You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by bb...@apache.org on 2022/03/02 00:47:05 UTC

[airflow] 04/08: improve rendering and add selected dag run

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 eb961505bac36095c84bd6c2b99e9ce49e6f37bc
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Mon Feb 28 12:24:27 2022 -0500

    improve rendering and add selected dag run
---
 airflow/www/static/js/tree/SidePanel.jsx      | 28 +++++++++++++++++--------
 airflow/www/static/js/tree/StatusBox.jsx      | 24 ++++++++++-----------
 airflow/www/static/js/tree/Tree.jsx           | 12 ++++++++---
 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 | 30 ++++++++++++++++++---------
 6 files changed, 65 insertions(+), 41 deletions(-)

diff --git a/airflow/www/static/js/tree/SidePanel.jsx b/airflow/www/static/js/tree/SidePanel.jsx
index 7a21eba..88439a0 100644
--- a/airflow/www/static/js/tree/SidePanel.jsx
+++ b/airflow/www/static/js/tree/SidePanel.jsx
@@ -25,8 +25,6 @@ import {
   Flex,
   Text,
   useDisclosure,
-  CloseButton,
-  Button,
   IconButton,
 } from '@chakra-ui/react';
 import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from 'react-icons/md';
@@ -38,30 +36,42 @@ const SidePanel = ({ instance: { runId, taskId, executionDate } }) => {
   if (!isOpen) {
     return (
       <IconButton
-        ml={2}
+        m={2}
         icon={<MdKeyboardArrowLeft size={18} />}
         aria-label="Open Details Panel"
         onClick={onOpen}
       />
     );
   }
-  const title = runId && taskId
-    ? (
+  let title = '';
+  if (runId && taskId) {
+    title = (
       <>
         <chakra.span>Task Instance: </chakra.span>
         <chakra.b>{taskId}</chakra.b>
         <chakra.span> at </chakra.span>
         <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
       </>
-    )
-    : (
+    );
+  } else if (runId) {
+    title = (
+      <>
+        <chakra.span>Dag Run: </chakra.span>
+        <chakra.b>{runId}</chakra.b>
+        <chakra.span> at </chakra.span>
+        <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
+      </>
+    );
+  } else {
+    title = (
       <chakra.span>Dag Details: </chakra.span>
     );
+  }
 
   return (
-    <Flex bg="gray.200" maxWidth={300} minWidth={300} flexDirection="column" p={3}>
+    <Flex bg="gray.200" maxWidth={isOpen ? '50%' : 0} minWidth={isOpen ? 300 : 0} flexDirection="column" p={3}>
       <IconButton
-        ml={2}
+        m={2}
         icon={<MdKeyboardArrowRight size={18} />}
         aria-label="Close Details Panel"
         onClick={onClose}
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index b4abc93..815e6a1 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -27,34 +27,32 @@ import {
   useTheme,
 } from '@chakra-ui/react';
 
-// import { callModal } from '../dag';
 import InstanceTooltip from './InstanceTooltip';
 
 const StatusBox = ({
-  group, instance, containerRef, extraLinks = [], onSelectInstance, ...rest
+  group, instance, containerRef, onSelectInstance, selectedInstance, ...rest
 }) => {
-  const {
-    executionDate, taskId, tryNumber = 0, operator, runId,
-  } = instance;
+  const { 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 = (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 = hoverBlue; });
+    if (selectedInstance.runId !== runId) {
+      [...containerRef.current.getElementsByClassName(`js-${runId}`)]
+        .forEach((e) => { e.style.backgroundColor = hoverBlue; });
+    }
   };
   const onMouseLeave = () => {
     [...containerRef.current.getElementsByClassName(`js-${runId}`)]
       .forEach((e) => { e.style.backgroundColor = null; });
   };
 
+  const onClick = (e) => {
+    e.stopPropagation();
+    onSelectInstance(instance);
+  };
+
   return (
     <>
       <Tooltip
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index ff1402f..199e373 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -39,9 +39,11 @@ import SidePanel from './SidePanel';
 const Tree = () => {
   const containerRef = useRef();
   const scrollRef = useRef();
-  const { data: { groups = {} }, isRefreshOn, onToggleRefresh } = useTreeData();
+  const { data: { groups = {}, dagRuns = [] }, isRefreshOn, onToggleRefresh } = useTreeData();
   const [selectedInstance, setSelectedInstance] = useState({});
 
+  const dagRunIds = dagRuns.map((dr) => dr.runId);
+
   useEffect(() => {
     // Set initial scroll to far right if it is scrollable
     const runsContainer = scrollRef.current;
@@ -73,11 +75,15 @@ const Tree = () => {
           <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="60vw">
             <Table height={0}>
               <Thead>
-                <DagRuns containerRef={containerRef} selectedInstance={selectedInstance} />
+                <DagRuns
+                  containerRef={containerRef}
+                  selectedInstance={selectedInstance}
+                  onSelectInstance={onSelectInstance}
+                />
               </Thead>
               <Tbody>
                 {renderTaskRows({
-                  task: groups, containerRef, onSelectInstance, selectedInstance,
+                  task: groups, containerRef, onSelectInstance, selectedInstance, dagRunIds,
                 })}
               </Tbody>
             </Table>
diff --git a/airflow/www/static/js/tree/dagRuns/Bar.jsx b/airflow/www/static/js/tree/dagRuns/Bar.jsx
index 4dbe20d..c64abdd 100644
--- a/airflow/www/static/js/tree/dagRuns/Bar.jsx
+++ b/airflow/www/static/js/tree/dagRuns/Bar.jsx
@@ -31,12 +31,11 @@ import {
 import { MdPlayArrow } from 'react-icons/md';
 
 import DagRunTooltip from './Tooltip';
-import { callModalDag } from '../../dag';
 
 const BAR_HEIGHT = 100;
 
 const DagRunBar = ({
-  run, max, index, totalRuns, containerRef, selectedInstance,
+  run, max, index, totalRuns, containerRef, selectedInstance, onSelectInstance,
 }) => {
   const { colors } = useTheme();
   const hoverBlue = `${colors.blue[100]}50`;
@@ -53,14 +52,14 @@ const DagRunBar = ({
         alignItems="flex-end"
         justifyContent="center"
         mb="2px"
-        // py="2px"
         px="2px"
         mx="1px"
         cursor="pointer"
         width="14px"
         zIndex={1}
-        onClick={() => {
-          callModalDag({ execution_date: run.executionDate, dag_id: run.dagId, run_id: run.runId });
+        onClick={(e) => {
+          e.stopPropagation();
+          onSelectInstance(run);
         }}
         position="relative"
         data-peer
diff --git a/airflow/www/static/js/tree/dagRuns/index.jsx b/airflow/www/static/js/tree/dagRuns/index.jsx
index 7de949f..7459634 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, selectedInstance }) => {
+const DagRuns = ({ containerRef, selectedInstance, onSelectInstance }) => {
   const { data: { dagRuns = [] } } = useTreeData();
   const durations = [];
   const runs = dagRuns.map((dagRun) => {
@@ -98,6 +98,7 @@ const DagRuns = ({ containerRef, selectedInstance }) => {
               totalRuns={runs.length}
               containerRef={containerRef}
               selectedInstance={selectedInstance}
+              onSelectInstance={onSelectInstance}
             />
           ))}
         </Flex>
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index 7eff252..9b454f0 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -32,7 +32,6 @@ import {
 } from '@chakra-ui/react';
 import { FiChevronUp, FiChevronDown } from 'react-icons/fi';
 
-import useTreeData from './useTreeData';
 import StatusBox from './StatusBox';
 
 import { getMetaValue } from '../utils';
@@ -41,7 +40,7 @@ import { getMetaValue } from '../utils';
 const dagId = getMetaValue('dag_id');
 
 const renderTaskRows = ({
-  task, containerRef, level = 0, isParentOpen, onSelectInstance, selectedInstance,
+  task, containerRef, level = 0, isParentOpen, onSelectInstance, selectedInstance, dagRunIds
 }) => task.children.map((t) => (
   <Row
     key={t.id}
@@ -52,6 +51,7 @@ const renderTaskRows = ({
     isParentOpen={isParentOpen}
     onSelectInstance={onSelectInstance}
     selectedInstance={selectedInstance}
+    dagRunIds={dagRunIds}
   />
 ));
 
@@ -85,33 +85,42 @@ const TaskName = ({
 );
 
 const TaskInstances = ({
-  task, containerRef, dagRuns, onSelectInstance,
+  task, containerRef, dagRunIds, onSelectInstance, selectedInstance,
 }) => (
   <Flex justifyContent="flex-end">
-    {dagRuns.map((run) => {
+    {dagRunIds.map((runId) => {
       // Check if an instance exists for the run, or return an empty box
-      const instance = task.instances.find((gi) => gi.runId === run.runId);
+      const instance = task.instances.find((gi) => gi.runId === runId);
+      const key = `${runId}-${task.id}`;
       return instance
         ? (
           <StatusBox
-            key={`${run.runId}-${task.id}`}
+            key={key}
             instance={instance}
             containerRef={containerRef}
             extraLinks={task.extraLinks}
             group={task}
             onSelectInstance={onSelectInstance}
+            selectedInstance={selectedInstance}
           />
         )
-        : <Box key={`${run.runId}-${task.id}`} width="16px" data-testid="blank-task" />;
+        : <Box key={key} width="16px" data-testid="blank-task" />;
     })}
   </Flex>
 );
 
 const Row = (props) => {
   const {
-    task, containerRef, level, prevTaskId, isParentOpen = true, onSelectInstance, selectedInstance,
+    task,
+    containerRef,
+    level,
+    prevTaskId,
+    isParentOpen = true,
+    onSelectInstance,
+    selectedInstance,
+    dagRunIds,
   } = props;
-  const { data: { dagRuns = [] } } = useTreeData();
+  // const { data: { dagRuns = [] } } = useTreeData();
   const { colors } = useTheme();
   const hoverBlue = `${colors.blue[100]}50`;
   const isGroup = !!task.children;
@@ -175,10 +184,11 @@ const Row = (props) => {
         >
           <Collapse in={isFullyOpen}>
             <TaskInstances
-              dagRuns={dagRuns}
+              dagRunIds={dagRunIds}
               task={task}
               containerRef={containerRef}
               onSelectInstance={onSelectInstance}
+              selectedInstance={selectedInstance}
             />
           </Collapse>
         </Td>