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 cf02a4169552628c3829ca5bd089213098791f79 Author: Brent Bovenzi <[email protected]> AuthorDate: Fri Feb 25 11:58:23 2022 -0500 reformat grid background colors --- airflow/www/static/js/tree/InstanceTooltip.jsx | 16 ++--- airflow/www/static/js/tree/SidePanel.jsx | 45 +++++++++++--- airflow/www/static/js/tree/StatusBox.jsx | 19 +++--- airflow/www/static/js/tree/Tree.jsx | 28 +++++---- airflow/www/static/js/tree/dagRuns/Bar.jsx | 9 ++- airflow/www/static/js/tree/dagRuns/index.jsx | 3 +- airflow/www/static/js/tree/renderTaskRows.jsx | 86 +++++++++++++++----------- 7 files changed, 129 insertions(+), 77 deletions(-) diff --git a/airflow/www/static/js/tree/InstanceTooltip.jsx b/airflow/www/static/js/tree/InstanceTooltip.jsx index bc0d58c..b0d0584 100644 --- a/airflow/www/static/js/tree/InstanceTooltip.jsx +++ b/airflow/www/static/js/tree/InstanceTooltip.jsx @@ -125,29 +125,29 @@ const InstanceTooltip = ({ </> )} <br /> - <Text> + {/* <Text> {taskIdTitle} {taskId} - </Text> - <Text whiteSpace="nowrap"> + </Text> */} + {/* <Text whiteSpace="nowrap"> Run Id: {' '} {runId} - </Text> - {operator && ( + </Text> */} + {/* {operator && ( <Text> Operator: {' '} {operator} </Text> - )} + )} */} <Text> Duration: {' '} {formatDuration(duration || getDuration(startDate, endDate))} </Text> <br /> - <Text as="strong">UTC</Text> + {/* <Text as="strong">UTC</Text> <Text> Started: {' '} @@ -173,7 +173,7 @@ const InstanceTooltip = ({ Ended: {' '} {endDate && formatDateTime(endDate)} - </Text> + </Text> */} </Box> ); }; diff --git a/airflow/www/static/js/tree/SidePanel.jsx b/airflow/www/static/js/tree/SidePanel.jsx index 3515f1c..7a21eba 100644 --- a/airflow/www/static/js/tree/SidePanel.jsx +++ b/airflow/www/static/js/tree/SidePanel.jsx @@ -21,29 +21,60 @@ import React from 'react'; import { - Box, chakra, Flex, Text, + useDisclosure, + CloseButton, + Button, + IconButton, } from '@chakra-ui/react'; +import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from 'react-icons/md'; import { formatDateTime } from '../datetime_utils'; -const SidePanel = ({ instance: { runId, taskId, executionDate }, isOpen }) => ( - <Box bg="gray.200" maxWidth={isOpen ? 300 : 0} minWidth={isOpen ? 300 : 0} transition="all 0.5s" position="relative" overflow="hidden"> - <Flex right={isOpen ? 0 : -300} top={0} transition="right 0.5s, max-width 0.5s" width={300} flexDirection="column" m={2}> - <Text as="h4"> +const SidePanel = ({ instance: { runId, taskId, executionDate } }) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + if (!isOpen) { + return ( + <IconButton + ml={2} + icon={<MdKeyboardArrowLeft size={18} />} + aria-label="Open Details Panel" + onClick={onOpen} + /> + ); + } + const title = runId && taskId + ? ( + <> <chakra.span>Task Instance: </chakra.span> <chakra.b>{taskId}</chakra.b> <chakra.span> at </chakra.span> <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b> + </> + ) + : ( + <chakra.span>Dag Details: </chakra.span> + ); + + return ( + <Flex bg="gray.200" maxWidth={300} minWidth={300} flexDirection="column" p={3}> + <IconButton + ml={2} + icon={<MdKeyboardArrowRight size={18} />} + aria-label="Close Details Panel" + onClick={onClose} + /> + <Text as="h4"> + {title} </Text> <Text> {/* eslint-disable-next-line max-len */} Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Nunc vel risus commodo viverra maecenas accumsan. Ut porttitor leo a diam sollicitudin tempor id eu. Molestie at elementum eu facilisis sed odio morbi quis commodo. Facilisis leo vel fringilla est ullamcorper eget nulla facilisi etiam. Est sit amet facilisis magna etiam tempor orci eu. Id semper risus in hendrerit gravida rutrum. Ac odio tempor orci dapibus [...] </Text> </Flex> - </Box> -); + ); +}; export default SidePanel; diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx index dce0fda..b4abc93 100644 --- a/airflow/www/static/js/tree/StatusBox.jsx +++ b/airflow/www/static/js/tree/StatusBox.jsx @@ -24,9 +24,10 @@ import { Flex, Box, Tooltip, + useTheme, } from '@chakra-ui/react'; -import { callModal } from '../dag'; +// import { callModal } from '../dag'; import InstanceTooltip from './InstanceTooltip'; const StatusBox = ({ @@ -35,21 +36,19 @@ const StatusBox = ({ const { executionDate, taskId, tryNumber = 0, operator, runId, } = instance; + const { colors } = useTheme(); + const hoverBlue = `${colors.blue[100]}50`; - const onOpenModal = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId); - const onClick = () => { - if (group.isMapped) { - onSelectInstance(instance); - } else { - onSelectInstance({}); - onOpenModal(); - } + // const onOpenModal = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId); + const onClick = (e) => { + e.stopPropagation(); + onSelectInstance(instance); }; // Fetch the corresponding column element and set its background color when hovering const onMouseOver = () => { [...containerRef.current.getElementsByClassName(`js-${runId}`)] - .forEach((e) => { e.style.backgroundColor = 'rgba(113, 128, 150, 0.1)'; }); + .forEach((e) => { e.style.backgroundColor = hoverBlue; }); }; const onMouseLeave = () => { [...containerRef.current.getElementsByClassName(`js-${runId}`)] diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx index e88c676..154a5db 100644 --- a/airflow/www/static/js/tree/Tree.jsx +++ b/airflow/www/static/js/tree/Tree.jsx @@ -60,7 +60,7 @@ const Tree = () => { return ( <Box position="relative" ref={containerRef}> - <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%"> + <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%" mb={2}> {isRefreshOn && <Spinner color="blue.500" speed="1s" mr="4px" />} <FormLabel htmlFor="auto-refresh" mb={0} fontSize="12px" fontWeight="normal"> Auto-refresh @@ -69,19 +69,21 @@ const Tree = () => { </FormControl> <Text transform="rotate(-90deg)" position="absolute" left="-6px" top="130px">Runs</Text> <Text transform="rotate(-90deg)" position="absolute" left="-6px" top="190px">Tasks</Text> - <Box pl="24px"> + <Box pl="24px" height="100%" onClick={() => setSelectedInstance({})}> <Flex position="relative" flexDirection="row" justifyContent="space-between" overflow="hidden"> - <Table mr="24px" overflowX="auto" ref={scrollRef} height={0}> - <Thead> - <DagRuns containerRef={containerRef} /> - </Thead> - <Tbody> - {renderTaskRows({ - task: groups, containerRef, onSelectInstance, dagRunIds, - })} - </Tbody> - </Table> - <SidePanel isOpen={!!runId} instance={selectedInstance} /> + <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="60vw"> + <Table height={0}> + <Thead> + <DagRuns containerRef={containerRef} selectedInstance={selectedInstance} /> + </Thead> + <Tbody> + {renderTaskRows({ + task: groups, containerRef, onSelectInstance, selectedInstance, dagRunIds, + })} + </Tbody> + </Table> + </Box> + <SidePanel instance={selectedInstance} /> </Flex> </Box> </Box> diff --git a/airflow/www/static/js/tree/dagRuns/Bar.jsx b/airflow/www/static/js/tree/dagRuns/Bar.jsx index a0fa5b1..4dbe20d 100644 --- a/airflow/www/static/js/tree/dagRuns/Bar.jsx +++ b/airflow/www/static/js/tree/dagRuns/Bar.jsx @@ -26,6 +26,7 @@ import { Tooltip, Text, VStack, + useTheme, } from '@chakra-ui/react'; import { MdPlayArrow } from 'react-icons/md'; @@ -35,13 +36,16 @@ import { callModalDag } from '../../dag'; const BAR_HEIGHT = 100; const DagRunBar = ({ - run, max, index, totalRuns, containerRef, + run, max, index, totalRuns, containerRef, selectedInstance, }) => { + const { colors } = useTheme(); + const hoverBlue = `${colors.blue[100]}50`; let highlightHeight = '100%'; if (containerRef && containerRef.current) { const table = containerRef.current.getElementsByTagName('tbody')[0]; highlightHeight = table.offsetHeight + BAR_HEIGHT; } + const isSelected = run.runId === selectedInstance.runId; return ( <Box position="relative"> <Flex @@ -93,7 +97,8 @@ const DagRunBar = ({ top="1px" height={highlightHeight} className={`js-${run.runId}`} - _peerHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} + bg={isSelected ? 'blue.100' : undefined} + _peerHover={!isSelected && { backgroundColor: hoverBlue }} zIndex={0} transition="background-color 0.2s" /> diff --git a/airflow/www/static/js/tree/dagRuns/index.jsx b/airflow/www/static/js/tree/dagRuns/index.jsx index a0a4931..7de949f 100644 --- a/airflow/www/static/js/tree/dagRuns/index.jsx +++ b/airflow/www/static/js/tree/dagRuns/index.jsx @@ -36,7 +36,7 @@ const DurationTick = ({ children, ...rest }) => ( </Text> ); -const DagRuns = ({ containerRef }) => { +const DagRuns = ({ containerRef, selectedInstance }) => { const { data: { dagRuns = [] } } = useTreeData(); const durations = []; const runs = dagRuns.map((dagRun) => { @@ -97,6 +97,7 @@ const DagRuns = ({ containerRef }) => { index={i} totalRuns={runs.length} containerRef={containerRef} + selectedInstance={selectedInstance} /> ))} </Flex> diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx index a9ee197..1a9e1ba 100644 --- a/airflow/www/static/js/tree/renderTaskRows.jsx +++ b/airflow/www/static/js/tree/renderTaskRows.jsx @@ -28,6 +28,7 @@ import { Flex, useDisclosure, Collapse, + useTheme, } from '@chakra-ui/react'; import { FiChevronUp, FiChevronDown } from 'react-icons/fi'; @@ -39,7 +40,7 @@ import { getMetaValue } from '../utils'; const dagId = getMetaValue('dag_id'); const renderTaskRows = ({ - task, containerRef, level = 0, isParentOpen, dagRunIds, onSelectInstance, + task, containerRef, level = 0, isParentOpen, dagRunIds, onSelectInstance, selectedInstance, }) => task.children.map((t) => ( <Row key={t.id} @@ -50,40 +51,37 @@ const renderTaskRows = ({ isParentOpen={isParentOpen} dagRunIds={dagRunIds} onSelectInstance={onSelectInstance} + selectedInstance={selectedInstance} /> )); const TaskName = ({ isGroup = false, isMapped = false, onToggle, isOpen, level, taskName, }) => ( - <Box _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s"> - <Flex - as={isGroup ? 'button' : 'div'} - onClick={() => isGroup && onToggle()} - color={level > 4 && 'white'} - aria-label={taskName} - title={taskName} - mr={4} - width="100%" - backgroundColor={`rgba(203, 213, 224, ${0.25 * level})`} - alignItems="center" + <Flex + as={isGroup ? 'button' : 'div'} + onClick={() => isGroup && onToggle()} + aria-label={taskName} + title={taskName} + mr={4} + width="100%" + alignItems="center" + > + <Text + display="inline" + fontSize="12px" + ml={level * 4 + 4} + isTruncated > - <Text - display="inline" - fontSize="12px" - ml={level * 4 + 4} - isTruncated - > - {taskName} - {isMapped && ( - ' [ ]' - )} - </Text> - {isGroup && ( - isOpen ? <FiChevronDown data-testid="open-group" /> : <FiChevronUp data-testid="closed-group" /> + {taskName} + {isMapped && ( + ' [ ]' )} - </Flex> - </Box> + </Text> + {isGroup && ( + isOpen ? <FiChevronDown data-testid="open-group" /> : <FiChevronUp data-testid="closed-group" /> + )} + </Flex> ); const TaskInstances = ({ @@ -104,16 +102,26 @@ const TaskInstances = ({ onSelectInstance={onSelectInstance} /> ) - : <Box key={`${runId}-${task.id}`} width="18px" data-testid="blank-task" />; + : <Box key={`${runId}-${task.id}`} width="16px" data-testid="blank-task" />; })} </Flex> ); const Row = (props) => { const { - task, containerRef, level, prevTaskId, isParentOpen = true, dagRunIds, onSelectInstance, + task, + containerRef, + level, + prevTaskId, + isParentOpen = true, + dagRunIds, + onSelectInstance, + selectedInstance, } = props; + const { colors } = useTheme(); + const hoverBlue = `${colors.blue[100]}50`; const isGroup = !!task.children; + const isSelected = selectedInstance.taskId === task.id; const taskName = prevTaskId ? task.id.replace(`${prevTaskId}.`, '') : task.id; @@ -136,21 +144,23 @@ const Row = (props) => { return ( <> <Tr - backgroundColor={`rgba(203, 213, 224, ${0.25 * level})`} + bg={isSelected ? 'blue.100' : undefined} borderBottomWidth={isFullyOpen ? 1 : 0} - borderBottomColor={level > 1 ? 'white' : 'gray.200'} + borderBottomColor="gray.200" role="group" + _hover={!isSelected && { bg: hoverBlue }} + transition="background-color 0.2s" > <Td - _groupHover={level > 3 && { - color: 'white', - }} + bg={isSelected ? 'blue.100' : 'white'} + _groupHover={!isSelected && ({ bg: 'blue.50' })} p={0} + transition="background-color 0.2s" lineHeight="18px" position="sticky" left={0} - backgroundColor="white" borderBottom={0} + zIndex={2} > <Collapse in={isFullyOpen}> <TaskName @@ -164,7 +174,11 @@ const Row = (props) => { </Collapse> </Td> <Td width={0} p={0} borderBottom={0} /> - <Td p={0} align="right" _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s" borderBottom={0}> + <Td + p={0} + align="right" + borderBottom={0} + > <Collapse in={isFullyOpen}> <TaskInstances dagRunIds={dagRunIds}
