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

pierrejeambrun 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 ad47a5c3262 AIP-38: align delete model (#49514)
ad47a5c3262 is described below

commit ad47a5c32622da59dd706bf0d06e63073912757b
Author: Guan Ming(Wesley) Chiu <[email protected]>
AuthorDate: Tue Apr 22 22:23:52 2025 +0800

    AIP-38: align delete model (#49514)
---
 .../src/components/DagActions/DeleteDagButton.tsx  | 39 ++++--------
 .../src/airflow/ui/src/components/DeleteDialog.tsx | 74 ++++++++++++++++++++++
 .../ui/src/pages/Pools/DeletePoolButton.tsx        | 61 ++++++------------
 .../src/airflow/ui/src/pages/Pools/PoolBar.tsx     |  4 +-
 4 files changed, 107 insertions(+), 71 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/DagActions/DeleteDagButton.tsx 
b/airflow-core/src/airflow/ui/src/components/DagActions/DeleteDagButton.tsx
index 78cb556557d..28645696b15 100644
--- a/airflow-core/src/airflow/ui/src/components/DagActions/DeleteDagButton.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DagActions/DeleteDagButton.tsx
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Text, Heading, HStack, useDisclosure } from "@chakra-ui/react";
+import { useDisclosure } from "@chakra-ui/react";
 import { FiTrash2 } from "react-icons/fi";
 import { useNavigate } from "react-router-dom";
 
-import { Button, Dialog } from "src/components/ui";
+import DeleteDialog from "src/components/DeleteDialog";
 import ActionButton from "src/components/ui/ActionButton";
 import { useDeleteDag } from "src/queries/useDeleteDag";
 
@@ -54,32 +54,15 @@ const DeleteDagButton = ({ dagDisplayName, dagId, withText 
= true }: DeleteDagBu
         withText={withText}
       />
 
-      <Dialog.Root lazyMount onOpenChange={onClose} open={open} size="md" 
unmountOnExit>
-        <Dialog.Content backdrop>
-          <Dialog.Header>
-            <Heading size="lg">Delete DAG</Heading>
-          </Dialog.Header>
-          <Dialog.CloseTrigger />
-          <Dialog.Body>
-            <Text>
-              Are you sure you want to delete 
<strong>{dagDisplayName}</strong>? This action cannot be undone.
-            </Text>
-            <Text color="red.500" fontWeight="bold" mt={4}>
-              This will remove all metadata related to the DAG, including DAG 
Runs and Tasks.
-            </Text>
-          </Dialog.Body>
-          <Dialog.Footer>
-            <HStack justifyContent="flex-end" width="100%">
-              <Button onClick={onClose} variant="outline">
-                Cancel
-              </Button>
-              <Button colorPalette="red" loading={isPending} onClick={() => 
deleteDag({ dagId })}>
-                <FiTrash2 style={{ marginRight: "8px" }} /> Delete
-              </Button>
-            </HStack>
-          </Dialog.Footer>
-        </Dialog.Content>
-      </Dialog.Root>
+      <DeleteDialog
+        isDeleting={isPending}
+        onClose={onClose}
+        onDelete={() => deleteDag({ dagId })}
+        open={open}
+        resourceName={dagDisplayName}
+        title="Delete DAG"
+        warningText="This will remove all metadata related to the DAG, 
including DAG Runs and Tasks."
+      />
     </>
   );
 };
