forked from MapComplete/MapComplete
Themes: allow to easily import tagrenderings and add a prefix key to all tags
This commit is contained in:
parent
4d9bdaf877
commit
01680f236c
9 changed files with 201 additions and 31 deletions
|
@ -0,0 +1,134 @@
|
||||||
|
import { DesugaringStep } from "./Conversion"
|
||||||
|
import { ConversionContext } from "./ConversionContext"
|
||||||
|
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
|
||||||
|
import { Translatable } from "../Json/Translatable"
|
||||||
|
import { TagConfigJson } from "../Json/TagConfigJson"
|
||||||
|
import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
|
||||||
|
|
||||||
|
export default class AddPrefixToTagRenderingConfig extends DesugaringStep<QuestionableTagRenderingConfigJson> {
|
||||||
|
|
||||||
|
|
||||||
|
private readonly _prefix: string
|
||||||
|
|
||||||
|
constructor(prefix: string) {
|
||||||
|
super("Adds `prefix` to _all_ keys. Used to add information about a subamenity withing a bigger amenity (e.g. toilets in a restaurant, a sauna in a water park, ...)", ["*"], "AddPrefixToTagRenderingConfig")
|
||||||
|
this._prefix = prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* const edit = new AddPrefixToTagRenderingConfig("PREFIX")
|
||||||
|
* edit.updateString("Some string") // => "Some string"
|
||||||
|
* edit.updateString("Some string {key0}") // => "Some string {PREFIX:key0}"
|
||||||
|
*
|
||||||
|
* // Should prefix a key in a special visualisation
|
||||||
|
* new AddPrefixToTagRenderingConfig("PREFIX").updateString("{opening_hours_table(opening_hours)}") // => "{opening_hours_table(PREFIX:opening_hours,,)}"
|
||||||
|
*
|
||||||
|
* // Should prefix the default key in a special visualisation
|
||||||
|
* new AddPrefixToTagRenderingConfig("PREFIX").updateString("{opening_hours_table()}") // => "{opening_hours_table(PREFIX:opening_hours,,)}"
|
||||||
|
*/
|
||||||
|
private updateString(str: string): string {
|
||||||
|
const parsed = SpecialVisualizations.constructSpecification(str)
|
||||||
|
const fixedSpec: string[] = []
|
||||||
|
for (const spec of parsed) {
|
||||||
|
if (typeof spec === "string") {
|
||||||
|
const part = spec.replace(/{([a-zA-Z0-9:_-]+)}/g, `{${this._prefix}:$1}`)
|
||||||
|
fixedSpec.push(part)
|
||||||
|
} else {
|
||||||
|
const newArgs: string[] = []
|
||||||
|
for (let i = 0; i < spec.func.args.length; i++) {
|
||||||
|
const argDoc = spec.func.args[i]
|
||||||
|
const argV = spec.args[i]
|
||||||
|
if (argDoc.type === "key") {
|
||||||
|
newArgs.push(this._prefix + ":" + (argV ?? argDoc.defaultValue ?? ""))
|
||||||
|
} else {
|
||||||
|
newArgs.push(argV ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fixedSpec.push("{" + spec.func.funcName + "(" + newArgs.join(",") + ")}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fixedSpec.join("")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTranslatable(val: Translatable | undefined): Translatable | undefined {
|
||||||
|
if (!val) {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
if (typeof val === "string") {
|
||||||
|
return this.updateString(val)
|
||||||
|
}
|
||||||
|
const newTranslations: Record<string, string> = {}
|
||||||
|
for (const lng in val) {
|
||||||
|
newTranslations[lng] = this.updateString(val[lng])
|
||||||
|
}
|
||||||
|
return newTranslations
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTag(tags: string): string;
|
||||||
|
private updateTag(tags: TagConfigJson): TagConfigJson;
|
||||||
|
private updateTag(tags: TagConfigJson): TagConfigJson {
|
||||||
|
if (!tags) {
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
if (tags["and"]) {
|
||||||
|
return { and: this.updateTags(tags["and"]) }
|
||||||
|
}
|
||||||
|
if (tags["or"]) {
|
||||||
|
return { or: this.updateTags(tags["or"]) }
|
||||||
|
}
|
||||||
|
return this._prefix + ":" + tags
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateTags(tags: ReadonlyArray<string>): string[] {
|
||||||
|
return tags?.map(tag => this.updateTag(tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateMapping(mapping: Readonly<MappingConfigJson>): MappingConfigJson {
|
||||||
|
return {
|
||||||
|
...mapping,
|
||||||
|
addExtraTags: this.updateTags(mapping.addExtraTags),
|
||||||
|
if: this.updateTag(mapping.if),
|
||||||
|
then: this.updateTranslatable(mapping.then),
|
||||||
|
alsoShowIf: this.updateTag(mapping.alsoShowIf),
|
||||||
|
ifnot: this.updateTag(mapping.ifnot),
|
||||||
|
priorityIf: this.updateTag(mapping.priorityIf),
|
||||||
|
hideInAnswer: mapping.hideInAnswer === true || mapping.hideInAnswer === false ? mapping.hideInAnswer : this.updateTag(mapping.hideInAnswer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public convert(json: Readonly<QuestionableTagRenderingConfigJson>, context: ConversionContext): QuestionableTagRenderingConfigJson {
|
||||||
|
let freeform = json.freeform
|
||||||
|
if (freeform) {
|
||||||
|
const ff = json.freeform
|
||||||
|
freeform = {
|
||||||
|
...ff,
|
||||||
|
key: this._prefix + ":" + ff.key,
|
||||||
|
addExtraTags: this.updateTags(ff.addExtraTags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <QuestionableTagRenderingConfigJson>{
|
||||||
|
...json,
|
||||||
|
id: this._prefix + "_" + json.id,
|
||||||
|
|
||||||
|
question: this.updateTranslatable(json.question),
|
||||||
|
questionHint: this.updateTranslatable(json.questionHint),
|
||||||
|
|
||||||
|
render: this.updateTranslatable(<Translatable>json.render),
|
||||||
|
freeform,
|
||||||
|
editButtonAriaLabel: json.editButtonAriaLabel,
|
||||||
|
onSoftDelete: this.updateTags(json.onSoftDelete),
|
||||||
|
invalidValues: this.updateTag(json.invalidValues),
|
||||||
|
mappings: json.mappings?.map(mapping => this.updateMapping(mapping)),
|
||||||
|
|
||||||
|
condition: this.updateTag(json.condition),
|
||||||
|
metacondition: json.metacondition, // no update here
|
||||||
|
filter: json.filter === true, // We break references to filters, as those references won't have the updated tags
|
||||||
|
_appliedPrefix: this._prefix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRende
|
||||||
import { TagUtils } from "../../../Logic/Tags/TagUtils"
|
import { TagUtils } from "../../../Logic/Tags/TagUtils"
|
||||||
import { Utils } from "../../../Utils"
|
import { Utils } from "../../../Utils"
|
||||||
import { AddContextToTranslations } from "./AddContextToTranslations"
|
import { AddContextToTranslations } from "./AddContextToTranslations"
|
||||||
|
import AddPrefixToTagRenderingConfig from "./AddPrefixToTagRenderingConfig"
|
||||||
|
import { Translatable } from "../Json/Translatable"
|
||||||
|
|
||||||
export class ExpandTagRendering extends Conversion<
|
export class ExpandTagRendering extends Conversion<
|
||||||
| string
|
| string
|
||||||
|
@ -208,6 +210,21 @@ export class ExpandTagRendering extends Conversion<
|
||||||
let matchingTrs: (TagRenderingConfigJson & { id: string })[]
|
let matchingTrs: (TagRenderingConfigJson & { id: string })[]
|
||||||
if (id === "*") {
|
if (id === "*") {
|
||||||
matchingTrs = layerTrs
|
matchingTrs = layerTrs
|
||||||
|
} else if (id === "title") {
|
||||||
|
const title = layer.title
|
||||||
|
if (title["render"] || title["mappings"]) {
|
||||||
|
const titleTr = <TagRenderingConfigJson>layer.title
|
||||||
|
return [{
|
||||||
|
...titleTr,
|
||||||
|
id: layer.id + "_title"
|
||||||
|
}]
|
||||||
|
} else {
|
||||||
|
const transl = <Translatable>layer.title
|
||||||
|
return [{
|
||||||
|
render: transl,
|
||||||
|
id: layer.id + "_title"
|
||||||
|
}]
|
||||||
|
}
|
||||||
} else if (id.startsWith("*")) {
|
} else if (id.startsWith("*")) {
|
||||||
const id_ = id.substring(1)
|
const id_ = id.substring(1)
|
||||||
matchingTrs = layerTrs.filter((tr) => tr["labels"]?.indexOf(id_) >= 0)
|
matchingTrs = layerTrs.filter((tr) => tr["labels"]?.indexOf(id_) >= 0)
|
||||||
|
@ -249,6 +266,25 @@ export class ExpandTagRendering extends Conversion<
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a variation of 'tr' where every key has been prefixed by the given 'prefix'-key.
|
||||||
|
* If the given key is undefined, returns the original tagRendering.
|
||||||
|
*
|
||||||
|
* Note: metacondition will _not_ be prefixed
|
||||||
|
* @param key
|
||||||
|
* @param tr
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private static applyKeyPrefix(key: string | undefined, tr: Readonly<QuestionableTagRenderingConfigJson>, ctx: ConversionContext): QuestionableTagRenderingConfigJson {
|
||||||
|
if (key === undefined || key === null) {
|
||||||
|
return tr
|
||||||
|
}
|
||||||
|
if (key.endsWith(":")) {
|
||||||
|
ctx.err("A 'prefix'-key should not end with a colon. The offending prefix value is: " + key)
|
||||||
|
}
|
||||||
|
return new AddPrefixToTagRenderingConfig(key).convert(tr, ctx.enter("prefix"))
|
||||||
|
}
|
||||||
|
|
||||||
private convertOnce(
|
private convertOnce(
|
||||||
tr: string | { builtin: string | string[] } | TagRenderingConfigJson,
|
tr: string | { builtin: string | string[] } | TagRenderingConfigJson,
|
||||||
ctx: ConversionContext
|
ctx: ConversionContext
|
||||||
|
@ -310,6 +346,7 @@ export class ExpandTagRendering extends Conversion<
|
||||||
if (
|
if (
|
||||||
key === "builtin" ||
|
key === "builtin" ||
|
||||||
key === "override" ||
|
key === "override" ||
|
||||||
|
key === "prefix" ||
|
||||||
key === "id" ||
|
key === "id" ||
|
||||||
key.startsWith("#")
|
key.startsWith("#")
|
||||||
) {
|
) {
|
||||||
|
@ -379,6 +416,7 @@ export class ExpandTagRendering extends Conversion<
|
||||||
}
|
}
|
||||||
for (let foundTr of lookup) {
|
for (let foundTr of lookup) {
|
||||||
foundTr = Utils.Clone(foundTr)
|
foundTr = Utils.Clone(foundTr)
|
||||||
|
foundTr = ExpandTagRendering.applyKeyPrefix(tr["prefix"], foundTr, ctx)
|
||||||
ctx.MergeObjectsForOverride(tr["override"] ?? {}, foundTr)
|
ctx.MergeObjectsForOverride(tr["override"] ?? {}, foundTr)
|
||||||
if (names.length == 1) {
|
if (names.length == 1) {
|
||||||
foundTr["id"] = tr["id"] ?? foundTr["id"]
|
foundTr["id"] = tr["id"] ?? foundTr["id"]
|
||||||
|
|
|
@ -1,14 +1,4 @@
|
||||||
import {
|
import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
|
||||||
Concat,
|
|
||||||
Conversion,
|
|
||||||
DesugaringContext,
|
|
||||||
DesugaringStep,
|
|
||||||
Each,
|
|
||||||
Fuse,
|
|
||||||
On,
|
|
||||||
Pass,
|
|
||||||
SetDefault,
|
|
||||||
} from "./Conversion"
|
|
||||||
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
|
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
|
||||||
import { PrepareLayer, RewriteSpecial } from "./PrepareLayer"
|
import { PrepareLayer, RewriteSpecial } from "./PrepareLayer"
|
||||||
import { LayerConfigJson } from "../Json/LayerConfigJson"
|
import { LayerConfigJson } from "../Json/LayerConfigJson"
|
||||||
|
@ -163,9 +153,8 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
const unused = Array.from(hideLabels).filter((l) => !usedLabels.has(l))
|
const unused = Array.from(hideLabels).filter((l) => !usedLabels.has(l))
|
||||||
if (unused.length > 0) {
|
if (unused.length > 0) {
|
||||||
context.err(
|
context.err(
|
||||||
"This theme specifies that certain tagrenderings have to be removed based on forbidden layers. One or more of these layers did not match any tagRenderings and caused no deletions: " +
|
`You are attempting to import layer '${found.id}' in this theme. This layer import specifies that certain tagrenderings have to be removed based on forbidden ids and/or labels. One or more of these forbidden ids did not match any tagRenderings and caused no deletions: ${unused.join(", ")}
|
||||||
unused.join(", ") +
|
This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore`
|
||||||
"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
found.tagRenderings = filtered
|
found.tagRenderings = filtered
|
||||||
|
|
|
@ -422,8 +422,15 @@ export interface LayerConfigJson {
|
||||||
| string
|
| string
|
||||||
| {
|
| {
|
||||||
id?: string
|
id?: string
|
||||||
|
/**
|
||||||
|
* Special value: "<layerid>.title" will return the layer's title for an element
|
||||||
|
*/
|
||||||
builtin: string | string[]
|
builtin: string | string[]
|
||||||
override: Partial<QuestionableTagRenderingConfigJson>
|
override: Partial<QuestionableTagRenderingConfigJson>,
|
||||||
|
/**
|
||||||
|
* Add this prefix to all keys. This is applied _before_ the override, thus keys added in 'override' will not be prefixed
|
||||||
|
*/
|
||||||
|
prefix?: string
|
||||||
}
|
}
|
||||||
| QuestionableTagRenderingConfigJson
|
| QuestionableTagRenderingConfigJson
|
||||||
| (RewritableConfigJson<
|
| (RewritableConfigJson<
|
||||||
|
|
|
@ -289,7 +289,7 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
|
||||||
* Extra arguments to configure the input element
|
* Extra arguments to configure the input element
|
||||||
* group: hidden
|
* group: hidden
|
||||||
*/
|
*/
|
||||||
helperArgs: any
|
helperArgs?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,7 +14,7 @@ import NearbyImagesCollapsed from "../Image/NearbyImagesCollapsed.svelte"
|
||||||
|
|
||||||
class NearbyImageVis implements SpecialVisualizationSvelte {
|
class NearbyImageVis implements SpecialVisualizationSvelte {
|
||||||
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
||||||
args: { name: string; defaultValue?: string; doc: string; required?: boolean }[] = [
|
args: [
|
||||||
{
|
{
|
||||||
name: "mode",
|
name: "mode",
|
||||||
defaultValue: "closed",
|
defaultValue: "closed",
|
||||||
|
@ -65,6 +65,7 @@ export class ImageVisualisations {
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "image_key",
|
name: "image_key",
|
||||||
|
type: "key",
|
||||||
defaultValue: AllImageProviders.defaultKeys.join(";"),
|
defaultValue: AllImageProviders.defaultKeys.join(";"),
|
||||||
doc: "The keys given to the images, e.g. if <span class='literal-code'>image</span> is given, the first picture URL will be added as <span class='literal-code'>image</span>, the second as <span class='literal-code'>image:0</span>, the third as <span class='literal-code'>image:1</span>, etc... Multiple values are allowed if ';'-separated ",
|
doc: "The keys given to the images, e.g. if <span class='literal-code'>image</span> is given, the first picture URL will be added as <span class='literal-code'>image</span>, the second as <span class='literal-code'>image:0</span>, the third as <span class='literal-code'>image:1</span>, etc... Multiple values are allowed if ';'-separated ",
|
||||||
},
|
},
|
||||||
|
@ -95,6 +96,7 @@ export class ImageVisualisations {
|
||||||
needsUrls: [Imgur.apiUrl, ...Imgur.supportingUrls],
|
needsUrls: [Imgur.apiUrl, ...Imgur.supportingUrls],
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
|
type: "key",
|
||||||
name: "image_key",
|
name: "image_key",
|
||||||
doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)",
|
doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)",
|
||||||
defaultValue: "panoramax",
|
defaultValue: "panoramax",
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||||
import BaseUIElement from "./BaseUIElement"
|
import BaseUIElement from "./BaseUIElement"
|
||||||
import ThemeConfig from "../Models/ThemeConfig/ThemeConfig"
|
import ThemeConfig from "../Models/ThemeConfig/ThemeConfig"
|
||||||
import {
|
import { FeatureSource, IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource"
|
||||||
FeatureSource,
|
|
||||||
IndexedFeatureSource,
|
|
||||||
WritableFeatureSource,
|
|
||||||
} from "../Logic/FeatureSource/FeatureSource"
|
|
||||||
import { OsmConnection } from "../Logic/Osm/OsmConnection"
|
import { OsmConnection } from "../Logic/Osm/OsmConnection"
|
||||||
import { Changes } from "../Logic/Osm/Changes"
|
import { Changes } from "../Logic/Osm/Changes"
|
||||||
import { ExportableMap, MapProperties } from "../Models/MapProperties"
|
import { ExportableMap, MapProperties } from "../Models/MapProperties"
|
||||||
|
@ -100,7 +96,8 @@ export interface SpecialVisualization {
|
||||||
name: string
|
name: string
|
||||||
defaultValue?: string
|
defaultValue?: string
|
||||||
doc: string
|
doc: string
|
||||||
required?: false | boolean
|
required?: false | boolean,
|
||||||
|
type?: "key"
|
||||||
}[]
|
}[]
|
||||||
readonly getLayerDependencies?: (argument: string[]) => string[]
|
readonly getLayerDependencies?: (argument: string[]) => string[]
|
||||||
|
|
||||||
|
@ -133,7 +130,8 @@ export interface SpecialVisualizationSvelte {
|
||||||
name: string
|
name: string
|
||||||
defaultValue?: string
|
defaultValue?: string
|
||||||
doc: string
|
doc: string
|
||||||
required?: false | boolean
|
required?: false | boolean,
|
||||||
|
type?: "key" | string
|
||||||
}[]
|
}[]
|
||||||
readonly getLayerDependencies?: (argument: string[]) => string[]
|
readonly getLayerDependencies?: (argument: string[]) => string[]
|
||||||
|
|
||||||
|
|
|
@ -257,6 +257,7 @@ export default class SpecialVisualizations {
|
||||||
{
|
{
|
||||||
name: "key",
|
name: "key",
|
||||||
defaultValue: "opening_hours",
|
defaultValue: "opening_hours",
|
||||||
|
type: "key",
|
||||||
doc: "The tagkey from which the table is constructed.",
|
doc: "The tagkey from which the table is constructed.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -284,6 +285,7 @@ export default class SpecialVisualizations {
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "key",
|
name: "key",
|
||||||
|
type: "key",
|
||||||
defaultValue: "opening_hours",
|
defaultValue: "opening_hours",
|
||||||
doc: "The tagkey from which the opening hours are read.",
|
doc: "The tagkey from which the opening hours are read.",
|
||||||
},
|
},
|
||||||
|
@ -324,6 +326,7 @@ export default class SpecialVisualizations {
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "key",
|
name: "key",
|
||||||
|
type: "key",
|
||||||
doc: "The key of the tag to give the canonical text for",
|
doc: "The key of the tag to give the canonical text for",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
@ -412,6 +415,7 @@ export default class SpecialVisualizations {
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "key",
|
name: "key",
|
||||||
|
type: "key",
|
||||||
doc: "The attribute to interpret as json",
|
doc: "The attribute to interpret as json",
|
||||||
defaultValue: "value",
|
defaultValue: "value",
|
||||||
},
|
},
|
||||||
|
@ -463,6 +467,7 @@ export default class SpecialVisualizations {
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "key",
|
name: "key",
|
||||||
|
type: "key",
|
||||||
defaultValue: "value",
|
defaultValue: "value",
|
||||||
doc: "The key to look for the tags",
|
doc: "The key to look for the tags",
|
||||||
},
|
},
|
||||||
|
@ -470,9 +475,7 @@ export default class SpecialVisualizations {
|
||||||
constr(
|
constr(
|
||||||
state: SpecialVisualizationState,
|
state: SpecialVisualizationState,
|
||||||
tagSource: UIEventSource<Record<string, string>>,
|
tagSource: UIEventSource<Record<string, string>>,
|
||||||
argument: string[],
|
argument: string[]
|
||||||
feature: Feature,
|
|
||||||
layer: LayerConfig
|
|
||||||
): BaseUIElement {
|
): BaseUIElement {
|
||||||
const key = argument[0] ?? "value"
|
const key = argument[0] ?? "value"
|
||||||
return new VariableUiElement(
|
return new VariableUiElement(
|
||||||
|
@ -508,8 +511,7 @@ export default class SpecialVisualizations {
|
||||||
state: SpecialVisualizationState,
|
state: SpecialVisualizationState,
|
||||||
tagSource: UIEventSource<Record<string, string>>,
|
tagSource: UIEventSource<Record<string, string>>,
|
||||||
argument: string[],
|
argument: string[],
|
||||||
feature: Feature,
|
feature: Feature
|
||||||
layer: LayerConfig
|
|
||||||
): BaseUIElement {
|
): BaseUIElement {
|
||||||
return new SvelteUIElement(DirectionIndicator, { state, feature })
|
return new SvelteUIElement(DirectionIndicator, { state, feature })
|
||||||
},
|
},
|
||||||
|
@ -520,6 +522,7 @@ export default class SpecialVisualizations {
|
||||||
args: [
|
args: [
|
||||||
{
|
{
|
||||||
name: "key",
|
name: "key",
|
||||||
|
type: "key",
|
||||||
doc: "The attribute containing the degrees",
|
doc: "The attribute containing the degrees",
|
||||||
defaultValue: "_direction:centerpoint",
|
defaultValue: "_direction:centerpoint",
|
||||||
},
|
},
|
||||||
|
|
|
@ -466,8 +466,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
if (v !== undefined && v !== null) {
|
if (v !== undefined && v !== null) {
|
||||||
if (v["toISOString"] != undefined) {
|
if (v["toISOString"] != undefined) {
|
||||||
// This is a date, probably the timestamp of the object
|
// This is a date, probably the timestamp of the object
|
||||||
// @ts-ignore
|
const date: Date = v
|
||||||
const date: Date = el
|
|
||||||
v = date.toISOString()
|
v = date.toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue