forked from MapComplete/MapComplete
Studo: WIP
This commit is contained in:
parent
7ebb3d721c
commit
338599454c
30 changed files with 42794 additions and 749 deletions
|
@ -149,7 +149,7 @@ class ExpandTagRendering extends Conversion<
|
|||
this._options = options
|
||||
this._tagRenderingsByLabel = new Map<string, TagRenderingConfigJson[]>()
|
||||
for (const trconfig of state.tagRenderings?.values() ?? []) {
|
||||
for (const label of trconfig.labels ?? []) {
|
||||
for (const label of trconfig["labels"] ?? []) {
|
||||
let withLabel = this._tagRenderingsByLabel.get(label)
|
||||
if (withLabel === undefined) {
|
||||
withLabel = []
|
||||
|
@ -193,7 +193,7 @@ class ExpandTagRendering extends Conversion<
|
|||
for (let foundTr of indirect) {
|
||||
foundTr = Utils.Clone<any>(foundTr)
|
||||
Utils.Merge(tagRenderingConfigJson["override"] ?? {}, foundTr)
|
||||
foundTr.id = tagRenderingConfigJson.id ?? foundTr.id
|
||||
foundTr["id"] = tagRenderingConfigJson["id"] ?? foundTr["id"]
|
||||
result.push(foundTr)
|
||||
}
|
||||
} else {
|
||||
|
@ -239,9 +239,9 @@ class ExpandTagRendering extends Conversion<
|
|||
matchingTrs = layerTrs
|
||||
} else if (id.startsWith("*")) {
|
||||
const id_ = id.substring(1)
|
||||
matchingTrs = layerTrs.filter((tr) => tr.labels?.indexOf(id_) >= 0)
|
||||
matchingTrs = layerTrs.filter((tr) => tr["labels"]?.indexOf(id_) >= 0)
|
||||
} else {
|
||||
matchingTrs = layerTrs.filter((tr) => tr.id === id || tr.labels?.indexOf(id) >= 0)
|
||||
matchingTrs = layerTrs.filter((tr) => tr["id"] === id || tr["labels"]?.indexOf(id) >= 0)
|
||||
}
|
||||
|
||||
const contextWriter = new AddContextToTranslations<TagRenderingConfigJson>("layers:")
|
||||
|
@ -489,7 +489,15 @@ class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
|
|||
}
|
||||
}
|
||||
json = JSON.parse(JSON.stringify(json))
|
||||
json.freeform.inline ??= true
|
||||
if (typeof json.freeform === "string") {
|
||||
errors.push("At " + context + ": 'freeform' is a string, but should be an object")
|
||||
return { result: json, errors }
|
||||
}
|
||||
try {
|
||||
json.freeform.inline ??= true
|
||||
} catch (e) {
|
||||
errors.push("At " + context + ": " + e.message)
|
||||
}
|
||||
return { result: json, errors }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,8 +64,7 @@ export interface LayerConfigJson {
|
|||
| {
|
||||
/**
|
||||
* question: Which tags must be present on the feature to show it in this layer?
|
||||
*
|
||||
* Every source must set which tags have to be present in order to load the given layer.
|
||||
* Every source must set which tags have to be present in order to load the given layer.
|
||||
*/
|
||||
osmTags: TagConfigJson
|
||||
/**
|
||||
|
@ -238,21 +237,19 @@ export interface LayerConfigJson {
|
|||
|
||||
/**
|
||||
* Visualisation of the items on the map
|
||||
*
|
||||
* Set 'null' explicitly if you do not want a maprendering
|
||||
* group: maprendering
|
||||
*/
|
||||
mapRendering:
|
||||
| null
|
||||
| (
|
||||
| PointRenderingConfigJson
|
||||
mapRendering?: (
|
||||
| PointRenderingConfigJson
|
||||
| LineRenderingConfigJson
|
||||
| RewritableConfigJson<
|
||||
| LineRenderingConfigJson
|
||||
| RewritableConfigJson<
|
||||
| LineRenderingConfigJson
|
||||
| PointRenderingConfigJson
|
||||
| LineRenderingConfigJson[]
|
||||
| PointRenderingConfigJson[]
|
||||
>
|
||||
)[]
|
||||
| PointRenderingConfigJson
|
||||
| LineRenderingConfigJson[]
|
||||
| PointRenderingConfigJson[]
|
||||
>
|
||||
)[]
|
||||
|
||||
/**
|
||||
* If set, this layer will pass all the features it receives onto the next layer.
|
||||
|
@ -467,7 +464,7 @@ export interface LayerConfigJson {
|
|||
* A no-delete option is offered as 'reason to delete it', but secretly retags.
|
||||
*
|
||||
* group: editing
|
||||
* types: use an advanced delete configuration ; boolean
|
||||
* types: Use an advanced delete configuration ; boolean
|
||||
* iftrue: Allow deletion
|
||||
* iffalse: Do not allow deletion
|
||||
*
|
||||
|
|
|
@ -260,7 +260,7 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
|
|||
questionHint?: string | Translatable
|
||||
|
||||
/**
|
||||
* A list of labels. These are strings that are used for various purposes, e.g. to filter them away
|
||||
* A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer
|
||||
*/
|
||||
labels?: string[]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import LanguageUtils from "../../../Utils/LanguageUtils";
|
||||
import { onDestroy } from "svelte";
|
||||
import { createEventDispatcher, onDestroy } from "svelte";
|
||||
import ValidatedInput from "../ValidatedInput.svelte";
|
||||
|
||||
export let value: UIEventSource<string> = new UIEventSource<string>("");
|
||||
|
@ -18,6 +18,7 @@
|
|||
const allLanguages: string[] = LanguageUtils.usedLanguagesSorted;
|
||||
let currentLang = new UIEventSource("en");
|
||||
const currentVal = new UIEventSource<string>("");
|
||||
let dispatch = createEventDispatcher<{ submit }>()
|
||||
|
||||
function update() {
|
||||
const v = currentVal.data;
|
||||
|
@ -49,5 +50,5 @@
|
|||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
<ValidatedInput type="string" value={currentVal} />
|
||||
<ValidatedInput type="string" value={currentVal} on:submit={() => dispatch("submit")} />
|
||||
</div>
|
||||
|
|
|
@ -4,30 +4,59 @@
|
|||
* Note that all values are stringified
|
||||
*/
|
||||
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import type { ValidatorType } from "./Validators"
|
||||
import InputHelpers from "./InputHelpers"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import type { Feature } from "geojson"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import { VariableUiElement } from "../Base/VariableUIElement"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import type { ValidatorType } from "./Validators";
|
||||
import InputHelpers from "./InputHelpers";
|
||||
import ToSvelte from "../Base/ToSvelte.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import { VariableUiElement } from "../Base/VariableUIElement";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import ImageHelper from "./Helpers/ImageHelper.svelte";
|
||||
import TranslationInput from "./Helpers/TranslationInput.svelte";
|
||||
import TagInput from "./Helpers/TagInput.svelte";
|
||||
import SimpleTagInput from "./Helpers/SimpleTagInput.svelte";
|
||||
import DirectionInput from "./Helpers/DirectionInput.svelte";
|
||||
import DateInput from "./Helpers/DateInput.svelte";
|
||||
import ColorInput from "./Helpers/ColorInput.svelte";
|
||||
|
||||
export let type: ValidatorType
|
||||
export let value: UIEventSource<string>
|
||||
export let type: ValidatorType;
|
||||
export let value: UIEventSource<string>;
|
||||
|
||||
export let feature: Feature
|
||||
export let args: (string | number | boolean)[] = undefined
|
||||
export let feature: Feature;
|
||||
export let args: (string | number | boolean)[] = undefined;
|
||||
|
||||
let properties = { feature, args: args ?? [] }
|
||||
let construct = new UIEventSource<(value, extraProperties) => BaseUIElement>(undefined)
|
||||
let properties = { feature, args: args ?? [] };
|
||||
let construct = new UIEventSource<(value, extraProperties) => BaseUIElement>(undefined);
|
||||
$: {
|
||||
construct.setData(InputHelpers.AvailableInputHelpers[type])
|
||||
const helper = InputHelpers.AvailableInputHelpers[type];
|
||||
construct.setData(helper);
|
||||
}
|
||||
let dispatch = createEventDispatcher<{ selected, submit }>();
|
||||
|
||||
</script>
|
||||
|
||||
{#if construct !== undefined}
|
||||
<ToSvelte
|
||||
construct={() =>
|
||||
{#if type === "translation" }
|
||||
<TranslationInput {value} on:submit={() => dispatch("submit")} />
|
||||
{:else if type === "direction"}
|
||||
<DirectionInput {value} mapProperties={InputHelpers.constructMapProperties(properties)} />
|
||||
{:else if type === "date"}
|
||||
<DateInput { value } />
|
||||
{:else if type === "color"}
|
||||
<ColorInput { value } />
|
||||
{:else if type === "image"}
|
||||
<ImageHelper { value } />
|
||||
{:else if type === "tag"}
|
||||
<TagInput { value } />
|
||||
{:else if type === "simple_tag"}
|
||||
<SimpleTagInput { value } />
|
||||
|
||||
{:else if $construct !== undefined}
|
||||
{#if isBaseUIElement}
|
||||
<ToSvelte
|
||||
construct={() =>
|
||||
new VariableUiElement(construct.mapD((construct) => construct(value, properties)))}
|
||||
/>
|
||||
/>
|
||||
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { ValidatorType } from "./Validators"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||
import DirectionInput from "./Helpers/DirectionInput.svelte"
|
||||
|
||||
import { MapProperties } from "../../Models/MapProperties"
|
||||
import DateInput from "./Helpers/DateInput.svelte"
|
||||
import ColorInput from "./Helpers/ColorInput.svelte"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import OpeningHoursInput from "../OpeningHours/OpeningHoursInput"
|
||||
import WikidataSearchBox from "../Wikipedia/WikidataSearchBox"
|
||||
|
@ -13,10 +10,6 @@ import { Utils } from "../../Utils"
|
|||
import Locale from "../i18n/Locale"
|
||||
import { Feature } from "geojson"
|
||||
import { GeoOperations } from "../../Logic/GeoOperations"
|
||||
import ImageHelper from "./Helpers/ImageHelper.svelte"
|
||||
import TranslationInput from "./Helpers/TranslationInput.svelte"
|
||||
import TagInput from "./Helpers/TagInput.svelte"
|
||||
import SimpleTagInput from "./Helpers/SimpleTagInput.svelte"
|
||||
|
||||
export interface InputHelperProperties {
|
||||
/**
|
||||
|
@ -39,6 +32,9 @@ export interface InputHelperProperties {
|
|||
}
|
||||
|
||||
export default class InputHelpers {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
public static readonly AvailableInputHelpers: Readonly<
|
||||
Partial<
|
||||
Record<
|
||||
|
@ -50,30 +46,21 @@ export default class InputHelpers {
|
|||
>
|
||||
>
|
||||
> = {
|
||||
direction: (value, properties) =>
|
||||
new SvelteUIElement(DirectionInput, {
|
||||
value,
|
||||
mapProperties: InputHelpers.constructMapProperties(properties),
|
||||
}),
|
||||
date: (value) => new SvelteUIElement(DateInput, { value }),
|
||||
color: (value) => new SvelteUIElement(ColorInput, { value }),
|
||||
// TODO: remake in svelte,move selection logic to 'inputHelper.svelte'
|
||||
opening_hours: (value) => new OpeningHoursInput(value),
|
||||
wikidata: InputHelpers.constructWikidataHelper,
|
||||
image: (value) => new SvelteUIElement(ImageHelper, { value }),
|
||||
translation: (value) => new SvelteUIElement(TranslationInput, { value }),
|
||||
tag: (value) => new SvelteUIElement(TagInput, { value }),
|
||||
simple_tag: (value) => new SvelteUIElement(SimpleTagInput, { value }),
|
||||
} as const
|
||||
|
||||
public static hideInputField: string[] = ["translation", "simple_tag", "tag"]
|
||||
|
||||
// noinspection JSUnusedLocalSymbols
|
||||
/**
|
||||
* Constructs a mapProperties-object for the given properties.
|
||||
* Assumes that the first helper-args contains the desired zoom-level
|
||||
* @param properties
|
||||
* @private
|
||||
*/
|
||||
private static constructMapProperties(
|
||||
public static constructMapProperties(
|
||||
properties: InputHelperProperties
|
||||
): Partial<MapProperties> {
|
||||
let location = properties?.mapProperties?.location
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
placeholder={_placeholder}></textarea>
|
||||
</form>
|
||||
{:else}
|
||||
<form class="inline-flex" on:submit={() => dispatch("submit")}>
|
||||
<form class="inline-flex" on:submit|preventDefault={() => dispatch("submit")}>
|
||||
<input
|
||||
bind:this={htmlElem}
|
||||
bind:value={$_value}
|
||||
|
|
|
@ -66,5 +66,5 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
<InputHelper args={config.freeform.helperArgs} {feature} type={config.freeform.type} {value} />
|
||||
<InputHelper args={config.freeform.helperArgs} {feature} type={config.freeform.type} {value} on:submit={() => dispatch("submit")} />
|
||||
</div>
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
<script lang="ts">
|
||||
import {ImmutableStore, Store, UIEventSource} from "../../../Logic/UIEventSource"
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||
import Tr from "../../Base/Tr.svelte"
|
||||
import type { Feature } from "geojson"
|
||||
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig"
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
|
||||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
|
||||
import FreeformInput from "./FreeformInput.svelte"
|
||||
import Translations from "../../i18n/Translations.js"
|
||||
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction"
|
||||
import { createEventDispatcher, onDestroy } from "svelte"
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||
import SpecialTranslation from "./SpecialTranslation.svelte"
|
||||
import TagHint from "../TagHint.svelte"
|
||||
import LoginToggle from "../../Base/LoginToggle.svelte"
|
||||
import SubtleButton from "../../Base/SubtleButton.svelte"
|
||||
import Loading from "../../Base/Loading.svelte"
|
||||
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte"
|
||||
import { Translation } from "../../i18n/Translation"
|
||||
import Constants from "../../../Models/Constants"
|
||||
import { Unit } from "../../../Models/Unit"
|
||||
import UserRelatedState from "../../../Logic/State/UserRelatedState"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import { ImmutableStore, UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import type { Feature } from "geojson";
|
||||
import type { Mapping } from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
|
||||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter";
|
||||
import FreeformInput from "./FreeformInput.svelte";
|
||||
import Translations from "../../i18n/Translations.js";
|
||||
import ChangeTagAction from "../../../Logic/Osm/Actions/ChangeTagAction";
|
||||
import { createEventDispatcher, onDestroy } from "svelte";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
import SpecialTranslation from "./SpecialTranslation.svelte";
|
||||
import TagHint from "../TagHint.svelte";
|
||||
import LoginToggle from "../../Base/LoginToggle.svelte";
|
||||
import SubtleButton from "../../Base/SubtleButton.svelte";
|
||||
import Loading from "../../Base/Loading.svelte";
|
||||
import TagRenderingMappingInput from "./TagRenderingMappingInput.svelte";
|
||||
import { Translation } from "../../i18n/Translation";
|
||||
import Constants from "../../../Models/Constants";
|
||||
import { Unit } from "../../../Models/Unit";
|
||||
import UserRelatedState from "../../../Logic/State/UserRelatedState";
|
||||
import { twJoin } from "tailwind-merge";
|
||||
|
||||
export let config: TagRenderingConfig
|
||||
export let tags: UIEventSource<Record<string, string>>
|
||||
export let selectedElement: Feature
|
||||
export let state: SpecialVisualizationState
|
||||
export let layer: LayerConfig | undefined
|
||||
export let config: TagRenderingConfig;
|
||||
export let tags: UIEventSource<Record<string, string>>;
|
||||
export let selectedElement: Feature;
|
||||
export let state: SpecialVisualizationState;
|
||||
export let layer: LayerConfig | undefined;
|
||||
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined);
|
||||
|
||||
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
|
||||
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key));
|
||||
|
||||
// Will be bound if a freeform is available
|
||||
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key])
|
||||
let selectedMapping: number = undefined
|
||||
let checkedMappings: boolean[]
|
||||
let freeformInput = new UIEventSource<string>(tags?.[config.freeform?.key]);
|
||||
let selectedMapping: number = undefined;
|
||||
let checkedMappings: boolean[];
|
||||
$: {
|
||||
let tgs = $tags
|
||||
let tgs = $tags;
|
||||
mappings = config.mappings?.filter((m) => {
|
||||
if (typeof m.hideInAnswer === "boolean") {
|
||||
return !m.hideInAnswer
|
||||
return !m.hideInAnswer;
|
||||
}
|
||||
return !m.hideInAnswer.matchesProperties(tgs)
|
||||
})
|
||||
return !m.hideInAnswer.matchesProperties(tgs);
|
||||
});
|
||||
// We received a new config -> reinit
|
||||
unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
|
||||
unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key));
|
||||
|
||||
if (
|
||||
config.mappings?.length > 0 &&
|
||||
|
@ -54,23 +54,23 @@
|
|||
) {
|
||||
checkedMappings = [
|
||||
...config.mappings.map((_) => false),
|
||||
false /*One element extra in case a freeform value is added*/,
|
||||
]
|
||||
false /*One element extra in case a freeform value is added*/
|
||||
];
|
||||
}
|
||||
if (config.freeform?.key) {
|
||||
if (!config.multiAnswer) {
|
||||
// Somehow, setting multianswer freeform values is broken if this is not set
|
||||
freeformInput.setData(tgs[config.freeform.key])
|
||||
freeformInput.setData(tgs[config.freeform.key]);
|
||||
}
|
||||
} else {
|
||||
freeformInput.setData(undefined)
|
||||
freeformInput.setData(undefined);
|
||||
}
|
||||
feedback.setData(undefined)
|
||||
feedback.setData(undefined);
|
||||
}
|
||||
export let selectedTags: TagsFilter = undefined
|
||||
export let selectedTags: TagsFilter = undefined;
|
||||
|
||||
let mappings: Mapping[] = config?.mappings
|
||||
let searchTerm: UIEventSource<string> = new UIEventSource("")
|
||||
let mappings: Mapping[] = config?.mappings;
|
||||
let searchTerm: UIEventSource<string> = new UIEventSource("");
|
||||
|
||||
$: {
|
||||
try {
|
||||
|
@ -79,10 +79,10 @@
|
|||
selectedMapping,
|
||||
checkedMappings,
|
||||
tags.data
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Could not calculate changeSpecification:", e)
|
||||
selectedTags = undefined
|
||||
console.error("Could not calculate changeSpecification:", e);
|
||||
selectedTags = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,53 +91,53 @@
|
|||
config: TagRenderingConfig
|
||||
applied: TagsFilter
|
||||
}
|
||||
}>()
|
||||
}>();
|
||||
|
||||
function onSave() {
|
||||
if (selectedTags === undefined) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if (layer === undefined || layer?.source === null) {
|
||||
/**
|
||||
* This is a special, priviliged layer.
|
||||
* We simply apply the tags onto the records
|
||||
*/
|
||||
const kv = selectedTags.asChange(tags.data)
|
||||
const kv = selectedTags.asChange(tags.data);
|
||||
for (const { k, v } of kv) {
|
||||
if (v === undefined) {
|
||||
delete tags.data[k]
|
||||
delete tags.data[k];
|
||||
} else {
|
||||
tags.data[k] = v
|
||||
tags.data[k] = v;
|
||||
}
|
||||
}
|
||||
tags.ping()
|
||||
return
|
||||
tags.ping();
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch("saved", { config, applied: selectedTags })
|
||||
dispatch("saved", { config, applied: selectedTags });
|
||||
const change = new ChangeTagAction(tags.data.id, selectedTags, tags.data, {
|
||||
theme: state.layout.id,
|
||||
changeType: "answer",
|
||||
})
|
||||
freeformInput.setData(undefined)
|
||||
selectedMapping = undefined
|
||||
selectedTags = undefined
|
||||
changeType: "answer"
|
||||
});
|
||||
freeformInput.setData(undefined);
|
||||
selectedMapping = undefined;
|
||||
selectedTags = undefined;
|
||||
|
||||
change
|
||||
.CreateChangeDescriptions()
|
||||
.then((changes) => state.changes.applyChanges(changes))
|
||||
.catch(console.error)
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
let featureSwitchIsTesting = state.featureSwitchIsTesting ?? new ImmutableStore(false)
|
||||
let featureSwitchIsDebugging = state.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false)
|
||||
let showTags = state.userRelatedState?.showTags ?? new ImmutableStore(undefined)
|
||||
let numberOfCs = state.osmConnection.userDetails.data.csCount
|
||||
let featureSwitchIsTesting = state.featureSwitchIsTesting ?? new ImmutableStore(false);
|
||||
let featureSwitchIsDebugging = state.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false);
|
||||
let showTags = state.userRelatedState?.showTags ?? new ImmutableStore(undefined);
|
||||
let numberOfCs = state.osmConnection.userDetails.data.csCount;
|
||||
onDestroy(
|
||||
state.osmConnection?.userDetails?.addCallbackAndRun((ud) => {
|
||||
numberOfCs = ud.csCount
|
||||
numberOfCs = ud.csCount;
|
||||
})
|
||||
)
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if config.question !== undefined}
|
||||
|
@ -218,6 +218,7 @@
|
|||
value={freeformInput}
|
||||
on:selected={() => (selectedMapping = config.mappings?.length)}
|
||||
on:submit={onSave}
|
||||
submit={onSave}
|
||||
/>
|
||||
</label>
|
||||
{/if}
|
||||
|
|
|
@ -1,69 +1,75 @@
|
|||
<script lang="ts">
|
||||
|
||||
import EditLayerState from "./EditLayerState";
|
||||
import layerSchemaRaw from "../../assets/schemas/layerconfigmeta.json"
|
||||
import Region from "./Region.svelte";
|
||||
import TabbedGroup from "../Base/TabbedGroup.svelte";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import type {ConfigMeta} from "./configMeta";
|
||||
import {Utils} from "../../Utils";
|
||||
import EditLayerState, { LayerStateSender } from "./EditLayerState";
|
||||
import layerSchemaRaw from "../../assets/schemas/layerconfigmeta.json";
|
||||
import Region from "./Region.svelte";
|
||||
import TabbedGroup from "../Base/TabbedGroup.svelte";
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource";
|
||||
import type { ConfigMeta } from "./configMeta";
|
||||
import { Utils } from "../../Utils";
|
||||
|
||||
import drinking_water from "../../../assets/layers/drinking_water/drinking_water.json"
|
||||
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw;
|
||||
let state = new EditLayerState(layerSchema);
|
||||
state.configuration.setData({});
|
||||
const configuration = state.configuration;
|
||||
new LayerStateSender("http://localhost:1235", state);
|
||||
/**
|
||||
* Blacklist of regions for the general area tab
|
||||
* These are regions which are handled by a different tab
|
||||
*/
|
||||
const regionBlacklist = ["hidden", undefined, "infobox", "tagrenderings", "maprendering", "editing", "title"];
|
||||
const allNames = Utils.Dedup(layerSchema.map(meta => meta.hints.group));
|
||||
|
||||
const layerSchema: ConfigMeta[] = <any> layerSchemaRaw
|
||||
let state = new EditLayerState(layerSchema)
|
||||
state.configuration.setData(drinking_water)
|
||||
/**
|
||||
* Blacklist for the general area tab
|
||||
*/
|
||||
const regionBlacklist = ["hidden",undefined,"infobox", "tagrenderings","maprendering", "editing", "title"]
|
||||
const allNames = Utils.Dedup(layerSchema.map(meta => meta.hints.group))
|
||||
const perRegion: Record<string, ConfigMeta[]> = {};
|
||||
for (const region of allNames) {
|
||||
perRegion[region] = layerSchema.filter(meta => meta.hints.group === region);
|
||||
}
|
||||
|
||||
const perRegion: Record<string, ConfigMeta[]> = {}
|
||||
for (const region of allNames) {
|
||||
perRegion[region] = layerSchema.filter(meta => meta.hints.group === region)
|
||||
const baselayerRegions: string[] = ["Basic", "presets", "filters", "advanced", "expert"];
|
||||
for (const baselayerRegion of baselayerRegions) {
|
||||
if (perRegion[baselayerRegion] === undefined) {
|
||||
console.error("BaseLayerRegions in editLayer: no items have group '" + baselayerRegion + "\"");
|
||||
}
|
||||
|
||||
const baselayerRegions: string[] = ["Basic", "presets","filters","advanced","expert"]
|
||||
for (const baselayerRegion of baselayerRegions) {
|
||||
if(perRegion[baselayerRegion] === undefined){
|
||||
console.error("BaseLayerRegions in editLayer: no items have group '"+baselayerRegion+'"')
|
||||
}
|
||||
}
|
||||
const leftoverRegions : string[] = allNames.filter(r => regionBlacklist.indexOf(r) <0 && baselayerRegions.indexOf(r) <0 )
|
||||
}
|
||||
const leftoverRegions: string[] = allNames.filter(r => regionBlacklist.indexOf(r) < 0 && baselayerRegions.indexOf(r) < 0);
|
||||
const title: Store<string> = state.getStoreFor(["id"]);
|
||||
</script>
|
||||
|
||||
<h3>Edit layer</h3>
|
||||
|
||||
<h3>Editing layer {$title}</h3>
|
||||
<h4>Leftover regions</h4>
|
||||
{leftoverRegions.join("; ")}
|
||||
<div class="m4">
|
||||
{allNames}
|
||||
<TabbedGroup tab={new UIEventSource(1)}>
|
||||
<TabbedGroup tab={new UIEventSource(2)}>
|
||||
<div slot="title0">General properties</div>
|
||||
<div class="flex flex-col" slot="content0">
|
||||
{#each baselayerRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region}/>
|
||||
{/each}
|
||||
|
||||
{#each leftoverRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region}/>
|
||||
{/each}
|
||||
{#each baselayerRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region} />
|
||||
{/each}
|
||||
{#each leftoverRegions as region}
|
||||
<Region {state} configs={perRegion[region]} title={region} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div slot="title1">Information panel (questions and answers)</div>
|
||||
<div slot="content1">
|
||||
<Region {state} configs={perRegion["tagrenderings"]} title="Popup contents">
|
||||
<div slot="description">
|
||||
The bulk of the popup content
|
||||
</div>
|
||||
</Region>
|
||||
<Region {state} configs={perRegion["title"]} title="Popup title"/>
|
||||
<Region {state} configs={perRegion["editing"]} title="Other editing elements"/>
|
||||
<Region configs={perRegion["title"]} {state} title="Popup title" />
|
||||
<Region configs={perRegion["tagrenderings"]} {state} title="Popup contents"/>
|
||||
<Region configs={perRegion["editing"]} {state} title="Other editing elements" />
|
||||
</div>
|
||||
|
||||
<div slot="title2">Rendering on the map</div>
|
||||
<div slot="content2">
|
||||
TODO: rendering on the map
|
||||
<Region configs={perRegion["maprendering"]} {state} />
|
||||
</div>
|
||||
</TabbedGroup>
|
||||
<div slot="title3">Configuration file</div>
|
||||
<div slot="content3">
|
||||
<div>
|
||||
Below, you'll find the raw configuration file in `.json`-format.
|
||||
This is mostly for debugging purposes
|
||||
</div>
|
||||
<div class="literal-code">
|
||||
{JSON.stringify($configuration, null, " ")}
|
||||
</div>
|
||||
</div>
|
||||
</TabbedGroup>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,30 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
|||
import { ConfigMeta } from "./configMeta"
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
|
||||
import { QueryParameters } from "../../Logic/Web/QueryParameters"
|
||||
|
||||
/**
|
||||
* Sends changes back to the server
|
||||
*/
|
||||
export class LayerStateSender {
|
||||
constructor(serverLocation: string, layerState: EditLayerState) {
|
||||
layerState.configuration.addCallback(async (config) => {
|
||||
// console.log("Current config is", Utils.Clone(config))
|
||||
const id = config.id
|
||||
if (id === undefined) {
|
||||
console.log("No id found in layer, not updating")
|
||||
return
|
||||
}
|
||||
const response = await fetch(`${serverLocation}/layers/${id}/${id}.json`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify(config, null, " "),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default class EditLayerState {
|
||||
public readonly osmConnection: OsmConnection
|
||||
|
@ -15,13 +39,17 @@ export default class EditLayerState {
|
|||
|
||||
constructor(schema: ConfigMeta[]) {
|
||||
this.schema = schema
|
||||
this.osmConnection = new OsmConnection({})
|
||||
this.osmConnection = new OsmConnection({
|
||||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
),
|
||||
})
|
||||
this.featureSwitches = {
|
||||
featureSwitchIsDebugging: new UIEventSource<boolean>(true),
|
||||
}
|
||||
this.configuration.addCallback((config) => {
|
||||
// console.log("Current config is", Utils.Clone(config))
|
||||
})
|
||||
console.log("Configuration store:", this.configuration)
|
||||
}
|
||||
|
||||
public getCurrentValueFor(path: ReadonlyArray<string | number>): any | undefined {
|
||||
|
@ -78,12 +106,17 @@ export default class EditLayerState {
|
|||
description: origConfig.description ?? "A translatable object",
|
||||
}
|
||||
}
|
||||
|
||||
public getSchema(path: string[]): ConfigMeta[] {
|
||||
return this.schema.filter(
|
||||
const schemas = this.schema.filter(
|
||||
(sch) =>
|
||||
sch !== undefined &&
|
||||
!path.some((part, i) => !(sch.path.length == path.length && sch.path[i] === part))
|
||||
)
|
||||
if (schemas.length == 0) {
|
||||
console.warn("No schemas found for path", path.join("."))
|
||||
}
|
||||
return schemas
|
||||
}
|
||||
|
||||
public setValueAt(path: ReadonlyArray<string | number>, v: any) {
|
||||
|
|
|
@ -13,7 +13,11 @@ export let title: string | undefined = undefined;
|
|||
export let path: (string | number)[] = [];
|
||||
|
||||
</script>
|
||||
{#if title}
|
||||
{#if configs === undefined}
|
||||
Bug: 'Region' received 'undefined'
|
||||
{:else if configs.length === 0}
|
||||
Bug: Region received empty list as configuration
|
||||
{:else if title}
|
||||
<div class="w-full flex flex-col">
|
||||
<h3>{title}</h3>
|
||||
<div class="pl-2 border border-black flex flex-col gap-y-1 w-full">
|
||||
|
@ -24,6 +28,9 @@ export let path: (string | number)[] = [];
|
|||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="literal-code">
|
||||
{JSON.stringify(configs, null, " ")}
|
||||
</div>
|
||||
<div class="pl-2 flex flex-col gap-y-1 w-full">
|
||||
{#each configs as config}
|
||||
<SchemaBasedInput {state} path={path.concat(config.path)} schema={config} />
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
<div class="flex">
|
||||
<button on:click={() => createItem()}>Add {article} {singular}</button>
|
||||
{#if path.length === 1 && path[0] === "tagRenderings"}
|
||||
<button on:click={() => {createItem();}}>Add a builtin tagRendering</button>
|
||||
<button on:click={() => {createItem("images");}}>Add a builtin tagRendering</button>
|
||||
{/if}
|
||||
<slot name="extra-button" />
|
||||
</div>
|
||||
|
|
|
@ -11,21 +11,21 @@
|
|||
import EditLayerState from "./EditLayerState";
|
||||
import { onDestroy } from "svelte";
|
||||
import type { JsonSchemaType } from "./jsonSchema";
|
||||
|
||||
import { ConfigMetaUtils } from "./configMeta.ts"
|
||||
|
||||
export let state: EditLayerState
|
||||
export let path: (string | number)[] = []
|
||||
export let schema: ConfigMeta
|
||||
let value = new UIEventSource<string>(undefined)
|
||||
|
||||
const isTranslation = schema.hints.typehint === "translation" || schema.hints.typehint === "rendered" || ConfigMetaUtils.isTranslation(schema)
|
||||
let type = schema.hints.typehint ?? "string"
|
||||
if(type === "rendered"){
|
||||
if(isTranslation){
|
||||
type = "translation"
|
||||
}
|
||||
if(type.endsWith("[]")){
|
||||
type = type.substring(0, type.length - 2)
|
||||
}
|
||||
const isTranslation =schema.hints.typehint === "translation" || schema.hints.typehint === "rendered"
|
||||
|
||||
const configJson: QuestionableTagRenderingConfigJson = {
|
||||
id: path.join("_"),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import SchemaBasedArray from "./SchemaBasedArray.svelte";
|
||||
import SchemaBasedMultiType from "./SchemaBasedMultiType.svelte";
|
||||
import SchemaBasedTranslationInput from "./SchemaBasedTranslationInput.svelte";
|
||||
|
||||
import { ConfigMetaUtils } from "./configMeta.ts"
|
||||
export let schema: ConfigMeta;
|
||||
export let state: EditLayerState;
|
||||
export let path: (string | number)[] = [];
|
||||
|
@ -16,8 +16,6 @@
|
|||
<SchemaBasedArray {path} {state} {schema} />
|
||||
{:else if schema.type === "array"}
|
||||
<SchemaBasedArray {path} {state} {schema} />
|
||||
{:else if schema.type === "translation"}
|
||||
<SchemaBasedTranslationInput {path} {state} {schema} />
|
||||
{:else if schema.hints.types}
|
||||
<SchemaBasedMultiType {path} {state} {schema} />
|
||||
{:else}
|
||||
|
|
|
@ -45,12 +45,12 @@
|
|||
configJson.mappings.unshift(
|
||||
{
|
||||
if: "direct=true",
|
||||
then: "Yes " + (schema.hints.iftrue ?? ""),
|
||||
then: (schema.hints.iftrue ?? "Yes"),
|
||||
addExtraTags: ["value="]
|
||||
},
|
||||
{
|
||||
if: "direct=false",
|
||||
then: "No " + (schema.hints.iffalse ?? ""),
|
||||
then: (schema.hints.iffalse ?? "No"),
|
||||
addExtraTags: ["value="]
|
||||
}
|
||||
);
|
||||
|
@ -95,7 +95,6 @@
|
|||
}
|
||||
possibleTypes.sort((a, b) => b.optionalMatches - a.optionalMatches);
|
||||
possibleTypes.sort((a, b) => b.matchingPropertiesCount - a.matchingPropertiesCount);
|
||||
console.log(">>> possible types", possibleTypes)
|
||||
if (possibleTypes.length > 0) {
|
||||
tags.setData({ value: "" + possibleTypes[0].index });
|
||||
}
|
||||
|
@ -122,13 +121,19 @@
|
|||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
const oldOption = chosenOption;
|
||||
chosenOption = tags["value"] ? Number(tags["value"]) : defaultOption;
|
||||
const type = schema.type[chosenOption];
|
||||
console.log("Subtype is", type, {chosenOption, oldOption, schema});
|
||||
if (chosenOption !== oldOption) {
|
||||
// Reset the values beneath
|
||||
subSchemas = [];
|
||||
state.setValueAt(path, undefined);
|
||||
const o = state.getCurrentValueFor(path) ?? {}
|
||||
console.log({o})
|
||||
for(const key of type?.required ?? []){
|
||||
console.log(key)
|
||||
o[key] ??= {}
|
||||
}
|
||||
state.setValueAt(path, o);
|
||||
}
|
||||
const type = schema.type[chosenOption];
|
||||
console.log("Subtype is", type);
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
|
@ -148,6 +153,7 @@
|
|||
for (const crumble of Object.keys(type.properties)) {
|
||||
subSchemas.push(...(state.getSchema([...cleanPath, crumble])));
|
||||
}
|
||||
console.log("Got subschemas for", path, ":", subSchemas)
|
||||
}));
|
||||
|
||||
|
||||
|
|
|
@ -22,3 +22,22 @@ export interface ConfigMeta {
|
|||
required: boolean
|
||||
description: string
|
||||
}
|
||||
|
||||
export class ConfigMetaUtils {
|
||||
static isTranslation(configMeta: ConfigMeta) {
|
||||
/* {
|
||||
"$ref": "#/definitions/Record<string,string>"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}*/
|
||||
if (!configMeta.type) {
|
||||
return false
|
||||
}
|
||||
if (Array.isArray(configMeta.type)) {
|
||||
return configMeta.type.some((t) => t["$ref"] === "#/definitions/Record<string,string>")
|
||||
} else {
|
||||
return configMeta.type["$ref"] === "#/definitions/Record<string,string>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -601,7 +601,8 @@
|
|||
"required": false,
|
||||
"hints": {
|
||||
"question": "Show the freeform as box within the question?",
|
||||
"ifunset": "do not show the"
|
||||
"iftrue": "show the freeform input field as a small field within the question",
|
||||
"ifunset": "show the freeform input field full-width"
|
||||
},
|
||||
"type": "boolean",
|
||||
"description": "Instead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout."
|
||||
|
@ -661,7 +662,7 @@
|
|||
"required": false,
|
||||
"hints": {},
|
||||
"type": "array",
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away"
|
||||
"description": "A list of labels. These are strings that are used for various purposes, e.g. to only include a subset of the tagRenderings when reusing a layer"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
|
|
|
@ -126,6 +126,72 @@
|
|||
],
|
||||
"description": "\nOnly show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"condition",
|
||||
"and"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"condition",
|
||||
"or"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"metacondition"
|
||||
|
@ -147,6 +213,72 @@
|
|||
],
|
||||
"description": "\nIf set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"metacondition",
|
||||
"and"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"metacondition",
|
||||
"or"
|
||||
],
|
||||
"required": false,
|
||||
"hints": {
|
||||
"typehint": "tag"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "The main representation of Tags.\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for more documentation\n"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"freeform"
|
||||
|
@ -178,6 +310,40 @@
|
|||
"type": "array",
|
||||
"description": "Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"mappings",
|
||||
"if"
|
||||
],
|
||||
"required": true,
|
||||
"hints": {
|
||||
"typehint": "tag",
|
||||
"question": "When should this single mapping match?"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"$ref": "#/definitions/{and:TagConfigJson[];}"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"or": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TagConfigJson"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"or"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "\nIf this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}"
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"mappings",
|
||||
|
|
29
src/test.ts
29
src/test.ts
|
@ -1,19 +1,16 @@
|
|||
import LayoutConfig from "./Models/ThemeConfig/LayoutConfig"
|
||||
import * as theme from "./assets/generated/themes/bookcases.json"
|
||||
import ThemeViewState from "./Models/ThemeViewState"
|
||||
import Combine from "./UI/Base/Combine"
|
||||
import SpecialVisualizations from "./UI/SpecialVisualizations"
|
||||
import { Utils } from "./Utils"
|
||||
|
||||
function testspecial() {
|
||||
const layout = new LayoutConfig(<any>theme, true) // qp.data === "" ? : new AllKnownLayoutsLazy().get(qp.data)
|
||||
const state = new ThemeViewState(layout)
|
||||
|
||||
const all = SpecialVisualizations.specialVisualizations.map((s) =>
|
||||
SpecialVisualizations.renderExampleOfSpecial(state, s)
|
||||
)
|
||||
new Combine(all).AttachTo("maindiv")
|
||||
class Test {
|
||||
public async test() {
|
||||
await Utils.waitFor(0)
|
||||
const response = await fetch("http://localhost:1235/layers/atm/atm.json", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/*/
|
||||
testspecial()
|
||||
//*/
|
||||
new Test().test()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue