forked from MapComplete/MapComplete
		
	Add move option, enable move and delete option on most layers
This commit is contained in:
		
							parent
							
								
									0a3eb966c1
								
							
						
					
					
						commit
						7e2b73ac5d
					
				
					 33 changed files with 454 additions and 104 deletions
				
			
		| 
						 | 
					@ -18,7 +18,6 @@ export default class ChangeLocationAction extends OsmChangeAction {
 | 
				
			||||||
        this._id = Number(id.substring("node/".length))
 | 
					        this._id = Number(id.substring("node/".length))
 | 
				
			||||||
        this._newLonLat = newLonLat;
 | 
					        this._newLonLat = newLonLat;
 | 
				
			||||||
        this._meta = meta;
 | 
					        this._meta = meta;
 | 
				
			||||||
        throw "TODO"
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
 | 
					    protected async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,14 +59,13 @@ export abstract class OsmObject {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    static async DownloadPropertiesOf(id: string): Promise<any> {
 | 
					    static async DownloadPropertiesOf(id: string): Promise<any> {
 | 
				
			||||||
        const splitted = id.split("/");
 | 
					        const splitted = id.split("/");
 | 
				
			||||||
        const type = splitted[0];
 | 
					 | 
				
			||||||
        const idN = Number(splitted[1]);
 | 
					        const idN = Number(splitted[1]);
 | 
				
			||||||
        if (idN < 0) {
 | 
					        if (idN < 0) {
 | 
				
			||||||
            return undefined;
 | 
					            return undefined;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const url = `${OsmObject.backendURL}api/0.6/${id}`;
 | 
					        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
 | 
					        return rawData.elements[0].tags
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,7 +79,7 @@ export abstract class OsmObject {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const full = (id.startsWith("way")) ? "/full" : "";
 | 
					        const full = (id.startsWith("way")) ? "/full" : "";
 | 
				
			||||||
        const url = `${OsmObject.backendURL}api/0.6/${id}${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)
 | 
					        // 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);
 | 
					        const parsed = OsmObject.ParseObjects(rawData.elements);
 | 
				
			||||||
        // Lets fetch the object we need
 | 
					        // Lets fetch the object we need
 | 
				
			||||||
| 
						 | 
					@ -105,7 +104,7 @@ export abstract class OsmObject {
 | 
				
			||||||
     * Beware: their geometry will be incomplete!
 | 
					     * Beware: their geometry will be incomplete!
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static DownloadReferencingWays(id: string): Promise<OsmWay[]> {
 | 
					    public static DownloadReferencingWays(id: string): Promise<OsmWay[]> {
 | 
				
			||||||
        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 => {
 | 
					            data => {
 | 
				
			||||||
                return data.elements.map(wayInfo => {
 | 
					                return data.elements.map(wayInfo => {
 | 
				
			||||||
                    const way = new OsmWay(wayInfo.id)
 | 
					                    const way = new OsmWay(wayInfo.id)
 | 
				
			||||||
| 
						 | 
					@ -121,7 +120,7 @@ export abstract class OsmObject {
 | 
				
			||||||
     * Beware: their geometry will be incomplete!
 | 
					     * Beware: their geometry will be incomplete!
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static async DownloadReferencingRelations(id: string): Promise<OsmRelation[]> {
 | 
					    public static async DownloadReferencingRelations(id: string): Promise<OsmRelation[]> {
 | 
				
			||||||
        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 => {
 | 
					        return data.elements.map(wayInfo => {
 | 
				
			||||||
            const rel = new OsmRelation(wayInfo.id)
 | 
					            const rel = new OsmRelation(wayInfo.id)
 | 
				
			||||||
            rel.LoadData(wayInfo)
 | 
					            rel.LoadData(wayInfo)
 | 
				
			||||||
| 
						 | 
					@ -139,7 +138,7 @@ export abstract class OsmObject {
 | 
				
			||||||
        const idN = Number(splitted[1]);
 | 
					        const idN = Number(splitted[1]);
 | 
				
			||||||
        const src = new UIEventSource<OsmObject[]>([]);
 | 
					        const src = new UIEventSource<OsmObject[]>([]);
 | 
				
			||||||
        OsmObject.historyCache.set(id, src);
 | 
					        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 elements: any[] = data.elements;
 | 
				
			||||||
            const osmObjects: OsmObject[] = []
 | 
					            const osmObjects: OsmObject[] = []
 | 
				
			||||||
            for (const element of elements) {
 | 
					            for (const element of elements) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import {TagRenderingConfigJson} from "./TagRenderingConfigJson";
 | 
				
			||||||
import FilterConfigJson from "./FilterConfigJson";
 | 
					import FilterConfigJson from "./FilterConfigJson";
 | 
				
			||||||
import {DeleteConfigJson} from "./DeleteConfigJson";
 | 
					import {DeleteConfigJson} from "./DeleteConfigJson";
 | 
				
			||||||
import UnitConfigJson from "./UnitConfigJson";
 | 
					import UnitConfigJson from "./UnitConfigJson";
 | 
				
			||||||
 | 
					import MoveConfigJson from "./MoveConfigJson";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Configuration for a single layer
 | 
					 * Configuration for a single layer
 | 
				
			||||||
| 
						 | 
					@ -314,6 +315,18 @@ export interface LayerConfigJson {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    deletion?: boolean | DeleteConfigJson
 | 
					    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
 | 
					     * IF set, a 'split this road' button is shown
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								Models/ThemeConfig/Json/MoveConfigJson.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Models/ThemeConfig/Json/MoveConfigJson.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ import {Unit} from "../Unit";
 | 
				
			||||||
import DeleteConfig from "./DeleteConfig";
 | 
					import DeleteConfig from "./DeleteConfig";
 | 
				
			||||||
import Svg from "../../Svg";
 | 
					import Svg from "../../Svg";
 | 
				
			||||||
import Img from "../../UI/Base/Img";
 | 
					import Img from "../../UI/Base/Img";
 | 
				
			||||||
 | 
					import MoveConfig from "./MoveConfig";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LayerConfig {
 | 
					export default class LayerConfig {
 | 
				
			||||||
    static WAYHANDLING_DEFAULT = 0;
 | 
					    static WAYHANDLING_DEFAULT = 0;
 | 
				
			||||||
| 
						 | 
					@ -49,6 +50,7 @@ export default class LayerConfig {
 | 
				
			||||||
    wayHandling: number;
 | 
					    wayHandling: number;
 | 
				
			||||||
    public readonly units: Unit[];
 | 
					    public readonly units: Unit[];
 | 
				
			||||||
    public readonly deletion: DeleteConfig | null;
 | 
					    public readonly deletion: DeleteConfig | null;
 | 
				
			||||||
 | 
					    public readonly allowMove: MoveConfig | null
 | 
				
			||||||
    public readonly allowSplit: boolean
 | 
					    public readonly allowSplit: boolean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    presets: PresetConfig[];
 | 
					    presets: PresetConfig[];
 | 
				
			||||||
| 
						 | 
					@ -67,7 +69,7 @@ export default class LayerConfig {
 | 
				
			||||||
        this.id = json.id;
 | 
					        this.id = json.id;
 | 
				
			||||||
        this.allowSplit = json.allowSplit ?? false;
 | 
					        this.allowSplit = json.allowSplit ?? false;
 | 
				
			||||||
        this.name = Translations.T(json.name, context + ".name");
 | 
					        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 (json.description !== undefined) {
 | 
				
			||||||
            if (Object.keys(json.description).length === 0) {
 | 
					            if (Object.keys(json.description).length === 0) {
 | 
				
			||||||
| 
						 | 
					@ -138,11 +140,11 @@ export default class LayerConfig {
 | 
				
			||||||
                const key = kv.substring(0, index);
 | 
					                const key = kv.substring(0, index);
 | 
				
			||||||
                const code = kv.substring(index + 1);
 | 
					                const code = kv.substring(index + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                try{
 | 
					                try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                new Function("feat", "return " + code + ";");
 | 
					                    new Function("feat", "return " + code + ";");
 | 
				
			||||||
                }catch(e){
 | 
					                } catch (e) {
 | 
				
			||||||
                 throw `Invalid function definition: code ${code} is invalid:${e} (at ${context})`   
 | 
					                    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.minzoom = json.minzoom ?? 0;
 | 
				
			||||||
        this.minzoomVisible = json.minzoomVisible ?? this.minzoom;
 | 
					        this.minzoomVisible = json.minzoomVisible ?? this.minzoom;
 | 
				
			||||||
        this.wayHandling = json.wayHandling ?? 0;
 | 
					        this.wayHandling = json.wayHandling ?? 0;
 | 
				
			||||||
        if(json.presets !== undefined && json.presets?.map === undefined){
 | 
					        if (json.presets !== undefined && json.presets?.map === undefined) {
 | 
				
			||||||
            throw "Presets should be a list of items (at "+context+")"
 | 
					            throw "Presets should be a list of items (at " + context + ")"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.presets = (json.presets ?? []).map((pr, i) => {
 | 
					        this.presets = (json.presets ?? []).map((pr, i) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,20 +294,20 @@ export default class LayerConfig {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.tagRenderings = trs(json.tagRenderings, false);
 | 
					        this.tagRenderings = trs(json.tagRenderings, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       const missingIds = json.tagRenderings?.filter(tr => typeof tr !== "string" && tr["builtin"] === undefined && tr["id"] === undefined) ?? [];
 | 
					        const missingIds = json.tagRenderings?.filter(tr => typeof tr !== "string" && tr["builtin"] === undefined && tr["id"] === undefined) ?? [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       if(missingIds.length > 0 && official){
 | 
					        if (missingIds.length > 0 && official) {
 | 
				
			||||||
           console.error("Some tagRenderings of", this.id, "are missing an id:", missingIds)
 | 
					            console.error("Some tagRenderings of", this.id, "are missing an id:", missingIds)
 | 
				
			||||||
           throw "Missing ids in tagrenderings"
 | 
					            throw "Missing ids in tagrenderings"
 | 
				
			||||||
       }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.filters = (json.filter ?? []).map((option, i) => {
 | 
					        this.filters = (json.filter ?? []).map((option, i) => {
 | 
				
			||||||
            return new FilterConfig(option, `${context}.filter-[${i}]`)
 | 
					            return new FilterConfig(option, `${context}.filter-[${i}]`)
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       if(json["filters"] !== undefined){
 | 
					        if (json["filters"] !== undefined) {
 | 
				
			||||||
           throw "Error in "+context+": use 'filter' instead of 'filters'"
 | 
					            throw "Error in " + context + ": use 'filter' instead of 'filters'"
 | 
				
			||||||
       }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const titleIcons = [];
 | 
					        const titleIcons = [];
 | 
				
			||||||
        const defaultIcons = [
 | 
					        const defaultIcons = [
 | 
				
			||||||
| 
						 | 
					@ -369,6 +371,16 @@ export default class LayerConfig {
 | 
				
			||||||
            this.deletion = new DeleteConfig(json.deletion, `${context}.deletion`);
 | 
					            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) {
 | 
					        if (json["showIf"] !== undefined) {
 | 
				
			||||||
            throw (
 | 
					            throw (
 | 
				
			||||||
                "Invalid key on layerconfig " +
 | 
					                "Invalid key on layerconfig " +
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								Models/ThemeConfig/MoveConfig.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Models/ThemeConfig/MoveConfig.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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 + ")"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ import {BBox} from "../../Logic/BBox";
 | 
				
			||||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
					import {FixedUiElement} from "../Base/FixedUiElement";
 | 
				
			||||||
import ShowDataLayer from "../ShowDataLayer/ShowDataLayer";
 | 
					import ShowDataLayer from "../ShowDataLayer/ShowDataLayer";
 | 
				
			||||||
import BaseUIElement from "../BaseUIElement";
 | 
					import BaseUIElement from "../BaseUIElement";
 | 
				
			||||||
 | 
					import Toggle from "./Toggle";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LocationInput extends InputElement<Loc> implements MinimapObj {
 | 
					export default class LocationInput extends InputElement<Loc> implements MinimapObj {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,6 +162,11 @@ export default class LocationInput extends InputElement<Loc> implements MinimapO
 | 
				
			||||||
    protected InnerConstructElement(): HTMLElement {
 | 
					    protected InnerConstructElement(): HTMLElement {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            const self = this;
 | 
					            const self = this;
 | 
				
			||||||
 | 
					            const hasMoved = new UIEventSource(false)
 | 
				
			||||||
 | 
					            this.GetValue().addCallbackAndRunD(_ => {
 | 
				
			||||||
 | 
					                hasMoved.setData(true)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
            this.clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location))
 | 
					            this.clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location))
 | 
				
			||||||
             if (this._snapTo !== undefined) {
 | 
					             if (this._snapTo !== undefined) {
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
| 
						 | 
					@ -213,8 +219,8 @@ export default class LocationInput extends InputElement<Loc> implements MinimapO
 | 
				
			||||||
                    ]).SetClass("block w-0 h-0 z-10 relative")
 | 
					                    ]).SetClass("block w-0 h-0 z-10 relative")
 | 
				
			||||||
                    .SetStyle("background: rgba(255, 128, 128, 0.21); left: 50%; top: 50%; opacity: 0.5"),
 | 
					                    .SetStyle("background: rgba(255, 128, 128, 0.21); left: 50%; top: 50%; opacity: 0.5"),
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                new Combine([
 | 
					                new Toggle(undefined,
 | 
				
			||||||
                    animatedHand])
 | 
					                    animatedHand, hasMoved)
 | 
				
			||||||
                    .SetClass("block w-0 h-0 z-10 relative")
 | 
					                    .SetClass("block w-0 h-0 z-10 relative")
 | 
				
			||||||
                    .SetStyle("left: calc(50% + 3rem); top: calc(50% + 2rem); opacity: 0.7"),
 | 
					                    .SetStyle("left: calc(50% + 3rem); top: calc(50% + 2rem); opacity: 0.7"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
 | 
				
			||||||
import {Translation} from "../i18n/Translation";
 | 
					import {Translation} from "../i18n/Translation";
 | 
				
			||||||
import {Utils} from "../../Utils";
 | 
					import {Utils} from "../../Utils";
 | 
				
			||||||
import {SubstitutedTranslation} from "../SubstitutedTranslation";
 | 
					import {SubstitutedTranslation} from "../SubstitutedTranslation";
 | 
				
			||||||
 | 
					import MoveWizard from "./MoveWizard";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
					export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,6 +73,19 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
				
			||||||
            editElements.push(questionBox);
 | 
					            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) {
 | 
					        if (layerConfig.deletion) {
 | 
				
			||||||
            editElements.push(
 | 
					            editElements.push(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,13 +15,17 @@ import {OsmObject} from "../../Logic/Osm/OsmObject";
 | 
				
			||||||
import {Changes} from "../../Logic/Osm/Changes";
 | 
					import {Changes} from "../../Logic/Osm/Changes";
 | 
				
			||||||
import ChangeLocationAction from "../../Logic/Osm/Actions/ChangeLocationAction";
 | 
					import ChangeLocationAction from "../../Logic/Osm/Actions/ChangeLocationAction";
 | 
				
			||||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
 | 
					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 {
 | 
					interface MoveReason {
 | 
				
			||||||
    text: Translation | string,
 | 
					    text: Translation | string,
 | 
				
			||||||
 | 
					    invitingText: Translation | string,
 | 
				
			||||||
    icon: string | BaseUIElement,
 | 
					    icon: string | BaseUIElement,
 | 
				
			||||||
    changesetCommentValue: string,
 | 
					    changesetCommentValue: string,
 | 
				
			||||||
    lockBounds: true | boolean,
 | 
					    lockBounds: true | boolean,
 | 
				
			||||||
    background: undefined | "map" | "photo",
 | 
					    background: undefined | "map" | "photo" | string | string[],
 | 
				
			||||||
    startZoom: number,
 | 
					    startZoom: number,
 | 
				
			||||||
    minZoom: number
 | 
					    minZoom: number
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -36,13 +40,9 @@ export default class MoveWizard extends Toggle {
 | 
				
			||||||
            osmConnection: OsmConnection,
 | 
					            osmConnection: OsmConnection,
 | 
				
			||||||
            featureSwitchUserbadge: UIEventSource<boolean>,
 | 
					            featureSwitchUserbadge: UIEventSource<boolean>,
 | 
				
			||||||
            changes: Changes,
 | 
					            changes: Changes,
 | 
				
			||||||
            layoutToUse: LayoutConfig
 | 
					            layoutToUse: LayoutConfig,
 | 
				
			||||||
        }, options?: {
 | 
					            allElements: ElementStorage
 | 
				
			||||||
            reasons?: MoveReason[]
 | 
					        }, options : MoveConfig) {
 | 
				
			||||||
            disableDefaultReasons?: false | boolean
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }) {
 | 
					 | 
				
			||||||
        options = options ?? {}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const t = Translations.t.move
 | 
					        const t = Translations.t.move
 | 
				
			||||||
        const loginButton = new Toggle(
 | 
					        const loginButton = new Toggle(
 | 
				
			||||||
| 
						 | 
					@ -51,14 +51,53 @@ export default class MoveWizard extends Toggle {
 | 
				
			||||||
            state.featureSwitchUserbadge
 | 
					            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 currentStep = new UIEventSource<"start" | "reason" | "pick_location" | "moved">("start")
 | 
				
			||||||
        const moveReason = new UIEventSource<MoveReason>(undefined)
 | 
					        const moveReason = new UIEventSource<MoveReason>(undefined)
 | 
				
			||||||
        const moveButton = new SubtleButton(
 | 
					        let moveButton : BaseUIElement;
 | 
				
			||||||
            Svg.move_ui(),
 | 
					        if(reasons.length === 1){
 | 
				
			||||||
            t.inviteToMove.Clone()
 | 
					            const reason = reasons[0]
 | 
				
			||||||
        ).onClick(() => {
 | 
					            moveReason.setData(reason)
 | 
				
			||||||
            currentStep.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(
 | 
					        const moveAgainButton = new SubtleButton(
 | 
				
			||||||
            Svg.move_ui(),
 | 
					            Svg.move_ui(),
 | 
				
			||||||
| 
						 | 
					@ -68,39 +107,7 @@ 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(() => {
 | 
					        const selectReason = new Combine(reasons.map(r => new SubtleButton(r.icon, r.text).onClick(() => {
 | 
				
			||||||
            moveReason.setData(r)
 | 
					            moveReason.setData(r)
 | 
				
			||||||
| 
						 | 
					@ -124,7 +131,8 @@ export default class MoveWizard extends Toggle {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const locationInput = new LocationInput({
 | 
					            const locationInput = new LocationInput({
 | 
				
			||||||
                minZoom: reason.minZoom,
 | 
					                minZoom: reason.minZoom,
 | 
				
			||||||
                centerLocation: loc
 | 
					                centerLocation: loc,
 | 
				
			||||||
 | 
					                mapBackground: AvailableBaseLayers.SelectBestLayerAccordingTo(loc,  new UIEventSource(reason.background))
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (reason.lockBounds) {
 | 
					            if (reason.lockBounds) {
 | 
				
			||||||
| 
						 | 
					@ -135,10 +143,14 @@ export default class MoveWizard extends Toggle {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const confirmMove = new SubtleButton(Svg.move_confirm_svg(), t.confirmMove)
 | 
					            const confirmMove = new SubtleButton(Svg.move_confirm_svg(), t.confirmMove)
 | 
				
			||||||
            confirmMove.onClick(() => {
 | 
					            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"),
 | 
					                    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")
 | 
					                currentStep.setData("moved")
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            const zoomInFurhter = t.zoomInFurther.Clone().SetClass("alert block m-6")
 | 
					            const zoomInFurhter = t.zoomInFurther.Clone().SetClass("alert block m-6")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								Utils.ts
									
										
									
									
									
								
							| 
						 | 
					@ -320,6 +320,19 @@ export class Utils {
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static _download_cache = new Map<string, {promise: Promise<any>, timestamp: number}>()
 | 
				
			||||||
 | 
					    public static async downloadJsonCached(url: string, maxCacheTimeMs: number, headers?: any): Promise<any> {
 | 
				
			||||||
 | 
					        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<any> {
 | 
					    public static async downloadJson(url: string, headers?: any): Promise<any> {
 | 
				
			||||||
        const injected = Utils.injectedDownloads[url]
 | 
					        const injected = Utils.injectedDownloads[url]
 | 
				
			||||||
        if (injected !== undefined) {
 | 
					        if (injected !== undefined) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -600,5 +600,18 @@
 | 
				
			||||||
                "preferredBackground": "photo"
 | 
					                "preferredBackground": "photo"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity=bench",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -255,5 +255,18 @@
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "multiAnswer": true
 | 
					            "multiAnswer": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -145,5 +145,18 @@
 | 
				
			||||||
            "roaming": false,
 | 
					            "roaming": false,
 | 
				
			||||||
            "id": "bike_cleaning-charge"
 | 
					            "id": "bike_cleaning-charge"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -508,5 +508,18 @@
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "id": "Cargo bike capacity?"
 | 
					            "id": "Cargo bike capacity?"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -731,5 +731,18 @@
 | 
				
			||||||
                "service:bicycle:pump=no"
 | 
					                "service:bicycle:pump=no"
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -100,5 +100,18 @@
 | 
				
			||||||
                "amenity=binoculars"
 | 
					                "amenity=binoculars"
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -296,5 +296,17 @@
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -181,5 +181,11 @@
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": ["amenity=","disused:amenity:={amenity}"]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3655,5 +3655,18 @@
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "eraseInvalidValues": true
 | 
					            "eraseInvalidValues": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -539,5 +539,18 @@
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "id": "defibrillator-fixme"
 | 
					            "id": "defibrillator-fixme"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:emergency:=defibrillator}",
 | 
				
			||||||
 | 
					                "emergency="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 5
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -166,5 +166,18 @@
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "condition": "_closest_other_drinking_water_id~*"
 | 
					            "condition": "_closest_other_drinking_water_id~*"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -624,5 +624,11 @@
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": ["amenity=","disused:amenity:={amenity}"]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -187,5 +187,18 @@
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "id": "ghost_bike-start_date"
 | 
					            "id": "ghost_bike-start_date"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "razed:memorial:=ghost_bike",
 | 
				
			||||||
 | 
					                "memorial="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 50
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -53,5 +53,20 @@
 | 
				
			||||||
                "ru": "Информационный щит"
 | 
					                "ru": "Информационный щит"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:tourism:=information",
 | 
				
			||||||
 | 
					                "tourism=" ,
 | 
				
			||||||
 | 
					                "razed:information=board",
 | 
				
			||||||
 | 
					                "information="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -227,5 +227,18 @@
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "wayHandling": 2
 | 
					    "wayHandling": 2,
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "razed:tourism:=information",
 | 
				
			||||||
 | 
					                "tourism="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -180,5 +180,9 @@
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "eraseInvalidValues": true
 | 
					            "eraseInvalidValues": true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -81,5 +81,18 @@
 | 
				
			||||||
                "nl": "Voeg hier een parking voor auto's toe"
 | 
					                "nl": "Voeg hier een parking voor auto's toe"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -101,5 +101,18 @@
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "wayHandling": 1
 | 
					    "wayHandling": 1,
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -498,5 +498,18 @@
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -115,5 +115,18 @@
 | 
				
			||||||
                "preferredBackground": "photo"
 | 
					                "preferredBackground": "photo"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ]
 | 
					    ],
 | 
				
			||||||
 | 
					    "deletion": {
 | 
				
			||||||
 | 
					        "softDeletionTags": {
 | 
				
			||||||
 | 
					            "and": [
 | 
				
			||||||
 | 
					                "disused:amenity:={amenity}",
 | 
				
			||||||
 | 
					                "amenity="
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "neededChangesets": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "allowMove": {
 | 
				
			||||||
 | 
					        "enableRelocation": false,
 | 
				
			||||||
 | 
					        "enableImproveAccuraccy": true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -256,7 +256,6 @@
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "move": {
 | 
					    "move": {
 | 
				
			||||||
        "loginToMove": "You must be logged in to move a point",
 | 
					        "loginToMove": "You must be logged in to move a point",
 | 
				
			||||||
        "inviteToMove": "Move this point",
 | 
					 | 
				
			||||||
        "inviteToMoveAgain": "Move this point again",
 | 
					        "inviteToMoveAgain": "Move this point again",
 | 
				
			||||||
        "moveTitle": "Move this point",
 | 
					        "moveTitle": "Move this point",
 | 
				
			||||||
        "whyMove": "Why do you want to move this point?",
 | 
					        "whyMove": "Why do you want to move this point?",
 | 
				
			||||||
| 
						 | 
					@ -264,8 +263,15 @@
 | 
				
			||||||
        "pointIsMoved": "The point has been moved",
 | 
					        "pointIsMoved": "The point has been moved",
 | 
				
			||||||
        "zoomInFurther": "Zoom in further to confirm this move",
 | 
					        "zoomInFurther": "Zoom in further to confirm this move",
 | 
				
			||||||
        "selectReason": "Why do you move this object?",
 | 
					        "selectReason": "Why do you move this object?",
 | 
				
			||||||
        "reasonRelocation": "The object has been relocated to a totally different location",
 | 
					        "reasons": {
 | 
				
			||||||
        "reasonInaccurate": "The location of this object is inaccurate and should be moved a few meter",
 | 
					            "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.",
 | 
					        "cannotBeMoved": "This feature cannot be moved.",
 | 
				
			||||||
        "isWay": "This feature is a way. Use another OpenStreetMap editor to move it.",
 | 
					        "isWay": "This feature is a way. Use another OpenStreetMap editor to move it.",
 | 
				
			||||||
        "isRelation": "This feature is a relation and can not be moved",
 | 
					        "isRelation": "This feature is a relation and can not be moved",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@
 | 
				
			||||||
  "homepage": "https://mapcomplete.osm.be",
 | 
					  "homepage": "https://mapcomplete.osm.be",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "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:*",
 | 
					    "start": "npm run start:prepare && npm-run-all --parallel start:parallel:*",
 | 
				
			||||||
    "strt": "npm run start:prepare && npm run start:parallel:parcel",
 | 
					    "strt": "npm run start:prepare && npm run start:parallel:parcel",
 | 
				
			||||||
    "start:prepare": "ts-node scripts/generateLayerOverview.ts --no-fail && npm run increase-memory",
 | 
					    "start:prepare": "ts-node scripts/generateLayerOverview.ts --no-fail && npm run increase-memory",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								test.ts
									
										
									
									
									
								
							| 
						 | 
					@ -2,6 +2,9 @@ import MoveWizard from "./UI/Popup/MoveWizard";
 | 
				
			||||||
import State from "./State";
 | 
					import State from "./State";
 | 
				
			||||||
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
 | 
					import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
 | 
				
			||||||
import MinimapImplementation from "./UI/Base/MinimapImplementation";
 | 
					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"))
 | 
					State.state = new State(AllKnownLayouts.allKnownLayouts.get("bookcases"))
 | 
				
			||||||
| 
						 | 
					@ -18,8 +21,14 @@ const feature = {
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
MinimapImplementation.initialize()
 | 
					MinimapImplementation.initialize()
 | 
				
			||||||
new MoveWizard(
 | 
					new MoveWizard(
 | 
				
			||||||
    feature,
 | 
					    feature,
 | 
				
			||||||
    State.state).AttachTo("maindiv")
 | 
					    State.state,
 | 
				
			||||||
 | 
					    new MoveConfig({
 | 
				
			||||||
 | 
					        enableRelocation: false,
 | 
				
			||||||
 | 
					        enableImproveAccuracy: true
 | 
				
			||||||
 | 
					    }, "test")).AttachTo("maindiv")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue