diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index c8f2929..bdd25f9 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -11,55 +11,53 @@ import {StreetWidth} from "./Layouts/StreetWidth"; import {Natuurpunt} from "./Layouts/Natuurpunt"; import {ClimbingTrees} from "./Layouts/ClimbingTrees"; import {Smoothness} from "./Layouts/Smoothness"; +import {LayerDefinition} from "./LayerDefinition"; +import {CustomLayers} from "../Logic/CustomLayers"; export class AllKnownLayouts { - public static allSets = AllKnownLayouts.AllLayouts(); + + public static allLayers: Map = undefined; + + public static layoutsList: Layout[] = [ + new Groen(), + new GRB(), + new Cyclofix(), + new Bookcases(), + new WalkByBrussels(), + new MetaMap(), + new StreetWidth(), + new Natuurpunt(), + new ClimbingTrees(), + new Artworks(), + new Smoothness(), + new CustomLayers() + /*new Toilets(), + */ + ]; + + public static allSets: Map = AllKnownLayouts.AllLayouts(); private static AllLayouts(): Map { - const layouts: Layout[] = [ - new Groen(), - new GRB(), - new Cyclofix(), - new Bookcases(), - new WalkByBrussels(), - new MetaMap(), - new StreetWidth(), - new Natuurpunt(), - new ClimbingTrees(), - new Artworks(), - new Smoothness() - /*new Toilets(), - */ - ]; - const all = new All(); - const knownKeys = [] - for (const layout of layouts) { + this.allLayers = new Map(); + for (const layout of this.layoutsList) { for (const layer of layout.layers) { - const key = layer.overpassFilter.asOverpass().join(""); - if (knownKeys.indexOf(key) >= 0) { + const key = layer.id; + if (this.allLayers[layer.id] !== undefined) { continue; } - knownKeys.push(key); + this.allLayers[layer.id] = layer; all.layers.push(layer); } } - layouts.push(all) const allSets: Map = new Map(); - for (const layout of layouts) { + for (const layout of this.layoutsList) { allSets[layout.name] = layout; } + allSets[all.name] = all; return allSets; } - public static GetSets(layoutNames): any { - const all = new All(); - for (const name of layoutNames) { - all.layers = all.layers.concat(AllKnownLayouts.allSets[name].layers); - } - - return all; - } } diff --git a/Customizations/LayerDefinition.ts b/Customizations/LayerDefinition.ts index 54d2f2f..be6bc27 100644 --- a/Customizations/LayerDefinition.ts +++ b/Customizations/LayerDefinition.ts @@ -51,6 +51,7 @@ export class LayerDefinition { * ]) */ overpassFilter: TagsFilter; + public readonly id: string; /** * This UIElement is rendered as title element in the popup @@ -90,7 +91,7 @@ export class LayerDefinition { static WAYHANDLING_CENTER_ONLY = 1; static WAYHANDLING_CENTER_AND_WAY = 2; - constructor(options: { + constructor(id: string, options: { name: string, description: string | UIElement, presets: { @@ -111,6 +112,7 @@ export class LayerDefinition { icon: any } } = undefined) { + this.id = id; if (options === undefined) { return; } @@ -127,6 +129,4 @@ export class LayerDefinition { this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT; } - - } \ No newline at end of file diff --git a/Customizations/Layers/Artwork.ts b/Customizations/Layers/Artwork.ts index 78c1e39..bb93518 100644 --- a/Customizations/Layers/Artwork.ts +++ b/Customizations/Layers/Artwork.ts @@ -10,7 +10,7 @@ import FixedText from "../Questions/FixedText"; export class Artwork extends LayerDefinition { constructor() { - super(); + super("artwork"); this.name = "artwork"; const t = Translations.t.artwork; this.title = t.title; diff --git a/Customizations/Layers/BikeCafes.ts b/Customizations/Layers/BikeCafes.ts index 0eeb3bd..b518c88 100644 --- a/Customizations/Layers/BikeCafes.ts +++ b/Customizations/Layers/BikeCafes.ts @@ -16,7 +16,7 @@ export default class BikeCafes extends LayerDefinition { private readonly to = Translations.t.cyclofix.cafe constructor() { - super() + super("bikecafe") this.name = this.to.name this.icon = "./assets/bike/cafe.svg" this.overpassFilter = new And([ diff --git a/Customizations/Layers/BikeOtherShops.ts b/Customizations/Layers/BikeOtherShops.ts index 60e2bc7..ffd27e9 100644 --- a/Customizations/Layers/BikeOtherShops.ts +++ b/Customizations/Layers/BikeOtherShops.ts @@ -20,7 +20,7 @@ export default class BikeOtherShops extends LayerDefinition { private readonly to = Translations.t.cyclofix.nonBikeShop constructor() { - super(); + super("bikeOtherShop"); this.name = this.to.name this.icon = "./assets/bike/non_bike_repair_shop.svg" this.overpassFilter = new And([ diff --git a/Customizations/Layers/BikeParkings.ts b/Customizations/Layers/BikeParkings.ts index 34ab337..4aed3bb 100644 --- a/Customizations/Layers/BikeParkings.ts +++ b/Customizations/Layers/BikeParkings.ts @@ -15,7 +15,7 @@ export default class BikeParkings extends LayerDefinition { private readonly accessCargoDesignated = new Tag("cargo_bike", "designated"); constructor() { - super(); + super("bikeparking"); this.name = Translations.t.cyclofix.parking.name; this.icon = "./assets/bike/parking.svg"; this.overpassFilter = new Tag("amenity", "bicycle_parking"); diff --git a/Customizations/Layers/BikeShops.ts b/Customizations/Layers/BikeShops.ts index 46e56cb..a56991f 100644 --- a/Customizations/Layers/BikeShops.ts +++ b/Customizations/Layers/BikeShops.ts @@ -21,7 +21,7 @@ export default class BikeShops extends LayerDefinition { private readonly repairsBikes = new Tag("service:bicycle:repair", "yes") constructor() { - super(); + super("bikeshop"); this.name = Translations.t.cyclofix.shop.name this.icon = "./assets/bike/repair_shop.svg" this.overpassFilter = new Tag("shop", "bicycle"); diff --git a/Customizations/Layers/BikeStations.ts b/Customizations/Layers/BikeStations.ts index 6638a79..251b198 100644 --- a/Customizations/Layers/BikeStations.ts +++ b/Customizations/Layers/BikeStations.ts @@ -27,7 +27,7 @@ export default class BikeStations extends LayerDefinition { private readonly to = Translations.t.cyclofix.station constructor() { - super(); + super("bikestation"); this.name = Translations.t.cyclofix.station.name; this.icon = "./assets/bike/repair_station_pump.svg"; diff --git a/Customizations/Layers/Birdhide.ts b/Customizations/Layers/Birdhide.ts index 0acb1bd..8d65152 100644 --- a/Customizations/Layers/Birdhide.ts +++ b/Customizations/Layers/Birdhide.ts @@ -10,7 +10,7 @@ export class Birdhide extends LayerDefinition { constructor() { - super({ + super("birdhide",{ name: "vogelkijkplaats", description: "Een plaats om vogels te kijken, zoals een vogelkijkhut of kijkwand", overpassFilter: Birdhide.birdhide, diff --git a/Customizations/Layers/Bookcases.ts b/Customizations/Layers/Bookcases.ts index 27e7275..ff21817 100644 --- a/Customizations/Layers/Bookcases.ts +++ b/Customizations/Layers/Bookcases.ts @@ -9,7 +9,7 @@ import T from "../../UI/i18n/Translation"; export class Bookcases extends LayerDefinition { constructor() { - super(); + super("bookcases"); this.name = "boekenkast"; this.presets = [{ diff --git a/Customizations/Layers/Bos.ts b/Customizations/Layers/Bos.ts index 7cfe489..906d609 100644 --- a/Customizations/Layers/Bos.ts +++ b/Customizations/Layers/Bos.ts @@ -10,7 +10,7 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi export class Bos extends LayerDefinition { constructor() { - super(); + super("bos"); this.name = "Bos"; this.icon = ""; diff --git a/Customizations/Layers/ClimbingTree.ts b/Customizations/Layers/ClimbingTree.ts index 9b0de43..e664302 100644 --- a/Customizations/Layers/ClimbingTree.ts +++ b/Customizations/Layers/ClimbingTree.ts @@ -8,7 +8,7 @@ export class ClimbingTree extends LayerDefinition { constructor() { - super(); + super("climbingtree"); const t = Translations.t.climbingTrees.layer; this.title = new FixedText(t.title); const icon = "assets/walkbybrussels/tree.svg"; diff --git a/Customizations/Layers/DrinkingWater.ts b/Customizations/Layers/DrinkingWater.ts index 490fbcb..f979130 100644 --- a/Customizations/Layers/DrinkingWater.ts +++ b/Customizations/Layers/DrinkingWater.ts @@ -10,7 +10,7 @@ import Translations from "../../UI/i18n/Translations"; export class DrinkingWater extends LayerDefinition { constructor() { - super(); + super("drinkingwater"); this.name = Translations.t.cyclofix.drinking_water.title; this.icon = "./assets/bike/drinking_water.svg"; diff --git a/Customizations/Layers/GhostBike.ts b/Customizations/Layers/GhostBike.ts index 77f5158..d70a7f0 100644 --- a/Customizations/Layers/GhostBike.ts +++ b/Customizations/Layers/GhostBike.ts @@ -8,7 +8,7 @@ import L from "leaflet"; export class GhostBike extends LayerDefinition { constructor() { - super(); + super("ghost bike"); this.name = "ghost bike"; this.overpassFilter = new Tag("memorial", "ghost_bike") this.title = new FixedText("Ghost bike"); diff --git a/Customizations/Layers/GrbToFix.ts b/Customizations/Layers/GrbToFix.ts index baecfb8..2b616ca 100644 --- a/Customizations/Layers/GrbToFix.ts +++ b/Customizations/Layers/GrbToFix.ts @@ -5,7 +5,7 @@ import {TagRenderingOptions} from "../TagRendering"; export class GrbToFix extends LayerDefinition { constructor() { - super(); + super("grb"); this.name = "grb"; this.presets = []; diff --git a/Customizations/Layers/InformationBoard.ts b/Customizations/Layers/InformationBoard.ts index 61c9db8..70afde0 100644 --- a/Customizations/Layers/InformationBoard.ts +++ b/Customizations/Layers/InformationBoard.ts @@ -6,7 +6,7 @@ import {And, Tag} from "../../Logic/TagsFilter"; export class InformationBoard extends LayerDefinition { constructor() { - super({ + super("informationBoard",{ name: "Informatiebord", description: "Een informatiebord of kaart", minzoom: 12, diff --git a/Customizations/Layers/Map.ts b/Customizations/Layers/Map.ts index 53ab452..00722c5 100644 --- a/Customizations/Layers/Map.ts +++ b/Customizations/Layers/Map.ts @@ -6,7 +6,7 @@ import {And, Tag} from "../../Logic/TagsFilter"; export class Map extends LayerDefinition { constructor() { - super(); + super("map"); this.name = "Map"; this.title = new FixedText("Map"); this.minzoom = 12; diff --git a/Customizations/Layers/NatureReserves.ts b/Customizations/Layers/NatureReserves.ts index bbf42f4..9d4fed3 100644 --- a/Customizations/Layers/NatureReserves.ts +++ b/Customizations/Layers/NatureReserves.ts @@ -11,7 +11,7 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi export class NatureReserves extends LayerDefinition { constructor(moreQuests: boolean = false) { - super(); + super("natureReserve"); this.name = "Natuurgebied"; this.icon = ""; this.overpassFilter = diff --git a/Customizations/Layers/Park.ts b/Customizations/Layers/Park.ts index 3089b68..5c69dae 100644 --- a/Customizations/Layers/Park.ts +++ b/Customizations/Layers/Park.ts @@ -45,7 +45,7 @@ export class Park extends LayerDefinition { constructor() { - super(); + super("park"); this.name = "Park"; this.icon = undefined; this.overpassFilter = diff --git a/Customizations/Layers/Toilets.ts b/Customizations/Layers/Toilets.ts index 2c0b69b..af41d6c 100644 --- a/Customizations/Layers/Toilets.ts +++ b/Customizations/Layers/Toilets.ts @@ -1,5 +1,4 @@ import {LayerDefinition} from "../LayerDefinition"; -import {Quests} from "../../Quests"; import {FixedUiElement} from "../../UI/Base/FixedUiElement"; import L from "leaflet"; import {Tag} from "../../Logic/TagsFilter"; @@ -7,7 +6,7 @@ import {Tag} from "../../Logic/TagsFilter"; export class Toilets extends LayerDefinition{ constructor() { - super(); + super("toilets"); this.name="toilet"; this.newElementTags = [new Tag( "amenity", "toilets")]; diff --git a/Customizations/Layers/Viewpoint.ts b/Customizations/Layers/Viewpoint.ts index 029d369..f6c477c 100644 --- a/Customizations/Layers/Viewpoint.ts +++ b/Customizations/Layers/Viewpoint.ts @@ -8,7 +8,7 @@ import {TagRenderingOptions} from "../TagRendering"; export class Viewpoint extends LayerDefinition { constructor() { - super({ + super("viewpoint",{ name: "Bezienswaardigheid", description: "Wil je een foto toevoegen van iets dat geen park, bos of natuurgebied is? Dit kan hiermee", presets: [{ diff --git a/Customizations/Layers/Widths.ts b/Customizations/Layers/Widths.ts index dc10b31..000bd67 100644 --- a/Customizations/Layers/Widths.ts +++ b/Customizations/Layers/Widths.ts @@ -113,7 +113,7 @@ export class Widths extends LayerDefinition { constructor(carWidth: number, cyclistWidth: number, pedestrianWidth: number) { - super(); + super("width"); this.carWidth = carWidth; this.cyclistWidth = cyclistWidth; this.pedestrianWidth = pedestrianWidth; diff --git a/Helpers.ts b/Helpers.ts deleted file mode 100644 index 2566c05..0000000 --- a/Helpers.ts +++ /dev/null @@ -1,93 +0,0 @@ -import {UIEventSource} from "./UI/UIEventSource"; -import {Changes} from "./Logic/Osm/Changes"; -import {State} from "./State"; - -export class Helpers { - - static DoEvery(millis: number, f: (() => void)) { - window.setTimeout( - function () { - f(); - Helpers.DoEvery(millis, f); - } - , millis) - } - - - static SetupAutoSave() { - - const changes = State.state.changes; - const millisTillChangesAreSaved = State.state.secondsTillChangesAreSaved; - const saveAfterXMillis = State.state.secondsTillChangesAreSaved.data * 1000; - changes.pendingChangesES.addCallback(function () { - - var c = changes.pendingChangesES.data; - if (c > 10) { - millisTillChangesAreSaved.setData(0); - changes.uploadAll(undefined); - return; - } - - if (c > 0) { - millisTillChangesAreSaved.setData(saveAfterXMillis); - } - - }); - - millisTillChangesAreSaved.addCallback((time) => { - if (time <= 0 && changes.pendingChangesES.data > 0) { - changes.uploadAll(undefined); - } - } - ) - - Helpers.DoEvery( - 1000, - () => { - millisTillChangesAreSaved - .setData(millisTillChangesAreSaved.data - 1000) - }); - } - - - /* - * Registers an action that: - * -> Upload everything to OSM - * -> Asks the user not to close. The 'not to close' dialog should profide enough time to upload - * -> WHen uploading is done, the window is closed anyway - */ - static LastEffortSave() { - const changes = State.state.changes; - window.addEventListener("beforeunload", function (e) { - // Quickly save everyting! - if (changes.pendingChangesES.data == 0) { - return ""; - } - - changes.uploadAll(function () { - window.close() - }); - var confirmationMessage = "Nog even geduld - je laatset wijzigingen worden opgeslaan!"; - - (e || window.event).returnValue = confirmationMessage; //Gecko + IE - return confirmationMessage; //Webkit, Safari, Chrome - }); - - - document.addEventListener('visibilitychange',() => { - if(document.visibilityState === "visible"){ - return; - } - if (changes.pendingChangesES.data == 0) { - return; - } - - console.log("Upmoading: loss of focus") - changes.uploadAll(function () { - window.close() - }); - }) - - } - -} \ No newline at end of file diff --git a/InitUiElements.ts b/InitUiElements.ts index e2b043a..26ed5e6 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -16,9 +16,13 @@ import {ElementStorage} from "./Logic/ElementStorage"; import {Preset} from "./UI/SimpleAddUI"; import {Changes} from "./Logic/Osm/Changes"; import {OsmConnection} from "./Logic/Osm/OsmConnection"; -import {Basemap} from "./Logic/Leaflet/Basemap"; +import {BaseLayers, Basemap} from "./Logic/Leaflet/Basemap"; import {State} from "./State"; import {WelcomeMessage} from "./UI/WelcomeMessage"; +import {Img} from "./UI/Img"; +import {DropDown} from "./UI/Input/DropDown"; +import {LayerSelection} from "./UI/LayerSelection"; +import {CustomLayersPanel} from "./Logic/CustomLayersPanel"; export class InitUiElements { @@ -47,7 +51,8 @@ export class InitUiElements { {header: ``, content: welcome}, {header: ``, content: Translations.t.general.openStreetMapIntro}, {header: ``, content: new ShareScreen()}, - {header: ``, content: new MoreScreen()} + {header: ``, content: new MoreScreen()}, + {header: ``, content: new CustomLayersPanel()}, ]) return fullOptions; @@ -89,14 +94,38 @@ export class InitUiElements { } + static InitLayerSelection(layerSetup) { + const closedFilterButton = ``; + + const openFilterButton = ``; + + let baseLayerOptions = BaseLayers.baseLayers.map((layer) => { + return {value: layer, shown: layer.name} + }); + const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLayerOptions, State.state.bm.CurrentLayer), openFilterButton]); + const layerSelection = new Combine([`

Maplayers

`, new LayerSelection(layerSetup.flayers)]); + let layerControl = backgroundMapPicker; + if (layerSetup.flayers.length > 1) { + layerControl = new Combine([layerSelection, backgroundMapPicker]); + } + + InitUiElements.OnlyIf(State.state.featureSwitchLayers, () => { + + const checkbox = new CheckBox(layerControl, closedFilterButton); + checkbox.AttachTo("filter__selection"); + State.state.bm.Location.addCallback(() => { + checkbox.isEnabled.setData(false); + }); + + }); + } static InitLayers(): { minZoom: number flayers: FilteredLayer[], presets: Preset[] } { - const addButtons: Preset[] - = []; + const addButtons: Preset[] = []; const flayers: FilteredLayer[] = [] diff --git a/Logic/CustomLayers.ts b/Logic/CustomLayers.ts new file mode 100644 index 0000000..042c2f2 --- /dev/null +++ b/Logic/CustomLayers.ts @@ -0,0 +1,26 @@ +import {Layout} from "../Customizations/Layout"; +import Translations from "../UI/i18n/Translations"; + +export class CustomLayers extends Layout { + + public static NAME: string = "personal"; + + constructor() { + super( + CustomLayers.NAME, + ["en"], + Translations.t.favourite.title, + [], + 12, + 0, + 0, + Translations.t.favourite.description, + ); + + this.icon = "./assets/star.svg" + } + +} + + + \ No newline at end of file diff --git a/Logic/CustomLayersPanel.ts b/Logic/CustomLayersPanel.ts new file mode 100644 index 0000000..36accf0 --- /dev/null +++ b/Logic/CustomLayersPanel.ts @@ -0,0 +1,96 @@ +import {UIElement} from "../UI/UIElement"; +import {State} from "../State"; +import Translations from "../UI/i18n/Translations"; +import {UIEventSource} from "../UI/UIEventSource"; +import {AllKnownLayouts} from "../Customizations/AllKnownLayouts"; +import Combine from "../UI/Base/Combine"; +import {Img} from "../UI/Img"; +import {CheckBox} from "../UI/Input/CheckBox"; +import {CustomLayersState} from "./CustomLayersState"; +import {VerticalCombine} from "../UI/Base/VerticalCombine"; +import {FixedUiElement} from "../UI/Base/FixedUiElement"; + +export class CustomLayersPanel extends UIElement { + private checkboxes: UIElement[]; + + constructor() { + super(State.state.favourteLayers); + this.ListenTo(State.state.osmConnection.userDetails); + + + const t = Translations.t.favourite; + + this.checkboxes = []; + const controls = new Map>(); + const favs = State.state.favourteLayers.data; + for (const layout of AllKnownLayouts.layoutsList) { + + const header = + new Combine([ + `
`, + "", + layout.title, + "
", + layout.description ?? "", + "
", + ], 'custom-layer-panel-header') + this.checkboxes.push(header); + + for (const layer of layout.layers) { + const image = (layer.icon ? `` : Img.checkmark); + const cb = new CheckBox( + new Combine([ + image, + "", layer.name ?? "", " ", layer.description ?? "" + ]), + new Combine([ + "", + image, "", "", layer.name ?? "", " ", layer.description ?? "" + ]), + controls[layer.id] ?? (favs.indexOf(layer.id) >= 0) + ); + cb.clss = "custom-layer-checkbox" + controls[layer.id] = cb.isEnabled; + + cb.isEnabled.addCallback((isEnabled) => { + if (isEnabled) { + CustomLayersState.AddFavouriteLayer(layer.id) + } else { + CustomLayersState.RemoveFavouriteLayer(layer.id); + } + }) + + this.checkboxes.push(cb); + + } + + } + + State.state.favourteLayers.addCallback((layers) => { + for (const layerId of layers) { + controls[layerId].setData(true); + } + }) + + } + + InnerRender(): string { + const t = Translations.t.favourite; + const userDetails = State.state.osmConnection.userDetails.data; + if(!userDetails.loggedIn){ + return ""; + } + + if(userDetails.csCount <= 100){ + return ""; + } + + return new VerticalCombine([ + t.panelIntro, + new FixedUiElement("GO"), + ...this.checkboxes + ], "custom-layer-panel").Render(); + } + + +} \ No newline at end of file diff --git a/Logic/CustomLayersState.ts b/Logic/CustomLayersState.ts new file mode 100644 index 0000000..a941083 --- /dev/null +++ b/Logic/CustomLayersState.ts @@ -0,0 +1,94 @@ +import {State} from "../State"; + +export class CustomLayersState { + static RemoveFavouriteLayer(layer: string) { + + const favs = State.state.favourteLayers.data; + const ind = favs.indexOf(layer); + if (ind < 0) { + return; + } + console.log("REmovign fav layer", layer); + favs.splice(ind, 1); + State.state.favourteLayers.ping(); + + const osmConnection = State.state.osmConnection; + const count = osmConnection.GetPreference("mapcomplete-custom-layer-count"); + if (favs.length === 0) { + count.setData("0") + } else if (count.data === undefined || isNaN(Number(count.data))) { + count.data = "0"; + } + const lastId = Number(count.data); + + for (let i = 0; i < lastId; i++) { + const layerIDescr = osmConnection.GetPreference("mapcomplete-custom-layer-" + i); + if (layerIDescr.data === layer) { + // We found the value to remove - mark with a tombstone + layerIDescr.setData("-"); + return; + } + } + } + + static AddFavouriteLayer(layer: string) { + const favs = State.state.favourteLayers.data; + const ind = favs.indexOf(layer); + if (ind >= 0) { + return; + } + console.log("Adding fav layer", layer); + favs.push(layer); + State.state.favourteLayers.ping(); + + + const osmConnection = State.state.osmConnection; + const count = osmConnection.GetPreference("mapcomplete-custom-layer-count"); + if (count.data === undefined || isNaN(Number(count.data))) { + count.data = "0"; + } + const lastId = Number(count.data); + + for (let i = 0; i < lastId; i++) { + const layerIDescr = osmConnection.GetPreference("mapcomplete-custom-layer-" + i); + if (layerIDescr.data === undefined || layerIDescr.data === "-") { + // An earlier item was removed -> overwrite it + layerIDescr.setData(layer); + count.ping(); + return; + } + } + + // No empty slot found -> create a new one + const layerIDescr = osmConnection.GetPreference("mapcomplete-custom-layer-" + lastId); + layerIDescr.setData(layer); + count.setData((lastId + 1) + ""); + } + + static InitFavouriteLayer() { + const osmConnection = State.state.osmConnection; + const count = osmConnection.GetPreference("mapcomplete-custom-layer-count"); + const favs = State.state.favourteLayers.data; + let changed = false; + count.addCallback((countStr) => { + if (countStr === undefined) { + return; + } + let countI = Number(countStr); + if (isNaN(countI)) { + countI = 999; + } + for (let i = 0; i < countI; i++) { + const layerId = osmConnection.GetPreference("mapcomplete-custom-layer-" + i).data; + if (layerId !== undefined && layerId !== "-" && favs.indexOf(layerId) < 0) { + State.state.favourteLayers.data.push(layerId); + changed = true; + } + } + if (changed) { + State.state.favourteLayers.ping(); + } + }) + } + +} \ No newline at end of file diff --git a/Logic/Leaflet/GeoLocationHandler.ts b/Logic/Leaflet/GeoLocationHandler.ts index 0df1746..67c19c4 100644 --- a/Logic/Leaflet/GeoLocationHandler.ts +++ b/Logic/Leaflet/GeoLocationHandler.ts @@ -1,8 +1,8 @@ import L from "leaflet"; import {UIEventSource} from "../../UI/UIEventSource"; import {UIElement} from "../../UI/UIElement"; -import {Helpers} from "../../Helpers"; import {State} from "../../State"; +import {Utils} from "../../Utils"; export class GeoLocationHandler extends UIElement { @@ -108,7 +108,7 @@ export class GeoLocationHandler extends UIElement { if (!self._isActive.data) { self._isActive.setData(true); - Helpers.DoEvery(60000, () => { + Utils.DoEvery(60000, () => { if (document.visibilityState !== "visible") { console.log("Not starting gps: document not visible") diff --git a/Logic/Osm/Changes.ts b/Logic/Osm/Changes.ts index ac83715..465865c 100644 --- a/Logic/Osm/Changes.ts +++ b/Logic/Osm/Changes.ts @@ -8,6 +8,7 @@ import {OsmNode, OsmObject} from "./OsmObject"; import {And, Tag, TagsFilter} from "../TagsFilter"; import {ElementStorage} from "../ElementStorage"; import {State} from "../../State"; +import {Utils} from "../../Utils"; export class Changes { @@ -22,9 +23,11 @@ export class Changes { constructor( changesetComment: string, - login: OsmConnection, - allElements: ElementStorage) { + state: State) { this._changesetComment = changesetComment; + + this.SetupAutoSave(state); + this.LastEffortSave(); } addTag(elementId: string, tagsFilter : TagsFilter){ @@ -52,7 +55,6 @@ export class Changes { * @param value */ addChange(elementId: string, key: string, value: string) { -console.log("Received change",key, value) if (key === undefined || key === null) { console.log("Invalid key"); return; @@ -256,5 +258,78 @@ console.log("Received change",key, value) optionalContinuationWrapped); }); } - + + /* + * Registers an action that: + * -> Upload everything to OSM + * -> Asks the user not to close. The 'not to close' dialog should profide enough time to upload + * -> WHen uploading is done, the window is closed anyway + */ + private LastEffortSave() { + const self = this; + window.addEventListener("beforeunload", function (e) { + // Quickly save everyting! + if (self.pendingChangesES.data == 0) { + return ""; + } + + self.uploadAll(function () { + window.close() + }); + var confirmationMessage = "Nog even geduld - je laatset wijzigingen worden opgeslaan!"; + + (e || window.event).returnValue = confirmationMessage; //Gecko + IE + return confirmationMessage; //Webkit, Safari, Chrome + }); + + + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === "visible") { + return; + } + if (this.pendingChangesES.data == 0) { + return; + } + + console.log("Upmoading: loss of focus") + this.uploadAll(function () { + window.close() + }); + }) + + } + + private SetupAutoSave(state: State) { + + const millisTillChangesAreSaved = state.secondsTillChangesAreSaved; + const saveAfterXMillis = state.secondsTillChangesAreSaved.data * 1000; + this.pendingChangesES.addCallback(function () { + + var c = this.pendingChangesES.data; + if (c > 10) { + millisTillChangesAreSaved.setData(0); + this.uploadAll(undefined); + return; + } + + if (c > 0) { + millisTillChangesAreSaved.setData(saveAfterXMillis); + } + + }); + + millisTillChangesAreSaved.addCallback((time) => { + if (time <= 0 && this.pendingChangesES.data > 0) { + this.uploadAll(undefined); + } + } + ) + + Utils.DoEvery( + 1000, + () => { + millisTillChangesAreSaved + .setData(millisTillChangesAreSaved.data - 1000) + }); + } } \ No newline at end of file diff --git a/Logic/Osm/OsmConnection.ts b/Logic/Osm/OsmConnection.ts index 423fcf1..993654b 100644 --- a/Logic/Osm/OsmConnection.ts +++ b/Logic/Osm/OsmConnection.ts @@ -1,6 +1,7 @@ // @ts-ignore import osmAuth from "osm-auth"; import {UIEventSource} from "../../UI/UIEventSource"; +import {CustomLayersState} from "../CustomLayersState"; export class UserDetails { @@ -215,6 +216,7 @@ export class OsmConnection { self.preferences.data[k] = v; } self.preferences.ping(); + CustomLayersState.InitFavouriteLayer(); }); } diff --git a/Logic/QueryParameters.ts b/Logic/QueryParameters.ts index 93b5765..9d5a004 100644 --- a/Logic/QueryParameters.ts +++ b/Logic/QueryParameters.ts @@ -52,7 +52,6 @@ export class QueryParameters { public static GetQueryParameter(key: string, deflt: string): UIEventSource { if (deflt !== undefined) { - console.log(key, "-->", deflt) QueryParameters.defaults[key] = deflt; } if (QueryParameters.knownSources[key] !== undefined) { diff --git a/State.ts b/State.ts index 959c07e..233e052 100644 --- a/State.ts +++ b/State.ts @@ -9,6 +9,10 @@ import {ElementStorage} from "./Logic/ElementStorage"; import {Changes} from "./Logic/Osm/Changes"; import {Basemap} from "./Logic/Leaflet/Basemap"; import {OsmConnection} from "./Logic/Osm/OsmConnection"; +import Locale from "./UI/i18n/Locale"; +import {VariableUiElement} from "./UI/Base/VariableUIElement"; +import Translations from "./UI/i18n/Translations"; +import {CustomLayersState} from "./Logic/CustomLayersState"; /** * Contains the global state: a bunch of UI-event sources @@ -95,6 +99,11 @@ export class State { // After this many milliseconds without changes, saves are sent of to OSM public readonly saveTimeout = new UIEventSource(30 * 1000); + /** + * Layers can be marked as favourites, they show up in a custom layout + */ + public favourteLayers: UIEventSource = new UIEventSource([]) + constructor(layoutToUse: Layout) { this.layoutToUse = new UIEventSource(layoutToUse); @@ -130,5 +139,57 @@ export class State { this.featureSwitchIframe = featSw("fs-iframe", () => false); + this.osmConnection = new OsmConnection( + QueryParameters.GetQueryParameter("test", "false").data === "true", + QueryParameters.GetQueryParameter("oauth_token", undefined) + ); + + + Locale.language.syncWith(this.osmConnection.GetPreference("language")); + + + Locale.language.addCallback((currentLanguage) => { + if (layoutToUse.supportedLanguages.indexOf(currentLanguage) < 0) { + console.log("Resetting languate to", layoutToUse.supportedLanguages[0], "as", currentLanguage, " is unsupported") + // The current language is not supported -> switch to a supported one + Locale.language.setData(layoutToUse.supportedLanguages[0]); + } + }).ping() + + document.title = Translations.W(layoutToUse.title).InnerRender(); + Locale.language.addCallback(e => { + document.title = Translations.W(layoutToUse.title).InnerRender(); + }) + + + this.allElements = new ElementStorage(); + this.changes = new Changes( + "Beantwoorden van vragen met #MapComplete voor vragenset #" + this.layoutToUse.data.name, + this); + + + + if (document.getElementById("leafletDiv") === null) { + console.warn("leafletDiv not found - not initializing map. Assuming test.html"); + return; + } + + this.bm = new Basemap("leafletDiv", this.locationControl, new VariableUiElement( + this.locationControl.map((location) => { + const mapComplete = "Mapcomple " + + " " + + "Report bug"; + let editHere = ""; + if (location !== undefined) { + editHere = " | " + + "" + + "edit here" + + "" + } + return mapComplete + editHere; + + }) + )); + } } \ No newline at end of file diff --git a/UI/Base/Combine.ts b/UI/Base/Combine.ts index 3a469cd..1dac940 100644 --- a/UI/Base/Combine.ts +++ b/UI/Base/Combine.ts @@ -3,10 +3,12 @@ import Translations from "../i18n/Translations"; export default class Combine extends UIElement { private uiElements: (string | UIElement)[]; + private className: string = undefined; private clas: string = undefined; - constructor(uiElements: (string | UIElement)[]) { + constructor(uiElements: (string | UIElement)[], className: string = undefined) { super(undefined); + this.className = className; this.uiElements = uiElements; } @@ -19,6 +21,10 @@ export default class Combine extends UIElement { elements += element; } } + if(this.className !== undefined){ + elements = `${elements}`; + } + return elements; } diff --git a/UI/Base/Image.ts b/UI/Base/Image.ts new file mode 100644 index 0000000..8f63ffd --- /dev/null +++ b/UI/Base/Image.ts @@ -0,0 +1,20 @@ +import {UIElement} from "../UIElement"; + + +export class Image extends UIElement{ + private src: string; + private style: string = ""; + constructor(src: string, style: string = "") { + super(undefined); + this.style = style; + this.src = src; + } + + InnerRender(): string { + if(this.src === undefined){ + return ""; + } + return ``; + } + +} \ No newline at end of file diff --git a/UI/Base/TabbedComponent.ts b/UI/Base/TabbedComponent.ts index 5e74e81..b7a0f96 100644 --- a/UI/Base/TabbedComponent.ts +++ b/UI/Base/TabbedComponent.ts @@ -27,8 +27,10 @@ export class TabbedComponent extends UIElement { for (let i = 0; i < this.headers.length; i++) { let header = this.headers[i]; - headerBar += `
` + - header.Render() + "
" + if (!this.content[i].IsEmpty()) { + headerBar += `
` + + header.Render() + "
" + } } diff --git a/UI/SimpleAddUI.ts b/UI/SimpleAddUI.ts index c16bb4e..4e56327 100644 --- a/UI/SimpleAddUI.ts +++ b/UI/SimpleAddUI.ts @@ -92,7 +92,7 @@ export class SimpleAddUI extends UIElement { const self = this; return () => { - const loc = State.state.bm.lastClickLocation.data; + const loc = State.state.bm.LastClickLocation.data; let feature = State.state.changes.createElement(option.tags, loc.lat, loc.lon); option.layerToAddTo.AddNewElement(feature); State.state.selectedElement.setData({feature: feature}); @@ -107,7 +107,7 @@ export class SimpleAddUI extends UIElement { if(userDetails.data.dryRun){ this.CreatePoint(this._confirmPreset.data)(); - return; + return ""; } return new Combine([ diff --git a/UI/UserBadge.ts b/UI/UserBadge.ts index 0b44bf9..de9f595 100644 --- a/UI/UserBadge.ts +++ b/UI/UserBadge.ts @@ -9,6 +9,7 @@ import {Basemap} from "../Logic/Leaflet/Basemap"; import {State} from "../State"; import {PendingChanges} from "./PendingChanges"; import Locale from "./i18n/Locale"; +import {Utils} from "../Utils"; /** * Handles and updates the user badge @@ -25,7 +26,7 @@ export class UserBadge extends UIElement { super(State.state.osmConnection.userDetails); this._userDetails = State.state.osmConnection.userDetails; this._pendingChanges = new PendingChanges(); - this._languagePicker = Locale.CreateLanguagePicker(); + this._languagePicker = Utils.CreateLanguagePicker(); this._logout = new FixedUiElement("logout") .onClick(() => { diff --git a/UI/WelcomeMessage.ts b/UI/WelcomeMessage.ts index 91dca1c..ca5e487 100644 --- a/UI/WelcomeMessage.ts +++ b/UI/WelcomeMessage.ts @@ -6,6 +6,7 @@ import {State} from "../State"; import {Layout} from "../Customizations/Layout"; import Translations from "./i18n/Translations"; import {VariableUiElement} from "./Base/VariableUIElement"; +import {Utils} from "../Utils"; export class WelcomeMessage extends UIElement { private readonly layout: Layout; @@ -20,7 +21,7 @@ export class WelcomeMessage extends UIElement { constructor() { super(State.state.osmConnection.userDetails); - this.languagePicker = Locale.CreateLanguagePicker(Translations.t.general.pickLanguage); + this.languagePicker = Utils.CreateLanguagePicker(Translations.t.general.pickLanguage); this.ListenTo(Locale.language); function fromLayout(f: (layout: Layout) => (string | UIElement)): UIElement { diff --git a/UI/i18n/Locale.ts b/UI/i18n/Locale.ts index b2b5019..821cfbf 100644 --- a/UI/i18n/Locale.ts +++ b/UI/i18n/Locale.ts @@ -7,15 +7,17 @@ import {State} from "../../State"; export default class Locale { - public static language: UIEventSource = LocalStorageSource.Get('language', "en"); - public static CreateLanguagePicker(label: string | UIElement = "") { - - return new DropDown(label, State.state.layoutToUse.data.supportedLanguages.map(lang => { - return {value: lang, shown: lang} - } - ), Locale.language); + public static language: UIEventSource = Locale.setup(); + private static setup() { + const source = LocalStorageSource.Get('language', "en"); + // @ts-ignore + window.setLanguage = function (language: string) { + source.setData(language) + } + return source; } + } diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index f021ce7..0e67fb9 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -793,8 +793,8 @@ export default class Translations { }), header: new T({ - en: "

No data

You clicked somewhere where no data is known yet.
", - nl: "

Geen selectie

Je klikte ergens waar er nog geen data is.
", + en: "

Add a point?

You clicked somewhere where no data is known yet.
", + nl: "

Punt toevoegen?

Je klikte ergens waar er nog geen data is.
", fr: "

Pas de données

vous avez cliqué sur un endroit ou il n'y a pas encore de données.
" }), @@ -814,8 +814,8 @@ export default class Translations { fr: "Chargement des donnés. Patientez un instant avant d'ajouter un nouveau point" }), confirmIntro: new T({ - en: "

Add a {title} here?

The point you create here will be visible for everyone. Please, only add things on to the map if they truly exist. A lot of applications use this data.", - nl: "

Voeg hier een {title} toe?

Het punt dat je hier toevoegt, is zichtbaar voor iedereen. Veel applicaties gebruiken deze data, voeg dus enkel punten toe die echt bestaan.", + en: "

Add a {title} here?

The point you create here will be visible for everyone. Please, only add things on to the map if they truly exist. A lot of applications use this data.", + nl: "

Voeg hier een {title} toe?

Het punt dat je hier toevoegt, is zichtbaar voor iedereen. Veel applicaties gebruiken deze data, voeg dus enkel punten toe die echt bestaan.", fr: "

Ajouter un/une {title} ici?

Le point que vous ajouter sera visible par tout le monde. Merci d'etre sûr que ce point existe réellement. Beaucoup d'autres applications reposent sur ces données.", }) @@ -952,6 +952,16 @@ export default class Translations { nl: "Ga naar de berichten", fr: "Ouvrir les messages" }) + }, + favourite: { + title: "Custom", + description: new T({ + en: "

Your custom theme

In your custom theme, you can add some favourite layers from other themes to create a custom theme." + }), + panelIntro: new T({ + en:"

Your custom theme

Create your own theme here by picking your favourite layers" + }) + } } diff --git a/Utils.ts b/Utils.ts index 081cd24..6391016 100644 --- a/Utils.ts +++ b/Utils.ts @@ -1,3 +1,8 @@ +import {UIElement} from "./UI/UIElement"; +import {DropDown} from "./UI/Input/DropDown"; +import {State} from "./State"; +import Locale from "./UI/i18n/Locale"; + export class Utils { /** @@ -18,4 +23,22 @@ export class Utils { public static Upper(str : string){ return str.substr(0,1).toUpperCase() + str.substr(1); } + + static DoEvery(millis: number, f: (() => void)) { + window.setTimeout( + function () { + f(); + Utils.DoEvery(millis, f); + } + , millis) + } + + public static CreateLanguagePicker(label: string | UIElement = "") { + + return new DropDown(label, State.state.layoutToUse.data.supportedLanguages.map(lang => { + return {value: lang, shown: lang} + } + ), Locale.language); + } + } diff --git a/index.css b/index.css index 90cb1ce..c20b66b 100644 --- a/index.css +++ b/index.css @@ -1241,4 +1241,65 @@ form { .add-ui { font-size: large; +} + + +.custom-layer-panel { + +} + + +.custom-layer-panel-header { + display: flex; + flex-wrap: nowrap; + flex-direction: row; + font-size: large; + margin: 0.5em; + background-color: white; + justify-content: flex-start; + align-items: center; + text-decoration: none; + color: black; +} + +.custom-layer-panel-header-img img { + max-width: 3em; + width: 100%; + max-height: 3em; + padding: 0.5em; +} + +.custom-layer-panel-header-img { + width: 4em; + height: 4em; + +} + +.custom-layer-checkbox { + font-size: larger; + height: 2em; + background-color: #e5f5ff; + margin:0.3em; + margin-left: 2em; + display: flex; + justify-content: flex-start; + align-items: stretch; + text-decoration: none; + padding: 0.5em; + border-radius: 1em; +} +.custom-layer-checkbox img { + max-width: 1.5em; + max-height: 1.5em; + width: 100%; + height: 100%; + padding: 0.2em; + padding-right: 0.5em; +} + +.custom-layer-checkbox svg { + max-width: 1.5em; + max-height: 1.5em; + padding: 0.2em; + padding-right: 0.5em; } \ No newline at end of file diff --git a/index.ts b/index.ts index 8992340..8121838 100644 --- a/index.ts +++ b/index.ts @@ -1,37 +1,21 @@ -import {ElementStorage} from "./Logic/ElementStorage"; -import {UIEventSource} from "./UI/UIEventSource"; import {UserBadge} from "./UI/UserBadge"; -import {PendingChanges} from "./UI/PendingChanges"; import {CenterMessageBox} from "./UI/CenterMessageBox"; -import {Helpers} from "./Helpers"; import {TagUtils} from "./Logic/TagsFilter"; import {LayerUpdater} from "./Logic/LayerUpdater"; -import {UIElement} from "./UI/UIElement"; import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler"; import {FeatureInfoBox} from "./UI/FeatureInfoBox"; import {SimpleAddUI} from "./UI/SimpleAddUI"; -import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {SearchAndGo} from "./UI/SearchAndGo"; import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; -import {CheckBox} from "./UI/Input/CheckBox"; -import Translations from "./UI/i18n/Translations"; -import Locale from "./UI/i18n/Locale"; import {Layout} from "./Customizations/Layout"; -import {DropDown} from "./UI/Input/DropDown"; import {FixedUiElement} from "./UI/Base/FixedUiElement"; -import {LayerSelection} from "./UI/LayerSelection"; -import Combine from "./UI/Base/Combine"; -import {Img} from "./UI/Img"; import {QueryParameters} from "./Logic/QueryParameters"; -import {Utils} from "./Utils"; -import {LocalStorageSource} from "./Logic/LocalStorageSource"; import {InitUiElements} from "./InitUiElements"; import {StrayClickHandler} from "./Logic/Leaflet/StrayClickHandler"; -import {BaseLayers, Basemap} from "./Logic/Leaflet/Basemap"; import {GeoLocationHandler} from "./Logic/Leaflet/GeoLocationHandler"; -import {OsmConnection} from "./Logic/Osm/OsmConnection"; -import {Changes} from "./Logic/Osm/Changes"; import {State} from "./State"; +import {All} from "./Customizations/Layouts/All"; +import {CustomLayers} from "./Logic/CustomLayers"; // --------------------- Special actions based on the parameters ----------------- @@ -79,114 +63,59 @@ for (const k in AllKnownLayouts.allSets) { defaultLayout = QueryParameters.GetQueryParameter("layout", defaultLayout).data; const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout] ?? AllKnownLayouts["all"]; -console.log("Using layout: ", layoutToUse.name); if (layoutToUse === undefined) { console.log("Incorrect layout") + new FixedUiElement("Error: incorrect layout " + defaultLayout + "Go to MapComplete").AttachTo("centermessage").onClick(() => { + }); + throw "Incorrect layout" } -// Setup the global state +console.log("Using layout: ", layoutToUse.name); + State.state = new State(layoutToUse); -const state = State.state; - - -// ----------------- Prepare the important objects ----------------- -state.osmConnection = new OsmConnection( - QueryParameters.GetQueryParameter("test", "false").data === "true", - QueryParameters.GetQueryParameter("oauth_token", undefined) -); - - -Locale.language.syncWith(state.osmConnection.GetPreference("language")); - -// @ts-ignore -window.setLanguage = function (language: string) { - Locale.language.setData(language) -} - -Locale.language.addCallback((currentLanguage) => { - if (layoutToUse.supportedLanguages.indexOf(currentLanguage) < 0) { - console.log("Resetting languate to", layoutToUse.supportedLanguages[0], "as", currentLanguage, " is unsupported") - // The current language is not supported -> switch to a supported one - Locale.language.setData(layoutToUse.supportedLanguages[0]); - } -}).ping() - - -state.allElements = new ElementStorage(); -state.changes = new Changes( - "Beantwoorden van vragen met #MapComplete voor vragenset #" + state.layoutToUse.data.name, - state.osmConnection, state.allElements); -state.bm = new Basemap("leafletDiv", state.locationControl, new VariableUiElement( - state.locationControl.map((location) => { - const mapComplete = "Mapcomple " + - " " + - "Report bug"; - let editHere = ""; - if (location !== undefined) { - editHere = " | " + - "" + - "edit here" + - "" - } - return mapComplete + editHere; - - }) -)); - +function setupAllLayerElements() { // ------------- Setup the layers ------------------------------- -const layerSetup = InitUiElements.InitLayers(); + const layerSetup = InitUiElements.InitLayers(); -const layerUpdater = new LayerUpdater(layerSetup.minZoom, layoutToUse.widenFactor, layerSetup.flayers); - - -// --------------- Setting up layer selection ui -------- - -const closedFilterButton = ``; - -const openFilterButton = ` -`; - -let baseLayerOptions = BaseLayers.baseLayers.map((layer) => { - return {value: layer, shown: layer.name} -}); -const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLayerOptions, State.state.bm.CurrentLayer), openFilterButton]); -const layerSelection = new Combine([`

Maplayers

`, new LayerSelection(layerSetup.flayers)]); -let layerControl = backgroundMapPicker; -if (layerSetup.flayers.length > 1) { - layerControl = new Combine([layerSelection, backgroundMapPicker]); -} - -InitUiElements.OnlyIf(State.state.featureSwitchLayers, () => { - - const checkbox = new CheckBox(layerControl, closedFilterButton); - checkbox.AttachTo("filter__selection"); - State.state.bm.Location.addCallback(() => { - checkbox.isEnabled.setData(false); - }); - -}); + const layerUpdater = new LayerUpdater(layerSetup.minZoom, layoutToUse.widenFactor, layerSetup.flayers); + InitUiElements.InitLayerSelection(layerSetup) // ------------------ Setup various other UI elements ------------ -document.title = Translations.W(layoutToUse.title).InnerRender(); -Locale.language.addCallback(e => { - document.title = Translations.W(layoutToUse.title).InnerRender(); -}) + InitUiElements.OnlyIf(State.state.featureSwitchAddNew, () => { + new StrayClickHandler(() => { + return new SimpleAddUI( + layerUpdater.runningQuery, + layerSetup.presets); + } + ); + }); + new CenterMessageBox( + layerSetup.minZoom, + layerUpdater.runningQuery) + .AttachTo("centermessage"); -InitUiElements.OnlyIf(State.state.featureSwitchAddNew, () => { - new StrayClickHandler(() => { - return new SimpleAddUI( - layerUpdater.runningQuery, - layerSetup.presets); +} + +setupAllLayerElements(); + +if (layoutToUse === AllKnownLayouts.allSets[CustomLayers.NAME]) { + State.state.favourteLayers.addCallback((favs) => { + for (const fav of favs) { + const layer = AllKnownLayouts.allLayers[fav]; + if (!!layer) { + layoutToUse.layers.push(layer); + } + setupAllLayerElements(); } - ); -}); + }) +} /** @@ -219,7 +148,6 @@ State.state.selectedElement.addCallback((feature) => { } ); -console.log("Enable new:",State.state.featureSwitchAddNew.data,"deafult", layoutToUse.enableAdd) InitUiElements.OnlyIf(State.state.featureSwitchUserbadge, () => { new UserBadge().AttachTo('userbadge'); }); @@ -241,16 +169,6 @@ if ((window != window.top && !State.state.featureSwitchWelcomeMessage) || State. } -new CenterMessageBox( - layerSetup.minZoom, - layerUpdater.runningQuery) - .AttachTo("centermessage"); - - -Helpers.SetupAutoSave(); -Helpers.LastEffortSave(); - - new GeoLocationHandler().AttachTo("geolocate-button"); diff --git a/test.ts b/test.ts index 51edd2c..8abf879 100644 --- a/test.ts +++ b/test.ts @@ -1,32 +1,11 @@ -import {ImageUploadFlow} from "./UI/ImageUploadFlow"; -import {OsmConnection, UserDetails} from "./Logic/Osm/OsmConnection"; -import {OsmImageUploadHandler} from "./Logic/Osm/OsmImageUploadHandler"; -import {UIEventSource} from "./UI/UIEventSource"; -import {Changes} from "./Logic/Osm/Changes"; -import {SlideShow} from "./UI/SlideShow"; -import {ElementStorage} from "./Logic/ElementStorage"; -import {isNullOrUndefined} from "util"; -import Locale from "./UI/i18n/Locale"; +import {State} from "./State"; +import Cyclofix from "./Customizations/Layouts/Cyclofix"; +import {CustomLayersPanel} from "./Logic/CustomLayersPanel"; -const osmConnection = new OsmConnection(true, new UIEventSource(undefined)); -const uploadHandler = new OsmImageUploadHandler( - new UIEventSource({}), - osmConnection.userDetails, - new UIEventSource("cc0"), - new Changes("blabla", osmConnection, new ElementStorage()), - undefined); +State.state= new State(new Cyclofix()); -new ImageUploadFlow( - osmConnection.userDetails, - new UIEventSource("cc0"), - (license: string) => { - return { - title: "test", - description: "test", - handleURL: console.log, - allDone: () => { - } - } - }).AttachTo("maindiv") +new CustomLayersPanel().AttachTo("maindiv"); -Locale.language.setData("nl") \ No newline at end of file +State.state.osmConnection.GetPreference("mapcomplete-custom-layer-count").addCallback((count) => console.log("Count: ", count)) + +State.state.favourteLayers.addCallback(console.log) \ No newline at end of file