From 7deb9b5d53bdc594b5d04ea76148fa7e64bb2766 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Wed, 14 Jul 2021 16:05:50 +0200 Subject: [PATCH 1/3] Refactoring of AvailableBaseLayer --- InitUiElements.ts | 2 +- Logic/Actors/AvailableBaseLayers.ts | 95 ++++++++++++++++++++--------- UI/Base/Minimap.ts | 2 +- UI/BigComponents/SimpleAddUI.ts | 22 ++++--- UI/Input/LocationInput.ts | 48 ++------------- 5 files changed, 90 insertions(+), 79 deletions(-) diff --git a/InitUiElements.ts b/InitUiElements.ts index 0f1143eba7..0dbc7eaac7 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -341,7 +341,7 @@ export class InitUiElements { private static InitBaseMap() { - State.state.availableBackgroundLayers = new AvailableBaseLayers(State.state.locationControl).availableEditorLayers; + State.state.availableBackgroundLayers = AvailableBaseLayers.AvailableLayersAt(State.state.locationControl); State.state.backgroundLayer = State.state.backgroundLayerId .map((selectedId: string) => { diff --git a/Logic/Actors/AvailableBaseLayers.ts b/Logic/Actors/AvailableBaseLayers.ts index 52b1c12de1..e84ecc6356 100644 --- a/Logic/Actors/AvailableBaseLayers.ts +++ b/Logic/Actors/AvailableBaseLayers.ts @@ -7,7 +7,6 @@ import {UIEventSource} from "../UIEventSource"; import {GeoOperations} from "../GeoOperations"; import {Utils} from "../../Utils"; import Loc from "../../Models/Loc"; -import {isBoolean} from "util"; /** * Calculates which layers are available at the current location @@ -31,42 +30,82 @@ export default class AvailableBaseLayers { category: "osmbasedmap" } - public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex()); - public availableEditorLayers: UIEventSource; - constructor(location: UIEventSource) { - const self = this; - this.availableEditorLayers = - location.map( - (currentLocation) => { + public static AvailableLayersAt(location: UIEventSource): UIEventSource { + const source = location.map( + (currentLocation) => { - if (currentLocation === undefined) { - return AvailableBaseLayers.layerOverview; - } + if (currentLocation === undefined) { + return AvailableBaseLayers.layerOverview; + } - const currentLayers = self.availableEditorLayers?.data; - const newLayers = AvailableBaseLayers.AvailableLayersAt(currentLocation?.lon, currentLocation?.lat); + const currentLayers = source?.data; // A bit unorthodox - I know + const newLayers = AvailableBaseLayers.CalculateAvailableLayersAt(currentLocation?.lon, currentLocation?.lat); - if (currentLayers === undefined) { + if (currentLayers === undefined) { + return newLayers; + } + if (newLayers.length !== currentLayers.length) { + return newLayers; + } + for (let i = 0; i < newLayers.length; i++) { + if (newLayers[i].name !== currentLayers[i].name) { return newLayers; } - if (newLayers.length !== currentLayers.length) { - return newLayers; - } - for (let i = 0; i < newLayers.length; i++) { - if (newLayers[i].name !== currentLayers[i].name) { - return newLayers; - } - } - - return currentLayers; - }); - + } + return currentLayers; + }); + return source; } - private static AvailableLayersAt(lon: number, lat: number): BaseLayer[] { + public static SelectBestLayerAccordingTo(location: UIEventSource, preferedCategory: UIEventSource): UIEventSource { + return AvailableBaseLayers.AvailableLayersAt(location).map(available => { + // First float all 'best layers' to the top + available.sort((a, b) => { + if (a.isBest && b.isBest) { + return 0; + } + if (!a.isBest) { + return 1 + } + + return -1; + } + ) + + if (preferedCategory.data === undefined) { + return available[0] + } + + let prefered: string [] + if (typeof preferedCategory.data === "string") { + prefered = [preferedCategory.data] + } else { + prefered = preferedCategory.data; + } + + prefered.reverse(); + for (const category of prefered) { + //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top + available.sort((a, b) => { + if (a.category === category && b.category === category) { + return 0; + } + if (a.category !== category) { + return 1 + } + + return -1; + } + ) + } + return available[0] + }) + } + + private static CalculateAvailableLayersAt(lon: number, lat: number): BaseLayer[] { const availableLayers = [AvailableBaseLayers.osmCarto] const globalLayers = []; for (const layerOverviewItem of AvailableBaseLayers.layerOverview) { @@ -146,7 +185,7 @@ export default class AvailableBaseLayers { layer: leafletLayer, feature: layer, isBest: props.best ?? false, - category: props.category + category: props.category }); } return layers; diff --git a/UI/Base/Minimap.ts b/UI/Base/Minimap.ts index 73bf2354aa..2c38e8b74b 100644 --- a/UI/Base/Minimap.ts +++ b/UI/Base/Minimap.ts @@ -52,7 +52,7 @@ export default class Minimap extends BaseUIElement { return wrapper; } - + private InitMap() { if (this._constructedHtmlElement === undefined) { // This element isn't initialized yet diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index 05fb52c64c..9d1fd1475e 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -19,6 +19,7 @@ import {Translation} from "../i18n/Translation"; import LocationInput from "../Input/LocationInput"; import {InputElement} from "../Input/InputElement"; import Loc from "../../Models/Loc"; +import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; /* * The SimpleAddUI is a single panel, which can have multiple states: @@ -115,14 +116,21 @@ export default class SimpleAddUI extends Toggle { let location = State.state.LastClickLocation; let preciseInput: InputElement = undefined if (preset.preciseInput !== undefined) { + const locationSrc = new UIEventSource({ + lat: location.data.lat, + lon: location.data.lon, + zoom: 19 + }); + + let backgroundLayer = undefined; + if(preset.preciseInput.preferredBackground){ + backgroundLayer= AvailableBaseLayers.SelectBestLayerAccordingTo(locationSrc, new UIEventSource(preset.preciseInput.preferredBackground)) + } + preciseInput = new LocationInput({ - preferCategory: preset.preciseInput.preferredBackground ?? State.state.backgroundLayer, - centerLocation: - new UIEventSource({ - lat: location.data.lat, - lon: location.data.lon, - zoom: 19 - }) + mapBackground: backgroundLayer, + centerLocation:locationSrc + }) preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;") } diff --git a/UI/Input/LocationInput.ts b/UI/Input/LocationInput.ts index cee2f5cbfb..d568e4443f 100644 --- a/UI/Input/LocationInput.ts +++ b/UI/Input/LocationInput.ts @@ -2,30 +2,27 @@ import {InputElement} from "./InputElement"; import Loc from "../../Models/Loc"; import {UIEventSource} from "../../Logic/UIEventSource"; import Minimap from "../Base/Minimap"; -import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; import BaseLayer from "../../Models/BaseLayer"; import Combine from "../Base/Combine"; import Svg from "../../Svg"; +import State from "../../State"; export default class LocationInput extends InputElement { IsSelected: UIEventSource = new UIEventSource(false); private _centerLocation: UIEventSource; - private readonly preferCategory; + private readonly mapBackground : UIEventSource; constructor(options?: { + mapBackground?: UIEventSource, centerLocation?: UIEventSource, - preferCategory?: string | UIEventSource, }) { super(); options = options ?? {} options.centerLocation = options.centerLocation ?? new UIEventSource({lat: 0, lon: 0, zoom: 1}) this._centerLocation = options.centerLocation; - if(typeof options.preferCategory === "string"){ - options.preferCategory = new UIEventSource(options.preferCategory); - } - this.preferCategory = options.preferCategory ?? new UIEventSource(undefined) + this.mapBackground = options.mapBackground ?? State.state.backgroundLayer this.SetClass("block h-full") } @@ -38,43 +35,10 @@ export default class LocationInput extends InputElement { } protected InnerConstructElement(): HTMLElement { - const layer: UIEventSource = new AvailableBaseLayers(this._centerLocation).availableEditorLayers.map(allLayers => { - // First float all 'best layers' to the top - allLayers.sort((a, b) => { - if (a.isBest && b.isBest) { - return 0; - } - if (!a.isBest) { - return 1 - } - - return -1; - } - ) - if (this.preferCategory) { - const self = this; - //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top - allLayers.sort((a, b) => { - const preferred = self.preferCategory.data - if (a.category === preferred && b.category === preferred) { - return 0; - } - if (a.category !== preferred) { - return 1 - } - - return -1; - } - ) - } - return allLayers[0] - }, [this.preferCategory] - ) - layer.addCallbackAndRunD(layer => console.log(layer)) const map = new Minimap( { location: this._centerLocation, - background: layer + background: this.mapBackground } ) map.leafletMap.addCallbackAndRunD(leaflet => { @@ -84,7 +48,7 @@ export default class LocationInput extends InputElement { ) }) - layer.map(layer => { + this.mapBackground.map(layer => { const leaflet = map.leafletMap.data if (leaflet === undefined || layer === undefined) { From 46d57edea0dd7a3f4bab5b5febbda033eb2f43e4 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Thu, 15 Jul 2021 21:01:10 +0200 Subject: [PATCH 2/3] Translation sync --- assets/themes/artwork/artwork.json | 2 +- assets/themes/bicycle_library/bicycle_library.json | 6 ++++-- assets/themes/openwindpowermap/openwindpowermap.json | 11 ++++++----- langs/themes/de.json | 8 ++++---- langs/themes/en.json | 7 +++++++ langs/themes/nl.json | 7 +++++++ 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/assets/themes/artwork/artwork.json b/assets/themes/artwork/artwork.json index 7b8cc876c1..c3b7b7c552 100644 --- a/assets/themes/artwork/artwork.json +++ b/assets/themes/artwork/artwork.json @@ -374,7 +374,7 @@ "en": "Is there a website with more information about this artwork?", "nl": "Op welke website kan men meer informatie vinden over dit kunstwerk?", "fr": "Sur quel site web pouvons-nous trouver plus d'informations sur cette œuvre d'art?", - "de": "Auf welcher Website gibt es mehr Informationen über dieses Kunstwerk?", + "de": "Gibt es eine Website mit weiteren Informationen über dieses Kunstwerk?", "it": "Esiste un sito web con maggiori informazioni su quest’opera?", "ru": "Есть ли сайт с более подробной информацией об этой работе?", "ja": "この作品についての詳しい情報はどのウェブサイトにありますか?", diff --git a/assets/themes/bicycle_library/bicycle_library.json b/assets/themes/bicycle_library/bicycle_library.json index 437020a3fc..6d0cf61e2b 100644 --- a/assets/themes/bicycle_library/bicycle_library.json +++ b/assets/themes/bicycle_library/bicycle_library.json @@ -10,7 +10,8 @@ "ja", "fr", "zh_Hant", - "nb_NO" + "nb_NO", + "de" ], "title": { "en": "Bicycle libraries", @@ -20,7 +21,8 @@ "ja": "自転車ライブラリ", "fr": "Vélothèques", "zh_Hant": "單車圖書館", - "nb_NO": "Sykkelbibliotek" + "nb_NO": "Sykkelbibliotek", + "de": "Fahrradbibliothek" }, "description": { "nl": "Een fietsbibliotheek is een plaats waar men een fiets kan lenen, vaak voor een klein bedrag per jaar. Een typisch voorbeeld zijn kinderfietsbibliotheken, waar men een fiets op maat van het kind kan lenen. Is het kind de fiets ontgroeid, dan kan het te kleine fietsje omgeruild worden voor een grotere.", diff --git a/assets/themes/openwindpowermap/openwindpowermap.json b/assets/themes/openwindpowermap/openwindpowermap.json index b1e4ecaa7c..22bba27ef9 100644 --- a/assets/themes/openwindpowermap/openwindpowermap.json +++ b/assets/themes/openwindpowermap/openwindpowermap.json @@ -56,7 +56,7 @@ "tagRenderings": [ { "render": { - "en": "The power output of this wind turbine is {canonical(generator:output:electricity)}." + "en": "The power output of this wind turbine is {generator:output:electricity}." }, "question": { "en": "What is the power output of this wind turbine? (e.g. 2.3 MW)" @@ -79,7 +79,7 @@ }, { "render": { - "en": "The total height (including rotor radius) of this wind turbine is {canonical(height)}." + "en": "The total height (including rotor radius) of this wind turbine is {height} metres." }, "question": { "en": "What is the total height of this wind turbine (including rotor radius), in metres?" @@ -91,7 +91,7 @@ }, { "render": { - "en": "The rotor diameter of this wind turbine is {canonical(rotor:diameter)}." + "en": "The rotor diameter of this wind turbine is {rotor:diameter} metres." }, "question": { "en": "What is the rotor diameter of this wind turbine, in metres?" @@ -129,7 +129,7 @@ } ], "units": [ - { + { "appliesToKey": [ "generator:output:electricity" ], @@ -183,7 +183,8 @@ }, { "appliesToKey": [ - "height","rotor:diameter" + "height", + "rotor:diameter" ], "applicableUnits": [ { diff --git a/langs/themes/de.json b/langs/themes/de.json index 95abb60b17..6a0b29fad1 100644 --- a/langs/themes/de.json +++ b/langs/themes/de.json @@ -87,6 +87,9 @@ "shortDescription": "Eine Karte aller Sitzbänke", "description": "Diese Karte zeigt alle Sitzbänke, die in OpenStreetMap eingetragen sind: Einzeln stehende Bänke und Bänke, die zu Haltestellen oder Unterständen gehören. Mit einem OpenStreetMap-Account können Sie neue Bänke eintragen oder Detailinformationen existierender Bänke bearbeiten." }, + "bicyclelib": { + "title": "Fahrradbibliothek" + }, "bookcases": { "title": "Öffentliche Bücherschränke Karte", "description": "Ein öffentlicher Bücherschrank ist ein kleiner Bücherschrank am Straßenrand, ein Kasten, eine alte Telefonzelle oder andere Gegenstände, in denen Bücher aufbewahrt werden. Jeder kann ein Buch hinstellen oder mitnehmen. Diese Karte zielt darauf ab, all diese Bücherschränke zu sammeln. Sie können neue Bücherschränke in der Nähe entdecken und mit einem kostenlosen OpenStreetMap-Account schnell Ihre Lieblingsbücherschränke hinzufügen." @@ -327,8 +330,5 @@ "toilets": { "title": "Offene Toilette Karte", "description": "Eine Karte der öffentlichen Toiletten" - }, - "bicyclelib": { - "title": "Fahrradbibliothek" } -} +} \ No newline at end of file diff --git a/langs/themes/en.json b/langs/themes/en.json index 48852d5a4c..f5db488b97 100644 --- a/langs/themes/en.json +++ b/langs/themes/en.json @@ -1143,6 +1143,13 @@ "human": " gigawatts" } } + }, + "1": { + "applicableUnits": { + "0": { + "human": " meter" + } + } } } }, diff --git a/langs/themes/nl.json b/langs/themes/nl.json index 7966e9e2d1..44bf09b5f4 100644 --- a/langs/themes/nl.json +++ b/langs/themes/nl.json @@ -919,6 +919,13 @@ "human": " gigawatt" } } + }, + "1": { + "applicableUnits": { + "0": { + "human": " meter" + } + } } } }, From 0af3a91fde5c9a72457d565d5a061145eb112eaa Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Fri, 16 Jul 2021 00:57:33 +0200 Subject: [PATCH 3/3] Fix licenses, small improvement to icon --- assets/svg/crosshair-locked.svg | 69 ++++++++++++++++----------------- assets/svg/license_info.json | 14 ++++++- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/assets/svg/crosshair-locked.svg b/assets/svg/crosshair-locked.svg index b1a741c287..d8d04340cd 100644 --- a/assets/svg/crosshair-locked.svg +++ b/assets/svg/crosshair-locked.svg @@ -25,9 +25,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="2.8284271" - inkscape:cx="67.47399" - inkscape:cy="29.788021" + inkscape:zoom="5.6568542" + inkscape:cx="27.044982" + inkscape:cy="77.667126" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -68,40 +68,39 @@ inkscape:groupmode="layer" id="layer1" transform="translate(0,-270.54165)"> - - - - - + id="g827"> + + inkscape:connector-curvature="0" + id="path817" + d="M 3.2841366,283.77082 H 1.0418969" + style="fill:none;stroke:#5555ec;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" /> + + + + diff --git a/assets/svg/license_info.json b/assets/svg/license_info.json index 1ef8f94c8e..f82b5fb71f 100644 --- a/assets/svg/license_info.json +++ b/assets/svg/license_info.json @@ -162,6 +162,18 @@ "license": "CC0; trivial", "sources": [] }, + { + "authors": [], + "path": "crosshair-empty.svg", + "license": "CC0; trivial", + "sources": [] + }, + { + "authors": [], + "path": "crosshair-locked.svg", + "license": "CC0; trivial", + "sources": [] + }, { "authors": [ "Dave Gandy" @@ -204,7 +216,7 @@ "license": "CC0", "sources": [ "https://commons.wikimedia.org/wiki/File:Media-floppy.svg", - " http://tango.freedesktop.org/Tango_Desktop_Project" + "http://tango.freedesktop.org/Tango_Desktop_Project" ] }, {