Better restrict editing of the live configuration
This commit is contained in:
@@ -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 @@
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button
|
||||
class="btn btn-ghost btn-sm btn-square"
|
||||
title="Save as new configuration"
|
||||
aria-label="Save as new configuration"
|
||||
disabled={saving}
|
||||
onclick={promptSaveAsNew}
|
||||
>
|
||||
<span class="text-lg leading-none">+</span>
|
||||
</button>
|
||||
|
||||
{#if isDirty}
|
||||
<span class="badge badge-warning badge-sm">Unsaved</span>
|
||||
{:else if currentEditor.configId === liveConfigId}
|
||||
<span class="badge badge-success badge-sm">Live</span>
|
||||
{/if}
|
||||
|
||||
<div class="flex-1"></div>
|
||||
|
||||
{#if isLive}
|
||||
<p class="text-sm text-info opacity-90">
|
||||
This is the live configuration and is read-only — click "+"
|
||||
to create an editable copy.
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<div class="flex-1"></div>
|
||||
@@ -329,27 +370,21 @@
|
||||
>
|
||||
Discard changes
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-outline btn-sm"
|
||||
hidden={currentEditor.configId === liveConfigId || isDirty}
|
||||
disabled={settingLive || isDirty}
|
||||
onclick={setLive}
|
||||
>
|
||||
{settingLive ? "Setting live..." : "Set as live"}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary btn-sm"
|
||||
disabled={saving || !isDirty}
|
||||
hidden={isLive}
|
||||
disabled={saving || !isDirty || isLive}
|
||||
onclick={save}
|
||||
>
|
||||
{saving ? "Saving..." : "Save"}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-outline btn-sm"
|
||||
disabled={saving || !currentEditor.name}
|
||||
onclick={saveAsNew}
|
||||
hidden={currentEditor.configId === liveConfigId}
|
||||
disabled={settingLive || isDirty}
|
||||
onclick={setLive}
|
||||
>
|
||||
Save as new
|
||||
{settingLive ? "Setting live..." : "Set as live"}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -359,6 +394,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
<section class="w-full flex gap-4 flex-wrap mt-6">
|
||||
<fieldset class="fieldset bg-base-200 p-4">
|
||||
<label class="flex flex-col gap-1">
|
||||
@@ -374,6 +410,7 @@
|
||||
<select
|
||||
class="select select-sm w-36"
|
||||
value={currentEditor.datasetId}
|
||||
disabled={isLive}
|
||||
onchange={(e) => onDatasetChange(e.currentTarget.value)}
|
||||
>
|
||||
{#each datasets as dataset}
|
||||
@@ -385,6 +422,7 @@
|
||||
<span class="label text-xs">Max level</span>
|
||||
<input
|
||||
class="input input-sm w-36"
|
||||
disabled={isLive}
|
||||
type="number"
|
||||
min="1"
|
||||
max="100"
|
||||
@@ -414,7 +452,7 @@
|
||||
</label>
|
||||
|
||||
<div class="flex gap-3 flex-wrap">
|
||||
<fieldset class="fieldset bg-base-300 p-2">
|
||||
<fieldset class="fieldset bg-base-300 p-2" disabled={isLive}>
|
||||
<legend class="fieldset-legend text-sm font-semibold"
|
||||
>Modifiers</legend
|
||||
>
|
||||
@@ -429,7 +467,7 @@
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="fieldset bg-base-300 p-2">
|
||||
<fieldset class="fieldset bg-base-300 p-2" disabled={isLive}>
|
||||
<legend class="fieldset-legend text-sm font-semibold"
|
||||
>Generation</legend
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user