Skip to content

Commit

Permalink
Merge pull request #1514 from astronomer/task-instance-details
Browse files Browse the repository at this point in the history
Task instance details
  • Loading branch information
bbovenzi authored Dec 4, 2024
2 parents a0d2d9c + f350786 commit 47af037
Show file tree
Hide file tree
Showing 18 changed files with 517 additions and 343 deletions.
2 changes: 1 addition & 1 deletion airflow/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.3.1",
"react-hook-form": "^7.20.0",
"react-icons": "^5.3.0",
"react-icons": "^5.4.0",
"react-router-dom": "^6.26.2",
"react-syntax-highlighter": "^15.5.6",
"use-debounce": "^10.0.3",
Expand Down
10 changes: 5 additions & 5 deletions airflow/ui/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 0 additions & 52 deletions airflow/ui/src/components/DagVizModal.tsx

This file was deleted.

92 changes: 92 additions & 0 deletions airflow/ui/src/layouts/Details/DagVizModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*!
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Button, Heading, HStack } from "@chakra-ui/react";
import { FaChartGantt } from "react-icons/fa6";
import { FiGrid } from "react-icons/fi";
import { Link as RouterLink, useSearchParams } from "react-router-dom";

import type { DAGResponse } from "openapi/requests/types.gen";
import { DagIcon } from "src/assets/DagIcon";
import { Dialog } from "src/components/ui";
import { Graph } from "src/pages/DagsList/Dag/Graph";
import { Grid } from "src/pages/DagsList/Dag/Grid";
import { capitalize } from "src/utils";

type TriggerDAGModalProps = {
dagDisplayName?: DAGResponse["dag_display_name"];
dagId?: DAGResponse["dag_id"];
onClose: () => void;
open: boolean;
};

const visualizationOptions = [
{ icon: <FaChartGantt height={5} width={5} />, value: "gantt" },
{ icon: <DagIcon height={5} width={5} />, value: "graph" },
{ icon: <FiGrid height={5} width={5} />, value: "grid" },
];

export const DagVizModal: React.FC<TriggerDAGModalProps> = ({
dagDisplayName,
dagId,
onClose,
open,
}) => {
const [searchParams] = useSearchParams();

const activeViz = searchParams.get("modal") ?? "graph";

return (
<Dialog.Root onOpenChange={onClose} open={open} size="full">
<Dialog.Content backdrop>
<Dialog.Header bg="blue.muted">
<HStack>
<Heading mr={3} size="xl">
{Boolean(dagDisplayName) ? dagDisplayName : "Dag Undefined"}
</Heading>
{visualizationOptions.map(({ icon, value }) => (
<RouterLink
key={value}
to={{
search: `modal=${value}`,
}}
>
<Button
borderColor="colorPalette.fg"
borderRadius={20}
colorPalette="blue"
variant={activeViz === value ? "solid" : "outline"}
>
{icon}
{capitalize(value)}
</Button>
</RouterLink>
))}
</HStack>
<Dialog.CloseTrigger closeButtonProps={{ size: "xl" }} />
</Dialog.Header>
<Dialog.Body display="flex">
{activeViz === "graph" && dagId !== undefined ? (
<Graph dagId={dagId} />
) : undefined}
{activeViz === "grid" && dagId !== undefined ? <Grid /> : undefined}
</Dialog.Body>
</Dialog.Content>
</Dialog.Root>
);
};
87 changes: 87 additions & 0 deletions airflow/ui/src/layouts/Details/DetailsLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*!
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Box, Button } from "@chakra-ui/react";
import type { PropsWithChildren } from "react";
import { FiChevronsLeft } from "react-icons/fi";
import {
Outlet,
Link as RouterLink,
useParams,
useSearchParams,
} from "react-router-dom";

import type { DAGResponse } from "openapi/requests/types.gen";
import { ErrorAlert } from "src/components/ErrorAlert";
import { ProgressBar } from "src/components/ui";
import { OpenGroupsProvider } from "src/context/openGroups";
import { DagVizModal } from "src/layouts/Details/DagVizModal";
import { NavTabs } from "src/layouts/Details/NavTabs";

type Props = {
readonly dag?: DAGResponse;
readonly error?: unknown;
readonly isLoading?: boolean;
readonly tabs: Array<{ label: string; value: string }>;
} & PropsWithChildren;

export const DetailsLayout = ({
children,
dag,
error,
isLoading,
tabs,
}: Props) => {
const { dagId = "" } = useParams();

const [searchParams, setSearchParams] = useSearchParams();

const modal = searchParams.get("modal");

const isModalOpen = modal !== null;
const onClose = () => {
searchParams.delete("modal");
setSearchParams(searchParams);
};

return (
<OpenGroupsProvider dagId={dagId}>
<Box>
<Button asChild colorPalette="blue" variant="ghost">
<RouterLink to="/dags">
<FiChevronsLeft />
Back to all dags
</RouterLink>
</Button>
{children}
<ErrorAlert error={error} />
<ProgressBar size="xs" visibility={isLoading ? "visible" : "hidden"} />
<NavTabs tabs={tabs} />
<DagVizModal
dagDisplayName={dag?.dag_display_name}
dagId={dag?.dag_id}
onClose={onClose}
open={isModalOpen}
/>
</Box>
<Box overflow="auto">
<Outlet />
</Box>
</OpenGroupsProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Center, Flex } from "@chakra-ui/react";
import type { ReactNode } from "react";
import { NavLink } from "react-router-dom";
import { Button, Center, Flex } from "@chakra-ui/react";
import { FaChartGantt } from "react-icons/fa6";
import { FiGrid } from "react-icons/fi";
import { NavLink, Link as RouterLink } from "react-router-dom";

import { DagIcon } from "src/assets/DagIcon";

type Props = {
readonly rightButtons?: ReactNode;
readonly tabs: Array<{ label: string; value: string }>;
};

export const NavTabs = ({ rightButtons, tabs }: Props) => (
export const NavTabs = ({ tabs }: Props) => (
<Flex
alignItems="center"
borderBottomWidth={1}
Expand All @@ -52,6 +54,25 @@ export const NavTabs = ({ rightButtons, tabs }: Props) => (
</NavLink>
))}
</Flex>
<Flex alignSelf="flex-end">{rightButtons}</Flex>
<Flex alignSelf="flex-end">
<Button asChild colorPalette="blue" variant="ghost">
<RouterLink to={{ search: "modal=gantt" }}>
<FaChartGantt height={5} width={5} />
Gantt
</RouterLink>
</Button>
<Button asChild colorPalette="blue" variant="ghost">
<RouterLink to={{ search: "modal=grid" }}>
<FiGrid height={5} width={5} />
Grid
</RouterLink>
</Button>
<Button asChild colorPalette="blue" variant="ghost">
<RouterLink to={{ search: "modal=graph" }}>
<DagIcon height={5} width={5} />
Graph
</RouterLink>
</Button>
</Flex>
</Flex>
);
Loading

0 comments on commit 47af037

Please sign in to comment.