diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json index 8085fcb942d81..8241c26ccae99 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/dag.json @@ -73,6 +73,12 @@ "navigation": "Navigation: Shift+{{arrow}}", "toggleGroup": "Toggle group: Space" }, + "notFound": { + "back": "Go Back", + "backToDags": "Back to Dags", + "message": "The Dag \"{{dagId}}\" does not exist.", + "title": "Dag Not Found" + }, "overview": { "buttons": { "failedRun_one": "Failed Run", diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx index 3ba287faffd2e..4ea3fa73d551b 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx @@ -26,6 +26,7 @@ import { RiArrowGoBackFill } from "react-icons/ri"; import { useParams } from "react-router-dom"; import { useDagServiceGetDagDetails, useDagServiceGetLatestRunInfo } from "openapi/queries"; +import { ApiError } from "openapi/requests/core/ApiError"; import { TaskIcon } from "src/assets/TaskIcon"; import { usePluginTabs } from "src/hooks/usePluginTabs"; import { useRequiredActionTabs } from "src/hooks/useRequiredActionTabs"; @@ -33,6 +34,7 @@ import { DetailsLayout } from "src/layouts/Details/DetailsLayout"; import { useRefreshOnNewDagRuns } from "src/queries/useRefreshOnNewDagRuns"; import { isStatePending, useAutoRefresh } from "src/utils"; +import { DagNotFound } from "./DagNotFound"; import { Header } from "./Header"; export const Dag = () => { @@ -103,6 +105,11 @@ export const Dag = () => { return true; }); + // Handle 404 error when Dag is not found + if (error instanceof ApiError && error.status === 404) { + return ; + } + return ( diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/DagNotFound.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/DagNotFound.tsx new file mode 100644 index 0000000000000..0a667e8ef63a8 --- /dev/null +++ b/airflow-core/src/airflow/ui/src/pages/Dag/DagNotFound.tsx @@ -0,0 +1,70 @@ +/*! + * 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, Container, Heading, HStack, Text, VStack } from "@chakra-ui/react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; + +import { AirflowPin } from "src/assets/AirflowPin"; + +type DagNotFoundProps = { + readonly dagId: string; +}; + +export const DagNotFound = ({ dagId }: DagNotFoundProps) => { + const navigate = useNavigate(); + const { t: translate } = useTranslation("dag"); + + return ( + + + + + + + 404 + {translate("notFound.title")} + {translate("notFound.message", { dagId })} + + + + + + + + + + ); +};