Merge branch 'project/natuurpunt' of https://github.com/pietervdvn/MapComplete into project/natuurpunt
This commit is contained in:
commit
9b2e93ddb0
7 changed files with 460 additions and 245 deletions
|
@ -41,6 +41,7 @@ import FeatureSource from "./Logic/FeatureSource/FeatureSource";
|
||||||
import AllKnownLayers from "./Customizations/AllKnownLayers";
|
import AllKnownLayers from "./Customizations/AllKnownLayers";
|
||||||
import LayerConfig from "./Customizations/JSON/LayerConfig";
|
import LayerConfig from "./Customizations/JSON/LayerConfig";
|
||||||
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
|
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
|
||||||
|
import FilterView from "./UI/BigComponents/FilterView";
|
||||||
|
|
||||||
export class InitUiElements {
|
export class InitUiElements {
|
||||||
static InitAll(
|
static InitAll(
|
||||||
|
@ -353,6 +354,7 @@ export class InitUiElements {
|
||||||
const layerControlPanel = new LayerControlPanel(
|
const layerControlPanel = new LayerControlPanel(
|
||||||
State.state.layerControlIsOpened
|
State.state.layerControlIsOpened
|
||||||
).SetClass("block p-1 rounded-full");
|
).SetClass("block p-1 rounded-full");
|
||||||
|
|
||||||
const layerControlButton = new Toggle(
|
const layerControlButton = new Toggle(
|
||||||
layerControlPanel,
|
layerControlPanel,
|
||||||
new MapControlButton(Svg.layers_svg()),
|
new MapControlButton(Svg.layers_svg()),
|
||||||
|
@ -365,7 +367,31 @@ export class InitUiElements {
|
||||||
State.state.featureSwitchLayers
|
State.state.featureSwitchLayers
|
||||||
);
|
);
|
||||||
|
|
||||||
new Combine([copyrightButton, layerControl]).AttachTo("bottom-left");
|
const filterView = new FilterView(State.state.FilterIsOpened).SetClass(
|
||||||
|
"block p-1 rounded-full"
|
||||||
|
);
|
||||||
|
|
||||||
|
const filterMapControlButton = new MapControlButton(
|
||||||
|
new CenterFlexedElement(
|
||||||
|
Img.AsImageElement(Svg.filter, "", "width:1.25rem;height:1.25rem")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const filterButton = new Toggle(
|
||||||
|
filterView,
|
||||||
|
filterMapControlButton,
|
||||||
|
State.state.FilterIsOpened
|
||||||
|
).ToggleOnClick();
|
||||||
|
|
||||||
|
const filterControl = new Toggle(
|
||||||
|
filterButton,
|
||||||
|
"",
|
||||||
|
State.state.featureSwitchFilter
|
||||||
|
);
|
||||||
|
|
||||||
|
new Combine([copyrightButton, layerControl, filterControl]).AttachTo(
|
||||||
|
"bottom-left"
|
||||||
|
);
|
||||||
|
|
||||||
State.state.locationControl.addCallback(() => {
|
State.state.locationControl.addCallback(() => {
|
||||||
// Close the layer selection when the map is moved
|
// Close the layer selection when the map is moved
|
||||||
|
|
612
State.ts
612
State.ts
|
@ -1,13 +1,13 @@
|
||||||
import {Utils} from "./Utils";
|
import { Utils } from "./Utils";
|
||||||
import {ElementStorage} from "./Logic/ElementStorage";
|
import { ElementStorage } from "./Logic/ElementStorage";
|
||||||
import {Changes} from "./Logic/Osm/Changes";
|
import { Changes } from "./Logic/Osm/Changes";
|
||||||
import {OsmConnection} from "./Logic/Osm/OsmConnection";
|
import { OsmConnection } from "./Logic/Osm/OsmConnection";
|
||||||
import Locale from "./UI/i18n/Locale";
|
import Locale from "./UI/i18n/Locale";
|
||||||
import {UIEventSource} from "./Logic/UIEventSource";
|
import { UIEventSource } from "./Logic/UIEventSource";
|
||||||
import {LocalStorageSource} from "./Logic/Web/LocalStorageSource";
|
import { LocalStorageSource } from "./Logic/Web/LocalStorageSource";
|
||||||
import {QueryParameters} from "./Logic/Web/QueryParameters";
|
import { QueryParameters } from "./Logic/Web/QueryParameters";
|
||||||
import LayoutConfig from "./Customizations/JSON/LayoutConfig";
|
import LayoutConfig from "./Customizations/JSON/LayoutConfig";
|
||||||
import {MangroveIdentity} from "./Logic/Web/MangroveReviews";
|
import { MangroveIdentity } from "./Logic/Web/MangroveReviews";
|
||||||
import InstalledThemes from "./Logic/Actors/InstalledThemes";
|
import InstalledThemes from "./Logic/Actors/InstalledThemes";
|
||||||
import BaseLayer from "./Models/BaseLayer";
|
import BaseLayer from "./Models/BaseLayer";
|
||||||
import Loc from "./Models/Loc";
|
import Loc from "./Models/Loc";
|
||||||
|
@ -17,7 +17,7 @@ import OverpassFeatureSource from "./Logic/Actors/OverpassFeatureSource";
|
||||||
import LayerConfig from "./Customizations/JSON/LayerConfig";
|
import LayerConfig from "./Customizations/JSON/LayerConfig";
|
||||||
import TitleHandler from "./Logic/Actors/TitleHandler";
|
import TitleHandler from "./Logic/Actors/TitleHandler";
|
||||||
import PendingChangesUploader from "./Logic/Actors/PendingChangesUploader";
|
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";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,274 +25,402 @@ import OsmApiFeatureSource from "./Logic/FeatureSource/OsmApiFeatureSource";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class State {
|
export default class State {
|
||||||
|
// The singleton of the global state
|
||||||
|
public static state: State;
|
||||||
|
|
||||||
// The singleton of the global state
|
public readonly layoutToUse = new UIEventSource<LayoutConfig>(undefined);
|
||||||
public static state: State;
|
|
||||||
|
|
||||||
|
/**
|
||||||
public readonly layoutToUse = new UIEventSource<LayoutConfig>(undefined);
|
|
||||||
|
|
||||||
/**
|
|
||||||
The mapping from id -> UIEventSource<properties>
|
The mapping from id -> UIEventSource<properties>
|
||||||
*/
|
*/
|
||||||
public allElements: ElementStorage;
|
public allElements: ElementStorage;
|
||||||
/**
|
/**
|
||||||
THe change handler
|
THe change handler
|
||||||
*/
|
*/
|
||||||
public changes: Changes;
|
public changes: Changes;
|
||||||
/**
|
/**
|
||||||
The leaflet instance of the big basemap
|
The leaflet instance of the big basemap
|
||||||
*/
|
*/
|
||||||
public leafletMap = new UIEventSource<L.Map>(undefined);
|
public leafletMap = new UIEventSource<L.Map>(undefined);
|
||||||
/**
|
/**
|
||||||
* Background layer id
|
* Background layer id
|
||||||
*/
|
*/
|
||||||
public availableBackgroundLayers: UIEventSource<BaseLayer[]>;
|
public availableBackgroundLayers: UIEventSource<BaseLayer[]>;
|
||||||
/**
|
/**
|
||||||
The user credentials
|
The user credentials
|
||||||
*/
|
*/
|
||||||
public osmConnection: OsmConnection;
|
public osmConnection: OsmConnection;
|
||||||
|
|
||||||
public mangroveIdentity: MangroveIdentity;
|
public mangroveIdentity: MangroveIdentity;
|
||||||
|
|
||||||
public favouriteLayers: UIEventSource<string[]>;
|
public favouriteLayers: UIEventSource<string[]>;
|
||||||
|
|
||||||
public layerUpdater: OverpassFeatureSource;
|
public layerUpdater: OverpassFeatureSource;
|
||||||
|
|
||||||
public osmApiFeatureSource : OsmApiFeatureSource ;
|
public osmApiFeatureSource: OsmApiFeatureSource;
|
||||||
|
|
||||||
|
public filteredLayers: UIEventSource<
|
||||||
|
{
|
||||||
|
readonly isDisplayed: UIEventSource<boolean>;
|
||||||
|
readonly layerDef: LayerConfig;
|
||||||
|
}[]
|
||||||
|
> = new UIEventSource<
|
||||||
|
{
|
||||||
|
readonly isDisplayed: UIEventSource<boolean>;
|
||||||
|
readonly layerDef: LayerConfig;
|
||||||
|
}[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
public filteredLayers: UIEventSource<{
|
/**
|
||||||
readonly isDisplayed: UIEventSource<boolean>,
|
|
||||||
readonly layerDef: LayerConfig;
|
|
||||||
}[]> = new UIEventSource<{
|
|
||||||
readonly isDisplayed: UIEventSource<boolean>,
|
|
||||||
readonly layerDef: LayerConfig;
|
|
||||||
}[]>([])
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
The latest element that was selected
|
The latest element that was selected
|
||||||
*/
|
*/
|
||||||
public readonly selectedElement = new UIEventSource<any>(undefined, "Selected element")
|
public readonly selectedElement = new UIEventSource<any>(
|
||||||
|
undefined,
|
||||||
|
"Selected element"
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of relations: which way is part of which other way?
|
* Keeps track of relations: which way is part of which other way?
|
||||||
* Set by the overpass-updater; used in the metatagging
|
* Set by the overpass-updater; used in the metatagging
|
||||||
*/
|
*/
|
||||||
public readonly knownRelations = new UIEventSource<Map<string, {role: string, relation: Relation}[]>>(undefined, "Relation memberships")
|
public readonly knownRelations = new UIEventSource<
|
||||||
|
Map<string, { role: string; relation: Relation }[]>
|
||||||
|
>(undefined, "Relation memberships");
|
||||||
|
|
||||||
public readonly featureSwitchUserbadge: UIEventSource<boolean>;
|
public readonly featureSwitchUserbadge: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchSearch: UIEventSource<boolean>;
|
public readonly featureSwitchSearch: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchLayers: UIEventSource<boolean>;
|
public readonly featureSwitchLayers: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchAddNew: UIEventSource<boolean>;
|
public readonly featureSwitchAddNew: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchWelcomeMessage: UIEventSource<boolean>;
|
public readonly featureSwitchWelcomeMessage: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchIframe: UIEventSource<boolean>;
|
public readonly featureSwitchIframe: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchMoreQuests: UIEventSource<boolean>;
|
public readonly featureSwitchMoreQuests: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchShareScreen: UIEventSource<boolean>;
|
public readonly featureSwitchShareScreen: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchGeolocation: UIEventSource<boolean>;
|
public readonly featureSwitchGeolocation: UIEventSource<boolean>;
|
||||||
public readonly featureSwitchIsTesting: UIEventSource<boolean>;
|
public readonly featureSwitchIsTesting: UIEventSource<boolean>;
|
||||||
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 featureSwitchFilter: UIEventSource<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map location: currently centered lat, lon and zoom
|
||||||
|
*/
|
||||||
|
public readonly locationControl = new UIEventSource<Loc>(undefined);
|
||||||
|
public backgroundLayer;
|
||||||
|
public readonly backgroundLayerId: UIEventSource<string>;
|
||||||
|
|
||||||
/**
|
/* Last location where a click was registered
|
||||||
* The map location: currently centered lat, lon and zoom
|
*/
|
||||||
*/
|
public readonly LastClickLocation: UIEventSource<{
|
||||||
public readonly locationControl = new UIEventSource<Loc>(undefined);
|
lat: number;
|
||||||
public backgroundLayer;
|
lon: number;
|
||||||
public readonly backgroundLayerId: UIEventSource<string>;
|
}> = new UIEventSource<{ lat: number; lon: number }>(undefined);
|
||||||
|
|
||||||
/* Last location where a click was registered
|
/**
|
||||||
*/
|
* The location as delivered by the GPS
|
||||||
public readonly LastClickLocation: UIEventSource<{ lat: number, lon: number }> = new UIEventSource<{ lat: number, lon: number }>(undefined)
|
*/
|
||||||
|
public currentGPSLocation: UIEventSource<{
|
||||||
|
latlng: { lat: number; lng: number };
|
||||||
|
accuracy: number;
|
||||||
|
}> = new UIEventSource<{
|
||||||
|
latlng: { lat: number; lng: number };
|
||||||
|
accuracy: number;
|
||||||
|
}>(undefined);
|
||||||
|
public layoutDefinition: string;
|
||||||
|
public installedThemes: UIEventSource<
|
||||||
|
{ layout: LayoutConfig; definition: string }[]
|
||||||
|
>;
|
||||||
|
|
||||||
/**
|
public layerControlIsOpened: UIEventSource<boolean> =
|
||||||
* The location as delivered by the GPS
|
QueryParameters.GetQueryParameter(
|
||||||
*/
|
"layer-control-toggle",
|
||||||
public currentGPSLocation: UIEventSource<{
|
"false",
|
||||||
latlng: { lat: number, lng: number },
|
"Whether or not the layer control is shown"
|
||||||
accuracy: number
|
).map<boolean>(
|
||||||
}> = new UIEventSource<{ latlng: { lat: number, lng: number }, accuracy: number }>(undefined);
|
(str) => str !== "false",
|
||||||
public layoutDefinition: string;
|
[],
|
||||||
public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>;
|
(b) => "" + b
|
||||||
|
|
||||||
public layerControlIsOpened: UIEventSource<boolean> =
|
|
||||||
QueryParameters.GetQueryParameter("layer-control-toggle", "false", "Whether or not the layer control is shown")
|
|
||||||
.map<boolean>((str) => str !== "false", [], b => "" + b)
|
|
||||||
|
|
||||||
public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter("tab", "0", `The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${Constants.userJourney.mapCompleteHelpUnlock} changesets)`).map<number>(
|
|
||||||
str => isNaN(Number(str)) ? 0 : Number(str), [], n => "" + n
|
|
||||||
);
|
);
|
||||||
|
|
||||||
constructor(layoutToUse: LayoutConfig) {
|
public FilterIsOpened: UIEventSource<boolean> =
|
||||||
const self = this;
|
QueryParameters.GetQueryParameter(
|
||||||
|
"filter-toggle",
|
||||||
|
"false",
|
||||||
|
"Whether or not the filter is shown"
|
||||||
|
).map<boolean>(
|
||||||
|
(str) => str !== "false",
|
||||||
|
[],
|
||||||
|
(b) => "" + b
|
||||||
|
);
|
||||||
|
|
||||||
this.layoutToUse.setData(layoutToUse);
|
public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter(
|
||||||
|
"tab",
|
||||||
|
"0",
|
||||||
|
`The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${Constants.userJourney.mapCompleteHelpUnlock} changesets)`
|
||||||
|
).map<number>(
|
||||||
|
(str) => (isNaN(Number(str)) ? 0 : Number(str)),
|
||||||
|
[],
|
||||||
|
(n) => "" + n
|
||||||
|
);
|
||||||
|
|
||||||
// -- Location control initialization
|
constructor(layoutToUse: LayoutConfig) {
|
||||||
{
|
const self = this;
|
||||||
const zoom = State.asFloat(
|
|
||||||
QueryParameters.GetQueryParameter("z", "" + (layoutToUse?.startZoom ?? 1), "The initial/current zoom level")
|
|
||||||
.syncWith(LocalStorageSource.Get("zoom")));
|
|
||||||
const lat = State.asFloat(QueryParameters.GetQueryParameter("lat", "" + (layoutToUse?.startLat ?? 0), "The initial/current latitude")
|
|
||||||
.syncWith(LocalStorageSource.Get("lat")));
|
|
||||||
const lon = State.asFloat(QueryParameters.GetQueryParameter("lon", "" + (layoutToUse?.startLon ?? 0), "The initial/current longitude of the app")
|
|
||||||
.syncWith(LocalStorageSource.Get("lon")));
|
|
||||||
|
|
||||||
|
this.layoutToUse.setData(layoutToUse);
|
||||||
|
|
||||||
this.locationControl = new UIEventSource<Loc>({
|
// -- Location control initialization
|
||||||
zoom: Utils.asFloat(zoom.data),
|
{
|
||||||
lat: Utils.asFloat(lat.data),
|
const zoom = State.asFloat(
|
||||||
lon: Utils.asFloat(lon.data),
|
QueryParameters.GetQueryParameter(
|
||||||
}).addCallback((latlonz) => {
|
"z",
|
||||||
zoom.setData(latlonz.zoom);
|
"" + (layoutToUse?.startZoom ?? 1),
|
||||||
lat.setData(latlonz.lat);
|
"The initial/current zoom level"
|
||||||
lon.setData(latlonz.lon);
|
).syncWith(LocalStorageSource.Get("zoom"))
|
||||||
});
|
);
|
||||||
|
const lat = State.asFloat(
|
||||||
|
QueryParameters.GetQueryParameter(
|
||||||
|
"lat",
|
||||||
|
"" + (layoutToUse?.startLat ?? 0),
|
||||||
|
"The initial/current latitude"
|
||||||
|
).syncWith(LocalStorageSource.Get("lat"))
|
||||||
|
);
|
||||||
|
const lon = State.asFloat(
|
||||||
|
QueryParameters.GetQueryParameter(
|
||||||
|
"lon",
|
||||||
|
"" + (layoutToUse?.startLon ?? 0),
|
||||||
|
"The initial/current longitude of the app"
|
||||||
|
).syncWith(LocalStorageSource.Get("lon"))
|
||||||
|
);
|
||||||
|
|
||||||
this.layoutToUse.addCallback(layoutToUse => {
|
this.locationControl = new UIEventSource<Loc>({
|
||||||
const lcd = self.locationControl.data;
|
zoom: Utils.asFloat(zoom.data),
|
||||||
lcd.zoom = lcd.zoom ?? layoutToUse?.startZoom;
|
lat: Utils.asFloat(lat.data),
|
||||||
lcd.lat = lcd.lat ?? layoutToUse?.startLat;
|
lon: Utils.asFloat(lon.data),
|
||||||
lcd.lon = lcd.lon ?? layoutToUse?.startLon;
|
}).addCallback((latlonz) => {
|
||||||
self.locationControl.ping();
|
zoom.setData(latlonz.zoom);
|
||||||
});
|
lat.setData(latlonz.lat);
|
||||||
|
lon.setData(latlonz.lon);
|
||||||
}
|
});
|
||||||
|
|
||||||
// Helper function to initialize feature switches
|
|
||||||
function featSw(key: string, deflt: (layout: LayoutConfig) => boolean, documentation: string): UIEventSource<boolean> {
|
|
||||||
const queryParameterSource = QueryParameters.GetQueryParameter(key, undefined, documentation);
|
|
||||||
// I'm so sorry about someone trying to decipher this
|
|
||||||
|
|
||||||
// It takes the current layout, extracts the default value for this query parameter. A query parameter event source is then retrieved and flattened
|
|
||||||
return UIEventSource.flatten(
|
|
||||||
self.layoutToUse.map((layout) => {
|
|
||||||
const defaultValue = deflt(layout);
|
|
||||||
const queryParam = QueryParameters.GetQueryParameter(key, "" + defaultValue, documentation)
|
|
||||||
return queryParam.map((str) => str === undefined ? defaultValue : (str !== "false"));
|
|
||||||
}), [queryParameterSource]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feature switch initialization - not as a function as the UIEventSources are readonly
|
|
||||||
{
|
|
||||||
|
|
||||||
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.featureSwitchLayers = featSw("fs-layers", (layoutToUse) => layoutToUse?.enableLayers ?? true,
|
|
||||||
"Disables/Enables the layer control");
|
|
||||||
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.featureSwitchIframe = featSw("fs-iframe", () => false,
|
|
||||||
"Disables/Enables the iframe-popup");
|
|
||||||
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.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")
|
|
||||||
.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.featureSwitchApiURL = QueryParameters.GetQueryParameter("backend","osm",
|
|
||||||
"The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'")
|
|
||||||
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Some other feature switches
|
|
||||||
const customCssQP = QueryParameters.GetQueryParameter("custom-css", "", "If specified, the custom css from the given link will be loaded additionaly");
|
|
||||||
if (customCssQP.data !== undefined && customCssQP.data !== "") {
|
|
||||||
Utils.LoadCustomCss(customCssQP.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.backgroundLayerId = QueryParameters.GetQueryParameter("background",
|
|
||||||
layoutToUse?.defaultBackgroundId ?? "osm",
|
|
||||||
"The id of the background layer to start with")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(Utils.runningFromConsole){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.osmConnection = new OsmConnection(
|
|
||||||
this.featureSwitchIsTesting.data,
|
|
||||||
QueryParameters.GetQueryParameter("oauth_token", undefined,
|
|
||||||
"Used to complete the login"),
|
|
||||||
layoutToUse?.id,
|
|
||||||
true,
|
|
||||||
// @ts-ignore
|
|
||||||
this.featureSwitchApiURL.data
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
this.allElements = new ElementStorage();
|
|
||||||
this.changes = new Changes();
|
|
||||||
this.osmApiFeatureSource = new OsmApiFeatureSource()
|
|
||||||
|
|
||||||
new PendingChangesUploader(this.changes, this.selectedElement);
|
|
||||||
|
|
||||||
this.mangroveIdentity = new MangroveIdentity(
|
|
||||||
this.osmConnection.GetLongPreference("identity", "mangrove")
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
this.installedThemes = new InstalledThemes(this.osmConnection).installedThemes;
|
|
||||||
|
|
||||||
// Important: the favourite layers are initialized _after_ the installed themes, as these might contain an installedTheme
|
|
||||||
this.favouriteLayers = LocalStorageSource.Get("favouriteLayers")
|
|
||||||
.syncWith(this.osmConnection.GetLongPreference("favouriteLayers"))
|
|
||||||
.map(
|
|
||||||
str => Utils.Dedup(str?.split(";")) ?? [],
|
|
||||||
[], layers => Utils.Dedup(layers)?.join(";")
|
|
||||||
);
|
|
||||||
|
|
||||||
Locale.language.syncWith(this.osmConnection.GetPreference("language"));
|
|
||||||
|
|
||||||
|
|
||||||
Locale.language.addCallback((currentLanguage) => {
|
|
||||||
const layoutToUse = self.layoutToUse.data;
|
|
||||||
if (layoutToUse === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.layoutToUse.data.language.indexOf(currentLanguage) < 0) {
|
|
||||||
console.log("Resetting language to", layoutToUse.language[0], "as", currentLanguage, " is unsupported")
|
|
||||||
// The current language is not supported -> switch to a supported one
|
|
||||||
Locale.language.setData(layoutToUse.language[0]);
|
|
||||||
}
|
|
||||||
}).ping()
|
|
||||||
|
|
||||||
new TitleHandler(this.layoutToUse, this.selectedElement, this.allElements);
|
|
||||||
|
|
||||||
|
this.layoutToUse.addCallback((layoutToUse) => {
|
||||||
|
const lcd = self.locationControl.data;
|
||||||
|
lcd.zoom = lcd.zoom ?? layoutToUse?.startZoom;
|
||||||
|
lcd.lat = lcd.lat ?? layoutToUse?.startLat;
|
||||||
|
lcd.lon = lcd.lon ?? layoutToUse?.startLon;
|
||||||
|
self.locationControl.ping();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static asFloat(source: UIEventSource<string>): UIEventSource<number> {
|
// Helper function to initialize feature switches
|
||||||
return source.map(str => {
|
function featSw(
|
||||||
let parsed = parseFloat(str);
|
key: string,
|
||||||
return isNaN(parsed) ? undefined : parsed;
|
deflt: (layout: LayoutConfig) => boolean,
|
||||||
}, [], fl => {
|
documentation: string
|
||||||
if (fl === undefined || isNaN(fl)) {
|
): UIEventSource<boolean> {
|
||||||
return undefined;
|
const queryParameterSource = QueryParameters.GetQueryParameter(
|
||||||
}
|
key,
|
||||||
return ("" + fl).substr(0, 8);
|
undefined,
|
||||||
})
|
documentation
|
||||||
|
);
|
||||||
|
// I'm so sorry about someone trying to decipher this
|
||||||
|
|
||||||
|
// It takes the current layout, extracts the default value for this query parameter. A query parameter event source is then retrieved and flattened
|
||||||
|
return UIEventSource.flatten(
|
||||||
|
self.layoutToUse.map((layout) => {
|
||||||
|
const defaultValue = deflt(layout);
|
||||||
|
const queryParam = QueryParameters.GetQueryParameter(
|
||||||
|
key,
|
||||||
|
"" + defaultValue,
|
||||||
|
documentation
|
||||||
|
);
|
||||||
|
return queryParam.map((str) =>
|
||||||
|
str === undefined ? defaultValue : str !== "false"
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
[queryParameterSource]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Feature switch initialization - not as a function as the UIEventSources are readonly
|
||||||
|
{
|
||||||
|
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.featureSwitchLayers = featSw(
|
||||||
|
"fs-layers",
|
||||||
|
(layoutToUse) => layoutToUse?.enableLayers ?? true,
|
||||||
|
"Disables/Enables the 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.featureSwitchIframe = featSw(
|
||||||
|
"fs-iframe",
|
||||||
|
() => false,
|
||||||
|
"Disables/Enables the iframe-popup"
|
||||||
|
);
|
||||||
|
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.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"
|
||||||
|
).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.featureSwitchApiURL = QueryParameters.GetQueryParameter(
|
||||||
|
"backend",
|
||||||
|
"osm",
|
||||||
|
"The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Some other feature switches
|
||||||
|
const customCssQP = QueryParameters.GetQueryParameter(
|
||||||
|
"custom-css",
|
||||||
|
"",
|
||||||
|
"If specified, the custom css from the given link will be loaded additionaly"
|
||||||
|
);
|
||||||
|
if (customCssQP.data !== undefined && customCssQP.data !== "") {
|
||||||
|
Utils.LoadCustomCss(customCssQP.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.backgroundLayerId = QueryParameters.GetQueryParameter(
|
||||||
|
"background",
|
||||||
|
layoutToUse?.defaultBackgroundId ?? "osm",
|
||||||
|
"The id of the background layer to start with"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Utils.runningFromConsole) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.osmConnection = new OsmConnection(
|
||||||
|
this.featureSwitchIsTesting.data,
|
||||||
|
QueryParameters.GetQueryParameter(
|
||||||
|
"oauth_token",
|
||||||
|
undefined,
|
||||||
|
"Used to complete the login"
|
||||||
|
),
|
||||||
|
layoutToUse?.id,
|
||||||
|
true,
|
||||||
|
// @ts-ignore
|
||||||
|
this.featureSwitchApiURL.data
|
||||||
|
);
|
||||||
|
|
||||||
|
this.allElements = new ElementStorage();
|
||||||
|
this.changes = new Changes();
|
||||||
|
this.osmApiFeatureSource = new OsmApiFeatureSource();
|
||||||
|
|
||||||
|
new PendingChangesUploader(this.changes, this.selectedElement);
|
||||||
|
|
||||||
|
this.mangroveIdentity = new MangroveIdentity(
|
||||||
|
this.osmConnection.GetLongPreference("identity", "mangrove")
|
||||||
|
);
|
||||||
|
|
||||||
|
this.installedThemes = new InstalledThemes(
|
||||||
|
this.osmConnection
|
||||||
|
).installedThemes;
|
||||||
|
|
||||||
|
// Important: the favourite layers are initialized _after_ the installed themes, as these might contain an installedTheme
|
||||||
|
this.favouriteLayers = LocalStorageSource.Get("favouriteLayers")
|
||||||
|
.syncWith(this.osmConnection.GetLongPreference("favouriteLayers"))
|
||||||
|
.map(
|
||||||
|
(str) => Utils.Dedup(str?.split(";")) ?? [],
|
||||||
|
[],
|
||||||
|
(layers) => Utils.Dedup(layers)?.join(";")
|
||||||
|
);
|
||||||
|
|
||||||
|
Locale.language.syncWith(this.osmConnection.GetPreference("language"));
|
||||||
|
|
||||||
|
Locale.language
|
||||||
|
.addCallback((currentLanguage) => {
|
||||||
|
const layoutToUse = self.layoutToUse.data;
|
||||||
|
if (layoutToUse === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.layoutToUse.data.language.indexOf(currentLanguage) < 0) {
|
||||||
|
console.log(
|
||||||
|
"Resetting language to",
|
||||||
|
layoutToUse.language[0],
|
||||||
|
"as",
|
||||||
|
currentLanguage,
|
||||||
|
" is unsupported"
|
||||||
|
);
|
||||||
|
// The current language is not supported -> switch to a supported one
|
||||||
|
Locale.language.setData(layoutToUse.language[0]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ping();
|
||||||
|
|
||||||
|
new TitleHandler(this.layoutToUse, this.selectedElement, this.allElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static asFloat(source: UIEventSource<string>): UIEventSource<number> {
|
||||||
|
return source.map(
|
||||||
|
(str) => {
|
||||||
|
let parsed = parseFloat(str);
|
||||||
|
return isNaN(parsed) ? undefined : parsed;
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
(fl) => {
|
||||||
|
if (fl === undefined || isNaN(fl)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return ("" + fl).substr(0, 8);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
12
Svg.ts
12
Svg.ts
|
@ -29,6 +29,11 @@ export default class Svg {
|
||||||
public static arrow_left_smooth_svg() { return new Img(Svg.arrow_left_smooth, true);}
|
public static arrow_left_smooth_svg() { return new Img(Svg.arrow_left_smooth, true);}
|
||||||
public static arrow_left_smooth_ui() { return new FixedUiElement(Svg.arrow_left_smooth_img);}
|
public static arrow_left_smooth_ui() { return new FixedUiElement(Svg.arrow_left_smooth_img);}
|
||||||
|
|
||||||
|
public static arrow_left_thin = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M16 7H3.83L9.42 1.41L8 0L0 8L8 16L9.41 14.59L3.83 9H16V7Z\" fill=\"#007759\"/> </svg> "
|
||||||
|
public static arrow_left_thin_img = Img.AsImageElement(Svg.arrow_left_thin)
|
||||||
|
public static arrow_left_thin_svg() { return new Img(Svg.arrow_left_thin, true);}
|
||||||
|
public static arrow_left_thin_ui() { return new FixedUiElement(Svg.arrow_left_thin_img);}
|
||||||
|
|
||||||
public static arrow_right_smooth = " <!-- 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\" sodipodi:docname=\"arrow-right-smooth.svg\" inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"> <defs id=\"defs2\" /> <sodipodi:namedview id=\"base\" pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1.0\" inkscape:pageopacity=\"0.0\" inkscape:pageshadow=\"2\" inkscape:zoom=\"4\" inkscape:cx=\"-22.237738\" inkscape:cy=\"36.323203\" 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=\"1001\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\"> <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)\"> <path style=\"fill: none !important;stroke:#ffffff;stroke-width:3.59588718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"m 6.3128214,273.41335 c 0,0 13.7995296,7.53922 13.8484366,10.36091 0.04891,2.82169 -13.8484366,10.38607 -13.8484366,10.38607\" id=\"path821\" inkscape:connector-curvature=\"0\" /> </g> </svg> "
|
public static arrow_right_smooth = " <!-- 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\" sodipodi:docname=\"arrow-right-smooth.svg\" inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"> <defs id=\"defs2\" /> <sodipodi:namedview id=\"base\" pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1.0\" inkscape:pageopacity=\"0.0\" inkscape:pageshadow=\"2\" inkscape:zoom=\"4\" inkscape:cx=\"-22.237738\" inkscape:cy=\"36.323203\" 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=\"1001\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\"> <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)\"> <path style=\"fill: none !important;stroke:#ffffff;stroke-width:3.59588718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"m 6.3128214,273.41335 c 0,0 13.7995296,7.53922 13.8484366,10.36091 0.04891,2.82169 -13.8484366,10.38607 -13.8484366,10.38607\" id=\"path821\" inkscape:connector-curvature=\"0\" /> </g> </svg> "
|
||||||
public static arrow_right_smooth_img = Img.AsImageElement(Svg.arrow_right_smooth)
|
public static arrow_right_smooth_img = Img.AsImageElement(Svg.arrow_right_smooth)
|
||||||
public static arrow_right_smooth_svg() { return new Img(Svg.arrow_right_smooth, true);}
|
public static arrow_right_smooth_svg() { return new Img(Svg.arrow_right_smooth, true);}
|
||||||
|
@ -134,6 +139,11 @@ export default class Svg {
|
||||||
public static envelope_svg() { return new Img(Svg.envelope, true);}
|
public static envelope_svg() { return new Img(Svg.envelope, true);}
|
||||||
public static envelope_ui() { return new FixedUiElement(Svg.envelope_img);}
|
public static envelope_ui() { return new FixedUiElement(Svg.envelope_img);}
|
||||||
|
|
||||||
|
public static filter = "<svg width=\"14\" height=\"16\" viewBox=\"0 0 14 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M8.71478 7.99533V15.0032C8.73645 15.138 8.7246 15.2762 8.68028 15.4051C8.63597 15.534 8.56056 15.6497 8.46103 15.7414C8.29711 15.907 8.07541 16 7.84428 16C7.61315 16 7.39145 15.907 7.22753 15.7414L5.47778 13.9627C5.38296 13.8675 5.31072 13.7513 5.26675 13.6234C5.22277 13.4954 5.2082 13.3591 5.22403 13.2245V8.00402L0.18473 1.44083C0.0426575 1.25543 -0.0214882 1.02037 0.0063802 0.78707C0.0342486 0.553773 0.151904 0.341292 0.333498 0.195845C0.487423 0.0703057 0.678576 0.00116361 0.875917 0H13.1242C13.3215 0.00116361 13.5127 0.0703057 13.6666 0.195845C13.8482 0.341292 13.9658 0.553773 13.9936 0.78707C14.0215 1.02037 13.9573 1.25543 13.8153 1.44083L8.77597 8.00402L8.71478 7.99533Z\" fill=\"white\"/> </svg> "
|
||||||
|
public static filter_img = Img.AsImageElement(Svg.filter)
|
||||||
|
public static filter_svg() { return new Img(Svg.filter, true);}
|
||||||
|
public static filter_ui() { return new FixedUiElement(Svg.filter_img);}
|
||||||
|
|
||||||
public static floppy = " <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"48\" height=\"48\"> <defs> <linearGradient id=\"d\"> <stop offset=\"0\"/> <stop offset=\"1\" stop-opacity=\"0\"/> </linearGradient> <linearGradient id=\"c\"> <stop offset=\"0\" stop-color=\"#858585\"/> <stop offset=\".5\" stop-color=\"#cbcbcb\"/> <stop offset=\"1\" stop-color=\"#6b6b6b\"/> </linearGradient> <linearGradient id=\"b\"> <stop offset=\"0\" stop-color=\"#fff\"/> <stop offset=\"1\" stop-color=\"#fff\" stop-opacity=\"0\"/> </linearGradient> <linearGradient id=\"a\"> <stop offset=\"0\" stop-color=\"#1e2d69\"/> <stop offset=\"1\" stop-color=\"#78a7e0\"/> </linearGradient> <linearGradient id=\"f\" x1=\"40.885\" x2=\"16.88\" y1=\"71.869\" y2=\"-.389\" gradientTransform=\"matrix(.97661 0 0 1.13979 .564 -3.271)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#a\"/> <linearGradient id=\"g\" x1=\"13.784\" x2=\"33.075\" y1=\"-.997\" y2=\"55.702\" gradientTransform=\"matrix(.98543 0 0 1.14818 .641 -2.934)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#b\"/> <linearGradient id=\"h\" x1=\"20.125\" x2=\"28.563\" y1=\"21.844\" y2=\"42.469\" gradientTransform=\"matrix(1.0677 0 0 1.12153 -1.369 -5.574)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#c\"/> <radialGradient id=\"e\" cx=\"24.313\" cy=\"41.156\" r=\"22.875\" fx=\"24.313\" fy=\"41.156\" gradientTransform=\"matrix(1 0 0 .26913 0 30.08)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#d\"/> </defs> <path fill=\"url(#e)\" d=\"M47.188 41.156a22.875 6.156 0 1 1-45.75 0 22.875 6.156 0 1 1 45.75 0z\" opacity=\".506\" transform=\"matrix(.91803 0 0 .98122 1.68 .648)\"/> <path fill=\"url(#f)\" stroke=\"#25375f\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.558 3.568h38.89c.59 0 1.064.474 1.064 1.063v37.765c0 .59-.475 1.064-1.064 1.064H6.558l-3.064-3.064V4.631a1.06 1.06 0 0 1 1.064-1.063z\"/> <path fill=\"#fff\" d=\"M9 4h30v23H9z\"/> <rect width=\"30\" height=\"4\" x=\"9\" y=\"4\" fill=\"#d31c00\" rx=\".126\" ry=\".126\"/> <rect width=\"2\" height=\"2\" x=\"6\" y=\"6\" opacity=\".739\" rx=\".126\" ry=\".126\"/> <path stroke=\"#000\" d=\"M11 12.5h26m-26 5h26m-26 5h26\" opacity=\".131\"/> <path fill=\"none\" stroke=\"url(#g)\" stroke-linecap=\"round\" d=\"M4.619 4.528h38.768c.07 0 .127.056.127.126v37.648c0 .07-.057.126-.127.126H6.928l-2.435-2.391V4.654c0-.07.056-.126.126-.126z\" opacity=\".597\"/> <path fill=\"url(#h)\" stroke=\"#525252\" d=\"M14.114 28.562h19.75c.888 0 1.603.751 1.603 1.684v13.201H12.51V30.246c0-.933.715-1.684 1.603-1.684z\"/> <rect width=\"5.03\" height=\"10.066\" x=\"16.464\" y=\"30.457\" fill=\"#4967a2\" stroke=\"#525252\" rx=\".751\" ry=\".751\"/> </svg>"
|
public static floppy = " <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"48\" height=\"48\"> <defs> <linearGradient id=\"d\"> <stop offset=\"0\"/> <stop offset=\"1\" stop-opacity=\"0\"/> </linearGradient> <linearGradient id=\"c\"> <stop offset=\"0\" stop-color=\"#858585\"/> <stop offset=\".5\" stop-color=\"#cbcbcb\"/> <stop offset=\"1\" stop-color=\"#6b6b6b\"/> </linearGradient> <linearGradient id=\"b\"> <stop offset=\"0\" stop-color=\"#fff\"/> <stop offset=\"1\" stop-color=\"#fff\" stop-opacity=\"0\"/> </linearGradient> <linearGradient id=\"a\"> <stop offset=\"0\" stop-color=\"#1e2d69\"/> <stop offset=\"1\" stop-color=\"#78a7e0\"/> </linearGradient> <linearGradient id=\"f\" x1=\"40.885\" x2=\"16.88\" y1=\"71.869\" y2=\"-.389\" gradientTransform=\"matrix(.97661 0 0 1.13979 .564 -3.271)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#a\"/> <linearGradient id=\"g\" x1=\"13.784\" x2=\"33.075\" y1=\"-.997\" y2=\"55.702\" gradientTransform=\"matrix(.98543 0 0 1.14818 .641 -2.934)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#b\"/> <linearGradient id=\"h\" x1=\"20.125\" x2=\"28.563\" y1=\"21.844\" y2=\"42.469\" gradientTransform=\"matrix(1.0677 0 0 1.12153 -1.369 -5.574)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#c\"/> <radialGradient id=\"e\" cx=\"24.313\" cy=\"41.156\" r=\"22.875\" fx=\"24.313\" fy=\"41.156\" gradientTransform=\"matrix(1 0 0 .26913 0 30.08)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#d\"/> </defs> <path fill=\"url(#e)\" d=\"M47.188 41.156a22.875 6.156 0 1 1-45.75 0 22.875 6.156 0 1 1 45.75 0z\" opacity=\".506\" transform=\"matrix(.91803 0 0 .98122 1.68 .648)\"/> <path fill=\"url(#f)\" stroke=\"#25375f\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.558 3.568h38.89c.59 0 1.064.474 1.064 1.063v37.765c0 .59-.475 1.064-1.064 1.064H6.558l-3.064-3.064V4.631a1.06 1.06 0 0 1 1.064-1.063z\"/> <path fill=\"#fff\" d=\"M9 4h30v23H9z\"/> <rect width=\"30\" height=\"4\" x=\"9\" y=\"4\" fill=\"#d31c00\" rx=\".126\" ry=\".126\"/> <rect width=\"2\" height=\"2\" x=\"6\" y=\"6\" opacity=\".739\" rx=\".126\" ry=\".126\"/> <path stroke=\"#000\" d=\"M11 12.5h26m-26 5h26m-26 5h26\" opacity=\".131\"/> <path fill=\"none\" stroke=\"url(#g)\" stroke-linecap=\"round\" d=\"M4.619 4.528h38.768c.07 0 .127.056.127.126v37.648c0 .07-.057.126-.127.126H6.928l-2.435-2.391V4.654c0-.07.056-.126.126-.126z\" opacity=\".597\"/> <path fill=\"url(#h)\" stroke=\"#525252\" d=\"M14.114 28.562h19.75c.888 0 1.603.751 1.603 1.684v13.201H12.51V30.246c0-.933.715-1.684 1.603-1.684z\"/> <rect width=\"5.03\" height=\"10.066\" x=\"16.464\" y=\"30.457\" fill=\"#4967a2\" stroke=\"#525252\" rx=\".751\" ry=\".751\"/> </svg>"
|
||||||
public static floppy_img = Img.AsImageElement(Svg.floppy)
|
public static floppy_img = Img.AsImageElement(Svg.floppy)
|
||||||
public static floppy_svg() { return new Img(Svg.floppy, true);}
|
public static floppy_svg() { return new Img(Svg.floppy, true);}
|
||||||
|
@ -349,4 +359,4 @@ export default class Svg {
|
||||||
public static wikipedia_svg() { return new Img(Svg.wikipedia, true);}
|
public static wikipedia_svg() { return new Img(Svg.wikipedia, true);}
|
||||||
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
|
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
|
||||||
|
|
||||||
public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"location.svg": Svg.location,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min-zoom.svg": Svg.min_zoom,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus-zoom.svg": Svg.plus_zoom,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
|
public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-left-thin.svg": Svg.arrow_left_thin,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"filter.svg": Svg.filter,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"location.svg": Svg.location,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min-zoom.svg": Svg.min_zoom,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus-zoom.svg": Svg.plus_zoom,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
|
||||||
|
|
39
UI/BigComponents/FilterView.ts
Normal file
39
UI/BigComponents/FilterView.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import { FixedUiElement } from "./../Base/FixedUiElement";
|
||||||
|
import { LayerConfigJson } from "./../../Customizations/JSON/LayerConfigJson";
|
||||||
|
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||||
|
import { VariableUiElement } from "../Base/VariableUIElement";
|
||||||
|
import State from "../../State";
|
||||||
|
import Toggle from "../Input/Toggle";
|
||||||
|
import Combine from "../Base/Combine";
|
||||||
|
import Translations from "../i18n/Translations";
|
||||||
|
import LayerConfig from "../../Customizations/JSON/LayerConfig";
|
||||||
|
import BaseUIElement from "../BaseUIElement";
|
||||||
|
import { Translation } from "../i18n/Translation";
|
||||||
|
import ScrollableFullScreen from "../Base/ScrollableFullScreen";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the filter
|
||||||
|
*/
|
||||||
|
export default class FilterView extends ScrollableFullScreen {
|
||||||
|
constructor(isShown: UIEventSource<boolean>) {
|
||||||
|
super(FilterView.GenTitle, FilterView.Generatecontent, "filter", isShown);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GenTitle(): BaseUIElement {
|
||||||
|
return new FixedUiElement(`Filter`).SetClass(
|
||||||
|
"text-2xl break-words font-bold p-2"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Generatecontent(): BaseUIElement {
|
||||||
|
let filterPanel: BaseUIElement = new FixedUiElement("more stuff");
|
||||||
|
|
||||||
|
if (State.state.filteredLayers.data.length > 1) {
|
||||||
|
let layers = State.state.filteredLayers;
|
||||||
|
console.log(layers);
|
||||||
|
filterPanel = new Combine(["layerssss", "<br/>", filterPanel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterPanel;
|
||||||
|
}
|
||||||
|
}
|
3
assets/svg/arrow-left-thin.svg
Normal file
3
assets/svg/arrow-left-thin.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M16 7H3.83L9.42 1.41L8 0L0 8L8 16L9.41 14.59L3.83 9H16V7Z" fill="#007759"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 188 B |
3
assets/svg/filter.svg
Normal file
3
assets/svg/filter.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.71478 7.99533V15.0032C8.73645 15.138 8.7246 15.2762 8.68028 15.4051C8.63597 15.534 8.56056 15.6497 8.46103 15.7414C8.29711 15.907 8.07541 16 7.84428 16C7.61315 16 7.39145 15.907 7.22753 15.7414L5.47778 13.9627C5.38296 13.8675 5.31072 13.7513 5.26675 13.6234C5.22277 13.4954 5.2082 13.3591 5.22403 13.2245V8.00402L0.18473 1.44083C0.0426575 1.25543 -0.0214882 1.02037 0.0063802 0.78707C0.0342486 0.553773 0.151904 0.341292 0.333498 0.195845C0.487423 0.0703057 0.678576 0.00116361 0.875917 0H13.1242C13.3215 0.00116361 13.5127 0.0703057 13.6666 0.195845C13.8482 0.341292 13.9658 0.553773 13.9936 0.78707C14.0215 1.02037 13.9573 1.25543 13.8153 1.44083L8.77597 8.00402L8.71478 7.99533Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 813 B |
|
@ -606,5 +606,11 @@
|
||||||
"path": "plus-zoom.svg",
|
"path": "plus-zoom.svg",
|
||||||
"license": "CC0",
|
"license": "CC0",
|
||||||
"sources": []
|
"sources": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"authors": ["Hannah Declerck"],
|
||||||
|
"path": "filter.svg",
|
||||||
|
"license": "CC0",
|
||||||
|
"sources": []
|
||||||
}
|
}
|
||||||
]
|
]
|
Loading…
Reference in a new issue