From 0d81decdc7828f844feee0ccd70fcf24aa69ead2 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Thu, 14 Apr 2022 19:46:14 +0200 Subject: [PATCH] Further translations of the import helper --- .../Conversion/AddContextToTranslations.ts | 44 ++++++++++++++++ UI/ImportFlow/ConflationChecker.ts | 51 +++++++++++-------- UI/ImportFlow/ImportHelperGui.ts | 2 +- UI/Input/InputElementWrapper.ts | 3 +- assets/welcome_message.json | 6 +++ langs/en.json | 21 ++++++++ 6 files changed, 105 insertions(+), 22 deletions(-) diff --git a/Models/ThemeConfig/Conversion/AddContextToTranslations.ts b/Models/ThemeConfig/Conversion/AddContextToTranslations.ts index 8d9a953905..9e3dc8c56a 100644 --- a/Models/ThemeConfig/Conversion/AddContextToTranslations.ts +++ b/Models/ThemeConfig/Conversion/AddContextToTranslations.ts @@ -39,6 +39,39 @@ export class AddContextToTranslations extends DesugaringStep { * } * rewritten // => expected * + * // should use the ID if one is present instead of the index + * const theme = { + * layers: [ + * { + * tagRenderings:[ + * + * {id: "some-tr", + * question:{ + * en:"Question?" + * } + * } + * ] + * } + * ] + * } + * const rewritten = new AddContextToTranslations("prefix:").convert(theme, "context").result + * const expected = { + * layers: [ + * { + * tagRenderings:[ + * + * {id: "some-tr", + * question:{ + * _context: "prefix:context.layers.0.tagRenderings.some-tr.question" + * en:"Question?" + * } + * } + * ] + * } + * ] + * } + * rewritten // => expected + * * // should preserve nulls * const theme = { * layers: [ @@ -70,6 +103,17 @@ export class AddContextToTranslations extends DesugaringStep { return leaf } if (typeof leaf === "object") { + + // follow the path. If we encounter a number, check that there is no ID we can use instead + let breadcrumb = json; + for (let i = 0; i < path.length; i++) { + const pointer = path[i] + breadcrumb = breadcrumb[pointer] + if(pointer.match("[0-9]+") && breadcrumb["id"] !== undefined){ + path[i] = breadcrumb["id"] + } + } + return {...leaf, _context: this._prefix + context + "." + path.join(".")} } else { return leaf diff --git a/UI/ImportFlow/ConflationChecker.ts b/UI/ImportFlow/ConflationChecker.ts index f0a3f17c96..0f01ce3c96 100644 --- a/UI/ImportFlow/ConflationChecker.ts +++ b/UI/ImportFlow/ConflationChecker.ts @@ -7,7 +7,6 @@ import {UIEventSource} from "../../Logic/UIEventSource"; import Constants from "../../Models/Constants"; import RelationsTracker from "../../Logic/Osm/RelationsTracker"; import {VariableUiElement} from "../Base/VariableUIElement"; -import {FixedUiElement} from "../Base/FixedUiElement"; import {FlowStep} from "./FlowStep"; import Loading from "../Base/Loading"; import {SubtleButton} from "../Base/SubtleButton"; @@ -28,6 +27,7 @@ import * as import_candidate from "../../assets/layers/import_candidate/import_c import {GeoOperations} from "../../Logic/GeoOperations"; import FeatureInfoBox from "../Popup/FeatureInfoBox"; import {ImportUtils} from "./ImportUtils"; +import Translations from "../i18n/Translations"; /** * Given the data to import, the bbox and the layer, will query overpass for similar items @@ -190,6 +190,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea features: toImportWithNearby }) + const t = Translations.t.importHelper.conflationChecker const conflationMaps = new Combine([ new VariableUiElement( @@ -197,7 +198,7 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea if (geojson === undefined) { return undefined; } - return new SubtleButton(Svg.download_svg(), "Download the loaded geojson from overpass").onClick(() => { + return new SubtleButton(Svg.download_svg(), t.downloadOverpassData).onClick(() => { Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson, null, " "), "mapcomplete-" + layer.id + ".geojson", { mimetype: "application/json+geo" }) @@ -208,43 +209,53 @@ export default class ConflationChecker extends Combine implements FlowStep<{ fea return undefined; } if (age < 0) { - return new FixedUiElement("Cache was expired") + return t.cacheExpired } - return new FixedUiElement("Loaded data is from the cache and is " + Utils.toHumanTime(age) + " old") + return t.loadedDataAge.Subs({age: Utils.toHumanTime(age)}) })), - new Title("Live data on OSM"), - "The "+toImport.features.length+" red elements on the following map are all your import candidates.", - new VariableUiElement(geojson.map(geojson => new FixedUiElement((geojson?.features?.length ?? "No") + " elements are loaded from OpenStreetMap which match the layer "+layer.id+". Zooming in might be needed to show them"))), + new Title(t.titleLive), + t.importCandidatesCount.Subs({count:toImport.features.length }), + new VariableUiElement(geojson.map(geojson => { + if(geojson?.features?.length === undefined && geojson?.features?.length === 0){ + return t.nothingLoaded.Subs(layer).SetClass("alert") + } + return new Combine([ + t.osmLoaded.Subs({count: geojson.features.length, name: layer.name}), + + ]) + })), osmLiveData, - new Combine(["The live data is shown if the zoomlevel is at least ", zoomLevel, ". The current zoom level is ", new VariableUiElement(osmLiveData.location.map(l => "" + l.zoom))]).SetClass("flex"), - - new Title("Nearby features"), - new Combine(["The following map shows features to import which have an OSM-feature within ", nearbyCutoff, "meter"]).SetClass("flex"), + new VariableUiElement(osmLiveData.location.map(location => { + return t.zoomIn.Subs({needed:zoomLevel, current: location.zoom }) + } )), + new Title(t.titleNearby), + new Combine([t.mapShowingNearbyIntro, nearbyCutoff]).SetClass("flex"), new VariableUiElement(toImportWithNearby.features.map(feats => - new FixedUiElement("The "+ feats.length +" red elements on the following map will not be imported!").SetClass("alert"))), - "Set the range to 0 or 1 if you want to import them all", + t.nearbyWarn.Subs({count: feats.length}).SetClass("alert"))), + ,t.setRangeToZero, matchedFeaturesMap]).SetClass("flex flex-col") super([ - new Title("Comparison with existing data"), + new Title(t.title), new VariableUiElement(overpassStatus.map(d => { if (d === "idle") { - return new Loading("Checking local storage...") - } - if (d["error"] !== undefined) { - return new FixedUiElement("Could not load latest data from overpass: " + d["error"]).SetClass("alert") + return new Loading(t.states.idle) } if (d === "running") { - return new Loading("Querying overpass...") + return new Loading(t.states.running) } + if (d["error"] !== undefined) { + return t.states.error.Subs(d).SetClass("alert") + } + if (d === "cached") { return conflationMaps } if (d === "success") { return conflationMaps } - return new FixedUiElement("Unexpected state " + d).SetClass("alert") + return t.states.unexpected.Subs({state: d}).SetClass("alert") })) ]) diff --git a/UI/ImportFlow/ImportHelperGui.ts b/UI/ImportFlow/ImportHelperGui.ts index 82cd8684f7..000cae3528 100644 --- a/UI/ImportFlow/ImportHelperGui.ts +++ b/UI/ImportFlow/ImportHelperGui.ts @@ -36,7 +36,7 @@ export default class ImportHelperGui extends LeftIndex { .then(t.mapPreview, geojson => new MapPreview(state, geojson)) .then(t.selectTheme, v => new SelectTheme(v)) .then(t.compareToAlreadyExistingNotes, v => new CompareToAlreadyExistingNotes(state, v)) - .then("Compare with existing data", v => new ConflationChecker(state, v)) + .then(t.conflationChecker, v => new ConflationChecker(state, v)) .then(t.confirmProcess, v => new ConfirmProcess(v)) .then(t.askMetadata, (v) => new AskMetadata(v)) .finish(t.createNotes.title, v => new CreateNotes(state, v)); diff --git a/UI/Input/InputElementWrapper.ts b/UI/Input/InputElementWrapper.ts index 9006956c52..623fc18d59 100644 --- a/UI/Input/InputElementWrapper.ts +++ b/UI/Input/InputElementWrapper.ts @@ -9,7 +9,8 @@ export default class InputElementWrapper extends InputElement { private readonly _inputElement: InputElement; private readonly _renderElement: BaseUIElement - constructor(inputElement: InputElement, translation: Translation, key: string, tags: UIEventSource, state: FeaturePipelineState) { + constructor(inputElement: InputElement, translation: Translation, key: string, + tags: UIEventSource, state: FeaturePipelineState) { super() this._inputElement = inputElement; const mapping = new Map() diff --git a/assets/welcome_message.json b/assets/welcome_message.json index 0d53ded19a..6b0117b6ed 100644 --- a/assets/welcome_message.json +++ b/assets/welcome_message.json @@ -1,4 +1,10 @@ [ + { + "start_date": "2022-05-30", + "end_date":"2022-06-05", + "message": "The 3rd of June is World Bicycle Day. Go find a bike shop or bike pump nearby", + "featured_theme": "cyclofix" + }, { "start_date": "2022-04-18", "end_date": "2022-04-24", diff --git a/langs/en.json b/langs/en.json index 953bad7a4e..3d39a5355a 100644 --- a/langs/en.json +++ b/langs/en.json @@ -310,6 +310,27 @@ "titleLong": "Did you go through the import process?", "wikipageIsMade": "The process is documented on the OSM-wiki (you'll need this link later)" }, + "conflationChecker": { + "cacheExpired": "Cache was expired", + "downloadOverpassData": "Download the loaded geojson from overpass", + "importCandidatesCount": "The {count} red elements on the following map are all your import candidates.", + "loadedDataAge": "Loaded data is from the cache and is {age} old", + "mapShowingNearbyIntro": "The following map shows features to import which have an OSM-feature within ", + "nearbyWarn": "The {count} red elements on the following map will not be imported!", + "nothingLoaded": "No elements are loaded from OpenStreetMap which match the current layer {name}", + "osmLoaded": "{count} elements are loaded from OpenStreetMap which match the layer {name}.", + "setRangeToZero": "Set the range to 0 or 1 if you want to import them all", + "states": { + "error": "Could not load latest data from overpass due to {error}", + "idle": "Checking local storage...", + "running": "Querying overpass...", + "unexpected": "Unexpected state {state}" + }, + "title": "Compare with existing data", + "titleLive": "Live data on OSM", + "titleNearby": "Nearby features", + "zoomIn": "The live data is shown if the zoomlevel is at least {needed}. The current zoom level is {current}" + }, "createNotes": { "creating": "Created {count} notes out of {total}", "done": "All {count} notes have been created!",