bbovenzi commented on code in PR #62195: URL: https://github.com/apache/airflow/pull/62195#discussion_r3053439039
########## airflow-core/src/airflow/ui/src/pages/Dag/Overview/DagDeadlines.tsx: ########## @@ -0,0 +1,200 @@ +/*! + * 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 { Badge, Box, Button, Flex, Heading, HStack, Separator, Skeleton, VStack } from "@chakra-ui/react"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { FiAlertTriangle, FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDeadlines } from "openapi/queries"; +import { ErrorAlert } from "src/components/ErrorAlert"; +import { useAutoRefresh } from "src/utils"; + +import { AllDeadlinesModal } from "./AllDeadlinesModal"; +import { DeadlineRow } from "./DeadlineRow"; + +const LIMIT = 5; + +type DagDeadlinesProps = { + readonly dagId: string; + readonly endDate: string; + readonly startDate: string; +}; + +export const DagDeadlines = ({ dagId, endDate, startDate }: DagDeadlinesProps) => { + const { t: translate } = useTranslation("dag"); + const refetchInterval = useAutoRefresh({ dagId }); + const [modalOpen, setModalOpen] = useState<"missed" | "pending" | null>(null); + + const { + data: pendingData, + error: pendingError, + isLoading: isPendingLoading, + } = useDeadlinesServiceGetDeadlines( + { + dagId, + dagRunId: "~", + deadlineTimeGte: endDate, + limit: LIMIT, + missed: false, + orderBy: ["deadline_time"], + }, + undefined, + { refetchInterval }, + ); + + const { + data: missedData, + error: missedError, + isLoading: isMissedLoading, + } = useDeadlinesServiceGetDeadlines( + { + dagId, + dagRunId: "~", + lastUpdatedAtGte: startDate, + lastUpdatedAtLte: endDate, + limit: LIMIT, + missed: true, + orderBy: ["-last_updated_at"], + }, + undefined, + { refetchInterval }, + ); + + const pendingDeadlines = pendingData?.deadlines ?? []; + const missedDeadlines = missedData?.deadlines ?? []; + + if ( + !isPendingLoading && + !isMissedLoading && + pendingDeadlines.length === 0 && + missedDeadlines.length === 0 + ) { + return undefined; + } + + return ( + <Box> + <Flex color="fg.muted" mb={2}> + <FiClock /> + <Heading ml={1} size="xs"> + {translate("overview.deadlines.title")} + </Heading> + </Flex> + <ErrorAlert error={pendingError ?? missedError} /> + <Flex flexDirection={{ base: "column", md: "row" }} gap={{ base: 4, md: 8 }}> + {isPendingLoading || pendingDeadlines.length > 0 ? ( + <Box borderRadius="lg" borderWidth={1} flex={1} overflow="hidden" p={3}> + <HStack mb={2}> + <FiClock /> + <Heading size="xs">{translate("overview.deadlines.pending")}</Heading> + {pendingData ? ( + <Badge colorPalette="blue" size="sm" variant="solid"> + {pendingData.total_entries} + </Badge> + ) : undefined} + </HStack> + {isPendingLoading ? ( + <VStack> + {Array.from({ length: 3 }).map((_, idx) => ( + // eslint-disable-next-line react/no-array-index-key + <Skeleton height="36px" key={idx} width="100%" /> + ))} + </VStack> + ) : ( + <VStack gap={0} separator={<Separator />}> + {pendingDeadlines.map((dl) => ( + <DeadlineRow deadline={dl} key={dl.id} /> + ))} + {(pendingData?.total_entries ?? 0) > LIMIT ? ( + <Button + mt={2} + onClick={() => setModalOpen("pending")} + size="xs" + variant="ghost" + width="100%" + > + {translate("overview.deadlines.viewAll", { + count: pendingData?.total_entries, + })} + </Button> + ) : undefined} + </VStack> + )} + </Box> + ) : undefined} + + {isMissedLoading || missedDeadlines.length > 0 ? ( + <Box borderRadius="lg" borderWidth={1} flex={1} overflow="hidden" p={3}> + <HStack color="fg.error" mb={2}> + <FiAlertTriangle /> + <Heading size="xs">{translate("overview.deadlines.recentlyMissed")}</Heading> + {missedData ? ( + <Badge colorPalette="failed" size="sm" variant="solid"> Review Comment: We used red elsewhere. Let's make sure we're consistent ########## airflow-core/src/airflow/ui/src/pages/Dag/DeadlineAlertsBadge.tsx: ########## @@ -0,0 +1,110 @@ +/*! + * 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, HStack, Separator, Text, VStack } from "@chakra-ui/react"; +import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; +import { FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDeadlines, useDeadlinesServiceGetDagDeadlineAlerts } from "openapi/queries"; +import type { DeadlineAlertResponse } from "openapi/requests/types.gen"; +import { Popover } from "src/components/ui"; +import { renderDuration } from "src/utils"; + +const referenceTypeLabels: Record<string, string> = { + AverageRuntimeDeadline: "Average Runtime", + DagRunLogicalDateDeadline: "Logical Date", + DagRunQueuedAtDeadline: "Queued At", + FixedDatetimeDeadline: "Fixed Datetime", +}; + +const formatReferenceType = (referenceType: string): string => + referenceTypeLabels[referenceType] ?? referenceType; + +const AlertRow = ({ alert }: { readonly alert: DeadlineAlertResponse }) => { + const { t: translate } = useTranslation("dag"); + + return ( + <Box py={2} width="100%"> + <Text fontWeight="bold"> + {alert.name !== undefined && alert.name !== null && alert.name !== "" + ? alert.name + : translate("deadlineAlerts.unnamed")} Review Comment: Better to not show a name instead of saying unnamed. ########## airflow-core/src/airflow/ui/src/pages/Dag/DeadlineAlertsBadge.tsx: ########## @@ -0,0 +1,110 @@ +/*! + * 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, HStack, Separator, Text, VStack } from "@chakra-ui/react"; +import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; +import { FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDeadlines, useDeadlinesServiceGetDagDeadlineAlerts } from "openapi/queries"; +import type { DeadlineAlertResponse } from "openapi/requests/types.gen"; +import { Popover } from "src/components/ui"; +import { renderDuration } from "src/utils"; + +const referenceTypeLabels: Record<string, string> = { + AverageRuntimeDeadline: "Average Runtime", + DagRunLogicalDateDeadline: "Logical Date", + DagRunQueuedAtDeadline: "Queued At", + FixedDatetimeDeadline: "Fixed Datetime", Review Comment: These need to be in the i18n files ########## airflow-core/src/airflow/ui/src/pages/Run/DeadlineStatus.tsx: ########## @@ -0,0 +1,109 @@ +/*! + * 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 { Badge, HStack, Text, VStack } from "@chakra-ui/react"; +import { useTranslation } from "react-i18next"; +import { FiAlertTriangle, FiCheck, FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDagDeadlineAlerts, useDeadlinesServiceGetDeadlines } from "openapi/queries"; +import Time from "src/components/Time"; + +type DeadlineStatusProps = { + readonly dagId: string; + readonly dagRunId: string; +}; + +export const DeadlineStatus = ({ dagId, dagRunId }: DeadlineStatusProps) => { + const { t: translate } = useTranslation("dag"); + + const { data: deadlineData, isLoading: isLoadingDeadlines } = useDeadlinesServiceGetDeadlines({ + dagId, + dagRunId, + limit: 10, + orderBy: ["deadline_time"], + }); + + const { data: alertData, isLoading: isLoadingAlerts } = useDeadlinesServiceGetDagDeadlineAlerts({ + dagId, + }); + + if (isLoadingDeadlines || isLoadingAlerts) { + return undefined; + } + + const deadlines = deadlineData?.deadlines ?? []; + const hasAlerts = (alertData?.total_entries ?? 0) > 0; + + if (deadlines.length === 0 && !hasAlerts) { + return undefined; + } + + if (deadlines.length === 0 && hasAlerts) { + return ( + <HStack gap={1}> + <Badge colorPalette="green" size="sm" variant="solid"> + <FiCheck color="var(--chakra-colors-fg-white)" /> + {translate("deadlineStatus.met")} + </Badge> + </HStack> + ); + } + + const missedDeadlines = deadlines.filter((dl) => dl.missed); + const upcomingDeadlines = deadlines.filter((dl) => !dl.missed); + + if (missedDeadlines.length > 0) { + return ( Review Comment: Do we want to return? What if there are a mix of missed and upcoming deadlines? I feel like that is useful info ########## airflow-core/src/airflow/ui/src/pages/Run/DeadlineStatus.tsx: ########## @@ -0,0 +1,109 @@ +/*! + * 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 { Badge, HStack, Text, VStack } from "@chakra-ui/react"; +import { useTranslation } from "react-i18next"; +import { FiAlertTriangle, FiCheck, FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDagDeadlineAlerts, useDeadlinesServiceGetDeadlines } from "openapi/queries"; +import Time from "src/components/Time"; + +type DeadlineStatusProps = { + readonly dagId: string; + readonly dagRunId: string; +}; + +export const DeadlineStatus = ({ dagId, dagRunId }: DeadlineStatusProps) => { + const { t: translate } = useTranslation("dag"); + + const { data: deadlineData, isLoading: isLoadingDeadlines } = useDeadlinesServiceGetDeadlines({ + dagId, + dagRunId, + limit: 10, + orderBy: ["deadline_time"], + }); + + const { data: alertData, isLoading: isLoadingAlerts } = useDeadlinesServiceGetDagDeadlineAlerts({ + dagId, + }); + + if (isLoadingDeadlines || isLoadingAlerts) { + return undefined; + } + + const deadlines = deadlineData?.deadlines ?? []; + const hasAlerts = (alertData?.total_entries ?? 0) > 0; + + if (deadlines.length === 0 && !hasAlerts) { Review Comment: Let's add comments to help understand each of these conditions. I keep confusing deadlines with deadlineAlerts ########## airflow-core/src/airflow/ui/src/pages/Run/DeadlineStatus.tsx: ########## @@ -0,0 +1,109 @@ +/*! + * 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 { Badge, HStack, Text, VStack } from "@chakra-ui/react"; +import { useTranslation } from "react-i18next"; +import { FiAlertTriangle, FiCheck, FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDagDeadlineAlerts, useDeadlinesServiceGetDeadlines } from "openapi/queries"; +import Time from "src/components/Time"; + +type DeadlineStatusProps = { + readonly dagId: string; + readonly dagRunId: string; +}; + +export const DeadlineStatus = ({ dagId, dagRunId }: DeadlineStatusProps) => { + const { t: translate } = useTranslation("dag"); + + const { data: deadlineData, isLoading: isLoadingDeadlines } = useDeadlinesServiceGetDeadlines({ + dagId, + dagRunId, + limit: 10, Review Comment: Without pagination we risk not showing deadlines. ########## airflow-core/src/airflow/ui/src/pages/Dag/DeadlineAlertsBadge.tsx: ########## @@ -0,0 +1,110 @@ +/*! + * 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, HStack, Separator, Text, VStack } from "@chakra-ui/react"; +import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; +import { FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDeadlines, useDeadlinesServiceGetDagDeadlineAlerts } from "openapi/queries"; +import type { DeadlineAlertResponse } from "openapi/requests/types.gen"; +import { Popover } from "src/components/ui"; +import { renderDuration } from "src/utils"; + +const referenceTypeLabels: Record<string, string> = { + AverageRuntimeDeadline: "Average Runtime", + DagRunLogicalDateDeadline: "Logical Date", + DagRunQueuedAtDeadline: "Queued At", + FixedDatetimeDeadline: "Fixed Datetime", +}; + +const formatReferenceType = (referenceType: string): string => + referenceTypeLabels[referenceType] ?? referenceType; + +const AlertRow = ({ alert }: { readonly alert: DeadlineAlertResponse }) => { + const { t: translate } = useTranslation("dag"); + + return ( + <Box py={2} width="100%"> + <Text fontWeight="bold"> + {alert.name !== undefined && alert.name !== null && alert.name !== "" + ? alert.name + : translate("deadlineAlerts.unnamed")} + </Text> + {alert.description !== undefined && alert.description !== null && alert.description !== "" ? ( + <Text color="fg.muted" fontSize="xs"> + {alert.description} + </Text> + ) : undefined} + <HStack fontSize="xs" gap={3} mt={1}> + <Text color="fg.muted"> + {translate("deadlineAlerts.referenceType")}: {formatReferenceType(alert.reference_type)} + </Text> + <Text color="fg.muted"> + {translate("deadlineAlerts.interval")}:{" "} + {renderDuration(alert.interval, false) ?? `${alert.interval}s`} + </Text> + </HStack> + </Box> + ); +}; + +export const DeadlineAlertsBadge = ({ dagId }: { readonly dagId: string }) => { + const { t: translate } = useTranslation("dag"); + + const { data } = useDeadlinesServiceGetDagDeadlineAlerts({ dagId }); + const { data: missedData } = useDeadlinesServiceGetDeadlines({ + dagId, + dagRunId: "~", + lastUpdatedAtGte: dayjs().subtract(24, "hour").toISOString(), + limit: 1, + missed: true, + }); Review Comment: I feel like this extra logic is not useful unless we give the user actionable information about the missed deadlines. So let's either remove this and improve it later. ########## airflow-core/src/airflow/ui/src/pages/Dag/DeadlineAlertsBadge.tsx: ########## @@ -0,0 +1,110 @@ +/*! + * 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, HStack, Separator, Text, VStack } from "@chakra-ui/react"; +import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; +import { FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDeadlines, useDeadlinesServiceGetDagDeadlineAlerts } from "openapi/queries"; +import type { DeadlineAlertResponse } from "openapi/requests/types.gen"; +import { Popover } from "src/components/ui"; +import { renderDuration } from "src/utils"; + +const referenceTypeLabels: Record<string, string> = { + AverageRuntimeDeadline: "Average Runtime", + DagRunLogicalDateDeadline: "Logical Date", + DagRunQueuedAtDeadline: "Queued At", + FixedDatetimeDeadline: "Fixed Datetime", +}; + +const formatReferenceType = (referenceType: string): string => + referenceTypeLabels[referenceType] ?? referenceType; + +const AlertRow = ({ alert }: { readonly alert: DeadlineAlertResponse }) => { + const { t: translate } = useTranslation("dag"); + + return ( + <Box py={2} width="100%"> + <Text fontWeight="bold"> + {alert.name !== undefined && alert.name !== null && alert.name !== "" + ? alert.name + : translate("deadlineAlerts.unnamed")} + </Text> + {alert.description !== undefined && alert.description !== null && alert.description !== "" ? ( + <Text color="fg.muted" fontSize="xs"> + {alert.description} + </Text> + ) : undefined} + <HStack fontSize="xs" gap={3} mt={1}> + <Text color="fg.muted"> + {translate("deadlineAlerts.referenceType")}: {formatReferenceType(alert.reference_type)} + </Text> Review Comment: I wonder if we can make this more human-readable. "Run to complete within [interval] time of [reference]" so "Run to complete within 1 hour of logical date" <img width="304" height="106" alt="Image" src="https://github.com/user-attachments/assets/7f381b79-032c-4017-b9f7-cd76e251a87f" /> ########## airflow-core/src/airflow/ui/src/pages/Run/DeadlineStatus.tsx: ########## @@ -0,0 +1,109 @@ +/*! + * 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 { Badge, HStack, Text, VStack } from "@chakra-ui/react"; +import { useTranslation } from "react-i18next"; +import { FiAlertTriangle, FiCheck, FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDagDeadlineAlerts, useDeadlinesServiceGetDeadlines } from "openapi/queries"; +import Time from "src/components/Time"; + +type DeadlineStatusProps = { + readonly dagId: string; + readonly dagRunId: string; +}; + +export const DeadlineStatus = ({ dagId, dagRunId }: DeadlineStatusProps) => { + const { t: translate } = useTranslation("dag"); + + const { data: deadlineData, isLoading: isLoadingDeadlines } = useDeadlinesServiceGetDeadlines({ + dagId, + dagRunId, + limit: 10, + orderBy: ["deadline_time"], + }); + + const { data: alertData, isLoading: isLoadingAlerts } = useDeadlinesServiceGetDagDeadlineAlerts({ + dagId, + }); + + if (isLoadingDeadlines || isLoadingAlerts) { + return undefined; + } + + const deadlines = deadlineData?.deadlines ?? []; + const hasAlerts = (alertData?.total_entries ?? 0) > 0; + + if (deadlines.length === 0 && !hasAlerts) { + return undefined; + } + + if (deadlines.length === 0 && hasAlerts) { + return ( + <HStack gap={1}> + <Badge colorPalette="green" size="sm" variant="solid"> + <FiCheck color="var(--chakra-colors-fg-white)" /> Review Comment: I don't think we even need to specify color. I believe it will be inferred. ########## airflow-core/src/airflow/ui/src/pages/Dag/DeadlineAlertsBadge.tsx: ########## @@ -0,0 +1,110 @@ +/*! + * 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, HStack, Separator, Text, VStack } from "@chakra-ui/react"; +import dayjs from "dayjs"; +import { useTranslation } from "react-i18next"; +import { FiClock } from "react-icons/fi"; + +import { useDeadlinesServiceGetDeadlines, useDeadlinesServiceGetDagDeadlineAlerts } from "openapi/queries"; +import type { DeadlineAlertResponse } from "openapi/requests/types.gen"; +import { Popover } from "src/components/ui"; +import { renderDuration } from "src/utils"; + +const referenceTypeLabels: Record<string, string> = { + AverageRuntimeDeadline: "Average Runtime", + DagRunLogicalDateDeadline: "Logical Date", + DagRunQueuedAtDeadline: "Queued At", + FixedDatetimeDeadline: "Fixed Datetime", +}; + +const formatReferenceType = (referenceType: string): string => + referenceTypeLabels[referenceType] ?? referenceType; + +const AlertRow = ({ alert }: { readonly alert: DeadlineAlertResponse }) => { + const { t: translate } = useTranslation("dag"); + + return ( + <Box py={2} width="100%"> + <Text fontWeight="bold"> + {alert.name !== undefined && alert.name !== null && alert.name !== "" + ? alert.name + : translate("deadlineAlerts.unnamed")} + </Text> + {alert.description !== undefined && alert.description !== null && alert.description !== "" ? ( + <Text color="fg.muted" fontSize="xs"> + {alert.description} + </Text> + ) : undefined} + <HStack fontSize="xs" gap={3} mt={1}> + <Text color="fg.muted"> + {translate("deadlineAlerts.referenceType")}: {formatReferenceType(alert.reference_type)} + </Text> Review Comment: Unless we expect name and description to do that work. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
