diff --git a/apps/portal/src/routes/(app)/calculator/+page.svelte b/apps/portal/src/routes/(app)/calculator/+page.svelte index 815fabc..0431acd 100644 --- a/apps/portal/src/routes/(app)/calculator/+page.svelte +++ b/apps/portal/src/routes/(app)/calculator/+page.svelte @@ -73,6 +73,10 @@ return JSON.stringify(current) !== JSON.stringify(savedSnapshot); }); + const isLive = $derived( + !!editor && editor.configId !== null && editor.configId === liveConfigId, + ); + const selectedMetrics = $derived({ gender: metrics.gender, age: metrics.age ?? 0, @@ -158,32 +162,39 @@ editor.data = res.data.data; } - async function persist(mode: "update" | "create") { - if (!editor || !editor.name) return; + async function persist(mode: "update" | "create", nameOverride?: string) { + if (!editor) return; + const name = nameOverride ?? editor.name; + if (!name) return; + if (mode === "update" && editor.configId && editor.configId === liveConfigId) + return; const target = editor; saveError = null; saving = true; try { if (mode === "update" && target.configId) { const res = await api.standards.configs({ id: target.configId }).put({ - name: target.name, + name, datasetId: target.datasetId, params: target.params, }); if (res.error) throw res.error; } else { const res = await api.standards.configs.post({ - name: target.name, + name, datasetId: target.datasetId, params: target.params, }); if (res.error) throw res.error; - // only stamp the new id if the user hasn't switched away in the meantime - if (editor === target) editor.configId = res.data.id; + // only stamp the new id/name if the user hasn't switched away in the meantime + if (editor === target) { + editor.configId = res.data.id; + editor.name = name; + } } if (editor === target) { savedSnapshot = { - name: target.name, + name, datasetId: target.datasetId, params: $state.snapshot(target.params), }; @@ -201,8 +212,16 @@ return persist(editor?.configId ? "update" : "create"); } - function saveAsNew() { - return persist("create"); + function promptSaveAsNew() { + if (!editor) return; + const name = prompt( + "Name for the new configuration:", + editor.name ? `${editor.name} copy` : "", + ); + if (name === null) return; + const trimmed = name.trim(); + if (!trimmed) return; + return persist("create", trimmed); } async function discard() { @@ -213,6 +232,12 @@ async function setLive() { if (!editor?.configId || isDirty) return; const configId = editor.configId; + if ( + !confirm( + `Set "${editor.name || "(untitled)"}" as the live configuration? This will immediately affect live calculations.`, + ) + ) + return; saveError = null; settingLive = true; try { @@ -313,11 +338,27 @@ {/each} + {#if isDirty} Unsaved - {:else if currentEditor.configId === liveConfigId} - Live + {/if} + +
+ + {#if isLive} ++ This is the live configuration and is read-only — click "+" + to create an editable copy. +
{/if} @@ -329,27 +370,21 @@ > Discard changes - @@ -359,6 +394,7 @@ {/if} +