From be5bcd99d7cf868e81fa862444954c495bd01c22 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Fri, 15 Aug 2025 02:32:04 +0200 Subject: [PATCH] Refactoring: switch specialVis constructor to an object --- assets/layers/icons/icons.json | 4 +- assets/layers/last_click/last_click.json | 4 +- assets/layers/note/note.json | 4 +- .../osm_community_index.json | 12 +- src/Models/ThemeViewState/WithChangesState.ts | 12 +- .../ThemeViewState/WithLayoutSourceState.ts | 3 +- .../ThemeViewState/WithSpecialLayers.ts | 5 +- src/UI/Map/ShowDataLayer.ts | 5 - src/UI/Popup/AutoApplyButtonVis.ts | 18 ++- src/UI/Popup/DataExportVisualisations.ts | 20 +--- src/UI/Popup/DataVisualisations.ts | 97 +++++---------- src/UI/Popup/HistogramViz.ts | 10 +- .../ImportButtons/ConflateImportButtonViz.ts | 34 +++--- src/UI/Popup/ImportButtons/ImportFlow.ts | 9 +- .../ImportButtons/PointImportButtonViz.ts | 25 ++-- .../Popup/ImportButtons/WayImportButtonViz.ts | 30 ++--- .../Popup/LanguageElement/LanguageElement.ts | 26 ++-- src/UI/Popup/MapillaryLinkVis.ts | 12 +- src/UI/Popup/MinimapViz.svelte | 19 +-- src/UI/Popup/MultiApplyViz.ts | 14 +-- src/UI/Popup/PlantNetDetectionViz.ts | 10 +- src/UI/Popup/ShareLinkViz.ts | 18 ++- .../TagRendering/SpecialTranslation.svelte | 2 +- src/UI/Popup/UploadToOsmViz.ts | 15 +-- .../DataImportSpecialVisualisations.ts | 35 ++---- .../FavouriteVisualisations.ts | 35 +----- .../ImageVisualisations.ts | 17 +-- .../NoteVisualisations.ts | 32 ++--- .../ReviewSpecialVisualisations.ts | 32 ++--- .../SettingsVisualisations.ts | 45 +++---- src/UI/SpecialVisualisations/TagApplyViz.ts | 9 +- ...deringManipulationSpecialVisualisations.ts | 37 ++---- .../UISpecialVisualisations.ts | 113 ++++-------------- ...ebAndCommunicationSpecialVisualisations.ts | 51 +++----- src/UI/SpecialVisualization.ts | 26 ++-- src/UI/SpecialVisualizations.ts | 20 ++-- src/Utils.ts | 1 - 37 files changed, 302 insertions(+), 559 deletions(-) diff --git a/assets/layers/icons/icons.json b/assets/layers/icons/icons.json index 54ebd45d54..93e9e91ec0 100644 --- a/assets/layers/icons/icons.json +++ b/assets/layers/icons/icons.json @@ -430,10 +430,10 @@ } }, { - "id": "favourite_icon", + "condition": "_favourite=yes", "description": "Only for rendering", "icon": "circle:white;heart:red", - "condition": "_favourite=yes", + "id": "favourite_icon", "metacondition": "__showTimeSensitiveIcons!=no" }, { diff --git a/assets/layers/last_click/last_click.json b/assets/layers/last_click/last_click.json index 3185c513fb..6aaa191159 100644 --- a/assets/layers/last_click/last_click.json +++ b/assets/layers/last_click/last_click.json @@ -217,8 +217,8 @@ }, { "id": "debug", - "render": "{all_tags()}", - "metacondition": "__featureSwitchIsDebugging=true" + "metacondition": "__featureSwitchIsDebugging=true", + "render": "{all_tags()}" } ], "filter": [ diff --git a/assets/layers/note/note.json b/assets/layers/note/note.json index b1dd36f327..eedef08c68 100644 --- a/assets/layers/note/note.json +++ b/assets/layers/note/note.json @@ -114,9 +114,9 @@ "lineRendering": [], "tagRenderings": [ { + "classes": "p-0", "id": "conversation", - "render": "{visualize_note_comments()}", - "classes": "p-0" + "render": "{visualize_note_comments()}" }, { "id": "add_image", diff --git a/assets/layers/osm_community_index/osm_community_index.json b/assets/layers/osm_community_index/osm_community_index.json index 1c605ca388..150fc6ecd9 100644 --- a/assets/layers/osm_community_index/osm_community_index.json +++ b/assets/layers/osm_community_index/osm_community_index.json @@ -66,16 +66,16 @@ ], "tagRenderings": [ { - "id": "country_name", + "condition": "level=country", "description": "The name of the country", - "render": "{nameEn} {emojiFlag}", - "condition": "level=country" + "id": "country_name", + "render": "{nameEn} {emojiFlag}" }, { - "id": "community_links", + "condition": "_community_links~*", "description": "Community Links (Discord, meetups, Slack groups, IRC channels, mailing lists etc...)", - "render": "{_community_links}", - "condition": "_community_links~*" + "id": "community_links", + "render": "{_community_links}" } ], "filter": [ diff --git a/src/Models/ThemeViewState/WithChangesState.ts b/src/Models/ThemeViewState/WithChangesState.ts index a7f919648c..27c2b85f1e 100644 --- a/src/Models/ThemeViewState/WithChangesState.ts +++ b/src/Models/ThemeViewState/WithChangesState.ts @@ -21,6 +21,7 @@ import SelectedElementTagsUpdater from "../../Logic/Actors/SelectedElementTagsUp import NoElementsInViewDetector, { FeatureViewState, } from "../../Logic/Actors/NoElementsInViewDetector" +import { features } from "monaco-editor/esm/metadata" export class WithChangesState extends WithLayoutSourceState { readonly changes: Changes @@ -226,15 +227,10 @@ export class WithChangesState extends WithLayoutSourceState { metaTags: this.userRelatedState.preferencesAsTags, selectedElement: this.selectedElement, fetchStore: (id) => this.featureProperties.getStore(id), + onClick: feature => { + this.setSelectedElement(feature) + } }) - /*new ShowDataLayer(map, { - layer: fs.layer.layerDef, - features: filtered, - doShowLayer, - metaTags: this.userRelatedState.preferencesAsTags, - selectedElement: this.selectedElement, - fetchStore: (id) => this.featureProperties.getStore(id), - })*/ }) return filteringFeatureSource } diff --git a/src/Models/ThemeViewState/WithLayoutSourceState.ts b/src/Models/ThemeViewState/WithLayoutSourceState.ts index cb9ceeeac2..d09f41d965 100644 --- a/src/Models/ThemeViewState/WithLayoutSourceState.ts +++ b/src/Models/ThemeViewState/WithLayoutSourceState.ts @@ -130,7 +130,8 @@ export class WithLayoutSourceState extends WithSelectedElementState { } protected setSelectedElement(feature: Feature) { - // The given feature might be a partial one from the cache + // The given feature might be a partial one from the cache or might be a centroid point instead of the way + // We lookup a version by IDP if (feature !== undefined) { feature = this.indexedFeatures.featuresById.data?.get(feature?.properties?.id) ?? feature diff --git a/src/Models/ThemeViewState/WithSpecialLayers.ts b/src/Models/ThemeViewState/WithSpecialLayers.ts index 15cdc4cb62..ff2bb58df5 100644 --- a/src/Models/ThemeViewState/WithSpecialLayers.ts +++ b/src/Models/ThemeViewState/WithSpecialLayers.ts @@ -4,7 +4,7 @@ import FavouritesFeatureSource from "../../Logic/FeatureSource/Sources/Favourite import Constants from "../Constants" import { FeatureSource } from "../../Logic/FeatureSource/FeatureSource" import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource" -import { Feature } from "geojson" +import { Feature, Geometry } from "geojson" import { BBox } from "../../Logic/BBox" import ShowDataLayer from "../../UI/Map/ShowDataLayer" import MetaTagging from "../../Logic/MetaTagging" @@ -22,6 +22,7 @@ import { } from "../../Logic/FeatureSource/TiledFeatureSource/SummaryTileSource" import { ShowDataLayerOptions } from "../../UI/Map/ShowDataLayerOptions" import { ClusterGrouping } from "../../Logic/FeatureSource/TiledFeatureSource/ClusteringFeatureSource" +import { OsmTags } from "../OsmFeature" export class WithSpecialLayers extends WithChangesState { readonly favourites: FavouritesFeatureSource @@ -180,7 +181,7 @@ export class WithSpecialLayers extends WithChangesState { }) ) // show last click = new point/note marker - const features = new StaticFeatureSource(lastClickFiltered) + const features: StaticFeatureSource & {id: string}>> = new StaticFeatureSource(lastClickFiltered) this.featureProperties.trackFeatureSource(features) new ShowDataLayer(this.map, { features, diff --git a/src/UI/Map/ShowDataLayer.ts b/src/UI/Map/ShowDataLayer.ts index 4d80c6c926..434e705fd7 100644 --- a/src/UI/Map/ShowDataLayer.ts +++ b/src/UI/Map/ShowDataLayer.ts @@ -459,11 +459,6 @@ export default class ShowDataLayer { preprocessPoints, } = this._options let onClick = this._options.onClick - if (!onClick && selectedElement && layer.title !== undefined) { - onClick = (feature: Feature) => { - selectedElement?.setData(feature) - } - } if (drawLines !== false) { for (let i = 0; i < layer.lineRendering.length; i++) { const lineRenderingConfig = layer.lineRendering[i] diff --git a/src/UI/Popup/AutoApplyButtonVis.ts b/src/UI/Popup/AutoApplyButtonVis.ts index e00f6ef417..8257745e82 100644 --- a/src/UI/Popup/AutoApplyButtonVis.ts +++ b/src/UI/Popup/AutoApplyButtonVis.ts @@ -3,8 +3,8 @@ import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" import { Changes } from "../../Logic/Osm/Changes" import { SpecialVisualisationArg, + SpecialVisualisationParams, SpecialVisualization, - SpecialVisualizationState, SpecialVisualizationSvelte, } from "../SpecialVisualization" import { IndexedFeatureSource } from "../../Logic/FeatureSource/FeatureSource" @@ -83,15 +83,11 @@ export default class AutoApplyButtonVis extends SpecialVisualizationSvelte { 4. At last, add this component` } - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[] - ): SvelteUIElement { - const target_layer_id = argument[0] - const targetTagRendering = argument[2] - const text = argument[3] - const icon = argument[4] + constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { + const target_layer_id = args[0] + const targetTagRendering = args[2] + const text = args[3] + const icon = args[4] const options = { target_layer_id, targetTagRendering, @@ -102,7 +98,7 @@ export default class AutoApplyButtonVis extends SpecialVisualizationSvelte { const to_parse: UIEventSource = new UIEventSource(undefined) Stores.chronic(500, () => to_parse.data === undefined) .map(() => { - const applicable = tagSource.data[argument[1]] + const applicable = tags.data[args[1]] if (typeof applicable === "string") { return JSON.parse(applicable) } else { diff --git a/src/UI/Popup/DataExportVisualisations.ts b/src/UI/Popup/DataExportVisualisations.ts index 81f5f3747f..dc82a9125e 100644 --- a/src/UI/Popup/DataExportVisualisations.ts +++ b/src/UI/Popup/DataExportVisualisations.ts @@ -1,11 +1,5 @@ -import { - SpecialVisualization, - SpecialVisualizationState, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" -import { UIEventSource } from "../../Logic/UIEventSource" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationSvelte } from "../SpecialVisualization" import { Feature, LineString } from "geojson" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import Translations from "../i18n/Translations" import SvelteUIElement from "../Base/SvelteUIElement" import ExportFeatureButton from "./ExportFeatureButton.svelte" @@ -17,13 +11,7 @@ class ExportAsGpxVis extends SpecialVisualizationSvelte { args = [] needsUrls = [] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ) { + constr({ tags, feature, layer }: SpecialVisualisationParams) { if (feature.geometry.type !== "LineString") { return undefined } @@ -48,7 +36,7 @@ class ExportAsGeojsonVis extends SpecialVisualizationSvelte { docs = "Exports the selected feature as GeoJson-file" args = [] - constr(state, tags, args, feature, layer) { + constr({ tags, feature, layer }: SpecialVisualisationParams) { const t = Translations.t.general.download return new SvelteUIElement(ExportFeatureButton, { tags, @@ -64,7 +52,7 @@ class ExportAsGeojsonVis extends SpecialVisualizationSvelte { } export class DataExportVisualisations { - public static initList(): SpecialVisualization[] { + public static initList(): SpecialVisualizationSvelte[] { return [new ExportAsGpxVis(), new ExportAsGeojsonVis()] } } diff --git a/src/UI/Popup/DataVisualisations.ts b/src/UI/Popup/DataVisualisations.ts index 0a24125354..d85ef9e71d 100644 --- a/src/UI/Popup/DataVisualisations.ts +++ b/src/UI/Popup/DataVisualisations.ts @@ -1,11 +1,6 @@ -import { - SpecialVisualization, - SpecialVisualizationState, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationSvelte } from "../SpecialVisualization" import { HistogramViz } from "./HistogramViz" -import { Store, UIEventSource } from "../../Logic/UIEventSource" -import { Feature } from "geojson" +import { Store } from "../../Logic/UIEventSource" import BaseUIElement from "../BaseUIElement" import SvelteUIElement from "../Base/SvelteUIElement" import DirectionIndicator from "../Base/DirectionIndicator.svelte" @@ -20,15 +15,15 @@ import NextChangeViz from "../OpeningHours/NextChangeViz.svelte" import { Unit } from "../../Models/Unit" import AllFeaturesStatistics from "../Statistics/AllFeaturesStatistics.svelte" import { LanguageElement } from "./LanguageElement/LanguageElement" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" import { And } from "../../Logic/Tags/And" import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig" import TagRenderingEditable from "./TagRendering/TagRenderingEditable.svelte" import AllTagsPanel from "./AllTagsPanel/AllTagsPanel.svelte" import CollectionTimes from "../CollectionTimes/CollectionTimes.svelte" +import Tr from "../Base/Tr.svelte" -class DirectionIndicatorVis extends SpecialVisualization { +class DirectionIndicatorVis extends SpecialVisualizationSvelte { funcName = "direction_indicator" args = [] @@ -36,13 +31,8 @@ class DirectionIndicatorVis extends SpecialVisualization { "Gives a distance indicator and a compass pointing towards the location from your GPS-location. If clicked, centers the map on the object" group = "data" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature - ): BaseUIElement { - return new SvelteUIElement(DirectionIndicator, { state, feature }) + constr(params: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(DirectionIndicator, params) } } @@ -65,17 +55,15 @@ class DirectionAbsolute extends SpecialVisualization { ] group = "data" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[] - ): BaseUIElement { + constr({ + tags, + args, + }: SpecialVisualisationParams): BaseUIElement { const key = args[0] === "" ? "_direction:centerpoint" : args[0] const offset = args[1] === "" ? 0 : Number(args[1]) return new VariableUiElement( - tagSource - .map((tags) => { + tags.map((tags) => { console.log("Direction value", tags[key], key) return tags[key] }) @@ -117,14 +105,12 @@ class OpeningHoursTableVis extends SpecialVisualizationSvelte { example = "A normal opening hours table can be invoked with `{opening_hours_table()}`. A table for e.g. conditional access with opening hours can be `{opening_hours_table(access:conditional, no @ &LPARENS, &RPARENS)}`" - constr(state, tagSource: UIEventSource, args) { + constr({ tags, args }: SpecialVisualisationParams): SvelteUIElement { const [key, prefix, postfix] = args const openingHoursStore: Store = - OH.CreateOhObjectStore(tagSource, key, prefix, postfix) + OH.CreateOhObjectStore(tags, key, prefix, postfix) return new SvelteUIElement(OpeningHoursWithError, { - tags: tagSource, - key, - opening_hours_obj: openingHoursStore, + tags, key, opening_hours_obj: openingHoursStore, }) } } @@ -152,11 +138,7 @@ class OpeningHoursState extends SpecialVisualizationSvelte { }, ] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - args: string[] - ): SvelteUIElement { + constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { const keyToUse = args[0] const prefix = args[1] const postfix = args[2] @@ -187,10 +169,10 @@ class Canonical extends SpecialVisualization { }, ] - constr(state, tagSource, args) { + constr({ state, tags, args }: SpecialVisualisationParams) { const key = args[0] return new VariableUiElement( - tagSource + tags .map((tags) => tags[key]) .map((value) => { if (value === undefined) { @@ -203,7 +185,7 @@ class Canonical extends SpecialVisualization { if (unit === undefined) { return value } - const getCountry = () => tagSource.data._country + const getCountry = () => tags.data._country return unit.asHumanLongValue(value, getCountry) }) ) @@ -217,26 +199,23 @@ class StatisticsVis extends SpecialVisualizationSvelte { "Show general statistics about all the elements currently in view. Intended to use on the `current_view`-layer. They will be split per layer" args = [] - constr(state) { - return new SvelteUIElement(AllFeaturesStatistics, { state }) + constr(params: SpecialVisualisationParams) { + return new SvelteUIElement(AllFeaturesStatistics, params) } } -class PresetDescription extends SpecialVisualization { +class PresetDescription extends SpecialVisualizationSvelte { funcName = "preset_description" docs = "Shows the extra description from the presets of the layer, if one matches. It will pick the most specific one (e.g. if preset `A` implies `B`, but `B` does not imply `A`, it'll pick B) or the first one if no ordering can be made. Might be empty" args = [] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource> - ): BaseUIElement { - const translation = tagSource.map((tags) => { + constr({ state, tags }: SpecialVisualisationParams): SvelteUIElement { + const translation = tags.map((tags) => { const layer = state.theme.getMatchingLayer(tags) return layer?.getMostMatchingPreset(tags)?.description }) - return new VariableUiElement(translation) + return new SvelteUIElement(Tr, { t: translation }) } } @@ -245,13 +224,7 @@ class PresetTypeSelect extends SpecialVisualizationSvelte { docs = "An editable tag rendering which allows to change the type" args = [] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - selectedElement: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, tags, feature, layer }: SpecialVisualisationParams,): SvelteUIElement { const t = Translations.t.preset_type if (layer._basedOn !== layer.id) { console.warn("Trying to use the _original_ layer") @@ -277,7 +250,7 @@ class PresetTypeSelect extends SpecialVisualizationSvelte { return new SvelteUIElement(TagRenderingEditable, { config, tags, - selectedElement, + selectedElement: feature, state, layer, }) @@ -290,8 +263,8 @@ class AllTagsVis extends SpecialVisualizationSvelte { args = [] group = "data" - constr(state, tags: UIEventSource>, _, __, layer: LayerConfig) { - return new SvelteUIElement(AllTagsPanel, { tags, layer }) + constr(params: SpecialVisualisationParams) { + return new SvelteUIElement(AllTagsPanel, params) } } @@ -308,18 +281,12 @@ class PointsInTimeVis extends SpecialVisualization { }, ] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[], - feature: Feature, - layer: LayerConfig - ): BaseUIElement { + constr( {tags, args}: SpecialVisualisationParams): BaseUIElement { const key = args[0] - const points_in_time = tagSource.map((tags) => tags[key]) + const points_in_time = tags.map((tags) => tags[key]) const times = points_in_time.map( - (times) => OH.createOhObject(tagSource.data, times, tagSource.data["_country"], 1), - [tagSource] + (times) => OH.createOhObject(tags.data, times, tags.data["_country"], 1), + [tags] ) return new VariableUiElement( times.map((times) => new SvelteUIElement(CollectionTimes, { times })) diff --git a/src/UI/Popup/HistogramViz.ts b/src/UI/Popup/HistogramViz.ts index a2f3732f28..7cfffd1f4b 100644 --- a/src/UI/Popup/HistogramViz.ts +++ b/src/UI/Popup/HistogramViz.ts @@ -1,5 +1,5 @@ import { Store, UIEventSource } from "../../Logic/UIEventSource" -import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" import { Feature } from "geojson" import SvelteUIElement from "../Base/SvelteUIElement" import Histogram from "../BigComponents/Histogram.svelte" @@ -36,12 +36,8 @@ export class HistogramViz extends SpecialVisualization { ] } - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[] - ) { - const values: Store = tagSource.map((tags) => { + constr( {tags, args}: SpecialVisualisationParams): SvelteUIElement { + const values: Store = tags.map((tags) => { const value = tags[args[0]] try { if (value === "" || value === undefined) { diff --git a/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts b/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts index 9600960f60..fce251a7dc 100644 --- a/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/ConflateImportButtonViz.ts @@ -1,7 +1,11 @@ -import { SpecialVisualisationArg, SpecialVisualization, SpecialVisualizationState } from "../../SpecialVisualization" +import { + SpecialVisualisationArg, + SpecialVisualisationParams, + SpecialVisualizationSvelte, + SpecialVisualizationUtils, +} from "../../SpecialVisualization" import { UIEventSource } from "../../../Logic/UIEventSource" import { Feature, Geometry, LineString, Polygon } from "geojson" -import BaseUIElement from "../../BaseUIElement" import { ImportFlowArguments, ImportFlowUtils } from "./ImportFlow" import Translations from "../../i18n/Translations" import { Utils } from "../../../Utils" @@ -14,6 +18,7 @@ import { Changes } from "../../../Logic/Osm/Changes" import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import { OsmConnection } from "../../../Logic/Osm/OsmConnection" import { OsmTags } from "../../../Models/OsmFeature" +import Tr from "../../Base/Tr.svelte" export interface ConflateFlowArguments extends ImportFlowArguments { way_to_conflate: string @@ -22,7 +27,7 @@ export interface ConflateFlowArguments extends ImportFlowArguments { snap_onto_layers?: string } -export default class ConflateImportButtonViz extends SpecialVisualization implements AutoAction { +export default class ConflateImportButtonViz extends SpecialVisualizationSvelte implements AutoAction { supportsAutoAction: boolean = true needsUrls = [] group = "data_import" @@ -80,32 +85,25 @@ export default class ConflateImportButtonViz extends SpecialVisualization implem await state.changes.applyAction(action) } - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource, - argument: string[], - feature: Feature - ): BaseUIElement { + constr({ state, tags, args, feature }: SpecialVisualisationParams): SvelteUIElement { const canBeImported = feature.geometry.type === "LineString" || (feature.geometry.type === "Polygon" && feature.geometry.coordinates.length === 1) if (!canBeImported) { - return Translations.t.general.add.import.wrongTypeToConflate.SetClass("alert") + return new SvelteUIElement(Tr, { t: Translations.t.general.add.import.wrongTypeToConflate, cls: "alert" }) } - const args: ConflateFlowArguments = Utils.ParseVisArgs(this.args, argument) - const tagsToApply = ImportFlowUtils.getTagsToApply(tagSource, args) - const idOfWayToReplaceGeometry = tagSource.data[args.way_to_conflate] + const argsParsed: ConflateFlowArguments = SpecialVisualizationUtils.parseArgs(this.args, args) + const tagsToApply = ImportFlowUtils.getTagsToApply(>tags, argsParsed) + const idOfWayToReplaceGeometry = tags.data[argsParsed.way_to_conflate] const importFlow = new ConflateImportFlowState( state, >feature, - args, + argsParsed, tagsToApply, - tagSource, + tags, idOfWayToReplaceGeometry ) - return new SvelteUIElement(WayImportFlow, { - importFlow, - }) + return new SvelteUIElement(WayImportFlow, { importFlow }) } getLayerDependencies = (args: string[]) => diff --git a/src/UI/Popup/ImportButtons/ImportFlow.ts b/src/UI/Popup/ImportButtons/ImportFlow.ts index 3deea70ed5..4ad16da1e2 100644 --- a/src/UI/Popup/ImportButtons/ImportFlow.ts +++ b/src/UI/Popup/ImportButtons/ImportFlow.ts @@ -66,13 +66,14 @@ ${Utils.special_visualizations_importRequirementDocs} * Given the tagsstore of the point which represents the challenge, creates a new store with tags that should be applied onto the newly created point, */ public static getTagsToApply( - originalFeatureTags: UIEventSource, + originalFeatureTags: Store, args: { tags: string } ): Store { if (originalFeatureTags === undefined) { return undefined } let newTags: Store + // Listing of the keys that should be transferred const tags = args.tags if ( tags.indexOf(" ") < 0 && @@ -81,12 +82,6 @@ ${Utils.special_visualizations_importRequirementDocs} ) { // This is a property to expand... const items: string = originalFeatureTags.data[tags] - console.debug( - "The import button is using tags from properties[" + - tags + - "] of this object, namely ", - items - ) if (items.startsWith("{")) { // This is probably a JSON diff --git a/src/UI/Popup/ImportButtons/PointImportButtonViz.ts b/src/UI/Popup/ImportButtons/PointImportButtonViz.ts index 9333102682..b36724eb89 100644 --- a/src/UI/Popup/ImportButtons/PointImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/PointImportButtonViz.ts @@ -1,7 +1,5 @@ import { Feature, Point } from "geojson" -import { UIEventSource } from "../../../Logic/UIEventSource" -import { SpecialVisualization, SpecialVisualizationState } from "../../SpecialVisualization" -import BaseUIElement from "../../BaseUIElement" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../../SpecialVisualization" import SvelteUIElement from "../../Base/SvelteUIElement" import PointImportFlow from "./PointImportFlow.svelte" import { PointImportFlowArguments, PointImportFlowState } from "./PointImportFlowState" @@ -9,12 +7,14 @@ import { Utils } from "../../../Utils" import { ImportFlowUtils } from "./ImportFlow" import Translations from "../../i18n/Translations" import { GeoOperations } from "../../../Logic/GeoOperations" +import Tr from "../../Base/Tr.svelte" +import { UIEventSource } from "../../../Logic/UIEventSource" import { OsmTags } from "../../../Models/OsmFeature" /** * The wrapper to make the special visualisation for the PointImportFlow */ -export class PointImportButtonViz extends SpecialVisualization { +export class PointImportButtonViz extends SpecialVisualizationSvelte { public readonly funcName = "import_button" public readonly docs: string = "This button will copy the point from an external dataset into OpenStreetMap" + @@ -47,29 +47,24 @@ export class PointImportButtonViz extends SpecialVisualization { public needsUrls = [] group = "data_import" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource, - argument: string[], - feature: Feature - ): BaseUIElement { + constr({ state, tags, args, feature }: SpecialVisualisationParams): SvelteUIElement { const to_point_index = this.args.findIndex((arg) => arg.name === "to_point") - const summarizePointArg = argument[to_point_index].toLowerCase() + const summarizePointArg = args[to_point_index].toLowerCase() if (feature.geometry.type !== "Point") { if (summarizePointArg !== "no" && summarizePointArg !== "false") { feature = GeoOperations.centerpoint(feature) } else { - return Translations.t.general.add.import.wrongType.SetClass("alert") + return new SvelteUIElement(Tr, { t: Translations.t.general.add.import.wrongType.SetClass("alert") }) } } - const baseArgs: PointImportFlowArguments = Utils.ParseVisArgs(this.args, argument) - const tagsToApply = ImportFlowUtils.getTagsToApply(tagSource, baseArgs) + const baseArgs: PointImportFlowArguments = Utils.ParseVisArgs(this.args, args) + const tagsToApply = ImportFlowUtils.getTagsToApply(>tags, baseArgs) const importFlow = new PointImportFlowState( state, >feature, baseArgs, tagsToApply, - tagSource + tags ) return new SvelteUIElement(PointImportFlow, { diff --git a/src/UI/Popup/ImportButtons/WayImportButtonViz.ts b/src/UI/Popup/ImportButtons/WayImportButtonViz.ts index 61272532f8..91106af08f 100644 --- a/src/UI/Popup/ImportButtons/WayImportButtonViz.ts +++ b/src/UI/Popup/ImportButtons/WayImportButtonViz.ts @@ -1,10 +1,12 @@ -import { SpecialVisualization, SpecialVisualizationState } from "../../SpecialVisualization" +import { + SpecialVisualisationParams, + SpecialVisualizationSvelte, + SpecialVisualizationUtils, +} from "../../SpecialVisualization" import { AutoAction } from "../AutoApplyButtonVis" import { Feature, LineString, Polygon } from "geojson" import { UIEventSource } from "../../../Logic/UIEventSource" -import BaseUIElement from "../../BaseUIElement" import { ImportFlowUtils } from "./ImportFlow" -import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" import SvelteUIElement from "../../Base/SvelteUIElement" import WayImportFlow from "./WayImportFlow.svelte" import WayImportFlowState, { WayImportFlowArguments } from "./WayImportFlowState" @@ -13,12 +15,11 @@ import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import { Changes } from "../../../Logic/Osm/Changes" import { IndexedFeatureSource } from "../../../Logic/FeatureSource/FeatureSource" import FullNodeDatabaseSource from "../../../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" -import { OsmTags } from "../../../Models/OsmFeature" /** * Wrapper around 'WayImportFlow' to make it a special visualisation */ -export default class WayImportButtonViz extends SpecialVisualization implements AutoAction { +export default class WayImportButtonViz extends SpecialVisualizationSvelte implements AutoAction { public readonly funcName: string = "import_way_button" needsUrls = [] group = "data_import" @@ -60,25 +61,20 @@ export default class WayImportButtonViz extends SpecialVisualization implements public readonly supportsAutoAction = true public readonly needsNodeDatabase = true - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource, - argument: string[], - feature: Feature, - _: LayerConfig - ): BaseUIElement { + constr({ state, tags, args, feature }: SpecialVisualisationParams): SvelteUIElement { const geometry = feature.geometry if (!(geometry.type == "LineString" || geometry.type === "Polygon")) { - throw "Invalid type to import " + geometry.type + throw "Invalid type to import, expected linestring of polygon but got " + geometry.type } - const args: WayImportFlowArguments = Utils.ParseVisArgs(this.args, argument) - const tagsToApply = ImportFlowUtils.getTagsToApply(tagSource, args) + const parsedArgs: WayImportFlowArguments = SpecialVisualizationUtils.parseArgs(this.args, args) + console.log("Parsed args are", parsedArgs) + const tagsToApply = ImportFlowUtils.getTagsToApply(tags, parsedArgs) const importFlow = new WayImportFlowState( state, >feature, - args, + parsedArgs, tagsToApply, - tagSource + tags, ) return new SvelteUIElement(WayImportFlow, { importFlow, diff --git a/src/UI/Popup/LanguageElement/LanguageElement.ts b/src/UI/Popup/LanguageElement/LanguageElement.ts index eb4c3786af..4d95929e3c 100644 --- a/src/UI/Popup/LanguageElement/LanguageElement.ts +++ b/src/UI/Popup/LanguageElement/LanguageElement.ts @@ -1,12 +1,8 @@ -import { SpecialVisualization, SpecialVisualizationState } from "../../SpecialVisualization" -import BaseUIElement from "../../BaseUIElement" -import { UIEventSource } from "../../../Logic/UIEventSource" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../../SpecialVisualization" import SvelteUIElement from "../../Base/SvelteUIElement" -import { Feature } from "geojson" -import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" import { default as LanguageElementSvelte } from "./LanguageElement.svelte" -export class LanguageElement extends SpecialVisualization { +export class LanguageElement extends SpecialVisualizationSvelte { funcName: string = "language_chooser" needsUrls = [] @@ -66,14 +62,16 @@ export class LanguageElement extends SpecialVisualization { ` constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): BaseUIElement { + { + state, + tags, + args, + feature, + layer, + }: SpecialVisualisationParams, + ): SvelteUIElement { let [key, question, item_render, single_render, all_render, on_no_known_languages] = - argument + args if (item_render === undefined || item_render.trim() === "") { item_render = "{language()}" } @@ -101,7 +99,7 @@ export class LanguageElement extends SpecialVisualization { return new SvelteUIElement(LanguageElementSvelte, { key, - tags: tagSource, + tags, state, feature, layer, diff --git a/src/UI/Popup/MapillaryLinkVis.ts b/src/UI/Popup/MapillaryLinkVis.ts index 048e99f94c..b3000a697c 100644 --- a/src/UI/Popup/MapillaryLinkVis.ts +++ b/src/UI/Popup/MapillaryLinkVis.ts @@ -1,7 +1,6 @@ import { GeoOperations } from "../../Logic/GeoOperations" -import { ImmutableStore, UIEventSource } from "../../Logic/UIEventSource" -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" -import { Feature } from "geojson" +import { ImmutableStore } from "../../Logic/UIEventSource" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" import MapillaryLink from "../BigComponents/MapillaryLink.svelte" @@ -20,12 +19,7 @@ export class MapillaryLinkVis extends SpecialVisualizationSvelte { }, ] - public constr( - state: SpecialVisualizationState, - tagsSource: UIEventSource>, - args: string[], - feature: Feature - ): SvelteUIElement { + public constr({ args, feature }: SpecialVisualisationParams): SvelteUIElement { const [lon, lat] = GeoOperations.centerpointCoordinates(feature) let zoom = Number(args[0]) if (isNaN(zoom)) { diff --git a/src/UI/Popup/MinimapViz.svelte b/src/UI/Popup/MinimapViz.svelte index e91ada4942..25b95242fb 100644 --- a/src/UI/Popup/MinimapViz.svelte +++ b/src/UI/Popup/MinimapViz.svelte @@ -1,6 +1,6 @@ diff --git a/src/UI/Popup/MultiApplyViz.ts b/src/UI/Popup/MultiApplyViz.ts index c9b0208229..a44ef8c243 100644 --- a/src/UI/Popup/MultiApplyViz.ts +++ b/src/UI/Popup/MultiApplyViz.ts @@ -1,6 +1,6 @@ -import { Store, UIEventSource } from "../../Logic/UIEventSource" +import { Store } from "../../Logic/UIEventSource" import { MultiApplyParams } from "./MultiApply" -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" import MultiApplyButton from "./MultiApplyButton.svelte" @@ -36,17 +36,13 @@ export class MultiApplyViz extends SpecialVisualizationSvelte { example = "{multi_apply(_features_with_the_same_name_within_100m, name:etymology:wikidata;name:etymology, Apply etymology information on all nearby objects with the same name)}" - constr( - state: SpecialVisualizationState, - tagsSource: UIEventSource>, - args: string[] - ): SvelteUIElement { + constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { const featureIdsKey = args[0] const keysToApply = args[1].split(";") const text = args[2] const autoapply = args[3]?.toLowerCase() === "true" const overwrite = args[4]?.toLowerCase() === "true" - const featureIds: Store = tagsSource.map((tags) => { + const featureIds: Store = tags.map((tags) => { const ids = tags[featureIdsKey] try { if (ids === undefined) { @@ -71,7 +67,7 @@ export class MultiApplyViz extends SpecialVisualizationSvelte { text, autoapply, overwrite, - tagsSource, + tagsSource: tags, state, } return new SvelteUIElement(MultiApplyButton, { params }) diff --git a/src/UI/Popup/PlantNetDetectionViz.ts b/src/UI/Popup/PlantNetDetectionViz.ts index 09dc5b9f4e..1b2f2f697d 100644 --- a/src/UI/Popup/PlantNetDetectionViz.ts +++ b/src/UI/Popup/PlantNetDetectionViz.ts @@ -1,11 +1,11 @@ -import { Store, UIEventSource } from "../../Logic/UIEventSource" +import { Store } from "../../Logic/UIEventSource" import { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" import Wikidata from "../../Logic/Web/Wikidata" import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction" import { And } from "../../Logic/Tags/And" import { Tag } from "../../Logic/Tags/Tag" import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders" -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" import PlantNet from "../PlantNet/PlantNet.svelte" import { default as PlantNetCode } from "../../Logic/Web/PlantNet" @@ -37,11 +37,7 @@ export class PlantNetDetectionViz extends SpecialVisualizationSvelte { }, ] - public constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - args: string[] - ): SvelteUIElement { + public constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { let imagePrefixes: string[] = undefined if (args.length > 0) { imagePrefixes = [].concat(...args.map((a) => a.split(","))) diff --git a/src/UI/Popup/ShareLinkViz.ts b/src/UI/Popup/ShareLinkViz.ts index e97ce55ddb..15e602ec8e 100644 --- a/src/UI/Popup/ShareLinkViz.ts +++ b/src/UI/Popup/ShareLinkViz.ts @@ -1,6 +1,5 @@ -import { UIEventSource } from "../../Logic/UIEventSource" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" import ShareButton from "../Base/ShareButton.svelte" @@ -23,20 +22,19 @@ export class ShareLinkViz extends SpecialVisualizationSvelte { ] needsUrls = [] - public constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[] + public constr({ + state, + tags, + args}:SpecialVisualisationParams ) { const text = args[1] const generateShareData = () => { const title = state?.theme?.title?.txt ?? "MapComplete" - - const matchingLayer: LayerConfig = state?.theme?.getMatchingLayer(tagSource?.data) + const matchingLayer: LayerConfig = state?.theme?.getMatchingLayer(tags?.data) let name = - matchingLayer?.title?.GetRenderValue(tagSource.data)?.Subs(tagSource.data)?.txt ?? - tagSource.data?.name ?? + matchingLayer?.title?.GetRenderValue(tags.data)?.Subs(tags.data)?.txt ?? + tags.data?.name ?? "POI" if (name) { name = `${name} (${title})` diff --git a/src/UI/Popup/TagRendering/SpecialTranslation.svelte b/src/UI/Popup/TagRendering/SpecialTranslation.svelte index a9d5eff003..9686f3ff9f 100644 --- a/src/UI/Popup/TagRendering/SpecialTranslation.svelte +++ b/src/UI/Popup/TagRendering/SpecialTranslation.svelte @@ -51,7 +51,7 @@ { try { return specpart.func - .constr(state, tags, specpart.args, feature, layer) + .constr({state, tags, args : specpart.args, feature, layer}) ?.SetClass(specpart.style) } catch (e) { console.error( diff --git a/src/UI/Popup/UploadToOsmViz.ts b/src/UI/Popup/UploadToOsmViz.ts index ebabf95ff4..b4d9982ab6 100644 --- a/src/UI/Popup/UploadToOsmViz.ts +++ b/src/UI/Popup/UploadToOsmViz.ts @@ -1,4 +1,9 @@ -import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" +import { + SpecialVisualisationParams, + SpecialVisualization, + SpecialVisualizationState, + SpecialVisualizationSvelte, +} from "../SpecialVisualization" import { UIEventSource } from "../../Logic/UIEventSource" import { GeoOperations } from "../../Logic/GeoOperations" import Constants from "../../Models/Constants" @@ -9,18 +14,14 @@ import { ServerSourceInfo } from "../../Models/SourceOverview" /** * Wrapper around 'UploadTraceToOsmUI' */ -export class UploadToOsmViz extends SpecialVisualization { +export class UploadToOsmViz extends SpecialVisualizationSvelte { funcName = "upload_to_osm" docs = "Uploads the GPS-history as GPX to OpenStreetMap.org; clears the history afterwards. The actual feature is ignored." args = [] needsUrls: ServerSourceInfo[] = [Constants.osmAuthConfig] - constr( - state: SpecialVisualizationState, - _: UIEventSource>, - __: string[] - ) { + constr({ state }: SpecialVisualisationParams): SvelteUIElement { const locations = state.historicalUserLocations.features.data return new SvelteUIElement(UploadTraceToOsmUI, { state, diff --git a/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts b/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts index cfb771c211..df7f1ac973 100644 --- a/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/DataImportSpecialVisualisations.ts @@ -1,4 +1,5 @@ import { + SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte, @@ -79,7 +80,7 @@ class MaprouletteSetStatusVis extends SpecialVisualizationSvelte { }, ] - constr(state, tagsSource, args) { + constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { let [message, image, message_closed, statusToSet, maproulette_id_key, askFeedback] = args if (image === "") { image = "confirm" @@ -90,7 +91,7 @@ class MaprouletteSetStatusVis extends SpecialVisualizationSvelte { statusToSet = statusToSet ?? "1" return new SvelteUIElement(MaprouletteSetStatus, { state, - tags: tagsSource, + tags, message, image, message_closed, @@ -149,21 +150,15 @@ class LinkedDataFromWebsite extends SpecialVisualization { }, ] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { if (state.theme.enableMorePrivacy) { return undefined } - const key = argument[0] ?? "website" - const useProxy = argument[1] !== "no" - const readonly = argument[3] === "readonly" - const isClosed = (argument[4] ?? "yes") === "yes" + const key = args[0] ?? "website" + const useProxy = args[1] !== "no" + const readonly = args[3] === "readonly" + const isClosed = (args[4] ?? "yes") === "yes" const downloadInformation = new UIEventSource(false) const countryStore: Store = tags.mapD((tags) => tags._country) const sourceUrl: Store = tags.mapD((tags) => { @@ -245,7 +240,7 @@ class LinkedDataFromWebsite extends SpecialVisualization { } } -class CompareData extends SpecialVisualization { +class CompareData extends SpecialVisualizationSvelte { funcName = "compare_data" group = "data_import" needsUrls = (args) => args[1].split(";") @@ -270,20 +265,14 @@ class CompareData extends SpecialVisualization { 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 { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { const url = args[0] const readonly = args[3] === "yes" const externalData = UIEventSource.fromPromiseWithErr(Utils.downloadJson(url)) return new SvelteUIElement(ComparisonTool, { url, state, - tags: tagSource, + tags, layer, feature, readonly, @@ -292,7 +281,7 @@ class CompareData extends SpecialVisualization { } } export class DataImportSpecialVisualisations { - public static initList(): (SpecialVisualization & { group })[] { + public static initList(): SpecialVisualizationSvelte[] { return [ new TagApplyViz(), new PointImportButtonViz(), diff --git a/src/UI/SpecialVisualisations/FavouriteVisualisations.ts b/src/UI/SpecialVisualisations/FavouriteVisualisations.ts index 4ab3d47ab6..156076cb68 100644 --- a/src/UI/SpecialVisualisations/FavouriteVisualisations.ts +++ b/src/UI/SpecialVisualisations/FavouriteVisualisations.ts @@ -1,7 +1,4 @@ -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" -import { UIEventSource } from "../../Logic/UIEventSource" -import { Feature } from "geojson" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" import MarkAsFavourite from "../Popup/MarkAsFavourite.svelte" import MarkAsFavouriteMini from "../Popup/MarkAsFavouriteMini.svelte" @@ -14,19 +11,8 @@ class FavouriteStatus extends SpecialVisualizationSvelte { args = [] group = "favourites" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { - return new SvelteUIElement(MarkAsFavourite, { - tags: tagSource, - state, - layer, - feature, - }) + constr(params: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(MarkAsFavourite, params) } } @@ -37,19 +23,8 @@ class FavouriteIcon extends SpecialVisualizationSvelte { "A small button that allows a (logged in) contributor to mark a location as a favourite location, sized to fit a title-icon" args = [] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { - return new SvelteUIElement(MarkAsFavouriteMini, { - tags: tagSource, - state, - layer, - feature, - }) + constr(params: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(MarkAsFavouriteMini, params) } } diff --git a/src/UI/SpecialVisualisations/ImageVisualisations.ts b/src/UI/SpecialVisualisations/ImageVisualisations.ts index c8c0c47e2e..9f08719d07 100644 --- a/src/UI/SpecialVisualisations/ImageVisualisations.ts +++ b/src/UI/SpecialVisualisations/ImageVisualisations.ts @@ -1,12 +1,9 @@ -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualizationSvelte } from "../SpecialVisualization" import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders" import SvelteUIElement from "../Base/SvelteUIElement" import ImageCarousel from "../Image/ImageCarousel.svelte" import UploadImage from "../Image/UploadImage.svelte" import { CombinedFetcher } from "../../Logic/Web/NearbyImagesSearch" -import { UIEventSource } from "../../Logic/UIEventSource" -import { Feature } from "geojson" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import { GeoOperations } from "../../Logic/GeoOperations" import NearbyImages from "../Image/NearbyImages.svelte" import NearbyImagesCollapsed from "../Image/NearbyImagesCollapsed.svelte" @@ -32,13 +29,7 @@ class NearbyImageVis extends SpecialVisualizationSvelte { funcName = "nearby_images" needsUrls = CombinedFetcher.apiUrls - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - args: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { const isOpen = args[0] === "open" const readonly = args[1] === "readonly" || args[1] === "yes" const [lon, lat] = GeoOperations.centerpointCoordinates(feature) @@ -69,7 +60,7 @@ class ImageCarouselVis extends SpecialVisualizationSvelte { ] needsUrls = AllImageProviders.apiUrls - constr(state, tags, args, feature) { + constr({state, tags, args, feature}: SpecialVisualisationParams) { let imagePrefixes: string[] = undefined if (args.length > 0) { imagePrefixes = [].concat(...args.map((a) => a.split(";"))) @@ -114,7 +105,7 @@ class ImageUpload extends SpecialVisualizationSvelte { }, ] - constr(state, tags, args, feature) { + constr({state, tags, args, feature}: SpecialVisualisationParams) { const targetKey = args[0] === "" ? undefined : args[0] const noBlur = args[3]?.toLowerCase()?.trim() return new SvelteUIElement(UploadImage, { diff --git a/src/UI/SpecialVisualisations/NoteVisualisations.ts b/src/UI/SpecialVisualisations/NoteVisualisations.ts index 19f9e8f979..1b9bebf57e 100644 --- a/src/UI/SpecialVisualisations/NoteVisualisations.ts +++ b/src/UI/SpecialVisualisations/NoteVisualisations.ts @@ -1,8 +1,4 @@ -import { - SpecialVisualization, - SpecialVisualizationState, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationSvelte } from "../SpecialVisualization" import Constants from "../../Models/Constants" import { UIEventSource } from "../../Logic/UIEventSource" import { Feature } from "geojson" @@ -57,11 +53,7 @@ class CloseNoteViz extends SpecialVisualizationSvelte { ] public readonly group = "notes" - public constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - args: string[] - ): SvelteUIElement { + public constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { const { text, icon, idkey, comment, minZoom, zoomButton } = Utils.ParseVisArgs( this.args, args @@ -94,10 +86,7 @@ class AddNoteCommentViz extends SpecialVisualizationSvelte { ] public readonly group = "notes" - public constr( - state: SpecialVisualizationState, - tags: UIEventSource> - ): SvelteUIElement { + public constr({ state, tags }: SpecialVisualisationParams): SvelteUIElement { return new SvelteUIElement(AddNoteComment, { state, tags }) } } @@ -110,13 +99,8 @@ class OpenNote extends SpecialVisualizationSvelte { docs = "Creates a new map note on the given location. This options is placed in the 'last_click'-popup automatically if the 'notes'-layer is enabled" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature - ): SvelteUIElement { - const [lon, lat] = GeoOperations.centerpointCoordinates(feature) + constr({ state, feature }: SpecialVisualisationParams): SvelteUIElement { + const [lon, lat] = GeoOperations.centerpointCoordinates(feature) return new SvelteUIElement(CreateNewNote, { state, coordinate: new UIEventSource({ lon, lat }), @@ -138,7 +122,7 @@ class AddImageToNote extends SpecialVisualizationSvelte { group = "notes" needsUrls = [] - constr(state, tags, args, feature) { + constr({ state, tags, args, feature }: SpecialVisualisationParams) { const id = tags.data[args[0] ?? "id"] tags = state.featureProperties.getStore(id) return new SvelteUIElement(UploadImage, { state, tags, feature }) @@ -164,7 +148,7 @@ class VisualiseNoteComment extends SpecialVisualization { ] needsUrls = [Constants.osmAuthConfig] - constr(state, tags, args) { + constr({ state, tags, args }: SpecialVisualisationParams) { return new VariableUiElement( tags .map((tags) => tags[args[0]]) @@ -191,7 +175,7 @@ class VisualiseNoteComment extends SpecialVisualization { } export class NoteVisualisations { - public static initList(): (SpecialVisualization & { group })[] { + public static initList(): SpecialVisualization[] { return [ new AddNoteCommentViz(), new CloseNoteViz(), diff --git a/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts b/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts index cd9b31f40f..750ae06f47 100644 --- a/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/ReviewSpecialVisualisations.ts @@ -1,4 +1,5 @@ import { + SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte, @@ -16,6 +17,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import BaseUIElement from "../BaseUIElement" import Combine from "../Base/Combine" import { ServerSourceInfo } from "../../Models/SourceOverview" +import { WithUserRelatedState } from "../../Models/ThemeViewState/WithUserRelatedState" class CreateReview extends SpecialVisualizationSvelte { public static MangroveReviewInfo: ServerSourceInfo = { @@ -58,7 +60,7 @@ class CreateReview extends SpecialVisualizationSvelte { }, ] - constr(state, tags, args, feature, layer) { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams) { const nameKey = args[0] ?? "name" const fallbackName = args[1] const question = args[2] @@ -70,7 +72,7 @@ class CreateReview extends SpecialVisualizationSvelte { nameKey: nameKey, fallbackName, }, - state + state, ) return new SvelteUIElement(ReviewForm, { reviews, @@ -103,7 +105,7 @@ class ListReview extends SpecialVisualizationSvelte { }, ] - constr(state, tags, args, feature) { + constr({ state, tags, args, feature }: SpecialVisualisationParams) { const nameKey = args[0] ?? "name" const fallbackName = args[1] const reviews = FeatureReviews.construct( @@ -138,7 +140,7 @@ class Rating extends SpecialVisualizationSvelte { }, ] - constr(state, tags, args, feature) { + constr({ state, tags, args, feature }: SpecialVisualisationParams) { const nameKey = args[0] ?? "name" const fallbackName = args[1] const reviews = FeatureReviews.construct( @@ -171,12 +173,8 @@ class ImportMangroveKey extends SpecialVisualizationSvelte { }, ] - constr( - state: SpecialVisualizationState, - _: UIEventSource>, - argument: string[] - ): SvelteUIElement { - const [text] = argument + constr({ state, args }: SpecialVisualisationParams): SvelteUIElement { + const [text] = args return new SvelteUIElement(ImportReviewIdentity, { state, text }) } } @@ -207,22 +205,16 @@ class Reviews extends SpecialVisualization { ] needsUrls = [CreateReview.MangroveReviewInfo] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[], - feature: Feature, - layer: LayerConfig - ): BaseUIElement { + constr(params: SpecialVisualisationParams): BaseUIElement { return new Combine([ - new CreateReview().constr(state, tagSource, args, feature, layer), - new ListReview().constr(state, tagSource, args, feature), + new CreateReview().constr(params), + new ListReview().constr(params), ]) } } export class ReviewSpecialVisualisations { - public static initList(): (SpecialVisualization & { group })[] { + public static initList(): SpecialVisualization[] { return [ new Rating(), new CreateReview(), diff --git a/src/UI/SpecialVisualisations/SettingsVisualisations.ts b/src/UI/SpecialVisualisations/SettingsVisualisations.ts index 75cd38e002..5347b8433e 100644 --- a/src/UI/SpecialVisualisations/SettingsVisualisations.ts +++ b/src/UI/SpecialVisualisations/SettingsVisualisations.ts @@ -1,4 +1,8 @@ -import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { + SpecialVisualisationParams, + SpecialVisualizationState, + SpecialVisualizationSvelte, +} from "../SpecialVisualization" import SvelteUIElement from "../Base/SvelteUIElement" import Constants from "../../Models/Constants" import LogoutButton from "../Base/LogoutButton.svelte" @@ -25,7 +29,7 @@ class LanguagePickerVis extends SpecialVisualizationSvelte { group = "settings" docs = "A component to set the language of the user interface" - constr(state: SpecialVisualizationState): SvelteUIElement { + constr({ state }: SpecialVisualisationParams): SvelteUIElement { const availableLanguages = Locale.showLinkToWeblate.map((showTranslations) => showTranslations ? LanguageUtils.usedLanguagesSorted @@ -68,7 +72,7 @@ class GpsAllTags extends SpecialVisualizationSvelte { docs = "Shows the current tags of the GPS-representing object, used for debugging" args = [] - constr(state: SpecialVisualizationState): SvelteUIElement { + constr({ state }: SpecialVisualisationParams): SvelteUIElement { const tags = (state).geolocation.currentUserLocation.features.map( (features) => features[0]?.properties ) @@ -85,7 +89,7 @@ class StorageAllTags extends SpecialVisualizationSvelte { docs = "Shows the current state of storage" args = [] - constr(state: SpecialVisualizationState): SvelteUIElement { + constr({ state }: SpecialVisualisationParams): SvelteUIElement { const data = {} for (const key in localStorage) { data[key] = localStorage[key] @@ -117,13 +121,9 @@ export class ClearCachesVis extends SpecialVisualizationSvelte { ] group = "settings" - constr( - _: SpecialVisualizationState, - __: UIEventSource>, - argument: string[] - ): SvelteUIElement { + constr({ args }: SpecialVisualisationParams): SvelteUIElement { return new SvelteUIElement(ClearCaches, { - msg: argument[0] ?? "Clear local caches", + msg: args[0] ?? "Clear local caches", }) } } @@ -144,7 +144,7 @@ class LoginButtonVis extends SpecialVisualizationSvelte { docs = "Show a login button" group = "settings" - constr(state: SpecialVisualizationState, _, args): SvelteUIElement { + constr({ state, args }: SpecialVisualisationParams): SvelteUIElement { const force = args[0].toLowerCase() let msg = args[1] if (msg === "") { @@ -175,16 +175,10 @@ class QrLogin extends SpecialVisualizationSvelte { "A QR-code which shares the current URL and adds the login token. Anyone with this login token will have the same permissions as you currently have. Logging out from this session will also log them out" group = "settings" - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { const shared_oauth_cookie = state.osmConnection.getToken() - const sideText = argument[0] - const sideTextClass = argument[1] ?? "" + const sideText = args[0] + const sideTextClass = args[1] ?? "" return new SvelteUIElement(QrCode, { state, tags, @@ -202,8 +196,8 @@ class Logout extends SpecialVisualizationSvelte { docs = "Shows a button where the user can log out" group = "settings" - constr(state: SpecialVisualizationState): SvelteUIElement { - return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection }) + constr({ state }: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(LogoutButton,state) } } @@ -213,7 +207,7 @@ class PendingChanges extends SpecialVisualizationSvelte { group = "settings" args = [] - constr(state: SpecialVisualizationState): SvelteUIElement { + constr({ state }: SpecialVisualisationParams): SvelteUIElement { return new SvelteUIElement(PendingChangesIndicator, { state, compact: false }) } } @@ -224,8 +218,8 @@ class ClearLocationHistoryVis extends SpecialVisualizationSvelte { docs = "A button to remove the travelled track information from the device" args = [] - constr(state) { - return new SvelteUIElement(ClearGPSHistory, { state }) + constr(params: SpecialVisualisationParams) { + return new SvelteUIElement(ClearGPSHistory, params) } } @@ -233,7 +227,6 @@ export class SettingsVisualisations { public static initList(): SpecialVisualizationSvelte[] { return [ new LanguagePickerVis(), - new DisabledQuestionsVis(), new GyroscopeAllTags(), new GpsAllTags(), diff --git a/src/UI/SpecialVisualisations/TagApplyViz.ts b/src/UI/SpecialVisualisations/TagApplyViz.ts index 10ad5ec8ce..50de0b06ca 100644 --- a/src/UI/SpecialVisualisations/TagApplyViz.ts +++ b/src/UI/SpecialVisualisations/TagApplyViz.ts @@ -1,5 +1,5 @@ import { AutoAction } from "../Popup/AutoApplyButtonVis" -import { SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationState } from "../SpecialVisualization" import { Utils } from "../../Utils" import { Store, UIEventSource } from "../../Logic/UIEventSource" import { Tag } from "../../Logic/Tags/Tag" @@ -174,12 +174,7 @@ export default class TagApplyViz extends SpecialVisualization implements AutoAct } } - public constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - args: string[], - feature: Feature - ): SvelteUIElement { + public constr({ state, tags, args, feature }: SpecialVisualisationParams): SvelteUIElement { const tagsToApply: Store = TagApplyViz.generateTagsToApply(args[0], tags) const msg = args[1] let image = args[2]?.trim() diff --git a/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts b/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts index 2dee3894cc..b997417f77 100644 --- a/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/TagrenderingManipulationSpecialVisualisations.ts @@ -1,4 +1,5 @@ import { + SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte, @@ -39,7 +40,7 @@ class StealViz extends SpecialVisualization { ] needsUrls = [] - constr(state: SpecialVisualizationState, featureTags, args) { + constr({ state, tags, args }: SpecialVisualisationParams) { const [featureIdKey, layerAndtagRenderingIds] = args const tagRenderings: [LayerConfig, TagRenderingConfig][] = [] for (const layerAndTagRenderingId of layerAndtagRenderingIds.split(";")) { @@ -52,7 +53,7 @@ class StealViz extends SpecialVisualization { throw "Could not create stolen tagrenddering: tagRenderings not found" } return new VariableUiElement( - featureTags.map( + tags.map( (tags) => { const featureId = tags[featureIdKey] if (featureId === undefined) { @@ -133,18 +134,12 @@ class Multi extends SpecialVisualization { }, ] - constr( - state: SpecialVisualizationState, - featureTags: UIEventSource>, - args: string[], - feature: Feature, - layer: LayerConfig - ) { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams) { const [key, tr, classesRaw] = args const classes = classesRaw ?? "" const translation = new Translation({ "*": tr }) return new VariableUiElement( - featureTags.map((tags) => { + tags.map((tags) => { let properties: object[] if (typeof tags[key] === "string") { properties = JSON.parse(tags[key]) @@ -198,20 +193,14 @@ class Group extends SpecialVisualizationSvelte { }, ] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - selectedElement: Feature, - layer: LayerConfig - ): SvelteUIElement { - const [header, labelsStr, blacklistStr] = argument + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { + const [header, labelsStr, blacklistStr] = args const labels = labelsStr.split(";").map((x) => x.trim()) const blacklist = blacklistStr?.split(";")?.map((x) => x.trim()) ?? [] return new SvelteUIElement(GroupedView, { state, tags, - selectedElement, + selectedElement: feature, layer, header, labels, @@ -226,10 +215,10 @@ class OpenInId extends SpecialVisualizationSvelte { args = [] group = "tagrendering_manipulation" - constr(state, feature): SvelteUIElement { + constr({state, feature}: SpecialVisualisationParams): SvelteUIElement { return new SvelteUIElement(OpenIdEditor, { mapProperties: state.mapProperties, - objectId: feature.data.id, + objectId: feature.properties.id, }) } } @@ -254,12 +243,12 @@ class OpenInJosm extends SpecialVisualizationSvelte { }, ] - constr(state): SvelteUIElement { - return new SvelteUIElement(OpenJosm, { state }) + constr(params: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(OpenJosm, params) } } export default class TagrenderingManipulationSpecialVisualisations { - public static initList(): (SpecialVisualization & { group })[] { + public static initList(): SpecialVisualization[] { return [new StealViz(), new Multi(), new Group(), new OpenInId(), new OpenInJosm()] } } diff --git a/src/UI/SpecialVisualisations/UISpecialVisualisations.ts b/src/UI/SpecialVisualisations/UISpecialVisualisations.ts index cda7fe99e1..0f2a08e6c8 100644 --- a/src/UI/SpecialVisualisations/UISpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/UISpecialVisualisations.ts @@ -1,4 +1,5 @@ import { + SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationState, SpecialVisualizationSvelte, @@ -49,13 +50,7 @@ class QuestionViz extends SpecialVisualizationSvelte { ] group = "default" - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - args: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { const labels = args[0] ?.split(";") ?.map((s) => s.trim()) @@ -110,12 +105,7 @@ class Minimap extends SpecialVisualizationSvelte { example = "`{minimap()}`, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[], - feature: Feature - ): SvelteUIElement { + constr({ state, tags, args, feature, layer }: SpecialVisualisationParams): SvelteUIElement { const minzoom = Number(args[0] ?? 18) const ids = args[1]?.split(";")?.map((s) => s.trim()) ?? ["id"] const clss = args[2] @@ -125,7 +115,7 @@ class Minimap extends SpecialVisualizationSvelte { idkeys: ids, clss, feature, - tagSource, + tags, }) } } @@ -136,12 +126,9 @@ class SplitButton extends SpecialVisualizationSvelte { args = [] group = "default" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource> - ): SvelteUIElement { + constr({ state, tags }: SpecialVisualisationParams): SvelteUIElement { return new SvelteUIElement(SplitRoadWizard, { - id: tagSource.map((pr) => pr.id), + id: tags.map((pr) => pr.id), state, }) } @@ -154,13 +141,7 @@ class MoveButton extends SpecialVisualizationSvelte { args = [] group = "default" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, feature, layer }: SpecialVisualisationParams): SvelteUIElement { if (feature.geometry.type !== "Point") { return undefined } @@ -180,18 +161,12 @@ class DeleteButton extends SpecialVisualizationSvelte { args = [] group = "default" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { + constr({ state, tags, feature, layer }: SpecialVisualisationParams): SvelteUIElement { if (!layer.deletion) { return undefined } return new SvelteUIElement(DeleteWizard, { - tags: tagSource, + tags, deleteConfig: layer.deletion, state, feature, @@ -215,14 +190,9 @@ class QrCodeVis extends SpecialVisualizationSvelte { group = "default" docs = "Generates a QR-code to share the selected object" - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - feature: Feature - ): SvelteUIElement { - const sideText = argument[0] - const sideTextClass = argument[1] ?? "" + constr({ state, tags, args, feature }: SpecialVisualisationParams): SvelteUIElement { + const sideText = args[0] + const sideTextClass = args[1] ?? "" return new SvelteUIElement(QrCode, { state, tags, @@ -248,18 +218,12 @@ class IfNothingKnown extends SpecialVisualizationSvelte { docs = "Shows a 'nothing is currently known-message if there is at least one unanswered question and no known (answerable) question" - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { - const text = argument[0] - const cssClasses = argument[1] + constr({ state, tags, args, layer }: SpecialVisualisationParams): SvelteUIElement { + const text = args[0] + const cssClasses = args[1] return new SvelteUIElement(NothingKnown, { state, - tags: tagSource, + tags, layer, text, cssClasses, @@ -274,7 +238,7 @@ class AddNewPointVis extends SpecialVisualizationSvelte { args = [] group = "default" - constr(state: SpecialVisualizationState, _, __, feature: GeoJSON): SvelteUIElement { + constr({ state, feature }: SpecialVisualisationParams): SvelteUIElement { const [lon, lat] = GeoOperations.centerpointCoordinates(feature) return new SvelteUIElement(AddNewPoint, { state, @@ -297,14 +261,10 @@ class Translated extends SpecialVisualization { }, ] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[] - ): BaseUIElement { + constr({ tags, args }: SpecialVisualisationParams): BaseUIElement { return new VariableUiElement( - tagSource.map((tags) => { - const v = tags[argument[0] ?? "value"] + tags.map((tags) => { + const v = tags[args[0] ?? "value"] try { const tr = typeof v === "string" ? JSON.parse(v) : v return new Translation(tr).SetClass("font-bold") @@ -327,14 +287,8 @@ class TitleVis extends SpecialVisualizationSvelte { example = "`What is the phone number of {title()}`, which might automatically become `What is the phone number of XYZ`." - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - _: string[], - feature: Feature, - layer: LayerConfig - ) { - return new SvelteUIElement(FeatureTitle, { state, tags, feature, layer }) + constr(params: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(FeatureTitle, params) } } @@ -352,13 +306,7 @@ class BracedVis extends SpecialVisualization { }, ] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[], - feature: Feature, - layer: LayerConfig - ): BaseUIElement { + constr({ args }: SpecialVisualisationParams): BaseUIElement { return new FixedUiElement("{" + args[0] + "}") } } @@ -368,18 +316,9 @@ class CreateCopyVis extends SpecialVisualizationSvelte { funcName = "create_copy" docs = "Allow to create a copy of the current element" args = [] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement { - try { - return new SvelteUIElement(CreateCopy, { state, tags, argument, feature, layer }) - } catch (e) { - console.error(">>> failed", e) - } + + constr(params: SpecialVisualisationParams): SvelteUIElement { + return new SvelteUIElement(CreateCopy, params) } } diff --git a/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts b/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts index be8831bd05..b6a0486257 100644 --- a/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts +++ b/src/UI/SpecialVisualisations/WebAndCommunicationSpecialVisualisations.ts @@ -1,10 +1,5 @@ -import { - SpecialVisualization, - SpecialVisualizationState, - SpecialVisualizationSvelte, -} from "../SpecialVisualization" -import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" -import BaseUIElement from "../BaseUIElement" +import { SpecialVisualisationParams, SpecialVisualization, SpecialVisualizationSvelte } from "../SpecialVisualization" +import { ImmutableStore, Store } from "../../Logic/UIEventSource" import SvelteUIElement from "../Base/SvelteUIElement" import FediverseLink from "../Popup/FediverseLink.svelte" import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata" @@ -18,7 +13,7 @@ import SendEmail from "../Popup/SendEmail.svelte" import DynLink from "../Base/DynLink.svelte" import { Lists } from "../../Utils/Lists" -class FediverseLinkVis extends SpecialVisualization { +class FediverseLinkVis extends SpecialVisualizationSvelte { funcName = "fediverse_link" group = "web_and_communication" docs = "Converts a fediverse username or link into a clickable link" @@ -31,17 +26,13 @@ class FediverseLinkVis extends SpecialVisualization { }, ] - constr( - state: SpecialVisualizationState, - tags: UIEventSource>, - argument: string[] - ): BaseUIElement { - const key = argument[0] + constr({ state, tags, args }: SpecialVisualisationParams): SvelteUIElement { + const key = args[0] return new SvelteUIElement(FediverseLink, { key, tags, state }) } } -class WikipediaVis extends SpecialVisualization { +class WikipediaVis extends SpecialVisualizationSvelte { funcName = "wikipedia" group = "web_and_communication" docs = "A box showing the corresponding wikipedia article(s) - based on the **wikidata** tag." @@ -58,9 +49,9 @@ class WikipediaVis extends SpecialVisualization { example = "`{wikipedia()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the wikipedia page of whom the feature was named after. Also remember that these can be styled, e.g. `{wikipedia():max-height: 10rem}` to limit the height" - constr(_, tagsSource, args) { + constr({ tags, args }: SpecialVisualisationParams) { const keys = args[0].split(";").map((k) => k.trim()) - const wikiIds: Store = tagsSource.map((tags) => { + const wikiIds: Store = tags.map((tags) => { const key = keys.find((k) => tags[k] !== undefined && tags[k] !== "") return tags[key]?.split(";")?.map((id) => id.trim()) ?? [] }) @@ -88,8 +79,8 @@ class WikidatalabelVis extends SpecialVisualization { example = "`{wikidata_label()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the label itself" - constr(_, tagsSource, args) { - const id = tagsSource + constr({ tags, args }: SpecialVisualisationParams) { + const id = tags .map((tags) => tags[args[0]]) .map((wikidata) => { const wikidataIds = Lists.noEmpty( @@ -144,8 +135,8 @@ class SendEmailVis extends SpecialVisualizationSvelte { }, ] - constr(__, tags, args) { - return new SvelteUIElement(SendEmail, { args, tags }) + constr(params: SpecialVisualisationParams) { + return new SvelteUIElement(SendEmail, params) } } @@ -184,31 +175,27 @@ class LinkVis extends SpecialVisualizationSvelte { }, ] - constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - args: string[] - ): SvelteUIElement { + constr({ tags, args }: SpecialVisualisationParams): SvelteUIElement { let [text, href, classnames, download, ariaLabel, icon] = args if (download === "") { download = undefined } const newTab = download === undefined && !href.startsWith("#") - const textStore = tagSource.map((tags) => Utils.SubstituteKeys(text, tags)) - const hrefStore = tagSource.map((tags) => Utils.SubstituteKeys(href, tags)) + const textStore = tags.map((tags) => Utils.SubstituteKeys(text, tags)) + const hrefStore = tags.map((tags) => Utils.SubstituteKeys(href, tags)) return new SvelteUIElement(DynLink, { text: textStore, href: hrefStore, classnames: new ImmutableStore(classnames), - download: tagSource.map((tags) => Utils.SubstituteKeys(download, tags)), - ariaLabel: tagSource.map((tags) => Utils.SubstituteKeys(ariaLabel, tags)), + download: tags.map((tags) => Utils.SubstituteKeys(download, tags)), + ariaLabel: tags.map((tags) => Utils.SubstituteKeys(ariaLabel, tags)), newTab: new ImmutableStore(newTab), - icon: tagSource.map((tags) => Utils.SubstituteKeys(icon, tags)), + icon: tags.map((tags) => Utils.SubstituteKeys(icon, tags)), }) } } export class WebAndCommunicationSpecialVisualisations { - public static initList(): (SpecialVisualization & { group })[] { + public static initList(): SpecialVisualization[] { return [ new FediverseLinkVis(), new WikipediaVis(), diff --git a/src/UI/SpecialVisualization.ts b/src/UI/SpecialVisualization.ts index 6b4285bb20..012ce52aa1 100644 --- a/src/UI/SpecialVisualization.ts +++ b/src/UI/SpecialVisualization.ts @@ -98,10 +98,20 @@ export interface SpecialVisualisationArg { export class SpecialVisualizationUtils { + static parseArgs(specs: { name: string; defaultValue?: string }[], args: string[]){ + return Utils.ParseVisArgs(specs, args) + } } +export interface SpecialVisualisationParams { + state: SpecialVisualizationState + tags: UIEventSource> + args: string[] + feature: Feature + layer: LayerConfig +} export abstract class SpecialVisualization { readonly funcName: string @@ -128,23 +138,11 @@ export abstract class SpecialVisualization { structuredExamples?(): { feature: Feature>; args: string[] }[] - abstract constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): BaseUIElement + abstract constr(options: SpecialVisualisationParams): BaseUIElement } export abstract class SpecialVisualizationSvelte extends SpecialVisualization { - abstract constr( - state: SpecialVisualizationState, - tagSource: UIEventSource>, - argument: string[], - feature: Feature, - layer: LayerConfig - ): SvelteUIElement + abstract constr(options: SpecialVisualisationParams): SvelteUIElement } export type RenderingSpecification = diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 69d93a165c..5a1416e1e3 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -1,4 +1,4 @@ -import { RenderingSpecification, SpecialVisualization } from "./SpecialVisualization" +import { RenderingSpecification, SpecialVisualization, SpecialVisualizationSvelte } from "./SpecialVisualization" import { UploadToOsmViz } from "./Popup/UploadToOsmViz" import { MultiApplyViz } from "./Popup/MultiApplyViz" import AutoApplyButtonVis from "./Popup/AutoApplyButtonVis" @@ -176,22 +176,26 @@ export default class SpecialVisualizations { } private static initList(): SpecialVisualization[] { - const specialVisualizations: SpecialVisualization[] = [ + const specialVisualizationsSv: SpecialVisualizationSvelte[] = [ ...ImageVisualisations.initList(), - ...NoteVisualisations.initList(), ...FavouriteVisualisations.initList(), - ...UISpecialVisualisations.initList(), ...SettingsVisualisations.initList(), - ...ReviewSpecialVisualisations.initList(), ...DataImportSpecialVisualisations.initList(), - ...TagrenderingManipulationSpecialVisualisations.initList(), - ...WebAndCommunicationSpecialVisualisations.initList(), - ...DataVisualisations.initList(), ...DataExportVisualisations.initList(), new UploadToOsmViz(), new MultiApplyViz(), ] + const specialVisualizations: SpecialVisualization[] = [ + ...NoteVisualisations.initList(), + ...UISpecialVisualisations.initList(), + ...ReviewSpecialVisualisations.initList(), + ...TagrenderingManipulationSpecialVisualisations.initList(), + ...WebAndCommunicationSpecialVisualisations.initList(), + ...DataVisualisations.initList(), + ...specialVisualizationsSv + ] + specialVisualizations.push(new AutoApplyButtonVis(specialVisualizations)) if (Utils.runningFromConsole) { diff --git a/src/Utils.ts b/src/Utils.ts index 432a2fab6a..df6d991994 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,6 +1,5 @@ import DOMPurify from "dompurify" import { Lists } from "./Utils/Lists" -import { Strings } from "./Utils/Strings" export class Utils { /**