diff --git a/Logic/Osm/Actions/ChangeLocationAction.ts b/Logic/Osm/Actions/ChangeLocationAction.ts index 506dc6539..9bb53b427 100644 --- a/Logic/Osm/Actions/ChangeLocationAction.ts +++ b/Logic/Osm/Actions/ChangeLocationAction.ts @@ -18,7 +18,6 @@ export default class ChangeLocationAction extends OsmChangeAction { this._id = Number(id.substring("node/".length)) this._newLonLat = newLonLat; this._meta = meta; - throw "TODO" } protected async CreateChangeDescriptions(changes: Changes): Promise { diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index fe4f48abc..91b4b6e89 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -59,14 +59,13 @@ export abstract class OsmObject { static async DownloadPropertiesOf(id: string): Promise { const splitted = id.split("/"); - const type = splitted[0]; const idN = Number(splitted[1]); if (idN < 0) { return undefined; } const url = `${OsmObject.backendURL}api/0.6/${id}`; - const rawData = await Utils.downloadJson(url) + const rawData = await Utils.downloadJsonCached(url, 1000) return rawData.elements[0].tags } @@ -80,7 +79,7 @@ export abstract class OsmObject { const full = (id.startsWith("way")) ? "/full" : ""; const url = `${OsmObject.backendURL}api/0.6/${id}${full}`; - const rawData = await Utils.downloadJson(url) + const rawData = await Utils.downloadJsonCached(url, 1000) // A full query might contain more then just the requested object (e.g. nodes that are part of a way, where we only want the way) const parsed = OsmObject.ParseObjects(rawData.elements); // Lets fetch the object we need @@ -105,7 +104,7 @@ export abstract class OsmObject { * Beware: their geometry will be incomplete! */ public static DownloadReferencingWays(id: string): Promise { - return Utils.downloadJson(`${OsmObject.backendURL}api/0.6/${id}/ways`).then( + return Utils.downloadJsonCached(`${OsmObject.backendURL}api/0.6/${id}/ways`, 60 * 1000).then( data => { return data.elements.map(wayInfo => { const way = new OsmWay(wayInfo.id) @@ -121,7 +120,7 @@ export abstract class OsmObject { * Beware: their geometry will be incomplete! */ public static async DownloadReferencingRelations(id: string): Promise { - const data = await Utils.downloadJson(`${OsmObject.backendURL}api/0.6/${id}/relations`) + const data = await Utils.downloadJsonCached(`${OsmObject.backendURL}api/0.6/${id}/relations`, 60 * 1000) return data.elements.map(wayInfo => { const rel = new OsmRelation(wayInfo.id) rel.LoadData(wayInfo) @@ -139,7 +138,7 @@ export abstract class OsmObject { const idN = Number(splitted[1]); const src = new UIEventSource([]); OsmObject.historyCache.set(id, src); - Utils.downloadJson(`${OsmObject.backendURL}api/0.6/${type}/${idN}/history`).then(data => { + Utils.downloadJsonCached(`${OsmObject.backendURL}api/0.6/${type}/${idN}/history`, 10 * 60 * 1000).then(data => { const elements: any[] = data.elements; const osmObjects: OsmObject[] = [] for (const element of elements) { diff --git a/Models/ThemeConfig/Json/LayerConfigJson.ts b/Models/ThemeConfig/Json/LayerConfigJson.ts index f337b1a19..69d1b972e 100644 --- a/Models/ThemeConfig/Json/LayerConfigJson.ts +++ b/Models/ThemeConfig/Json/LayerConfigJson.ts @@ -3,6 +3,7 @@ import {TagRenderingConfigJson} from "./TagRenderingConfigJson"; import FilterConfigJson from "./FilterConfigJson"; import {DeleteConfigJson} from "./DeleteConfigJson"; import UnitConfigJson from "./UnitConfigJson"; +import MoveConfigJson from "./MoveConfigJson"; /** * Configuration for a single layer @@ -314,6 +315,18 @@ export interface LayerConfigJson { */ deletion?: boolean | DeleteConfigJson + /** + * Indicates if a point can be moved and configures the modalities. + * + * A feature can be moved by MapComplete if: + * + * - It is a point + * - The point is _not_ part of a way or a a relation. + * + * Off by default. Can be enabled by setting this flag or by configuring. + */ + allowMove?: boolean | MoveConfigJson + /** * IF set, a 'split this road' button is shown */ diff --git a/Models/ThemeConfig/Json/MoveConfigJson.ts b/Models/ThemeConfig/Json/MoveConfigJson.ts new file mode 100644 index 000000000..3ae9bf70c --- /dev/null +++ b/Models/ThemeConfig/Json/MoveConfigJson.ts @@ -0,0 +1,12 @@ +export default interface MoveConfigJson { + /** + * One default reason to move a point is to improve accuracy. + * Set to false to disable this reason + */ + enableImproveAccuracy?: true | boolean + /** + * One default reason to move a point is because it has relocated + * Set to false to disable this reason + */ + enableRelocation?: true | boolean +} \ No newline at end of file diff --git a/Models/ThemeConfig/LayerConfig.ts b/Models/ThemeConfig/LayerConfig.ts index a2e55d71c..09f3f0fd2 100644 --- a/Models/ThemeConfig/LayerConfig.ts +++ b/Models/ThemeConfig/LayerConfig.ts @@ -19,6 +19,7 @@ import {Unit} from "../Unit"; import DeleteConfig from "./DeleteConfig"; import Svg from "../../Svg"; import Img from "../../UI/Base/Img"; +import MoveConfig from "./MoveConfig"; export default class LayerConfig { static WAYHANDLING_DEFAULT = 0; @@ -49,6 +50,7 @@ export default class LayerConfig { wayHandling: number; public readonly units: Unit[]; public readonly deletion: DeleteConfig | null; + public readonly allowMove: MoveConfig | null public readonly allowSplit: boolean presets: PresetConfig[]; @@ -67,7 +69,7 @@ export default class LayerConfig { this.id = json.id; this.allowSplit = json.allowSplit ?? false; this.name = Translations.T(json.name, context + ".name"); - this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`))) + this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`))) if (json.description !== undefined) { if (Object.keys(json.description).length === 0) { @@ -138,11 +140,11 @@ export default class LayerConfig { const key = kv.substring(0, index); const code = kv.substring(index + 1); - try{ - - new Function("feat", "return " + code + ";"); - }catch(e){ - throw `Invalid function definition: code ${code} is invalid:${e} (at ${context})` + try { + + new Function("feat", "return " + code + ";"); + } catch (e) { + throw `Invalid function definition: code ${code} is invalid:${e} (at ${context})` } @@ -155,8 +157,8 @@ export default class LayerConfig { this.minzoom = json.minzoom ?? 0; this.minzoomVisible = json.minzoomVisible ?? this.minzoom; this.wayHandling = json.wayHandling ?? 0; - if(json.presets !== undefined && json.presets?.map === undefined){ - throw "Presets should be a list of items (at "+context+")" + if (json.presets !== undefined && json.presets?.map === undefined) { + throw "Presets should be a list of items (at " + context + ")" } this.presets = (json.presets ?? []).map((pr, i) => { @@ -291,21 +293,21 @@ export default class LayerConfig { } this.tagRenderings = trs(json.tagRenderings, false); - - const missingIds = json.tagRenderings?.filter(tr => typeof tr !== "string" && tr["builtin"] === undefined && tr["id"] === undefined) ?? []; - if(missingIds.length > 0 && official){ - console.error("Some tagRenderings of", this.id, "are missing an id:", missingIds) - throw "Missing ids in tagrenderings" - } - + const missingIds = json.tagRenderings?.filter(tr => typeof tr !== "string" && tr["builtin"] === undefined && tr["id"] === undefined) ?? []; + + if (missingIds.length > 0 && official) { + console.error("Some tagRenderings of", this.id, "are missing an id:", missingIds) + throw "Missing ids in tagrenderings" + } + this.filters = (json.filter ?? []).map((option, i) => { return new FilterConfig(option, `${context}.filter-[${i}]`) }); - - if(json["filters"] !== undefined){ - throw "Error in "+context+": use 'filter' instead of 'filters'" - } + + if (json["filters"] !== undefined) { + throw "Error in " + context + ": use 'filter' instead of 'filters'" + } const titleIcons = []; const defaultIcons = [ @@ -369,6 +371,16 @@ export default class LayerConfig { this.deletion = new DeleteConfig(json.deletion, `${context}.deletion`); } + this.allowMove = null + if (json.allowMove === false) { + this.allowMove = null; + } else if (json.allowMove === true) { + this.allowMove = new MoveConfig({}, context + ".allowMove") + } else if (json.allowMove !== undefined && json.allowMove !== false) { + this.allowMove = new MoveConfig(json.allowMove, context + ".allowMove") + } + + if (json["showIf"] !== undefined) { throw ( "Invalid key on layerconfig " + diff --git a/Models/ThemeConfig/MoveConfig.ts b/Models/ThemeConfig/MoveConfig.ts new file mode 100644 index 000000000..b2cb08260 --- /dev/null +++ b/Models/ThemeConfig/MoveConfig.ts @@ -0,0 +1,17 @@ +import MoveConfigJson from "./Json/MoveConfigJson"; + +export default class MoveConfig { + + public readonly enableImproveAccuracy: boolean + public readonly enableRelocation: boolean + + constructor(json: MoveConfigJson, context: string) { + this.enableImproveAccuracy = json.enableImproveAccuracy ?? true + this.enableRelocation = json.enableRelocation ?? true + if (!(this.enableRelocation || this.enableImproveAccuracy)) { + throw "At least one default move reason should be allowed (at " + context + ")" + } + } + + +} \ No newline at end of file diff --git a/UI/Input/LocationInput.ts b/UI/Input/LocationInput.ts index 53715562b..ccbf6ba55 100644 --- a/UI/Input/LocationInput.ts +++ b/UI/Input/LocationInput.ts @@ -15,6 +15,7 @@ import {BBox} from "../../Logic/BBox"; import {FixedUiElement} from "../Base/FixedUiElement"; import ShowDataLayer from "../ShowDataLayer/ShowDataLayer"; import BaseUIElement from "../BaseUIElement"; +import Toggle from "./Toggle"; export default class LocationInput extends InputElement implements MinimapObj { @@ -157,10 +158,15 @@ export default class LocationInput extends InputElement implements MinimapO IsValid(t: Loc): boolean { return t !== undefined; } - + protected InnerConstructElement(): HTMLElement { try { const self = this; + const hasMoved = new UIEventSource(false) + this.GetValue().addCallbackAndRunD(_ => { + hasMoved.setData(true) + return true; + }) this.clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location)) if (this._snapTo !== undefined) { @@ -213,8 +219,8 @@ export default class LocationInput extends InputElement implements MinimapO ]).SetClass("block w-0 h-0 z-10 relative") .SetStyle("background: rgba(255, 128, 128, 0.21); left: 50%; top: 50%; opacity: 0.5"), - new Combine([ - animatedHand]) + new Toggle(undefined, + animatedHand, hasMoved) .SetClass("block w-0 h-0 z-10 relative") .SetStyle("left: calc(50% + 3rem); top: calc(50% + 2rem); opacity: 0.7"), diff --git a/UI/Popup/FeatureInfoBox.ts b/UI/Popup/FeatureInfoBox.ts index b7e33546b..484a27ea2 100644 --- a/UI/Popup/FeatureInfoBox.ts +++ b/UI/Popup/FeatureInfoBox.ts @@ -17,6 +17,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; import {Translation} from "../i18n/Translation"; import {Utils} from "../../Utils"; import {SubstitutedTranslation} from "../SubstitutedTranslation"; +import MoveWizard from "./MoveWizard"; export default class FeatureInfoBox extends ScrollableFullScreen { @@ -72,6 +73,19 @@ export default class FeatureInfoBox extends ScrollableFullScreen { editElements.push(questionBox); } + if(layerConfig.allowMove) { + editElements.push( + new VariableUiElement(tags.map(tags => tags.id).map(id => { + const feature = State.state.allElements.ContainingFeatures.get(id) + return new MoveWizard( + feature, + State.state, + layerConfig.allowMove + ); + }) + ) + ); + } if (layerConfig.deletion) { editElements.push( diff --git a/UI/Popup/MoveWizard.ts b/UI/Popup/MoveWizard.ts index b59b56bc7..6a5d4a07b 100644 --- a/UI/Popup/MoveWizard.ts +++ b/UI/Popup/MoveWizard.ts @@ -15,13 +15,17 @@ import {OsmObject} from "../../Logic/Osm/OsmObject"; import {Changes} from "../../Logic/Osm/Changes"; import ChangeLocationAction from "../../Logic/Osm/Actions/ChangeLocationAction"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; +import MoveConfig from "../../Models/ThemeConfig/MoveConfig"; +import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; +import {ElementStorage} from "../../Logic/ElementStorage"; interface MoveReason { text: Translation | string, + invitingText: Translation | string, icon: string | BaseUIElement, changesetCommentValue: string, lockBounds: true | boolean, - background: undefined | "map" | "photo", + background: undefined | "map" | "photo" | string | string[], startZoom: number, minZoom: number } @@ -36,13 +40,9 @@ export default class MoveWizard extends Toggle { osmConnection: OsmConnection, featureSwitchUserbadge: UIEventSource, changes: Changes, - layoutToUse: LayoutConfig - }, options?: { - reasons?: MoveReason[] - disableDefaultReasons?: false | boolean - - }) { - options = options ?? {} + layoutToUse: LayoutConfig, + allElements: ElementStorage + }, options : MoveConfig) { const t = Translations.t.move const loginButton = new Toggle( @@ -51,14 +51,53 @@ export default class MoveWizard extends Toggle { state.featureSwitchUserbadge ) + const reasons: MoveReason[] = [] + if (options.enableRelocation) { + reasons.push({ + text: t.reasons.reasonRelocation.Clone(), + invitingText: t.inviteToMove.reasonRelocation.Clone(), + icon: Svg.relocation_svg(), + changesetCommentValue: "relocated", + lockBounds: false, + background: undefined, + startZoom: 12, + minZoom: 6 + }) + } + if(options.enableImproveAccuracy){ + reasons.push({ + text: t.reasons.reasonInaccurate.Clone(), + invitingText: t.inviteToMove.reasonInaccurate, + icon: Svg.crosshair_svg(), + changesetCommentValue: "improve_accuracy", + lockBounds: true, + background: "photo", + startZoom: 17, + minZoom: 16 + }) + } + const currentStep = new UIEventSource<"start" | "reason" | "pick_location" | "moved">("start") const moveReason = new UIEventSource(undefined) - const moveButton = new SubtleButton( - Svg.move_ui(), - t.inviteToMove.Clone() - ).onClick(() => { - currentStep.setData("reason") - }) + let moveButton : BaseUIElement; + if(reasons.length === 1){ + const reason = reasons[0] + moveReason.setData(reason) + moveButton = new SubtleButton( + reason.icon, + Translations.WT(reason.invitingText).Clone() + ).onClick(() => { + currentStep.setData("pick_location") + }) + }else{ + moveButton = new SubtleButton( + Svg.move_ui(), + t.inviteToMove.generic.Clone() + ).onClick(() => { + currentStep.setData("reason") + }) + } + const moveAgainButton = new SubtleButton( Svg.move_ui(), @@ -68,40 +107,8 @@ export default class MoveWizard extends Toggle { }) - const reasons: MoveReason[] = [] - if (!options.disableDefaultReasons) { - reasons.push({ - text: t.reasonRelocation.Clone(), - icon: Svg.relocation_svg(), - changesetCommentValue: "relocated", - lockBounds: false, - background: undefined, - startZoom: 12, - minZoom: 6 - }) - - reasons.push({ - text: t.reasonInaccurate.Clone(), - icon: Svg.crosshair_svg(), - changesetCommentValue: "improve_accuracy", - lockBounds: true, - background: "photo", - startZoom: 17, - minZoom: 16 - }) - } - for (const reason of options.reasons ?? []) { - reasons.push({ - text: reason.text, - icon: reason.icon, - changesetCommentValue: reason.changesetCommentValue, - lockBounds: reason.lockBounds ?? true, - background: reason.background, - startZoom: reason.startZoom ?? 15, - minZoom: reason.minZoom - }) - } - + + const selectReason = new Combine(reasons.map(r => new SubtleButton(r.icon, r.text).onClick(() => { moveReason.setData(r) currentStep.setData("pick_location") @@ -124,7 +131,8 @@ export default class MoveWizard extends Toggle { const locationInput = new LocationInput({ minZoom: reason.minZoom, - centerLocation: loc + centerLocation: loc, + mapBackground: AvailableBaseLayers.SelectBestLayerAccordingTo(loc, new UIEventSource(reason.background)) }) if (reason.lockBounds) { @@ -135,10 +143,14 @@ export default class MoveWizard extends Toggle { const confirmMove = new SubtleButton(Svg.move_confirm_svg(), t.confirmMove) confirmMove.onClick(() => { - state.changes.applyAction(new ChangeLocationAction(featureToMove.properties.id, [locationInput.GetValue().data.lon, locationInput.GetValue().data.lat], { + const loc = locationInput.GetValue().data + state.changes.applyAction(new ChangeLocationAction(featureToMove.properties.id, [loc.lon, loc.lat], { reason: Translations.WT(reason.text).textFor("en"), - theme: state.layoutToUse.icon + theme: state.layoutToUse.id })) + featureToMove.properties._lat = loc.lat + featureToMove.properties._lon = loc.lon + state.allElements.getEventSourceById(id).ping() currentStep.setData("moved") }) const zoomInFurhter = t.zoomInFurther.Clone().SetClass("alert block m-6") diff --git a/Utils.ts b/Utils.ts index e293e4f4b..26c8a7534 100644 --- a/Utils.ts +++ b/Utils.ts @@ -320,6 +320,19 @@ export class Utils { ) } + private static _download_cache = new Map, timestamp: number}>() + public static async downloadJsonCached(url: string, maxCacheTimeMs: number, headers?: any): Promise { + const cached = Utils._download_cache.get(url) + if(cached !== undefined){ + if((new Date().getTime() - cached.timestamp) <= maxCacheTimeMs){ + return cached.promise + } + } + const promise = Utils.downloadJson(url, headers) + Utils._download_cache.set(url, {promise, timestamp: new Date().getTime()}) + return await promise + } + public static async downloadJson(url: string, headers?: any): Promise { const injected = Utils.injectedDownloads[url] if (injected !== undefined) { diff --git a/assets/layers/bench/bench.json b/assets/layers/bench/bench.json index af5bbd10b..f9b94008a 100644 --- a/assets/layers/bench/bench.json +++ b/assets/layers/bench/bench.json @@ -600,5 +600,18 @@ "preferredBackground": "photo" } } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity=bench", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json b/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json index 665a75942..360a0444c 100644 --- a/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json +++ b/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json @@ -255,5 +255,18 @@ ], "multiAnswer": true } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/bike_cleaning/bike_cleaning.json b/assets/layers/bike_cleaning/bike_cleaning.json index 6c76d519b..3bd07aa39 100644 --- a/assets/layers/bike_cleaning/bike_cleaning.json +++ b/assets/layers/bike_cleaning/bike_cleaning.json @@ -145,5 +145,18 @@ "roaming": false, "id": "bike_cleaning-charge" } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/bike_parking/bike_parking.json b/assets/layers/bike_parking/bike_parking.json index 049bcac9e..2f866351e 100644 --- a/assets/layers/bike_parking/bike_parking.json +++ b/assets/layers/bike_parking/bike_parking.json @@ -508,5 +508,18 @@ }, "id": "Cargo bike capacity?" } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/bike_repair_station/bike_repair_station.json b/assets/layers/bike_repair_station/bike_repair_station.json index cd202c6c8..29b8fe215 100644 --- a/assets/layers/bike_repair_station/bike_repair_station.json +++ b/assets/layers/bike_repair_station/bike_repair_station.json @@ -731,5 +731,18 @@ "service:bicycle:pump=no" ] } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/binocular/binocular.json b/assets/layers/binocular/binocular.json index 46ba8fe42..325628818 100644 --- a/assets/layers/binocular/binocular.json +++ b/assets/layers/binocular/binocular.json @@ -100,5 +100,18 @@ "amenity=binoculars" ] } + }, + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true } } \ No newline at end of file diff --git a/assets/layers/birdhide/birdhide.json b/assets/layers/birdhide/birdhide.json index 38f8e1970..da7042bd3 100644 --- a/assets/layers/birdhide/birdhide.json +++ b/assets/layers/birdhide/birdhide.json @@ -296,5 +296,17 @@ } ] } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + } + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/cafe_pub/cafe_pub.json b/assets/layers/cafe_pub/cafe_pub.json index e5977e8bb..a815bd6d9 100644 --- a/assets/layers/cafe_pub/cafe_pub.json +++ b/assets/layers/cafe_pub/cafe_pub.json @@ -181,5 +181,11 @@ } ] } - ] + ], + "deletion": { + "softDeletionTags": { + "and": ["amenity=","disused:amenity:={amenity}"] + } + }, + "allowMove": true } \ No newline at end of file diff --git a/assets/layers/charging_station/charging_station.json b/assets/layers/charging_station/charging_station.json index 454f26ff1..23ee4411f 100644 --- a/assets/layers/charging_station/charging_station.json +++ b/assets/layers/charging_station/charging_station.json @@ -3655,5 +3655,18 @@ ], "eraseInvalidValues": true } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/defibrillator/defibrillator.json b/assets/layers/defibrillator/defibrillator.json index 639020383..484e6f4a5 100644 --- a/assets/layers/defibrillator/defibrillator.json +++ b/assets/layers/defibrillator/defibrillator.json @@ -539,5 +539,18 @@ }, "id": "defibrillator-fixme" } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:emergency:=defibrillator}", + "emergency=" + ] + }, + "neededChangesets": 5 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/drinking_water/drinking_water.json b/assets/layers/drinking_water/drinking_water.json index 43af3910c..63f4f849e 100644 --- a/assets/layers/drinking_water/drinking_water.json +++ b/assets/layers/drinking_water/drinking_water.json @@ -166,5 +166,18 @@ }, "condition": "_closest_other_drinking_water_id~*" } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/food/food.json b/assets/layers/food/food.json index 1bac9814d..79b0015fc 100644 --- a/assets/layers/food/food.json +++ b/assets/layers/food/food.json @@ -624,5 +624,11 @@ } ] } - ] + ], + "deletion": { + "softDeletionTags": { + "and": ["amenity=","disused:amenity:={amenity}"] + } + }, + "allowMove": true } \ No newline at end of file diff --git a/assets/layers/ghost_bike/ghost_bike.json b/assets/layers/ghost_bike/ghost_bike.json index 25a6097ef..99ec27a2a 100644 --- a/assets/layers/ghost_bike/ghost_bike.json +++ b/assets/layers/ghost_bike/ghost_bike.json @@ -187,5 +187,18 @@ }, "id": "ghost_bike-start_date" } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "razed:memorial:=ghost_bike", + "memorial=" + ] + }, + "neededChangesets": 50 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/information_board/information_board.json b/assets/layers/information_board/information_board.json index 6f240fa4f..2634f1df3 100644 --- a/assets/layers/information_board/information_board.json +++ b/assets/layers/information_board/information_board.json @@ -53,5 +53,20 @@ "ru": "Информационный щит" } } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:tourism:=information", + "tourism=" , + "razed:information=board", + "information=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/map/map.json b/assets/layers/map/map.json index 221bfa7ef..b0031e573 100644 --- a/assets/layers/map/map.json +++ b/assets/layers/map/map.json @@ -227,5 +227,18 @@ } } ], - "wayHandling": 2 + "wayHandling": 2, + "deletion": { + "softDeletionTags": { + "and": [ + "razed:tourism:=information", + "tourism=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/observation_tower/observation_tower.json b/assets/layers/observation_tower/observation_tower.json index 8443b1213..d789271af 100644 --- a/assets/layers/observation_tower/observation_tower.json +++ b/assets/layers/observation_tower/observation_tower.json @@ -180,5 +180,9 @@ ], "eraseInvalidValues": true } - ] + ], + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/parking/parking.json b/assets/layers/parking/parking.json index 42f09f53e..b428d5f99 100644 --- a/assets/layers/parking/parking.json +++ b/assets/layers/parking/parking.json @@ -81,5 +81,18 @@ "nl": "Voeg hier een parking voor auto's toe" } } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/picnic_table/picnic_table.json b/assets/layers/picnic_table/picnic_table.json index c414410fe..c3c5e6e0b 100644 --- a/assets/layers/picnic_table/picnic_table.json +++ b/assets/layers/picnic_table/picnic_table.json @@ -101,5 +101,18 @@ } } ], - "wayHandling": 1 + "wayHandling": 1, + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/toilet/toilet.json b/assets/layers/toilet/toilet.json index d7592efc7..7b0366ca9 100644 --- a/assets/layers/toilet/toilet.json +++ b/assets/layers/toilet/toilet.json @@ -498,5 +498,18 @@ } ] } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/assets/layers/waste_basket/waste_basket.json b/assets/layers/waste_basket/waste_basket.json index 1cd888dcd..f18791611 100644 --- a/assets/layers/waste_basket/waste_basket.json +++ b/assets/layers/waste_basket/waste_basket.json @@ -115,5 +115,18 @@ "preferredBackground": "photo" } } - ] + ], + "deletion": { + "softDeletionTags": { + "and": [ + "disused:amenity:={amenity}", + "amenity=" + ] + }, + "neededChangesets": 1 + }, + "allowMove": { + "enableRelocation": false, + "enableImproveAccuraccy": true + } } \ No newline at end of file diff --git a/langs/en.json b/langs/en.json index b94746cc3..5b0e4f150 100644 --- a/langs/en.json +++ b/langs/en.json @@ -256,7 +256,6 @@ }, "move": { "loginToMove": "You must be logged in to move a point", - "inviteToMove": "Move this point", "inviteToMoveAgain": "Move this point again", "moveTitle": "Move this point", "whyMove": "Why do you want to move this point?", @@ -264,8 +263,15 @@ "pointIsMoved": "The point has been moved", "zoomInFurther": "Zoom in further to confirm this move", "selectReason": "Why do you move this object?", - "reasonRelocation": "The object has been relocated to a totally different location", - "reasonInaccurate": "The location of this object is inaccurate and should be moved a few meter", + "reasons": { + "reasonRelocation": "The object has been relocated to a totally different location", + "reasonInaccurate": "The location of this object is inaccurate and should be moved a few meter" + }, + "inviteToMove": { + "generic": "Move this point", + "reasonInaccurate": "Improve the accuracy of this point", + "reasonRelocation": "Move this object to a another place because it has relocated" + }, "cannotBeMoved": "This feature cannot be moved.", "isWay": "This feature is a way. Use another OpenStreetMap editor to move it.", "isRelation": "This feature is a relation and can not be moved", diff --git a/package.json b/package.json index 4f8cc5a9d..ed6bf9570 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "homepage": "https://mapcomplete.osm.be", "main": "index.js", "scripts": { - "increase-memory": "export NODE_OPTIONS=--max_old_space_size=6182", + "increase-memory": "export NODE_OPTIONS=--max_old_space_size=8364", "start": "npm run start:prepare && npm-run-all --parallel start:parallel:*", "strt": "npm run start:prepare && npm run start:parallel:parcel", "start:prepare": "ts-node scripts/generateLayerOverview.ts --no-fail && npm run increase-memory", diff --git a/test.ts b/test.ts index 6bf459512..0442ef091 100644 --- a/test.ts +++ b/test.ts @@ -2,6 +2,9 @@ import MoveWizard from "./UI/Popup/MoveWizard"; import State from "./State"; import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; import MinimapImplementation from "./UI/Base/MinimapImplementation"; +import MoveConfig from "./Models/ThemeConfig/MoveConfig"; +import {FixedUiElement} from "./UI/Base/FixedUiElement"; +import Combine from "./UI/Base/Combine"; State.state = new State(AllKnownLayouts.allKnownLayouts.get("bookcases")) @@ -18,8 +21,14 @@ const feature = { ] } } +/* MinimapImplementation.initialize() new MoveWizard( feature, - State.state).AttachTo("maindiv") + State.state, + new MoveConfig({ + enableRelocation: false, + enableImproveAccuracy: true + }, "test")).AttachTo("maindiv") +*/