From 3e3da25edba731ea17d125577ff503493633b996 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Fri, 23 Apr 2021 17:22:01 +0200 Subject: [PATCH] Small fixes --- .gitignore | 2 +- InitUiElements.ts | 2 +- Logic/Web/MangroveReviews.ts | 58 +++++----- Models/Constants.ts | 2 +- UI/BigComponents/AttributionPanel.ts | 21 +++- UI/SubstitutedTranslation.ts | 6 + UI/i18n/Translation.ts | 1 + .../layers/grass_in_parks/grass_in_parks.json | 2 +- .../layers/nature_reserve/nature_reserve.json | 3 +- assets/layers/playground/playground.json | 23 +++- assets/layers/sport_pitch/license_info.json | 109 +++++++++++++++++- assets/layers/sport_pitch/sport_pitch.json | 46 +++++++- assets/layers/sport_pitch/tabletennis.svg | 5 - .../layers/village_green/village_green.json | 2 +- assets/license_info.json | 4 +- assets/svg/license_info.json | 8 +- assets/themes/speelplekken/speelplekken.json | 67 +++++------ scripts/generateLicenseInfo.ts | 5 + 18 files changed, 263 insertions(+), 103 deletions(-) delete mode 100644 assets/layers/sport_pitch/tabletennis.svg diff --git a/.gitignore b/.gitignore index 6e2d1fd..6301889 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ assets/generated/* .parcel-cache Docs/Tools/stats.*.json Docs/Tools/stats.csv - +missing_translations.txt diff --git a/InitUiElements.ts b/InitUiElements.ts index d2e4b9e..908eb20 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -375,8 +375,8 @@ export class InitUiElements { state.layoutToUse.map(layoutToUse => { const flayers = []; + for (const layer of layoutToUse.layers) { - const isDisplayed = QueryParameters.GetQueryParameter("layer-" + layer.id, "true", "Wether or not layer " + layer.id + " is shown") .map((str) => str !== "false", [], (b) => b.toString()); const flayer = { diff --git a/Logic/Web/MangroveReviews.ts b/Logic/Web/MangroveReviews.ts index 90c18a5..aeaeeb1 100644 --- a/Logic/Web/MangroveReviews.ts +++ b/Logic/Web/MangroveReviews.ts @@ -3,9 +3,9 @@ import {UIEventSource} from "../UIEventSource"; import {Review} from "./Review"; export class MangroveIdentity { - private readonly _mangroveIdentity: UIEventSource; public keypair: any = undefined; public readonly kid: UIEventSource = new UIEventSource(undefined); + private readonly _mangroveIdentity: UIEventSource; constructor(mangroveIdentity: UIEventSource) { const self = this; @@ -26,7 +26,7 @@ export class MangroveIdentity { if ((mangroveIdentity.data ?? "") === "") { this.CreateIdentity(); } - }catch(e){ + } catch (e) { console.error("Could not create identity: ", e) } } @@ -53,46 +53,47 @@ export class MangroveIdentity { } export default class MangroveReviews { + private static _reviewsCache = {}; + private static didWarn = false; private readonly _lon: number; private readonly _lat: number; private readonly _name: string; private readonly _reviews: UIEventSource = new UIEventSource([]); private _dryRun: boolean; private _mangroveIdentity: MangroveIdentity; - private _lastUpdate : Date = undefined; + private _lastUpdate: Date = undefined; + + private constructor(lon: number, lat: number, name: string, + identity: MangroveIdentity, + dryRun?: boolean) { - private static _reviewsCache = {}; - - public static Get(lon: number, lat: number, name: string, - identity: MangroveIdentity, - dryRun?: boolean){ - const newReviews = new MangroveReviews(lon, lat, name, identity, dryRun); - - const uri = newReviews.GetSubjectUri(); - const cached = MangroveReviews._reviewsCache[uri]; - if(cached !== undefined){ - return cached; - } - MangroveReviews._reviewsCache[uri] = newReviews; - - return newReviews; - } - - private constructor(lon: number, lat: number, name: string, - identity: MangroveIdentity, - dryRun?: boolean) { - this._lon = lon; this._lat = lat; this._name = name; this._mangroveIdentity = identity; this._dryRun = dryRun; - if(dryRun){ + if (dryRun && !MangroveReviews.didWarn) { + MangroveReviews.didWarn = true; console.warn("Mangrove reviews will _not_ be saved as dryrun is specified") } } + public static Get(lon: number, lat: number, name: string, + identity: MangroveIdentity, + dryRun?: boolean) { + const newReviews = new MangroveReviews(lon, lat, name, identity, dryRun); + + const uri = newReviews.GetSubjectUri(); + const cached = MangroveReviews._reviewsCache[uri]; + if (cached !== undefined) { + return cached; + } + MangroveReviews._reviewsCache[uri] = newReviews; + + return newReviews; + } + /** * Gets an URI which represents the item in a mangrove-compatible way * @constructor @@ -111,10 +112,10 @@ export default class MangroveReviews { * Note: rating is between 1 and 100 */ public GetReviews(): UIEventSource { - - if(this._lastUpdate !== undefined && this._reviews.data !== undefined && + + if (this._lastUpdate !== undefined && this._reviews.data !== undefined && (new Date().getTime() - this._lastUpdate.getTime()) < 15000 - ){ + ) { // Last update was pretty recent return this._reviews; } @@ -140,7 +141,6 @@ export default class MangroveReviews { rating: r.rating // percentage points }; - (rev.made_by_user ? reviewsByUser : reviews).push(rev); } diff --git a/Models/Constants.ts b/Models/Constants.ts index 298531e..156f871 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import { Utils } from "../Utils"; export default class Constants { - public static vNumber = "0.6.11a"; + public static vNumber = "0.6.11b"; // The user journey states thresholds when a new feature gets unlocked public static userJourney = { diff --git a/UI/BigComponents/AttributionPanel.ts b/UI/BigComponents/AttributionPanel.ts index b3843c6..f5cf1a8 100644 --- a/UI/BigComponents/AttributionPanel.ts +++ b/UI/BigComponents/AttributionPanel.ts @@ -1,4 +1,3 @@ -import {UIElement} from "../UIElement"; import Combine from "../Base/Combine"; import Translations from "../i18n/Translations"; import Attribution from "./Attribution"; @@ -8,9 +7,8 @@ import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; import {FixedUiElement} from "../Base/FixedUiElement"; import * as licenses from "../../assets/generated/license_info.json" import SmallLicense from "../../Models/smallLicense"; -import {Icon} from "leaflet"; -import Img from "../Base/Img"; import {Utils} from "../../Utils"; +import Link from "../Base/Link"; /** * The attribution panel shown on mobile @@ -48,12 +46,25 @@ export default class AttributionPanel extends Combine { return undefined; } + const sources =Utils.NoNull(Utils.NoEmpty(license.sources)) + return new Combine([ ``, new Combine([ new FixedUiElement(license.authors.join("; ")).SetClass("font-bold"), - new Combine([license.license, license.sources.length > 0 ? " - " : "", - ...license.sources.map(link => `${new URL(link).hostname} `)]).SetClass("block") + new Combine([license.license, + sources.length > 0 ? " - " : "", + ... sources.map(lnk => { + let sourceLinkContent = lnk; + try{ + sourceLinkContent = new URL(lnk).hostname + }catch{ + console.error("Not a valid URL:", lnk) + } + return new Link(sourceLinkContent, lnk, true); + }) + ] + ).SetClass("block") ]).SetClass("flex flex-col") ]).SetClass("flex") } diff --git a/UI/SubstitutedTranslation.ts b/UI/SubstitutedTranslation.ts index 24c200f..7b39e9a 100644 --- a/UI/SubstitutedTranslation.ts +++ b/UI/SubstitutedTranslation.ts @@ -117,6 +117,12 @@ export class SubstitutedTranslation extends UIElement { } } + // Let's to a small sanity check to help the theme designers: + if(template.search(/{[^}]+\([^}]*\)}/) >= 0){ + // Hmm, we might have found an invalid rendering name + console.warn("Found a suspicious special rendering value in: ", template, " did you mean one of: ", SpecialVisualizations.specialVisualizations.map(sp => sp.funcName+"()").join(", ")) + } + // IF we end up here, no changes have to be made - except to remove any resting {} return [new FixedUiElement(template.replace(/{.*}/g, ""))]; } diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts index 6372245..f6adfb2 100644 --- a/UI/i18n/Translation.ts +++ b/UI/i18n/Translation.ts @@ -20,6 +20,7 @@ export class Translation extends UIElement { for (const translationsKey in translations) { count++; if (typeof (translations[translationsKey]) != "string") { + console.error("Non-string object in translation: ", translations[translationsKey]) throw "Error in an object depicting a translation: a non-string object was found. (" + context + ")\n You probably put some other section accidentally in the translation" } } diff --git a/assets/layers/grass_in_parks/grass_in_parks.json b/assets/layers/grass_in_parks/grass_in_parks.json index 9d8bee8..d51cdde 100644 --- a/assets/layers/grass_in_parks/grass_in_parks.json +++ b/assets/layers/grass_in_parks/grass_in_parks.json @@ -32,7 +32,7 @@ ] }, "icon": "./assets/themes/playgrounds/playground.svg", - "iconSize": "40,40,bottom", + "iconSize": "40,40,center", "width": "1", "color": "#0f0", "wayHandling": 2, diff --git a/assets/layers/nature_reserve/nature_reserve.json b/assets/layers/nature_reserve/nature_reserve.json index 301fe7d..f7393c1 100644 --- a/assets/layers/nature_reserve/nature_reserve.json +++ b/assets/layers/nature_reserve/nature_reserve.json @@ -335,7 +335,8 @@ { "#": "Surface area", "render": { - "en": "Surface area: {_surface:ha}Ha" + "en": "Surface area: {_surface:ha}Ha", + "nl": "Totale oppervlakte: {_surface:ha}Ha" }, "mappings":[ { "if": "_surface:ha=0", diff --git a/assets/layers/playground/playground.json b/assets/layers/playground/playground.json index 0dedfe8..e449ea4 100644 --- a/assets/layers/playground/playground.json +++ b/assets/layers/playground/playground.json @@ -13,6 +13,9 @@ ] } }, + "calculatedTags": [ + "_size_classification=Number(feat.properties._surface) < 10 ? 'small' : (Number(feat.properties._surface) < 100 ? 'medium' : 'large') " + ], "description": { "nl": "Speeltuinen", "en": "Playgrounds" @@ -331,7 +334,25 @@ "render": "1" }, "iconSize": { - "render": "40,40,center" + "render": "40,40,center", + "mappings": [ + { + "if": "id~node/.*", + "then": "40,40,center" + }, + { + "if": "_size_classification=small", + "then": "25,25,center" + }, + { + "if": "_size_classification=medium", + "then": "40,40,center" + }, + { + "if": "_size_classification=large", + "then": "60,60,center" + } + ] }, "color": { "render": "#0c3" diff --git a/assets/layers/sport_pitch/license_info.json b/assets/layers/sport_pitch/license_info.json index c0b1696..ee47902 100644 --- a/assets/layers/sport_pitch/license_info.json +++ b/assets/layers/sport_pitch/license_info.json @@ -1,13 +1,112 @@ [ { "authors": [ - "@fontawesome" + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " ], - "path": "tabletennis.svg", - "license": "CC-BY 4.0", + "path": "baseball.svg", + "license": "CC-BY-SA 4.0", "sources": [ - "https://commons.wikimedia.org/wiki/File:Font_Awesome_5_solid_table-tennis.svg", - " https://fontawesome.com" + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "basketball.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "beachvolleyball.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "boules.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "skateboard.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": ".svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "soccer.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "table_tennis.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "tennis.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" + ] + }, + { + "authors": [ + "Gitte Loos (Createlli) in opdracht van Provincie Antwerpen " + ], + "path": "volleyball.svg", + "license": "CC-BY-SA 4.0", + "sources": [ + "https://createlli.com/", + "https://www.provincieantwerpen.be/" ] } ] \ No newline at end of file diff --git a/assets/layers/sport_pitch/sport_pitch.json b/assets/layers/sport_pitch/sport_pitch.json index 51e6995..947aa9d 100644 --- a/assets/layers/sport_pitch/sport_pitch.json +++ b/assets/layers/sport_pitch/sport_pitch.json @@ -4,7 +4,7 @@ "nl": "Sportterrein", "en": "Sport pitches" }, - "wayHandling": 2, + "wayHandling": 1, "minzoom": 12, "source": { "osmTags": { @@ -13,6 +13,9 @@ ] } }, + "calculatedTags": [ + "_size_classification=Number(feat.properties._surface) < 200 ? 'small' : (Number(feat.properties._surface) < 750 ? 'medium' : 'large') " + ], "title": { "render": { "nl": "Sportterrein", @@ -264,7 +267,7 @@ "nl": "Wanneer is dit sportveld toegankelijk?", "en": "When is this pitch accessible?" }, - "render": "{opening_hours()}", + "render": "Openingsuren: {opening_hours_table()}", "freeform": { "key": "opening_hours", "type": "opening_hours" @@ -292,7 +295,25 @@ ], "hideUnderlayingFeaturesMinPercentage": 0, "icon": { - "render": "circle:white;./assets/layers/sport_pitch/tabletennis.svg" + "render": "./assets/layers/sport_pitch/basketball.svg", + "mappings": [ + { + "if": { + "or": [ + "sport=baseball", + "sport=basketball", + "sport=beachvolleyball", + "sport=boules", + "sport=skateboard", + "sport=soccer", + "sport=table_tennis", + "sport=tennis", + "sport=volleyball" + ] + }, + "then": "./assets/layers/sport_pitch/{sport}.svg" + } + ] }, "iconOverlays": [ { @@ -310,7 +331,24 @@ "render": "1" }, "iconSize": { - "render": "25,25,center" + "render": "25,25,center", + "mappings": [ + { + "if": { + "or": ["_size_classification=medium","id~node/.*"] + }, + "then": "40,40,center" + }, + { + "if": "_size_classification=small", + "then": "25,25,center" + }, + + { + "if": "_size_classification=large", + "then": "50,50,center" + } + ] }, "color": { "render": "#009" diff --git a/assets/layers/sport_pitch/tabletennis.svg b/assets/layers/sport_pitch/tabletennis.svg deleted file mode 100644 index f766c7e..0000000 --- a/assets/layers/sport_pitch/tabletennis.svg +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/assets/layers/village_green/village_green.json b/assets/layers/village_green/village_green.json index 524aa86..e339dbf 100644 --- a/assets/layers/village_green/village_green.json +++ b/assets/layers/village_green/village_green.json @@ -21,7 +21,7 @@ ] }, "icon": "./assets/themes/playgrounds/playground.svg", - "iconSize": "40,40,bottom", + "iconSize": "40,40,center", "width": "1", "color": "#0f0", "wayHandling": 2, diff --git a/assets/license_info.json b/assets/license_info.json index 79c0350..aed65a6 100644 --- a/assets/license_info.json +++ b/assets/license_info.json @@ -33,9 +33,7 @@ ], "path": "social_image_front.png", "license": "CC-BY-SA", - "sources": [ - "" - ] + "sources": [] }, { "authors": [ diff --git a/assets/svg/license_info.json b/assets/svg/license_info.json index 3ce5788..07ec4ae 100644 --- a/assets/svg/license_info.json +++ b/assets/svg/license_info.json @@ -6,7 +6,7 @@ "path": "SocialImageForeground.svg", "license": "CC-BY-SA", "sources": [ - "" + "https://mapcomplete.osm.be" ] }, { @@ -15,9 +15,7 @@ ], "path": "add.svg", "license": "CC0", - "sources": [ - "" - ] + "sources": [] }, { "authors": [ @@ -354,7 +352,7 @@ "path": "mapcomplete_logo.svg", "license": "Logo; CC-BY-SA", "sources": [ - "" + "https://mapcomplete.osm.be" ] }, { diff --git a/assets/themes/speelplekken/speelplekken.json b/assets/themes/speelplekken/speelplekken.json index d4e13ab..0bc5af3 100644 --- a/assets/themes/speelplekken/speelplekken.json +++ b/assets/themes/speelplekken/speelplekken.json @@ -30,58 +30,39 @@ "source": { "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", "geoJsonZoomLevel": 14 - } + }, + "icon": "./assets/themes/speelplekken/speelbos.svg" } }, { "builtin": "playground", "override": { - "source": { - "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", - "geoJsonZoomLevel": 14 - } - } - }, - { - "builtin": "sport_pitch", - "override": { - "minzoom": 15, - "source": { - "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", - "geoJsonZoomLevel": 14 - } - } - }, - { - "builtin": "slow_roads", - "override": { - "source": { - "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", - "geoJsonZoomLevel": 14 - }, - "calculatedTags": [ - "_part_of_walking_routes=feat.memberships().map(r => \"\" + r.relation.tags.name + \"\").join(', ')" - ] - } - }, - { - "builtin": "grass_in_parks", - "override": { - "source": { - "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", - "geoJsonZoomLevel": 14 - } + "icon": "./assets/themes/speelplekken/speeltuin.svg" } }, { "builtin": "village_green", "override": { - "source": { - "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", - "geoJsonZoomLevel": 14 - } + "icon": "./assets/themes/speelplekken/speelweide.svg" } }, + { + "builtin": "grass_in_parks", + "override": { + "icon": "./assets/themes/speelplekken/speelweide.svg" + } + }, + "sport_pitch", + + { + "builtin": "slow_roads", + "override": { + "calculatedTags": [ + "_part_of_walking_routes=feat.memberships().map(r => \"\" + r.relation.tags.name + \"\").join(', ')" + ] + } + }, + { "id": "walking_routes", "name": { @@ -190,6 +171,12 @@ } } ], + "overrideAll": { + "source": { + "geoJson": "https://pietervdvn.github.io/speelplekken_cache/speelplekken_{z}_{x}_{y}.geojson", + "geoJsonZoomLevel": 14 + } + }, "roamingRenderings": [ { "render": "Maakt deel uit van {_part_of_walking_routes}", diff --git a/scripts/generateLicenseInfo.ts b/scripts/generateLicenseInfo.ts index 4e6db80..c34d73e 100644 --- a/scripts/generateLicenseInfo.ts +++ b/scripts/generateLicenseInfo.ts @@ -13,6 +13,9 @@ Utils.runningFromConsole = true; function generateLicenseInfos(paths: string[]): SmallLicense[] { const licenses = [] for (const path of paths) { + try{ + + const parsed = JSON.parse(readFileSync(path, "UTF-8")) if (Array.isArray(parsed)) { const l: SmallLicense[] = parsed @@ -30,6 +33,8 @@ function generateLicenseInfos(paths: string[]): SmallLicense[] { smallLicens.path = path.substring(0, 1 + path.lastIndexOf("/")) + smallLicens.path licenses.push(smallLicens) + }}catch(e){ + console.error("Error: ",e, "while handling",path) } }