This is an automated email from the ASF dual-hosted git repository.

jscheffl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 9178f8f0b1f Data Interval Date validation of trigger Dag form  (#45223)
9178f8f0b1f is described below

commit 9178f8f0b1ffd80b8eacf4d02b732528fde218e5
Author: Shubham Raj <[email protected]>
AuthorDate: Fri Dec 27 03:48:04 2024 +0530

    Data Interval Date validation of trigger Dag form  (#45223)
    
    * throw error instead of replacing
    
    * manage error
    
    * reset
    
    * handle close
    
    * remove then
    
    ---------
    
    Co-authored-by: Shubham <[email protected]>
---
 .../src/components/TriggerDag/TriggerDAGForm.tsx   | 56 ++++++++------------
 airflow/ui/src/queries/useTrigger.ts               | 61 +++++++++++++++++-----
 2 files changed, 70 insertions(+), 47 deletions(-)

diff --git a/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx 
b/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx
index 8288849ecf1..19f1aedbd01 100644
--- a/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx
+++ b/airflow/ui/src/components/TriggerDag/TriggerDAGForm.tsx
@@ -48,14 +48,18 @@ export type DagRunTriggerParams = {
 const TriggerDAGForm = ({ dagId, onClose, open }: TriggerDAGFormProps) => {
   const [errors, setErrors] = useState<{ conf?: string; date?: unknown }>({});
   const conf = useDagParams(dagId, open);
-  const { error: errorTrigger, isPending, triggerDagRun } = 
useTrigger(onClose);
+  const {
+    dateValidationError,
+    error: errorTrigger,
+    isPending,
+    triggerDagRun,
+  } = useTrigger({ onSuccessConfirm: onClose });
 
   const {
     control,
     formState: { isDirty },
     handleSubmit,
     reset,
-    setValue,
     watch,
   } = useForm<DagRunTriggerParams>({
     defaultValues: {
@@ -74,28 +78,27 @@ const TriggerDAGForm = ({ dagId, onClose, open }: 
TriggerDAGFormProps) => {
     }
   }, [conf, reset]);
 
+  useEffect(() => {
+    if (Boolean(dateValidationError)) {
+      setErrors((prev) => ({ ...prev, date: dateValidationError }));
+    }
+  }, [dateValidationError]);
+
   const dataIntervalStart = watch("dataIntervalStart");
   const dataIntervalEnd = watch("dataIntervalEnd");
 
   const handleReset = () => {
     setErrors({ conf: undefined, date: undefined });
-    reset();
+    reset({
+      conf,
+      dagRunId: "",
+      dataIntervalEnd: "",
+      dataIntervalStart: "",
+      note: "",
+    });
   };
 
   const onSubmit = (data: DagRunTriggerParams) => {
-    if (Boolean(data.dataIntervalStart) !== Boolean(data.dataIntervalEnd)) {
-      setErrors((prev) => ({
-        ...prev,
-        date: {
-          body: {
-            detail:
-              "Either both Data Interval Start and End must be provided, or 
both must be empty.",
-          },
-        },
-      }));
-
-      return;
-    }
     triggerDagRun(dagId, data);
   };
 
@@ -119,23 +122,8 @@ const TriggerDAGForm = ({ dagId, onClose, open }: 
TriggerDAGFormProps) => {
     }
   };
 
-  const validateDates = (
-    fieldName: "dataIntervalEnd" | "dataIntervalStart",
-  ) => {
-    const startDate = dataIntervalStart
-      ? new Date(dataIntervalStart)
-      : undefined;
-    const endDate = dataIntervalEnd ? new Date(dataIntervalEnd) : undefined;
-
+  const resetDateError = () => {
     setErrors((prev) => ({ ...prev, date: undefined }));
-
-    if (startDate && endDate) {
-      if (fieldName === "dataIntervalStart" && startDate > endDate) {
-        setValue("dataIntervalStart", dataIntervalEnd);
-      } else if (fieldName === "dataIntervalEnd" && endDate < startDate) {
-        setValue("dataIntervalEnd", dataIntervalStart);
-      }
-    }
   };
 
   const { colorMode } = useColorMode();
@@ -160,7 +148,7 @@ const TriggerDAGForm = ({ dagId, onClose, open }: 
TriggerDAGFormProps) => {
                     <Input
                       {...field}
                       max={dataIntervalEnd || undefined}
-                      onBlur={() => validateDates("dataIntervalStart")}
+                      onBlur={resetDateError}
                       placeholder="yyyy-mm-ddThh:mm"
                       size="sm"
                       type="datetime-local"
@@ -180,7 +168,7 @@ const TriggerDAGForm = ({ dagId, onClose, open }: 
TriggerDAGFormProps) => {
                     <Input
                       {...field}
                       min={dataIntervalStart || undefined}
-                      onBlur={() => validateDates("dataIntervalEnd")}
+                      onBlur={resetDateError}
                       placeholder="yyyy-mm-ddThh:mm"
                       size="sm"
                       type="datetime-local"
diff --git a/airflow/ui/src/queries/useTrigger.ts 
b/airflow/ui/src/queries/useTrigger.ts
index b454d0176a7..d70efc8aeff 100644
--- a/airflow/ui/src/queries/useTrigger.ts
+++ b/airflow/ui/src/queries/useTrigger.ts
@@ -28,10 +28,17 @@ import {
 import type { DagRunTriggerParams } from 
"src/components/TriggerDag/TriggerDAGForm";
 import { toaster } from "src/components/ui";
 
-export const useTrigger = (onClose: () => void) => {
+export const useTrigger = ({
+  onSuccessConfirm,
+}: {
+  onSuccessConfirm: () => void;
+}) => {
   const queryClient = useQueryClient();
   const [error, setError] = useState<unknown>(undefined);
 
+  const [dateValidationError, setDateValidationError] =
+    useState<unknown>(undefined);
+
   const onSuccess = async () => {
     const queryKeys = [
       useDagServiceGetDagsKey,
@@ -43,14 +50,13 @@ export const useTrigger = (onClose: () => void) => {
       queryKeys.map((key) =>
         queryClient.invalidateQueries({ queryKey: [key] }),
       ),
-    ).then(() => {
-      toaster.create({
-        description: "DAG run has been successfully triggered.",
-        title: "DAG Run Request Submitted",
-        type: "success",
-      });
-      onClose();
+    );
+    toaster.create({
+      description: "DAG run has been successfully triggered.",
+      title: "DAG Run Request Submitted",
+      type: "success",
     });
+    onSuccessConfirm();
   };
 
   const onError = (_error: unknown) => {
@@ -71,13 +77,42 @@ export const useTrigger = (onClose: () => void) => {
       unknown
     >;
 
-    const formattedDataIntervalStart = dagRunRequestBody.dataIntervalStart
-      ? new Date(dagRunRequestBody.dataIntervalStart).toISOString()
+    const DataIntervalStart = dagRunRequestBody.dataIntervalStart
+      ? new Date(dagRunRequestBody.dataIntervalStart)
       : undefined;
-    const formattedDataIntervalEnd = dagRunRequestBody.dataIntervalEnd
-      ? new Date(dagRunRequestBody.dataIntervalEnd).toISOString()
+    const DataIntervalEnd = dagRunRequestBody.dataIntervalEnd
+      ? new Date(dagRunRequestBody.dataIntervalEnd)
       : undefined;
 
+    if (Boolean(DataIntervalStart) !== Boolean(DataIntervalEnd)) {
+      setDateValidationError({
+        body: {
+          detail:
+            "Either both Data Interval Start Date and End Date must be 
provided, or both must be empty.",
+        },
+      });
+
+      return;
+    }
+
+    if (DataIntervalStart && DataIntervalEnd) {
+      if (DataIntervalStart > DataIntervalEnd) {
+        setDateValidationError({
+          body: {
+            detail:
+              "Data Interval Start Date must be less than or equal to Data 
Interval End Date.",
+          },
+        });
+
+        return;
+      }
+    }
+
+    const formattedDataIntervalStart =
+      DataIntervalStart?.toISOString() ?? undefined;
+    const formattedDataIntervalEnd =
+      DataIntervalEnd?.toISOString() ?? undefined;
+
     const checkDagRunId =
       dagRunRequestBody.dagRunId === ""
         ? undefined
@@ -97,5 +132,5 @@ export const useTrigger = (onClose: () => void) => {
     });
   };
 
-  return { error, isPending, triggerDagRun };
+  return { dateValidationError, error, isPending, triggerDagRun };
 };

Reply via email to