forked from MapComplete/MapComplete
		
	Merge develop
This commit is contained in:
		
						commit
						42391b4ff1
					
				
					 20 changed files with 362 additions and 199 deletions
				
			
		| 
						 | 
					@ -42,6 +42,7 @@ export default class LayoutConfig {
 | 
				
			||||||
    public readonly enableGeolocation: boolean;
 | 
					    public readonly enableGeolocation: boolean;
 | 
				
			||||||
    public readonly enableBackgroundLayerSelection: boolean;
 | 
					    public readonly enableBackgroundLayerSelection: boolean;
 | 
				
			||||||
    public readonly enableShowAllQuestions: boolean;
 | 
					    public readonly enableShowAllQuestions: boolean;
 | 
				
			||||||
 | 
					    public readonly enableExportButton: boolean;
 | 
				
			||||||
    public readonly customCss?: string;
 | 
					    public readonly customCss?: string;
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
    How long is the cache valid, in seconds?
 | 
					    How long is the cache valid, in seconds?
 | 
				
			||||||
| 
						 | 
					@ -152,6 +153,7 @@ export default class LayoutConfig {
 | 
				
			||||||
        this.enableAddNewPoints = json.enableAddNewPoints ?? true;
 | 
					        this.enableAddNewPoints = json.enableAddNewPoints ?? true;
 | 
				
			||||||
        this.enableBackgroundLayerSelection = json.enableBackgroundLayerSelection ?? true;
 | 
					        this.enableBackgroundLayerSelection = json.enableBackgroundLayerSelection ?? true;
 | 
				
			||||||
        this.enableShowAllQuestions = json.enableShowAllQuestions ?? false;
 | 
					        this.enableShowAllQuestions = json.enableShowAllQuestions ?? false;
 | 
				
			||||||
 | 
					        this.enableExportButton = json.enableExportButton ?? false;
 | 
				
			||||||
        this.customCss = json.customCss;
 | 
					        this.customCss = json.customCss;
 | 
				
			||||||
        this.cacheTimeout = json.cacheTimout ?? (60 * 24 * 60 * 60)
 | 
					        this.cacheTimeout = json.cacheTimout ?? (60 * 24 * 60 * 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ import UnitConfigJson from "./UnitConfigJson";
 | 
				
			||||||
 * General remark: a type (string | any) indicates either a fixed or a translatable string.
 | 
					 * General remark: a type (string | any) indicates either a fixed or a translatable string.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export interface LayoutConfigJson {
 | 
					export interface LayoutConfigJson {
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The id of this layout.
 | 
					     * The id of this layout.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -335,4 +336,5 @@ export interface LayoutConfigJson {
 | 
				
			||||||
    enableGeolocation?: boolean;
 | 
					    enableGeolocation?: boolean;
 | 
				
			||||||
    enableBackgroundLayerSelection?: boolean;
 | 
					    enableBackgroundLayerSelection?: boolean;
 | 
				
			||||||
    enableShowAllQuestions?: boolean;
 | 
					    enableShowAllQuestions?: boolean;
 | 
				
			||||||
 | 
					    enableExportButton?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,34 @@ the URL-parameters are stated in the part between the `?` and the `#`. There are
 | 
				
			||||||
Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
 | 
					Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					backend
 | 
				
			||||||
 | 
					---------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test' The default value is _osm_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org The default value is _false_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The layout to load into MapComplete The default value is __
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					userlayout
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The hash of the URL contains a base64-encoded .json-file containing the theme definition
 | 
				
			||||||
 | 
					- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator
 | 
				
			||||||
 | 
					- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme The default value is _false_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layer-control-toggle
 | 
					layer-control-toggle
 | 
				
			||||||
----------------------
 | 
					----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,19 +63,19 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
 | 
				
			||||||
z
 | 
					z
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 The initial/current zoom level The default value is _0_
 | 
					The initial/current zoom level The default value is _14_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lat
 | 
					lat
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 The initial/current latitude The default value is _0_
 | 
					The initial/current latitude The default value is _51.2095_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lon
 | 
					lon
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 The initial/current longitude of the app The default value is _0_
 | 
					The initial/current longitude of the app The default value is _3.2228_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fs-userbadge
 | 
					fs-userbadge
 | 
				
			||||||
| 
						 | 
					@ -110,10 +138,16 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
 | 
				
			||||||
Always show all questions The default value is _false_
 | 
					Always show all questions The default value is _false_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 test 
 | 
					fs-export
 | 
				
			||||||
------
 | 
					-----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org The default value is _false_
 | 
					If set, enables the 'download'-button to download everything as geojson The default value is _false_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fake-user
 | 
				
			||||||
 | 
					-----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If true, 'dryrun' mode is activated and a fake user account is loaded The default value is _false_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
debug
 | 
					debug
 | 
				
			||||||
| 
						 | 
					@ -122,12 +156,6 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
 | 
				
			||||||
If true, shows some extra debugging help such as all the available tags on every object The default value is _false_
 | 
					If true, shows some extra debugging help such as all the available tags on every object The default value is _false_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 backend 
 | 
					 | 
				
			||||||
---------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test' The default value is _osm_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
custom-css
 | 
					custom-css
 | 
				
			||||||
------------
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,6 +168,10 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.
 | 
				
			||||||
The id of the background layer to start with The default value is _osm_
 | 
					The id of the background layer to start with The default value is _osm_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					oauth_token
 | 
				
			||||||
 | 
					-------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Used to complete the login No default value set
 | 
				
			||||||
 layer-<layer-id> 
 | 
					 layer-<layer-id> 
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -427,6 +427,8 @@ export class InitUiElements {
 | 
				
			||||||
            state.locationControl,
 | 
					            state.locationControl,
 | 
				
			||||||
            state.selectedElement);
 | 
					            state.selectedElement);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        State.state.featurePipeline = source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        new ShowDataLayer(source.features, State.state.leafletMap, State.state.layoutToUse);
 | 
					        new ShowDataLayer(source.features, State.state.leafletMap, State.state.layoutToUse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const selectedFeatureHandler = new SelectedFeatureHandler(Hash.hash, State.state.selectedElement, source, State.state.osmApiFeatureSource);
 | 
					        const selectedFeatureHandler = new SelectedFeatureHandler(Hash.hash, State.state.selectedElement, source, State.state.osmApiFeatureSource);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
import {UIEventSource} from "../UIEventSource";
 | 
					import {UIEventSource} from "../UIEventSource";
 | 
				
			||||||
 | 
					import {Utils} from "../../Utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default interface FeatureSource {
 | 
					export default interface FeatureSource {
 | 
				
			||||||
    features: UIEventSource<{ feature: any, freshness: Date }[]>;
 | 
					    features: UIEventSource<{ feature: any, freshness: Date }[]>;
 | 
				
			||||||
| 
						 | 
					@ -7,3 +8,38 @@ export default interface FeatureSource {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class FeatureSourceUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Exports given featurePipeline as a geojson FeatureLists (downloads as a json)
 | 
				
			||||||
 | 
					     * @param featurePipeline The FeaturePipeline you want to export
 | 
				
			||||||
 | 
					     * @param options The options object
 | 
				
			||||||
 | 
					     * @param options.metadata True if you want to include the MapComplete metadata, false otherwise
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static extractGeoJson(featurePipeline: FeatureSource, options: { metadata?: boolean } = {}) {
 | 
				
			||||||
 | 
					        let defaults = {
 | 
				
			||||||
 | 
					            metadata: false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        options = Utils.setDefaults(options, defaults);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Select all features, ignore the freshness and other data
 | 
				
			||||||
 | 
					        let featureList: any[] = featurePipeline.features.data.map((feature) => feature.feature);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!options.metadata) {
 | 
				
			||||||
 | 
					            for (let i = 0; i < featureList.length; i++) {
 | 
				
			||||||
 | 
					                let feature = featureList[i];
 | 
				
			||||||
 | 
					                for (let property in feature.properties) {
 | 
				
			||||||
 | 
					                    if (property[0] == "_") {
 | 
				
			||||||
 | 
					                        delete featureList[i]["properties"][property];
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return {type: "FeatureCollection", features: featureList}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,7 @@ export class OsmConnection {
 | 
				
			||||||
    public auth;
 | 
					    public auth;
 | 
				
			||||||
    public userDetails: UIEventSource<UserDetails>;
 | 
					    public userDetails: UIEventSource<UserDetails>;
 | 
				
			||||||
    public isLoggedIn: UIEventSource<boolean>
 | 
					    public isLoggedIn: UIEventSource<boolean>
 | 
				
			||||||
 | 
					    private fakeUser: boolean;
 | 
				
			||||||
    _dryRun: boolean;
 | 
					    _dryRun: boolean;
 | 
				
			||||||
    public preferencesHandler: OsmPreferences;
 | 
					    public preferencesHandler: OsmPreferences;
 | 
				
			||||||
    public changesetHandler: ChangesetHandler;
 | 
					    public changesetHandler: ChangesetHandler;
 | 
				
			||||||
| 
						 | 
					@ -59,12 +60,15 @@ export class OsmConnection {
 | 
				
			||||||
        url: string
 | 
					        url: string
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(dryRun: boolean, oauth_token: UIEventSource<string>,
 | 
					    constructor(dryRun: boolean, 
 | 
				
			||||||
 | 
					                fakeUser: boolean,
 | 
				
			||||||
 | 
					                oauth_token: UIEventSource<string>,
 | 
				
			||||||
                // Used to keep multiple changesets open and to write to the correct changeset
 | 
					                // Used to keep multiple changesets open and to write to the correct changeset
 | 
				
			||||||
                layoutName: string,
 | 
					                layoutName: string,
 | 
				
			||||||
                singlePage: boolean = true,
 | 
					                singlePage: boolean = true,
 | 
				
			||||||
                osmConfiguration: "osm" | "osm-test" = 'osm'
 | 
					                osmConfiguration: "osm" | "osm-test" = 'osm'
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
 | 
					        this.fakeUser = fakeUser;
 | 
				
			||||||
        this._singlePage = singlePage;
 | 
					        this._singlePage = singlePage;
 | 
				
			||||||
        this._oauth_config = OsmConnection.oauth_configs[osmConfiguration] ?? OsmConnection.oauth_configs.osm;
 | 
					        this._oauth_config = OsmConnection.oauth_configs[osmConfiguration] ?? OsmConnection.oauth_configs.osm;
 | 
				
			||||||
        console.debug("Using backend", this._oauth_config.url)
 | 
					        console.debug("Using backend", this._oauth_config.url)
 | 
				
			||||||
| 
						 | 
					@ -72,7 +76,15 @@ export class OsmConnection {
 | 
				
			||||||
        this._iframeMode = Utils.runningFromConsole ? false : window !== window.top;
 | 
					        this._iframeMode = Utils.runningFromConsole ? false : window !== window.top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.userDetails = new UIEventSource<UserDetails>(new UserDetails(this._oauth_config.url), "userDetails");
 | 
					        this.userDetails = new UIEventSource<UserDetails>(new UserDetails(this._oauth_config.url), "userDetails");
 | 
				
			||||||
        this.userDetails.data.dryRun = dryRun;
 | 
					        this.userDetails.data.dryRun = dryRun || fakeUser;
 | 
				
			||||||
 | 
					        if(fakeUser){
 | 
				
			||||||
 | 
					            const ud = this.userDetails.data;
 | 
				
			||||||
 | 
					            ud.csCount = 5678
 | 
				
			||||||
 | 
					            ud.loggedIn= true;
 | 
				
			||||||
 | 
					            ud.unreadMessages = 0
 | 
				
			||||||
 | 
					            ud.name = "Fake user"
 | 
				
			||||||
 | 
					            ud.totalMessages = 42;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const self =this;
 | 
					        const self =this;
 | 
				
			||||||
        this.isLoggedIn = this.userDetails.map(user => user.loggedIn).addCallback(isLoggedIn => {
 | 
					        this.isLoggedIn = this.userDetails.map(user => user.loggedIn).addCallback(isLoggedIn => {
 | 
				
			||||||
            if(self.userDetails.data.loggedIn == false && isLoggedIn == true){
 | 
					            if(self.userDetails.data.loggedIn == false && isLoggedIn == true){
 | 
				
			||||||
| 
						 | 
					@ -138,6 +150,10 @@ export class OsmConnection {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public AttemptLogin() {
 | 
					    public AttemptLogin() {
 | 
				
			||||||
 | 
					        if(this.fakeUser){
 | 
				
			||||||
 | 
					            console.log("AttemptLogin called, but ignored as fakeUser is set")
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const self = this;
 | 
					        const self = this;
 | 
				
			||||||
        console.log("Trying to log in...");
 | 
					        console.log("Trying to log in...");
 | 
				
			||||||
        this.updateAuthObject();
 | 
					        this.updateAuthObject();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								State.ts
									
										
									
									
									
								
							| 
						 | 
					@ -20,6 +20,7 @@ import PendingChangesUploader from "./Logic/Actors/PendingChangesUploader";
 | 
				
			||||||
import {Relation} from "./Logic/Osm/ExtractRelations";
 | 
					import {Relation} from "./Logic/Osm/ExtractRelations";
 | 
				
			||||||
import OsmApiFeatureSource from "./Logic/FeatureSource/OsmApiFeatureSource";
 | 
					import OsmApiFeatureSource from "./Logic/FeatureSource/OsmApiFeatureSource";
 | 
				
			||||||
import ChangeToElementsActor from "./Logic/Actors/ChangeToElementsActor";
 | 
					import ChangeToElementsActor from "./Logic/Actors/ChangeToElementsActor";
 | 
				
			||||||
 | 
					import FeaturePipeline from "./Logic/FeatureSource/FeaturePipeline";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Contains the global state: a bunch of UI-event sources
 | 
					 * Contains the global state: a bunch of UI-event sources
 | 
				
			||||||
| 
						 | 
					@ -96,6 +97,11 @@ export default class State {
 | 
				
			||||||
    public readonly featureSwitchIsDebugging: UIEventSource<boolean>;
 | 
					    public readonly featureSwitchIsDebugging: UIEventSource<boolean>;
 | 
				
			||||||
    public readonly featureSwitchShowAllQuestions: UIEventSource<boolean>;
 | 
					    public readonly featureSwitchShowAllQuestions: UIEventSource<boolean>;
 | 
				
			||||||
    public readonly featureSwitchApiURL: UIEventSource<string>;
 | 
					    public readonly featureSwitchApiURL: UIEventSource<string>;
 | 
				
			||||||
 | 
					    public readonly featureSwitchEnableExport: UIEventSource<boolean>;
 | 
				
			||||||
 | 
					    public readonly featureSwitchFakeUser: UIEventSource<boolean>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public readonly featurePipeline: FeaturePipeline;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -200,11 +206,17 @@ export default class State {
 | 
				
			||||||
                "Disables/Enables the geolocation button");
 | 
					                "Disables/Enables the geolocation button");
 | 
				
			||||||
            this.featureSwitchShowAllQuestions = featSw("fs-all-questions", (layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false,
 | 
					            this.featureSwitchShowAllQuestions = featSw("fs-all-questions", (layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false,
 | 
				
			||||||
                "Always show all questions");
 | 
					                "Always show all questions");
 | 
				
			||||||
 | 
					            this.featureSwitchEnableExport = featSw("fs-export", (layoutToUse) => layoutToUse?.enableExportButton ?? false,
 | 
				
			||||||
 | 
					                "If set, enables the 'download'-button to download everything as geojson")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.featureSwitchIsTesting = QueryParameters.GetQueryParameter("test", "false",
 | 
					            this.featureSwitchIsTesting = QueryParameters.GetQueryParameter("test", "false",
 | 
				
			||||||
                "If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org")
 | 
					                "If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org")
 | 
				
			||||||
                .map(str => str === "true", [], b => "" + b);
 | 
					                .map(str => str === "true", [], b => "" + b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.featureSwitchFakeUser = QueryParameters.GetQueryParameter("fake-user", "false",
 | 
				
			||||||
 | 
					                "If true, 'dryrun' mode is activated and a fake user account is loaded")
 | 
				
			||||||
 | 
					                .map(str => str === "true", [], b => "" + b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter("debug", "false",
 | 
					            this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter("debug", "false",
 | 
				
			||||||
                "If true, shows some extra debugging help such as all the available tags on every object")
 | 
					                "If true, shows some extra debugging help such as all the available tags on every object")
 | 
				
			||||||
                .map(str => str === "true", [], b => "" + b)
 | 
					                .map(str => str === "true", [], b => "" + b)
 | 
				
			||||||
| 
						 | 
					@ -234,6 +246,7 @@ export default class State {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.osmConnection = new OsmConnection(
 | 
					        this.osmConnection = new OsmConnection(
 | 
				
			||||||
            this.featureSwitchIsTesting.data,
 | 
					            this.featureSwitchIsTesting.data,
 | 
				
			||||||
 | 
					            this.featureSwitchFakeUser.data,
 | 
				
			||||||
            QueryParameters.GetQueryParameter("oauth_token", undefined,
 | 
					            QueryParameters.GetQueryParameter("oauth_token", undefined,
 | 
				
			||||||
                "Used to complete the login"),
 | 
					                "Used to complete the login"),
 | 
				
			||||||
            layoutToUse?.id,
 | 
					            layoutToUse?.id,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								Svg.ts
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Svg.ts
									
										
									
									
									
								
							| 
						 | 
					@ -94,7 +94,7 @@ export default class Svg {
 | 
				
			||||||
    public static crosshair_empty_svg() { return new Img(Svg.crosshair_empty, true);}
 | 
					    public static crosshair_empty_svg() { return new Img(Svg.crosshair_empty, true);}
 | 
				
			||||||
    public static crosshair_empty_ui() { return new FixedUiElement(Svg.crosshair_empty_img);}
 | 
					    public static crosshair_empty_ui() { return new FixedUiElement(Svg.crosshair_empty_img);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static crosshair_locked = " <!-- Created with Inkscape (http://www.inkscape.org/) -->  <svg    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"    xmlns:cc=\"http://creativecommons.org/ns#\"    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"    xmlns:svg=\"http://www.w3.org/2000/svg\"    xmlns=\"http://www.w3.org/2000/svg\"    xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"    xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"    width=\"100\"    height=\"100\"    viewBox=\"0 0 26.458333 26.458334\"    version=\"1.1\"    id=\"svg8\"    inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\"    sodipodi:docname=\"crosshair-locked.svg\">   <defs      id=\"defs2\" />   <sodipodi:namedview      id=\"base\"      pagecolor=\"#ffffff\"      bordercolor=\"#666666\"      borderopacity=\"1.0\"      inkscape:pageopacity=\"0.0\"      inkscape:pageshadow=\"2\"      inkscape:zoom=\"2.8284271\"      inkscape:cx=\"67.47399\"      inkscape:cy=\"29.788021\"      inkscape:document-units=\"px\"      inkscape:current-layer=\"layer1\"      showgrid=\"false\"      units=\"px\"      showguides=\"true\"      inkscape:guide-bbox=\"true\"      inkscape:window-width=\"1920\"      inkscape:window-height=\"999\"      inkscape:window-x=\"0\"      inkscape:window-y=\"0\"      inkscape:window-maximized=\"1\"      inkscape:snap-global=\"false\">     <sodipodi:guide        position=\"13.229167,23.859748\"        orientation=\"1,0\"        id=\"guide815\"        inkscape:locked=\"false\" />     <sodipodi:guide        position=\"14.944824,13.229167\"        orientation=\"0,1\"        id=\"guide817\"        inkscape:locked=\"false\" />   </sodipodi:namedview>   <metadata      id=\"metadata5\">     <rdf:RDF>       <cc:Work          rdf:about=\"\">         <dc:format>image/svg+xml</dc:format>         <dc:type            rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />         <dc:title />       </cc:Work>     </rdf:RDF>   </metadata>   <g      inkscape:label=\"Layer 1\"      inkscape:groupmode=\"layer\"      id=\"layer1\"      transform=\"translate(0,-270.54165)\">     <circle        style=\"fill: none !important;fill-opacity:1;stroke:#5555ec;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529\"        id=\"path815\"        cx=\"13.16302\"        cy=\"283.77081\"        r=\"8.8715391\" />     <path        style=\"fill: none !important;stroke:#5555ec;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"M 3.2841366,283.77082 H 1.0418969\"        id=\"path817\"        inkscape:connector-curvature=\"0\" />     <path        style=\"fill: none !important;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"M 25.405696,283.77082 H 23.286471\"        id=\"path817-3\"        inkscape:connector-curvature=\"0\" />     <path        style=\"fill: none !important;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"m 13.229167,295.9489 v -2.11763\"        id=\"path817-3-6\"        inkscape:connector-curvature=\"0\" />     <path        style=\"fill: none !important;stroke:#5555ec;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\"        d=\"m 13.229167,275.05759 v -3.44507\"        id=\"path817-3-6-7\"        inkscape:connector-curvature=\"0\" />     <g        id=\"g824\"        transform=\"matrix(0.63953151,0,0,0.64343684,6.732623,276.71502)\"        style=\"fill:#ffcc33\">       <path          id=\"path822\"          d=\"M 16.07,8 H 15 V 5 C 15,5 15,0 10,0 5,0 5,5 5,5 V 8 H 3.93 A 1.93,1.93 0 0 0 2,9.93 v 8.15 A 1.93,1.93 0 0 0 3.93,20 H 16.07 A 1.93,1.93 0 0 0 18,18.07 V 9.93 A 1.93,1.93 0 0 0 16.07,8 Z M 10,16 a 2,2 0 1 1 2,-2 2,2 0 0 1 -2,2 z M 13,8 H 7 V 5.5 C 7,4 7,2 10,2 c 3,0 3,2 3,3.5 z\"          inkscape:connector-curvature=\"0\" />     </g>   </g> </svg> "
 | 
					    public static crosshair_locked = " <!-- Created with Inkscape (http://www.inkscape.org/) -->  <svg    xmlns:dc=\"http://purl.org/dc/elements/1.1/\"    xmlns:cc=\"http://creativecommons.org/ns#\"    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"    xmlns:svg=\"http://www.w3.org/2000/svg\"    xmlns=\"http://www.w3.org/2000/svg\"    xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"    xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"    width=\"100\"    height=\"100\"    viewBox=\"0 0 26.458333 26.458334\"    version=\"1.1\"    id=\"svg8\"    inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\"    sodipodi:docname=\"crosshair-locked.svg\">   <defs      id=\"defs2\" />   <sodipodi:namedview      id=\"base\"      pagecolor=\"#ffffff\"      bordercolor=\"#666666\"      borderopacity=\"1.0\"      inkscape:pageopacity=\"0.0\"      inkscape:pageshadow=\"2\"      inkscape:zoom=\"5.6568542\"      inkscape:cx=\"27.044982\"      inkscape:cy=\"77.667126\"      inkscape:document-units=\"px\"      inkscape:current-layer=\"layer1\"      showgrid=\"false\"      units=\"px\"      showguides=\"true\"      inkscape:guide-bbox=\"true\"      inkscape:window-width=\"1920\"      inkscape:window-height=\"999\"      inkscape:window-x=\"0\"      inkscape:window-y=\"0\"      inkscape:window-maximized=\"1\"      inkscape:snap-global=\"false\">     <sodipodi:guide        position=\"13.229167,23.859748\"        orientation=\"1,0\"        id=\"guide815\"        inkscape:locked=\"false\" />     <sodipodi:guide        position=\"14.944824,13.229167\"        orientation=\"0,1\"        id=\"guide817\"        inkscape:locked=\"false\" />   </sodipodi:namedview>   <metadata      id=\"metadata5\">     <rdf:RDF>       <cc:Work          rdf:about=\"\">         <dc:format>image/svg+xml</dc:format>         <dc:type            rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />         <dc:title />       </cc:Work>     </rdf:RDF>   </metadata>   <g      inkscape:label=\"Layer 1\"      inkscape:groupmode=\"layer\"      id=\"layer1\"      transform=\"translate(0,-270.54165)\">     <g        id=\"g827\">       <circle          r=\"8.8715391\"          cy=\"283.77081\"          cx=\"13.16302\"          id=\"path815\"          style=\"fill: none !important;fill-opacity:1;stroke:#5555ec;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529\" />       <path          inkscape:connector-curvature=\"0\"          id=\"path817\"          d=\"M 3.2841366,283.77082 H 1.0418969\"          style=\"fill: none !important;stroke:#5555ec;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />       <path          inkscape:connector-curvature=\"0\"          id=\"path817-3\"          d=\"M 25.405696,283.77082 H 23.286471\"          style=\"fill: none !important;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />       <path          inkscape:connector-curvature=\"0\"          id=\"path817-3-6\"          d=\"m 13.229167,295.9489 v -2.11763\"          style=\"fill: none !important;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />       <path          inkscape:connector-curvature=\"0\"          id=\"path817-3-6-7\"          d=\"m 13.229167,275.05759 v -3.44507\"          style=\"fill: none !important;stroke:#5555ec;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529\" />     </g>     <path        style=\"fill:#5555ec;fill-opacity:0.98823529;stroke-width:0.6151033\"        inkscape:connector-curvature=\"0\"        d=\"m 16.850267,281.91543 h -0.65616 v -1.85094 c 0,0 0,-3.08489 -3.066169,-3.08489 -3.066169,0 -3.066169,3.08489 -3.066169,3.08489 v 1.85094 H 9.4056091 a 1.1835412,1.1907685 0 0 0 -1.1835412,1.19077 v 5.02838 a 1.1835412,1.1907685 0 0 0 1.1835412,1.1846 h 7.4446579 a 1.1835412,1.1907685 0 0 0 1.183541,-1.19078 v -5.0222 a 1.1835412,1.1907685 0 0 0 -1.183541,-1.19077 z m -3.722329,4.93583 a 1.2264675,1.233957 0 1 1 1.226468,-1.23395 1.2264675,1.233957 0 0 1 -1.226468,1.23395 z m 1.839702,-4.93583 h -3.679403 v -1.54245 c 0,-0.92546 0,-2.15942 1.839701,-2.15942 1.839702,0 1.839702,1.23396 1.839702,2.15942 z\"        id=\"path822\" />   </g> </svg> "
 | 
				
			||||||
    public static crosshair_locked_img = Img.AsImageElement(Svg.crosshair_locked)
 | 
					    public static crosshair_locked_img = Img.AsImageElement(Svg.crosshair_locked)
 | 
				
			||||||
    public static crosshair_locked_svg() { return new Img(Svg.crosshair_locked, true);}
 | 
					    public static crosshair_locked_svg() { return new Img(Svg.crosshair_locked, true);}
 | 
				
			||||||
    public static crosshair_locked_ui() { return new FixedUiElement(Svg.crosshair_locked_img);}
 | 
					    public static crosshair_locked_ui() { return new FixedUiElement(Svg.crosshair_locked_img);}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ export default class Minimap extends BaseUIElement {
 | 
				
			||||||
            doubleClickZoom: this._allowMoving,
 | 
					            doubleClickZoom: this._allowMoving,
 | 
				
			||||||
            keyboard: this._allowMoving,
 | 
					            keyboard: this._allowMoving,
 | 
				
			||||||
            touchZoom: this._allowMoving,
 | 
					            touchZoom: this._allowMoving,
 | 
				
			||||||
            zoomAnimation: this._allowMoving,
 | 
					          // Disabling this breaks the geojson layer - don't ask me why!  zoomAnimation: this._allowMoving,
 | 
				
			||||||
            fadeAnimation: this._allowMoving
 | 
					            fadeAnimation: this._allowMoving
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										21
									
								
								UI/BigComponents/ExportDataButton.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								UI/BigComponents/ExportDataButton.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					import {SubtleButton} from "../Base/SubtleButton";
 | 
				
			||||||
 | 
					import Svg from "../../Svg";
 | 
				
			||||||
 | 
					import Translations from "../i18n/Translations";
 | 
				
			||||||
 | 
					import State from "../../State";
 | 
				
			||||||
 | 
					import {FeatureSourceUtils} from "../../Logic/FeatureSource/FeatureSource";
 | 
				
			||||||
 | 
					import {Utils} from "../../Utils";
 | 
				
			||||||
 | 
					import Combine from "../Base/Combine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class ExportDataButton extends Combine {
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        const t = Translations.t.general.download
 | 
				
			||||||
 | 
					        const button = new SubtleButton(Svg.floppy_ui(), t.downloadGeojson.Clone().SetClass("font-bold"))
 | 
				
			||||||
 | 
					            .onClick(() => {
 | 
				
			||||||
 | 
					                const geojson = FeatureSourceUtils.extractGeoJson(State.state.featurePipeline)
 | 
				
			||||||
 | 
					                const name = State.state.layoutToUse.data.id;
 | 
				
			||||||
 | 
					                Utils.offerContentsAsDownloadableFile(JSON.stringify(geojson), `MapComplete_${name}_export_${new Date().toISOString().substr(0,19)}.geojson`);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        super([button, t.licenseInfo.Clone().SetClass("link-underline")])
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,12 @@ import State from "../../State";
 | 
				
			||||||
import BackgroundSelector from "./BackgroundSelector";
 | 
					import BackgroundSelector from "./BackgroundSelector";
 | 
				
			||||||
import LayerSelection from "./LayerSelection";
 | 
					import LayerSelection from "./LayerSelection";
 | 
				
			||||||
import Combine from "../Base/Combine";
 | 
					import Combine from "../Base/Combine";
 | 
				
			||||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
					 | 
				
			||||||
import ScrollableFullScreen from "../Base/ScrollableFullScreen";
 | 
					import ScrollableFullScreen from "../Base/ScrollableFullScreen";
 | 
				
			||||||
import Translations from "../i18n/Translations";
 | 
					import Translations from "../i18n/Translations";
 | 
				
			||||||
import {UIEventSource} from "../../Logic/UIEventSource";
 | 
					import {UIEventSource} from "../../Logic/UIEventSource";
 | 
				
			||||||
import BaseUIElement from "../BaseUIElement";
 | 
					import BaseUIElement from "../BaseUIElement";
 | 
				
			||||||
 | 
					import Toggle from "../Input/Toggle";
 | 
				
			||||||
 | 
					import {ExportDataButton} from "./ExportDataButton";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LayerControlPanel extends ScrollableFullScreen {
 | 
					export default class LayerControlPanel extends ScrollableFullScreen {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,22 +20,29 @@ export default class LayerControlPanel extends ScrollableFullScreen {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static GeneratePanel(): BaseUIElement {
 | 
					    private static GeneratePanel(): BaseUIElement {
 | 
				
			||||||
        let layerControlPanel: BaseUIElement = new FixedUiElement("");
 | 
					        const elements: BaseUIElement[] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (State.state.layoutToUse.data.enableBackgroundLayerSelection) {
 | 
					        if (State.state.layoutToUse.data.enableBackgroundLayerSelection) {
 | 
				
			||||||
            layerControlPanel = new BackgroundSelector();
 | 
					            const backgroundSelector = new BackgroundSelector();
 | 
				
			||||||
            layerControlPanel.SetStyle("margin:1em");
 | 
					            backgroundSelector.SetStyle("margin:1em");
 | 
				
			||||||
            layerControlPanel.onClick(() => {
 | 
					            backgroundSelector.onClick(() => {
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					            elements.push(backgroundSelector)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (State.state.filteredLayers.data.length > 1) {
 | 
					        elements.push(new Toggle(
 | 
				
			||||||
            const layerSelection = new LayerSelection(State.state.filteredLayers);
 | 
					            new LayerSelection(State.state.filteredLayers),
 | 
				
			||||||
            layerSelection.onClick(() => {
 | 
					            undefined,
 | 
				
			||||||
            });
 | 
					            State.state.filteredLayers.map(layers => layers.length > 1)
 | 
				
			||||||
            layerControlPanel = new Combine([layerSelection, "<br/>", layerControlPanel]);
 | 
					        ))
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return layerControlPanel;
 | 
					        elements.push(new Toggle(
 | 
				
			||||||
 | 
					            new ExportDataButton(),
 | 
				
			||||||
 | 
					            undefined,
 | 
				
			||||||
 | 
					            State.state.featureSwitchEnableExport
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return new Combine(elements).SetClass("flex flex-col")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,6 @@ export default class LayerSelection extends Combine {
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        super(checkboxes)
 | 
					        super(checkboxes)
 | 
				
			||||||
        this.SetStyle("display:flex;flex-direction:column;")
 | 
					        this.SetStyle("display:flex;flex-direction:column;")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
 | 
				
			||||||
            .SetClass("break-words font-bold sm:p-0.5 md:p-1 sm:p-1.5 md:p-2");
 | 
					            .SetClass("break-words font-bold sm:p-0.5 md:p-1 sm:p-1.5 md:p-2");
 | 
				
			||||||
        const titleIcons = new Combine(
 | 
					        const titleIcons = new Combine(
 | 
				
			||||||
            layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon,
 | 
					            layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon,
 | 
				
			||||||
                "block w-8 h-8 align-baseline box-content sm:p-0.5")
 | 
					                "block w-8 h-8 align-baseline box-content sm:p-0.5", "width: 2rem;")
 | 
				
			||||||
            ))
 | 
					            ))
 | 
				
			||||||
            .SetClass("flex flex-row flex-wrap pt-0.5 sm:pt-1 items-center mr-2")
 | 
					            .SetClass("flex flex-row flex-wrap pt-0.5 sm:pt-1 items-center mr-2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ export default class TagRenderingAnswer extends VariableUiElement {
 | 
				
			||||||
            return undefined;
 | 
					            return undefined;
 | 
				
			||||||
        }).map((element: BaseUIElement) => element?.SetClass(contentClasses)?.SetStyle(contentStyle)))
 | 
					        }).map((element: BaseUIElement) => element?.SetClass(contentClasses)?.SetStyle(contentStyle)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.SetClass("flex items-center flex-row text-lg link-underline tag-renering-answer")
 | 
					        this.SetClass("flex items-center flex-row text-lg link-underline")
 | 
				
			||||||
        this.SetStyle("word-wrap: anywhere;");
 | 
					        this.SetStyle("word-wrap: anywhere;");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Utils.ts
									
										
									
									
									
								
							| 
						 | 
					@ -461,5 +461,12 @@ export class Utils {
 | 
				
			||||||
            b: parseInt(hex.substr(5, 2), 16),
 | 
					            b: parseInt(hex.substr(5, 2), 16),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static setDefaults(options, defaults){
 | 
				
			||||||
 | 
					        for (let key in defaults){
 | 
				
			||||||
 | 
					            if (!(key in options)) options[key] = defaults[key];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return options;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,9 +25,9 @@
 | 
				
			||||||
     borderopacity="1.0"
 | 
					     borderopacity="1.0"
 | 
				
			||||||
     inkscape:pageopacity="0.0"
 | 
					     inkscape:pageopacity="0.0"
 | 
				
			||||||
     inkscape:pageshadow="2"
 | 
					     inkscape:pageshadow="2"
 | 
				
			||||||
     inkscape:zoom="2.8284271"
 | 
					     inkscape:zoom="5.6568542"
 | 
				
			||||||
     inkscape:cx="67.47399"
 | 
					     inkscape:cx="27.044982"
 | 
				
			||||||
     inkscape:cy="29.788021"
 | 
					     inkscape:cy="77.667126"
 | 
				
			||||||
     inkscape:document-units="px"
 | 
					     inkscape:document-units="px"
 | 
				
			||||||
     inkscape:current-layer="layer1"
 | 
					     inkscape:current-layer="layer1"
 | 
				
			||||||
     showgrid="false"
 | 
					     showgrid="false"
 | 
				
			||||||
| 
						 | 
					@ -68,40 +68,39 @@
 | 
				
			||||||
     inkscape:groupmode="layer"
 | 
					     inkscape:groupmode="layer"
 | 
				
			||||||
     id="layer1"
 | 
					     id="layer1"
 | 
				
			||||||
     transform="translate(0,-270.54165)">
 | 
					     transform="translate(0,-270.54165)">
 | 
				
			||||||
    <circle
 | 
					 | 
				
			||||||
       style="fill:none;fill-opacity:1;stroke:#5555ec;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529"
 | 
					 | 
				
			||||||
       id="path815"
 | 
					 | 
				
			||||||
       cx="13.16302"
 | 
					 | 
				
			||||||
       cy="283.77081"
 | 
					 | 
				
			||||||
       r="8.8715391" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
       style="fill:none;stroke:#5555ec;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529"
 | 
					 | 
				
			||||||
       d="M 3.2841366,283.77082 H 1.0418969"
 | 
					 | 
				
			||||||
       id="path817"
 | 
					 | 
				
			||||||
       inkscape:connector-curvature="0" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
       style="fill:none;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529"
 | 
					 | 
				
			||||||
       d="M 25.405696,283.77082 H 23.286471"
 | 
					 | 
				
			||||||
       id="path817-3"
 | 
					 | 
				
			||||||
       inkscape:connector-curvature="0" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
       style="fill:none;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529"
 | 
					 | 
				
			||||||
       d="m 13.229167,295.9489 v -2.11763"
 | 
					 | 
				
			||||||
       id="path817-3-6"
 | 
					 | 
				
			||||||
       inkscape:connector-curvature="0" />
 | 
					 | 
				
			||||||
    <path
 | 
					 | 
				
			||||||
       style="fill:none;stroke:#5555ec;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529"
 | 
					 | 
				
			||||||
       d="m 13.229167,275.05759 v -3.44507"
 | 
					 | 
				
			||||||
       id="path817-3-6-7"
 | 
					 | 
				
			||||||
       inkscape:connector-curvature="0" />
 | 
					 | 
				
			||||||
    <g
 | 
					    <g
 | 
				
			||||||
       id="g824"
 | 
					       id="g827">
 | 
				
			||||||
       transform="matrix(0.63953151,0,0,0.64343684,6.732623,276.71502)"
 | 
					      <circle
 | 
				
			||||||
       style="fill:#ffcc33">
 | 
					         r="8.8715391"
 | 
				
			||||||
 | 
					         cy="283.77081"
 | 
				
			||||||
 | 
					         cx="13.16302"
 | 
				
			||||||
 | 
					         id="path815"
 | 
				
			||||||
 | 
					         style="fill:none;fill-opacity:1;stroke:#5555ec;stroke-width:2.64583335;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98823529" />
 | 
				
			||||||
      <path
 | 
					      <path
 | 
				
			||||||
         id="path822"
 | 
					         inkscape:connector-curvature="0"
 | 
				
			||||||
         d="M 16.07,8 H 15 V 5 C 15,5 15,0 10,0 5,0 5,5 5,5 V 8 H 3.93 A 1.93,1.93 0 0 0 2,9.93 v 8.15 A 1.93,1.93 0 0 0 3.93,20 H 16.07 A 1.93,1.93 0 0 0 18,18.07 V 9.93 A 1.93,1.93 0 0 0 16.07,8 Z M 10,16 a 2,2 0 1 1 2,-2 2,2 0 0 1 -2,2 z M 13,8 H 7 V 5.5 C 7,4 7,2 10,2 c 3,0 3,2 3,3.5 z"
 | 
					         id="path817"
 | 
				
			||||||
         inkscape:connector-curvature="0" />
 | 
					         d="M 3.2841366,283.77082 H 1.0418969"
 | 
				
			||||||
 | 
					         style="fill:none;stroke:#5555ec;stroke-width:2.09723878;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" />
 | 
				
			||||||
 | 
					      <path
 | 
				
			||||||
 | 
					         inkscape:connector-curvature="0"
 | 
				
			||||||
 | 
					         id="path817-3"
 | 
				
			||||||
 | 
					         d="M 25.405696,283.77082 H 23.286471"
 | 
				
			||||||
 | 
					         style="fill:none;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" />
 | 
				
			||||||
 | 
					      <path
 | 
				
			||||||
 | 
					         inkscape:connector-curvature="0"
 | 
				
			||||||
 | 
					         id="path817-3-6"
 | 
				
			||||||
 | 
					         d="m 13.229167,295.9489 v -2.11763"
 | 
				
			||||||
 | 
					         style="fill:none;stroke:#5555ec;stroke-width:2.11666679;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" />
 | 
				
			||||||
 | 
					      <path
 | 
				
			||||||
 | 
					         inkscape:connector-curvature="0"
 | 
				
			||||||
 | 
					         id="path817-3-6-7"
 | 
				
			||||||
 | 
					         d="m 13.229167,275.05759 v -3.44507"
 | 
				
			||||||
 | 
					         style="fill:none;stroke:#5555ec;stroke-width:2.11666668;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529" />
 | 
				
			||||||
    </g>
 | 
					    </g>
 | 
				
			||||||
 | 
					    <path
 | 
				
			||||||
 | 
					       style="fill:#5555ec;fill-opacity:0.98823529;stroke-width:0.6151033"
 | 
				
			||||||
 | 
					       inkscape:connector-curvature="0"
 | 
				
			||||||
 | 
					       d="m 16.850267,281.91543 h -0.65616 v -1.85094 c 0,0 0,-3.08489 -3.066169,-3.08489 -3.066169,0 -3.066169,3.08489 -3.066169,3.08489 v 1.85094 H 9.4056091 a 1.1835412,1.1907685 0 0 0 -1.1835412,1.19077 v 5.02838 a 1.1835412,1.1907685 0 0 0 1.1835412,1.1846 h 7.4446579 a 1.1835412,1.1907685 0 0 0 1.183541,-1.19078 v -5.0222 a 1.1835412,1.1907685 0 0 0 -1.183541,-1.19077 z m -3.722329,4.93583 a 1.2264675,1.233957 0 1 1 1.226468,-1.23395 1.2264675,1.233957 0 0 1 -1.226468,1.23395 z m 1.839702,-4.93583 h -3.679403 v -1.54245 c 0,-0.92546 0,-2.15942 1.839701,-2.15942 1.839702,0 1.839702,1.23396 1.839702,2.15942 z"
 | 
				
			||||||
 | 
					       id="path822" />
 | 
				
			||||||
  </g>
 | 
					  </g>
 | 
				
			||||||
</svg>
 | 
					</svg>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 4.3 KiB  | 
| 
						 | 
					@ -162,6 +162,18 @@
 | 
				
			||||||
    "license": "CC0; trivial",
 | 
					    "license": "CC0; trivial",
 | 
				
			||||||
    "sources": []
 | 
					    "sources": []
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "authors": [],
 | 
				
			||||||
 | 
					    "path": "crosshair-empty.svg",
 | 
				
			||||||
 | 
					    "license": "CC0; trivial",
 | 
				
			||||||
 | 
					    "sources": []
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "authors": [],
 | 
				
			||||||
 | 
					    "path": "crosshair-locked.svg",
 | 
				
			||||||
 | 
					    "license": "CC0; trivial",
 | 
				
			||||||
 | 
					    "sources": []
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    "authors": [
 | 
					    "authors": [
 | 
				
			||||||
      "Dave Gandy"
 | 
					      "Dave Gandy"
 | 
				
			||||||
| 
						 | 
					@ -582,5 +594,15 @@
 | 
				
			||||||
    "sources": [
 | 
					    "sources": [
 | 
				
			||||||
      "https://www.mapillary.com/"
 | 
					      "https://www.mapillary.com/"
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "authors": [
 | 
				
			||||||
 | 
					      "The Tango! Desktop Project"
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "path": "floppy.svg",
 | 
				
			||||||
 | 
					    "license": "CC0",
 | 
				
			||||||
 | 
					    "sources": [
 | 
				
			||||||
 | 
					      "https://commons.wikimedia.org/wiki/File:Media-floppy.svg"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
| 
						 | 
					@ -157,6 +157,10 @@
 | 
				
			||||||
      "zoomInToSeeThisLayer": "Zoom in to see this layer",
 | 
					      "zoomInToSeeThisLayer": "Zoom in to see this layer",
 | 
				
			||||||
      "title": "Select layers"
 | 
					      "title": "Select layers"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "download": {
 | 
				
			||||||
 | 
					      "downloadGeojson": "Download visible data as geojson",
 | 
				
			||||||
 | 
					      "licenseInfo": "<h3>Copyright notice</h3>The provided is available under ODbL. Reusing this data is free for any purpose, but <ul><li>the attribution <b>© OpenStreetMap contributors</b></li><li>Any change to this data must be republished under the same license</li></ul>. Please see the full <a href='https://www.openstreetmap.org/copyright' target='_blank'>copyright notice</a> for details"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "weekdays": {
 | 
					    "weekdays": {
 | 
				
			||||||
      "abbreviations": {
 | 
					      "abbreviations": {
 | 
				
			||||||
        "monday": "Mon",
 | 
					        "monday": "Mon",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ import BaseUIElement from "./UI/BaseUIElement";
 | 
				
			||||||
import Table from "./UI/Base/Table";
 | 
					import Table from "./UI/Base/Table";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const connection = new OsmConnection(false, new UIEventSource<string>(undefined), "");
 | 
					const connection = new OsmConnection(false, false, new UIEventSource<string>(undefined), "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let rendered = false;
 | 
					let rendered = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ export default class OsmConnectionSpec extends T {
 | 
				
			||||||
        super("OsmConnectionSpec-test", [
 | 
					        super("OsmConnectionSpec-test", [
 | 
				
			||||||
            ["login on dev",
 | 
					            ["login on dev",
 | 
				
			||||||
                () => {
 | 
					                () => {
 | 
				
			||||||
                   const osmConn = new OsmConnection(false,
 | 
					                   const osmConn = new OsmConnection(false,false,
 | 
				
			||||||
                        new UIEventSource<string>(undefined),
 | 
					                        new UIEventSource<string>(undefined),
 | 
				
			||||||
                        "Unit test",
 | 
					                        "Unit test",
 | 
				
			||||||
                        true,
 | 
					                        true,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue