forked from MapComplete/MapComplete
		
	Add export_as_geojson, open_in_id and open_in_josm special renderings
This commit is contained in:
		
							parent
							
								
									b0f0a57bc7
								
							
						
					
					
						commit
						7f829a3578
					
				
					 8 changed files with 144 additions and 60 deletions
				
			
		| 
						 | 
					@ -19,9 +19,82 @@ import Loc from "../../Models/Loc";
 | 
				
			||||||
import Toggle from "../Input/Toggle";
 | 
					import Toggle from "../Input/Toggle";
 | 
				
			||||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
 | 
					import {OsmConnection} from "../../Logic/Osm/OsmConnection";
 | 
				
			||||||
import Constants from "../../Models/Constants";
 | 
					import Constants from "../../Models/Constants";
 | 
				
			||||||
import PrivacyPolicy from "./PrivacyPolicy";
 | 
					 | 
				
			||||||
import ContributorCount from "../../Logic/ContributorCount";
 | 
					import ContributorCount from "../../Logic/ContributorCount";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class OpenIdEditor extends VariableUiElement {
 | 
				
			||||||
 | 
					    constructor(state : {locationControl: UIEventSource<Loc>}, iconStyle? : string, objectId?: string) {
 | 
				
			||||||
 | 
					        const t = Translations.t.general.attribution
 | 
				
			||||||
 | 
					        super(state.locationControl.map(location => {
 | 
				
			||||||
 | 
					            let elementSelect = "";
 | 
				
			||||||
 | 
					            if(objectId !== undefined){
 | 
				
			||||||
 | 
					               const parts = objectId.split("/")
 | 
				
			||||||
 | 
					                const tp = parts[0]
 | 
				
			||||||
 | 
					                if(parts.length === 2 && !isNaN(Number(parts[1]))  && (tp === "node" || tp === "way" || tp === "relation")){
 | 
				
			||||||
 | 
					                    elementSelect = "&"+ tp+"="+parts[1]
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const idLink = `https://www.openstreetmap.org/edit?editor=id${elementSelect}#map=${location?.zoom ?? 0}/${location?.lat ?? 0}/${location?.lon ?? 0}`
 | 
				
			||||||
 | 
					            return new SubtleButton(Svg.pencil_ui().SetStyle(iconStyle), t.editId, {url: idLink, newTab: true})
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class OpenMapillary extends VariableUiElement {
 | 
				
			||||||
 | 
					    constructor(state : {locationControl: UIEventSource<Loc>}, iconStyle? : string) {
 | 
				
			||||||
 | 
					        const t = Translations.t.general.attribution
 | 
				
			||||||
 | 
					       super( state.locationControl.map(location => {
 | 
				
			||||||
 | 
					            const mapillaryLink = `https://www.mapillary.com/app/?focus=map&lat=${location?.lat ?? 0}&lng=${location?.lon ?? 0}&z=${Math.max((location?.zoom ?? 2) - 1, 1)}`
 | 
				
			||||||
 | 
					            return new SubtleButton(Svg.mapillary_black_ui().SetStyle(iconStyle), t.openMapillary, {
 | 
				
			||||||
 | 
					                url: mapillaryLink,
 | 
				
			||||||
 | 
					                newTab: true
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class OpenJosm extends Combine {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(state : {osmConnection: OsmConnection, currentBounds: UIEventSource<BBox>,}, iconStyle? : string) {
 | 
				
			||||||
 | 
					   const t = Translations.t.general.attribution
 | 
				
			||||||
 | 
					     
 | 
				
			||||||
 | 
					        const josmState = new UIEventSource<string>(undefined)
 | 
				
			||||||
 | 
					        // Reset after 15s
 | 
				
			||||||
 | 
					        josmState.stabilized(15000).addCallbackD(_ => josmState.setData(undefined))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const stateIndication = new VariableUiElement(josmState.map(state => {
 | 
				
			||||||
 | 
					            if (state === undefined) {
 | 
				
			||||||
 | 
					                return undefined
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            state = state.toUpperCase()
 | 
				
			||||||
 | 
					            if (state === "OK") {
 | 
				
			||||||
 | 
					                return t.josmOpened.SetClass("thanks")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return t.josmNotOpened.SetClass("alert")
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const toggle =    new Toggle(
 | 
				
			||||||
 | 
					                new SubtleButton(Svg.josm_logo_ui().SetStyle(iconStyle), t.editJosm).onClick(() => {
 | 
				
			||||||
 | 
					                    const bounds: any = state.currentBounds.data;
 | 
				
			||||||
 | 
					                    if (bounds === undefined) {
 | 
				
			||||||
 | 
					                        return undefined
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    const top = bounds.getNorth();
 | 
				
			||||||
 | 
					                    const bottom = bounds.getSouth();
 | 
				
			||||||
 | 
					                    const right = bounds.getEast();
 | 
				
			||||||
 | 
					                    const left = bounds.getWest();
 | 
				
			||||||
 | 
					                    const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}`
 | 
				
			||||||
 | 
					                    Utils.download(josmLink).then(answer => josmState.setData(answer.replace(/\n/g, '').trim())).catch(_ => josmState.setData("ERROR"))
 | 
				
			||||||
 | 
					                }), undefined, state.osmConnection.userDetails.map(ud => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super([stateIndication, toggle]);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The attribution panel shown on mobile
 | 
					 * The attribution panel shown on mobile
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -39,9 +112,6 @@ export default class CopyrightPanel extends Combine {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const t = Translations.t.general.attribution
 | 
					        const t = Translations.t.general.attribution
 | 
				
			||||||
        const layoutToUse = state.layoutToUse
 | 
					        const layoutToUse = state.layoutToUse
 | 
				
			||||||
        const josmState = new UIEventSource<string>(undefined)
 | 
					 | 
				
			||||||
        // Reset after 15s
 | 
					 | 
				
			||||||
        josmState.stabilized(15000).addCallbackD(_ => josmState.setData(undefined))
 | 
					 | 
				
			||||||
          const iconStyle = "height: 1.5rem; width: auto"
 | 
					          const iconStyle = "height: 1.5rem; width: auto"
 | 
				
			||||||
        const actionButtons = [
 | 
					        const actionButtons = [
 | 
				
			||||||
            new SubtleButton(Svg.liberapay_ui().SetStyle(iconStyle), t.donate, {
 | 
					            new SubtleButton(Svg.liberapay_ui().SetStyle(iconStyle), t.donate, {
 | 
				
			||||||
| 
						 | 
					@ -56,42 +126,9 @@ export default class CopyrightPanel extends Combine {
 | 
				
			||||||
                url: Utils.OsmChaLinkFor(31, state.layoutToUse.id),
 | 
					                url: Utils.OsmChaLinkFor(31, state.layoutToUse.id),
 | 
				
			||||||
                newTab: true
 | 
					                newTab: true
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
            new VariableUiElement(state.locationControl.map(location => {
 | 
					            new OpenIdEditor(state, iconStyle),
 | 
				
			||||||
                const idLink = `https://www.openstreetmap.org/edit?editor=id#map=${location?.zoom ?? 0}/${location?.lat ?? 0}/${location?.lon ?? 0}`
 | 
					            new OpenMapillary(state, iconStyle),
 | 
				
			||||||
                return new SubtleButton(Svg.pencil_ui().SetStyle(iconStyle), t.editId, {url: idLink, newTab: true})
 | 
					            new OpenJosm(state, iconStyle)
 | 
				
			||||||
            })),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            new VariableUiElement(state.locationControl.map(location => {
 | 
					 | 
				
			||||||
                const mapillaryLink = `https://www.mapillary.com/app/?focus=map&lat=${location?.lat ?? 0}&lng=${location?.lon ?? 0}&z=${Math.max((location?.zoom ?? 2) - 1, 1)}`
 | 
					 | 
				
			||||||
                return new SubtleButton(Svg.mapillary_black_ui().SetStyle(iconStyle), t.openMapillary, {
 | 
					 | 
				
			||||||
                    url: mapillaryLink,
 | 
					 | 
				
			||||||
                    newTab: true
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })),
 | 
					 | 
				
			||||||
            new VariableUiElement(josmState.map(state => {
 | 
					 | 
				
			||||||
                if (state === undefined) {
 | 
					 | 
				
			||||||
                    return undefined
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                state = state.toUpperCase()
 | 
					 | 
				
			||||||
                if (state === "OK") {
 | 
					 | 
				
			||||||
                    return t.josmOpened.SetClass("thanks")
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return t.josmNotOpened.SetClass("alert")
 | 
					 | 
				
			||||||
            })),
 | 
					 | 
				
			||||||
            new Toggle(
 | 
					 | 
				
			||||||
                new SubtleButton(Svg.josm_logo_ui().SetStyle(iconStyle), t.editJosm).onClick(() => {
 | 
					 | 
				
			||||||
                    const bounds: any = state.currentBounds.data;
 | 
					 | 
				
			||||||
                    if (bounds === undefined) {
 | 
					 | 
				
			||||||
                        return undefined
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    const top = bounds.getNorth();
 | 
					 | 
				
			||||||
                    const bottom = bounds.getSouth();
 | 
					 | 
				
			||||||
                    const right = bounds.getEast();
 | 
					 | 
				
			||||||
                    const left = bounds.getWest();
 | 
					 | 
				
			||||||
                    const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}`
 | 
					 | 
				
			||||||
                    Utils.download(josmLink).then(answer => josmState.setData(answer.replace(/\n/g, '').trim())).catch(_ => josmState.setData("ERROR"))
 | 
					 | 
				
			||||||
                }), undefined, state.osmConnection.userDetails.map(ud => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible)),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const iconAttributions = Utils.NoNull(Array.from(layoutToUse.ExtractImages()))
 | 
					        const iconAttributions = Utils.NoNull(Array.from(layoutToUse.ExtractImages()))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,6 @@ import {Utils} from "../../Utils";
 | 
				
			||||||
import {SubstitutedTranslation} from "../SubstitutedTranslation";
 | 
					import {SubstitutedTranslation} from "../SubstitutedTranslation";
 | 
				
			||||||
import MoveWizard from "./MoveWizard";
 | 
					import MoveWizard from "./MoveWizard";
 | 
				
			||||||
import Toggle from "../Input/Toggle";
 | 
					import Toggle from "../Input/Toggle";
 | 
				
			||||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
					export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -189,8 +188,13 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
				
			||||||
            new VariableUiElement(
 | 
					            new VariableUiElement(
 | 
				
			||||||
                State.state.featureSwitchIsDebugging.map(isDebugging => {
 | 
					                State.state.featureSwitchIsDebugging.map(isDebugging => {
 | 
				
			||||||
                    if (isDebugging) {
 | 
					                    if (isDebugging) {
 | 
				
			||||||
                        const config: TagRenderingConfig = new TagRenderingConfig({render: "{all_tags()}"}, "");
 | 
					                        const config_all_tags: TagRenderingConfig = new TagRenderingConfig({render: "{all_tags()}"}, "");
 | 
				
			||||||
                        return new TagRenderingAnswer(tags, config, "all_tags")
 | 
					                        const config_download: TagRenderingConfig = new TagRenderingConfig({render: "{export_as_geojson()}"}, "");
 | 
				
			||||||
 | 
					                        const config_id: TagRenderingConfig = new TagRenderingConfig({render: "{open_in_iD()}"}, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return new Combine([new TagRenderingAnswer(tags, config_all_tags, "all_tags"),
 | 
				
			||||||
 | 
					                            new TagRenderingAnswer(tags, config_download, ""),
 | 
				
			||||||
 | 
					                            new TagRenderingAnswer(tags, config_id, "")])
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@ import FeaturePipelineState from "../Logic/State/FeaturePipelineState";
 | 
				
			||||||
import {ConflateButton, ImportPointButton, ImportWayButton} from "./Popup/ImportButton";
 | 
					import {ConflateButton, ImportPointButton, ImportWayButton} from "./Popup/ImportButton";
 | 
				
			||||||
import TagApplyButton from "./Popup/TagApplyButton";
 | 
					import TagApplyButton from "./Popup/TagApplyButton";
 | 
				
			||||||
import AutoApplyButton from "./Popup/AutoApplyButton";
 | 
					import AutoApplyButton from "./Popup/AutoApplyButton";
 | 
				
			||||||
 | 
					import {OpenIdEditor} from "./BigComponents/CopyrightPanel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface SpecialVisualization {
 | 
					export interface SpecialVisualization {
 | 
				
			||||||
    funcName: string,
 | 
					    funcName: string,
 | 
				
			||||||
| 
						 | 
					@ -543,7 +544,7 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                        const t = Translations.t.general.download;
 | 
					                        const t = Translations.t.general.download;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        return new SubtleButton(Svg.download_ui(),
 | 
					                        return new SubtleButton(Svg.download_ui(),
 | 
				
			||||||
                            new Combine([t.downloadGpx.SetClass("font-bold text-lg"),
 | 
					                            new Combine([t.downloadFeatureAsGpx.SetClass("font-bold text-lg"),
 | 
				
			||||||
                                t.downloadGpxHelper.SetClass("subtle")]).SetClass("flex flex-col")
 | 
					                                t.downloadGpxHelper.SetClass("subtle")]).SetClass("flex flex-col")
 | 
				
			||||||
                        ).onClick(() => {
 | 
					                        ).onClick(() => {
 | 
				
			||||||
                            console.log("Exporting as GPX!")
 | 
					                            console.log("Exporting as GPX!")
 | 
				
			||||||
| 
						 | 
					@ -560,6 +561,41 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    funcName: "export_as_geojson",
 | 
				
			||||||
 | 
					                    docs: "Exports the selected feature as GeoJson-file",
 | 
				
			||||||
 | 
					                    args: [],
 | 
				
			||||||
 | 
					                    constr: (state, tagSource, args) => {
 | 
				
			||||||
 | 
					                        const t = Translations.t.general.download;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return new SubtleButton(Svg.download_ui(),
 | 
				
			||||||
 | 
					                            new Combine([t.downloadFeatureAsGeojson.SetClass("font-bold text-lg"),
 | 
				
			||||||
 | 
					                                t.downloadGeoJsonHelper.SetClass("subtle")]).SetClass("flex flex-col")
 | 
				
			||||||
 | 
					                        ).onClick(() => {
 | 
				
			||||||
 | 
					                            console.log("Exporting as Geojson")
 | 
				
			||||||
 | 
					                            const tags = tagSource.data
 | 
				
			||||||
 | 
					                            const feature = state.allElements.ContainingFeatures.get(tags.id)
 | 
				
			||||||
 | 
					                            const matchingLayer = state?.layoutToUse?.getMatchingLayer(tags)
 | 
				
			||||||
 | 
					                            const title = matchingLayer.title?.GetRenderValue(tags)?.Subs(tags)?.txt ?? "geojson"
 | 
				
			||||||
 | 
					                            const data = JSON.stringify(feature, null, "  ");
 | 
				
			||||||
 | 
					                            Utils.offerContentsAsDownloadableFile(data, title + "_mapcomplete_export.geojson", {
 | 
				
			||||||
 | 
					                                mimetype: "application/vnd.geo+json"
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    funcName: "open_in_iD",
 | 
				
			||||||
 | 
					                    docs: "Opens the current view in the iD-editor",
 | 
				
			||||||
 | 
					                    args: [],
 | 
				
			||||||
 | 
					                    constr: (state, feature ) => {
 | 
				
			||||||
 | 
					                        return new OpenIdEditor(state, undefined, feature.data.id)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    funcName: "clear_location_history",
 | 
					                    funcName: "clear_location_history",
 | 
				
			||||||
                    docs: "A button to remove the travelled track information from the device",
 | 
					                    docs: "A button to remove the travelled track information from the device",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,11 +3,16 @@
 | 
				
			||||||
  "description": "The default rendering for a locationInput which snaps onto another object",
 | 
					  "description": "The default rendering for a locationInput which snaps onto another object",
 | 
				
			||||||
  "source": {
 | 
					  "source": {
 | 
				
			||||||
    "osmTags": {
 | 
					    "osmTags": {
 | 
				
			||||||
      "and": []}
 | 
					      "and": []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "mapRendering": [{
 | 
					  "mapRendering": [
 | 
				
			||||||
    "location": ["point","centroid"],
 | 
					    {
 | 
				
			||||||
 | 
					      "location": [
 | 
				
			||||||
 | 
					        "point",
 | 
				
			||||||
 | 
					        "centroid"
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
      "icon": "./assets/svg/crosshair-empty.svg"
 | 
					      "icon": "./assets/svg/crosshair-empty.svg"
 | 
				
			||||||
  }]
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -99,8 +99,7 @@
 | 
				
			||||||
        "osmTags": "building~*",
 | 
					        "osmTags": "building~*",
 | 
				
			||||||
        "maxCacheAge": 0
 | 
					        "maxCacheAge": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "calculatedTags": [
 | 
					      "calculatedTags": [],
 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
      "mapRendering": [
 | 
					      "mapRendering": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "width": {
 | 
					          "width": {
 | 
				
			||||||
| 
						 | 
					@ -319,7 +318,6 @@
 | 
				
			||||||
        "render": "Service road"
 | 
					        "render": "Service road"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "tagRenderings": []
 | 
					      "tagRenderings": []
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "generic_osm_object",
 | 
					      "id": "generic_osm_object",
 | 
				
			||||||
| 
						 | 
					@ -475,7 +473,10 @@
 | 
				
			||||||
      "description": "Geometry which comes from GRB with tools to import them",
 | 
					      "description": "Geometry which comes from GRB with tools to import them",
 | 
				
			||||||
      "source": {
 | 
					      "source": {
 | 
				
			||||||
        "osmTags": {
 | 
					        "osmTags": {
 | 
				
			||||||
         "and": ["HUISNR~*","man_made!=mast"]
 | 
					          "and": [
 | 
				
			||||||
 | 
					            "HUISNR~*",
 | 
				
			||||||
 | 
					            "man_made!=mast"
 | 
				
			||||||
 | 
					          ]
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "geoJson": "https://betadata.grbosm.site/grb?bbox={x_min},{y_min},{x_max},{y_max}",
 | 
					        "geoJson": "https://betadata.grbosm.site/grb?bbox={x_min},{y_min},{x_max},{y_max}",
 | 
				
			||||||
        "geoJsonZoomLevel": 18,
 | 
					        "geoJsonZoomLevel": 18,
 | 
				
			||||||
| 
						 | 
					@ -508,7 +509,8 @@
 | 
				
			||||||
          "id": "Import-button",
 | 
					          "id": "Import-button",
 | 
				
			||||||
          "render": "{import_way_button(OSM-buildings,building=$building;man_made=$man_made; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber; building:min_level=$_building:min_level, Upload this building to OpenStreetMap,,_is_part_of_building=true,1,_moveable=true)}",
 | 
					          "render": "{import_way_button(OSM-buildings,building=$building;man_made=$man_made; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber; building:min_level=$_building:min_level, Upload this building to OpenStreetMap,,_is_part_of_building=true,1,_moveable=true)}",
 | 
				
			||||||
          "mappings": [
 | 
					          "mappings": [
 | 
				
			||||||
            {"#": "Hide import button if intersection with other objects are detected",
 | 
					            {
 | 
				
			||||||
 | 
					              "#": "Hide import button if intersection with other objects are detected",
 | 
				
			||||||
              "if": "_intersects_with_other_features~*",
 | 
					              "if": "_intersects_with_other_features~*",
 | 
				
			||||||
              "then": "This GRB building intersects with the following features: {_intersects_with_other_features}.<br/>Fix the overlap and try again"
 | 
					              "then": "This GRB building intersects with the following features: {_intersects_with_other_features}.<br/>Fix the overlap and try again"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -555,7 +557,6 @@
 | 
				
			||||||
              "if": "_osm_obj:addr:housenumber~*",
 | 
					              "if": "_osm_obj:addr:housenumber~*",
 | 
				
			||||||
              "then": "The overlapping building only has a housenumber known: {_osm_obj:addr:housenumber}"
 | 
					              "then": "The overlapping building only has a housenumber known: {_osm_obj:addr:housenumber}"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              "if": "_osm_obj:id=",
 | 
					              "if": "_osm_obj:id=",
 | 
				
			||||||
              "then": "No overlapping OpenStreetMap-building found"
 | 
					              "then": "No overlapping OpenStreetMap-building found"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,7 +198,8 @@
 | 
				
			||||||
      "downloadAsPdf": "Download a PDF of the current map",
 | 
					      "downloadAsPdf": "Download a PDF of the current map",
 | 
				
			||||||
      "downloadAsPdfHelper": "Ideal to print the current map",
 | 
					      "downloadAsPdfHelper": "Ideal to print the current map",
 | 
				
			||||||
      "downloadGeojson": "Download visible data as GeoJSON",
 | 
					      "downloadGeojson": "Download visible data as GeoJSON",
 | 
				
			||||||
      "downloadGpx": "Download as GPX-file",
 | 
					      "downloadFeatureAsGpx": "Download as GPX-file",
 | 
				
			||||||
 | 
					      "downloadFeatureAsGeojson": "Download as GeoJson-file",
 | 
				
			||||||
      "downloadGpxHelper": "A GPX-file can be used with most navigation devices and applications",
 | 
					      "downloadGpxHelper": "A GPX-file can be used with most navigation devices and applications",
 | 
				
			||||||
      "uploadGpx": "Upload your track to OpenStreetMap",
 | 
					      "uploadGpx": "Upload your track to OpenStreetMap",
 | 
				
			||||||
      "exporting": "Exporting…",
 | 
					      "exporting": "Exporting…",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ export default class T {
 | 
				
			||||||
     * Returns an empty list if successful
 | 
					     * Returns an empty list if successful
 | 
				
			||||||
     * @constructor
 | 
					     * @constructor
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public Run(): ({ testsuite: string, name: string, msg: string } []) {
 | 
					    public Run(): { testsuite: string, name: string, msg: string } [] {
 | 
				
			||||||
        const failures: { testsuite: string, name: string, msg: string } [] = []
 | 
					        const failures: { testsuite: string, name: string, msg: string } [] = []
 | 
				
			||||||
        for (const [name, test] of this._tests) {
 | 
					        for (const [name, test] of this._tests) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue