This is an automated email from the ASF dual-hosted git repository. jscheffl pushed a commit to branch revert-59231-feature/trigger-url-params in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 56c4855a59ffcf3a2d290e4fd18fba5a229f898b Author: Jens Scheffler <[email protected]> AuthorDate: Tue Dec 23 18:10:06 2025 +0100 Revert "Feat: Support URL params for pre-filling Trigger and Backfill forms (…" This reverts commit 907b4ef5340d8a489ea547a14ae2e6449b0b1a4e. --- airflow-core/docs/core-concepts/params.rst | 52 -------- .../src/airflow/ui/src/components/ConfigForm.tsx | 6 +- .../src/components/DagActions/RunBackfillForm.tsx | 47 +++----- .../TriggerDag/TriggerDAGAdvancedOptions.tsx | 3 +- .../src/components/TriggerDag/TriggerDAGForm.tsx | 132 ++++++++------------- .../src/components/TriggerDag/TriggerDAGModal.tsx | 26 +--- .../airflow/ui/src/pages/Dag/Overview/Overview.tsx | 19 +-- .../src/airflow/ui/src/queries/useTrigger.ts | 4 +- airflow-core/src/airflow/ui/src/router.tsx | 1 - airflow-core/src/airflow/ui/src/utils/trigger.ts | 114 ------------------ docs/spelling_wordlist.txt | 1 - 11 files changed, 79 insertions(+), 326 deletions(-) diff --git a/airflow-core/docs/core-concepts/params.rst b/airflow-core/docs/core-concepts/params.rst index ca3fb6849b3..cdcd150a73b 100644 --- a/airflow-core/docs/core-concepts/params.rst +++ b/airflow-core/docs/core-concepts/params.rst @@ -409,55 +409,3 @@ Disabling Runtime Param Modification The ability to update params while triggering a Dag depends on the flag ``core.dag_run_conf_overrides_params``. Setting this config to ``False`` will effectively turn your default params into constants. - -Pre-populating Trigger Form via URL ------------------------------------ - -To pre-populate values in the form when publishing a link to the trigger form you can call the trigger URL ``/dags/<dag_name>/trigger/single`` or ``/dags/<dag_name>/trigger/backfill``, -and add query parameters to the URL. - -There are two trigger form URLs available, each supporting a different set of query parameters: - -* ``/trigger/single``: - - ``conf`` - JSON configuration. - - ``run_id`` - run identifier. - - ``logical_date`` - execution date in ``YYYY-MM-DDTHH:mm:ss.SSS`` format. Defaults to the current timestamp if not provided. - - ``note`` - note attached to the DAG run. - -* ``/trigger/backfill``: - - ``conf`` - JSON configuration, applied to all runs. - - ``from_date`` - start of the backfill window in ``YYYY-MM-DDTHH:mm:ss`` format. - - ``to_date`` - end of the backfill window in ``YYYY-MM-DDTHH:mm:ss`` format. - - ``max_active_runs`` - maximum concurrent runs. Defaults to ``1``. - - ``reprocess_behavior`` - determines how existing runs are reprocessed. Supported values are: - - * ``failed`` - Missing and Errored Runs - * ``completed`` - All Runs - * ``none`` - Missing Runs - - - ``run_backwards`` - if set to true, the backfill is scheduled in reverse order. Defaults to ``false``. - -The trigger form supports two different ways of providing ``conf`` values. The available input methods are summarized in the table below: - -.. list-table:: ``conf`` parameter usage - :header-rows: 1 - :widths: 15 35 55 - - * - Form - - Usage - - Example - * - JSON (explicit) - - Provide the entire configuration as a JSON object. - This form has higher priority if present. - - ``/dags/{dag_id}/trigger/single?conf={"foo":"bar","x":123}`` - * - Key-value (implicit) - - If ``conf`` is not specified, any query parameter that is not a reserved keyword - will be automatically collected into ``conf``. - - ``/dags/{dag_id}/trigger/single?run_id=myrun&foo=bar&x=123`` - results in ``conf={"foo":"bar","x":"123"}`` - -For example, you can pass the pathname and query like below: - -``/dags/{dag_id}/trigger/single?run_id=my_run_dag&logical_date=2025-09-06T12:34:56.789&conf={"foo":"bar"}¬e=run_note`` - -``/dags/{dag_id}/trigger/backfill?from_date=2025-09-01T00:00:00&to_date=2025-09-03T23:59:59&conf={"abc":"loo"}&max_active_runs=2&reprocess_behavior=failed&run_backwards=true`` diff --git a/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx b/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx index b8c52106586..65adf1bfca3 100644 --- a/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx +++ b/airflow-core/src/airflow/ui/src/components/ConfigForm.tsx @@ -35,7 +35,6 @@ type ConfigFormProps<T extends FieldValues = FieldValues> = { date?: unknown; }; readonly initialParamsDict: { paramsDict: ParamsSpec }; - readonly openAdvanced?: boolean; readonly setErrors: React.Dispatch< React.SetStateAction<{ conf?: string; @@ -50,7 +49,6 @@ const ConfigForm = <T extends FieldValues = FieldValues>({ control, errors, initialParamsDict, - openAdvanced = false, setErrors, setFormError, }: ConfigFormProps<T>) => { @@ -85,9 +83,7 @@ const ConfigForm = <T extends FieldValues = FieldValues>({ return ( <Accordion.Root collapsible - defaultValue={ - openAdvanced ? [flexibleFormDefaultSection, "advancedOptions"] : [flexibleFormDefaultSection] - } + defaultValue={[flexibleFormDefaultSection]} mb={4} overflow="visible" size="lg" diff --git a/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx b/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx index 0be91753c22..2d3a99b4600 100644 --- a/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx +++ b/airflow-core/src/airflow/ui/src/components/DagActions/RunBackfillForm.tsx @@ -21,14 +21,8 @@ import dayjs from "dayjs"; import { useEffect, useState } from "react"; import { Controller, useForm, useWatch } from "react-hook-form"; import { useTranslation } from "react-i18next"; -import { useSearchParams } from "react-router-dom"; -import type { - DAGResponse, - DAGWithLatestDagRunsResponse, - BackfillPostBody, - ReprocessBehavior, -} from "openapi/requests/types.gen"; +import type { BackfillPostBody, DAGResponse, DAGWithLatestDagRunsResponse } from "openapi/requests/types.gen"; import { RadioCardItem, RadioCardLabel, RadioCardRoot } from "src/components/ui/RadioCard"; import { reprocessBehaviors } from "src/constants/reprocessBehaviourParams"; import { useCreateBackfill } from "src/queries/useCreateBackfill"; @@ -36,12 +30,11 @@ import { useCreateBackfillDryRun } from "src/queries/useCreateBackfillDryRun"; import { useDagParams } from "src/queries/useDagParams"; import { useParamStore } from "src/queries/useParamStore"; import { useTogglePause } from "src/queries/useTogglePause"; -import { getTriggerConf } from "src/utils/trigger"; -import type { DagRunTriggerParams } from "src/utils/trigger"; import ConfigForm from "../ConfigForm"; import { DateTimeInput } from "../DateTimeInput"; import { ErrorAlert } from "../ErrorAlert"; +import type { DagRunTriggerParams } from "../TriggerDag/TriggerDAGForm"; import { Checkbox } from "../ui/Checkbox"; import { getInlineMessage } from "./inlineMessage"; @@ -59,19 +52,16 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { const [formError, setFormError] = useState(false); const initialParamsDict = useDagParams(dag.dag_id, true); const { conf } = useParamStore(); - const [searchParams] = useSearchParams(); - const reservedKeys = ["from_date", "to_date", "max_active_runs", "reprocess_behavior", "run_backwards"]; - const urlConf = getTriggerConf(searchParams, reservedKeys); - const { control, handleSubmit, reset } = useForm<BackfillFormProps>({ + const { control, handleSubmit, reset, watch } = useForm<BackfillFormProps>({ defaultValues: { - conf: urlConf === "{}" ? conf || "{}" : urlConf, + conf, dag_id: dag.dag_id, - from_date: searchParams.get("from_date") ?? "", - max_active_runs: parseInt(searchParams.get("max_active_runs") ?? "1", 10) || 1, - reprocess_behavior: (searchParams.get("reprocess_behavior") ?? "none") as ReprocessBehavior, - run_backwards: searchParams.get("run_backwards") === "true", + from_date: "", + max_active_runs: 1, + reprocess_behavior: "none", + run_backwards: false, run_on_latest_version: true, - to_date: searchParams.get("to_date") ?? "", + to_date: "", }, mode: "onBlur", }); @@ -101,13 +91,16 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { if (Boolean(dateValidationError)) { setErrors((prev) => ({ ...prev, date: dateValidationError })); } - if (Boolean(conf) && urlConf === "{}") { - reset((prev) => ({ ...prev, conf })); + }, [dateValidationError]); + useEffect(() => { + if (conf) { + reset((prevValues) => ({ ...prevValues, conf })); } - }, [dateValidationError, conf, reset, urlConf]); - - const noDataInterval = !Boolean(values.from_date) || !Boolean(values.to_date); - const dataIntervalInvalid = dayjs(values.from_date).isAfter(dayjs(values.to_date)); + }, [conf, reset]); + const dataIntervalStart = watch("from_date"); + const dataIntervalEnd = watch("to_date"); + const noDataInterval = !Boolean(dataIntervalStart) || !Boolean(dataIntervalEnd); + const dataIntervalInvalid = dayjs(dataIntervalStart).isAfter(dayjs(dataIntervalEnd)); const onSubmit = (fdata: BackfillFormProps) => { if (unpause && dag.is_paused) { @@ -246,10 +239,6 @@ const RunBackfillForm = ({ dag, onClose }: RunBackfillFormProps) => { control={control} errors={errors} initialParamsDict={initialParamsDict} - openAdvanced={ - urlConf !== "{}" || - ["max_active_runs", "reprocess_behavior", "run_backwards"].some((key) => searchParams.has(key)) - } setErrors={setErrors} setFormError={setFormError} /> diff --git a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx index 70c0b2a91b2..b8d3fe2b9f4 100644 --- a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx +++ b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGAdvancedOptions.tsx @@ -20,9 +20,8 @@ import { Input, Field, Stack } from "@chakra-ui/react"; import { Controller, type Control } from "react-hook-form"; import { useTranslation } from "react-i18next"; -import type { DagRunTriggerParams } from "src/utils/trigger"; - import EditableMarkdown from "./EditableMarkdown"; +import type { DagRunTriggerParams } from "./TriggerDAGForm"; type TriggerDAGAdvancedOptionsProps = { readonly control: Control<DagRunTriggerParams>; diff --git a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx index 4bad37b767b..cd291acb09e 100644 --- a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx +++ b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx @@ -18,26 +18,16 @@ */ import { Button, Box, Spacer, HStack, Field, Stack, Text, VStack } from "@chakra-ui/react"; import dayjs from "dayjs"; -import { useEffect, useState, useRef, useMemo } from "react"; +import { useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { FiPlay } from "react-icons/fi"; -import { useSearchParams } from "react-router-dom"; import { useDagParams } from "src/queries/useDagParams"; import { useParamStore } from "src/queries/useParamStore"; import { useTogglePause } from "src/queries/useTogglePause"; import { useTrigger } from "src/queries/useTrigger"; import { DEFAULT_DATETIME_FORMAT } from "src/utils/datetimeUtils"; -import { - getTriggerConf, - mergeUrlParams, - getUpdatedParamsDict, - type DagRunTriggerParams, - dataIntervalModeOptions, - extractParamValues, - type TriggerDAGFormProps, -} from "src/utils/trigger"; import ConfigForm from "../ConfigForm"; import { DateTimeInput } from "../DateTimeInput"; @@ -46,6 +36,33 @@ import { Checkbox } from "../ui/Checkbox"; import { RadioCardItem, RadioCardRoot } from "../ui/RadioCard"; import TriggerDAGAdvancedOptions from "./TriggerDAGAdvancedOptions"; +type TriggerDAGFormProps = { + readonly dagDisplayName: string; + readonly dagId: string; + readonly hasSchedule: boolean; + readonly isPaused: boolean; + readonly onClose: () => void; + readonly open: boolean; +}; + +type DataIntervalMode = "auto" | "manual"; + +export type DagRunTriggerParams = { + conf: string; + dagRunId: string; + dataIntervalEnd: string; + dataIntervalMode: DataIntervalMode; + dataIntervalStart: string; + logicalDate: string; + note: string; + partitionKey: string | undefined; +}; + +const dataIntervalModeOptions: Array<{ label: string; value: DataIntervalMode }> = [ + { label: "components:triggerDag.dataIntervalAuto", value: "auto" }, + { label: "components:triggerDag.dataIntervalManual", value: "manual" }, +]; + const TriggerDAGForm = ({ dagDisplayName, dagId, @@ -59,84 +76,38 @@ const TriggerDAGForm = ({ const [formError, setFormError] = useState(false); const initialParamsDict = useDagParams(dagId, open); const { error: errorTrigger, isPending, triggerDagRun } = useTrigger({ dagId, onSuccessConfirm: onClose }); - const { conf, setParamsDict } = useParamStore(); + const { conf } = useParamStore(); const [unpause, setUnpause] = useState(true); - const [searchParams] = useSearchParams(); - const urlConf = getTriggerConf(searchParams, ["run_id", "logical_date", "note"]); - const urlRunId = searchParams.get("run_id") ?? ""; - const urlDate = searchParams.get("logical_date"); - const urlNote = searchParams.get("note") ?? ""; const { mutate: togglePause } = useTogglePause({ dagId }); - const defaultsRef = useRef<DagRunTriggerParams | undefined>(undefined); - const isSyncedRef = useRef(false); - - const cleanInitialParams = useMemo( - () => extractParamValues(initialParamsDict.paramsDict as Record<string, unknown>), - [initialParamsDict.paramsDict], - ); - const { control, getValues, handleSubmit, reset, watch } = useForm<DagRunTriggerParams>({ + const { control, handleSubmit, reset, watch } = useForm<DagRunTriggerParams>({ defaultValues: { - ...initialParamsDict, - conf: urlConf === "{}" ? conf || "{}" : urlConf, - dagRunId: urlRunId, + conf, + dagRunId: "", dataIntervalEnd: "", dataIntervalMode: "auto", dataIntervalStart: "", // Default logical date to now, show it in the selected timezone - logicalDate: urlDate ?? dayjs().format(DEFAULT_DATETIME_FORMAT), - note: urlNote, - params: cleanInitialParams, + logicalDate: dayjs().format(DEFAULT_DATETIME_FORMAT), + note: "", partitionKey: undefined, }, }); // Automatically reset form when conf is fetched useEffect(() => { - if (defaultsRef.current === undefined && Object.keys(cleanInitialParams).length > 0) { - const current = getValues(); - - defaultsRef.current = { - ...current, - params: cleanInitialParams, - }; - } - }, [getValues, cleanInitialParams]); - - useEffect(() => { - if (defaultsRef.current === undefined) { - return; + if (conf) { + reset((prevValues) => ({ + ...prevValues, + conf, + })); } + }, [conf, reset]); - if (isSyncedRef.current) { - return; - } - - if (urlConf === "{}") { - if (conf) { - reset((prev) => ({ ...prev, conf })); - } - isSyncedRef.current = true; - - return; - } - - const mergedValues = mergeUrlParams(urlConf, defaultsRef.current.params ?? {}); - - reset({ - ...defaultsRef.current, - conf: JSON.stringify(mergedValues, undefined, 2), - dagRunId: urlRunId || defaultsRef.current.dagRunId, - logicalDate: urlDate ?? defaultsRef.current.logicalDate, - note: urlNote || defaultsRef.current.note, - }); - - setParamsDict(getUpdatedParamsDict(initialParamsDict.paramsDict, mergedValues)); - isSyncedRef.current = true; - }, [urlConf, urlRunId, urlDate, urlNote, initialParamsDict, reset, setParamsDict, conf]); - - const resetDateError = () => setErrors((prev) => ({ ...prev, date: undefined })); + const resetDateError = () => { + setErrors((prev) => ({ ...prev, date: undefined })); + }; const dataIntervalMode = watch("dataIntervalMode"); const dataIntervalStart = watch("dataIntervalStart"); @@ -145,17 +116,17 @@ const TriggerDAGForm = ({ const dataIntervalInvalid = dataIntervalMode === "manual" && (noDataInterval || dayjs(dataIntervalStart).isAfter(dayjs(dataIntervalEnd))); + const onSubmit = (data: DagRunTriggerParams) => { if (unpause && isPaused) { - togglePause({ dagId, requestBody: { is_paused: false } }); + togglePause({ + dagId, + requestBody: { + is_paused: false, + }, + }); } - - const finalParams = mergeUrlParams(data.conf, data.params ?? {}); - - triggerDagRun({ - ...data, - conf: JSON.stringify(finalParams), - }); + triggerDagRun(data); }; return ( @@ -248,7 +219,6 @@ const TriggerDAGForm = ({ control={control} errors={errors} initialParamsDict={initialParamsDict} - openAdvanced={urlConf !== "{}" || Boolean(urlRunId) || Boolean(urlDate) || Boolean(urlNote)} setErrors={setErrors} setFormError={setFormError} > diff --git a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsx b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsx index aaf9e22db52..9eb3e00a0e1 100644 --- a/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsx +++ b/airflow-core/src/airflow/ui/src/components/TriggerDag/TriggerDAGModal.tsx @@ -17,9 +17,8 @@ * under the License. */ import { Heading, VStack, HStack, Spinner, Center, Text } from "@chakra-ui/react"; -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { useTranslation } from "react-i18next"; -import { useParams, useNavigate } from "react-router-dom"; import { useDagServiceGetDag } from "openapi/queries"; import { Dialog, Tooltip } from "src/components/ui"; @@ -49,11 +48,7 @@ const TriggerDAGModal: React.FC<TriggerDAGModalProps> = ({ open, }) => { const { t: translate } = useTranslation("components"); - const { mode } = useParams(); - const navigate = useNavigate(); - const [runMode, setRunMode] = useState<RunMode>( - mode === RunMode.BACKFILL ? RunMode.BACKFILL : RunMode.SINGLE, - ); + const [runMode, setRunMode] = useState<RunMode>(RunMode.SINGLE); const { data: dag, isError, @@ -68,17 +63,6 @@ const TriggerDAGModal: React.FC<TriggerDAGModalProps> = ({ }, ); - useEffect(() => { - if (mode === RunMode.BACKFILL) { - setRunMode(RunMode.BACKFILL); - } else { - setRunMode(RunMode.SINGLE); - } - }, [mode]); - const handleModeChange = (value: string) => { - setRunMode(value as RunMode); - navigate(`/dags/${dagId}/trigger/${value}`, { replace: true }); - }; const hasSchedule = dag?.timetable_summary !== null; const maxDisplayLength = 59; // hard-coded length to prevent dag name overflowing the modal const nameOverflowing = dagDisplayName.length > maxDisplayLength; @@ -114,10 +98,8 @@ const TriggerDAGModal: React.FC<TriggerDAGModalProps> = ({ {dag ? ( <RadioCardRoot my={4} - onValueChange={(details) => { - if (details.value !== null) { - handleModeChange(details.value); - } + onChange={(event) => { + setRunMode((event.target as HTMLInputElement).value as RunMode); }} value={runMode} > diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx index 5dd2e2fa949..8cebcc4ba0b 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx @@ -20,13 +20,12 @@ import { Box, HStack, Skeleton } from "@chakra-ui/react"; import dayjs from "dayjs"; import { lazy, useState, Suspense } from "react"; import { useTranslation } from "react-i18next"; -import { useParams, useNavigate } from "react-router-dom"; +import { useParams } from "react-router-dom"; import { useLocalStorage } from "usehooks-ts"; import { useAssetServiceGetAssetEvents, useDagRunServiceGetDagRuns, - useDagServiceGetDag, useTaskInstanceServiceGetTaskInstances, } from "openapi/queries"; import { AssetEvents } from "src/components/Assets/AssetEvents"; @@ -34,7 +33,6 @@ import { DurationChart } from "src/components/DurationChart"; import { NeedsReviewButton } from "src/components/NeedsReviewButton"; import TimeRangeSelector from "src/components/TimeRangeSelector"; import { TrendCountButton } from "src/components/TrendCountButton"; -import TriggerDAGModal from "src/components/TriggerDag/TriggerDAGModal"; import { SearchParamsKeys } from "src/constants/searchParams"; import { useGridRuns } from "src/queries/useGridRuns.ts"; @@ -44,10 +42,7 @@ const defaultHour = "24"; export const Overview = () => { const { t: translate } = useTranslation("dag"); - const { dagId, mode } = useParams(); - const navigate = useNavigate(); - - const { data: dagData } = useDagServiceGetDag({ dagId: dagId ?? "" }); + const { dagId } = useParams(); const now = dayjs(); const [startDate, setStartDate] = useState(now.subtract(Number(defaultHour), "hour").toISOString()); @@ -145,16 +140,6 @@ export const Overview = () => { <Suspense fallback={<Skeleton height="100px" width="full" />}> <FailedLogs failedTasks={failedTasks} /> </Suspense> - - {dagData ? ( - <TriggerDAGModal - dagDisplayName={dagData.dag_display_name} - dagId={dagData.dag_id} - isPaused={dagData.is_paused} - onClose={() => navigate(`/dags/${dagId}`)} - open={Boolean(mode)} - /> - ) : null} </Box> ); }; diff --git a/airflow-core/src/airflow/ui/src/queries/useTrigger.ts b/airflow-core/src/airflow/ui/src/queries/useTrigger.ts index f395da3ca1c..de2baede248 100644 --- a/airflow-core/src/airflow/ui/src/queries/useTrigger.ts +++ b/airflow-core/src/airflow/ui/src/queries/useTrigger.ts @@ -29,8 +29,8 @@ import { UseGridServiceGetGridRunsKeyFn, } from "openapi/queries"; import type { TriggerDagRunResponse } from "openapi/requests/types.gen"; +import type { DagRunTriggerParams } from "src/components/TriggerDag/TriggerDAGForm"; import { toaster } from "src/components/ui"; -import type { DagRunTriggerParams } from "src/utils/trigger"; export const useTrigger = ({ dagId, onSuccessConfirm }: { dagId: string; onSuccessConfirm: () => void }) => { const queryClient = useQueryClient(); @@ -107,7 +107,7 @@ export const useTrigger = ({ dagId, onSuccessConfirm }: { dagId: string; onSucce data_interval_start: formattedDataIntervalStart, logical_date: formattedLogicalDate, note: checkNote, - partition_key: dagRunRequestBody.partitionKey ?? undefined, + partition_key: dagRunRequestBody.partitionKey ?? null, }, }); }; diff --git a/airflow-core/src/airflow/ui/src/router.tsx b/airflow-core/src/airflow/ui/src/router.tsx index faaff2bfa96..5c3ddc76174 100644 --- a/airflow-core/src/airflow/ui/src/router.tsx +++ b/airflow-core/src/airflow/ui/src/router.tsx @@ -160,7 +160,6 @@ export const routerConfig = [ { children: [ { element: <Overview />, index: true }, - { element: <Overview />, path: "trigger/:mode?" }, { element: <DagRuns />, path: "runs" }, { element: <Tasks />, path: "tasks" }, { element: <Calendar />, path: "calendar" }, diff --git a/airflow-core/src/airflow/ui/src/utils/trigger.ts b/airflow-core/src/airflow/ui/src/utils/trigger.ts deleted file mode 100644 index 1fd7c963b91..00000000000 --- a/airflow-core/src/airflow/ui/src/utils/trigger.ts +++ /dev/null @@ -1,114 +0,0 @@ -/*! - * 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. - */ - -// Helper to extract configuration from URL search params -export const getTriggerConf = (searchParams: URLSearchParams, reservedKeys: Array<string>) => { - const confParam = searchParams.get("conf"); - - // 1. If the user provided direct JSON 'conf' param (e.g., ?conf={"foo":"bar"}) - if (confParam !== null) { - try { - const parsed = JSON.parse(confParam) as unknown; - - return JSON.stringify(parsed, undefined, 2); - } catch { - // Ignore parsing errors - } - } - - // 2. If the user provided individual key-value params (e.g., ?foo=bar&run_id=123) - const collected: Record<string, unknown> = {}; - - searchParams.forEach((value, key) => { - // Do not include reserved keys (like run_id, date) in the config, as they belong to specific form fields - if (!reservedKeys.includes(key) && key !== "conf") { - collected[key] = value; - } - }); - - return Object.keys(collected).length > 0 ? JSON.stringify(collected, undefined, 2) : "{}"; -}; - -export type DataIntervalMode = "auto" | "manual"; - -export type DagRunTriggerParams = { - conf: string; - dagRunId: string; - dataIntervalEnd: string; - dataIntervalMode: DataIntervalMode; - dataIntervalStart: string; - logicalDate: string; - note: string; - params?: Record<string, unknown>; - partitionKey: string | undefined; -}; -export type TriggerDAGFormProps = { - readonly dagDisplayName: string; - readonly dagId: string; - readonly hasSchedule: boolean; - readonly isPaused: boolean; - readonly onClose: () => void; - readonly open: boolean; -}; -export const dataIntervalModeOptions: Array<{ label: string; value: DataIntervalMode }> = [ - { label: "components:triggerDag.dataIntervalAuto", value: "auto" }, - { label: "components:triggerDag.dataIntervalManual", value: "manual" }, -]; - -export const extractParamValues = (obj: Record<string, unknown>) => { - const out: Record<string, unknown> = {}; - - Object.entries(obj).forEach(([key, val]) => { - if (val !== null && typeof val === "object" && "value" in val) { - out[key] = (val as { value: unknown }).value; - } else if (val !== null && typeof val === "object" && "default" in val) { - out[key] = (val as { default: unknown }).default; - } else { - out[key] = val; - } - }); - - return out; -}; - -export const mergeUrlParams = (urlConf: string, baseParams: Record<string, unknown>) => { - try { - const parsed = urlConf === "{}" ? {} : (JSON.parse(urlConf) as Record<string, unknown>); - - return { ...baseParams, ...parsed }; - } catch { - return baseParams; - } -}; -export type ParamEntry = { - [key: string]: unknown; - value: unknown; -}; -export const getUpdatedParamsDict = <T>(paramsDict: T, mergedValues: Record<string, unknown>): T => { - const updated = structuredClone(paramsDict); - const record = updated as Record<string, { value: unknown }>; - - Object.entries(mergedValues).forEach(([key, val]) => { - if (record[key] !== undefined) { - record[key].value = val; - } - }); - - return updated; -}; diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 9cd8c459c19..a3e10044b57 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -1523,7 +1523,6 @@ replicaSet repo repos repr -reprocessed req reqs requeue
