diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index 12e8bc0..251679f 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -12,6 +12,7 @@ import {Widths} from "./Layers/Widths"; import {StreetWidth} from "./Layouts/StreetWidth"; import {NatureReserves} from "./Layers/NatureReserves"; import {Natuurpunt} from "./Layouts/Natuurpunt"; +import Translations from "../UI/i18n/Translations"; export class AllKnownLayouts { public static allSets = AllKnownLayouts.AllLayouts(); @@ -36,6 +37,7 @@ export class AllKnownLayouts { const knownKeys = [] for (const layout of layouts) { for (const layer of layout.layers) { + console.log("Adding ", Translations.W(layer.name).InnerRender()); const key = layer.overpassFilter.asOverpass().join(""); if (knownKeys.indexOf(key) >= 0) { continue; diff --git a/Customizations/LayerDefinition.ts b/Customizations/LayerDefinition.ts index e1dbc86..29a71f1 100644 --- a/Customizations/LayerDefinition.ts +++ b/Customizations/LayerDefinition.ts @@ -13,7 +13,7 @@ export class LayerDefinition { /** - * This name is shown in the 'add XXX button' + * This name is used in the 'hide or show this layer'-buttons */ name: string | UIElement; @@ -26,7 +26,12 @@ export class LayerDefinition { * These tags are added whenever a new point is added by the user on the map. * This is the ideal place to add extra info, such as "fixme=added by MapComplete, geometry should be checked" */ - newElementTags: Tag[] + presets: { + tags: Tag[], + title: string | UIElement, + description?: string | UIElement, + icon: string + }[] /** * Not really used anymore * This is meant to serve as icon in the buttons @@ -91,9 +96,14 @@ export class LayerDefinition { static WAYHANDLING_CENTER_AND_WAY = 2; constructor(options: { - name: string | UIElement, + name: string, description: string | UIElement, - newElementTags: Tag[], + presets: { + tags: Tag[], + title: string | UIElement, + description?: string | UIElement, + icon: string + }[], icon: string, minzoom: number, overpassFilter: TagsFilter, @@ -112,7 +122,7 @@ export class LayerDefinition { this.name = options.name; this.description = options.description; this.maxAllowedOverlapPercentage = options.maxAllowedOverlapPercentage ?? 0; - this.newElementTags = options.newElementTags; + this.presets = options.presets; this.icon = options.icon; this.minzoom = options.minzoom; this.overpassFilter = options.overpassFilter; diff --git a/Customizations/Layers/BikeCafes.ts b/Customizations/Layers/BikeCafes.ts index 29ff9ef..66bb274 100644 --- a/Customizations/Layers/BikeCafes.ts +++ b/Customizations/Layers/BikeCafes.ts @@ -35,10 +35,18 @@ export default class BikeCafes extends LayerDefinition { new Tag("pub", "cycling") ]) ]) - this.newElementTags = [ - new Tag("amenity", "pub"), - new Tag("pub", "cycling"), - ]; + + this.presets = [ + { + title: Translations.t.cyclofix.cafe.title, + icon: "/assets/bike/cafe.svg", + tags : [ + new Tag("amenity", "pub"), + new Tag("pub", "cycling"), + ] + } + ] + this.maxAllowedOverlapPercentage = 10; this.minzoom = 13; diff --git a/Customizations/Layers/BikeOtherShops.ts b/Customizations/Layers/BikeOtherShops.ts index 5c8bacc..bfb4fee 100644 --- a/Customizations/Layers/BikeOtherShops.ts +++ b/Customizations/Layers/BikeOtherShops.ts @@ -40,7 +40,7 @@ export default class BikeOtherShops extends LayerDefinition { anyValueExcept("shop", "bicycle"), this.hasBikeServices ]) - this.newElementTags = undefined + this.presets = [] this.maxAllowedOverlapPercentage = 10 this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY diff --git a/Customizations/Layers/BikeParkings.ts b/Customizations/Layers/BikeParkings.ts index 6a45a6c..507f3f1 100644 --- a/Customizations/Layers/BikeParkings.ts +++ b/Customizations/Layers/BikeParkings.ts @@ -19,9 +19,14 @@ export default class BikeParkings extends LayerDefinition { this.name = Translations.t.cyclofix.parking.name; this.icon = "./assets/bike/parking.svg"; this.overpassFilter = new Tag("amenity", "bicycle_parking"); - this.newElementTags = [ - new Tag("amenity", "bicycle_parking"), - ]; + this.presets = [{ + title: Translations.t.cyclofix.parking.title, + icon: "/assets/bike/parking.svg", + tags: [ + new Tag("amenity", "bicycle_parking"), + ] + }]; + this.maxAllowedOverlapPercentage = 10; this.minzoom = 13; diff --git a/Customizations/Layers/BikeShops.ts b/Customizations/Layers/BikeShops.ts index 9912981..5a2b787 100644 --- a/Customizations/Layers/BikeShops.ts +++ b/Customizations/Layers/BikeShops.ts @@ -24,9 +24,13 @@ export default class BikeShops extends LayerDefinition { this.name = Translations.t.cyclofix.shop.name this.icon = "./assets/bike/repair_shop.svg" this.overpassFilter = new Tag("shop", "bicycle"); - this.newElementTags = [ - new Tag("shop", "bicycle"), - ] + this.presets = [{ + title: Translations.t.cyclofix.shop.title, + icon: "/assets/bike/repair_shop.svg", + tags: [ + new Tag("shop", "bicycle"), + ] + }] this.maxAllowedOverlapPercentage = 10 this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY diff --git a/Customizations/Layers/BikeStations.ts b/Customizations/Layers/BikeStations.ts index f7f1b22..837f3e1 100644 --- a/Customizations/Layers/BikeStations.ts +++ b/Customizations/Layers/BikeStations.ts @@ -1,5 +1,5 @@ import {LayerDefinition} from "../LayerDefinition"; -import {And, Tag, TagsFilter, Or} from "../../Logic/TagsFilter"; +import {And, Tag, TagsFilter, Or, Not} from "../../Logic/TagsFilter"; import BikeStationChain from "../Questions/bike/StationChain"; import BikeStationPumpTools from "../Questions/bike/StationPumpTools"; import BikeStationStand from "../Questions/bike/StationStand"; @@ -16,10 +16,14 @@ import { TagRenderingOptions } from "../TagRendering"; export default class BikeStations extends LayerDefinition { + private readonly repairStation = new Tag("amenity", "bicycle_repair_station"); private readonly pump = new Tag("service:bicycle:pump", "yes"); + private readonly nopump = new Tag("service:bicycle:pump", "no"); private readonly pumpOperationalAny = new Tag("service:bicycle:pump:operational_status", "yes"); private readonly pumpOperationalOk = new Or([new Tag("service:bicycle:pump:operational_status", "yes"), new Tag("service:bicycle:pump:operational_status", "operational"), new Tag("service:bicycle:pump:operational_status", "ok"), new Tag("service:bicycle:pump:operational_status", "")]); private readonly tools = new Tag("service:bicycle:tools", "yes"); + private readonly notools = new Tag("service:bicycle:tools", "no"); + private readonly to = Translations.t.cyclofix.station constructor() { @@ -27,13 +31,30 @@ export default class BikeStations extends LayerDefinition { this.name = Translations.t.cyclofix.station.name; this.icon = "./assets/bike/repair_station_pump.svg"; - this.overpassFilter = new And([ - new Tag("amenity", "bicycle_repair_station") - ]); + const tr = Translations.t.cyclofix.station + this.overpassFilter = this.repairStation; + this.presets = [ + { + title: tr.titlePump, + description: tr.services.pump, + icon: "/assets/bike/pump.svg", + tags: [this.repairStation, this.pump, this.notools] + }, + { + title: tr.titleRepair, + description: tr.services.tools, + icon: "/assets/bike/repair_station.svg", + tags: [this.repairStation, this.tools, this.nopump] + }, + { + title: tr.titlePumpAndRepair, + description: tr.services.both, + icon: "/assets/bike/repair_station_pump.svg", + tags: [this.repairStation, this.tools, this.nopump] + }, + + ] - this.newElementTags = [ - new Tag("amenity", "bicycle_repair_station") - ]; this.maxAllowedOverlapPercentage = 10; this.minzoom = 13; diff --git a/Customizations/Layers/Birdhide.ts b/Customizations/Layers/Birdhide.ts index ea9e642..4b07564 100644 --- a/Customizations/Layers/Birdhide.ts +++ b/Customizations/Layers/Birdhide.ts @@ -18,7 +18,13 @@ export class Birdhide extends LayerDefinition { icon: "assets/nature/birdhide.svg", minzoom: 12, wayHandling: LayerDefinition.WAYHANDLING_CENTER_AND_WAY, - newElementTags: [Birdhide.birdhide], + presets: [ + { + title: "Vogelkijkplaats", + icon: "/assets/nature/birdhide.svg", + tags: [Birdhide.birdhide] + } + ], style(tags: any): { color: string; icon: any } { return {color: "", icon: undefined}; }, diff --git a/Customizations/Layers/Bookcases.ts b/Customizations/Layers/Bookcases.ts index 868ce3b..ba45fb5 100644 --- a/Customizations/Layers/Bookcases.ts +++ b/Customizations/Layers/Bookcases.ts @@ -12,7 +12,12 @@ export class Bookcases extends LayerDefinition { super(); this.name = "boekenkast"; - this.newElementTags = [new Tag("amenity", "public_bookcase")]; + this.presets = [{ + tags: [new Tag("amenity", "public_bookcase")], + description: "Add a new bookcase here", + title: Translations.t.bookcases.bookcase, + icon: "/assets/bookcase.svg" + }]; this.icon = "./assets/bookcase.svg"; this.overpassFilter = new Tag("amenity", "public_bookcase"); this.minzoom = 11; diff --git a/Customizations/Layers/Bos.ts b/Customizations/Layers/Bos.ts index 36cf4bf..7cfe489 100644 --- a/Customizations/Layers/Bos.ts +++ b/Customizations/Layers/Bos.ts @@ -22,10 +22,15 @@ export class Bos extends LayerDefinition { ); - this.newElementTags = [ - new Tag("landuse", "forest"), - new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen") - ]; + this.presets = [{ + title: "Bos", + description: "Voeg een ontbrekend bos toe aan de kaart", + icon: undefined, + tags: [ + new Tag("landuse", "forest"), + new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen") + ] + }]; this.maxAllowedOverlapPercentage = 10; this.minzoom = 13; diff --git a/Customizations/Layers/DrinkingWater.ts b/Customizations/Layers/DrinkingWater.ts index 579eed4..1871101 100644 --- a/Customizations/Layers/DrinkingWater.ts +++ b/Customizations/Layers/DrinkingWater.ts @@ -21,9 +21,11 @@ export class DrinkingWater extends LayerDefinition { ]); - this.newElementTags = [ - new Tag("amenity", "drinking_water"), - ]; + this.presets = [{ + title: Translations.t.cyclofix.drinking_water.title, + icon: "/assets/bike/drinking_water.svg", + tags: [new Tag("amenity", "drinking_water")] + }]; this.maxAllowedOverlapPercentage = 10; this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY diff --git a/Customizations/Layers/GhostBike.ts b/Customizations/Layers/GhostBike.ts index 751f72f..6ab0e8b 100644 --- a/Customizations/Layers/GhostBike.ts +++ b/Customizations/Layers/GhostBike.ts @@ -15,6 +15,16 @@ export class GhostBike extends LayerDefinition { this.description = "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."; + + this.presets = [ + { + title: "Ghost bike", + description: "Add a missing ghost bike to the map", + icon: "/assets/bike/ghost.svg", + tags: [new Tag("historic", "memorial"), new Tag("memorial", "ghost_bike")] + } + ] + this.elementsToShow = [ new FixedText(this.description), new ImageCarouselWithUploadConstructor(), diff --git a/Customizations/Layers/GrbToFix.ts b/Customizations/Layers/GrbToFix.ts index d92f8b3..baecfb8 100644 --- a/Customizations/Layers/GrbToFix.ts +++ b/Customizations/Layers/GrbToFix.ts @@ -8,7 +8,7 @@ export class GrbToFix extends LayerDefinition { super(); this.name = "grb"; - this.newElementTags = undefined; + this.presets = []; this.icon = "./assets/star.svg"; this.overpassFilter = new Regex("fixme", "GRB"); this.minzoom = 13; diff --git a/Customizations/Layers/InformationBoard.ts b/Customizations/Layers/InformationBoard.ts index 7b696db..4a3e81a 100644 --- a/Customizations/Layers/InformationBoard.ts +++ b/Customizations/Layers/InformationBoard.ts @@ -11,7 +11,16 @@ export class InformationBoard extends LayerDefinition { description: "Een informatiebord of kaart", minzoom: 12, overpassFilter: new Tag("tourism", "information"), - newElementTags: [new Tag("tourism", "information")], + presets: [{ + title: "Informatiebord", + icon: "/assets/nature/info.png", + tags: [new Tag("tourism", "information")] + }, + { + title: "Kaart", + icon: "/assets/map.svg", + tags: [new Tag("tourism", "information"), new Tag("information", "map")] + }], maxAllowedOverlapPercentage: 0, icon: "assets/nature/info.png", }); diff --git a/Customizations/Layers/Map.ts b/Customizations/Layers/Map.ts index 183db79..436c775 100644 --- a/Customizations/Layers/Map.ts +++ b/Customizations/Layers/Map.ts @@ -12,16 +12,19 @@ export class Map extends LayerDefinition { this.minzoom = 12; this.overpassFilter = new Tag("information", "map"); - this.newElementTags = [new Tag("tourism", "information"), new Tag("information", "map")]; + this.presets = [{ + title: "Map", + icon: "/assets/map.svg", + tags: [new Tag("tourism", "information"), new Tag("information", "map")] + }]; + - const isOsmSource = new Tag("map_source", "OpenStreetMap"); - - - + + this.style = (properties) => { let icon = "assets/map.svg"; - if(isOsmSource.matchesProperties(properties)){ + if (isOsmSource.matchesProperties(properties)) { icon = "assets/osm-logo-white-bg.svg"; const attr = properties["map_source:attribution"]; diff --git a/Customizations/Layers/NatureReserves.ts b/Customizations/Layers/NatureReserves.ts index d3f13c6..8bbe3cc 100644 --- a/Customizations/Layers/NatureReserves.ts +++ b/Customizations/Layers/NatureReserves.ts @@ -18,20 +18,26 @@ export class NatureReserves extends LayerDefinition { new Or([new Tag("leisure", "nature_reserve"), new Tag("boundary", "protected_area")]); this.maxAllowedOverlapPercentage = 10; - this.newElementTags = [new Tag("leisure", "nature_reserve"), - new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")] + this.presets = [{ + title: "Natuurreservaat", + description: "Voeg een ontbrekend, erkend natuurreservaat toe, bv. een gebied dat beheerd wordt door het ANB of natuurpunt", + icon: undefined, + tags: [new Tag("leisure", "nature_reserve"), + new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")] + } + ]; this.minzoom = 13; this.title = new NameInline("natuurreservaat"); this.style = this.generateStyleFunction(); this.elementsToShow = [ new ImageCarouselWithUploadConstructor(), - /* new TagRenderingOptions({ - freeform: { - key: "_surface", - renderTemplate: "{_surface}m²", - template: "$$$" - } - }),*/ + /* new TagRenderingOptions({ + freeform: { + key: "_surface", + renderTemplate: "{_surface}m²", + template: "$$$" + } + }),*/ new NameQuestion(), new AccessTag(), new OperatorTag(), diff --git a/Customizations/Layers/Park.ts b/Customizations/Layers/Park.ts index b8106e7..240de86 100644 --- a/Customizations/Layers/Park.ts +++ b/Customizations/Layers/Park.ts @@ -50,8 +50,14 @@ export class Park extends LayerDefinition { this.icon = undefined; this.overpassFilter = new Or([new Tag("leisure", "park"), new Tag("landuse", "village_green")]); - this.newElementTags = [new Tag("leisure", "park"), - new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")]; + this.presets = [{ + title: "Park", + description: "Voeg een ontbrekend park toe. Een park is een groene ruimte die openbaar is." + + "Typisch vind je er banken, vuilbakken, standbeelden, ... ", + icon: undefined, + tags: [new Tag("leisure", "park"), + new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")] + }]; this.maxAllowedOverlapPercentage = 25; this.minzoom = 13; diff --git a/Customizations/Layers/Viewpoint.ts b/Customizations/Layers/Viewpoint.ts index 442d94e..ab66f70 100644 --- a/Customizations/Layers/Viewpoint.ts +++ b/Customizations/Layers/Viewpoint.ts @@ -11,12 +11,18 @@ export class Viewpoint extends LayerDefinition { super({ name: "Bezienswaardigheid", description: "Wil je een foto toevoegen van iets dat geen park, bos of natuurgebied is? Dit kan hiermee", - newElementTags: [new Tag("tourism", "viewpoint"), new Tag("fixme", "Added with mapcomplete. This viewpoint should probably me merged with some existing feature")], + presets: [{ + title: "Bezienswaardigheid (andere)", + description: "Wens je een foto toe te voegen dat geen park, bos of (erkend) natuurreservaat is? Dit kan hiermee", + icon: "/assets/viewpoint.svg", + tags: [new Tag("tourism", "viewpoint"), + new Tag("fixme", "Added with mapcomplete. This viewpoint should probably me merged with some existing feature")] + }], icon: "assets/viewpoint.svg", wayHandling: LayerDefinition.WAYHANDLING_CENTER_ONLY, style: tags => { return { - color: undefined, icon:{ + color: undefined, icon: { iconUrl: "assets/viewpoint.svg", iconSize: [20, 20] } diff --git a/InitUiElements.ts b/InitUiElements.ts index 7d20c4c..e1084ca 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -54,7 +54,7 @@ export class InitUiElements { const help = new FixedUiElement(`
help
`); const close = new FixedUiElement(`
close
`); - new CheckBox( + const checkbox = new CheckBox( new Combine([ "", close, "", "", fullOptions.onClick(() => { @@ -62,6 +62,14 @@ export class InitUiElements { new Combine(["", help, ""]) , true ).AttachTo("messagesbox"); + let dontCloseYet = true; + bm.Location.addCallback(() => { + if(dontCloseYet){ + dontCloseYet = false; + return; + } + checkbox.isEnabled.setData(false); + }) const fullOptions2 = this.CreateWelcomePane(layoutToUse, osmConnection, bm); diff --git a/UI/Base/SubtleButton.ts b/UI/Base/SubtleButton.ts index 444e71a..68523f6 100644 --- a/UI/Base/SubtleButton.ts +++ b/UI/Base/SubtleButton.ts @@ -17,7 +17,7 @@ export class SubtleButton extends UIElement{ InnerRender(): string { return new Combine([ '', - ``, + this.imageUrl !== undefined ? `` : "", this.message, '' ]).Render(); diff --git a/UI/SimpleAddUI.ts b/UI/SimpleAddUI.ts index 77ff1d7..a76392c 100644 --- a/UI/SimpleAddUI.ts +++ b/UI/SimpleAddUI.ts @@ -8,6 +8,16 @@ import {Button} from "./Base/Button"; import {UserDetails} from "../Logic/OsmConnection"; import Translations from "./i18n/Translations"; import Combine from "./Base/Combine"; +import {SubtleButton} from "./Base/SubtleButton"; +import {VerticalCombine} from "./Base/VerticalCombine"; + +interface Preset { + description: string | UIElement, + name: string | UIElement, + icon: string, + tags: Tag[], + layerToAddTo: FilteredLayer +} /** * Asks to add a feature at the last clicked location, at least if zoom is sufficient @@ -17,17 +27,22 @@ export class SimpleAddUI extends UIElement { private _addButtons: UIElement[]; private _lastClickLocation: UIEventSource<{ lat: number; lon: number }>; private _changes: Changes; - private _selectedElement: UIEventSource<{feature: any}>; + private _selectedElement: UIEventSource<{ feature: any }>; private _dataIsLoading: UIEventSource; private _userDetails: UIEventSource; + private _confirmPreset: UIEventSource + = new UIEventSource(undefined); + private confirmButton: UIElement = undefined; + private cancelButton: UIElement; + constructor(zoomlevel: UIEventSource<{ zoom: number }>, lastClickLocation: UIEventSource<{ lat: number, lon: number }>, changes: Changes, - selectedElement: UIEventSource<{feature: any}>, + selectedElement: UIEventSource<{ feature: any }>, dataIsLoading: UIEventSource, userDetails: UIEventSource, - addButtons: { name: UIElement; icon: string; tags: Tag[]; layerToAddTo: FilteredLayer }[], + addButtons: { description: string | UIElement, name: string | UIElement; icon: string; tags: Tag[]; layerToAddTo: FilteredLayer }[], ) { super(zoomlevel); this._zoomlevel = zoomlevel; @@ -39,18 +54,47 @@ export class SimpleAddUI extends UIElement { this.ListenTo(userDetails); this.ListenTo(dataIsLoading); this._addButtons = []; + this.ListenTo(this._confirmPreset); + this.clss = "add-ui" + const self = this; for (const option of addButtons) { //