Fix personal theme, add possibility to sync layer selection
This commit is contained in:
parent
4f45fed45a
commit
419f2b1351
10 changed files with 68 additions and 36 deletions
|
@ -138,7 +138,6 @@ export class OsmPreferences {
|
||||||
const prefixes = ["mapcomplete-installed-theme", "mapcomplete-installed-themes-", "mapcomplete-current-open-changeset", "mapcomplete-personal-theme-layer"]
|
const prefixes = ["mapcomplete-installed-theme", "mapcomplete-installed-themes-", "mapcomplete-current-open-changeset", "mapcomplete-personal-theme-layer"]
|
||||||
for (const key in prefs) {
|
for (const key in prefs) {
|
||||||
for (const prefix of prefixes) {
|
for (const prefix of prefixes) {
|
||||||
// console.log(key)
|
|
||||||
if (key.startsWith(prefix)) {
|
if (key.startsWith(prefix)) {
|
||||||
console.log("Clearing ", key)
|
console.log("Clearing ", key)
|
||||||
self.GetPreference(key, "").setData("")
|
self.GetPreference(key, "").setData("")
|
||||||
|
@ -173,8 +172,9 @@ export class OsmPreferences {
|
||||||
// We merge all the preferences: new keys are uploaded
|
// We merge all the preferences: new keys are uploaded
|
||||||
// For differing values, the server overrides local changes
|
// For differing values, the server overrides local changes
|
||||||
self.preferenceSources.forEach((preference, key) => {
|
self.preferenceSources.forEach((preference, key) => {
|
||||||
const osmValue = self.preferences[key]
|
const osmValue = self.preferences.data[key]
|
||||||
if(osmValue === undefined){
|
console.log("Sending value to osm:", key," osm has: ", osmValue, " local has: ", preference.data)
|
||||||
|
if(osmValue === undefined && preference.data !== undefined){
|
||||||
// OSM doesn't know this value yet
|
// OSM doesn't know this value yet
|
||||||
self.UploadPreference(key, preference.data)
|
self.UploadPreference(key, preference.data)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -146,17 +146,17 @@ export default class FeatureSwitchState {
|
||||||
|
|
||||||
this.featureSwitchIsTesting = QueryParameters.GetBooleanQueryParameter(
|
this.featureSwitchIsTesting = QueryParameters.GetBooleanQueryParameter(
|
||||||
"test",
|
"test",
|
||||||
"" + testingDefaultValue,
|
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"
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
this.featureSwitchIsDebugging = QueryParameters.GetBooleanQueryParameter(
|
this.featureSwitchIsDebugging = QueryParameters.GetBooleanQueryParameter(
|
||||||
"debug",
|
"debug",
|
||||||
"false",
|
false,
|
||||||
"If true, shows some extra debugging help such as all the available tags on every object"
|
"If true, shows some extra debugging help such as all the available tags on every object"
|
||||||
)
|
)
|
||||||
|
|
||||||
this.featureSwitchFakeUser = QueryParameters.GetBooleanQueryParameter("fake-user", "false",
|
this.featureSwitchFakeUser = QueryParameters.GetBooleanQueryParameter("fake-user", false,
|
||||||
"If true, 'dryrun' mode is activated and a fake user account is loaded")
|
"If true, 'dryrun' mode is activated and a fake user account is loaded")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import BaseUIElement from "../../UI/BaseUIElement";
|
||||||
import FilteredLayer, {FilterState} from "../../Models/FilteredLayer";
|
import FilteredLayer, {FilterState} from "../../Models/FilteredLayer";
|
||||||
import TilesourceConfig from "../../Models/ThemeConfig/TilesourceConfig";
|
import TilesourceConfig from "../../Models/ThemeConfig/TilesourceConfig";
|
||||||
import {QueryParameters} from "../Web/QueryParameters";
|
import {QueryParameters} from "../Web/QueryParameters";
|
||||||
import * as personal from "../../assets/themes/personal/personal.json";
|
|
||||||
import ShowOverlayLayer from "../../UI/ShowDataLayer/ShowOverlayLayer";
|
import ShowOverlayLayer from "../../UI/ShowDataLayer/ShowOverlayLayer";
|
||||||
import {FeatureSourceForLayer, Tiled} from "../FeatureSource/FeatureSource";
|
import {FeatureSourceForLayer, Tiled} from "../FeatureSource/FeatureSource";
|
||||||
import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource";
|
import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource";
|
||||||
|
@ -18,7 +17,7 @@ import {LocalStorageSource} from "../Web/LocalStorageSource";
|
||||||
import {GeoOperations} from "../GeoOperations";
|
import {GeoOperations} from "../GeoOperations";
|
||||||
import TitleHandler from "../Actors/TitleHandler";
|
import TitleHandler from "../Actors/TitleHandler";
|
||||||
import {BBox} from "../BBox";
|
import {BBox} from "../BBox";
|
||||||
import MetaTagging from "../MetaTagging";
|
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all the leaflet-map related state
|
* Contains all the leaflet-map related state
|
||||||
|
@ -120,7 +119,7 @@ export default class MapState extends UserRelatedState {
|
||||||
|
|
||||||
this.overlayToggles = this.layoutToUse.tileLayerSources.filter(c => c.name !== undefined).map(c => ({
|
this.overlayToggles = this.layoutToUse.tileLayerSources.filter(c => c.name !== undefined).map(c => ({
|
||||||
config: c,
|
config: c,
|
||||||
isDisplayed: QueryParameters.GetBooleanQueryParameter("overlay-" + c.id, "" + c.defaultState, "Wether or not the overlay " + c.id + " is shown")
|
isDisplayed: QueryParameters.GetBooleanQueryParameter("overlay-" + c.id, c.defaultState, "Wether or not the overlay " + c.id + " is shown")
|
||||||
}))
|
}))
|
||||||
this.filteredLayers = this.InitializeFilteredLayers()
|
this.filteredLayers = this.InitializeFilteredLayers()
|
||||||
|
|
||||||
|
@ -345,24 +344,41 @@ export default class MapState extends UserRelatedState {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getPref(key: string, layer: LayerConfig): UIEventSource<boolean> {
|
||||||
|
const pref = this.osmConnection
|
||||||
|
.GetPreference(key)
|
||||||
|
.map(v => {
|
||||||
|
if(v === undefined){
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return v === "true";
|
||||||
|
}, [], b => {
|
||||||
|
if(b === undefined){
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return "" + b;
|
||||||
|
})
|
||||||
|
pref.setData(layer.shownByDefault)
|
||||||
|
return pref
|
||||||
|
}
|
||||||
|
|
||||||
private InitializeFilteredLayers() {
|
private InitializeFilteredLayers() {
|
||||||
|
|
||||||
const layoutToUse = this.layoutToUse;
|
const layoutToUse = this.layoutToUse;
|
||||||
const flayers: FilteredLayer[] = [];
|
const flayers: FilteredLayer[] = [];
|
||||||
for (const layer of layoutToUse.layers) {
|
for (const layer of layoutToUse.layers) {
|
||||||
let isDisplayed: UIEventSource<boolean>
|
let isDisplayed: UIEventSource<boolean>
|
||||||
if (layoutToUse.id === personal.id) {
|
if (layer.syncSelection === "local") {
|
||||||
isDisplayed = this.osmConnection.GetPreference("personal-theme-layer-" + layer.id + "-enabled")
|
isDisplayed = LocalStorageSource.GetParsed(layoutToUse.id + "-layer-" + layer.id + "-enabled", layer.shownByDefault)
|
||||||
.map(value => value === "yes", [], enabled => {
|
} else if (layer.syncSelection === "theme-only") {
|
||||||
return enabled ? "yes" : "";
|
isDisplayed = this.getPref(layoutToUse.id+ "-layer-" + layer.id + "-enabled", layer)
|
||||||
})
|
} else if (layer.syncSelection === "global") {
|
||||||
|
isDisplayed = this.getPref("layer-" + layer.id + "-enabled", layer)
|
||||||
} else {
|
} else {
|
||||||
isDisplayed = QueryParameters.GetBooleanQueryParameter(
|
isDisplayed = QueryParameters.GetBooleanQueryParameter("layer-" + layer.id + "-enabled",layer.shownByDefault, "Wether or not layer "+layer.id+" is shown")
|
||||||
"layer-" + layer.id,
|
|
||||||
"" + layer.shownByDefault,
|
|
||||||
"Wether or not layer " + layer.id + " is shown"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const flayer: FilteredLayer = {
|
const flayer: FilteredLayer = {
|
||||||
isDisplayed: isDisplayed,
|
isDisplayed: isDisplayed,
|
||||||
layerDef: layer,
|
layerDef: layer,
|
||||||
|
@ -380,14 +396,14 @@ export default class MapState extends UserRelatedState {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const layer of layoutToUse.layers) {
|
for (const layer of layoutToUse.layers) {
|
||||||
if(layer.filterIsSameAs === undefined){
|
if (layer.filterIsSameAs === undefined) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const toReuse = flayers.find(l => l.layerDef.id === layer.filterIsSameAs)
|
const toReuse = flayers.find(l => l.layerDef.id === layer.filterIsSameAs)
|
||||||
if(toReuse === undefined){
|
if (toReuse === undefined) {
|
||||||
throw "Error in layer "+layer.id+": it defines that it should be use the filters of "+layer.filterIsSameAs+", but this layer was not loaded"
|
throw "Error in layer " + layer.id + ": it defines that it should be use the filters of " + layer.filterIsSameAs + ", but this layer was not loaded"
|
||||||
}
|
}
|
||||||
console.warn("Linking filter and isDisplayed-states of "+layer.id+" and "+layer.filterIsSameAs)
|
console.warn("Linking filter and isDisplayed-states of " + layer.id + " and " + layer.filterIsSameAs)
|
||||||
const selfLayer = flayers.findIndex(l => l.layerDef.id === layer.id)
|
const selfLayer = flayers.findIndex(l => l.layerDef.id === layer.id)
|
||||||
flayers[selfLayer] = {
|
flayers[selfLayer] = {
|
||||||
isDisplayed: toReuse.isDisplayed,
|
isDisplayed: toReuse.isDisplayed,
|
||||||
|
@ -395,7 +411,7 @@ export default class MapState extends UserRelatedState {
|
||||||
appliedFilters: toReuse.appliedFilters
|
appliedFilters: toReuse.appliedFilters
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UIEventSource<FilteredLayer[]>(flayers);
|
return new UIEventSource<FilteredLayer[]>(flayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,8 +326,10 @@ export class UIEventSource<T> {
|
||||||
this.addCallback((latest) => otherSource.setData(latest));
|
this.addCallback((latest) => otherSource.setData(latest));
|
||||||
const self = this;
|
const self = this;
|
||||||
otherSource.addCallback((latest) => self.setData(latest));
|
otherSource.addCallback((latest) => self.setData(latest));
|
||||||
if (reverseOverride && otherSource.data !== undefined) {
|
if (reverseOverride) {
|
||||||
this.setData(otherSource.data);
|
if(otherSource.data !== undefined){
|
||||||
|
this.setData(otherSource.data);
|
||||||
|
}
|
||||||
} else if (this.data === undefined) {
|
} else if (this.data === undefined) {
|
||||||
this.setData(otherSource.data);
|
this.setData(otherSource.data);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -32,8 +32,8 @@ export class QueryParameters {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GetBooleanQueryParameter(key: string, deflt: string, documentation?: string): UIEventSource<boolean> {
|
public static GetBooleanQueryParameter(key: string, deflt: boolean, documentation?: string): UIEventSource<boolean> {
|
||||||
return QueryParameters.GetQueryParameter(key, deflt, documentation).map(str => str === "true", [], b => "" + b)
|
return QueryParameters.GetQueryParameter(key, ""+ deflt, documentation).map(str => str === "true", [], b => "" + b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -399,4 +399,13 @@ export interface LayerConfigJson {
|
||||||
*/
|
*/
|
||||||
units?: UnitConfigJson[]
|
units?: UnitConfigJson[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, synchronizes wether or not this layer is selected.
|
||||||
|
*
|
||||||
|
* no: Do not sync at all, always revert to default
|
||||||
|
* local: keep selection on local storage
|
||||||
|
* theme-only: sync via OSM, but this layer will only be toggled in this theme
|
||||||
|
* global: all layers with this ID will be synced accross all themes
|
||||||
|
*/
|
||||||
|
syncSelection?: "no" | "local" | "theme-only" | "global"
|
||||||
}
|
}
|
|
@ -61,6 +61,8 @@ export default class LayerConfig extends WithContextLoader {
|
||||||
public readonly filterIsSameAs: string;
|
public readonly filterIsSameAs: string;
|
||||||
public readonly forceLoad: boolean;
|
public readonly forceLoad: boolean;
|
||||||
|
|
||||||
|
public readonly syncSelection: "no" | "local" | "theme-only" | "global"
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
json: LayerConfigJson,
|
json: LayerConfigJson,
|
||||||
context?: string,
|
context?: string,
|
||||||
|
@ -90,7 +92,7 @@ export default class LayerConfig extends WithContextLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.maxAgeOfCache = json.source.maxCacheAge ?? 24 * 60 * 60 * 30
|
this.maxAgeOfCache = json.source.maxCacheAge ?? 24 * 60 * 60 * 30
|
||||||
|
this.syncSelection = json.syncSelection;
|
||||||
const osmTags = TagUtils.Tag(
|
const osmTags = TagUtils.Tag(
|
||||||
json.source.osmTags,
|
json.source.osmTags,
|
||||||
context + "source.osmTags"
|
context + "source.osmTags"
|
||||||
|
|
|
@ -22,27 +22,27 @@ export class DefaultGuiState {
|
||||||
));
|
));
|
||||||
this.welcomeMessageIsOpened = QueryParameters.GetBooleanQueryParameter(
|
this.welcomeMessageIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||||
"welcome-control-toggle",
|
"welcome-control-toggle",
|
||||||
"false",
|
false,
|
||||||
"Whether or not the welcome panel is shown"
|
"Whether or not the welcome panel is shown"
|
||||||
)
|
)
|
||||||
this.downloadControlIsOpened = QueryParameters.GetBooleanQueryParameter(
|
this.downloadControlIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||||
"download-control-toggle",
|
"download-control-toggle",
|
||||||
"false",
|
false,
|
||||||
"Whether or not the download panel is shown"
|
"Whether or not the download panel is shown"
|
||||||
)
|
)
|
||||||
this.filterViewIsOpened = QueryParameters.GetBooleanQueryParameter(
|
this.filterViewIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||||
"filter-toggle",
|
"filter-toggle",
|
||||||
"false",
|
false,
|
||||||
"Whether or not the filter view is shown"
|
"Whether or not the filter view is shown"
|
||||||
)
|
)
|
||||||
this.copyrightViewIsOpened = QueryParameters.GetBooleanQueryParameter(
|
this.copyrightViewIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||||
"copyright-toggle",
|
"copyright-toggle",
|
||||||
"false",
|
false,
|
||||||
"Whether or not the copyright view is shown"
|
"Whether or not the copyright view is shown"
|
||||||
)
|
)
|
||||||
this.currentViewControlIsOpened = QueryParameters.GetBooleanQueryParameter(
|
this.currentViewControlIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||||
"currentview-toggle",
|
"currentview-toggle",
|
||||||
"false",
|
false,
|
||||||
"Whether or not the current view box is shown"
|
"Whether or not the current view box is shown"
|
||||||
)
|
)
|
||||||
const states = {
|
const states = {
|
||||||
|
|
|
@ -34,5 +34,6 @@
|
||||||
"width": 3,
|
"width": 3,
|
||||||
"color": "#bb000077"
|
"color": "#bb000077"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"syncSelection": "global"
|
||||||
}
|
}
|
|
@ -40,7 +40,9 @@
|
||||||
"#note": "The 'overpassMaxZoom' should be exactly the same as or less then the overrideAll",
|
"#note": "The 'overpassMaxZoom' should be exactly the same as or less then the overrideAll",
|
||||||
"overpassMaxZoom": 15,
|
"overpassMaxZoom": 15,
|
||||||
"overrideAll": {
|
"overrideAll": {
|
||||||
"minZoom": 16
|
"minZoom": 16,
|
||||||
|
"syncSelection": "theme",
|
||||||
|
"shownByDefault": false
|
||||||
},
|
},
|
||||||
"layers": []
|
"layers": []
|
||||||
}
|
}
|
Loading…
Reference in a new issue