From 939dad477a218b22dffa2f4bf4f03f8db45a33bd Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Fri, 17 Nov 2023 01:59:41 +0100 Subject: [PATCH 01/21] UX: Small tweaks to walkthrough: show page number, show link underline --- Docs/Studio/Introduction.md | 4 +- src/UI/Walkthrough/Walkthrough.svelte | 2 + src/UI/Walkthrough/WalkthroughStep.svelte | 46 ++++++++++++++--------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Docs/Studio/Introduction.md b/Docs/Studio/Introduction.md index ca858b0cb..40277ef1d 100644 --- a/Docs/Studio/Introduction.md +++ b/Docs/Studio/Introduction.md @@ -34,7 +34,7 @@ OpenStreetMap data can be reused freely, including for commercial purposes. Howe 1. Give attribution 2. Keep the data open - changes to data based on OpenStreetMap must be published under the same license. -You can read the [full copyright notice here](https://osm.org/copyright) +See the [full copyright notice](https://osm.org/copyright) for details This also means that we are *not* allowed to copy data from other maps. Do not enter data based on Google Maps! @@ -83,7 +83,7 @@ These features are based on OpenStreetMap. If some data is not known, the user w -Data can also be loaded and visualised from external sources. No changes can be made to the data in that case. +Data can also be loaded and visualised from external sources. No changes can be made to this externally loaded data in that case. diff --git a/src/UI/Walkthrough/Walkthrough.svelte b/src/UI/Walkthrough/Walkthrough.svelte index 5b1874f93..d3fda9f12 100644 --- a/src/UI/Walkthrough/Walkthrough.svelte +++ b/src/UI/Walkthrough/Walkthrough.svelte @@ -28,6 +28,8 @@ on:next={() => step(1)} isFirst={currentPage === 0} islast={currentPage + 1 === pages.length} + totalPages={pages.length} + pageNumber={currentPage} > diff --git a/src/UI/Walkthrough/WalkthroughStep.svelte b/src/UI/Walkthrough/WalkthroughStep.svelte index ad5beec28..f1dcc955a 100644 --- a/src/UI/Walkthrough/WalkthroughStep.svelte +++ b/src/UI/Walkthrough/WalkthroughStep.svelte @@ -1,30 +1,42 @@ -
+ diff --git a/src/UI/Popup/NearbyImagesCollapsed.svelte b/src/UI/Popup/NearbyImagesCollapsed.svelte index 0a315dcb3..c78917a77 100644 --- a/src/UI/Popup/NearbyImagesCollapsed.svelte +++ b/src/UI/Popup/NearbyImagesCollapsed.svelte @@ -11,6 +11,7 @@ import ToSvelte from "../Base/ToSvelte.svelte" import { XCircleIcon } from "@babeard/svelte-heroicons/solid" import exp from "constants" + import Camera_plus from "../../assets/svg/Camera_plus.svelte"; export let tags: Store export let state: SpecialVisualizationState @@ -42,7 +43,7 @@ expanded = true }} > - + {/if} diff --git a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte index 9db0c8ccd..94f28218f 100644 --- a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte @@ -23,6 +23,8 @@ import UserRelatedState from "../../../Logic/State/UserRelatedState" import { twJoin } from "tailwind-merge" import { TagUtils } from "../../../Logic/Tags/TagUtils" + import Search from "../../../assets/svg/Search.svelte"; + import Login from "../../../assets/svg/Login.svelte"; export let config: TagRenderingConfig export let tags: UIEventSource> @@ -217,7 +219,7 @@ {#if config.mappings?.length >= 8}
- +
{/if} @@ -324,7 +326,7 @@ state?.osmConnection?.AttemptLogin()}> - + {#if $feedback !== undefined} diff --git a/src/UI/Reviews/AllReviews.svelte b/src/UI/Reviews/AllReviews.svelte index 75d5ec63c..fc4b635d0 100644 --- a/src/UI/Reviews/AllReviews.svelte +++ b/src/UI/Reviews/AllReviews.svelte @@ -12,6 +12,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import ToSvelte from "../Base/ToSvelte.svelte" import Svg from "../../Svg" + import Mangrove_logo from "../../assets/svg/Mangrove_logo.svelte"; /** * An element showing all reviews @@ -40,7 +41,7 @@ {/if}
- +
diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 2c65d6228..aea5f3906 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -58,7 +58,6 @@ import { PointImportButtonViz } from "./Popup/ImportButtons/PointImportButtonViz import WayImportButtonViz from "./Popup/ImportButtons/WayImportButtonViz" import ConflateImportButtonViz from "./Popup/ImportButtons/ConflateImportButtonViz" import DeleteWizard from "./Popup/DeleteFlow/DeleteWizard.svelte" -import { OpenJosm } from "./BigComponents/OpenJosm" import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte" import FediverseValidator from "./InputElement/Validators/FediverseValidator" import SendEmail from "./Popup/SendEmail.svelte" @@ -78,6 +77,8 @@ import { TagUtils } from "../Logic/Tags/TagUtils" import Giggity from "./BigComponents/Giggity.svelte" import ThemeViewState from "../Models/ThemeViewState" import LanguagePicker from "./InputElement/LanguagePicker.svelte" +import LogoutButton from "./Base/LogoutButton.svelte" +import OpenJosm from "./Base/OpenJosm.svelte" class NearbyImageVis implements SpecialVisualization { // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests @@ -465,11 +466,7 @@ export default class SpecialVisualizations { needsUrls: [Constants.osmAuthConfig.url], docs: "Shows a button where the user can log out", constr(state: SpecialVisualizationState): BaseUIElement { - return new SubtleButton(Svg.logout_svg(), Translations.t.general.logout, { - imgSize: "w-6 h-6", - }).onClick(() => { - state.osmConnection.LogOut() - }) + return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection }) }, }, new HistogramViz(), @@ -903,10 +900,10 @@ export default class SpecialVisualizations { funcName: "open_in_josm", docs: "Opens the current view in the JOSM-editor", args: [], - needsUrls: OpenJosm.needsUrls, + needsUrls: ["http://127.0.0.1:8111/load_and_zoom"], constr: (state) => { - return new OpenJosm(state.osmConnection, state.mapProperties.bounds) + return new SvelteUIElement(OpenJosm, { state }) }, }, { @@ -1099,12 +1096,6 @@ export default class SpecialVisualizations { if (maproulette_id_key === "" || maproulette_id_key === undefined) { maproulette_id_key = "mr_taskId" } - if (Svg.All[image] !== undefined || Svg.All[image + ".svg"] !== undefined) { - if (image.endsWith(".svg")) { - image = image.substring(0, image.length - 4) - } - image = Svg[image + "_svg"]() - } const failed = new UIEventSource(false) const closeButton = new SubtleButton(image, message).OnClickWithLoading( diff --git a/src/UI/StudioGUI.svelte b/src/UI/StudioGUI.svelte index bd2d6cf14..cfdfda1ae 100644 --- a/src/UI/StudioGUI.svelte +++ b/src/UI/StudioGUI.svelte @@ -29,6 +29,7 @@ import { Utils } from "../Utils"; import Translations from "./i18n/Translations"; import Tr from "./Base/Tr.svelte"; + import Add from "../assets/svg/Add.svelte"; export let studioUrl = window.location.hostname === "127.0.0.2" @@ -197,7 +198,7 @@ Show the introduction again - + diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index 1bf9f0cb8..04356ee27 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -43,18 +43,25 @@ import RasterLayerOverview from "./Map/RasterLayerOverview.svelte"; import IfHidden from "./Base/IfHidden.svelte"; import { onDestroy } from "svelte"; - import { OpenJosm } from "./BigComponents/OpenJosm"; import MapillaryLink from "./BigComponents/MapillaryLink.svelte"; import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte"; import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte"; import StateIndicator from "./BigComponents/StateIndicator.svelte"; - import Locale from "./i18n/Locale"; import ShareScreen from "./BigComponents/ShareScreen.svelte"; import UploadingImageCounter from "./Image/UploadingImageCounter.svelte"; import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte"; import Cross from "../assets/svg/Cross.svelte"; import Summary from "./BigComponents/Summary.svelte"; import LanguagePicker from "./InputElement/LanguagePicker.svelte"; + import Mastodon from "../assets/svg/Mastodon.svelte"; + import Bug from "../assets/svg/Bug.svelte"; + import Liberapay from "../assets/svg/Liberapay.svelte"; + import OpenJosm from "./Base/OpenJosm.svelte"; + import Min from "../assets/svg/Min.svelte"; + import Plus from "../assets/svg/Plus.svelte"; + import Filter from "../assets/svg/Filter.svelte"; + import Add from "../assets/svg/Add.svelte"; + import Statistics from "../assets/svg/Statistics.svelte"; export let state: ThemeViewState; let layout = state.layout; @@ -205,7 +212,7 @@ state.guistate.openFilterView()}> - + @@ -244,10 +251,10 @@ mapproperties.zoom.update((z) => z + 1)}> - + mapproperties.zoom.update((z) => z - 1)}> - + @@ -340,7 +347,7 @@
- +
@@ -431,27 +438,27 @@ - + - + - + - + - + {Constants.vNumber} @@ -503,10 +510,7 @@
- - new OpenJosm(state.osmConnection, state.mapProperties.bounds).SetClass("w-full")} - /> + diff --git a/src/UI/Wikipedia/WikipediaArticle.svelte b/src/UI/Wikipedia/WikipediaArticle.svelte index 9ffba16e4..ab37314ef 100644 --- a/src/UI/Wikipedia/WikipediaArticle.svelte +++ b/src/UI/Wikipedia/WikipediaArticle.svelte @@ -9,6 +9,7 @@ import WikidataPreviewBox from "./WikidataPreviewBox" import Tr from "../Base/Tr.svelte" import Translations from "../i18n/Translations" + import Wikipedia from "../../assets/svg/Wikipedia.svelte"; /** * Shows a wikipedia-article + wikidata preview for the given item @@ -18,7 +19,7 @@ {#if $wikipediaDetails.articleUrl} - + {/if} diff --git a/src/assets/svg/No_checkmark.svelte b/src/assets/svg/No_checkmark.svelte deleted file mode 100644 index a0721c478..000000000 --- a/src/assets/svg/No_checkmark.svelte +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file diff --git a/src/assets/svg/None.svelte b/src/assets/svg/None.svelte deleted file mode 100644 index d9222c9c8..000000000 --- a/src/assets/svg/None.svelte +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file diff --git a/src/assets/svg/Star_outline_half.svelte b/src/assets/svg/Star_outline_half.svelte deleted file mode 100644 index 1c209b5e5..000000000 --- a/src/assets/svg/Star_outline_half.svelte +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/svg/Wikipedia.svelte b/src/assets/svg/Wikipedia.svelte index fa9d45da1..6164f2f83 100644 --- a/src/assets/svg/Wikipedia.svelte +++ b/src/assets/svg/Wikipedia.svelte @@ -1,4 +1,4 @@ - Wikipedia logo version 2 \ No newline at end of file + Wikipedia logo version 2 \ No newline at end of file diff --git a/test/CodeQuality.spec.ts b/test/CodeQuality.spec.ts index dcf5d27eb..513fcaafb 100644 --- a/test/CodeQuality.spec.ts +++ b/test/CodeQuality.spec.ts @@ -4,14 +4,16 @@ import { describe, it } from "vitest" import { parse as parse_html } from "node-html-parser" import { readFileSync } from "fs" import ScriptUtils from "../scripts/ScriptUtils" - +function detectInCode(forbidden: string, reason: string) { + return wrap(detectInCodeUnwrapped(forbidden, reason)) +} /** * * @param forbidden: a GREP-regex. This means that '.' is a wildcard and should be escaped to match a literal dot * @param reason * @private */ -function detectInCode(forbidden: string, reason: string): Promise { +function detectInCodeUnwrapped(forbidden: string, reason: string): Promise { return new Promise((done) => { const excludedDirs = [ ".git", @@ -24,37 +26,35 @@ function detectInCode(forbidden: string, reason: string): Promise { ".idea/", ] - exec( + const command = 'grep -n "' + - forbidden + - '" -r . ' + - excludedDirs.map((d) => "--exclude-dir=" + d).join(" "), - (error, stdout, stderr) => { - if (error?.message?.startsWith("Command failed: grep")) { - console.warn("Command failed!", error) - return - } - if (error !== null) { - throw error - } - if (stderr !== "") { - throw stderr - } - - const found = stdout - .split("\n") - .filter((s) => s !== "") - .filter((s) => !s.startsWith("./test/")) - if (found.length > 0) { - const msg = `Found a '${forbidden}' at \n ${found.join( - "\n " - )}.\n ${reason}` - console.error(msg) - console.error(found.length, "issues found") - throw msg - } + forbidden + + '" -r . ' + + excludedDirs.map((d) => "--exclude-dir=" + d).join(" ") + console.log(command) + exec(command, (error, stdout, stderr) => { + if (error?.message?.startsWith("Command failed: grep")) { + console.warn("Command failed!", error) + throw error } - ) + if (error !== null) { + throw error + } + if (stderr !== "") { + throw stderr + } + + const found = stdout + .split("\n") + .filter((s) => s !== "") + .filter((s) => !s.startsWith("./test/")) + if (found.length > 0) { + const msg = `Found a '${forbidden}' at \n ${found.join("\n ")}.\n ${reason}` + console.error(msg) + console.error(found.length, "issues found") + throw msg + } + }) }) } @@ -64,10 +64,6 @@ function wrap(promise: Promise): (done: () => void) => void { } } -function itAsync(name: string, promise: Promise) { - it(name, wrap(promise)) -} - function validateScriptIntegrityOf(path: string) { const htmlContents = readFileSync(path, "utf8") const doc = parse_html(htmlContents) @@ -95,7 +91,7 @@ function validateScriptIntegrityOf(path: string) { } describe("Code quality", () => { - itAsync( + it( "should not contain reverse", detectInCode( "reverse()", @@ -103,12 +99,12 @@ describe("Code quality", () => { ) ) - itAsync( + it( "should not contain 'constructor.name'", detectInCode("constructor\\.name", "This is not allowed, as minification does erase names.") ) - itAsync( + it( "should not contain 'innerText'", detectInCode( "innerText", From fc62d41e1b832278bb0c846ffcaa971273419730 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 05:05:15 +0100 Subject: [PATCH 08/21] Fix: generating layeroverview; performance: do not try to download ratings if no ratings element is present --- assets/layers/icons/icons.json | 3 --- .../mapcomplete-changes.json | 4 +-- .../mapcomplete-changes.proto.json | 2 +- assets/themes/onwheels/onwheels.json | 2 +- package.json | 2 +- src/Models/Constants.ts | 8 ++++++ .../ThemeConfig/Conversion/PrepareLayer.ts | 27 +++++++++++++++++++ .../ThemeConfig/Conversion/Validation.ts | 2 +- .../ThemeConfig/Conversion/ValidationUtils.ts | 6 +++++ src/UI/Map/Icon.svelte | 19 +++++++++++++ src/UI/i18n/Locale.ts | 1 - src/Utils/svgToPdf.ts | 6 +---- 12 files changed, 67 insertions(+), 15 deletions(-) diff --git a/assets/layers/icons/icons.json b/assets/layers/icons/icons.json index 35e2a7c36..cb5da7543 100644 --- a/assets/layers/icons/icons.json +++ b/assets/layers/icons/icons.json @@ -189,9 +189,6 @@ }, { "id": "rating", - "labels": [ - "defaults" - ], "icon": { "class": "w-20 mx-1 flex items-center" }, diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.json index 153c37965..9b37d1f43 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.json @@ -604,7 +604,7 @@ ], "marker": [ { - "icon": "statistics:black" + "icon": "./assets/svg/statistics.svg" } ], "iconSize": "30,30", @@ -614,4 +614,4 @@ } } ] -} \ No newline at end of file +} diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json index d82eb3043..e7a05ff6e 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json @@ -294,7 +294,7 @@ ], "marker": [ { - "icon": "statistics:black" + "icon": "./assets/svg/statistics.svg" } ], "iconSize": "30,30", diff --git a/assets/themes/onwheels/onwheels.json b/assets/themes/onwheels/onwheels.json index a32ec3c3d..ea77a8823 100644 --- a/assets/themes/onwheels/onwheels.json +++ b/assets/themes/onwheels/onwheels.json @@ -467,7 +467,7 @@ ], "marker": [ { - "icon": "statistics" + "icon": "./assets/svg/statistics.svg" } ] } diff --git a/package.json b/package.json index 17496db23..f1ecefd07 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mapcomplete", - "version": "0.34.9", + "version": "0.35.0", "repository": "https://github.com/pietervdvn/MapComplete", "description": "A small website to edit OSM easily", "bugs": "https://github.com/pietervdvn/MapComplete/issues", diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index 25f0de6ba..f15232e3d 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -123,6 +123,14 @@ export default class Constants { "teardrop", "triangle", "crosshair", + "brick_wall_square", + "brick_wall_round", + "gps_arrow", + "checkmark", + "help", + "clock", + "invalid", + "close", ] as const public static readonly defaultPinIcons: string[] = Constants._defaultPinIcons diff --git a/src/Models/ThemeConfig/Conversion/PrepareLayer.ts b/src/Models/ThemeConfig/Conversion/PrepareLayer.ts index a72306dd9..6413e87a5 100644 --- a/src/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/src/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -1193,6 +1193,32 @@ class ExpandMarkerRenderings extends DesugaringStep { } } +export class AddRatingBadge extends DesugaringStep { + constructor() { + super( + "Adds the 'rating'-element if a reviews-element is used in the tagRenderings", + ["titleIcons"], + "AddRatingBadge" + ) + } + + convert(json: LayerConfigJson, context: ConversionContext): LayerConfigJson { + if (!json.tagRenderings) { + return json + } + + const specialVis: RenderingSpecification[] = ValidationUtils.getAllSpecialVisualisations( + json.tagRenderings + ) + + const calledFuncs = new Set(specialVis.map((rs) => rs["func"])) + if (calledFuncs.has("list_reviews")) { + ;(<(string | TagRenderingConfigJson)[]>json.titleIcons).push("ratings") + } + return json + } +} + export class PrepareLayer extends Fuse { constructor(state: DesugaringContext) { super( @@ -1223,6 +1249,7 @@ export class PrepareLayer extends Fuse { (layer) => new Concat(new ExpandTagRendering(state, layer, { noHardcodedStrings: true })) ), + new AddRatingBadge(), new ExpandFilter(state) ) } diff --git a/src/Models/ThemeConfig/Conversion/Validation.ts b/src/Models/ThemeConfig/Conversion/Validation.ts index ddf224576..9002c3a9a 100644 --- a/src/Models/ThemeConfig/Conversion/Validation.ts +++ b/src/Models/ThemeConfig/Conversion/Validation.ts @@ -110,7 +110,7 @@ export class DoesImageExist extends DesugaringStep { ) } else if (!this.doesPathExist(image)) { context.err( - `Image with path ${image} does not exist; it is used in ${context}.\n Check for typo's and missing directories in the path.` + `Image with path ${image} does not exist.\n Check for typo's and missing directories in the path.` ) } else { context.err( diff --git a/src/Models/ThemeConfig/Conversion/ValidationUtils.ts b/src/Models/ThemeConfig/Conversion/ValidationUtils.ts index 93c507aea..1f8bf800f 100644 --- a/src/Models/ThemeConfig/Conversion/ValidationUtils.ts +++ b/src/Models/ThemeConfig/Conversion/ValidationUtils.ts @@ -9,6 +9,12 @@ export default class ValidationUtils { renderingConfigs: (TagRenderingConfigJson | QuestionableTagRenderingConfigJson)[] ): RenderingSpecification[] { const visualisations: RenderingSpecification[] = [] + if (!Array.isArray(renderingConfigs)) { + throw ( + "Could not inspect renderingConfigs, not an array: " + + JSON.stringify(renderingConfigs) + ) + } for (const renderConfig of renderingConfigs) { visualisations.push(...ValidationUtils.getSpecialVisualisationsWithArgs(renderConfig)) } diff --git a/src/UI/Map/Icon.svelte b/src/UI/Map/Icon.svelte index 00cef96f2..1d250f5e6 100644 --- a/src/UI/Map/Icon.svelte +++ b/src/UI/Map/Icon.svelte @@ -19,6 +19,9 @@ import Teardrop from "../../assets/svg/Teardrop.svelte" import Teardrop_with_hole_green from "../../assets/svg/Teardrop_with_hole_green.svelte" import Triangle from "../../assets/svg/Triangle.svelte" + import Brick_wall_square from "../../assets/svg/Brick_wall_square.svelte"; + import Brick_wall_round from "../../assets/svg/Brick_wall_round.svelte"; + import Gps_arrow from "../../assets/svg/Gps_arrow.svelte"; /** * Renders a single icon. @@ -72,6 +75,22 @@ {:else if icon === "triangle"} + {:else if icon === "brick_wall_square"} + + {:else if icon === "brick_wall_round"} + + {:else if icon === "gps_arrow"} + + {:else if icon === "checkmark"} + + {:else if icon === "help"} + + {:else if icon === "clock"} + + {:else if icon === "close"} + + {:else if icon === "invalid"} + {:else} {/if} diff --git a/src/UI/i18n/Locale.ts b/src/UI/i18n/Locale.ts index 2968f8642..9c88ceb8c 100644 --- a/src/UI/i18n/Locale.ts +++ b/src/UI/i18n/Locale.ts @@ -78,7 +78,6 @@ export default class Locale { Locale.showLinkToWeblate.setData(Locale.showLinkToWeblate.data || tr) }) - console.log("Initial language:", source, source.data) return source } } diff --git a/src/Utils/svgToPdf.ts b/src/Utils/svgToPdf.ts index fffb02fcf..9c715b601 100644 --- a/src/Utils/svgToPdf.ts +++ b/src/Utils/svgToPdf.ts @@ -999,7 +999,7 @@ class SvgToPdfPage { export interface PdfTemplateInfo { pages: string[] - description: string | Translation + description?: string | Translation format: "a3" | "a4" | "a2" orientation: "portrait" | "landscape" isPublic: boolean @@ -1043,22 +1043,18 @@ export class SvgToPdf { format: "a4", orientation: "landscape", pages: ["./assets/templates/CurrentMapWithHeaderA4.svg"], - description: Translations.t.general.download.pdf.current_view_a4, - isPublic: true, }, current_view_a3_landscape: { format: "a3", orientation: "landscape", pages: ["./assets/templates/CurrentMapWithHeader_A3_Landscape.svg"], - description: Translations.t.general.download.pdf.current_view_a3, isPublic: true, }, current_view_a3_portrait: { format: "a3", orientation: "portrait", pages: ["./assets/templates/CurrentMapWithHeader_A3_Portrait.svg"], - description: Translations.t.general.download.pdf.current_view_a3, isPublic: true, }, } From 2b728fdf8bd6effce1682119f7f0d67a13d1c97d Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 05:07:44 +0100 Subject: [PATCH 09/21] Fix: fix settings menu --- src/UI/InputElement/LanguagePicker.svelte | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/UI/InputElement/LanguagePicker.svelte b/src/UI/InputElement/LanguagePicker.svelte index ac59348dc..15329a48c 100644 --- a/src/UI/InputElement/LanguagePicker.svelte +++ b/src/UI/InputElement/LanguagePicker.svelte @@ -18,10 +18,9 @@ * EventStore to assign to, defaults to 'Locale.langauge' */ export let assignTo: UIEventSource = Locale.language; - export let preferredLanguages: UIEventSource; + export let preferredLanguages: UIEventSource = undefined; let preferredFiltered: string[] = undefined; - preferredLanguages.addCallbackAndRunD(preferredLanguages => { - + preferredLanguages?.addCallbackAndRunD(preferredLanguages => { let lng = navigator.language; if (lng === "en-US") { lng = "en"; From 0ea103f24780ef2c6ba191cbd4891716bb2d86f6 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 05:08:40 +0100 Subject: [PATCH 10/21] Fix: show preferred languages (according to OSM) in usersettings --- src/UI/SpecialVisualizations.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index aea5f3906..f32f28d9e 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -457,6 +457,9 @@ export default class SpecialVisualizations { return new SvelteUIElement(LanguagePicker, { assignTo: state.userRelatedState.language, availableLanguages: state.layout.language, + preferredLanguages: state.osmConnection.userDetails.map( + (ud) => ud.languages + ), }) }, }, From e71a1c7a3d011b921c6ff08dcc54f93dd84971dc Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 05:21:46 +0100 Subject: [PATCH 11/21] Fix: generate layeroverview --- assets/layers/note/note.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/layers/note/note.json b/assets/layers/note/note.json index cbf752842..db0771c2a 100644 --- a/assets/layers/note/note.json +++ b/assets/layers/note/note.json @@ -66,11 +66,11 @@ "marker": [ { "icon": { - "render": "note", + "render": "./assets/svg/note.svg", "mappings": [ { "if": "closed_at~*", - "then": "resolved" + "then": "./assets/svg/resolved.svg" } ] } @@ -80,11 +80,11 @@ "iconBadges": [ { "if": "_total_comments>1", - "then": "circle:white;speech_bubble" + "then": "circle:white;./assets/svg/speech_bubble.svg" }, { "if": "_is_import_note~*", - "then": "addSmall" + "then": "./assets/svg/addSmall.svg" } ], "anchor": "bottom" From 6c75553f3fec7642c7bbb75d999781126a344065 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 13:03:46 +0100 Subject: [PATCH 12/21] Themes: only add rating-title-icon if 'review_list()' is used in the layer --- .../ThemeConfig/Conversion/PrepareLayer.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Models/ThemeConfig/Conversion/PrepareLayer.ts b/src/Models/ThemeConfig/Conversion/PrepareLayer.ts index 6413e87a5..fd041335c 100644 --- a/src/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/src/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -26,7 +26,7 @@ import predifined_filters from "../../../../assets/layers/filters/filters.json" import { TagConfigJson } from "../Json/TagConfigJson" import PointRenderingConfigJson, { IconConfigJson } from "../Json/PointRenderingConfigJson" import ValidationUtils from "./ValidationUtils" -import { RenderingSpecification } from "../../../UI/SpecialVisualization" +import { RenderingSpecification, SpecialVisualization } from "../../../UI/SpecialVisualization" import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson" import { ConfigMeta } from "../../../UI/Studio/configMeta" import LineRenderingConfigJson from "../Json/LineRenderingConfigJson" @@ -1207,13 +1207,15 @@ export class AddRatingBadge extends DesugaringStep { return json } - const specialVis: RenderingSpecification[] = ValidationUtils.getAllSpecialVisualisations( - json.tagRenderings + const specialVis: Exclude[] = < + Exclude[] + >ValidationUtils.getAllSpecialVisualisations(json.tagRenderings).filter( + (rs) => typeof rs !== "string" ) + const funcs = new Set(specialVis.map((rs) => rs.func.funcName)) - const calledFuncs = new Set(specialVis.map((rs) => rs["func"])) - if (calledFuncs.has("list_reviews")) { - ;(<(string | TagRenderingConfigJson)[]>json.titleIcons).push("ratings") + if (funcs.has("list_reviews")) { + ;(<(string | TagRenderingConfigJson)[]>json.titleIcons).push("icons.rating") } return json } @@ -1244,12 +1246,12 @@ export class PrepareLayer extends Fuse { (layer) => new Each(new PreparePointRendering(state, layer)) ), new SetDefault("titleIcons", ["icons.defaults"]), + new AddRatingBadge(), new On( "titleIcons", (layer) => new Concat(new ExpandTagRendering(state, layer, { noHardcodedStrings: true })) ), - new AddRatingBadge(), new ExpandFilter(state) ) } From e4aedc9696409cf391197408b2ac4534ad8239ca Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 16:20:47 +0100 Subject: [PATCH 13/21] Refactoring: more removal of old-style SVG bundling --- scripts/generateIncludedImages.ts | 24 ++++++++++ src/UI/BigComponents/ThemeIntroPanel.svelte | 48 ++++++++----------- .../Helpers/DirectionInput.svelte | 3 +- src/UI/Map/Icon.svelte | 2 - src/UI/Reviews/StarElement.svelte | 9 ++-- src/UI/StylesheetTestGui.svelte | 23 ++++----- src/UI/ThemeViewGUI.svelte | 10 ++-- 7 files changed, 70 insertions(+), 49 deletions(-) diff --git a/scripts/generateIncludedImages.ts b/scripts/generateIncludedImages.ts index 93a163ef3..dd7160a40 100644 --- a/scripts/generateIncludedImages.ts +++ b/scripts/generateIncludedImages.ts @@ -4,6 +4,30 @@ function genImages(dryrun = false) { console.log("Generating images") // These images are not referenced via 'Svg.ts' anymore and can be ignored const blacklist: string[] = [ + "add", + "addSmall", + "brick_wall_square", + "clock", + "community", + "copyright", + "cross", + "cross_bottom_right", + "crosshair_locked", + "delete_not_allowed", + "direction_gradient", + "direction_stroke", + "duplicate", + "elevator", + "elevator_wheelchair", + "liberapay", + "length_crosshair", + "speech_bubble_black_outline", + "square", + "star_half", + "star_outline", + "star", + "osm_logo_us", + "SocialImageForeground", "wikipedia", "Upload", diff --git a/src/UI/BigComponents/ThemeIntroPanel.svelte b/src/UI/BigComponents/ThemeIntroPanel.svelte index e0dde8cd1..6e125a6ea 100644 --- a/src/UI/BigComponents/ThemeIntroPanel.svelte +++ b/src/UI/BigComponents/ThemeIntroPanel.svelte @@ -1,21 +1,21 @@
@@ -40,16 +41,16 @@
@@ -59,11 +60,11 @@
@@ -82,7 +83,7 @@
@@ -106,26 +107,26 @@
diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index 04356ee27..a3b81e559 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -36,7 +36,6 @@ import LevelSelector from "./BigComponents/LevelSelector.svelte"; import ExtraLinkButton from "./BigComponents/ExtraLinkButton"; import SelectedElementTitle from "./BigComponents/SelectedElementTitle.svelte"; - import Svg from "../Svg"; import ThemeIntroPanel from "./BigComponents/ThemeIntroPanel.svelte"; import type { RasterLayerPolygon } from "../Models/RasterLayers"; import { AvailableRasterLayers } from "../Models/RasterLayers"; @@ -62,6 +61,9 @@ import Filter from "../assets/svg/Filter.svelte"; import Add from "../assets/svg/Add.svelte"; import Statistics from "../assets/svg/Statistics.svelte"; + import Community from "../assets/svg/Community.svelte"; + import Download from "../assets/svg/Download.svelte"; + import Share from "../assets/svg/Share.svelte"; export let state: ThemeViewState; let layout = state.layout; @@ -371,7 +373,7 @@
- +
@@ -386,7 +388,7 @@ new CopyrightPanel(state)} slot="content3" />
- +
@@ -492,7 +494,7 @@
- +
From 29b1f5be4d456d724026f5b94e40dd4c85bd14fb Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 16:31:58 +0100 Subject: [PATCH 14/21] Security: calculate connect-source of specialVisualisations by argument, if applicable --- scripts/generateLayouts.ts | 43 +++++++++++++++++++++++++++------ src/UI/SpecialVisualization.ts | 2 +- src/UI/SpecialVisualizations.ts | 2 +- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 53465995b..6aea996be 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -15,6 +15,7 @@ import { ImmutableStore } from "../src/Logic/UIEventSource" import * as crypto from "crypto" import * as eli from "../src/assets/editor-layer-index.json" import * as eli_global from "../src/assets/global-raster-layers.json" +import ValidationUtils from "../src/Models/ThemeConfig/Conversion/ValidationUtils" const sharp = require("sharp") const template = readFileSync("theme.html", "utf8") @@ -264,6 +265,7 @@ async function eliUrls(): Promise { async function generateCsp( layout: LayoutConfig, + layoutJson: LayoutConfigJson, options: { scriptSrcs: string[] } @@ -275,9 +277,20 @@ async function generateCsp( Constants.nominatimEndpoint, "https://api.openstreetmap.org", "https://pietervdvn.goatcounter.com", - ] - .concat(...SpecialVisualizations.specialVisualizations.map((sv) => sv.needsUrls)) - .concat(...(await eliUrls())) + ].concat(...(await eliUrls())) + + const usedSpecialVisualisations = ValidationUtils.getSpecialVisualisationsWithArgs(layoutJson) + for (const usedSpecialVisualisation of usedSpecialVisualisations) { + if (typeof usedSpecialVisualisation === "string") { + continue + } + const neededUrls = usedSpecialVisualisation.func.needsUrls + if (typeof neededUrls === "function") { + apiUrls.push(...neededUrls(usedSpecialVisualisation.args)) + } else { + apiUrls.push(...neededUrls) + } + } const geojsonSources: string[] = layout.layers.map((l) => l.source?.geojsonSource) const hosts = new Set() @@ -299,6 +312,10 @@ async function generateCsp( } } + if (hosts.has("*")) { + throw "* is not allowed as connect-src" + } + const connectSrc = Array.from(hosts).sort() const newSrcs = connectSrc.filter((newItem) => !previousSrc.has(newItem)) @@ -317,7 +334,7 @@ async function generateCsp( "default-src": "'self'", "child-src": "'self' blob: ", "img-src": "* data:", // maplibre depends on 'data:' to load - "connect-src": connectSrc.join(" "), + "connect-src": onnectSrc.join(" "), "report-to": "https://report.mapcomplete.org/csp", "worker-src": "'self' blob:", // Vite somehow loads the worker via a 'blob' "style-src": "'self' 'unsafe-inline'", // unsafe-inline is needed to change the default background pin colours @@ -344,7 +361,13 @@ const removeOtherLanguagesHash = crypto .update(removeOtherLanguages) .digest("base64") -async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alreadyWritten) { +async function createLandingPage( + layout: LayoutConfig, + layoutJson: LayoutConfigJson, + manifest, + whiteIcons, + alreadyWritten +) { Locale.language.setData(layout.language[0]) const targetLanguage = layout.language[0] const ogTitle = Translations.T(layout.title).textFor(targetLanguage).replace(/"/g, '\\"') @@ -428,7 +451,7 @@ async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alr .replace(/.*/s, themeSpecific) .replace( //, - await generateCsp(layout, { + await generateCsp(layout, layoutJson, { scriptSrcs: [`'sha256-${removeOtherLanguagesHash}'`], }) ) @@ -518,7 +541,13 @@ async function main(): Promise { writeFile("public/" + manifestLocation, manif, err) // Create a landing page for the given theme - const landing = await createLandingPage(layout, manifest, whiteIcons, alreadyWritten) + const landing = await createLandingPage( + layout, + layoutConfigJson, + manifest, + whiteIcons, + alreadyWritten + ) writeFile(enc(layout.id) + ".html", landing, err) await createIndexFor(layout) diff --git a/src/UI/SpecialVisualization.ts b/src/UI/SpecialVisualization.ts index 28125837c..be3ffee15 100644 --- a/src/UI/SpecialVisualization.ts +++ b/src/UI/SpecialVisualization.ts @@ -88,7 +88,7 @@ export interface SpecialVisualization { readonly funcName: string readonly docs: string | BaseUIElement readonly example?: string - readonly needsUrls: string[] + readonly needsUrls: string[] | ((args: string[]) => string) /** * Indicates that this special visualisation will make requests to the 'alLNodesDatabase' and that it thus should be included diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index f32f28d9e..c0720293a 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -1454,7 +1454,7 @@ export default class SpecialVisualizations { }, ], docs: "Shows events that are happening based on a Giggity URL", - needsUrls: ["*"], + needsUrls: (args) => args[0], constr( state: SpecialVisualizationState, tagSource: UIEventSource>, From 79e40d0fee2e40b32babc218a374095f6ca520a5 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 18:08:57 +0100 Subject: [PATCH 15/21] Themes: add warning if a tagRendering can be replaced by a direct value --- src/Models/ThemeConfig/Conversion/Validation.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Models/ThemeConfig/Conversion/Validation.ts b/src/Models/ThemeConfig/Conversion/Validation.ts index 9002c3a9a..59130c1e9 100644 --- a/src/Models/ThemeConfig/Conversion/Validation.ts +++ b/src/Models/ThemeConfig/Conversion/Validation.ts @@ -813,6 +813,12 @@ class MiscTagRenderingChecks extends DesugaringStep { ) } + if (Object.keys(json).length === 1 && typeof json["render"] === "string") { + context.warn( + `use the content directly instead of {render: ${JSON.stringify(json["render"])}}` + ) + } + { for (const key of ["question", "questionHint", "render"]) { CheckTranslation.allowUndefined.convert(json[key], context.enter(key)) From a612d4e1c2f6469c7b2d1fc66c8fc416ccdcac1a Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 18:13:32 +0100 Subject: [PATCH 16/21] Fix: generateCSP --- scripts/generateLayouts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 6aea996be..dc4819f62 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -334,7 +334,7 @@ async function generateCsp( "default-src": "'self'", "child-src": "'self' blob: ", "img-src": "* data:", // maplibre depends on 'data:' to load - "connect-src": onnectSrc.join(" "), + "connect-src": connectSrc.join(" "), "report-to": "https://report.mapcomplete.org/csp", "worker-src": "'self' blob:", // Vite somehow loads the worker via a 'blob' "style-src": "'self' 'unsafe-inline'", // unsafe-inline is needed to change the default background pin colours From 6b4be1200c60664bbbee87f9f8f8e3d821a277c3 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 21:21:33 +0100 Subject: [PATCH 17/21] Fix: always allow www.openstreetmap.org --- scripts/generateLayouts.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index dc4819f62..7a672427a 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -275,6 +275,7 @@ async function generateCsp( ...Constants.defaultOverpassUrls, Constants.countryCoderEndpoint, Constants.nominatimEndpoint, + "https://www.openstreetmap.org", "https://api.openstreetmap.org", "https://pietervdvn.goatcounter.com", ].concat(...(await eliUrls())) From ce1855b2bd322044f9710a4dab38287298ad5fc6 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 22:00:37 +0100 Subject: [PATCH 18/21] Fix: add all needed urls again --- scripts/generateLayouts.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index 7a672427a..61d178e31 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -280,6 +280,13 @@ async function generateCsp( "https://pietervdvn.goatcounter.com", ].concat(...(await eliUrls())) + SpecialVisualizations.specialVisualizations.forEach(sv => { + if(typeof sv.needsUrls === "function"){ + return + } + apiUrls.push(...sv.needsUrls) + }) + const usedSpecialVisualisations = ValidationUtils.getSpecialVisualisationsWithArgs(layoutJson) for (const usedSpecialVisualisation of usedSpecialVisualisations) { if (typeof usedSpecialVisualisation === "string") { @@ -288,8 +295,6 @@ async function generateCsp( const neededUrls = usedSpecialVisualisation.func.needsUrls if (typeof neededUrls === "function") { apiUrls.push(...neededUrls(usedSpecialVisualisation.args)) - } else { - apiUrls.push(...neededUrls) } } From ff47d75d41fc1fd4f576cd483150fe27cb3942d3 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 23 Nov 2023 17:07:53 +0100 Subject: [PATCH 19/21] Fix: re-enable speed and heading in GPS-cursor --- src/Logic/Actors/GeoLocationHandler.ts | 19 ++++++------------- src/UI/Popup/AllTagsPanel.svelte | 9 ++------- src/UI/Test.svelte | 11 +---------- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/src/Logic/Actors/GeoLocationHandler.ts b/src/Logic/Actors/GeoLocationHandler.ts index 9333a8413..68efc803d 100644 --- a/src/Logic/Actors/GeoLocationHandler.ts +++ b/src/Logic/Actors/GeoLocationHandler.ts @@ -137,7 +137,6 @@ export default class GeoLocationHandler { } } - console.trace("Moving the map to the GPS-location") mapLocation.setData({ lon: newLocation.longitude, lat: newLocation.latitude, @@ -152,7 +151,6 @@ export default class GeoLocationHandler { private CopyGeolocationIntoMapstate() { const features: UIEventSource = new UIEventSource([]) this.currentUserLocation = new StaticFeatureSource(features) - const keysToCopy = ["speed", "accuracy", "altitude", "altitudeAccuracy", "heading"] let i = 0 this.geolocationState.currentGPSLocation.addCallbackAndRun((location) => { if (location === undefined) { @@ -163,19 +161,15 @@ export default class GeoLocationHandler { id: "gps-" + i, "user:location": "yes", date: new Date().toISOString(), + // GeolocationObject behaves really weird when indexing, so copying it one by one is the most stable + accuracy: location.accuracy, + speed: location.speed, + altitude: location.altitude, + altitudeAccuracy: location.altitudeAccuracy, + heading: location.heading, } i++ - for (const k in keysToCopy) { - // For some weird reason, the 'Object.keys' method doesn't work for the 'location: GeolocationCoordinates'-object and will thus not copy all the properties when using {...location} - // As such, they are copied here - if (location[k]) { - properties[k] = location[k] - } - } - console.debug("Current location object:", location) - properties["_all"] = JSON.stringify(location) - const feature = { type: "Feature", properties, @@ -184,7 +178,6 @@ export default class GeoLocationHandler { coordinates: [location.longitude, location.latitude], }, } - features.setData([feature]) }) } diff --git a/src/UI/Popup/AllTagsPanel.svelte b/src/UI/Popup/AllTagsPanel.svelte index 81bc9219e..9913416fb 100644 --- a/src/UI/Popup/AllTagsPanel.svelte +++ b/src/UI/Popup/AllTagsPanel.svelte @@ -9,6 +9,7 @@ import Lazy from "../Base/Lazy" import BaseUIElement from "../BaseUIElement" import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" + import { VariableUiElement } from "../Base/VariableUIElement"; //Svelte props export let tags: UIEventSource @@ -54,13 +55,7 @@ return parts }) - let _allTags = [] - onDestroy( - allTags.addCallbackAndRunD((allTags) => { - _allTags = allTags - }) - ) - const tagsTable = new Table(["Key", "Value"], _allTags).SetClass("zebra-table break-all") + const tagsTable = new VariableUiElement(allTags.mapD(_allTags => new Table(["Key", "Value"], _allTags).SetClass("zebra-table break-all")))
diff --git a/src/UI/Test.svelte b/src/UI/Test.svelte index 22f2d9313..1b51c34bf 100644 --- a/src/UI/Test.svelte +++ b/src/UI/Test.svelte @@ -1,15 +1,6 @@ -
- - - - {$language} + No tests
From f87e73596e65a12b7fb88456dfb21dcc1eb8a850 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sun, 19 Nov 2023 22:20:39 +0100 Subject: [PATCH 20/21] Themes: don't use 'Yes' or 'No' as start --- assets/themes/sidewalks/sidewalks.json | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/assets/themes/sidewalks/sidewalks.json b/assets/themes/sidewalks/sidewalks.json index 03b439468..459225a4a 100644 --- a/assets/themes/sidewalks/sidewalks.json +++ b/assets/themes/sidewalks/sidewalks.json @@ -166,31 +166,31 @@ { "if": "sidewalk:left|right=yes", "then": { - "en": "Yes, there is a sidewalk on this side of the road", - "de": "Ja, es gibt einen Bürgersteig auf dieser Straßenseite", - "da": "Ja, der er et fortov på denne side af vejen", - "nl": "Ja, er is een stoep aan deze kant van de weg", - "fr": "Oui, il y a un trottoir de ce côté de la route", - "ca": "Sí, hi ha una vorera a aquest costat del carrer", - "es": "Sí, hay una acera en este lado de la calle", - "cs": "Ano, na této straně silnice je chodník", - "it": "Sì, c'è un marciapiede su questo lato della strada", - "pl": "Tak, jest chodnik z boku drogi" + "en": "There is a sidewalk on this side of the road", + "de": "Es gibt einen Bürgersteig auf dieser Straßenseite", + "da": "Der er et fortov på denne side af vejen", + "nl": "Er is een stoep aan deze kant van de weg", + "fr": "Il y a un trottoir de ce côté de la route", + "ca": "Hi ha una vorera a aquest costat del carrer", + "es": "Hay una acera en este lado de la calle", + "cs": "Na této straně silnice je chodník", + "it": "C'è un marciapiede su questo lato della strada", + "pl": "Jest chodnik z boku drogi" } }, { "if": "sidewalk:left|right=no", "then": { - "en": "No, there is no sidewalk to walk on", - "de": "Nein, es gibt keinen Bürgersteig für Fußgänger", - "da": "Nej, der er ikke noget fortov at gå på", - "nl": "Nee, er is geen stoep om op te lopen", - "fr": "Non, il n'y a pas de trottoir où marcher", - "ca": "No, no hi ha vorera per la que caminar", - "es": "No, no hay acera por la que caminar", - "cs": "Ne, není tu žádný chodník", - "it": "No, non c'è un marciapiede su cui camminare", - "pl": "Nie, nie ma chodnika, którym można chodzić" + "en": "There is no sidewalk to walk on", + "de": "Es gibt keinen Bürgersteig für Fußgänger", + "da": "Der er ikke noget fortov at gå på", + "nl": "Er is geen stoep om op te lopen", + "fr": "Il n'y a pas de trottoir où marcher", + "ca": "No hi ha vorera per la que caminar", + "es": "No hay acera por la que caminar", + "cs": "Není tu žádný chodník", + "it": "Non c'è un marciapiede su cui camminare", + "pl": "Nie ma chodnika, którym można chodzić" } }, { From 98c337c71b232e689553768100c699b0bf92a490 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Mon, 27 Nov 2023 15:59:16 +0100 Subject: [PATCH 21/21] Version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1ecefd07..dbd6b213f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mapcomplete", - "version": "0.35.0", + "version": "0.35.1", "repository": "https://github.com/pietervdvn/MapComplete", "description": "A small website to edit OSM easily", "bugs": "https://github.com/pietervdvn/MapComplete/issues",