/** * The part of the global state which initializes the feature switches, based on default values and on the layoutToUse */ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import {UIEventSource} from "../UIEventSource"; import {QueryParameters} from "../Web/QueryParameters"; import Constants from "../../Models/Constants"; import {Utils} from "../../Utils"; export default class FeatureSwitchState { /** * The layout that is being used in this run */ public readonly layoutToUse: LayoutConfig; public readonly featureSwitchUserbadge: UIEventSource; public readonly featureSwitchSearch: UIEventSource; public readonly featureSwitchBackgroundSlection: UIEventSource; public readonly featureSwitchAddNew: UIEventSource; public readonly featureSwitchWelcomeMessage: UIEventSource; public readonly featureSwitchIframePopoutEnabled: UIEventSource; public readonly featureSwitchMoreQuests: UIEventSource; public readonly featureSwitchShareScreen: UIEventSource; public readonly featureSwitchGeolocation: UIEventSource; public readonly featureSwitchIsTesting: UIEventSource; public readonly featureSwitchIsDebugging: UIEventSource; public readonly featureSwitchShowAllQuestions: UIEventSource; public readonly featureSwitchApiURL: UIEventSource; public readonly featureSwitchFilter: UIEventSource; public readonly featureSwitchEnableExport: UIEventSource; public readonly featureSwitchFakeUser: UIEventSource; public readonly featureSwitchExportAsPdf: UIEventSource; public readonly overpassUrl: UIEventSource; public readonly overpassTimeout: UIEventSource; public readonly overpassMaxZoom: UIEventSource; public readonly osmApiTileSize: UIEventSource; public readonly backgroundLayerId: UIEventSource; protected constructor(layoutToUse: LayoutConfig) { this.layoutToUse = layoutToUse; // Helper function to initialize feature switches function featSw( key: string, deflt: (layout: LayoutConfig) => boolean, documentation: string ): UIEventSource { const defaultValue = deflt(layoutToUse); const queryParam = QueryParameters.GetQueryParameter( key, "" + defaultValue, documentation ); // It takes the current layout, extracts the default value for this query parameter. A query parameter event source is then retrieved and flattened return queryParam.map((str) => str === undefined ? defaultValue : str !== "false" ) } this.featureSwitchUserbadge = featSw( "fs-userbadge", (layoutToUse) => layoutToUse?.enableUserBadge ?? true, "Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus disables editing all together, effectively putting MapComplete into read-only mode." ); this.featureSwitchSearch = featSw( "fs-search", (layoutToUse) => layoutToUse?.enableSearch ?? true, "Disables/Enables the search bar" ); this.featureSwitchBackgroundSlection = featSw( "fs-background", (layoutToUse) => layoutToUse?.enableBackgroundLayerSelection ?? true, "Disables/Enables the background layer control" ); this.featureSwitchFilter = featSw( "fs-filter", (layoutToUse) => layoutToUse?.enableLayers ?? true, "Disables/Enables the filter" ); this.featureSwitchAddNew = featSw( "fs-add-new", (layoutToUse) => layoutToUse?.enableAddNewPoints ?? true, "Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place)" ); this.featureSwitchWelcomeMessage = featSw( "fs-welcome-message", () => true, "Disables/enables the help menu or welcome message" ); this.featureSwitchIframePopoutEnabled = featSw( "fs-iframe-popout", (layoutToUse) => layoutToUse?.enableIframePopout, "Disables/Enables the iframe-popout button. If in iframe mode and the welcome message is hidden, a popout button to the full mapcomplete instance is shown instead (unless disabled with this switch)" ); this.featureSwitchMoreQuests = featSw( "fs-more-quests", (layoutToUse) => layoutToUse?.enableMoreQuests ?? true, "Disables/Enables the 'More Quests'-tab in the welcome message" ); this.featureSwitchShareScreen = featSw( "fs-share-screen", (layoutToUse) => layoutToUse?.enableShareScreen ?? true, "Disables/Enables the 'Share-screen'-tab in the welcome message" ); this.featureSwitchGeolocation = featSw( "fs-geolocation", (layoutToUse) => layoutToUse?.enableGeolocation ?? true, "Disables/Enables the geolocation button" ); this.featureSwitchShowAllQuestions = featSw( "fs-all-questions", (layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false, "Always show all questions" ); this.featureSwitchEnableExport = featSw( "fs-export", (layoutToUse) => layoutToUse?.enableExportButton ?? false, "Enable the export as GeoJSON and CSV button" ); this.featureSwitchExportAsPdf = featSw( "fs-pdf", (layoutToUse) => layoutToUse?.enablePdfDownload ?? false, "Enable the PDF download button" ); this.featureSwitchApiURL = QueryParameters.GetQueryParameter( "backend", "osm", "The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'" ); let testingDefaultValue = false; if (this.featureSwitchApiURL.data !== "osm-test" && !Utils.runningFromConsole && (location.hostname === "localhost" || location.hostname === "127.0.0.1")) { testingDefaultValue = true } this.featureSwitchIsTesting = QueryParameters.GetQueryParameter( "test", ""+testingDefaultValue, "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 ); this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter( "debug", "false", "If true, shows some extra debugging help such as all the available tags on every object" ).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.overpassUrl = QueryParameters.GetQueryParameter("overpassUrl", (layoutToUse?.overpassUrl ?? Constants.defaultOverpassUrls).join(","), "Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter" ).map(param => param.split(","), [], urls => urls.join(",")) this.overpassTimeout = UIEventSource.asFloat(QueryParameters.GetQueryParameter("overpassTimeout", "" + layoutToUse?.overpassTimeout, "Set a different timeout (in seconds) for queries in overpass")) this.overpassMaxZoom = UIEventSource.asFloat(QueryParameters.GetQueryParameter("overpassMaxZoom", "" + layoutToUse?.overpassMaxZoom, " point to switch between OSM-api and overpass")) this.osmApiTileSize = UIEventSource.asFloat(QueryParameters.GetQueryParameter("osmApiTileSize", "" + layoutToUse?.osmApiTileSize, "Tilesize when the OSM-API is used to fetch data within a BBOX")) this.featureSwitchUserbadge.addCallbackAndRun(userbadge => { if (!userbadge) { this.featureSwitchAddNew.setData(false) } }) this.backgroundLayerId = QueryParameters.GetQueryParameter( "background", layoutToUse?.defaultBackgroundId ?? "osm", "The id of the background layer to start with" ); } }