forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
59356545ed
68 changed files with 1670 additions and 67 deletions
|
|
@ -8,6 +8,9 @@
|
|||
let _c: boolean = selected.data ?? true
|
||||
let id = `checkbox-input-${Math.round(Math.random()*100000000)}`
|
||||
$: selected.set(_c)
|
||||
selected.addCallbackD(s => {
|
||||
_c = s
|
||||
})
|
||||
</script>
|
||||
|
||||
<label class="no-image-background flex items-center gap-1">
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -1,17 +1,49 @@
|
|||
<script lang="ts">
|
||||
/**
|
||||
* THe panel containing all filter- and layerselection options
|
||||
*/
|
||||
/**
|
||||
* THe panel containing all filter- and layerselection options
|
||||
*/
|
||||
|
||||
import OverlayToggle from "./OverlayToggle.svelte"
|
||||
import Filterview from "./Filterview.svelte"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import Filter from "../../assets/svg/Filter.svelte"
|
||||
import OverlayToggle from "./OverlayToggle.svelte"
|
||||
import Filterview from "./Filterview.svelte"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import Filter from "../../assets/svg/Filter.svelte"
|
||||
|
||||
export let state: ThemeViewState
|
||||
let layout = state.layout
|
||||
export let state: ThemeViewState
|
||||
let layout = state.layout
|
||||
|
||||
let allEnabled : boolean
|
||||
let allDisabled: boolean
|
||||
|
||||
function updateEnableState(){
|
||||
allEnabled = true
|
||||
allDisabled = true
|
||||
state.layerState.filteredLayers.forEach((v) => {
|
||||
if(!v.layerDef.name){
|
||||
return
|
||||
}
|
||||
allEnabled &&= v.isDisplayed.data
|
||||
allDisabled &&= !v.isDisplayed.data
|
||||
})
|
||||
}
|
||||
|
||||
updateEnableState()
|
||||
state.layerState.filteredLayers.forEach((v) => {
|
||||
if(!v.layerDef.name){
|
||||
return
|
||||
}
|
||||
v.isDisplayed.addCallbackD(_ => updateEnableState())
|
||||
})
|
||||
function enableAll(doEnable: boolean){
|
||||
state.layerState.filteredLayers.forEach((v) => {
|
||||
if(!v.layerDef.name){
|
||||
return
|
||||
}
|
||||
v.isDisplayed.setData(doEnable)
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="m-2 flex flex-col">
|
||||
|
|
@ -27,6 +59,15 @@
|
|||
highlightedLayer={state.guistate.highlightedLayerInFilters}
|
||||
/>
|
||||
{/each}
|
||||
<div class="flex self-end mt-1">
|
||||
<button class="small" class:disabled={allEnabled} on:click={() => enableAll(true)}>
|
||||
<Tr t={Translations.t.general.filterPanel.enableAll}/>
|
||||
</button>
|
||||
<button class="small" class:disabled={allDisabled} on:click={() => enableAll(false)}>
|
||||
<Tr t={Translations.t.general.filterPanel.disableAll}/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#each layout.tileLayerSources as tilesource}
|
||||
<OverlayToggle
|
||||
layerproperties={tilesource}
|
||||
|
|
|
|||
|
|
@ -13,14 +13,15 @@
|
|||
import SchemaBasedInput from "./SchemaBasedInput.svelte"
|
||||
import FloatOver from "../Base/FloatOver.svelte"
|
||||
import TagRenderingInput from "./TagRenderingInput.svelte"
|
||||
import FromHtml from "../Base/FromHtml.svelte"
|
||||
import AllTagsPanel from "../Popup/AllTagsPanel.svelte"
|
||||
import QuestionPreview from "./QuestionPreview.svelte"
|
||||
import ShowConversionMessages from "./ShowConversionMessages.svelte"
|
||||
import RawEditor from "./RawEditor.svelte"
|
||||
|
||||
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw
|
||||
|
||||
export let state: EditLayerState
|
||||
|
||||
export let backToStudio: () => void
|
||||
let messages = state.messages
|
||||
let hasErrors = messages.mapD(
|
||||
|
|
@ -59,7 +60,7 @@
|
|||
}
|
||||
|
||||
let requiredFields = ["id", "name", "description", "source"]
|
||||
let currentlyMissing = state.configuration.map((config) => {
|
||||
let currentlyMissing = configuration.map((config) => {
|
||||
if (!config) {
|
||||
return []
|
||||
}
|
||||
|
|
@ -184,33 +185,34 @@
|
|||
<Region configs={perRegion["expert"]} {state} />
|
||||
</div>
|
||||
<div slot="title5">Configuration file</div>
|
||||
<div slot="content5">
|
||||
<div slot="content5" class="flex h-full flex-col">
|
||||
<div>
|
||||
Below, you'll find the raw configuration file in `.json`-format. This is mostly for
|
||||
debugging purposes
|
||||
debugging purposes, but you can also edit the file directly if you want.
|
||||
</div>
|
||||
<div class="literal-code">
|
||||
<FromHtml src={JSON.stringify($configuration, null, " ").replaceAll("\n", "</br>")} />
|
||||
</div>
|
||||
|
||||
<ShowConversionMessages messages={$messages} />
|
||||
<div>
|
||||
The testobject (which is used to render the questions in the 'information panel' item
|
||||
has the following tags:
|
||||
</div>
|
||||
<div class="flex h-full w-full flex-row justify-between overflow-y-auto">
|
||||
<div class="literal-code h-full w-5/6 overflow-y-auto">
|
||||
<RawEditor {state} />
|
||||
</div>
|
||||
<div class="h-full w-1/6">
|
||||
<div>
|
||||
The testobject (which is used to render the questions in the 'information panel'
|
||||
item has the following tags:
|
||||
</div>
|
||||
|
||||
<AllTagsPanel tags={state.testTags} />
|
||||
<AllTagsPanel tags={state.testTags} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabbedGroup>
|
||||
</div>
|
||||
{#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}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import TabbedGroup from "../Base/TabbedGroup.svelte"
|
||||
import ShowConversionMessages from "./ShowConversionMessages.svelte"
|
||||
import Region from "./Region.svelte"
|
||||
import RawEditor from "./RawEditor.svelte"
|
||||
|
||||
export let state: EditThemeState
|
||||
let schema: ConfigMeta[] = state.schema.filter((schema) => schema.path.length > 0)
|
||||
|
|
@ -50,7 +51,7 @@
|
|||
</div>
|
||||
|
||||
<div class="m4 h-full overflow-y-auto">
|
||||
{Object.keys(perRegion).join(";")}
|
||||
<!-- {Object.keys(perRegion).join(";")} -->
|
||||
<TabbedGroup>
|
||||
<div slot="title0">Basic properties</div>
|
||||
<div slot="content0">
|
||||
|
|
@ -73,12 +74,15 @@
|
|||
</div>
|
||||
|
||||
<div slot="title4">Configuration file</div>
|
||||
<div slot="content4">
|
||||
<div class="literal-code">
|
||||
{JSON.stringify($config)}
|
||||
<div slot="content4" class="flex h-full flex-col">
|
||||
<div>
|
||||
Below, you'll find the raw configuration file in `.json`-format. This is mostly for
|
||||
debugging purposes, but you can also edit the file directly if you want.
|
||||
</div>
|
||||
|
||||
<ShowConversionMessages messages={$messages} />
|
||||
<div class="literal-code h-full w-full">
|
||||
<RawEditor {state} />
|
||||
</div>
|
||||
</div>
|
||||
</TabbedGroup>
|
||||
</div>
|
||||
|
|
|
|||
101
src/UI/Studio/RawEditor.svelte
Normal file
101
src/UI/Studio/RawEditor.svelte
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<script lang="ts">
|
||||
import { onDestroy, onMount } from "svelte"
|
||||
import EditLayerState, { EditThemeState } from "./EditLayerState"
|
||||
import loader from "@monaco-editor/loader"
|
||||
import type * as Monaco from "monaco-editor/esm/vs/editor/editor.api"
|
||||
import layerSchemaJSON from "../../../Docs/Schemas/LayerConfigJson.schema.json"
|
||||
import layoutSchemaJSON from "../../../Docs/Schemas/LayoutConfigJson.schema.json"
|
||||
|
||||
export let state: EditLayerState | EditThemeState
|
||||
|
||||
let container: HTMLDivElement
|
||||
let monaco: typeof Monaco
|
||||
let editor: Monaco.editor.IStandaloneCodeEditor
|
||||
let model: Monaco.editor.ITextModel
|
||||
|
||||
function save() {
|
||||
try {
|
||||
const newConfig = JSON.parse(editor.getValue())
|
||||
state.configuration.setData(newConfig)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Catch keyboard shortcuts
|
||||
onMount(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if (e.key === "s" && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault()
|
||||
save()
|
||||
}
|
||||
}
|
||||
window.addEventListener("keydown", handler)
|
||||
return () => window.removeEventListener("keydown", handler)
|
||||
})
|
||||
|
||||
onMount(async () => {
|
||||
const monacoEditor = await import("monaco-editor")
|
||||
loader.config({
|
||||
monaco: monacoEditor.default,
|
||||
})
|
||||
|
||||
monaco = await loader.init()
|
||||
|
||||
// Determine schema based on the state
|
||||
let schemaUri: string
|
||||
if (state instanceof EditLayerState) {
|
||||
schemaUri = "https://mapcomplete.org/schemas/layerconfig.json"
|
||||
} else {
|
||||
schemaUri = "https://mapcomplete.org/schemas/layoutconfig.json"
|
||||
}
|
||||
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
validate: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: schemaUri,
|
||||
fileMatch: ["file.json"],
|
||||
schema:
|
||||
schemaUri === "https://mapcomplete.org/schemas/layerconfig.json"
|
||||
? layerSchemaJSON
|
||||
: layoutSchemaJSON,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
let modelUri = monaco.Uri.parse("inmemory://inmemory/file.json")
|
||||
|
||||
// Create a new model
|
||||
model = monaco.editor.createModel(
|
||||
JSON.stringify(state.configuration.data, null, " "),
|
||||
"json",
|
||||
modelUri
|
||||
)
|
||||
|
||||
editor = monaco.editor.create(container, {
|
||||
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
|
||||
editor.onDidChangeModelContent(() => {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
save()
|
||||
}, 500)
|
||||
})
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
if (editor) {
|
||||
editor.dispose()
|
||||
}
|
||||
if (model) {
|
||||
model.dispose()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div bind:this={container} class="h-full w-full" />
|
||||
Loading…
Add table
Add a link
Reference in a new issue