diff --git a/UI/BigComponents/BackgroundSelector.ts b/UI/BigComponents/BackgroundSelector.ts index d13b4e9c0..f5d1a1415 100644 --- a/UI/BigComponents/BackgroundSelector.ts +++ b/UI/BigComponents/BackgroundSelector.ts @@ -25,7 +25,9 @@ export default class BackgroundSelector extends VariableUiElement { if (baseLayers.length <= 1) { return undefined; } - return new DropDown(Translations.t.general.backgroundMap.Clone(), baseLayers, State.state.backgroundLayer) + return new DropDown(Translations.t.general.backgroundMap.Clone(), baseLayers, State.state.backgroundLayer, { + select_class: 'bg-indigo-100 p-1 rounded hover:bg-indigo-200 w-full' + }) } ) ) diff --git a/UI/BigComponents/DownloadPanel.ts b/UI/BigComponents/DownloadPanel.ts index f23d98747..552f6f357 100644 --- a/UI/BigComponents/DownloadPanel.ts +++ b/UI/BigComponents/DownloadPanel.ts @@ -20,7 +20,7 @@ export class DownloadPanel extends Toggle { constructor() { const state: { featurePipeline: FeaturePipeline, - layoutToUse: UIEventSource, + layoutToUse: LayoutConfig, currentBounds: UIEventSource } = State.state diff --git a/UI/BigComponents/ImportButton.ts b/UI/BigComponents/ImportButton.ts index f62b912fd..160405264 100644 --- a/UI/BigComponents/ImportButton.ts +++ b/UI/BigComponents/ImportButton.ts @@ -31,14 +31,14 @@ export default class ImportButton extends Toggle { const button = new SubtleButton(imageUrl, message) - button.onClick(() => { + button.onClick(async () => { if (isImported.data) { return } originalTags.data["_imported"] = "yes" originalTags.ping() // will set isImported as per its definition const newElementAction = new CreateNewNodeAction(newTags.data, lat, lon) - State.state.changes.applyAction(newElementAction) + await State.state.changes.applyAction(newElementAction) State.state.selectedElement.setData(State.state.allElements.ContainingFeatures.get( newElementAction.newElementId )) diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index ca758ab80..5e8a7b46d 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -56,9 +56,9 @@ export default class SimpleAddUI extends Toggle { const presetsOverview = SimpleAddUI.CreateAllPresetsPanel(selectedPreset) - function createNewPoint(tags: any[], location: { lat: number, lon: number }, snapOntoWay?: OsmWay) { + async function createNewPoint(tags: any[], location: { lat: number, lon: number }, snapOntoWay?: OsmWay) { const newElementAction = new CreateNewNodeAction(tags, location.lat, location.lon, {snapOnto: snapOntoWay}) - State.state.changes.applyAction(newElementAction) + await State.state.changes.applyAction(newElementAction) selectedPreset.setData(undefined) isShown.setData(false) State.state.selectedElement.setData(State.state.allElements.ContainingFeatures.get( diff --git a/UI/Image/DeleteImage.ts b/UI/Image/DeleteImage.ts index fe3f2cf09..800eec53c 100644 --- a/UI/Image/DeleteImage.ts +++ b/UI/Image/DeleteImage.ts @@ -15,15 +15,15 @@ export default class DeleteImage extends Toggle { const isDeletedBadge = Translations.t.image.isDeleted.Clone() .SetClass("rounded-full p-1") .SetStyle("color:white;background:#ff8c8c") - .onClick(() => { - State.state?.changes?.applyAction(new ChangeTagAction(tags.data.id, new Tag(key, oldValue), tags.data)) + .onClick(async() => { + await State.state?.changes?.applyAction(new ChangeTagAction(tags.data.id, new Tag(key, oldValue), tags.data)) }); const deleteButton = Translations.t.image.doDelete.Clone() .SetClass("block w-full pl-4 pr-4") .SetStyle("color:white;background:#ff8c8c; border-top-left-radius:30rem; border-top-right-radius: 30rem;") - .onClick(() => { - State.state?.changes?.applyAction( + .onClick( async() => { + await State.state?.changes?.applyAction( new ChangeTagAction(tags.data.id, new Tag(key, ""), tags.data) ) }); diff --git a/UI/Image/ImageUploadFlow.ts b/UI/Image/ImageUploadFlow.ts index 432541395..4eec0b85c 100644 --- a/UI/Image/ImageUploadFlow.ts +++ b/UI/Image/ImageUploadFlow.ts @@ -29,10 +29,10 @@ export class ImageUploadFlow extends Toggle { key = imagePrefix + ":" + freeIndex; } console.log("Adding image:" + key, url); - State.state.changes + Promise.resolve(State.state.changes .applyAction(new ChangeTagAction( tags.id, new Tag(key, url), tagsSource.data - )) + ))) }) diff --git a/UI/Input/DropDown.ts b/UI/Input/DropDown.ts index 147ad0f50..fe8f8bc98 100644 --- a/UI/Input/DropDown.ts +++ b/UI/Input/DropDown.ts @@ -47,7 +47,7 @@ export class DropDown extends InputElement { } options = options ?? {} - options.select_class = options.select_class ?? 'bg-indigo-100 p-1 rounded hover:bg-indigo-200 w-full' + options.select_class = options.select_class ?? 'bg-indigo-100 p-1 rounded hover:bg-indigo-200' { diff --git a/UI/Popup/DeleteWizard.ts b/UI/Popup/DeleteWizard.ts index b81e82f47..6025ff890 100644 --- a/UI/Popup/DeleteWizard.ts +++ b/UI/Popup/DeleteWizard.ts @@ -51,14 +51,14 @@ export default class DeleteWizard extends Toggle { const confirm = new UIEventSource(false) - function softDelete(reason: string, tagsToApply: { k: string, v: string }[]) { + async function softDelete(reason: string, tagsToApply: { k: string, v: string }[]) { if (reason !== undefined) { tagsToApply.splice(0, 0, { k: "fixme", v: `A mapcomplete user marked this feature to be deleted (${reason})` }) } - (State.state?.changes ?? new Changes()) + await (State.state?.changes ?? new Changes()) .applyAction(new ChangeTagAction( id, new And(tagsToApply.map(kv => new Tag(kv.k, kv.v))), tagsSource.data )) diff --git a/UI/Popup/TagRenderingQuestion.ts b/UI/Popup/TagRenderingQuestion.ts index 5f0881d29..ea6839e14 100644 --- a/UI/Popup/TagRenderingQuestion.ts +++ b/UI/Popup/TagRenderingQuestion.ts @@ -58,10 +58,10 @@ export default class TagRenderingQuestion extends Combine { console.error("MultiAnswer failed - probably not a single option was possible", configuration) throw "MultiAnswer failed - probably not a single option was possible" } - const save = () => { + const save = async () => { const selection = inputElement.GetValue().data; if (selection) { - (State.state?.changes ?? new Changes()) + await (State.state?.changes ?? new Changes()) .applyAction(new ChangeTagAction( tags.data.id, selection, tags.data )) diff --git a/UI/ShowDataLayer/ShowDataLayer.ts b/UI/ShowDataLayer/ShowDataLayer.ts index 0d02bcd4e..ade1860ae 100644 --- a/UI/ShowDataLayer/ShowDataLayer.ts +++ b/UI/ShowDataLayer/ShowDataLayer.ts @@ -63,6 +63,7 @@ export default class ShowDataLayer { }) + State.state.selectedElement.addCallbackAndRunD(selected => { if (self._leafletMap.data === undefined) { return; @@ -76,17 +77,20 @@ export default class ShowDataLayer { if (leafletLayer.getPopup().isOpen()) { return; } - if (selected.properties.id === feature.properties.id) { - // A small sanity check to prevent infinite loops: - if (selected.geometry.type === feature.geometry.type // If a feature is rendered both as way and as point, opening one popup might trigger the other to open, which might trigger the one to open again - && feature.id === feature.properties.id // the feature might have as id 'node/-1' and as 'feature.properties.id' = 'the newly assigned id'. That is no good too - ) { - leafletLayer.openPopup() - } - if (feature.id !== feature.properties.id) { - console.trace("Not opening the popup for", feature) - } - + if (selected.properties.id !== feature.properties.id) { + return; + } + + if (feature.id !== feature.properties.id) { + // Probably a feature which has renamed + console.trace("Not opening the popup for", feature) + return; + } + if (selected.geometry.type === feature.geometry.type // If a feature is rendered both as way and as point, opening one popup might trigger the other to open, which might trigger the one to open again + && feature.id === feature.properties.id // the feature might have as id 'node/-1' and as 'feature.properties.id' = 'the newly assigned id'. That is no good too + ) { + console.log("Opening popup of feature", feature) + leafletLayer.openPopup() } }) @@ -167,8 +171,10 @@ export default class ShowDataLayer { return; } - const tagSource = feature.properties.id === undefined ? new UIEventSource(feature.properties) : - State.state.allElements.getEventSourceById(feature.properties.id) + let tagSource = State.state.allElements.getEventSourceById(feature.properties.id) + if(tagSource === undefined){ + tagSource = new UIEventSource(feature.properties) + } const clickable = !(layer.title === undefined && (layer.tagRenderings ?? []).length === 0) const style = layer.GenerateLeafletStyle(tagSource, clickable); const baseElement = style.icon.html; diff --git a/UI/ShowDataLayer/ShowTileInfo.ts b/UI/ShowDataLayer/ShowTileInfo.ts index a2fa322b6..1bb636727 100644 --- a/UI/ShowDataLayer/ShowTileInfo.ts +++ b/UI/ShowDataLayer/ShowTileInfo.ts @@ -1,32 +1,14 @@ import FeatureSource, {Tiled} from "../../Logic/FeatureSource/FeatureSource"; import {UIEventSource} from "../../Logic/UIEventSource"; -import {Utils} from "../../Utils"; import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; import ShowDataLayer from "./ShowDataLayer"; import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource"; import {GeoOperations} from "../../Logic/GeoOperations"; import {Tiles} from "../../Models/TileRange"; - +import * as clusterstyle from "../../assets/layers/cluster_style/cluster_style.json" export default class ShowTileInfo { - public static readonly styling = new LayerConfig({ - id: "tileinfo_styling", - title: { - render: "Tile {z}/{x}/{y}" - }, - tagRenderings: [ - "all_tags" - ], - source: { - osmTags: "tileId~*" - }, - color: {"render": "#3c3"}, - width: { - "render": "1" - }, - label: { - render: "
{count}
" - } - }, "tileinfo", true) + public static readonly styling = new LayerConfig( + clusterstyle, "tileinfo", true) constructor(options: { source: FeatureSource & Tiled, leafletMap: UIEventSource, layer?: LayerConfig, diff --git a/UI/ShowDataLayer/PerTileCountAggregator.ts b/UI/ShowDataLayer/TileHierarchyAggregator.ts similarity index 93% rename from UI/ShowDataLayer/PerTileCountAggregator.ts rename to UI/ShowDataLayer/TileHierarchyAggregator.ts index f313e741f..4b1685981 100644 --- a/UI/ShowDataLayer/PerTileCountAggregator.ts +++ b/UI/ShowDataLayer/TileHierarchyAggregator.ts @@ -22,7 +22,7 @@ export class TileHierarchyAggregator implements FeatureSource { public readonly name; private readonly featuresStatic = [] - private readonly featureProperties: { count: number, tileId: number }; + private readonly featureProperties: { count: string, tileId: string, id: string }; private constructor(parent: TileHierarchyAggregator, z: number, x: number, y: number) { this._parent = parent; @@ -34,8 +34,9 @@ export class TileHierarchyAggregator implements FeatureSource { this.name = "Count(" + this._tileIndex + ")" const totals = { - tileId: this._tileIndex, - count: 0 + id: ""+this._tileIndex, + tileId: ""+this._tileIndex, + count: ""+0 } this.featureProperties = totals @@ -106,7 +107,7 @@ export class TileHierarchyAggregator implements FeatureSource { if (total === 0) { this.features.setData(TileHierarchyAggregator.empty) } else { - this.featureProperties.count = total; + this.featureProperties.count = "" + total; this.features.data = this.featuresStatic this.features.ping() } @@ -145,7 +146,6 @@ export class TileHierarchyAggregator implements FeatureSource { return new TileHierarchyAggregator(undefined, 0, 0, 0) } - private visitSubTiles(f : (aggr: TileHierarchyAggregator) => boolean){ const visitFurther = f(this) if(visitFurther){ @@ -153,8 +153,9 @@ export class TileHierarchyAggregator implements FeatureSource { } } - getCountsForZoom(locationControl: UIEventSource<{ zoom : number }>, cutoff: number) : FeatureSource{ + getCountsForZoom(locationControl: UIEventSource<{ zoom : number }>, cutoff: number = 0) : FeatureSource{ const self = this + return new StaticFeatureSource( locationControl.map(loc => { const features = [] @@ -205,9 +206,11 @@ class SingleTileCounter implements Tiled { const self = this source.features.map(f => { - self.countsPerLayer.data.set(layer.id, f.length) + const isDisplayed = source.layer.isDisplayed.data + self.countsPerLayer.data.set(layer.id, isDisplayed ? f.length : 0) self.countsPerLayer.ping() - }) + }, [source.layer.isDisplayed]) + }