forked from MapComplete/MapComplete
🚧 Allow editing of layer file in Studio
This commit is contained in:
parent
2b12715f5c
commit
a093d52647
4 changed files with 125 additions and 17 deletions
49
package-lock.json
generated
49
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "mapcomplete",
|
||||
"version": "0.37.0",
|
||||
"version": "0.37.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mapcomplete",
|
||||
"version": "0.37.0",
|
||||
"version": "0.37.2",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@rgossiaux/svelte-headlessui": "^1.0.2",
|
||||
|
@ -44,6 +44,7 @@
|
|||
"lz-string": "^1.4.4",
|
||||
"mangrove-reviews-typescript": "^1.1.0",
|
||||
"maplibre-gl": "^3.5.0",
|
||||
"monaco-editor": "^0.46.0",
|
||||
"nano-markdown": "^1.2.2",
|
||||
"opening_hours": "^3.6.0",
|
||||
"osm-auth": "^2.2.0",
|
||||
|
@ -68,6 +69,7 @@
|
|||
"@babeard/svelte-heroicons": "^2.0.0-rc.0",
|
||||
"@babel/polyfill": "^7.10.4",
|
||||
"@babel/preset-env": "7.13.8",
|
||||
"@monaco-editor/loader": "^1.4.0",
|
||||
"@parcel/service-worker": "^2.6.0",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^2.0.2",
|
||||
|
@ -2355,6 +2357,18 @@
|
|||
"gl-style-validate": "dist/gl-style-validate.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@monaco-editor/loader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz",
|
||||
"integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"state-local": "^1.0.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"monaco-editor": ">= 0.21.0 < 1"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
@ -9377,6 +9391,11 @@
|
|||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/monaco-editor": {
|
||||
"version": "0.46.0",
|
||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.46.0.tgz",
|
||||
"integrity": "sha512-ADwtLIIww+9FKybWscd7OCfm9odsFYHImBRI1v9AviGce55QY8raT+9ihH8jX/E/e6QVSGM+pKj4jSUSRmALNQ=="
|
||||
},
|
||||
"node_modules/monotone-convex-hull-2d": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/monotone-convex-hull-2d/-/monotone-convex-hull-2d-1.0.1.tgz",
|
||||
|
@ -11499,6 +11518,12 @@
|
|||
"node": ">=0.1.14"
|
||||
}
|
||||
},
|
||||
"node_modules/state-local": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
|
||||
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/std-env": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.2.tgz",
|
||||
|
@ -15357,6 +15382,15 @@
|
|||
"sort-object": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"@monaco-editor/loader": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz",
|
||||
"integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"state-local": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
@ -20688,6 +20722,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"monaco-editor": {
|
||||
"version": "0.46.0",
|
||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.46.0.tgz",
|
||||
"integrity": "sha512-ADwtLIIww+9FKybWscd7OCfm9odsFYHImBRI1v9AviGce55QY8raT+9ihH8jX/E/e6QVSGM+pKj4jSUSRmALNQ=="
|
||||
},
|
||||
"monotone-convex-hull-2d": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/monotone-convex-hull-2d/-/monotone-convex-hull-2d-1.0.1.tgz",
|
||||
|
@ -22222,6 +22261,12 @@
|
|||
"integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==",
|
||||
"optional": true
|
||||
},
|
||||
"state-local": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
|
||||
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
|
||||
"dev": true
|
||||
},
|
||||
"std-env": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.2.tgz",
|
||||
|
|
|
@ -142,6 +142,7 @@
|
|||
"lz-string": "^1.4.4",
|
||||
"mangrove-reviews-typescript": "^1.1.0",
|
||||
"maplibre-gl": "^3.5.0",
|
||||
"monaco-editor": "^0.46.0",
|
||||
"nano-markdown": "^1.2.2",
|
||||
"opening_hours": "^3.6.0",
|
||||
"osm-auth": "^2.2.0",
|
||||
|
@ -166,6 +167,7 @@
|
|||
"@babeard/svelte-heroicons": "^2.0.0-rc.0",
|
||||
"@babel/polyfill": "^7.10.4",
|
||||
"@babel/preset-env": "7.13.8",
|
||||
"@monaco-editor/loader": "^1.4.0",
|
||||
"@parcel/service-worker": "^2.6.0",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^2.0.2",
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
window.setTimeout(() => tabElements[tab.data].click(), 50)
|
||||
}
|
||||
}
|
||||
export function getTab() {
|
||||
return tab
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="tabbedgroup flex h-full w-full">
|
||||
|
|
|
@ -17,14 +17,24 @@
|
|||
import AllTagsPanel from "../Popup/AllTagsPanel.svelte"
|
||||
import QuestionPreview from "./QuestionPreview.svelte"
|
||||
import ShowConversionMessages from "./ShowConversionMessages.svelte"
|
||||
import loader from "@monaco-editor/loader"
|
||||
import type * as Monaco from "monaco-editor/esm/vs/editor/editor.api"
|
||||
import { onMount } from "svelte"
|
||||
import layerSchemaJSON from "../../../Docs/Schemas/LayerConfigJson.schema.json"
|
||||
|
||||
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw
|
||||
|
||||
export let state: EditLayerState
|
||||
|
||||
// Throw error if we don't have a state
|
||||
if (!state) {
|
||||
throw new Error("No state provided")
|
||||
}
|
||||
|
||||
export let backToStudio: () => void
|
||||
let messages = state.messages
|
||||
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
|
||||
|
||||
|
@ -78,6 +88,61 @@
|
|||
state.delete()
|
||||
backToStudio()
|
||||
}
|
||||
|
||||
let tabbedGroup: TabbedGroup
|
||||
let openTab: UIEventSource<number> = new UIEventSource<number>(0)
|
||||
|
||||
let monaco: typeof Monaco
|
||||
let editorContainer: HTMLDivElement
|
||||
let layerEditor: Monaco.editor.IStandaloneCodeEditor
|
||||
let model: Monaco.editor.ITextModel
|
||||
|
||||
onMount(async () => {
|
||||
openTab = tabbedGroup.getTab()
|
||||
|
||||
const monacoEditor = await import("monaco-editor")
|
||||
loader.config({ monaco: monacoEditor.default })
|
||||
|
||||
monaco = await loader.init()
|
||||
|
||||
// Prepare the Monaco editor (language settings)
|
||||
// A.K.A. The schemas for the Monaco editor
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
validate: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: "https://mapcomplete.org/schemas/layerconfig.json",
|
||||
fileMatch: ["layer.json"],
|
||||
schema: layerSchemaJSON,
|
||||
},
|
||||
],
|
||||
})
|
||||
let modelUri = monaco.Uri.parse("inmemory://inmemory/layer.json")
|
||||
model = monaco.editor.createModel(
|
||||
JSON.stringify(state.configuration.data, null, " "),
|
||||
"json",
|
||||
modelUri
|
||||
)
|
||||
|
||||
layerEditor = monaco.editor.create(editorContainer, {
|
||||
model: model,
|
||||
automaticLayout: true,
|
||||
})
|
||||
|
||||
// When the editor is changed, update the configuration, but only if the user hasn't typed for 500ms and the JSON is valid
|
||||
let timeout: number
|
||||
layerEditor.onDidChangeModelContent(() => {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
try {
|
||||
const newConfig = JSON.parse(layerEditor.getValue())
|
||||
state.configuration.setData(newConfig)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}, 500)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="flex h-screen flex-col">
|
||||
|
@ -102,10 +167,7 @@
|
|||
rel="noopener"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
|
||||
<b>
|
||||
Test in safe mode
|
||||
</b>
|
||||
<b>Test in safe mode</b>
|
||||
<div>No changes are recoded to OSM</div>
|
||||
</div>
|
||||
<ChevronRightIcon class="h-6 w-6 shrink-0" />
|
||||
|
@ -129,7 +191,7 @@
|
|||
{/each}
|
||||
{:else}
|
||||
<div class="m4 h-full overflow-y-auto">
|
||||
<TabbedGroup>
|
||||
<TabbedGroup bind:this={tabbedGroup}>
|
||||
<div slot="title0" class="flex">
|
||||
General properties
|
||||
<ErrorIndicatorForRegion firstPaths={firstPathsFor("Basic")} {state} />
|
||||
|
@ -190,11 +252,9 @@
|
|||
<div slot="content5">
|
||||
<div>
|
||||
Below, you'll find the raw configuration file in `.json`-format. This is mostly for
|
||||
debugging purposes
|
||||
</div>
|
||||
<div class="literal-code">
|
||||
<FromHtml src={JSON.stringify($configuration, null, " ").replaceAll("\n", "</br>")} />
|
||||
debugging purposes, but you can also edit the file directly if you want.
|
||||
</div>
|
||||
<div class="literal-code h-64 w-full" bind:this={editorContainer} />
|
||||
|
||||
<ShowConversionMessages messages={$messages} />
|
||||
<div>
|
||||
|
@ -209,11 +269,9 @@
|
|||
{#if $highlightedItem !== undefined}
|
||||
<FloatOver on:close={() => highlightedItem.setData(undefined)}>
|
||||
<div>
|
||||
<TagRenderingInput
|
||||
path={$highlightedItem.path}
|
||||
{state}
|
||||
schema={$highlightedItem.schema}
|
||||
/>
|
||||
<TagRenderingInput path={$highlightedItem.path} {state} />
|
||||
<!--
|
||||
schema={$highlightedItem.schema} -->
|
||||
</div>
|
||||
</FloatOver>
|
||||
{/if}
|
||||
|
|
Loading…
Reference in a new issue