feat(dashboard): confirm modal for script delete
Replaces window.confirm + alert() with the in-dashboard ConfirmModal (danger variant, name-retype). Body summarises what gets removed (routes + execution logs) and embeds the API error inline rather than firing a native alert. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
pathKindMismatchWarning
|
pathKindMismatchWarning
|
||||||
} from '$lib/route-utils';
|
} from '$lib/route-utils';
|
||||||
import CodeEditor from '$lib/CodeEditor.svelte';
|
import CodeEditor from '$lib/CodeEditor.svelte';
|
||||||
|
import ConfirmModal from '$lib/ConfirmModal.svelte';
|
||||||
import { format as formatRhai } from '$lib/rhai';
|
import { format as formatRhai } from '$lib/rhai';
|
||||||
|
|
||||||
/// Pretty-print a JSON string in place, leaving it untouched if the
|
/// Pretty-print a JSON string in place, leaving it untouched if the
|
||||||
@@ -375,16 +376,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------- deletion ----------------
|
// ---------------- deletion ----------------
|
||||||
|
let confirmingDelete = $state(false);
|
||||||
let deleting = $state(false);
|
let deleting = $state(false);
|
||||||
async function remove() {
|
let deleteError = $state<string | null>(null);
|
||||||
|
|
||||||
|
function askDelete() {
|
||||||
|
deleteError = null;
|
||||||
|
confirmingDelete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function confirmDelete() {
|
||||||
if (!script) return;
|
if (!script) return;
|
||||||
if (!confirm(`Delete script "${script.name}"? This cannot be undone.`)) return;
|
|
||||||
deleting = true;
|
deleting = true;
|
||||||
|
deleteError = null;
|
||||||
try {
|
try {
|
||||||
await api.scripts.remove(id);
|
await api.scripts.remove(id);
|
||||||
await goto(base + '/');
|
await goto(base + '/');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(e instanceof Error ? e.message : String(e));
|
deleteError = e instanceof Error ? e.message : String(e);
|
||||||
|
} finally {
|
||||||
deleting = false;
|
deleting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,7 +439,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{#if canAdmin}
|
{#if canAdmin}
|
||||||
<button type="button" class="danger" onclick={remove} disabled={deleting}>
|
<button type="button" class="danger" onclick={askDelete} disabled={deleting}>
|
||||||
{deleting ? 'Deleting…' : 'Delete'}
|
{deleting ? 'Deleting…' : 'Delete'}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -821,6 +831,35 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if confirmingDelete && script}
|
||||||
|
<ConfirmModal
|
||||||
|
title="Delete script “{script.name}”"
|
||||||
|
variant="danger"
|
||||||
|
confirmLabel="Delete script"
|
||||||
|
busyLabel="Deleting…"
|
||||||
|
confirmPhrase={script.name}
|
||||||
|
confirmPhrasePrompt="Type the script name to confirm:"
|
||||||
|
busy={deleting}
|
||||||
|
onConfirm={confirmDelete}
|
||||||
|
onCancel={() => (confirmingDelete = false)}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
This will <strong>permanently delete</strong>
|
||||||
|
<strong>{script.name}</strong>, all its routes, and all its
|
||||||
|
execution logs. There is no undo.
|
||||||
|
</p>
|
||||||
|
{#if routes.length > 0}
|
||||||
|
<p class="muted">
|
||||||
|
{routes.length} route{routes.length === 1 ? '' : 's'} bound to
|
||||||
|
this script will be removed.
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
{#if deleteError}
|
||||||
|
<p class="modal-error">{deleteError}</p>
|
||||||
|
{/if}
|
||||||
|
</ConfirmModal>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user