More fixes to studio, move error message to validation step, fix #1710

This commit is contained in:
Pieter Vander Vennet 2024-01-03 14:57:26 +01:00
parent 8b4544db04
commit 21563e4dc2
5 changed files with 49 additions and 22 deletions

View file

@ -421,6 +421,7 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
// No need to check the writable tags, as this cannot write // No need to check the writable tags, as this cannot write
return json return json
} }
function addAll(keys: { forEach: (f: (s: string) => void) => void }, addTo: Set<string>) { function addAll(keys: { forEach: (f: (s: string) => void) => void }, addTo: Set<string>) {
keys?.forEach((k) => addTo.add(k)) keys?.forEach((k) => addTo.add(k))
} }
@ -1359,6 +1360,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> { export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
private readonly validator: ValidateLayer private readonly validator: ValidateLayer
constructor( constructor(
path: string, path: string,
isBuiltin: boolean, isBuiltin: boolean,
@ -1385,6 +1387,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
return prepared?.raw return prepared?.raw
} }
} }
export class ValidateLayer extends Conversion< export class ValidateLayer extends Conversion<
LayerConfigJson, LayerConfigJson,
{ parsed: LayerConfig; raw: LayerConfigJson } { parsed: LayerConfig; raw: LayerConfigJson }
@ -1462,6 +1465,19 @@ export class ValidateLayer extends Conversion<
} }
} }
for (let i = 0; i < json.presets.length; i++) {
const preset = json.presets[i]
if (
preset.snapToLayer === undefined &&
preset.maxSnapDistance !== undefined &&
preset.maxSnapDistance !== null
) {
context
.enters("presets", i, "maxSnapDistance")
.err("A maxSnapDistance is given, but there is no layer given to snap to")
}
}
return { raw: json, parsed: layerConfig } return { raw: json, parsed: layerConfig }
} }
} }

View file

@ -184,14 +184,6 @@ export default class LayerConfig extends WithContextLoader {
snapToLayers, snapToLayers,
maxSnapDistance: pr.maxSnapDistance ?? 10, maxSnapDistance: pr.maxSnapDistance ?? 10,
} }
} else if (pr.maxSnapDistance !== undefined) {
throw (
"Layer " +
this.id +
" defines a maxSnapDistance, but does not include a `snapToLayer` (at " +
context +
")"
)
} }
const config: PresetConfig = { const config: PresetConfig = {

View file

@ -24,7 +24,7 @@
export let backToStudio: () => void export let backToStudio: () => void
let messages = state.messages let messages = state.messages
let hasErrors = messages.mapD( let hasErrors = messages.mapD(
(m: ConversionMessage[]) => m.filter((m) => m.level === "error").length (m: ConversionMessage[]) => m.filter((m) => m.level === "error").length,
) )
const configuration = state.configuration const configuration = state.configuration
@ -73,6 +73,7 @@
}) })
let highlightedItem: UIEventSource<HighlightedTagRendering> = state.highlightedItem let highlightedItem: UIEventSource<HighlightedTagRendering> = state.highlightedItem
function deleteLayer() { function deleteLayer() {
state.delete() state.delete()
backToStudio() backToStudio()
@ -93,15 +94,32 @@
{:else if $hasErrors > 0} {:else if $hasErrors > 0}
<div class="alert">{$hasErrors} errors detected</div> <div class="alert">{$hasErrors} errors detected</div>
{:else} {:else}
<a <div class="flex">
class="primary button" <a
href={baseUrl + state.server.layerUrl(title.data)} class="button small"
target="_blank" href={baseUrl + state.server.layerUrl(title.data) + "&test=true"}
rel="noopener" target="_blank"
> rel="noopener"
Try it out >
<ChevronRightIcon class="h-6 w-6 shrink-0" /> <div class="flex flex-col">
</a>
<b>
Test in safe mode
</b>
<div>No changes are recoded to OSM</div>
</div>
<ChevronRightIcon class="h-6 w-6 shrink-0" />
</a>
<a
class="primary button"
href={baseUrl + state.server.layerUrl(title.data)}
target="_blank"
rel="noopener"
>
Try it out
<ChevronRightIcon class="h-6 w-6 shrink-0" />
</a>
</div>
{/if} {/if}
</div> </div>
@ -120,7 +138,8 @@
<Region {state} configs={perRegion["Basic"]} /> <Region {state} configs={perRegion["Basic"]} />
<div class="mt-12"> <div class="mt-12">
<button on:click={() => deleteLayer()} class="small"> <button on:click={() => deleteLayer()} class="small">
<TrashIcon class="h-6 w-6" /> Delete this layer <TrashIcon class="h-6 w-6" />
Delete this layer
</button> </button>
</div> </div>
</div> </div>

View file

@ -158,7 +158,7 @@
} }
} }
if (schema.type === "number") { if (schema.type === "number") {
if (v === "") { if (v === "" || v === null || isNaN(Number(v))) {
return undefined return undefined
} }
return Number(v) return Number(v)

View file

@ -95,7 +95,7 @@
const version = meta.version const version = meta.version
async function editLayer(event: Event) { async function editLayer(event: Event) {
const layerId: { owner: number; id: string } = event.detail const layerId: { owner: number; id: string } = event["detail"]
state = "loading" state = "loading"
editLayerState.startSavingUpdates(false) editLayerState.startSavingUpdates(false)
editLayerState.configuration.setData(await studio.fetch(layerId.id, "layers", layerId.owner)) editLayerState.configuration.setData(await studio.fetch(layerId.id, "layers", layerId.owner))
@ -104,7 +104,7 @@
} }
async function editTheme(event: Event) { async function editTheme(event: Event) {
const id: { id: string; owner: number } = event.detail const id: { id: string; owner: number } = event["detail"]
state = "loading" state = "loading"
editThemeState.startSavingUpdates(false) editThemeState.startSavingUpdates(false)
editThemeState.configuration.setData(await studio.fetch(id.id, "themes", id.owner)) editThemeState.configuration.setData(await studio.fetch(id.id, "themes", id.owner))