From 9ec625302b12cffff0fde62d8db03739d4ac2e49 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Fri, 26 Jul 2024 18:14:17 +0200 Subject: [PATCH] Add 'preset_description' special visualisation, use in ghostbikes --- assets/layers/ghost_bike/ghost_bike.json | 17 +- src/UI/SpecialVisualizations.ts | 467 ++++++++++++----------- 2 files changed, 261 insertions(+), 223 deletions(-) diff --git a/assets/layers/ghost_bike/ghost_bike.json b/assets/layers/ghost_bike/ghost_bike.json index 924f933a1..4718beb7e 100644 --- a/assets/layers/ghost_bike/ghost_bike.json +++ b/assets/layers/ghost_bike/ghost_bike.json @@ -125,6 +125,15 @@ "ca": "una bicicleta fantasma", "cs": "kola duchů" }, + "description": { + "en": "A ghost bike is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location.", + "nl": "Een Witte Fiets (of Spookfiets) is een aandenken aan een fietser die bij een verkeersongeval om het leven kwam. Het gaat over een witgeschilderde fiets die geplaatst werd in de buurt van het ongeval.", + "de": "Ein Geisterrad ist ein Denkmal für einen Radfahrer, der bei einem Verkehrsunfall ums Leben kam, in Form eines weißen Fahrrades, das dauerhaft in der Nähe des Unfallortes aufgestellt wird.", + "it": "Una bici fantasma è il memoriale di un ciclista che è morto in un incidente stradale e che ha la forma di una bicicletta bianca piazzata in maniera stabile vicino al luogo dell’incidente.", + "fr": "Un vélo fantôme est un monument commémoratif pour un cycliste décédé dans un accident de la route, sous la forme d'un vélo blanc placé en permanence près du lieu de l'accident.", + "ca": "Una bicicleta fantasma és un memorial per a un ciclista que va morir en un accident de trànsit, en forma de bicicleta blanca col·locada permanentment a prop del lloc de l'accident.", + "cs": "kolo duchů je památník cyklisty, který zemřel při dopravní nehodě, v podobě bílého kola umístěného trvale v blízkosti místa nehody." + }, "tags": [ "historic=memorial", "memorial=ghost_bike" @@ -135,13 +144,7 @@ { "id": "ghost-bike-explanation", "render": { - "en": "A ghost bike is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location.", - "nl": "Een Witte Fiets (of Spookfiets) is een aandenken aan een fietser die bij een verkeersongeval om het leven kwam. Het gaat over een witgeschilderde fiets die geplaatst werd in de buurt van het ongeval.", - "de": "Ein Geisterrad ist ein Denkmal für einen Radfahrer, der bei einem Verkehrsunfall ums Leben kam, in Form eines weißen Fahrrades, das dauerhaft in der Nähe des Unfallortes aufgestellt wird.", - "it": "Una bici fantasma è il memoriale di un ciclista che è morto in un incidente stradale e che ha la forma di una bicicletta bianca piazzata in maniera stabile vicino al luogo dell’incidente.", - "fr": "Un vélo fantôme est un monument commémoratif pour un cycliste décédé dans un accident de la route, sous la forme d'un vélo blanc placé en permanence près du lieu de l'accident.", - "ca": "Una bicicleta fantasma és un memorial per a un ciclista que va morir en un accident de trànsit, en forma de bicicleta blanca col·locada permanentment a prop del lloc de l'accident.", - "cs": "kolo duchů je památník cyklisty, který zemřel při dopravní nehodě, v podobě bílého kola umístěného trvale v blízkosti místa nehody." + "*": "{preset_description()}" } }, "images", diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 964ac2c71..b004f966c 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -5,7 +5,7 @@ import Title from "./Base/Title" import { RenderingSpecification, SpecialVisualization, - SpecialVisualizationState, + SpecialVisualizationState } from "./SpecialVisualization" import { HistogramViz } from "./Popup/HistogramViz" import MinimapViz from "./Popup/MinimapViz.svelte" @@ -98,6 +98,7 @@ import ArrowDownTray from "@babeard/svelte-heroicons/mini/ArrowDownTray" import Trash from "@babeard/svelte-heroicons/mini/Trash" import NothingKnown from "./Popup/NothingKnown.svelte" import { CombinedFetcher } from "../Logic/Web/NearbyImagesSearch" +import { And } from "../Logic/Tags/And" class NearbyImageVis implements SpecialVisualization { // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests @@ -105,13 +106,13 @@ class NearbyImageVis implements SpecialVisualization { { name: "mode", defaultValue: "closed", - doc: "Either `open` or `closed`. If `open`, then the image carousel will always be shown", + doc: "Either `open` or `closed`. If `open`, then the image carousel will always be shown" }, { name: "readonly", required: false, - doc: "If 'readonly', will not show the 'link'-button", - }, + doc: "If 'readonly', will not show the 'link'-button" + } ] docs = "A component showing nearby images loaded from various online services such as Mapillary. In edit mode and when used on a feature, the user can select an image to add to the feature" @@ -136,7 +137,7 @@ class NearbyImageVis implements SpecialVisualization { lat, feature, layer, - linkable: !readonly, + linkable: !readonly }) } } @@ -150,13 +151,13 @@ class StealViz implements SpecialVisualization { { name: "featureId", doc: "The key of the attribute which contains the id of the feature from which to use the tags", - required: true, + required: true }, { name: "tagRenderingId", doc: "The layer-id and tagRenderingId to render. Can be multiple value if ';'-separated (in which case every value must also contain the layerId, e.g. `layerId.tagRendering0; layerId.tagRendering1`). Note: this can cause layer injection", - required: true, - }, + required: true + } ] needsUrls = [] svelteBased = true @@ -190,7 +191,7 @@ class StealViz implements SpecialVisualization { tags: otherTags, selectedElement: otherFeature, state, - layer, + layer }) ) } @@ -225,12 +226,12 @@ export class QuestionViz implements SpecialVisualization { args = [ { name: "labels", - doc: "One or more ';'-separated labels. If these are given, only questions with these labels will be given. Use `unlabeled` for all questions that don't have an explicit label. If none given, all questions will be shown", + doc: "One or more ';'-separated labels. If these are given, only questions with these labels will be given. Use `unlabeled` for all questions that don't have an explicit label. If none given, all questions will be shown" }, { name: "blacklisted-labels", - doc: "One or more ';'-separated labels of questions which should _not_ be included", - }, + doc: "One or more ';'-separated labels of questions which should _not_ be included" + } ] svelteBased = true @@ -255,7 +256,7 @@ export class QuestionViz implements SpecialVisualization { selectedElement: feature, state, onlyForLabels: labels, - notForLabels: blacklist, + notForLabels: blacklist }).SetClass("w-full") } } @@ -278,18 +279,18 @@ export default class SpecialVisualizations { viz.docs, viz.args.length > 0 ? MarkdownUtils.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, "#### Example usage of " + viz.funcName, - "" + example + "", + "" + example + "" ].join("\n\n") } @@ -321,24 +322,24 @@ export default class SpecialVisualizations { argname: "some_arg", message: { en: "some other really long message", - nl: "een boodschap in een andere taal", + nl: "een boodschap in een andere taal" }, - other_arg_name: "more args", + other_arg_name: "more args" }, before: { en: "Some text to prefix before the special element (e.g. a title)", - nl: "Een tekst om voor het element te zetten (bv. een titel)", + nl: "Een tekst om voor het element te zetten (bv. een titel)" }, after: { - en: "Some text to put after the element, e.g. a footer", - }, - }, + en: "Some text to put after the element, e.g. a footer" + } + } }, 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") .AsMarkdown() @@ -358,9 +359,9 @@ export default class SpecialVisualizations { const [lon, lat] = GeoOperations.centerpointCoordinates(feature) return new SvelteUIElement(AddNewPoint, { state, - coordinate: { lon, lat }, + coordinate: { lon, lat } }).SetClass("w-full h-full overflow-auto") - }, + } }, { funcName: "user_profile", @@ -369,9 +370,9 @@ export default class SpecialVisualizations { docs: "A component showing information about the currently logged in user (username, profile description, profile picture + link to edit them). Mostly meant to be used in the 'user-settings'", constr(state: SpecialVisualizationState): BaseUIElement { return new SvelteUIElement(UserProfile, { - osmConnection: state.osmConnection, + osmConnection: state.osmConnection }) - }, + } }, { funcName: "language_picker", @@ -388,11 +389,11 @@ export default class SpecialVisualizations { availableLanguages: languages, preferredLanguages: state.osmConnection.userDetails.map( (ud) => ud.languages - ), + ) }) }) ) - }, + } }, { funcName: "logout", @@ -402,25 +403,25 @@ export default class SpecialVisualizations { constr(state: SpecialVisualizationState): BaseUIElement { return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection }) - }, + } }, new HistogramViz(), new StealViz(), { - funcName : "minimap", - docs :"A small map showing the selected feature.", - needsUrls : [], - args : [ + funcName: "minimap", + docs: "A small map showing the selected feature.", + needsUrls: [], + args: [ { doc: "The (maximum) zoomlevel: the target zoomlevel after fitting the entire feature. The minimap will fit the entire feature, then zoom out to this zoom level. The higher, the more zoomed in with 1 being the entire world and 19 being really close", name: "zoomlevel", - defaultValue: "18", + defaultValue: "18" }, { doc: "(Matches all resting arguments) This argument should be the key of a property of the feature. The corresponding value is interpreted as either the id or the a list of ID's. The features with these ID's will be shown on this minimap. (Note: if the key is 'id', list interpration is disabled)", name: "idKey", - defaultValue: "id", - }, + defaultValue: "id" + } ], example: "`{minimap()}`, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`", @@ -429,9 +430,8 @@ export default class SpecialVisualizations { tagSource: UIEventSource>, args: string[], feature: Feature - ): SvelteUIElement { - return new SvelteUIElement(MinimapViz, {state, args, feature, tagSource}) + return new SvelteUIElement(MinimapViz, { state, args, feature, tagSource }) } }, { @@ -453,7 +453,7 @@ export default class SpecialVisualizations { return undefined }) ) - }, + } }, { funcName: "move_button", @@ -474,9 +474,9 @@ export default class SpecialVisualizations { return new SvelteUIElement(MoveWizard, { state, featureToMove: feature, - layer, + layer }) - }, + } }, { funcName: "delete_button", @@ -498,9 +498,9 @@ export default class SpecialVisualizations { deleteConfig: layer.deletion, state, feature, - layer, + layer }).SetClass("p-0 m-0") - }, + } }, new ShareLinkViz(), new ExportAsGpxViz(), @@ -521,9 +521,9 @@ export default class SpecialVisualizations { const [lon, lat] = GeoOperations.centerpointCoordinates(feature) return new SvelteUIElement(CreateNewNote, { state, - coordinate: new UIEventSource({ lon, lat }), + coordinate: new UIEventSource({ lon, lat }) }) - }, + } }, new CloseNoteButton(), new PlantNetDetectionViz(), @@ -543,8 +543,8 @@ export default class SpecialVisualizations { { name: "keyToShowWikipediaFor", doc: "Use the wikidata entry from this key to show the wikipedia article for. Multiple keys can be given (separated by ';'), in which case the first matching value is used", - defaultValue: "wikidata;wikipedia", - }, + defaultValue: "wikidata;wikipedia" + } ], needsUrls: [...Wikidata.neededUrls, ...Wikipedia.neededUrls], @@ -557,9 +557,9 @@ export default class SpecialVisualizations { return tags[key]?.split(";")?.map((id) => id.trim()) ?? [] }) return new SvelteUIElement(WikipediaPanel, { - wikiIds, + wikiIds }) - }, + } }, { funcName: "wikidata_label", @@ -568,8 +568,8 @@ export default class SpecialVisualizations { { name: "keyToShowWikidataFor", doc: "Use the wikidata entry from this key to show the label", - defaultValue: "wikidata", - }, + defaultValue: "wikidata" + } ], needsUrls: Wikidata.neededUrls, example: @@ -593,7 +593,7 @@ export default class SpecialVisualizations { }) ) }) - ), + ) }, new MapillaryLinkVis(), new LanguageElement(), @@ -607,7 +607,7 @@ export default class SpecialVisualizations { _, __, layer: LayerConfig - ) => new SvelteUIElement(AllTagsPanel, { tags, layer }), + ) => new SvelteUIElement(AllTagsPanel, { tags, layer }) }, { funcName: "image_carousel", @@ -616,8 +616,8 @@ export default class SpecialVisualizations { { name: "image_key", defaultValue: AllImageProviders.defaultKeys.join(","), - doc: "The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated ", - }, + doc: "The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated " + } ], needsUrls: AllImageProviders.apiUrls, constr: (state, tags, args) => { @@ -630,7 +630,7 @@ export default class SpecialVisualizations { tags, state ) - }, + } }, { funcName: "image_upload", @@ -640,13 +640,13 @@ export default class SpecialVisualizations { { name: "image-key", doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)", - required: false, + required: false }, { name: "label", doc: "The text to show on the button", - required: false, - }, + required: false + } ], constr: (state, tags, args) => { const targetKey = args[0] === "" ? undefined : args[0] @@ -655,9 +655,9 @@ export default class SpecialVisualizations { tags, targetKey, labelText: args[1], - image: args[2], + image: args[2] }) - }, + } }, { funcName: "rating", @@ -667,12 +667,12 @@ export default class SpecialVisualizations { { name: "subjectKey", defaultValue: "name", - doc: "The key to use to determine the subject. If the value is specified, the subject will be tags[subjectKey] and will use this to filter the reviews.", + doc: "The key to use to determine the subject. If the value is specified, the subject will be tags[subjectKey] and will use this to filter the reviews." }, { name: "fallback", - doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value", - }, + doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value" + } ], constr: (state, tags, args, feature) => { const nameKey = args[0] ?? "name" @@ -683,14 +683,14 @@ export default class SpecialVisualizations { state.userRelatedState.mangroveIdentity, { nameKey: nameKey, - fallbackName, + fallbackName }, state.featureSwitchIsTesting ) return new SvelteUIElement(StarsBarIcon, { - score: reviews.average, + score: reviews.average }) - }, + } }, { @@ -701,12 +701,12 @@ export default class SpecialVisualizations { { name: "subjectKey", defaultValue: "name", - doc: "The key to use to determine the subject. If specified, the subject will be tags[subjectKey]", + doc: "The key to use to determine the subject. If specified, the subject will be tags[subjectKey]" }, { name: "fallback", - doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value", - }, + doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value" + } ], constr: (state, tags, args, feature, layer) => { const nameKey = args[0] ?? "name" @@ -717,12 +717,12 @@ export default class SpecialVisualizations { state.userRelatedState?.mangroveIdentity, { nameKey: nameKey, - fallbackName, + fallbackName }, state.featureSwitchIsTesting ) return new SvelteUIElement(ReviewForm, { reviews, state, tags, feature, layer }) - }, + } }, { funcName: "list_reviews", @@ -734,12 +734,12 @@ export default class SpecialVisualizations { { name: "subjectKey", defaultValue: "name", - doc: "The key to use to determine the subject. If specified, the subject will be tags[subjectKey]", + doc: "The key to use to determine the subject. If specified, the subject will be tags[subjectKey]" }, { name: "fallback", - doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value", - }, + doc: "The identifier to use, if tags[subjectKey] as specified above is not available. This is effectively a fallback value" + } ], constr: (state, tags, args, feature, layer) => { const nameKey = args[0] ?? "name" @@ -750,12 +750,12 @@ export default class SpecialVisualizations { state.userRelatedState?.mangroveIdentity, { nameKey: nameKey, - fallbackName, + fallbackName }, state.featureSwitchIsTesting ) return new SvelteUIElement(AllReviews, { reviews, state, tags, feature, layer }) - }, + } }, { funcName: "import_mangrove_key", @@ -763,8 +763,8 @@ export default class SpecialVisualizations { args: [ { name: "text", - doc: "The text that is shown on the button", - }, + doc: "The text that is shown on the button" + } ], needsUrls: [], constr( @@ -774,7 +774,7 @@ export default class SpecialVisualizations { ): BaseUIElement { const [text] = argument return new SvelteUIElement(ImportReviewIdentity, { state, text }) - }, + } }, { funcName: "opening_hours_table", @@ -783,18 +783,18 @@ export default class SpecialVisualizations { { name: "key", defaultValue: "opening_hours", - doc: "The tagkey from which the table is constructed.", + doc: "The tagkey from which the table is constructed." }, { name: "prefix", defaultValue: "", - doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__", + doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__" }, { name: "postfix", defaultValue: "", - doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__", - }, + doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__" + } ], needsUrls: [Constants.countryCoderEndpoint], example: @@ -802,7 +802,7 @@ export default class SpecialVisualizations { constr: (state, tagSource: UIEventSource, args) => { const [key, prefix, postfix] = args return new OpeningHoursVisualization(tagSource, key, prefix, postfix) - }, + } }, { funcName: "opening_hours_state", @@ -811,18 +811,18 @@ export default class SpecialVisualizations { { name: "key", defaultValue: "opening_hours", - doc: "The tagkey from which the opening hours are read.", + doc: "The tagkey from which the opening hours are read." }, { name: "prefix", defaultValue: "", - doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__", + doc: "Remove this string from the start of the value before parsing. __Note: use `&LPARENs` to indicate `(` if needed__" }, { name: "postfix", defaultValue: "", - doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__", - }, + doc: "Remove this string from the end of the value before parsing. __Note: use `&RPARENs` to indicate `)` if needed__" + } ], constr( state: SpecialVisualizationState, @@ -837,9 +837,9 @@ export default class SpecialVisualizations { keyToUse, tags, prefix, - postfix, + postfix }) - }, + } }, { funcName: "canonical", @@ -851,8 +851,8 @@ export default class SpecialVisualizations { { name: "key", doc: "The key of the tag to give the canonical text for", - required: true, - }, + required: true + } ], constr: (state, tagSource, args) => { const key = args[0] @@ -876,7 +876,7 @@ export default class SpecialVisualizations { return unit.asHumanLongValue(value, getCountry) }) ) - }, + } }, { funcName: "export_as_geojson", @@ -890,7 +890,7 @@ export default class SpecialVisualizations { new SvelteUIElement(ArrowDownTray), new Combine([ t.downloadFeatureAsGeojson.SetClass("font-bold text-lg"), - t.downloadGeoJsonHelper.SetClass("subtle"), + t.downloadGeoJsonHelper.SetClass("subtle") ]).SetClass("flex flex-col") ) .onClick(() => { @@ -903,12 +903,12 @@ export default class SpecialVisualizations { data, title + "_mapcomplete_export.geojson", { - mimetype: "application/vnd.geo+json", + mimetype: "application/vnd.geo+json" } ) }) .SetClass("w-full") - }, + } }, { funcName: "open_in_iD", @@ -918,9 +918,9 @@ export default class SpecialVisualizations { constr: (state, feature) => { return new SvelteUIElement(OpenIdEditor, { mapProperties: state.mapProperties, - objectId: feature.data.id, + objectId: feature.data.id }) - }, + } }, { funcName: "open_in_josm", @@ -930,7 +930,7 @@ export default class SpecialVisualizations { constr: (state) => { return new SvelteUIElement(OpenJosm, { state }) - }, + } }, { funcName: "clear_location_history", @@ -945,7 +945,7 @@ export default class SpecialVisualizations { state.historicalUserLocations.features.setData([]) state.selectedElement.setData(undefined) }) - }, + } }, { funcName: "visualize_note_comments", @@ -954,13 +954,13 @@ export default class SpecialVisualizations { { name: "commentsKey", doc: "The property name of the comments, which should be stringified json", - defaultValue: "comments", + defaultValue: "comments" }, { name: "start", doc: "Drop the first 'start' comments", - defaultValue: "0", - }, + defaultValue: "0" + } ], needsUrls: [Constants.osmAuthConfig.url], constr: (state, tags, args) => @@ -982,7 +982,7 @@ export default class SpecialVisualizations { ) ).SetClass("flex flex-col") }) - ), + ) }, { funcName: "add_image_to_note", @@ -991,8 +991,8 @@ export default class SpecialVisualizations { { name: "Id-key", doc: "The property name where the ID of the note to close can be found", - defaultValue: "id", - }, + defaultValue: "id" + } ], needsUrls: [Imgur.apiUrl], @@ -1001,7 +1001,7 @@ export default class SpecialVisualizations { tags = state.featureProperties.getStore(id) console.log("Id is", id) return new SvelteUIElement(UploadImage, { state, tags }) - }, + } }, { funcName: "title", @@ -1031,12 +1031,12 @@ export default class SpecialVisualizations { tags: tagsSource, state, feature, - layer, + layer }) .SetClass("px-1") .setSpan() }) - ), + ) }, { funcName: "maproulette_task", @@ -1080,7 +1080,7 @@ export default class SpecialVisualizations { }) ) }, - 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.", + 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." }, { funcName: "maproulette_set_status", @@ -1091,15 +1091,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" + @@ -1107,32 +1107,32 @@ export default class SpecialVisualizations { args: [ { name: "message", - doc: "A message to show to the user", + doc: "A message to show to the user" }, { name: "image", doc: "Image to show", - defaultValue: "confirm", + defaultValue: "confirm" }, { name: "message_confirm", - doc: "What to show when the task is closed, either by the user or was already closed.", + doc: "What to show when the task is closed, either by the user or was already closed." }, { name: "status", doc: "A statuscode to apply when the button is clicked. 1 = `close`, 2 = `false_positive`, 3 = `skip`, 4 = `deleted`, 5 = `already fixed` (on the map, e.g. for duplicates), 6 = `too hard`", - defaultValue: "1", + defaultValue: "1" }, { name: "maproulette_id", doc: "The property name containing the maproulette id", - defaultValue: "mr_taskId", + defaultValue: "mr_taskId" }, { name: "ask_feedback", doc: "If not an empty string, this will be used as question to ask some additional feedback. A text field will be added", - defaultValue: "", - }, + defaultValue: "" + } ], constr: (state, tagsSource, args) => { @@ -1142,7 +1142,7 @@ export default class SpecialVisualizations { message_closed, statusToSet, maproulette_id_key, - askFeedback, + askFeedback ] = args if (image === "") { image = "confirm" @@ -1159,9 +1159,9 @@ export default class SpecialVisualizations { message_closed, statusToSet, maproulette_id_key, - askFeedback, + askFeedback }) - }, + } }, { funcName: "statistics", @@ -1188,7 +1188,7 @@ export default class SpecialVisualizations { [state.mapProperties.bounds] ) ) - }, + } }, { funcName: "send_email", @@ -1197,29 +1197,29 @@ export default class SpecialVisualizations { { name: "to", doc: "Who to send the email to?", - required: true, + required: true }, { name: "subject", doc: "The subject of the email", - required: true, + required: true }, { name: "body", doc: "The text in the email", - required: true, + required: true }, { name: "button_text", doc: "The text shown on the button in the UI", - required: true, - }, + required: true + } ], constr(__, tags, args) { return new SvelteUIElement(SendEmail, { args, tags }) - }, + } }, { funcName: "link", @@ -1228,25 +1228,25 @@ export default class SpecialVisualizations { { name: "text", doc: "Text to be shown", - required: true, + required: true }, { name: "href", doc: "The URL to link to. Note that this will be URI-encoded before ", - required: true, + required: true }, { name: "class", - doc: "CSS-classes to add to the element", + doc: "CSS-classes to add to the element" }, { name: "download", - doc: "Expects a string which denotes the filename to download the contents of `href` into. If set, this link will act as a download-button.", + doc: "Expects a string which denotes the filename to download the contents of `href` into. If set, this link will act as a download-button." }, { name: "arialabel", - doc: "If set, this text will be used as aria-label", - }, + doc: "If set, this text will be used as aria-label" + } ], constr( @@ -1273,9 +1273,9 @@ export default class SpecialVisualizations { classnames: new ImmutableStore(classnames), download: tagSource.map((tags) => Utils.SubstituteKeys(download, tags)), ariaLabel: tagSource.map((tags) => Utils.SubstituteKeys(ariaLabel, tags)), - newTab: new ImmutableStore(newTab), + newTab: new ImmutableStore(newTab) }).setSpan() - }, + } }, { funcName: "multi", @@ -1289,10 +1289,10 @@ export default class SpecialVisualizations { type: "multi", key: "_doors_from_building_properties", tagrendering: { - en: "The building containing this feature has a door of width {entrance:width}", - }, - }, - }, + en: "The building containing this feature has a door of width {entrance:width}" + } + } + } }, null, " " @@ -1302,17 +1302,17 @@ export default class SpecialVisualizations { { name: "key", doc: "The property to read and to interpret as a list of properties", - required: true, + required: true }, { name: "tagrendering", doc: "An entire tagRenderingConfig", - required: true, + required: true }, { name: "classes", - doc: "CSS-classes to apply on every individual item. Seperated by `space`", - }, + doc: "CSS-classes to apply on every individual item. Seperated by `space`" + } ], constr( state: SpecialVisualizationState, @@ -1348,14 +1348,14 @@ export default class SpecialVisualizations { tags: new ImmutableStore(property), state, feature, - layer, + layer }).SetClass(classes) elements.push(subsTr) } return elements }) ) - }, + } }, { funcName: "translated", @@ -1365,8 +1365,8 @@ export default class SpecialVisualizations { { name: "key", doc: "The attribute to interpret as json", - defaultValue: "value", - }, + defaultValue: "value" + } ], constr( state: SpecialVisualizationState, @@ -1387,7 +1387,7 @@ export default class SpecialVisualizations { } }) ) - }, + } }, { funcName: "fediverse_link", @@ -1396,8 +1396,8 @@ export default class SpecialVisualizations { { name: "key", doc: "The attribute-name containing the link", - required: true, - }, + required: true + } ], constr( @@ -1421,13 +1421,13 @@ export default class SpecialVisualizations { const normalLink = new SvelteUIElement(Link, { text: fediAccount, href: "https://" + host + "/@" + username, - newTab: true, + newTab: true }) const loggedInContributorMastodon = state.userRelatedState?.preferencesAsTags?.data?.[ "_mastodon_link" - ] + ] console.log( "LoggedinContributorMastodon", loggedInContributorMastodon @@ -1443,12 +1443,12 @@ export default class SpecialVisualizations { new SvelteUIElement(Link, { href: homeHost + "/" + fediAccount, text: Translations.t.validation.fediverse.onYourServer, - newTab: true, - }).SetClass("button"), + newTab: true + }).SetClass("button") ]) }) ) - }, + } }, { funcName: "braced", @@ -1458,8 +1458,8 @@ export default class SpecialVisualizations { { name: "text", required: true, - doc: "The value to show", - }, + doc: "The value to show" + } ], constr( state: SpecialVisualizationState, @@ -1469,7 +1469,7 @@ export default class SpecialVisualizations { layer: LayerConfig ): BaseUIElement { return new FixedUiElement("{" + args[0] + "}") - }, + } }, { funcName: "tags", @@ -1479,8 +1479,8 @@ export default class SpecialVisualizations { { name: "key", defaultValue: "value", - doc: "The key to look for the tags", - }, + doc: "The key to look for the tags" + } ], constr( state: SpecialVisualizationState, @@ -1505,14 +1505,14 @@ 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") } }) ) - }, + } }, { funcName: "giggity", @@ -1520,8 +1520,8 @@ export default class SpecialVisualizations { { name: "giggityUrl", required: true, - doc: "The URL of the giggity-XML", - }, + doc: "The URL of the giggity-XML" + } ], docs: "Shows events that are happening based on a Giggity URL", needsUrls: (args) => args[0], @@ -1535,7 +1535,7 @@ export default class SpecialVisualizations { ): BaseUIElement { const giggityUrl = argument[0] return new SvelteUIElement(Giggity, { tags: tagSource, state, giggityUrl }) - }, + } }, { funcName: "gps_all_tags", @@ -1558,10 +1558,10 @@ export default class SpecialVisualizations { new SvelteUIElement(OrientationDebugPanel, {}), new SvelteUIElement(AllTagsPanel, { state, - tags, - }), + tags + }) ]) - }, + } }, { funcName: "favourite_status", @@ -1580,9 +1580,9 @@ export default class SpecialVisualizations { tags: tagSource, state, layer, - feature, + feature }) - }, + } }, { funcName: "favourite_icon", @@ -1600,9 +1600,9 @@ export default class SpecialVisualizations { tags: tagSource, state, layer, - feature, + feature }).SetClass("w-full h-full") - }, + } }, { funcName: "direction_indicator", @@ -1617,7 +1617,7 @@ export default class SpecialVisualizations { layer: LayerConfig ): BaseUIElement { return new SvelteUIElement(DirectionIndicator, { state, feature }) - }, + } }, { funcName: "qr_code", @@ -1666,7 +1666,7 @@ export default class SpecialVisualizations { size.setData(smallSize) } }) - }, + } }, { funcName: "direction_absolute", @@ -1675,8 +1675,8 @@ export default class SpecialVisualizations { { name: "key", doc: "The attribute containing the degrees", - defaultValue: "_direction:centerpoint", - }, + defaultValue: "_direction:centerpoint" + } ], constr( @@ -1699,7 +1699,7 @@ export default class SpecialVisualizations { return Translations.t.general.visualFeedback.directionsAbsolute[dir] }) ) - }, + } }, { funcName: "compare_data", @@ -1708,18 +1708,18 @@ export default class SpecialVisualizations { { 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 '*'. ", + 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: "readonly", required: false, - doc: "If 'yes', will not show 'apply'-buttons", - }, + 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( @@ -1739,9 +1739,9 @@ export default class SpecialVisualizations { layer, feature, readonly, - externalData, + externalData }) - }, + } }, { funcName: "login_button", @@ -1760,7 +1760,7 @@ export default class SpecialVisualizations { new SvelteUIElement(LoginButton, { osmConnection: state.osmConnection }), state.osmConnection.isLoggedIn ) - }, + } }, { funcName: "linked_data_from_website", @@ -1769,26 +1769,26 @@ export default class SpecialVisualizations { { name: "key", defaultValue: "website", - doc: "Attempt to load ld+json from the specified URL. This can be in an embedded