diff --git a/scripts/hetzner/deployHetzner.sh b/scripts/hetzner/deployHetzner.sh
index 63dc7e07a..8498129bd 100755
--- a/scripts/hetzner/deployHetzner.sh
+++ b/scripts/hetzner/deployHetzner.sh
@@ -11,9 +11,9 @@
cp config.json config.json.bu &&
cp ./scripts/hetzner/config.json . && # Copy the config _before_ building, as the config might contain some needed URLs
-npm run reset:layeroverview
-npm run test
+# npm run reset:layeroverview
npm run prepare-deploy &&
+npm run test &&
zip dist.zip -r dist/* &&
mv config.json.bu config.json &&
scp ./scripts/hetzner/config/* hetzner:/root/ &&
diff --git a/src/Models/ThemeConfig/Conversion/Conversion.ts b/src/Models/ThemeConfig/Conversion/Conversion.ts
index 71863250c..1e23edbcc 100644
--- a/src/Models/ThemeConfig/Conversion/Conversion.ts
+++ b/src/Models/ThemeConfig/Conversion/Conversion.ts
@@ -39,6 +39,12 @@ export class ConversionContext {
}
static print(msg: ConversionMessage) {
+ const noString = msg.context.path.filter(
+ (p) => typeof p !== "string" && typeof p !== "number"
+ )
+ if (noString.length > 0) {
+ console.warn("Non-string value in path:", ...noString)
+ }
if (msg.level === "error") {
console.error(
ConversionContext.red("ERR "),
diff --git a/src/UI/Studio/EditLayer.svelte b/src/UI/Studio/EditLayer.svelte
index bcbc03ead..e6dc6fb6e 100644
--- a/src/UI/Studio/EditLayer.svelte
+++ b/src/UI/Studio/EditLayer.svelte
@@ -1,6 +1,6 @@
-
Editing layer {$title}
+
+
Editing layer {$title}
+ {#if $hasErrors > 0}
+
{$hasErrors} errors detected
+ {:else}
+
Try it out
+ {/if}
+
General properties
diff --git a/src/UI/Studio/EditLayerState.ts b/src/UI/Studio/EditLayerState.ts
index e9eaed972..dc15a1682 100644
--- a/src/UI/Studio/EditLayerState.ts
+++ b/src/UI/Studio/EditLayerState.ts
@@ -177,7 +177,12 @@ export default class EditLayerState {
}
entry = entry[breadcrumb]
}
- if (v !== undefined && v !== null && v !== "") {
+ if (
+ v !== undefined &&
+ v !== null &&
+ v !== "" &&
+ !(typeof v === "object" && Object.keys({}).length === 0)
+ ) {
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 11f972306..573e57bd5 100644
--- a/src/UI/Studio/SchemaBasedField.svelte
+++ b/src/UI/Studio/SchemaBasedField.svelte
@@ -16,7 +16,7 @@
export let state: EditLayerState
export let path: (string | number)[] = []
export let schema: ConfigMeta
- let value = new UIEventSource(undefined)
+ let value = new UIEventSource(undefined)
const isTranslation = schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema)
let type = schema.hints.typehint ?? "string"
@@ -122,7 +122,7 @@
}
return Number(v)
}
- if (isTranslation) {
+ if (isTranslation && typeof v === "string") {
if (v === "") {
return {}
}
diff --git a/src/UI/Studio/StudioServer.ts b/src/UI/Studio/StudioServer.ts
index aa1f81e23..52e737e49 100644
--- a/src/UI/Studio/StudioServer.ts
+++ b/src/UI/Studio/StudioServer.ts
@@ -22,9 +22,7 @@ export default class StudioServer {
async fetchLayer(layerId: string): Promise {
try {
- return await Utils.downloadJson(
- this.url + "/layers/" + layerId + "/" + layerId + ".json"
- )
+ return await Utils.downloadJson(this.layerUrl(layerId))
} catch (e) {
return undefined
}
@@ -35,7 +33,7 @@ export default class StudioServer {
if (id === undefined || id === "") {
return
}
- await fetch(`${this.url}/layers/${id}/${id}.json`, {
+ await fetch(this.layerUrl(id), {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
@@ -43,4 +41,8 @@ export default class StudioServer {
body: JSON.stringify(config, null, " "),
})
}
+
+ public layerUrl(id: string) {
+ return `${this.url}/layers/${id}/${id}.json`
+ }
}
diff --git a/src/UI/StudioGUI.svelte b/src/UI/StudioGUI.svelte
index be7d82f9c..ee4d3536a 100644
--- a/src/UI/StudioGUI.svelte
+++ b/src/UI/StudioGUI.svelte
@@ -15,10 +15,12 @@
import { QueryParameters } from "../Logic/Web/QueryParameters";
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 = /* "https://studio.mapcomplete.org"; /*/ "http://127.0.0.1:1235"; //*/
const studio = new StudioServer(studioUrl);
- let layers = UIEventSource.FromPromise(studio.fetchLayerOverview());
+ let layersWithErr = UIEventSource.FromPromiseWithErr(studio.fetchLayerOverview());
+ let layers = layersWithErr.mapD(l => l.success);
let state: undefined | "edit_layer" | "new_layer" | "edit_theme" | "new_theme" | "editing_layer" | "loading" = undefined;
let initialLayerConfig: { id: string };
@@ -61,8 +63,8 @@
}]
}
],
- lineRendering : [{
- width : 1,
+ lineRendering: [{
+ width: 1,
color: "blue"
}]
};
@@ -82,73 +84,99 @@
-
-
-
- Please log in to use MapComplete Studio
-
-
- {#if state === undefined}
- MapComplete Studio
-
+
d?.error !== undefined)}>
+
+
+ Something went wrong while contacting the MapComplete Studio Server: {$layersWithErr["error"]}
+
+ The server might be offline. Please:
+
- state = "edit_layer"}>
- Edit an existing layer
-
- state = "new_layer"}>
- Create a new layer
-
- state = "edit_theme"}>
- Edit a theme
-
- state = "new_theme"}>
- Create a new theme
+ -
+ Try again in a few minutes
+
+ -
+ Contact the MapComplete community via the
+ chat. Someone might be able to help you
+
+ -
+ File an issue
+
+ -
+ Contact the devs via email
+
+
+
+
+
+
+ Please log in to use MapComplete Studio
- {:else if state === "edit_layer"}
-
- {#each Array.from($layers) as layerId}
-
{
+ {#if state === undefined}
+ MapComplete Studio
+
+
+ state = "edit_layer"}>
+ Edit an existing layer
+
+ state = "new_layer"}>
+ Create a new layer
+
+
+
+ {:else if state === "edit_layer"}
+
+ {#each Array.from($layers) as layerId}
+
{
state = "loading"
initialLayerConfig = await studio.fetchLayer(layerId)
state = "editing_layer"
}}>
-
-
-
- {layerId}
-
- {/each}
-
- {:else if state === "new_layer"}
-
-
Enter the ID for the new layer
- A good ID is:
-
- - a noun
- - singular
- - describes the object
- - in English
-
-
-
-
createNewLayer()} />
+
+
+
+ {layerId}
+
+ {/each}
- {#if $layerIdFeedback !== undefined}
-
- {$layerIdFeedback}
+ {:else if state === "new_layer"}
+
+
Enter the ID for the new layer
+ A good ID is:
+
+ - a noun
+ - singular
+ - describes the object
+ - in English
+
+
+
+ createNewLayer()} />
- {:else }
-
createNewLayer()}>
- Create layer {$newLayerId}
-
- {/if}
-
- {:else if state === "loading"}
-
-
-
- {:else if state === "editing_layer"}
-
- {/if}
-
+ {#if $layerIdFeedback !== undefined}
+
+ {$layerIdFeedback}
+
+ {:else }
+
createNewLayer()}>
+ Create layer {$newLayerId}
+
+ {/if}
+
+ {:else if state === "loading"}
+
+
+
+ {:else if state === "editing_layer"}
+
+ {/if}
+
+