Refactoring: LayoutToUse is a simple value now

This commit is contained in:
pietervdvn 2021-09-28 18:00:44 +02:00
parent 41a2a79fe9
commit a78d33112b
22 changed files with 133 additions and 153 deletions

View file

@ -323,9 +323,7 @@ export class InitUiElements {
State.state.backgroundLayer, State.state.backgroundLayer,
State.state.locationControl, State.state.locationControl,
State.state.availableBackgroundLayers, State.state.availableBackgroundLayers,
State.state.layoutToUse.map( State.state.layoutToUse.defaultBackgroundId
(layout: LayoutConfig) => layout.defaultBackgroundId
)
); );
const attr = new Attribution( const attr = new Attribution(
@ -345,7 +343,7 @@ export class InitUiElements {
}).SetClass("w-full h-full") }).SetClass("w-full h-full")
.AttachTo("leafletDiv") .AttachTo("leafletDiv")
const layout = State.state.layoutToUse.data; const layout = State.state.layoutToUse;
if (layout.lockLocation) { if (layout.lockLocation) {
if (layout.lockLocation === true) { if (layout.lockLocation === true) {
const tile = Tiles.embedded_tile( const tile = Tiles.embedded_tile(
@ -375,66 +373,66 @@ export class InitUiElements {
const state = State.state; const state = State.state;
const empty = [] const empty = []
state.filteredLayers = state.layoutToUse.map((layoutToUse) => { const flayers: FilteredLayer[] = [];
const flayers: FilteredLayer[] = [];
for (const layer of layoutToUse.layers) { for (const layer of state.layoutToUse.layers) {
let defaultShown = "true" let defaultShown = "true"
if(layoutToUse.id === personal.id){ if(state.layoutToUse.id === personal.id){
defaultShown = "false" defaultShown = "false"
}
let isDisplayed: UIEventSource<boolean>
if(layoutToUse.id === personal.id){
isDisplayed = State.state.osmConnection.GetPreference("personal-theme-layer-" + layer.id + "-enabled")
.map(value => value === "yes", [], enabled => {
return enabled ? "yes" : "";
})
isDisplayed.addCallbackAndRun(d =>console.log("IsDisplayed for layer", layer.id, "is currently", d) )
}else{
isDisplayed = QueryParameters.GetQueryParameter(
"layer-" + layer.id,
defaultShown,
"Wether or not layer " + layer.id + " is shown"
).map<boolean>(
(str) => str !== "false",
[],
(b) => b.toString()
);
}
const flayer = {
isDisplayed: isDisplayed,
layerDef: layer,
appliedFilters: new UIEventSource<{ filter: FilterConfig, selected: number }[]>([]),
};
if (layer.filters.length > 0) {
const filtersPerName = new Map<string, FilterConfig>()
layer.filters.forEach(f => filtersPerName.set(f.id, f))
const qp = QueryParameters.GetQueryParameter("filter-" + layer.id, "","Filtering state for a layer")
flayer.appliedFilters.map(filters => {
filters = filters ?? []
return filters.map(f => f.filter.id + "." + f.selected).join(",")
}, [], textual => {
if(textual.length === 0){
return empty
}
return textual.split(",").map(part => {
const [filterId, selected] = part.split(".");
return {filter: filtersPerName.get(filterId), selected: Number(selected)}
}).filter(f => f.filter !== undefined && !isNaN(f.selected))
}).syncWith(qp, true)
}
flayers.push(flayer);
} }
return flayers;
}); let isDisplayed: UIEventSource<boolean>
if(state.layoutToUse.id === personal.id){
isDisplayed = State.state.osmConnection.GetPreference("personal-theme-layer-" + layer.id + "-enabled")
.map(value => value === "yes", [], enabled => {
return enabled ? "yes" : "";
})
isDisplayed.addCallbackAndRun(d =>console.log("IsDisplayed for layer", layer.id, "is currently", d) )
}else{
isDisplayed = QueryParameters.GetQueryParameter(
"layer-" + layer.id,
defaultShown,
"Wether or not layer " + layer.id + " is shown"
).map<boolean>(
(str) => str !== "false",
[],
(b) => b.toString()
);
}
const flayer = {
isDisplayed: isDisplayed,
layerDef: layer,
appliedFilters: new UIEventSource<{ filter: FilterConfig, selected: number }[]>([]),
};
if (layer.filters.length > 0) {
const filtersPerName = new Map<string, FilterConfig>()
layer.filters.forEach(f => filtersPerName.set(f.id, f))
const qp = QueryParameters.GetQueryParameter("filter-" + layer.id, "","Filtering state for a layer")
flayer.appliedFilters.map(filters => {
filters = filters ?? []
return filters.map(f => f.filter.id + "." + f.selected).join(",")
}, [], textual => {
if(textual.length === 0){
return empty
}
return textual.split(",").map(part => {
const [filterId, selected] = part.split(".");
return {filter: filtersPerName.get(filterId), selected: Number(selected)}
}).filter(f => f.filter !== undefined && !isNaN(f.selected))
}).syncWith(qp, true)
}
flayers.push(flayer);
}
state.filteredLayers = new UIEventSource<FilteredLayer[]>(flayers);
const clusterCounter = TileHierarchyAggregator.createHierarchy() const clusterCounter = TileHierarchyAggregator.createHierarchy()
new ShowDataLayer({ new ShowDataLayer({
features: clusterCounter.getCountsForZoom(State.state.locationControl, State.state.layoutToUse.data.clustering.minNeededElements), features: clusterCounter.getCountsForZoom(State.state.locationControl, State.state.layoutToUse.clustering.minNeededElements),
leafletMap: State.state.leafletMap, leafletMap: State.state.leafletMap,
layerToShow: ShowTileInfo.styling, layerToShow: ShowTileInfo.styling,
}) })
@ -444,7 +442,7 @@ export class InitUiElements {
clusterCounter.addTile(source) clusterCounter.addTile(source)
const clustering = State.state.layoutToUse.data.clustering const clustering = State.state.layoutToUse.clustering
const doShowFeatures = source.features.map( const doShowFeatures = source.features.map(
f => { f => {
const z = State.state.locationControl.data.zoom const z = State.state.locationControl.data.zoom

View file

@ -11,8 +11,8 @@ export default class BackgroundLayerResetter {
constructor(currentBackgroundLayer: UIEventSource<BaseLayer>, constructor(currentBackgroundLayer: UIEventSource<BaseLayer>,
location: UIEventSource<Loc>, location: UIEventSource<Loc>,
availableLayers: UIEventSource<BaseLayer[]>, availableLayers: UIEventSource<BaseLayer[]>,
defaultLayerId: UIEventSource<string> = undefined) { defaultLayerId: string = undefined) {
defaultLayerId = defaultLayerId ?? new UIEventSource<string>(AvailableBaseLayers.osmCarto.id); defaultLayerId = defaultLayerId ?? AvailableBaseLayers.osmCarto.id;
// Change the baselayer back to OSM if we go out of the current range of the layer // Change the baselayer back to OSM if we go out of the current range of the layer
availableLayers.addCallbackAndRun(availableLayers => { availableLayers.addCallbackAndRun(availableLayers => {
@ -28,7 +28,7 @@ export default class BackgroundLayerResetter {
if (availableLayer.min_zoom > location.data.zoom) { if (availableLayer.min_zoom > location.data.zoom) {
break; break;
} }
if (availableLayer.id === defaultLayerId.data) { if (availableLayer.id === defaultLayerId) {
defaultLayer = availableLayer; defaultLayer = availableLayer;
} }
return; // All good - the current layer still works! return; // All good - the current layer still works!

View file

@ -3,7 +3,7 @@ import Loc from "../../Models/Loc";
import {Or} from "../Tags/Or"; import {Or} from "../Tags/Or";
import {Overpass} from "../Osm/Overpass"; import {Overpass} from "../Osm/Overpass";
import Bounds from "../../Models/Bounds"; import Bounds from "../../Models/Bounds";
import FeatureSource, {FeatureSourceState} from "../FeatureSource/FeatureSource"; import FeatureSource from "../FeatureSource/FeatureSource";
import {Utils} from "../../Utils"; import {Utils} from "../../Utils";
import {TagsFilter} from "../Tags/TagsFilter"; import {TagsFilter} from "../Tags/TagsFilter";
import SimpleMetaTagger from "../SimpleMetaTagger"; import SimpleMetaTagger from "../SimpleMetaTagger";
@ -39,7 +39,7 @@ export default class OverpassFeatureSource implements FeatureSource {
private readonly _previousBounds: Map<number, Bounds[]> = new Map<number, Bounds[]>(); private readonly _previousBounds: Map<number, Bounds[]> = new Map<number, Bounds[]>();
private readonly state: { private readonly state: {
readonly locationControl: UIEventSource<Loc>, readonly locationControl: UIEventSource<Loc>,
readonly layoutToUse: UIEventSource<LayoutConfig>, readonly layoutToUse: LayoutConfig,
readonly overpassUrl: UIEventSource<string>; readonly overpassUrl: UIEventSource<string>;
readonly overpassTimeout: UIEventSource<number>; readonly overpassTimeout: UIEventSource<number>;
readonly currentBounds :UIEventSource<BBox> readonly currentBounds :UIEventSource<BBox>
@ -52,7 +52,7 @@ export default class OverpassFeatureSource implements FeatureSource {
constructor( constructor(
state: { state: {
readonly locationControl: UIEventSource<Loc>, readonly locationControl: UIEventSource<Loc>,
readonly layoutToUse: UIEventSource<LayoutConfig>, readonly layoutToUse: LayoutConfig,
readonly overpassUrl: UIEventSource<string>; readonly overpassUrl: UIEventSource<string>;
readonly overpassTimeout: UIEventSource<number>; readonly overpassTimeout: UIEventSource<number>;
readonly overpassMaxZoom: UIEventSource<number>, readonly overpassMaxZoom: UIEventSource<number>,
@ -76,9 +76,6 @@ export default class OverpassFeatureSource implements FeatureSource {
this._previousBounds.set(i, []); this._previousBounds.set(i, []);
} }
state.layoutToUse.addCallback(() => {
self.update()
});
location.addCallback(() => { location.addCallback(() => {
self.update() self.update()
}); });
@ -92,7 +89,7 @@ export default class OverpassFeatureSource implements FeatureSource {
private GetFilter(): Overpass { private GetFilter(): Overpass {
let filters: TagsFilter[] = []; let filters: TagsFilter[] = [];
let extraScripts: string[] = []; let extraScripts: string[] = [];
for (const layer of this.state.layoutToUse.data.layers) { for (const layer of this.state.layoutToUse.layers) {
if (typeof (layer) === "string") { if (typeof (layer) === "string") {
throw "A layer was not expanded!" throw "A layer was not expanded!"
} }
@ -164,7 +161,7 @@ export default class OverpassFeatureSource implements FeatureSource {
return undefined; return undefined;
} }
const bounds = this.state.currentBounds.data?.pad(this.state.layoutToUse.data.widenFactor)?.expandToTileBounds(14); const bounds = this.state.currentBounds.data?.pad(this.state.layoutToUse.widenFactor)?.expandToTileBounds(14);
if (bounds === undefined) { if (bounds === undefined) {
return undefined; return undefined;

View file

@ -3,12 +3,18 @@ import Translations from "../../UI/i18n/Translations";
import Locale from "../../UI/i18n/Locale"; import Locale from "../../UI/i18n/Locale";
import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer"; import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer";
import Combine from "../../UI/Base/Combine"; import Combine from "../../UI/Base/Combine";
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
import {ElementStorage} from "../ElementStorage";
export default class TitleHandler { export default class TitleHandler {
constructor(state) { constructor(state : {
selectedElement: UIEventSource<any>,
layoutToUse: LayoutConfig,
allElements: ElementStorage
}) {
const currentTitle: UIEventSource<string> = state.selectedElement.map( const currentTitle: UIEventSource<string> = state.selectedElement.map(
selected => { selected => {
const layout = state.layoutToUse.data const layout = state.layoutToUse
const defaultTitle = Translations.WT(layout?.title)?.txt ?? "MapComplete" const defaultTitle = Translations.WT(layout?.title)?.txt ?? "MapComplete"
if (selected === undefined) { if (selected === undefined) {
@ -27,7 +33,7 @@ export default class TitleHandler {
} }
} }
return defaultTitle return defaultTitle
}, [Locale.language, state.layoutToUse] }, [Locale.language]
) )

View file

@ -1,7 +1,7 @@
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
import FilteringFeatureSource from "./Sources/FilteringFeatureSource"; import FilteringFeatureSource from "./Sources/FilteringFeatureSource";
import PerLayerFeatureSourceSplitter from "./PerLayerFeatureSourceSplitter"; import PerLayerFeatureSourceSplitter from "./PerLayerFeatureSourceSplitter";
import FeatureSource, {FeatureSourceForLayer, FeatureSourceState, IndexedFeatureSource, Tiled} from "./FeatureSource"; import FeatureSource, {FeatureSourceForLayer, IndexedFeatureSource, Tiled} from "./FeatureSource";
import TiledFeatureSource from "./TiledFeatureSource/TiledFeatureSource"; import TiledFeatureSource from "./TiledFeatureSource/TiledFeatureSource";
import {UIEventSource} from "../UIEventSource"; import {UIEventSource} from "../UIEventSource";
import {TileHierarchyTools} from "./TiledFeatureSource/TileHierarchy"; import {TileHierarchyTools} from "./TiledFeatureSource/TileHierarchy";
@ -48,7 +48,7 @@ export default class FeaturePipeline {
readonly locationControl: UIEventSource<Loc>, readonly locationControl: UIEventSource<Loc>,
readonly selectedElement: UIEventSource<any>, readonly selectedElement: UIEventSource<any>,
readonly changes: Changes, readonly changes: Changes,
readonly layoutToUse: UIEventSource<LayoutConfig>, readonly layoutToUse: LayoutConfig,
readonly leafletMap: any, readonly leafletMap: any,
readonly overpassUrl: UIEventSource<string>; readonly overpassUrl: UIEventSource<string>;
readonly overpassTimeout: UIEventSource<number>; readonly overpassTimeout: UIEventSource<number>;
@ -86,7 +86,7 @@ export default class FeaturePipeline {
if (location?.zoom === undefined) { if (location?.zoom === undefined) {
return false; return false;
} }
let minzoom = Math.min(...state.layoutToUse.data.layers.map(layer => layer.minzoom ?? 18)); let minzoom = Math.min(...state.layoutToUse.layers.map(layer => layer.minzoom ?? 18));
return location.zoom >= minzoom; return location.zoom >= minzoom;
} }
); );
@ -223,8 +223,8 @@ export default class FeaturePipeline {
layer: source.layer, layer: source.layer,
minZoomLevel: 14, minZoomLevel: 14,
dontEnforceMinZoom: true, dontEnforceMinZoom: true,
maxFeatureCount: state.layoutToUse.data.clustering.minNeededElements, maxFeatureCount: state.layoutToUse.clustering.minNeededElements,
maxZoomLevel: state.layoutToUse.data.clustering.maxZoom, maxZoomLevel: state.layoutToUse.clustering.maxZoom,
registerTile: (tile) => { registerTile: (tile) => {
// We save the tile data for the given layer to local storage // We save the tile data for the given layer to local storage
new SaveTileToLocalStorageActor(tile, tile.tileIndex) new SaveTileToLocalStorageActor(tile, tile.tileIndex)

View file

@ -65,7 +65,7 @@ export default class OsmFeatureSource {
} }
private async LoadTile(z, x, y): Promise<void> { private async LoadTile(z, x, y): Promise<void> {
if (z > 18) { if (z > 20) {
throw "This is an absurd high zoom level" throw "This is an absurd high zoom level"
} }

View file

@ -62,7 +62,7 @@ export default class DeleteAction {
} }
State.state.osmConnection.changesetHandler.DeleteElement( State.state.osmConnection.changesetHandler.DeleteElement(
obj, obj,
State.state.layoutToUse.data, State.state.layoutToUse,
reason, reason,
State.state.allElements, State.state.allElements,
() => { () => {

View file

@ -131,7 +131,7 @@ export class Changes {
} }
await State.state.osmConnection.UploadChangeset( await State.state.osmConnection.UploadChangeset(
State.state.layoutToUse.data, State.state.layoutToUse,
State.state.allElements, State.state.allElements,
(csId) => Changes.createChangesetFor(csId, changes), (csId) => Changes.createChangesetFor(csId, changes),
) )

View file

@ -87,7 +87,7 @@ export default class SimpleMetaTagger {
}, },
(feature => { (feature => {
const units = Utils.NoNull([].concat(...State.state?.layoutToUse?.data?.layers?.map(layer => layer.units ?? []))); const units = Utils.NoNull([].concat(...State.state?.layoutToUse?.layers?.map(layer => layer.units ?? [])));
if (units.length == 0) { if (units.length == 0) {
return; return;
} }

View file

@ -27,7 +27,7 @@ export default class State {
// The singleton of the global state // The singleton of the global state
public static state: State; public static state: State;
public readonly layoutToUse = new UIEventSource<LayoutConfig>(undefined, "layoutToUse"); public readonly layoutToUse : LayoutConfig;
/** /**
The mapping from id -> UIEventSource<properties> The mapping from id -> UIEventSource<properties>
@ -83,7 +83,9 @@ export default class State {
public readonly featureSwitchExportAsPdf: UIEventSource<boolean>; public readonly featureSwitchExportAsPdf: UIEventSource<boolean>;
public readonly overpassUrl: UIEventSource<string>; public readonly overpassUrl: UIEventSource<string>;
public readonly overpassTimeout: UIEventSource<number>; public readonly overpassTimeout: UIEventSource<number>;
public readonly overpassMaxZoom: UIEventSource<number> = new UIEventSource<number>(20);
public readonly overpassMaxZoom: UIEventSource<number> = new UIEventSource<number>(17, "overpass-max-zoom: point to switch between OSM-api and overpass");
public featurePipeline: FeaturePipeline; public featurePipeline: FeaturePipeline;
@ -155,7 +157,7 @@ export default class State {
constructor(layoutToUse: LayoutConfig) { constructor(layoutToUse: LayoutConfig) {
const self = this; const self = this;
this.layoutToUse.setData(layoutToUse); this.layoutToUse = layoutToUse;
// -- Location control initialization // -- Location control initialization
{ {
@ -192,14 +194,7 @@ export default class State {
lat.setData(latlonz.lat); lat.setData(latlonz.lat);
lon.setData(latlonz.lon); lon.setData(latlonz.lon);
}); });
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 // Helper function to initialize feature switches
@ -208,28 +203,19 @@ export default class State {
deflt: (layout: LayoutConfig) => boolean, deflt: (layout: LayoutConfig) => boolean,
documentation: string documentation: string
): UIEventSource<boolean> { ): UIEventSource<boolean> {
const queryParameterSource = QueryParameters.GetQueryParameter(
const defaultValue = deflt(self.layoutToUse);
const queryParam = QueryParameters.GetQueryParameter(
key, key,
undefined, "" + defaultValue,
documentation 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 // 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( return queryParam.map((str) =>
self.layoutToUse.map((layout) => { str === undefined ? defaultValue : str !== "false"
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 // Feature switch initialization - not as a function as the UIEventSources are readonly
@ -412,11 +398,11 @@ export default class State {
Locale.language Locale.language
.addCallback((currentLanguage) => { .addCallback((currentLanguage) => {
const layoutToUse = self.layoutToUse.data; const layoutToUse = self.layoutToUse;
if (layoutToUse === undefined) { if (layoutToUse === undefined) {
return; return;
} }
if (this.layoutToUse.data.language.indexOf(currentLanguage) < 0) { if (this.layoutToUse.language.indexOf(currentLanguage) < 0) {
console.log( console.log(
"Resetting language to", "Resetting language to",
layoutToUse.language[0], layoutToUse.language[0],

View file

@ -16,13 +16,13 @@ export default class Attribution extends Combine {
constructor(location: UIEventSource<Loc>, constructor(location: UIEventSource<Loc>,
userDetails: UIEventSource<UserDetails>, userDetails: UIEventSource<UserDetails>,
layoutToUse: UIEventSource<LayoutConfig>, layoutToUse: LayoutConfig,
currentBounds: UIEventSource<BBox>) { currentBounds: UIEventSource<BBox>) {
const mapComplete = new Link(`Mapcomplete ${Constants.vNumber}`, 'https://github.com/pietervdvn/MapComplete', true); const mapComplete = new Link(`Mapcomplete ${Constants.vNumber}`, 'https://github.com/pietervdvn/MapComplete', true);
const reportBug = new Link(Svg.bug_ui().SetClass("small-image"), "https://github.com/pietervdvn/MapComplete/issues", true); const reportBug = new Link(Svg.bug_ui().SetClass("small-image"), "https://github.com/pietervdvn/MapComplete/issues", true);
const layoutId = layoutToUse?.data?.id; const layoutId = layoutToUse?.id;
const now = new Date() const now = new Date()
// Note: getMonth is zero-index, we want 1-index but with one substracted, so it checks out! // Note: getMonth is zero-index, we want 1-index but with one substracted, so it checks out!
const startDate = now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() const startDate = now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate()

View file

@ -20,11 +20,11 @@ export default class AttributionPanel extends Combine {
private static LicenseObject = AttributionPanel.GenerateLicenses(); private static LicenseObject = AttributionPanel.GenerateLicenses();
constructor(layoutToUse: UIEventSource<LayoutConfig>, contributions: UIEventSource<Map<string, number>>) { constructor(layoutToUse: LayoutConfig, contributions: UIEventSource<Map<string, number>>) {
super([ super([
Translations.t.general.attribution.attributionContent, Translations.t.general.attribution.attributionContent,
((layoutToUse.data.maintainer ?? "") == "") ? "" : Translations.t.general.attribution.themeBy.Subs({author: layoutToUse.data.maintainer}), ((layoutToUse.maintainer ?? "") == "") ? "" : Translations.t.general.attribution.themeBy.Subs({author: layoutToUse.maintainer}),
layoutToUse.data.credits, layoutToUse.credits,
"<br/>", "<br/>",
new Attribution(State.state.locationControl, State.state.osmConnection.userDetails, State.state.layoutToUse, State.state.currentBounds), new Attribution(State.state.locationControl, State.state.osmConnection.userDetails, State.state.layoutToUse, State.state.currentBounds),
"<br/>", "<br/>",
@ -65,7 +65,7 @@ export default class AttributionPanel extends Combine {
"<br/>", "<br/>",
AttributionPanel.CodeContributors(), AttributionPanel.CodeContributors(),
"<h3>", Translations.t.general.attribution.iconAttribution.title.Clone().SetClass("pt-6 pb-3"), "</h3>", "<h3>", Translations.t.general.attribution.iconAttribution.title.Clone().SetClass("pt-6 pb-3"), "</h3>",
...Utils.NoNull(Array.from(layoutToUse.data.ExtractImages())) ...Utils.NoNull(Array.from(layoutToUse.ExtractImages()))
.map(AttributionPanel.IconAttribution) .map(AttributionPanel.IconAttribution)
]); ]);
this.SetClass("flex flex-col link-underline overflow-hidden") this.SetClass("flex flex-col link-underline overflow-hidden")

View file

@ -26,7 +26,7 @@ export class DownloadPanel extends Toggle {
const t = Translations.t.general.download const t = Translations.t.general.download
const name = State.state.layoutToUse.data.id; const name = State.state.layoutToUse.id;
const includeMetaToggle = new CheckBoxes([t.includeMetaData.Clone()]) const includeMetaToggle = new CheckBoxes([t.includeMetaData.Clone()])
const metaisIncluded = includeMetaToggle.GetValue().map(selected => selected.length > 0) const metaisIncluded = includeMetaToggle.GetValue().map(selected => selected.length > 0)

View file

@ -19,7 +19,7 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
constructor(isShown: UIEventSource<boolean>) { constructor(isShown: UIEventSource<boolean>) {
const layoutToUse = State.state.layoutToUse.data; const layoutToUse = State.state.layoutToUse;
super( super(
() => layoutToUse.title.Clone(), () => layoutToUse.title.Clone(),
() => FullWelcomePaneWithTabs.GenerateContents(layoutToUse, State.state.osmConnection.userDetails, isShown), () => FullWelcomePaneWithTabs.GenerateContents(layoutToUse, State.state.osmConnection.userDetails, isShown),

View file

@ -126,7 +126,7 @@ export default class MoreScreen extends Combine {
if (layout.hideFromOverview) { if (layout.hideFromOverview) {
return undefined; return undefined;
} }
if (layout.id === State.state.layoutToUse.data?.id) { if (layout.id === State.state.layoutToUse?.id) {
return undefined; return undefined;
} }

View file

@ -17,7 +17,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
export default class ShareScreen extends Combine { export default class ShareScreen extends Combine {
constructor(layout: LayoutConfig = undefined, layoutDefinition: string = undefined) { constructor(layout: LayoutConfig = undefined, layoutDefinition: string = undefined) {
layout = layout ?? State.state?.layoutToUse?.data; layout = layout ?? State.state?.layoutToUse;
layoutDefinition = layoutDefinition ?? State.state?.layoutDefinition; layoutDefinition = layoutDefinition ?? State.state?.layoutDefinition;
const tr = Translations.t.general.sharescreen; const tr = Translations.t.general.sharescreen;

View file

@ -2,21 +2,17 @@ import State from "../../State";
import Combine from "../Base/Combine"; import Combine from "../Base/Combine";
import LanguagePicker from "../LanguagePicker"; import LanguagePicker from "../LanguagePicker";
import Translations from "../i18n/Translations"; import Translations from "../i18n/Translations";
import {VariableUiElement} from "../Base/VariableUIElement";
import Toggle from "../Input/Toggle"; import Toggle from "../Input/Toggle";
import {SubtleButton} from "../Base/SubtleButton"; import {SubtleButton} from "../Base/SubtleButton";
import Svg from "../../Svg"; import Svg from "../../Svg";
import {UIEventSource} from "../../Logic/UIEventSource"; import {UIEventSource} from "../../Logic/UIEventSource";
export default class ThemeIntroductionPanel extends VariableUiElement { export default class ThemeIntroductionPanel extends Combine {
constructor(isShown: UIEventSource<boolean>) { constructor(isShown: UIEventSource<boolean>) {
const layout = State.state.layoutToUse
const languagePicker = const languagePicker = LanguagePicker.CreateLanguagePicker(layout.language, Translations.t.general.pickLanguage.Clone())
new VariableUiElement(
State.state.layoutToUse.map(layout => LanguagePicker.CreateLanguagePicker(layout.language, Translations.t.general.pickLanguage.Clone()))
)
;
const toTheMap = new SubtleButton( const toTheMap = new SubtleButton(
undefined, undefined,
@ -53,8 +49,7 @@ export default class ThemeIntroductionPanel extends VariableUiElement {
State.state.featureSwitchUserbadge State.state.featureSwitchUserbadge
) )
super([
super(State.state.layoutToUse.map(layout => new Combine([
layout.description.Clone(), layout.description.Clone(),
"<br/><br/>", "<br/><br/>",
toTheMap, toTheMap,
@ -63,7 +58,7 @@ export default class ThemeIntroductionPanel extends VariableUiElement {
"<br/>", "<br/>",
languagePicker, languagePicker,
...layout.CustomCodeSnippets() ...layout.CustomCodeSnippets()
]))) ])
this.SetClass("link-underline") this.SetClass("link-underline")
} }

View file

@ -47,7 +47,7 @@ export default class UserBadge extends Toggle {
}); });
const linkStyle = "flex items-baseline" const linkStyle = "flex items-baseline"
const languagePicker = (LanguagePicker.CreateLanguagePicker(State.state.layoutToUse.data.language) ?? new FixedUiElement("")) const languagePicker = (LanguagePicker.CreateLanguagePicker(State.state.layoutToUse.language) ?? new FixedUiElement(""))
.SetStyle("width:min-content;"); .SetStyle("width:min-content;");
let messageSpan = let messageSpan =

View file

@ -55,7 +55,7 @@ export class ImageUploadFlow extends Toggle {
const tags = tagsSource.data; const tags = tagsSource.data;
const layout = State.state?.layoutToUse?.data const layout = State.state?.layoutToUse
let matchingLayer: LayerConfig = undefined let matchingLayer: LayerConfig = undefined
for (const layer of layout?.layers ?? []) { for (const layer of layout?.layers ?? []) {
if (layer.source.osmTags.matchesProperties(tags)) { if (layer.source.osmTags.matchesProperties(tags)) {

View file

@ -47,7 +47,7 @@ export class DropDown<T> extends InputElement<T> {
} }
options = options ?? {} options = options ?? {}
options.select_class = options.select_class ?? 'bg-indigo-100 p-1 rounded hover:bg-indigo-200' options.select_class = options.select_class ?? 'bg-indigo-100 p-1 rounded hover:bg-indigo-200 w-full'
{ {

View file

@ -39,7 +39,7 @@ export default class LocationInput extends InputElement<Loc> {
private readonly _maxSnapDistance: number private readonly _maxSnapDistance: number
private readonly _snappedPointTags: any; private readonly _snappedPointTags: any;
private readonly _bounds: UIEventSource<BBox>; private readonly _bounds: UIEventSource<BBox>;
public readonly _matching_layer: UIEventSource<LayerConfig>; public readonly _matching_layer: LayerConfig;
constructor(options: { constructor(options: {
mapBackground?: UIEventSource<BaseLayer>, mapBackground?: UIEventSource<BaseLayer>,
@ -63,18 +63,17 @@ export default class LocationInput extends InputElement<Loc> {
if (self._snappedPointTags !== undefined) { if (self._snappedPointTags !== undefined) {
this._matching_layer = State.state.layoutToUse.map(layout => { const layout = State.state.layoutToUse
for (const layer of layout.layers) { let matchingLayer = LocationInput.matchLayer
if (layer.source.osmTags.matchesProperties(self._snappedPointTags)) { for (const layer of layout.layers) {
return layer if (layer.source.osmTags.matchesProperties(self._snappedPointTags)) {
} matchingLayer = layer
} }
console.error("No matching layer found for tags ", self._snappedPointTags) }
return LocationInput.matchLayer this._matching_layer = matchingLayer;
})
} else { } else {
this._matching_layer = new UIEventSource<LayerConfig>(LocationInput.matchLayer) this._matching_layer = LocationInput.matchLayer
} }
this._snappedPoint = options.centerLocation.map(loc => { this._snappedPoint = options.centerLocation.map(loc => {
@ -176,7 +175,7 @@ export default class LocationInput extends InputElement<Loc> {
enablePopups: false, enablePopups: false,
zoomToFeatures: false, zoomToFeatures: false,
leafletMap: map.leafletMap, leafletMap: map.leafletMap,
layerToShow: this._matching_layer.data layerToShow: this._matching_layer
}) })
} }

View file

@ -316,10 +316,10 @@ export default class SpecialVisualizations {
const generateShareData = () => { const generateShareData = () => {
const title = state?.layoutToUse?.data?.title?.txt ?? "MapComplete"; const title = state?.layoutToUse?.title?.txt ?? "MapComplete";
let matchingLayer: LayerConfig = undefined; let matchingLayer: LayerConfig = undefined;
for (const layer of (state?.layoutToUse?.data?.layers ?? [])) { for (const layer of (state?.layoutToUse?.layers ?? [])) {
if (layer.source.osmTags.matchesProperties(tagSource?.data)) { if (layer.source.osmTags.matchesProperties(tagSource?.data)) {
matchingLayer = layer matchingLayer = layer
} }
@ -337,7 +337,7 @@ export default class SpecialVisualizations {
return { return {
title: name, title: name,
url: url, url: url,
text: state?.layoutToUse?.data?.shortDescription?.txt ?? "MapComplete" text: state?.layoutToUse?.shortDescription?.txt ?? "MapComplete"
} }
} }
@ -363,15 +363,14 @@ export default class SpecialVisualizations {
if (value === undefined) { if (value === undefined) {
return undefined return undefined
} }
const allUnits = [].concat(...state.layoutToUse.data.layers.map(lyr => lyr.units)) const allUnits = [].concat(...state.layoutToUse.layers.map(lyr => lyr.units))
const unit = allUnits.filter(unit => unit.isApplicableToKey(key))[0] const unit = allUnits.filter(unit => unit.isApplicableToKey(key))[0]
if (unit === undefined) { if (unit === undefined) {
return value; return value;
} }
return unit.asHumanLongValue(value); return unit.asHumanLongValue(value);
}, })
[state.layoutToUse])
) )
} }
}, },
@ -410,7 +409,7 @@ There are also some technicalities in your theme to keep in mind:
A reference number to the original dataset is an excellen way to do this A reference number to the original dataset is an excellen way to do this
`, `,
constr: (state, tagSource, args) => { constr: (state, tagSource, args) => {
if (!state.layoutToUse.data.official && !state.featureSwitchIsTesting.data) { if (!state.layoutToUse.official && !state.featureSwitchIsTesting.data) {
return new Combine([new FixedUiElement("The import button is disabled for unofficial themes to prevent accidents.").SetClass("alert"), return new Combine([new FixedUiElement("The import button is disabled for unofficial themes to prevent accidents.").SetClass("alert"),
new FixedUiElement("To test, add 'test=true' to the URL. The changeset will be printed in the console. Please open a PR to officialize this theme to actually enable the import button.")]) new FixedUiElement("To test, add 'test=true' to the URL. The changeset will be printed in the console. Please open a PR to officialize this theme to actually enable the import button.")])
} }