Add ability to delete configurations
This commit is contained in:
@@ -157,6 +157,9 @@ export const app = new Elysia()
|
|||||||
params: t.Object({ id: t.String() }),
|
params: t.Object({ id: t.String() }),
|
||||||
body: t.Object({ name: t.String(), datasetId: t.String(), params: StandardsParamsSchema })
|
body: t.Object({ name: t.String(), datasetId: t.String(), params: StandardsParamsSchema })
|
||||||
})
|
})
|
||||||
|
.delete("/configs/:id", async ({ params: { id } }) => {
|
||||||
|
await s.Standards.Configs.delete(id);
|
||||||
|
}, { params: t.Object({ id: t.String() }) })
|
||||||
.get("/datasets", async () => {
|
.get("/datasets", async () => {
|
||||||
return await s.Standards.Datasets.list();
|
return await s.Standards.Datasets.list();
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -61,6 +61,18 @@ class StandardsConfigService {
|
|||||||
.execute();
|
.execute();
|
||||||
if (result[0]?.numUpdatedRows === 0n) throw new Error(`No config with id "${id}"`);
|
if (result[0]?.numUpdatedRows === 0n) throw new Error(`No config with id "${id}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async delete(id: string) {
|
||||||
|
const { count } = await db.selectFrom("standards_configs")
|
||||||
|
.select(db.fn.countAll<number>().as("count"))
|
||||||
|
.executeTakeFirstOrThrow();
|
||||||
|
if (Number(count) <= 1) throw new Error("Cannot delete the last remaining standards configuration");
|
||||||
|
|
||||||
|
const result = await db.deleteFrom("standards_configs")
|
||||||
|
.where("id", "=", id)
|
||||||
|
.execute();
|
||||||
|
if (result[0]?.numDeletedRows === 0n) throw new Error(`No config with id "${id}"`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StandardsDatasetService {
|
class StandardsDatasetService {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
let saveError = $state<string | null>(null);
|
let saveError = $state<string | null>(null);
|
||||||
let saving = $state(false);
|
let saving = $state(false);
|
||||||
let settingLive = $state(false);
|
let settingLive = $state(false);
|
||||||
|
let deleting = $state(false);
|
||||||
|
|
||||||
const allStandards = $derived(
|
const allStandards = $derived(
|
||||||
editor
|
editor
|
||||||
@@ -229,6 +230,26 @@
|
|||||||
await loadConfig(editor.configId, { skipDirtyCheck: true });
|
await loadConfig(editor.configId, { skipDirtyCheck: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteConfig() {
|
||||||
|
if (!editor?.configId || isLive) return;
|
||||||
|
if (!confirm(`Delete "${editor.name || "(untitled)"}"? This cannot be undone.`))
|
||||||
|
return;
|
||||||
|
const configId = editor.configId;
|
||||||
|
saveError = null;
|
||||||
|
deleting = true;
|
||||||
|
try {
|
||||||
|
const res = await api.standards.configs({ id: configId }).delete();
|
||||||
|
if (res.error) throw res.error;
|
||||||
|
localStorage.removeItem(DRAFT_KEY);
|
||||||
|
await refreshLists();
|
||||||
|
if (liveConfigId) await loadConfig(liveConfigId, { skipDirtyCheck: true });
|
||||||
|
} catch (err) {
|
||||||
|
saveError = errorMessage(err);
|
||||||
|
} finally {
|
||||||
|
deleting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function setLive() {
|
async function setLive() {
|
||||||
if (!editor?.configId || isDirty) return;
|
if (!editor?.configId || isDirty) return;
|
||||||
const configId = editor.configId;
|
const configId = editor.configId;
|
||||||
@@ -346,7 +367,7 @@
|
|||||||
class="btn btn-ghost btn-sm btn-square"
|
class="btn btn-ghost btn-sm btn-square"
|
||||||
title="Save as new configuration"
|
title="Save as new configuration"
|
||||||
aria-label="Save as new configuration"
|
aria-label="Save as new configuration"
|
||||||
disabled={saving}
|
disabled={saving || deleting}
|
||||||
onclick={promptSaveAsNew}
|
onclick={promptSaveAsNew}
|
||||||
>
|
>
|
||||||
<span class="text-lg leading-none">+</span>
|
<span class="text-lg leading-none">+</span>
|
||||||
@@ -377,7 +398,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm"
|
||||||
hidden={isLive && !isDirty}
|
hidden={isLive && !isDirty}
|
||||||
disabled={saving || !isDirty || isLive}
|
disabled={saving || !isDirty || isLive || deleting}
|
||||||
onclick={save}
|
onclick={save}
|
||||||
>
|
>
|
||||||
{saving ? "Saving..." : "Save"}
|
{saving ? "Saving..." : "Save"}
|
||||||
@@ -385,11 +406,34 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-outline btn-sm"
|
class="btn btn-outline btn-sm"
|
||||||
hidden={currentEditor.configId === liveConfigId}
|
hidden={currentEditor.configId === liveConfigId}
|
||||||
disabled={settingLive || isDirty}
|
disabled={settingLive || isDirty || deleting}
|
||||||
onclick={setLive}
|
onclick={setLive}
|
||||||
>
|
>
|
||||||
{settingLive ? "Setting live..." : "Set as live"}
|
{settingLive ? "Setting live..." : "Set as live"}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<details hidden={isLive} class="dropdown dropdown-end">
|
||||||
|
<summary
|
||||||
|
class="btn btn-ghost btn-sm btn-square list-none"
|
||||||
|
title="More actions"
|
||||||
|
aria-label="More actions"
|
||||||
|
>
|
||||||
|
<span class="text-lg leading-none">⋮</span>
|
||||||
|
</summary>
|
||||||
|
<ul
|
||||||
|
class="dropdown-content menu bg-base-200 border border-base-300 rounded-box z-20 w-40 p-2 shadow-lg mt-2"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class="text-error"
|
||||||
|
disabled={deleting || isLive || !currentEditor.configId}
|
||||||
|
onclick={deleteConfig}
|
||||||
|
>
|
||||||
|
{deleting ? "Deleting..." : "Delete"}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if saveError}
|
{#if saveError}
|
||||||
|
|||||||
Reference in New Issue
Block a user