fix: use ConfirmDialog for dismiss, move warning to top of page
Replace window.confirm with design system ConfirmDialog for the dismiss action. Move the "No agents connected" section to the top of the Runtime page using Alert component with warning variant. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
StatCard, StatusDot, Badge, MonoText,
|
||||
GroupCard, DataTable, EventFeed,
|
||||
LogViewer, ButtonGroup, SectionHeader, Toggle, Select, Button, useToast,
|
||||
Alert, ConfirmDialog,
|
||||
} from '@cameleer/design-system';
|
||||
import type { Column, FeedEvent, LogEntry, ButtonGroupItem } from '@cameleer/design-system';
|
||||
import styles from './AgentHealth.module.css';
|
||||
@@ -111,6 +112,7 @@ export default function AgentHealth() {
|
||||
const dismissApp = useDismissApp();
|
||||
const catalogEntry = catalogApps?.find((a) => a.slug === appId);
|
||||
|
||||
const [confirmDismissOpen, setConfirmDismissOpen] = useState(false);
|
||||
const [configEditing, setConfigEditing] = useState(false);
|
||||
const [configDraft, setConfigDraft] = useState<Record<string, string | boolean>>({});
|
||||
|
||||
@@ -292,6 +294,46 @@ export default function AgentHealth() {
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
{/* No agents warning + dismiss — shown when app-scoped, no agents, admin */}
|
||||
{appId && agentList.length === 0 && isAdmin && (
|
||||
<>
|
||||
<Alert variant="warning" title="No agents connected">
|
||||
<span>
|
||||
{catalogEntry?.managed ? 'Managed app' : 'Discovered app'} — {(catalogEntry?.exchangeCount ?? 0).toLocaleString()} exchanges recorded.
|
||||
{' '}You can dismiss this application to remove it and all associated data.
|
||||
</span>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Button variant="danger" size="sm" disabled={dismissApp.isPending}
|
||||
onClick={() => setConfirmDismissOpen(true)}>
|
||||
{dismissApp.isPending ? 'Dismissing\u2026' : 'Dismiss Application'}
|
||||
</Button>
|
||||
</div>
|
||||
</Alert>
|
||||
<ConfirmDialog
|
||||
open={confirmDismissOpen}
|
||||
onClose={() => setConfirmDismissOpen(false)}
|
||||
onConfirm={() => {
|
||||
setConfirmDismissOpen(false);
|
||||
dismissApp.mutate(appId, {
|
||||
onSuccess: () => {
|
||||
toast({ title: 'Application dismissed', description: `${appId} and all associated data have been deleted`, variant: 'success' });
|
||||
navigate('/runtime');
|
||||
},
|
||||
onError: (err) => {
|
||||
toast({ title: 'Dismiss failed', description: err.message, variant: 'error', duration: 86_400_000 });
|
||||
},
|
||||
});
|
||||
}}
|
||||
title="Dismiss Application"
|
||||
message={`This will permanently delete "${appId}" and all associated data (${(catalogEntry?.exchangeCount ?? 0).toLocaleString()} exchanges, logs, diagrams).`}
|
||||
confirmText="This action cannot be undone."
|
||||
confirmLabel="Dismiss"
|
||||
variant="danger"
|
||||
loading={dismissApp.isPending}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Stat strip */}
|
||||
<div className={styles.statStrip}>
|
||||
<StatCard
|
||||
@@ -476,45 +518,6 @@ export default function AgentHealth() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Dismiss application card — shown when app-scoped, no agents, admin */}
|
||||
{appId && agentList.length === 0 && isAdmin && (
|
||||
<div className={`${sectionStyles.section}`} style={{ marginBottom: 16, padding: '16px 20px' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<div>
|
||||
<strong>No agents connected</strong>
|
||||
{catalogEntry && (
|
||||
<span style={{ marginLeft: 8, color: 'var(--text-muted)', fontSize: 13 }}>
|
||||
{catalogEntry.managed ? 'Managed app' : 'Discovered app'} — {catalogEntry.exchangeCount.toLocaleString()} exchanges recorded
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
variant="danger"
|
||||
size="sm"
|
||||
disabled={dismissApp.isPending}
|
||||
onClick={() => {
|
||||
const count = catalogEntry?.exchangeCount ?? 0;
|
||||
const ok = window.confirm(
|
||||
`Dismiss "${appId}" and permanently delete all data (${count.toLocaleString()} exchanges)?\n\nThis action cannot be undone.`
|
||||
);
|
||||
if (ok) {
|
||||
dismissApp.mutate(appId, {
|
||||
onSuccess: () => {
|
||||
toast({ title: 'Application dismissed', description: `${appId} and all associated data have been deleted`, variant: 'success' });
|
||||
navigate('/runtime');
|
||||
},
|
||||
onError: (err) => {
|
||||
toast({ title: 'Dismiss failed', description: err.message, variant: 'error', duration: 86_400_000 });
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
{dismissApp.isPending ? 'Dismissing\u2026' : 'Dismiss Application'}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Group cards grid */}
|
||||
<div className={isFullWidth ? styles.groupGridSingle : styles.groupGrid}>
|
||||
|
||||
Reference in New Issue
Block a user