diff --git a/src/UI/BigComponents/NewPointLocationInput.svelte b/src/UI/BigComponents/NewPointLocationInput.svelte index 5625910d98..bf17a273a2 100644 --- a/src/UI/BigComponents/NewPointLocationInput.svelte +++ b/src/UI/BigComponents/NewPointLocationInput.svelte @@ -1,129 +1,135 @@ dispatch("click", data)} - mapProperties={initialMapProperties} - value={preciseLocation} initialCoordinate={coordinate} - maxDistanceInMeters="50" + {map} + mapProperties={initialMapProperties} + maxDistanceInMeters={50} + on:click={(data) => dispatch("click", data)} + value={preciseLocation} > diff --git a/src/UI/Popup/ImportButtons/ImportFlow.svelte b/src/UI/Popup/ImportButtons/ImportFlow.svelte index 415d4b8979..4c766c25ec 100644 --- a/src/UI/Popup/ImportButtons/ImportFlow.svelte +++ b/src/UI/Popup/ImportButtons/ImportFlow.svelte @@ -1,41 +1,57 @@ @@ -44,13 +60,13 @@ {#if $canBeImported.extraHelp} {/if} - {:else if !$isDisplayed} + {:else if undisplayedLayer !== undefined}
@@ -60,7 +76,7 @@ class="flex w-full gap-x-1" on:click={() => { abort() - state.guistate.openFilterView(importFlow.targetLayer.layerDef) + state.guistate.openFilterView(filteredLayer.layerDef) }} > @@ -70,19 +86,19 @@ - {:else if $hasFilter} + {:else if filteredLayer !== undefined}
@@ -93,7 +109,7 @@ class="primary flex w-full gap-x-1" on:click={() => { abort() - importFlow.targetLayer.disableAllFilters() + filteredLayer.disableAllFilters() }} > @@ -103,7 +119,7 @@ class="flex w-full gap-x-1" on:click={() => { abort() - state.guistate.openFilterView(importFlow.targetLayer.layerDef) + state.guistate.openFilterView(filteredLayer.layerDef) }} > diff --git a/src/UI/Popup/ImportButtons/ImportFlow.ts b/src/UI/Popup/ImportButtons/ImportFlow.ts index 50943d8af3..22a54eed7c 100644 --- a/src/UI/Popup/ImportButtons/ImportFlow.ts +++ b/src/UI/Popup/ImportButtons/ImportFlow.ts @@ -6,7 +6,6 @@ import TagApplyButton from "../TagApplyButton" import { PointImportFlowArguments } from "./PointImportFlowState" import { Translation } from "../../i18n/Translation" import Translations from "../../i18n/Translations" -import { OsmConnection } from "../../../Logic/Osm/OsmConnection" import FilteredLayer from "../../../Models/FilteredLayer" import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" import { LayerConfigJson } from "../../../Models/ThemeConfig/Json/LayerConfigJson" @@ -25,7 +24,7 @@ export class ImportFlowUtils { public static readonly conflationLayer = new LayerConfig( conflation_json, "all_known_layers", - true + true, ) public static readonly documentationGeneral = `\n\n\nNote that the contributor must zoom to at least zoomlevel 18 to be able to use this functionality. @@ -67,7 +66,7 @@ ${Utils.special_visualizations_importRequirementDocs} */ public static getTagsToApply( originalFeatureTags: UIEventSource, - args: { tags: string } + args: { tags: string }, ): Store { if (originalFeatureTags === undefined) { return undefined @@ -83,9 +82,9 @@ ${Utils.special_visualizations_importRequirementDocs} const items: string = originalFeatureTags.data[tags] console.debug( "The import button is using tags from properties[" + - tags + - "] of this object, namely ", - items + tags + + "] of this object, namely ", + items, ) if (items.startsWith("{")) { @@ -108,13 +107,12 @@ ${Utils.special_visualizations_importRequirementDocs} * - targetLayer * * Others (e.g.: snapOnto-layers) are not to be handled here - * @param argsRaw */ - public static getLayerDependencies(argsRaw: string[], argSpec?) { + public static getLayerDependencies(argsRaw: string[], argSpec?): string[] { const args: ImportFlowArguments = ( Utils.ParseVisArgs(argSpec ?? ImportFlowUtils.generalArguments, argsRaw) ) - return [args.targetLayer] + return args.targetLayer.split(" ") } public static getLayerDependenciesWithSnapOnto( @@ -122,7 +120,7 @@ ${Utils.special_visualizations_importRequirementDocs} name: string defaultValue?: string }[], - argsRaw: string[] + argsRaw: string[], ): string[] { const deps = ImportFlowUtils.getLayerDependencies(argsRaw, argSpec) const argsParsed: PointImportFlowArguments = Utils.ParseVisArgs(argSpec, argsRaw) @@ -130,30 +128,6 @@ ${Utils.special_visualizations_importRequirementDocs} deps.push(...snapOntoLayers) return deps } - - public static buildTagSpec( - args: ImportFlowArguments, - tagSource: Store> - ): Store { - let tagSpec = args.tags - return tagSource.mapD((tags) => { - if ( - tagSpec.indexOf(" ") < 0 && - tagSpec.indexOf(";") < 0 && - tags[args.tags] !== undefined - ) { - // This is probably a key - tagSpec = tags[args.tags] - console.debug( - "The import button is using tags from properties[" + - args.tags + - "] of this object, namely ", - tagSpec - ) - } - return tagSpec - }) - } } /** @@ -164,7 +138,7 @@ ${Utils.special_visualizations_importRequirementDocs} export default abstract class ImportFlow { public readonly state: SpecialVisualizationState public readonly args: ArgT - public readonly targetLayer: FilteredLayer + public readonly targetLayer: FilteredLayer[] public readonly tagsToApply: Store protected readonly _originalFeatureTags: UIEventSource> @@ -172,13 +146,19 @@ export default abstract class ImportFlow { state: SpecialVisualizationState, args: ArgT, tagsToApply: Store, - originalTags: UIEventSource> + originalTags: UIEventSource>, ) { this.state = state this.args = args this.tagsToApply = tagsToApply this._originalFeatureTags = originalTags - this.targetLayer = state.layerState.filteredLayers.get(args.targetLayer) + this.targetLayer = args.targetLayer.split(" ").map(tl => { + let found = state.layerState.filteredLayers.get(tl) + if (!found) { + throw "Layer " + tl + " not found" + } + return found + }) } /** @@ -218,7 +198,7 @@ export default abstract class ImportFlow { return undefined }, - [state.mapProperties.zoom, state.dataIsLoading, this._originalFeatureTags] + [state.mapProperties.zoom, state.dataIsLoading, this._originalFeatureTags], ) } } diff --git a/src/UI/Popup/ImportButtons/PointImportButtonViz.ts b/src/UI/Popup/ImportButtons/PointImportButtonViz.ts index 583e5d3c32..67f92dcc8c 100644 --- a/src/UI/Popup/ImportButtons/PointImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/PointImportButtonViz.ts @@ -17,7 +17,7 @@ export class PointImportButtonViz implements SpecialVisualization { public readonly funcName: string public readonly docs: string | BaseUIElement public readonly example?: string - public readonly args: { name: string; defaultValue?: string; doc: string }[] + public readonly args: { name: string; defaultValue?: string; doc: string, split?: boolean }[] public needsUrls = [] constructor() { diff --git a/src/UI/Popup/ImportButtons/PointImportFlow.svelte b/src/UI/Popup/ImportButtons/PointImportFlow.svelte index 9063842481..e02ae27b11 100644 --- a/src/UI/Popup/ImportButtons/PointImportFlow.svelte +++ b/src/UI/Popup/ImportButtons/PointImportFlow.svelte @@ -13,7 +13,7 @@ const args = importFlow.args // The following variables are used for the map - const targetLayer: LayerConfig = state.layout.layers.find((l) => l.id === args.targetLayer) + const targetLayers: LayerConfig[] = args.targetLayer.split(" ").map(tl => state.layout.layers.find((l) => l.id === tl)) const snapToLayers: string[] | undefined = args.snap_onto_layers?.split(",")?.map((l) => l.trim()) ?? [] const maxSnapDistance: number = Number(args.max_snap_distance ?? 25) ?? 25 @@ -33,21 +33,20 @@ async function onConfirm(): Promise { const importedId = await importFlow.onConfirm(value.data, snappedTo.data) - state.selectedLayer.setData(targetLayer) state.selectedElement.setData(state.indexedFeatures.featuresById.data.get(importedId)) }
-
+
diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index d36c0eb7a9..5bfc47024a 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -3,11 +3,7 @@ import { FixedUiElement } from "./Base/FixedUiElement" import BaseUIElement from "./BaseUIElement" import Title from "./Base/Title" import Table from "./Base/Table" -import { - RenderingSpecification, - SpecialVisualization, - SpecialVisualizationState, -} from "./SpecialVisualization" +import { RenderingSpecification, SpecialVisualization, SpecialVisualizationState } from "./SpecialVisualization" import { HistogramViz } from "./Popup/HistogramViz" import { MinimapViz } from "./Popup/MinimapViz" import { ShareLinkViz } from "./Popup/ShareLinkViz" @@ -110,7 +106,7 @@ class NearbyImageVis implements SpecialVisualization { tags: UIEventSource>, args: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const isOpen = args[0] === "open" const [lon, lat] = GeoOperations.centerpointCoordinates(feature) @@ -175,7 +171,7 @@ class StealViz implements SpecialVisualization { selectedElement: otherFeature, state, layer, - }) + }), ) } if (elements.length === 1) { @@ -183,8 +179,8 @@ class StealViz implements SpecialVisualization { } return new Combine(elements).SetClass("flex flex-col") }, - [state.indexedFeatures.featuresById] - ) + [state.indexedFeatures.featuresById], + ), ) } @@ -223,7 +219,7 @@ export class QuestionViz implements SpecialVisualization { tags: UIEventSource>, args: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const labels = args[0] ?.split(";") @@ -277,17 +273,17 @@ export default class SpecialVisualizations { * templ.args[0] = "{email}" */ public static constructSpecification( - template: string, - extraMappings: SpecialVisualization[] = [] + template: string | { special: Record> & { type: string } }, + extraMappings: SpecialVisualization[] = [], ): RenderingSpecification[] { if (template === "") { return [] } - if (template["type"] !== undefined) { + if (typeof template !== "string") { console.trace( "Got a non-expanded template while constructing the specification, it still has a 'special-key':", - template + template, ) throw "Got a non-expanded template while constructing the specification" } @@ -295,20 +291,20 @@ export default class SpecialVisualizations { for (const knownSpecial of allKnownSpecials) { // Note: the '.*?' in the regex reads as 'any character, but in a non-greedy way' const matched = template.match( - new RegExp(`(.*){${knownSpecial.funcName}\\((.*?)\\)(:.*)?}(.*)`, "s") + new RegExp(`(.*){${knownSpecial.funcName}\\((.*?)\\)(:.*)?}(.*)`, "s"), ) if (matched != null) { // We found a special component that should be brought to live const partBefore = SpecialVisualizations.constructSpecification( matched[1], - extraMappings + extraMappings, ) const argument = matched[2] /* .trim() // We don't trim, as spaces might be relevant, e.g. "what is ... of {title()}"*/ const style = matched[3]?.substring(1) ?? "" const partAfter = SpecialVisualizations.constructSpecification( matched[4], - extraMappings + extraMappings, ) const args = knownSpecial.args.map((arg) => arg.defaultValue ?? "") if (argument.length > 0) { @@ -347,31 +343,31 @@ export default class SpecialVisualizations { viz.docs, viz.args.length > 0 ? new Table( - ["name", "default", "description"], - viz.args.map((arg) => { - let defaultArg = arg.defaultValue ?? "_undefined_" - if (defaultArg == "") { - defaultArg = "_empty string_" - } - return [arg.name, defaultArg, arg.doc] - }) - ) + ["name", "default", "description"], + viz.args.map((arg) => { + let defaultArg = arg.defaultValue ?? "_undefined_" + if (defaultArg == "") { + defaultArg = "_empty string_" + } + return [arg.name, defaultArg, arg.doc] + }), + ) : undefined, new Title("Example usage of " + viz.funcName, 4), new FixedUiElement( viz.example ?? - "`{" + - viz.funcName + - "(" + - viz.args.map((arg) => arg.defaultValue).join(",") + - ")}`" + "`{" + + viz.funcName + + "(" + + viz.args.map((arg) => arg.defaultValue).join(",") + + ")}`", ).SetClass("literal-code"), ]) } public static HelpMessage() { const helpTexts = SpecialVisualizations.specialVisualizations.map((viz) => - SpecialVisualizations.DocumentationFor(viz) + SpecialVisualizations.DocumentationFor(viz), ) return new Combine([ @@ -405,10 +401,10 @@ export default class SpecialVisualizations { }, }, null, - " " - ) + " ", + ), ).SetClass("code"), - 'In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "argname": ...argvalue...}`. The args are in the `special` block; an argvalue can be a string, a translation or another value. (Refer to class `RewriteSpecial` in case of problems)', + "In other words: use `{ \"before\": ..., \"after\": ..., \"special\": {\"type\": ..., \"argname\": ...argvalue...}`. The args are in the `special` block; an argvalue can be a string, a translation or another value. (Refer to class `RewriteSpecial` in case of problems)", ]).SetClass("flex flex-col"), ...helpTexts, ]).SetClass("flex flex-col") @@ -417,20 +413,20 @@ export default class SpecialVisualizations { // noinspection JSUnusedGlobalSymbols public static renderExampleOfSpecial( state: SpecialVisualizationState, - s: SpecialVisualization + s: SpecialVisualization, ): BaseUIElement { const examples = s.structuredExamples === undefined ? [] : s.structuredExamples().map((e) => { - return s.constr( - state, - new UIEventSource>(e.feature.properties), - e.args, - e.feature, - undefined - ) - }) + return s.constr( + state, + new UIEventSource>(e.feature.properties), + e.args, + e.feature, + undefined, + ) + }) return new Combine([new Title(s.funcName), s.docs, ...examples]) } @@ -470,7 +466,7 @@ export default class SpecialVisualizations { assignTo: state.userRelatedState.language, availableLanguages: state.layout.language, preferredLanguages: state.osmConnection.userDetails.map( - (ud) => ud.languages + (ud) => ud.languages, ), }) }, @@ -495,7 +491,7 @@ export default class SpecialVisualizations { constr( state: SpecialVisualizationState, - tagSource: UIEventSource> + tagSource: UIEventSource>, ): BaseUIElement { return new VariableUiElement( tagSource @@ -505,7 +501,7 @@ export default class SpecialVisualizations { return new SplitRoadWizard(id, state) } return undefined - }) + }), ) }, }, @@ -519,7 +515,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { if (feature.geometry.type !== "Point") { return undefined @@ -542,7 +538,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { if (!layer.deletion) { return undefined @@ -570,7 +566,7 @@ export default class SpecialVisualizations { state: SpecialVisualizationState, tagSource: UIEventSource>, argument: string[], - feature: Feature + feature: Feature, ): BaseUIElement { const [lon, lat] = GeoOperations.centerpointCoordinates(feature) return new SvelteUIElement(CreateNewNote, { @@ -634,7 +630,7 @@ export default class SpecialVisualizations { .map((tags) => tags[args[0]]) .map((wikidata) => { wikidata = Utils.NoEmpty( - wikidata?.split(";")?.map((wd) => wd.trim()) ?? [] + wikidata?.split(";")?.map((wd) => wd.trim()) ?? [], )[0] const entry = Wikidata.LoadWikidataEntry(wikidata) return new VariableUiElement( @@ -644,9 +640,9 @@ export default class SpecialVisualizations { } const response = e["success"] return Translation.fromMap(response.labels) - }) + }), ) - }) + }), ), }, new MapillaryLinkVis(), @@ -678,7 +674,7 @@ export default class SpecialVisualizations { AllImageProviders.LoadImagesFor(tags, imagePrefixes), tags, state, - feature + feature, ) }, }, @@ -734,7 +730,7 @@ export default class SpecialVisualizations { { nameKey: nameKey, fallbackName, - } + }, ) return new SvelteUIElement(StarsBarIcon, { score: reviews.average, @@ -767,7 +763,7 @@ export default class SpecialVisualizations { { nameKey: nameKey, fallbackName, - } + }, ) return new SvelteUIElement(ReviewForm, { reviews, state, tags, feature, layer }) }, @@ -799,7 +795,7 @@ export default class SpecialVisualizations { { nameKey: nameKey, fallbackName, - } + }, ) return new SvelteUIElement(AllReviews, { reviews, state, tags, feature, layer }) }, @@ -857,7 +853,7 @@ export default class SpecialVisualizations { tags: UIEventSource>, args: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): SvelteUIElement { const keyToUse = args[0] const prefix = args[1] @@ -894,10 +890,10 @@ export default class SpecialVisualizations { return undefined } const allUnits: Unit[] = [].concat( - ...(state?.layout?.layers?.map((lyr) => lyr.units) ?? []) + ...(state?.layout?.layers?.map((lyr) => lyr.units) ?? []), ) const unit = allUnits.filter((unit) => - unit.isApplicableToKey(key) + unit.isApplicableToKey(key), )[0] if (unit === undefined) { return value @@ -905,7 +901,7 @@ export default class SpecialVisualizations { const getCountry = () => tagSource.data._country const [v, denom] = unit.findDenomination(value, getCountry) return unit.asHumanLongValue(v, getCountry) - }) + }), ) }, }, @@ -922,7 +918,7 @@ export default class SpecialVisualizations { new Combine([ t.downloadFeatureAsGeojson.SetClass("font-bold text-lg"), t.downloadGeoJsonHelper.SetClass("subtle"), - ]).SetClass("flex flex-col") + ]).SetClass("flex flex-col"), ) .onClick(() => { console.log("Exporting as Geojson") @@ -935,7 +931,7 @@ export default class SpecialVisualizations { title + "_mapcomplete_export.geojson", { mimetype: "application/vnd.geo+json", - } + }, ) }) .SetClass("w-full") @@ -971,7 +967,7 @@ export default class SpecialVisualizations { constr: (state) => { return new SubtleButton( Svg.delete_icon_svg().SetStyle("height: 1.5rem"), - Translations.t.general.removeLocationHistory + Translations.t.general.removeLocationHistory, ).onClick(() => { state.historicalUserLocations.features.setData([]) state.selectedElement.setData(undefined) @@ -1009,10 +1005,10 @@ export default class SpecialVisualizations { .filter((c) => c.text !== "") .map( (c, i) => - new NoteCommentElement(c, state, i, comments.length) - ) + new NoteCommentElement(c, state, i, comments.length), + ), ).SetClass("flex flex-col") - }) + }), ), }, { @@ -1053,9 +1049,9 @@ export default class SpecialVisualizations { return undefined } return new SubstitutedTranslation(title, tagsSource, state).SetClass( - "px-1" + "px-1", ) - }) + }), ), }, { @@ -1071,8 +1067,8 @@ export default class SpecialVisualizations { let challenge = Stores.FromPromise( Utils.downloadJsonCached( `${Maproulette.defaultEndpoint}/challenge/${parentId}`, - 24 * 60 * 60 * 1000 - ) + 24 * 60 * 60 * 1000, + ), ) return new VariableUiElement( @@ -1097,7 +1093,7 @@ export default class SpecialVisualizations { } else { return [title, new List(listItems)] } - }) + }), ) }, docs: "Fetches the metadata of MapRoulette campaign that this task is part of and shows those details (namely `title`, `description` and `instruction`).\n\nThis reads the property `mr_challengeId` to detect the parent campaign.", @@ -1111,15 +1107,15 @@ export default class SpecialVisualizations { "\n" + "```json\n" + "{\n" + - ' "id": "mark_duplicate",\n' + - ' "render": {\n' + - ' "special": {\n' + - ' "type": "maproulette_set_status",\n' + - ' "message": {\n' + - ' "en": "Mark as not found or false positive"\n' + + " \"id\": \"mark_duplicate\",\n" + + " \"render\": {\n" + + " \"special\": {\n" + + " \"type\": \"maproulette_set_status\",\n" + + " \"message\": {\n" + + " \"en\": \"Mark as not found or false positive\"\n" + " },\n" + - ' "status": "2",\n' + - ' "image": "close"\n' + + " \"status\": \"2\",\n" + + " \"image\": \"close\"\n" + " }\n" + " }\n" + "}\n" + @@ -1185,8 +1181,8 @@ export default class SpecialVisualizations { const fsBboxed = new BBoxFeatureSourceForLayer(fs, bbox) return new StatisticsPanel(fsBboxed) }, - [state.mapProperties.bounds] - ) + [state.mapProperties.bounds], + ), ) }, }, @@ -1252,7 +1248,7 @@ export default class SpecialVisualizations { constr( state: SpecialVisualizationState, tagSource: UIEventSource>, - args: string[] + args: string[], ): BaseUIElement { let [text, href, classnames, download, ariaLabel] = args if (download === "") { @@ -1269,15 +1265,14 @@ export default class SpecialVisualizations { download: Utils.SubstituteKeys(download, tags), ariaLabel: Utils.SubstituteKeys(ariaLabel, tags), newTab, - }) - ) + }), + ), ) }, }, { funcName: "multi", docs: "Given an embedded tagRendering (read only) and a key, will read the keyname as a JSON-list. Every element of this list will be considered as tags and rendered with the tagRendering", - example: "```json\n" + JSON.stringify( @@ -1293,7 +1288,7 @@ export default class SpecialVisualizations { }, }, null, - " " + " ", ) + "\n```", args: [ @@ -1313,18 +1308,28 @@ export default class SpecialVisualizations { const translation = new Translation({ "*": tr }) return new VariableUiElement( featureTags.map((tags) => { - const properties: object[] = JSON.parse(tags[key]) - const elements = [] - for (const property of properties) { - const subsTr = new SubstitutedTranslation( - translation, - new UIEventSource(property), - state - ) - elements.push(subsTr) + try { + const data = tags[key] + const properties: object[] = typeof data === "string" ? JSON.parse(tags[key]) : data + const elements = [] + for (const property of properties) { + const subsTr = new SubstitutedTranslation( + translation, + new UIEventSource(property), + state, + ) + elements.push(subsTr) + } + return new List(elements) + } catch (e) { + console.log("Something went wrong while generating the elements for a multi", { + e, + tags, + key, + loaded: tags[key], + }) } - return new List(elements) - }) + }), ) }, }, @@ -1344,7 +1349,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { return new VariableUiElement( tagSource.map((tags) => { @@ -1356,7 +1361,7 @@ export default class SpecialVisualizations { console.error("Cannot create a translation for", v, "due to", e) return JSON.stringify(v) } - }) + }), ) }, }, @@ -1376,7 +1381,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const key = argument[0] const validator = new FediverseValidator() @@ -1386,14 +1391,14 @@ export default class SpecialVisualizations { .map((fediAccount) => { fediAccount = validator.reformat(fediAccount) const [_, username, host] = fediAccount.match( - FediverseValidator.usernameAtServer + FediverseValidator.usernameAtServer, ) return new SvelteUIElement(Link, { text: fediAccount, url: "https://" + host + "/@" + username, newTab: true, }) - }) + }), ) }, }, @@ -1413,7 +1418,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, args: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { return new FixedUiElement("{" + args[0] + "}") }, @@ -1434,7 +1439,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const key = argument[0] ?? "value" return new VariableUiElement( @@ -1452,12 +1457,12 @@ export default class SpecialVisualizations { } catch (e) { return new FixedUiElement( "Could not parse this tag: " + - JSON.stringify(value) + - " due to " + - e + JSON.stringify(value) + + " due to " + + e, ).SetClass("alert") } - }) + }), ) }, }, @@ -1478,7 +1483,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const giggityUrl = argument[0] return new SvelteUIElement(Giggity, { tags: tagSource, state, giggityUrl }) @@ -1494,12 +1499,12 @@ export default class SpecialVisualizations { _: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const tags = (( state )).geolocation.currentUserLocation.features.map( - (features) => features[0]?.properties + (features) => features[0]?.properties, ) return new Combine([ new SvelteUIElement(OrientationDebugPanel, {}), @@ -1521,7 +1526,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { return new SvelteUIElement(MarkAsFavourite, { tags: tagSource, @@ -1541,7 +1546,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { return new SvelteUIElement(MarkAsFavouriteMini, { tags: tagSource, @@ -1561,7 +1566,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { return new SvelteUIElement(DirectionIndicator, { state, feature }) }, @@ -1576,7 +1581,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, argument: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { return new VariableUiElement( tagSource @@ -1598,9 +1603,9 @@ export default class SpecialVisualizations { `${window.location.protocol}//${window.location.host}${window.location.pathname}?${layout}lat=${lat}&lon=${lon}&z=15` + `#${id}` return new Img(new Qr(url).toImageElement(75)).SetStyle( - "width: 75px" + "width: 75px", ) - }) + }), ) }, }, @@ -1620,7 +1625,7 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, args: string[], feature: Feature, - layer: LayerConfig + layer: LayerConfig, ): BaseUIElement { const key = args[0] === "" ? "_direction:centerpoint" : args[0] return new VariableUiElement( @@ -1631,41 +1636,55 @@ export default class SpecialVisualizations { }) .mapD((value) => { const dir = GeoOperations.bearingToHuman( - GeoOperations.parseBearing(value) + GeoOperations.parseBearing(value), ) console.log("Human dir", dir) return Translations.t.general.visualFeedback.directionsAbsolute[dir] - }) + }), ) }, }, { funcName: "compare_data", needsUrls: (args) => args[1].split(";"), - args:[ + args: [ { name: "url", required: true, - doc: "The attribute containing the url where to fetch more data" + doc: "The attribute containing the url where to fetch more data", }, { - name:"host", - required:true, - doc: "The domain name(s) where data might be fetched from - this is needed to set the CSP. A domain must include 'https', e.g. 'https://example.com'. For multiple domains, separate them with ';'. If you don't know the possible domains, use '*'. " + name: "host", + required: true, + doc: "The domain name(s) where data might be fetched from - this is needed to set the CSP. A domain must include 'https', e.g. 'https://example.com'. For multiple domains, separate them with ';'. If you don't know the possible domains, use '*'. ", }, { name: "postprocessing", required: false, - doc: "Apply some postprocessing. Currently, only 'velopark' is allowed as value" + doc: "Apply some postprocessing. Currently, only 'velopark' is allowed as value", + }, + { + name:"readonly", + required: false, + doc: "If 'yes', will not show 'apply'-buttons" } ], docs: "Gives an interactive element which shows a tag comparison between the OSM-object and the upstream object. This allows to copy some or all tags into OSM", constr(state: SpecialVisualizationState, tagSource: UIEventSource>, args: string[], feature: Feature, layer: LayerConfig): BaseUIElement { const url = args[0] const postprocessVelopark = args[2] === "velopark" - return new SvelteUIElement(ComparisonTool, {url, postprocessVelopark, state, tags: tagSource, layer, feature}) - } - } + const readonly = args[3] === "yes" + return new SvelteUIElement(ComparisonTool, { + url, + postprocessVelopark, + state, + tags: tagSource, + layer, + feature, + readonly + }) + }, + }, ] specialVisualizations.push(new AutoApplyButton(specialVisualizations)) @@ -1677,7 +1696,7 @@ export default class SpecialVisualizations { throw ( "Invalid special visualisation found: funcName is undefined for " + invalid.map((sp) => sp.i).join(", ") + - '. Did you perhaps type \n funcName: "funcname" // type declaration uses COLON\ninstead of:\n funcName = "funcName" // value definition uses EQUAL' + ". Did you perhaps type \n funcName: \"funcname\" // type declaration uses COLON\ninstead of:\n funcName = \"funcName\" // value definition uses EQUAL" ) }