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

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git


The following commit(s) were added to refs/heads/master by this push:
     new 83ca53f  fix(ui): dismiss the confirm dialog after confirming
83ca53f is described below

commit 83ca53f1d231545f982970f37b6c0b93378982c0
Author: Yang Luo <[email protected]>
AuthorDate: Fri Sep 4 00:31:54 2026 +0800

    fix(ui): dismiss the confirm dialog after confirming
---
 web/src/components/shared/confirm-dialog.tsx | 18 +++++++++++++-----
 web/src/pages/AgentDetailPage.tsx            | 14 ++++++++++----
 web/src/pages/AgentsPage.tsx                 |  5 ++++-
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/web/src/components/shared/confirm-dialog.tsx 
b/web/src/components/shared/confirm-dialog.tsx
index 8fad78a..637fbbf 100644
--- a/web/src/components/shared/confirm-dialog.tsx
+++ b/web/src/components/shared/confirm-dialog.tsx
@@ -61,23 +61,31 @@ export function ConfirmDialog({
   onOpenChange?: (open: boolean) => void;
 }) {
   const [pending, setPending] = React.useState(false);
+  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
+  const isOpen = open ?? uncontrolledOpen;
+
+  const setOpen = (next: boolean) => {
+    if (open === undefined) {
+      setUncontrolledOpen(next);
+    }
+    onOpenChange?.(next);
+  };
 
   const handleConfirm = async(event: React.MouseEvent) => {
-    // The dialog closes itself on action; awaiting first would let it close
-    // before an async handler reports a failure, so errors are surfaced by the
-    // handler's own toast instead.
+    // Hold the dialog open while an async handler runs, then close it here, 
so a
+    // failure surfaces (through the handler's own toast) before it disappears.
     event.preventDefault();
     setPending(true);
     try {
       await onConfirm();
     } finally {
       setPending(false);
-      onOpenChange?.(false);
+      setOpen(false);
     }
   };
 
   return (
-    <AlertDialog open={open} onOpenChange={onOpenChange}>
+    <AlertDialog open={isOpen} onOpenChange={setOpen}>
       <AlertDialogTrigger asChild disabled={disabled}>
         {children}
       </AlertDialogTrigger>
diff --git a/web/src/pages/AgentDetailPage.tsx 
b/web/src/pages/AgentDetailPage.tsx
index 19f3260..f4aee80 100644
--- a/web/src/pages/AgentDetailPage.tsx
+++ b/web/src/pages/AgentDetailPage.tsx
@@ -14,7 +14,7 @@
 
 import * as React from "react";
 import {Link, useParams, useSearchParams} from "react-router-dom";
-import {ArrowLeft, Bot, ChevronRight, CircleX, Copy, RefreshCw} from 
"lucide-react";
+import {ArrowLeft, Bot, ChevronRight, CircleX, Copy, Eye, EyeOff, RefreshCw} 
from "lucide-react";
 import copy from "copy-to-clipboard";
 import i18next from "i18next";
 
@@ -84,6 +84,7 @@ function MonitoringCard({
   onToggle: () => void;
 }) {
   const action = i18next.t(`agent:${agent.patched ? "Unpatch" : "Patch"}`);
+  const Icon = agent.patched ? EyeOff : Eye;
   const note = [agent.notice, agent.followup].filter(Boolean).join(" ");
 
   return (
@@ -113,13 +114,18 @@ function MonitoringCard({
             variant={agent.patched ? "destructive" : "default"}
             onConfirm={onToggle}
           >
-            <Button variant={agent.patched ? "outline" : "default"} 
disabled={busy}>
-              {busy ? <AiDots size="small" /> : null}
+            <Button
+              size="sm"
+              variant={agent.patched ? "outline" : "default"}
+              loading={busy}
+            >
+              <Icon />
               {action}
             </Button>
           </ConfirmDialog>
         ) : (
-          <Button variant="outline" disabled>
+          <Button size="sm" variant="outline" disabled>
+            <Eye />
             {i18next.t("agent:Patch")}
           </Button>
         )}
diff --git a/web/src/pages/AgentsPage.tsx b/web/src/pages/AgentsPage.tsx
index 5285313..32c4482 100644
--- a/web/src/pages/AgentsPage.tsx
+++ b/web/src/pages/AgentsPage.tsx
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 import {Link} from "react-router-dom";
-import {ArrowLeft, Bot, Container, RefreshCw} from "lucide-react";
+import {ArrowLeft, Bot, Container, Eye, EyeOff, RefreshCw} from "lucide-react";
 import i18next from "i18next";
 
 import * as Setting from "@/Setting";
@@ -195,12 +195,14 @@ export default function AgentsPage({account}: {account: 
Account}) {
     if (!record.supported) {
       return (
         <Button size="sm" variant="outline" disabled>
+          <Eye />
           {i18next.t("agent:Patch")}
         </Button>
       );
     }
 
     const action = i18next.t(`agent:${record.patched ? "Unpatch" : "Patch"}`);
+    const Icon = record.patched ? EyeOff : Eye;
     const note = [record.notice, record.followup].filter(Boolean).join(" ");
     return (
       <ConfirmDialog
@@ -215,6 +217,7 @@ export default function AgentsPage({account}: {account: 
Account}) {
           variant={record.patched ? "outline" : "default"}
           loading={busyKey === agentKey(record)}
         >
+          <Icon />
           {action}
         </Button>
       </ConfirmDialog>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to