This is an automated email from the ASF dual-hosted git repository. bbovenzi pushed a commit to branch mapped-task-drawer in repository https://gitbox.apache.org/repos/asf/airflow.git
commit e251bb5b4e31b2045ad4210a39457d9cb26e26c9 Author: Brent Bovenzi <[email protected]> AuthorDate: Tue Mar 1 18:19:27 2022 -0500 add tooltip info to details --- .../www/static/js/tree/details/content/DagRun.jsx | 79 ++++++++++- .../js/tree/details/content/TaskInstance.jsx | 146 ++++++++++++++++++++- airflow/www/static/js/tree/details/index.jsx | 2 +- 3 files changed, 217 insertions(+), 10 deletions(-) diff --git a/airflow/www/static/js/tree/details/content/DagRun.jsx b/airflow/www/static/js/tree/details/content/DagRun.jsx index 58e4b92..abcf908 100644 --- a/airflow/www/static/js/tree/details/content/DagRun.jsx +++ b/airflow/www/static/js/tree/details/content/DagRun.jsx @@ -17,15 +17,86 @@ * under the License. */ +/* global moment */ + import React from 'react'; import { Text, + Box, } from '@chakra-ui/react'; +import { MdPlayArrow } from 'react-icons/md'; + +import { formatDateTime, formatDuration } from '../../../datetime_utils'; -const DagRun = () => ( - <> - <Text>dag run details</Text> - </> +const DagRun = ({ + dagRun: { + state, runId, duration, dataIntervalStart, dataIntervalEnd, startDate, endDate, runType, + }, +}) => ( + <Box fontSize="12px" py="4px"> + <Text> + <Text as="strong">Status:</Text> + {' '} + {state || 'no status'} + </Text> + <br /> + <Text whiteSpace="nowrap"> + Run Id: + {' '} + {runId} + </Text> + <Text> + Run Type: + {' '} + {runType === 'manual' && <MdPlayArrow style={{ display: 'inline' }} />} + {runType} + </Text> + <Text> + Duration: + {' '} + {formatDuration(duration)} + </Text> + <br /> + <Text as="strong">Data Interval:</Text> + <Text> + Start: + {' '} + {formatDateTime(dataIntervalStart)} + </Text> + <Text> + End: + {' '} + {formatDateTime(dataIntervalEnd)} + </Text> + <br /> + <Text as="strong">UTC</Text> + <Text> + Started: + {' '} + {formatDateTime(moment.utc(startDate))} + </Text> + <Text> + Ended: + {' '} + {endDate && formatDateTime(moment.utc(endDate))} + </Text> + <br /> + <Text as="strong"> + Local: + {' '} + {moment().format('Z')} + </Text> + <Text> + Started: + {' '} + {formatDateTime(startDate)} + </Text> + <Text> + Ended: + {' '} + {endDate && formatDateTime(endDate)} + </Text> + </Box> ); export default DagRun; diff --git a/airflow/www/static/js/tree/details/content/TaskInstance.jsx b/airflow/www/static/js/tree/details/content/TaskInstance.jsx index 4ab46e5..bc60737 100644 --- a/airflow/www/static/js/tree/details/content/TaskInstance.jsx +++ b/airflow/www/static/js/tree/details/content/TaskInstance.jsx @@ -17,15 +17,151 @@ * under the License. */ +/* global moment */ + import React from 'react'; import { Text, + Box, } from '@chakra-ui/react'; -const TaskInstance = () => ( - <> - <Text>task instance details</Text> - </> -); +import { formatDateTime, getDuration, formatDuration } from '../../../datetime_utils'; + +const TaskInstance = ({ + instance: { + duration, operator, startDate, endDate, state, taskId, runId, // mappedStates, + }, +}) => { + const isGroup = false; // !!group.children; + const groupSummary = []; + // const mapSummary = []; + + // if (isGroup) { + // const numMap = finalStatesMap(); + // group.children.forEach((child) => { + // const taskInstance = child.instances.find((ti) => ti.runId === runId); + // if (taskInstance) { + // const stateKey = taskInstance.state == null ? 'no_status' : taskInstance.state; + // if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1); + // } + // }); + // numMap.forEach((key, val) => { + // if (key > 0) { + // groupSummary.push( + // // eslint-disable-next-line react/no-array-index-key + // <Text key={val} ml="10px"> + // {val} + // {': '} + // {key} + // </Text>, + // ); + // } + // }); + // } + + // if (group.isMapped && mappedStates) { + // const numMap = finalStatesMap(); + // mappedStates.forEach((s) => { + // const stateKey = s || 'no_status'; + // if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1); + // }); + // numMap.forEach((key, val) => { + // if (key > 0) { + // mapSummary.push( + // // eslint-disable-next-line react/no-array-index-key + // <Text key={val} ml="10px"> + // {val} + // {': '} + // {key} + // </Text>, + // ); + // } + // }); + // } + + const taskIdTitle = isGroup ? 'Task Group Id: ' : 'Task Id: '; + + return ( + <Box fontSize="12px" py="4px"> + {/* {group.tooltip && ( + <Text>{group.tooltip}</Text> + )} */} + <Text> + <Text as="strong">Status:</Text> + {' '} + {state || 'no status'} + </Text> + {isGroup && ( + <> + <br /> + <Text as="strong">Group Summary</Text> + {groupSummary} + </> + )} + {/* {group.isMapped && ( + <> + <br /> + <Text as="strong"> + {mappedStates.length} + {' '} + {mappedStates.length === 1 ? 'Task ' : 'Tasks '} + Mapped + </Text> + {mapSummary} + </> + )} */} + <br /> + <Text> + {taskIdTitle} + {taskId} + </Text> + <Text whiteSpace="nowrap"> + Run Id: + {' '} + {runId} + </Text> + {operator && ( + <Text> + Operator: + {' '} + {operator} + </Text> + )} + <Text> + Duration: + {' '} + {formatDuration(duration || getDuration(startDate, endDate))} + </Text> + <br /> + <Text as="strong">UTC</Text> + <Text> + Started: + {' '} + {startDate && formatDateTime(moment.utc(startDate))} + </Text> + <Text> + Ended: + {' '} + {endDate && formatDateTime(moment.utc(endDate))} + </Text> + <br /> + <Text as="strong"> + Local: + {' '} + {moment().format('Z')} + </Text> + <Text> + Started: + {' '} + {startDate && formatDateTime(startDate)} + </Text> + <Text> + Ended: + {' '} + {endDate && formatDateTime(endDate)} + </Text> + </Box> + ); +}; export default TaskInstance; diff --git a/airflow/www/static/js/tree/details/index.jsx b/airflow/www/static/js/tree/details/index.jsx index b8f960e..31610a7 100644 --- a/airflow/www/static/js/tree/details/index.jsx +++ b/airflow/www/static/js/tree/details/index.jsx @@ -39,7 +39,7 @@ const Details = ({ <Box> {/* TODO: get full instance data from the API */} {!selected.runId && !selected.taskId && <DagContent />} - {selected.runId && !selected.taskId && <DagRunContent />} + {selected.runId && !selected.taskId && <DagRunContent dagRun={selected} />} {selected.taskId && <TaskInstanceContent instance={selected} />} </Box> </Flex>
