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 LayerConfig from "./Customizations/JSON/LayerConfig";
|
||||
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
|
||||
import FilterView from "./UI/BigComponents/FilterView";
|
||||
|
||||
export class InitUiElements {
|
||||
static InitAll(
|
||||
|
@ -353,6 +354,7 @@ export class InitUiElements {
|
|||
const layerControlPanel = new LayerControlPanel(
|
||||
State.state.layerControlIsOpened
|
||||
).SetClass("block p-1 rounded-full");
|
||||
|
||||
const layerControlButton = new Toggle(
|
||||
layerControlPanel,
|
||||
new MapControlButton(Svg.layers_svg()),
|
||||
|
@ -365,7 +367,31 @@ export class InitUiElements {
|
|||
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(() => {
|
||||
// Close the layer selection when the map is moved
|
||||
|
|
306
State.ts
306
State.ts
|
@ -25,11 +25,9 @@ import OsmApiFeatureSource from "./Logic/FeatureSource/OsmApiFeatureSource";
|
|||
*/
|
||||
|
||||
export default class State {
|
||||
|
||||
// The singleton of the global state
|
||||
public static state: State;
|
||||
|
||||
|
||||
public readonly layoutToUse = new UIEventSource<LayoutConfig>(undefined);
|
||||
|
||||
/**
|
||||
|
@ -61,26 +59,33 @@ export default class State {
|
|||
|
||||
public osmApiFeatureSource: OsmApiFeatureSource;
|
||||
|
||||
|
||||
public filteredLayers: UIEventSource<{
|
||||
readonly isDisplayed: UIEventSource<boolean>,
|
||||
public filteredLayers: UIEventSource<
|
||||
{
|
||||
readonly isDisplayed: UIEventSource<boolean>;
|
||||
readonly layerDef: LayerConfig;
|
||||
}[]> = new UIEventSource<{
|
||||
readonly isDisplayed: UIEventSource<boolean>,
|
||||
}[]
|
||||
> = new UIEventSource<
|
||||
{
|
||||
readonly isDisplayed: UIEventSource<boolean>;
|
||||
readonly layerDef: LayerConfig;
|
||||
}[]>([])
|
||||
|
||||
}[]
|
||||
>([]);
|
||||
|
||||
/**
|
||||
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?
|
||||
* 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 featureSwitchSearch: UIEventSource<boolean>;
|
||||
|
@ -95,7 +100,7 @@ export default class State {
|
|||
public readonly featureSwitchIsDebugging: UIEventSource<boolean>;
|
||||
public readonly featureSwitchShowAllQuestions: UIEventSource<boolean>;
|
||||
public readonly featureSwitchApiURL: UIEventSource<string>;
|
||||
|
||||
public readonly featureSwitchFilter: UIEventSource<boolean>;
|
||||
|
||||
/**
|
||||
* The map location: currently centered lat, lon and zoom
|
||||
|
@ -106,24 +111,56 @@ export default class State {
|
|||
|
||||
/* Last location where a click was registered
|
||||
*/
|
||||
public readonly LastClickLocation: UIEventSource<{ lat: number, lon: number }> = new UIEventSource<{ lat: number, lon: number }>(undefined)
|
||||
public readonly LastClickLocation: UIEventSource<{
|
||||
lat: number;
|
||||
lon: number;
|
||||
}> = new UIEventSource<{ lat: number; lon: number }>(undefined);
|
||||
|
||||
/**
|
||||
* The location as delivered by the GPS
|
||||
*/
|
||||
public currentGPSLocation: UIEventSource<{
|
||||
latlng: { lat: number, lng: number },
|
||||
accuracy: number
|
||||
}> = new UIEventSource<{ latlng: { lat: number, lng: number }, accuracy: number }>(undefined);
|
||||
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 installedThemes: UIEventSource<
|
||||
{ layout: LayoutConfig; definition: string }[]
|
||||
>;
|
||||
|
||||
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)
|
||||
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
|
||||
public FilterIsOpened: UIEventSource<boolean> =
|
||||
QueryParameters.GetQueryParameter(
|
||||
"filter-toggle",
|
||||
"false",
|
||||
"Whether or not the filter 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) {
|
||||
|
@ -134,13 +171,26 @@ export default class State {
|
|||
// -- Location control initialization
|
||||
{
|
||||
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")));
|
||||
|
||||
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.locationControl = new UIEventSource<Loc>({
|
||||
zoom: Utils.asFloat(zoom.data),
|
||||
|
@ -152,99 +202,167 @@ export default class State {
|
|||
lon.setData(latlonz.lon);
|
||||
});
|
||||
|
||||
this.layoutToUse.addCallback(layoutToUse => {
|
||||
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();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 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);
|
||||
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]);
|
||||
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.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.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'")
|
||||
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");
|
||||
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",
|
||||
this.backgroundLayerId = QueryParameters.GetQueryParameter(
|
||||
"background",
|
||||
layoutToUse?.defaultBackgroundId ?? "osm",
|
||||
"The id of the background layer to start with")
|
||||
|
||||
"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"),
|
||||
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()
|
||||
this.osmApiFeatureSource = new OsmApiFeatureSource();
|
||||
|
||||
new PendingChangesUploader(this.changes, this.selectedElement);
|
||||
|
||||
|
@ -252,47 +370,57 @@ export default class State {
|
|||
this.osmConnection.GetLongPreference("identity", "mangrove")
|
||||
);
|
||||
|
||||
|
||||
this.installedThemes = new InstalledThemes(this.osmConnection).installedThemes;
|
||||
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(";")
|
||||
(str) => Utils.Dedup(str?.split(";")) ?? [],
|
||||
[],
|
||||
(layers) => Utils.Dedup(layers)?.join(";")
|
||||
);
|
||||
|
||||
Locale.language.syncWith(this.osmConnection.GetPreference("language"));
|
||||
|
||||
|
||||
Locale.language.addCallback((currentLanguage) => {
|
||||
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")
|
||||
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()
|
||||
})
|
||||
.ping();
|
||||
|
||||
new TitleHandler(this.layoutToUse, this.selectedElement, this.allElements);
|
||||
|
||||
}
|
||||
|
||||
private static asFloat(source: UIEventSource<string>): UIEventSource<number> {
|
||||
return source.map(str => {
|
||||
return source.map(
|
||||
(str) => {
|
||||
let parsed = parseFloat(str);
|
||||
return isNaN(parsed) ? undefined : parsed;
|
||||
}, [], fl => {
|
||||
},
|
||||
[],
|
||||
(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_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_img = Img.AsImageElement(Svg.arrow_right_smooth)
|
||||
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_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_img = Img.AsImageElement(Svg.floppy)
|
||||
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_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",
|
||||
"license": "CC0",
|
||||
"sources": []
|
||||
},
|
||||
{
|
||||
"authors": ["Hannah Declerck"],
|
||||
"path": "filter.svg",
|
||||
"license": "CC0",
|
||||
"sources": []
|
||||
}
|
||||
]
|
Loading…
Reference in a new issue