feat: add delete confirmation dialog for apps
Prevents accidental app deletion by requiring the user to type the app slug before confirming. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { useParams, useNavigate } from 'react-router';
|
|||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
|
ConfirmDialog,
|
||||||
DataTable,
|
DataTable,
|
||||||
Input,
|
Input,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -271,6 +272,7 @@ function AppDetailView({ appId, environments, selectedEnv }: { appId: string; en
|
|||||||
const deleteApp = useDeleteApp();
|
const deleteApp = useDeleteApp();
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
const [subTab, setSubTab] = useState<'overview' | 'config'>('overview');
|
const [subTab, setSubTab] = useState<'overview' | 'config'>('overview');
|
||||||
|
const [deleteConfirm, setDeleteConfirm] = useState(false);
|
||||||
|
|
||||||
const envMap = useMemo(() => new Map(environments.map((e) => [e.id, e])), [environments]);
|
const envMap = useMemo(() => new Map(environments.map((e) => [e.id, e])), [environments]);
|
||||||
const sortedVersions = useMemo(() => [...versions].sort((a, b) => b.version - a.version), [versions]);
|
const sortedVersions = useMemo(() => [...versions].sort((a, b) => b.version - a.version), [versions]);
|
||||||
@@ -323,7 +325,7 @@ function AppDetailView({ appId, environments, selectedEnv }: { appId: string; en
|
|||||||
<div className={styles.detailActions}>
|
<div className={styles.detailActions}>
|
||||||
<input ref={fileInputRef} type="file" accept=".jar" style={{ display: 'none' }} onChange={handleUpload} />
|
<input ref={fileInputRef} type="file" accept=".jar" style={{ display: 'none' }} onChange={handleUpload} />
|
||||||
<Button size="sm" variant="primary" onClick={() => fileInputRef.current?.click()} loading={uploadJar.isPending}>Upload JAR</Button>
|
<Button size="sm" variant="primary" onClick={() => fileInputRef.current?.click()} loading={uploadJar.isPending}>Upload JAR</Button>
|
||||||
<Button size="sm" variant="danger" onClick={handleDelete}>Delete App</Button>
|
<Button size="sm" variant="danger" onClick={() => setDeleteConfirm(true)}>Delete App</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -342,6 +344,15 @@ function AppDetailView({ appId, environments, selectedEnv }: { appId: string; en
|
|||||||
{subTab === 'config' && (
|
{subTab === 'config' && (
|
||||||
<ConfigSubTab app={app} environment={env} />
|
<ConfigSubTab app={app} environment={env} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<ConfirmDialog
|
||||||
|
open={deleteConfirm}
|
||||||
|
onClose={() => setDeleteConfirm(false)}
|
||||||
|
onConfirm={handleDelete}
|
||||||
|
message={`Delete app "${app.displayName}"? All versions and deployments will be removed. This cannot be undone.`}
|
||||||
|
confirmText={app.slug}
|
||||||
|
loading={deleteApp.isPending}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user