fix: standardize button order, add confirmation dialogs for destructive actions

- Fix Cancel|Save order and add primary/loading props (AppConfigDetailPage)
- Add AlertDialog before stopping deployments (AppsTab)
- Add ConfirmDialog before deleting taps (TapConfigModal)
- Add AlertDialog before killing queries with toast feedback (DatabaseAdminPage)
- Add AlertDialog before removing roles from users (UsersTab)
- Standardize Cancel button to variant="ghost" (TapConfigModal, RouteDetail)
- Add loading prop to ConfirmDialogs (OidcConfigPage, RouteDetail)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-09 18:39:22 +02:00
parent 3d910af491
commit fb53dc6dfc
7 changed files with 95 additions and 31 deletions

View File

@@ -49,6 +49,7 @@ export default function UsersTab({ highlightId, onHighlightConsumed }: { highlig
const [creating, setCreating] = useState(false);
const [deleteTarget, setDeleteTarget] = useState<UserDetail | null>(null);
const [removeGroupTarget, setRemoveGroupTarget] = useState<string | null>(null);
const [removeRoleTarget, setRemoveRoleTarget] = useState<{ id: string; name: string } | null>(null);
// Auto-select highlighted item from cmd-k navigation
useEffect(() => {
@@ -515,25 +516,7 @@ export default function UsersTab({ highlightId, onHighlightConsumed }: { highlig
key={r.id}
label={r.name}
color="warning"
onRemove={() => {
removeRole.mutate(
{ userId: selected.userId, roleId: r.id },
{
onSuccess: () =>
toast({
title: 'Role removed',
description: r.name,
variant: 'success',
}),
onError: () =>
toast({
title: 'Failed to remove role',
variant: 'error',
duration: 86_400_000,
}),
},
);
}}
onRemove={() => setRemoveRoleTarget(r)}
/>
))}
{inheritedRoles.map((r) => (
@@ -621,6 +604,31 @@ export default function UsersTab({ highlightId, onHighlightConsumed }: { highlig
confirmLabel="Remove"
variant="warning"
/>
<AlertDialog
open={removeRoleTarget !== null}
onClose={() => setRemoveRoleTarget(null)}
onConfirm={() => {
if (removeRoleTarget && selected) {
removeRole.mutate(
{ userId: selected.userId, roleId: removeRoleTarget.id },
{
onSuccess: () => {
toast({ title: 'Role removed', description: removeRoleTarget.name, variant: 'success' });
setRemoveRoleTarget(null);
},
onError: () => {
toast({ title: 'Failed to remove role', variant: 'error', duration: 86_400_000 });
setRemoveRoleTarget(null);
},
},
);
}
}}
title="Remove role"
description={`Remove the "${removeRoleTarget?.name}" role from this user?`}
confirmLabel="Remove"
variant="warning"
/>
</>
);
}