From 2f8cb91d31f97f8e537a30d0b4d7c58d0971c3fb Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Tue, 17 Oct 2023 00:32:54 +0200 Subject: [PATCH] Studio: Fix some usability errors --- src/UI/Base/LoginToggle.svelte | 5 +-- src/UI/Popup/LoginButton.ts | 2 +- .../TagRendering/TagRenderingEditable.svelte | 2 +- src/UI/SpecialVisualizations.ts | 7 ++-- src/UI/Studio/EditLayerState.ts | 34 +++++++++++++------ src/UI/Studio/SchemaBasedField.svelte | 6 ++-- src/UI/Studio/SchemaBasedMultiType.svelte | 11 ++---- src/UI/Studio/TagRenderingInput.svelte | 4 +-- src/UI/StudioGUI.svelte | 2 +- 9 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/UI/Base/LoginToggle.svelte b/src/UI/Base/LoginToggle.svelte index 93df7e84b..8aa8e7fcf 100644 --- a/src/UI/Base/LoginToggle.svelte +++ b/src/UI/Base/LoginToggle.svelte @@ -28,7 +28,8 @@ {#if $badge} - {#if !ignoreLoading && $loadingStatus === "loading"} + + {/if} diff --git a/src/UI/Popup/LoginButton.ts b/src/UI/Popup/LoginButton.ts index 7e7f585cc..d47f22b13 100644 --- a/src/UI/Popup/LoginButton.ts +++ b/src/UI/Popup/LoginButton.ts @@ -88,7 +88,7 @@ export class LoginToggle extends VariableUiElement { ) }, [state.featureSwitchUserbadge, state.osmConnection?.apiIsOnline] - ) ?? new ImmutableStore(el) // + ) ?? new ImmutableStore(el) ) } } diff --git a/src/UI/Popup/TagRendering/TagRenderingEditable.svelte b/src/UI/Popup/TagRendering/TagRenderingEditable.svelte index 11c4646a7..6dfb260ab 100644 --- a/src/UI/Popup/TagRendering/TagRenderingEditable.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingEditable.svelte @@ -16,7 +16,7 @@ export let tags: UIEventSource> export let selectedElement: Feature | undefined export let state: SpecialVisualizationState - export let layer: LayerConfig + export let layer: LayerConfig = undefined export let editingEnabled : Store | undefined = state?.featureSwitchUserbadge diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 31509b0b5..262a4fa6b 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -986,6 +986,9 @@ export default class SpecialVisualizations { constr: (state, tagsSource) => new VariableUiElement( tagsSource.map((tags) => { + if (state.layout === undefined) { + return "" + } const layer = state.layout.getMatchingLayer(tags) const title = layer?.title?.GetRenderValue(tags) if (title === undefined) { @@ -1335,10 +1338,10 @@ export default class SpecialVisualizations { tagSource.map((tags) => { const v = tags[argument[0] ?? "value"] try { - const tr = JSON.parse(v) + const tr = typeof v === "string" ? JSON.parse(v) : v return new Translation(tr).SetClass("font-bold") } catch (e) { - return v + return JSON.stringify(v) } }) ) diff --git a/src/UI/Studio/EditLayerState.ts b/src/UI/Studio/EditLayerState.ts index dc15a1682..82abb0435 100644 --- a/src/UI/Studio/EditLayerState.ts +++ b/src/UI/Studio/EditLayerState.ts @@ -15,6 +15,7 @@ import { AllSharedLayers } from "../../Customizations/AllSharedLayers" import { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" import { TagUtils } from "../../Logic/Tags/TagUtils" import StudioServer from "./StudioServer" +import { Utils } from "../../Utils" /** * Sends changes back to the server @@ -72,9 +73,9 @@ export default class EditLayerState { } this.messages = this.configuration.mapD((config) => { const context = ConversionContext.construct([], ["prepare"]) - - for (let i = 0; i < (config.tagRenderings ?? []).length; i++) { - const tr = config.tagRenderings[i] + const trs = Utils.NoNull(config.tagRenderings ?? []) + for (let i = 0; i < trs.length; i++) { + const tr = trs[i] if (typeof tr === "string") { continue } @@ -116,11 +117,19 @@ export default class EditLayerState { return entry } - public getStoreFor(path: ReadonlyArray): UIEventSource { + private readonly _stores = new Map>() + public getStoreFor(path: ReadonlyArray): UIEventSource { + const key = path.join(".") + + // TODO check if this gives problems when changing the order of e.g. mappings and questions + if (this._stores.has(key)) { + return this._stores.get(key) + } const store = new UIEventSource(this.getCurrentValueFor(path)) store.addCallback((v) => { this.setValueAt(path, v) }) + this._stores.set(key, store) return store } @@ -170,19 +179,24 @@ export default class EditLayerState { public setValueAt(path: ReadonlyArray, v: any) { let entry = this.configuration.data + const isUndefined = + v !== undefined && + v !== null && + v !== "" && + !(typeof v === "object" && Object.keys({}).length === 0) + for (let i = 0; i < path.length - 1; i++) { const breadcrumb = path[i] if (entry[breadcrumb] === undefined) { entry[breadcrumb] = typeof path[i + 1] === "number" ? [] : {} } entry = entry[breadcrumb] + if (entry === undefined && isUndefined) { + // Nothing to do anymore: we cannot traverse the object, but don't have to set something anyway + return + } } - if ( - v !== undefined && - v !== null && - v !== "" && - !(typeof v === "object" && Object.keys({}).length === 0) - ) { + if (isUndefined) { entry[path.at(-1)] = v } else if (entry) { delete entry[path.at(-1)] diff --git a/src/UI/Studio/SchemaBasedField.svelte b/src/UI/Studio/SchemaBasedField.svelte index 573e57bd5..272d8389f 100644 --- a/src/UI/Studio/SchemaBasedField.svelte +++ b/src/UI/Studio/SchemaBasedField.svelte @@ -29,7 +29,7 @@ const configJson: QuestionableTagRenderingConfigJson = { id: path.join("_"), - render: schema.type === "boolean" ? undefined : ((schema.hints.inline ?? schema.path.at(-1) )+ ": {translated(value)}"), + render: schema.type === "boolean" ? undefined : ((schema.hints.inline ?? schema.path.at(-1) )+ ": translated value: {translated(value)}"), question: schema.hints.question, questionHint: nmd(schema.description), freeform: schema.type === "boolean" ? undefined : { @@ -100,7 +100,9 @@ try { onDestroy(state.register(path, tags.map(tgs => { const v = tgs["value"]; - console.log("Registering",path,"setting value to", v) + if(v !== ""){ + console.log("Registering",path,"setting value to", v) + } if(typeof v !== "string"){ return v } diff --git a/src/UI/Studio/SchemaBasedMultiType.svelte b/src/UI/Studio/SchemaBasedMultiType.svelte index d712edd66..a9df2a859 100644 --- a/src/UI/Studio/SchemaBasedMultiType.svelte +++ b/src/UI/Studio/SchemaBasedMultiType.svelte @@ -113,7 +113,6 @@ for (const requiredAttribute of type.required) { if (existingValue[requiredAttribute] === undefined) { - console.log(path.join("."), " does not have required field", requiredAttribute, " so it cannot be type ", type); // The 'existingValue' does _not_ have this required attribute, so it cannot be of this type continue outer; } @@ -128,7 +127,6 @@ } possibleTypes.sort((a, b) => b.optionalMatches - a.optionalMatches); possibleTypes.sort((a, b) => b.matchingPropertiesCount - a.matchingPropertiesCount); - console.log("Possible types are", possibleTypes) if (possibleTypes.length > 0) { chosenOption = possibleTypes[0].index tags.setData({ chosen_type_index: "" + chosenOption}); @@ -157,27 +155,23 @@ let subSchemas: ConfigMeta[] = []; let subpath = path; - console.log("Initial chosen option for",path.join("."),"is", chosenOption); + const store = state.getStoreFor(path) onDestroy(tags.addCallbackAndRun(tags => { if (tags["value"] !== undefined && tags["value"] !== "") { chosenOption = undefined; - console.log("Resetting chosenOption as `value` is present in the tags:", tags["value"]) return; } const oldOption = chosenOption; - console.log("Updating chosenOption based on", tags, oldOption) chosenOption = tags["chosen_type_index"] ? Number(tags["chosen_type_index"]) : defaultOption; const type = schema.type[chosenOption]; if (chosenOption !== oldOption) { // Reset the values beneath subSchemas = []; const o = state.getCurrentValueFor(path) ?? {}; - console.log({ o }); for (const key of type?.required ?? []) { - console.log(key); o[key] ??= {}; } - state.setValueAt(path, o); + store.setData(o) } if (!type) { return; @@ -187,7 +181,6 @@ if (type["$ref"] === "#/definitions/Record") { // The subtype is a translation object const schema = state.getTranslationAt(cleanPath); - console.log("Got a translation,", schema); subSchemas.push(schema); subpath = path.slice(0, path.length - 2); return; diff --git a/src/UI/Studio/TagRenderingInput.svelte b/src/UI/Studio/TagRenderingInput.svelte index 31c7274bb..1559e8997 100644 --- a/src/UI/Studio/TagRenderingInput.svelte +++ b/src/UI/Studio/TagRenderingInput.svelte @@ -44,9 +44,9 @@ const configBuiltin = new TagRenderingConfig( { - state.setValueAt(path, tgs["value"]); + store.setData(tgs["value"]) }); let mappings: UIEventSource = state.getStoreFor([...path, "mappings"]); diff --git a/src/UI/StudioGUI.svelte b/src/UI/StudioGUI.svelte index ee4d3536a..cfbfe5fde 100644 --- a/src/UI/StudioGUI.svelte +++ b/src/UI/StudioGUI.svelte @@ -17,7 +17,7 @@ import layerSchemaRaw from "../../src/assets/schemas/layerconfigmeta.json"; import If from "./Base/If.svelte"; - export let studioUrl = /* "https://studio.mapcomplete.org"; /*/ "http://127.0.0.1:1235"; //*/ + export let studioUrl = window.location.hostname === "127.0.0.1" ? "http://127.0.0.1:1235" : "https://studio.mapcomplete.org"; const studio = new StudioServer(studioUrl); let layersWithErr = UIEventSource.FromPromiseWithErr(studio.fetchLayerOverview()); let layers = layersWithErr.mapD(l => l.success);