diff --git a/airflow-core/src/airflow/ui/src/components/DeleteDialog.tsx 
b/airflow-core/src/airflow/ui/src/components/DeleteDialog.tsx
new file mode 100644
index 00000000000..6d8ac6b56fc
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/components/DeleteDialog.tsx
@@ -0,0 +1,74 @@
+/*!
+ * 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 { Text, Heading, HStack } from "@chakra-ui/react";
+import React from "react";
+import { FiTrash2 } from "react-icons/fi";
+
+import { Button, Dialog } from "src/components/ui";
+
+type DeleteDialogProps = {
+  readonly deleteButtonText?: string;
+  readonly isDeleting: boolean;
+  readonly onClose: () => void;
+  readonly onDelete: () => void;
+  readonly open: boolean;
+  readonly resourceName: string;
+  readonly title: string;
+  readonly warningText: string;
+};
+
+const DeleteDialog: React.FC<DeleteDialogProps> = ({
+  deleteButtonText = "Delete",
+  isDeleting,
+  onClose,
+  onDelete,
+  open,
+  resourceName,
+  title,
+  warningText,
+}) => (
+  <Dialog.Root lazyMount onOpenChange={onClose} open={open} size="md" 
unmountOnExit>
+    <Dialog.Content backdrop>
+      <Dialog.Header>
+        <Heading size="lg">{title}</Heading>
+      </Dialog.Header>
+      <Dialog.CloseTrigger />
+      <Dialog.Body>
+        <Text>
+          Are you sure you want to delete <strong>{resourceName}</strong>? 
This action cannot be undone.
+        </Text>
+        <Text color="red.500" fontWeight="bold" mt={4}>
+          {warningText}
+        </Text>
+      </Dialog.Body>
+      <Dialog.Footer>
+        <HStack justifyContent="flex-end" width="100%">
+          <Button onClick={onClose} variant="outline">
+            Cancel
+          </Button>
+          <Button colorPalette="red" loading={isDeleting} onClick={onDelete}>
+            <FiTrash2 style={{ marginRight: "8px" }} /> {deleteButtonText}
+          </Button>
+        </HStack>
+      </Dialog.Footer>
+    </Dialog.Content>
+  </Dialog.Root>
+);
+
+export default DeleteDialog;
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx
index f2b7adf2769..1e76102ba83 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/DeletePoolButton.tsx
@@ -16,18 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Flex, useDisclosure, Text, VStack, Heading } from "@chakra-ui/react";
-import { FiTrash } from "react-icons/fi";
+import { useDisclosure } from "@chakra-ui/react";
+import { FiTrash2 } from "react-icons/fi";
 
-import { Button, Dialog } from "src/components/ui";
+import DeleteDialog from "src/components/DeleteDialog";
 import ActionButton from "src/components/ui/ActionButton";
 import { useDeletePool } from "src/queries/useDeletePool";
 
 type Props = {
   readonly poolName: string;
+  readonly withText?: boolean;
 };
 
-const DeletePoolButton = ({ poolName }: Props) => {
+const DeletePoolButton = ({ poolName, withText = false }: Props) => {
   const { onClose, onOpen, open } = useDisclosure();
   const { isPending, mutate } = useDeletePool({
     onSuccessConfirm: onClose,
@@ -37,47 +38,23 @@ const DeletePoolButton = ({ poolName }: Props) => {
     <>
       <ActionButton
         actionName="Delete Pool"
-        icon={<FiTrash />}
-        onClick={() => {
-          onOpen();
-        }}
+        colorPalette="red"
+        icon={<FiTrash2 />}
+        onClick={onOpen}
         text="Delete Pool"
-        withText={false}
+        variant="solid"
+        withText={withText}
       />
 
-      <Dialog.Root onOpenChange={onClose} open={open} size="xl">
-        <Dialog.Content backdrop>
-          <Dialog.Header>
-            <VStack align="start" gap={4}>
-              <Heading size="xl">Delete Pool</Heading>
-            </VStack>
-          </Dialog.Header>
-
-          <Dialog.CloseTrigger />
-
-          <Dialog.Body width="full">
-            <Text color="gray.solid" fontSize="md" fontWeight="semibold" 
mb={4}>
-              You are about to delete pool <strong>{poolName}</strong>.
-              <br />
-              This action is permanent and cannot be undone.{" "}
-              <strong>Are you sure you want to proceed?</strong>
-            </Text>
-            <Flex justifyContent="end" mt={3}>
-              <Button
-                colorPalette="red"
-                loading={isPending}
-                onClick={() => {
-                  mutate({
-                    poolName,
-                  });
-                }}
-              >
-                <FiTrash /> <Text fontWeight="bold">Yes, Delete</Text>
-              </Button>
-            </Flex>
-          </Dialog.Body>
-        </Dialog.Content>
-      </Dialog.Root>
+      <DeleteDialog
+        isDeleting={isPending}
+        onClose={onClose}
+        onDelete={() => mutate({ poolName })}
+        open={open}
+        resourceName={poolName}
+        title="Delete Pool"
+        warningText="This will remove all metadata related to the pool and may 
affect tasks using this pool."
+      />
     </>
   );
 };
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/PoolBar.tsx 
b/airflow-core/src/airflow/ui/src/pages/Pools/PoolBar.tsx
index 22bf9a0c43a..9c086cb5276 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/PoolBar.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/PoolBar.tsx
@@ -57,7 +57,9 @@ const PoolBar = ({ pool }: PoolBarProps) => (
           </Text>
           <HStack gap={0}>
             <EditPoolButton pool={pool} />
-            {pool.name === "default_pool" ? undefined : <DeletePoolButton 
poolName={pool.name} />}
+            {pool.name === "default_pool" ? undefined : (
+              <DeletePoolButton poolName={pool.name} withText={false} />
+            )}
           </HStack>
         </HStack>
         {pool.description ?? (

Reply via email to