Skip to content

Commit

Permalink
AIP-38 | List Import Errors (#44021)
Browse files Browse the repository at this point in the history
* create skeleton

* added modal

* add data in modal

* refactor

* time stamp

* handling reviews

* colour fix and search

* add skeleton and colour fix

* add error

* handle reviews
  • Loading branch information
shubhamraj-git authored Nov 18, 2024
1 parent 6c3caa6 commit 8027055
Show file tree
Hide file tree
Showing 10 changed files with 287 additions and 6 deletions.
6 changes: 3 additions & 3 deletions airflow/ui/src/pages/DagsList/DagCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ export const DagCard = ({ dag }: Props) => {
</Flex>
<SimpleGrid columns={4} gap={4} height={20} px={3} py={2}>
<VStack align="flex-start" gap={1}>
<Heading color="gray.500" fontSize="xs">
<Heading color="fg.muted" fontSize="xs">
Schedule
</Heading>
<Schedule dag={dag} />
</VStack>
<VStack align="flex-start" gap={1}>
<Heading color="gray.500" fontSize="xs">
<Heading color="fg.muted" fontSize="xs">
Latest Run
</Heading>
{latestRun ? (
Expand All @@ -99,7 +99,7 @@ export const DagCard = ({ dag }: Props) => {
) : undefined}
</VStack>
<VStack align="flex-start" gap={1}>
<Heading color="gray.500" fontSize="xs">
<Heading color="fg.muted" fontSize="xs">
Next Run
</Heading>
{Boolean(dag.next_dagrun) ? (
Expand Down
4 changes: 4 additions & 0 deletions airflow/ui/src/pages/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@ import { Box, Heading } from "@chakra-ui/react";

import { Health } from "./Health";
import { HistoricalMetrics } from "./HistoricalMetrics";
import { Stats } from "./Stats";

export const Dashboard = () => (
<Box>
<Heading mb={4}>Welcome</Heading>
<Box>
<Health />
</Box>
<Box mt={5}>
<Stats />
</Box>
<Box mt={5}>
<HistoricalMetrics />
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/
import { Box, Flex, Heading, HStack } from "@chakra-ui/react";
import { FiClipboard } from "react-icons/fi";
import { MdOutlineHealthAndSafety } from "react-icons/md";

import { useMonitorServiceGetHealth } from "openapi/queries";
import { ErrorAlert } from "src/components/ErrorAlert";
Expand All @@ -29,8 +29,8 @@ export const Health = () => {

return (
<Box>
<Flex color="gray.500" mb={2}>
<FiClipboard />
<Flex color="fg.muted" mb={2}>
<MdOutlineHealthAndSafety />
<Heading ml={1} size="xs">
Health
</Heading>
Expand Down
20 changes: 20 additions & 0 deletions airflow/ui/src/pages/Dashboard/Health/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*!
* 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.
*/

export { Health } from "./Health";
78 changes: 78 additions & 0 deletions airflow/ui/src/pages/Dashboard/Stats/DAGImportErrors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*!
* 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,
Badge,
Text,
Button,
useDisclosure,
Skeleton,
} from "@chakra-ui/react";
import { FiChevronRight } from "react-icons/fi";

import { useImportErrorServiceGetImportErrors } from "openapi/queries";
import { ErrorAlert } from "src/components/ErrorAlert";

import { DAGImportErrorsModal } from "./DAGImportErrorsModal";

export const DAGImportErrors = () => {
const { onClose, onOpen, open } = useDisclosure();

const { data, error, isLoading } = useImportErrorServiceGetImportErrors();
const importErrorsCount = data?.total_entries ?? 0;
const importErrors = data?.import_errors ?? [];

if (isLoading) {
return <Skeleton height="9" width="225px" />;
}

return (
<Box alignItems="center" display="flex" gap={2}>
<ErrorAlert error={error} />
{importErrorsCount > 0 && (
<Button
alignItems="center"
borderRadius="md"
display="flex"
gap={2}
onClick={onOpen}
variant="outline"
>
<Badge
background="red.solid"
borderRadius="full"
color="red.contrast"
px={2}
>
{importErrorsCount}
</Badge>
<Box alignItems="center" display="flex" gap={1}>
<Text fontWeight="bold">Dag Import Errors</Text>
<FiChevronRight />
</Box>
</Button>
)}
<DAGImportErrorsModal
importErrors={importErrors}
onClose={onClose}
open={open}
/>
</Box>
);
};
125 changes: 125 additions & 0 deletions airflow/ui/src/pages/Dashboard/Stats/DAGImportErrorsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*!
* 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 { Heading, Text, HStack, Input } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import { PiFilePy } from "react-icons/pi";

import type { ImportErrorResponse } from "openapi/requests/types.gen";
import Time from "src/components/Time";
import { Accordion, Dialog } from "src/components/ui";
import { Pagination } from "src/components/ui/Pagination";

type ImportDAGErrorModalProps = {
importErrors: Array<ImportErrorResponse>;
onClose: () => void;
open: boolean;
};

const PAGE_LIMIT = 15;

export const DAGImportErrorsModal: React.FC<ImportDAGErrorModalProps> = ({
importErrors,
onClose,
open,
}) => {
const [page, setPage] = useState(1);
const [searchQuery, setSearchQuery] = useState("");
const [filteredErrors, setFilteredErrors] = useState(importErrors);

const startRange = (page - 1) * PAGE_LIMIT;
const endRange = startRange + PAGE_LIMIT;
const visibleItems = filteredErrors.slice(startRange, endRange);

const onOpenChange = () => {
setSearchQuery("");
setPage(1);
onClose();
};

useEffect(() => {
const query = searchQuery.toLowerCase();
const filtered = importErrors.filter((error) =>
error.filename.toLowerCase().includes(query),
);

setFilteredErrors(filtered);
setPage(1);
}, [searchQuery, importErrors]);

return (
<Dialog.Root
onOpenChange={onOpenChange}
open={open}
scrollBehavior="inside"
size="xl"
>
<Dialog.Content backdrop>
<Dialog.Header>
<Heading size="xl">Dag Import Errors</Heading>
<Input
mt={4}
onChange={(event) => setSearchQuery(event.target.value)}
placeholder="Search by file"
value={searchQuery}
/>
</Dialog.Header>

<Dialog.CloseTrigger />

<Dialog.Body>
<Accordion.Root collapsible multiple size="md" variant="enclosed">
{visibleItems.map((importError) => (
<Accordion.Item
key={importError.import_error_id}
value={importError.filename}
>
<Accordion.ItemTrigger cursor="pointer">
<PiFilePy />
{importError.filename}
</Accordion.ItemTrigger>
<Accordion.ItemContent>
<Text color="fg.muted" fontSize="sm" mb={1}>
Timestamp: <Time datetime={importError.timestamp} />
</Text>
<Text color="fg.error" fontSize="sm" whiteSpace="pre-wrap">
<code>{importError.stack_trace}</code>
</Text>
</Accordion.ItemContent>
</Accordion.Item>
))}
</Accordion.Root>
</Dialog.Body>

<Pagination.Root
count={filteredErrors.length}
onPageChange={(event) => setPage(event.page)}
p={4}
page={page}
pageSize={PAGE_LIMIT}
>
<HStack>
<Pagination.PrevTrigger />
<Pagination.Items />
<Pagination.NextTrigger />
</HStack>
</Pagination.Root>
</Dialog.Content>
</Dialog.Root>
);
};
34 changes: 34 additions & 0 deletions airflow/ui/src/pages/Dashboard/Stats/Stats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*!
* 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, Flex, Heading } from "@chakra-ui/react";
import { FiClipboard } from "react-icons/fi";

import { DAGImportErrors } from "./DAGImportErrors";

export const Stats = () => (
<Box>
<Flex color="fg.muted" my={2}>
<FiClipboard />
<Heading ml={1} size="xs">
Stats
</Heading>
</Flex>
<DAGImportErrors />
</Box>
);
20 changes: 20 additions & 0 deletions airflow/ui/src/pages/Dashboard/Stats/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*!
* 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.
*/

export { Stats } from "./Stats";

0 comments on commit 8027055

Please sign in to comment.