From 2804f2cbf956c659804c8375e24f15362daeeb9b Mon Sep 17 00:00:00 2001 From: Dominic Ferrando Date: Wed, 8 Jul 2026 13:25:07 -0400 Subject: [PATCH] Add initial portal frontend for configuration managemetn --- apps/api/src/services/calculator.ts | 11 +- .../src/routes/(app)/calculator/+page.svelte | 708 +++++++++++------- 2 files changed, 442 insertions(+), 277 deletions(-) diff --git a/apps/api/src/services/calculator.ts b/apps/api/src/services/calculator.ts index 7b50460..d2cdbec 100644 --- a/apps/api/src/services/calculator.ts +++ b/apps/api/src/services/calculator.ts @@ -55,9 +55,10 @@ class CalculatorStandardsConfigService { return Date.now() - this.lastRefreshedAt >= this.refreshInterval; }, isIncomplete: function () { - return !this.data.datasetId || !this.data.config + return !this.data.id || !this.data.datasetId || !this.data.config }, data: { + id: null as string | null, datasetId: null as string | null, config: null as StandardsConfig | null }, @@ -65,10 +66,10 @@ class CalculatorStandardsConfigService { constructor(private name: string) { } - async get(): Promise { + async get(): Promise { await this.refresh({ onlyIfStale: true }); - if (!this.cache.data.config) throw new CalculatorUnavailableError("Unable to determine the calculator's standards configuration"); - return this.cache.data.config; + if (!this.cache.data.id || !this.cache.data.config) throw new CalculatorUnavailableError("Unable to determine the calculator's standards configuration"); + return { id: this.cache.data.id, ...this.cache.data.config }; } async refresh(opt: { onlyIfStale?: boolean } = {}): Promise { @@ -79,6 +80,7 @@ class CalculatorStandardsConfigService { .innerJoin("standards_configs", "standards_configs.id", "calculators.standards_config_id") .innerJoin("standards_datasets", "standards_datasets.id", "standards_configs.dataset_id") .select([ + "standards_configs.id as id", "standards_configs.dataset_id as datasetId", "standards_configs.params as params", "standards_datasets.data as data", @@ -89,6 +91,7 @@ class CalculatorStandardsConfigService { Value.Assert(StandardsParamsSchema, result.params); Value.Assert(StandardsDataSchema, result.data); + this.cache.data.id = result.id; this.cache.data.datasetId = result.datasetId; this.cache.data.config = { data: result.data, diff --git a/apps/portal/src/routes/(app)/calculator/+page.svelte b/apps/portal/src/routes/(app)/calculator/+page.svelte index 2d13946..58d0cff 100644 --- a/apps/portal/src/routes/(app)/calculator/+page.svelte +++ b/apps/portal/src/routes/(app)/calculator/+page.svelte @@ -1,8 +1,10 @@ -{#if !(input.standardsConfig && allStandards)} +{#if !(editor && allStandards)}
- {#if standardsConfigLoadError} + {#if loadError} {:else} {/if}
{:else} - {@const standardsConfig = input.standardsConfig} -
-
- - Data - + {@const currentEditor = editor} +
+ -
-
- - General - + -
+ {#if isDirty} + Unsaved + {:else if currentEditor.configId === liveConfigId} + Live + {/if} + +
+ + + + + +
+ + {#if saveError} + + {/if} + +
+
+
+ Data + +
+
+ General + +
+ + +
+
+ +
+ Data Generation + +
+ + + + + + +
+ Stretch + + +
+
+
+
+
+ + {#if activeTab === "standards"} +
+ Metrics +
+ + +
- -
- - Data Generation - - -
- - - - - - - - - - - - - - - - - - - - - - -
- - Stretch - - - -
-
-
-
-
- - {#if activeTab === "standards"} -
- - Metrics - -
- - - - - -
-
- {/if} + {/if} +
@@ -356,7 +514,11 @@ {#if activeTab === "standards"} {/if}