From bdc9ba52a6b49d5c56c7db9dffa6591a3c2c8c15 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 17 Oct 2024 04:06:03 +0200 Subject: [PATCH] Refactoring: use `theme` instead of `layout` in a lot of places --- Docs/Making_Your_Own_Theme.md | 6 +- assets/themes/bag/bag.json | 26 ++++----- scripts/ScriptUtils.ts | 4 +- scripts/generateDocs.ts | 6 +- scripts/generateLayerOverview.ts | 24 ++++---- scripts/generateLayouts.ts | 28 +++++----- scripts/generateTaginfoProjectFiles.ts | 6 +- scripts/handleErrors.ts | 6 +- src/Customizations/AllKnownLayouts.ts | 14 ++--- src/Logic/Actors/InitialMapPositioning.ts | 4 +- src/Logic/Actors/NoElementsInViewDetector.ts | 6 +- .../Actors/SelectedElementTagsUpdater.ts | 4 +- src/Logic/Actors/TitleHandler.ts | 4 +- .../{DetermineLayout.ts => DetermineTheme.ts} | 42 +++++++------- .../Sources/FavouritesFeatureSource.ts | 2 +- .../Sources/LastClickFeatureSource.ts | 4 +- .../{LayoutSource.ts => ThemeSource.ts} | 14 ++--- .../ImageProviders/ImageUploadManager.ts | 10 ++-- src/Logic/MetaTagging.ts | 20 +++---- .../CreateMultiPolygonWithPointReuseAction.ts | 8 +-- .../Actions/CreateWayWithPointReuseAction.ts | 8 +-- .../Osm/Actions/ReplaceGeometryAction.ts | 2 +- src/Logic/Search/FilterSearch.ts | 8 +-- src/Logic/Search/LayerSearch.ts | 15 +++-- src/Logic/Search/ThemeSearch.ts | 24 ++++---- src/Logic/SimpleMetaTagger.ts | 6 +- src/Logic/State/FeatureSwitchState.ts | 43 +++++++------- src/Logic/State/SearchState.ts | 6 +- src/Logic/State/UserRelatedState.ts | 12 ++-- src/Logic/Web/LocalStorageSource.ts | 15 +++-- src/Models/Constants.ts | 2 +- .../ThemeConfig/Conversion/FixImages.ts | 10 ++-- .../Conversion/LegacyJsonConvert.ts | 8 +-- .../ThemeConfig/Conversion/PrepareTheme.ts | 36 ++++++------ .../ThemeConfig/Conversion/ValidateTheme.ts | 10 ++-- .../Conversion/ValidateThemeAndLayers.ts | 4 +- .../ThemeConfig/Conversion/Validation.ts | 46 +++++++-------- src/Models/ThemeConfig/FilterConfig.ts | 2 +- ...LayoutConfigJson.ts => ThemeConfigJson.ts} | 2 +- .../{LayoutConfig.ts => ThemeConfig.ts} | 16 +++--- src/Models/ThemeViewState.ts | 56 +++++++++---------- src/UI/AllThemesGui.svelte | 18 +++--- src/UI/BigComponents/CopyrightAllIcons.svelte | 2 +- src/UI/BigComponents/CopyrightPanel.svelte | 4 +- src/UI/BigComponents/ExtraLinkButton.svelte | 6 +- src/UI/BigComponents/FilterPage.svelte | 6 +- src/UI/BigComponents/MenuDrawer.svelte | 20 +++---- src/UI/BigComponents/ShareScreen.svelte | 10 ++-- src/UI/BigComponents/Summary.svelte | 2 +- src/UI/BigComponents/ThemeButton.svelte | 4 +- src/UI/BigComponents/ThemeIntroPanel.svelte | 8 +-- src/UI/BigComponents/ThemesList.svelte | 4 +- .../BigComponents/UploadTraceToOsmUI.svelte | 4 +- src/UI/Comparison/ComparisonAction.svelte | 2 +- src/UI/Comparison/ComparisonTable.svelte | 2 +- src/UI/DownloadFlow/DownloadButton.svelte | 2 +- src/UI/DownloadFlow/DownloadHelper.ts | 4 +- src/UI/DownloadFlow/DownloadPdf.svelte | 8 +-- src/UI/Image/DeleteImage.ts | 8 +-- src/UI/Image/ImageCarousel.ts | 4 +- src/UI/Image/LinkableImage.svelte | 4 +- src/UI/Image/NearbyImages.svelte | 2 +- .../MapRoulette/MaprouletteSetStatus.svelte | 2 +- src/UI/Popup/AddNewPoint/AddNewPoint.svelte | 2 +- src/UI/Popup/AddNewPoint/PresetList.svelte | 4 +- src/UI/Popup/AutoApplyButton.ts | 6 +- src/UI/Popup/DeleteFlow/DeleteWizard.svelte | 4 +- .../ImportButtons/ConflateImportButtonViz.ts | 5 +- .../ImportButtons/ConflateImportFlowState.ts | 6 +- src/UI/Popup/ImportButtons/ImportFlow.ts | 4 +- .../ImportButtons/PointImportFlow.svelte | 2 +- .../ImportButtons/PointImportFlowState.ts | 2 +- .../Popup/ImportButtons/WayImportButtonViz.ts | 4 +- .../Popup/ImportButtons/WayImportFlow.svelte | 2 +- .../Popup/ImportButtons/WayImportFlowState.ts | 4 +- .../LanguageElement/LanguageQuestion.svelte | 2 +- src/UI/Popup/MarkAsFavourite.svelte | 2 +- src/UI/Popup/MarkAsFavouriteMini.svelte | 2 +- src/UI/Popup/MinimapViz.svelte | 2 +- src/UI/Popup/MoveWizardState.ts | 6 +- src/UI/Popup/MultiApply.ts | 2 +- src/UI/Popup/Notes/CreateNewNote.svelte | 2 +- src/UI/Popup/PlantNetDetectionViz.ts | 2 +- src/UI/Popup/QrCode.svelte | 2 +- src/UI/Popup/ShareLinkViz.ts | 6 +- src/UI/Popup/SplitRoadWizard.svelte | 2 +- src/UI/Popup/TagApplyButton.ts | 2 +- .../TagRendering/TagRenderingQuestion.svelte | 4 +- src/UI/QueryParameterDocumentation.ts | 4 +- src/UI/Search/GeocodeResult.svelte | 2 +- src/UI/Search/ThemeResult.svelte | 4 +- src/UI/Search/ThemeResults.svelte | 2 +- src/UI/SpecialVisualization.ts | 8 +-- src/UI/SpecialVisualizations.ts | 12 ++-- src/UI/StatisticsGUI.ts | 4 +- src/UI/Studio/EditLayerState.ts | 20 ++++--- src/UI/Studio/StudioServer.ts | 6 +- src/UI/ThemeViewGUI.svelte | 12 ++-- src/Utils/pngMapCreator.ts | 2 +- src/all_themes_index.ts | 8 +-- src/index.ts | 12 ++-- test/Logic/Actors/Actors.spec.ts | 4 +- .../Conversion/FixLegacyTheme.spec.ts | 4 +- .../Conversion/PrepareTheme.spec.ts | 14 ++--- 104 files changed, 445 insertions(+), 449 deletions(-) rename src/Logic/{DetermineLayout.ts => DetermineTheme.ts} (88%) rename src/Logic/FeatureSource/Sources/{LayoutSource.ts => ThemeSource.ts} (93%) rename src/Models/ThemeConfig/Json/{LayoutConfigJson.ts => ThemeConfigJson.ts} (99%) rename src/Models/ThemeConfig/{LayoutConfig.ts => ThemeConfig.ts} (96%) diff --git a/Docs/Making_Your_Own_Theme.md b/Docs/Making_Your_Own_Theme.md index a16889da0..3db8fe6bf 100644 --- a/Docs/Making_Your_Own_Theme.md +++ b/Docs/Making_Your_Own_Theme.md @@ -33,7 +33,7 @@ You can create your own theme at https://mapcomplete.org/studio What is a good theme? --------------------- -A **theme** (or _layout_) is a single map showing one or more layers. +A **theme** is a single map showing one or more layers. The layers should work together in such a way that they serve a certain **audience**. You should be able to state in a few sentences whom would be the user of such a map, e.g. @@ -294,12 +294,12 @@ There are three important levels in the JSON file: Every field is documented in the source code itself - you can find them here: -- [The top level `LayoutConfig`](/src/Models/ThemeConfig/Json/LayoutConfigJson.ts) +- [The top level `ThemeConfig`](/src/Models/ThemeConfig/Json/ThemeConfigJson.ts) - [A layer object `LayerConfig`](/src/Models/ThemeConfig/Json/LayerConfigJson.ts) - [The `TagRendering`](/src/Models/ThemeConfig/Json/TagRenderingConfigJson.ts) - At last, the exact semantics of tags are documented [here](Tags_format.md) -A JSON schema file is available in `Docs/Schemas` - use `LayoutConfig.schema.json` to validate a theme file. +A JSON schema file is available in `Docs/Schemas` - use `ThemeConfig.schema.json` to validate a theme file. ### MetaTags diff --git a/assets/themes/bag/bag.json b/assets/themes/bag/bag.json index 0af44dc15..03dfae4fe 100644 --- a/assets/themes/bag/bag.json +++ b/assets/themes/bag/bag.json @@ -61,7 +61,7 @@ "minzoom": 18, "isCounted": false, "calculatedTags": [ - "_surface:strict:=feat(get)('_surface')" + "_surface:strict:=get(feat)('_surface')" ], "tagRenderings": [ { @@ -224,19 +224,19 @@ "minzoom": 18, "calculatedTags": [ "_overlaps_with_buildings=overlapWith(feat)('osm_buildings').filter(f => f.feat.properties.id.indexOf('-') < 0)", - "_overlaps_with=feat(get)('_overlaps_with_buildings').find(f => f.overlap > 1 /* square meter */ )", - "_overlaps_with_properties=feat(get)('_overlaps_with')?.feat?.properties", - "_overlap_percentage=Math.round(100 * (feat(get)('_overlaps_with')?.overlap / feat(get)('_overlaps_with_properties')['_surface:strict']))", - "_reverse_overlap_percentage=Math.round(100 * (feat(get)('_overlaps_with')?.overlap / feat(get)('_surface')))", + "_overlaps_with=get(feat)('_overlaps_with_buildings').find(f => f.overlap > 1 /* square meter */ )", + "_overlaps_with_properties=get(feat)('_overlaps_with')?.feat?.properties", + "_overlap_percentage=Math.round(100 * (get(feat)('_overlaps_with')?.overlap / get(feat)('_overlaps_with_properties')['_surface:strict']))", + "_reverse_overlap_percentage=Math.round(100 * (get(feat)('_overlaps_with')?.overlap / get(feat)('_surface')))", "_bag_obj:in_construction=feat.properties.status.startsWith('Bouwvergunning verleend') || feat.properties.status.startsWith('Bouw gestart')", "_bag_obj:construction=(feat.properties.gebruiksdoel == 'woonfunctie') ? ((Number(feat.properties.aantal_verblijfsobjecten) == 1) ? 'house' : 'apartments') : 'yes'", "_bag_obj:building=(feat.properties.status.startsWith('Bouwvergunning verleend') || feat.properties.status.startsWith('Bouw gestart')) ? 'construction' : feat.properties['_bag_obj:construction']", "_bag_obj:ref:bag=Number(feat.properties.identificatie)", "_bag_obj:source:date=new Date().toISOString().split('T')[0]", "_bag_obj:start_date=feat.properties.bouwjaar", - "_osm_obj:id=feat(get)('_overlaps_with_properties')?.id", - "_osm_obj:building=feat(get)('_overlaps_with_properties')?.building", - "_imported_osm_object_found:=Number(feat.properties.identificatie)==Number(feat(get)('_overlaps_with_properties')['ref:bag'])" + "_osm_obj:id=get(feat)('_overlaps_with_properties')?.id", + "_osm_obj:building=get(feat)('_overlaps_with_properties')?.building", + "_imported_osm_object_found:=Number(feat.properties.identificatie)==Number(get(feat)('_overlaps_with_properties')['ref:bag'])" ], "tagRenderings": [ { @@ -435,11 +435,11 @@ "_bag_obj:addr:housenumber=`${feat.properties.huisnummer}${feat.properties.huisletter}${(feat.properties.toevoeging != '') ? '-' : ''}${feat.properties.toevoeging}`", "_bag_obj:ref:bag=Number(feat.properties.identificatie)", "_bag_obj:source:date=new Date().toISOString().split('T')[0]", - "_osm_obj:addr:city:=feat(get)('_closed_osm_addr')['addr:city']", - "_osm_obj:addr:housenumber:=feat(get)('_closed_osm_addr')['addr:housenumber']", - "_osm_obj:addr:postcode:=feat(get)('_closed_osm_addr')['addr:postcode']", - "_osm_obj:addr:street:=feat(get)('_closed_osm_addr')['addr:street']", - "_imported_osm_object_found:=(feat.properties.woonplaats==feat(get)('_closed_osm_addr')['addr:city'])&&(feat(get)('_bag_obj:addr:housenumber')==feat(get)('_closed_osm_addr')['addr:housenumber'])&&(feat.properties.postcode==feat(get)('_closed_osm_addr')['addr:postcode'])&&(feat.properties.openbare_ruimte==feat(get)('_closed_osm_addr')['addr:street'])" + "_osm_obj:addr:city:=get(feat)('_closed_osm_addr')['addr:city']", + "_osm_obj:addr:housenumber:=get(feat)('_closed_osm_addr')['addr:housenumber']", + "_osm_obj:addr:postcode:=get(feat)('_closed_osm_addr')['addr:postcode']", + "_osm_obj:addr:street:=get(feat)('_closed_osm_addr')['addr:street']", + "_imported_osm_object_found:=(feat.properties.woonplaats==get(feat)('_closed_osm_addr')['addr:city'])&&(get(feat)('_bag_obj:addr:housenumber')==get(feat)('_closed_osm_addr')['addr:housenumber'])&&(feat.properties.postcode==get(feat)('_closed_osm_addr')['addr:postcode'])&&(feat.properties.openbare_ruimte==get(feat)('_closed_osm_addr')['addr:street'])" ], "tagRenderings": [ { diff --git a/scripts/ScriptUtils.ts b/scripts/ScriptUtils.ts index 7eb369a3a..ac3a915bb 100644 --- a/scripts/ScriptUtils.ts +++ b/scripts/ScriptUtils.ts @@ -2,7 +2,7 @@ import * as fs from "fs" import { existsSync, lstatSync, readdirSync, readFileSync } from "fs" import { Utils } from "../src/Utils" import { https } from "follow-redirects" -import { LayoutConfigJson } from "../src/Models/ThemeConfig/Json/LayoutConfigJson" +import { ThemeConfigJson } from "../src/Models/ThemeConfig/Json/ThemeConfigJson" import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" import xml2js from "xml2js" @@ -111,7 +111,7 @@ export default class ScriptUtils { } public static getThemeFiles(useTranslationPaths = false): { - parsed: LayoutConfigJson; + parsed: ThemeConfigJson; path: string; raw: string }[] { diff --git a/scripts/generateDocs.ts b/scripts/generateDocs.ts index c06a3c449..ab6ccc680 100644 --- a/scripts/generateDocs.ts +++ b/scripts/generateDocs.ts @@ -8,7 +8,7 @@ import QueryParameterDocumentation from "../src/UI/QueryParameterDocumentation" import ScriptUtils from "./ScriptUtils" import Translations from "../src/UI/i18n/Translations" import themeOverview from "../src/assets/generated/theme_overview.json" -import LayoutConfig from "../src/Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../src/Models/ThemeConfig/ThemeConfig" import bookcases from "../src/assets/generated/themes/bookcases.json" import fakedom from "fake-dom" import unit from "../src/assets/generated/layers/unit.json" @@ -253,7 +253,7 @@ export class GenerateDocs extends Script { } private generateHotkeyDocs() { - new ThemeViewState(new LayoutConfig(bookcases), new Set()) + new ThemeViewState(new ThemeConfig(bookcases), new Set()) this.WriteMarkdownFile("./Docs/Hotkeys.md", Hotkeys.generateDocumentation(), [ "src/UI/Base/Hotkeys.ts", ]) @@ -455,7 +455,7 @@ export class GenerateDocs extends Script { ) } - private generateForTheme(theme: LayoutConfig): void { + private generateForTheme(theme: ThemeConfig): void { const allLayers = AllSharedLayers.getSharedLayersConfigs() const layersToShow = theme.layers.filter( (l) => diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index 3924ec560..61301eeeb 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -1,7 +1,7 @@ import ScriptUtils from "./ScriptUtils" import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs" import licenses from "../src/assets/generated/license_info.json" -import { LayoutConfigJson } from "../src/Models/ThemeConfig/Json/LayoutConfigJson" +import { ThemeConfigJson } from "../src/Models/ThemeConfig/Json/ThemeConfigJson" import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" import Constants from "../src/Models/Constants" import { @@ -29,7 +29,7 @@ import LayerConfig from "../src/Models/ThemeConfig/LayerConfig" import PointRenderingConfig from "../src/Models/ThemeConfig/PointRenderingConfig" import { ConversionContext } from "../src/Models/ThemeConfig/Conversion/ConversionContext" import { GenerateFavouritesLayer } from "./generateFavouritesLayer" -import LayoutConfig, { MinimalLayoutInformation } from "../src/Models/ThemeConfig/LayoutConfig" +import ThemeConfig, { MinimalThemeInformation } from "../src/Models/ThemeConfig/ThemeConfig" import Translations from "../src/UI/i18n/Translations" import { Translatable } from "../src/Models/ThemeConfig/Json/Translatable" import { ValidateThemeAndLayers } from "../src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers" @@ -148,14 +148,14 @@ class LayerOverviewUtils extends Script { super("Reviews and generates the compiled themes") } - private static publicLayerIdsFrom(themefiles: LayoutConfigJson[]): Set { + private static publicLayerIdsFrom(themefiles: ThemeConfigJson[]): Set { const publicThemes = [].concat(...themefiles.filter((th) => !th.hideFromOverview)) return new Set([].concat(...publicThemes.map((th) => this.extractLayerIdsFrom(th)))) } private static extractLayerIdsFrom( - themeFile: LayoutConfigJson, + themeFile: ThemeConfigJson, includeInlineLayers = true, ): string[] { const publicLayerIds: string[] = [] @@ -295,7 +295,7 @@ class LayerOverviewUtils extends Script { layerKeywords[id] = this.layerKeywords(layer) }) - const perId = new Map() + const perId = new Map() for (const theme of themes) { const keywords: Record = {} @@ -308,7 +308,7 @@ class LayerOverviewUtils extends Script { } - const data = { + const data = { id: theme.id, title: theme.title, shortDescription: LayerOverviewUtils.cleanTranslation(theme.shortDescription), @@ -342,7 +342,7 @@ class LayerOverviewUtils extends Script { ) } - writeTheme(theme: LayoutConfigJson) { + writeTheme(theme: ThemeConfigJson) { if (!existsSync(LayerOverviewUtils.themePath)) { mkdirSync(LayerOverviewUtils.themePath) } @@ -519,7 +519,7 @@ class LayerOverviewUtils extends Script { ) new ValidateThemeEnsemble().convertStrict( - Array.from(sharedThemes.values()).map((th) => new LayoutConfig(th, true)), + Array.from(sharedThemes.values()).map((th) => new ThemeConfig(th, true)), ) if (recompiledThemes.length > 0) { @@ -545,7 +545,7 @@ class LayerOverviewUtils extends Script { if: "theme=" + th.id, then: th.icon, })) - const proto: LayoutConfigJson = JSON.parse( + const proto: ThemeConfigJson = JSON.parse( readFileSync("./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json", { encoding: "utf8", }), @@ -689,7 +689,7 @@ class LayerOverviewUtils extends Script { * @param themeFile * @private */ - private extractJavascriptCode(themeFile: LayoutConfigJson) { + private extractJavascriptCode(themeFile: ThemeConfigJson) { const allCode = [ "import {Feature} from 'geojson'", "import { ExtraFuncType } from \"../../../Logic/ExtraFunctions\";", @@ -804,10 +804,10 @@ class LayerOverviewUtils extends Script { recompiledThemes: string[], forceReload: boolean, whitelist: Set, - ): Map { + ): Map { console.log(" ---------- VALIDATING BUILTIN THEMES ---------") const themeFiles = ScriptUtils.getThemeFiles() - const fixed = new Map() + const fixed = new Map() const publicLayers = LayerOverviewUtils.publicLayerIdsFrom( themeFiles.map((th) => th.parsed), diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index fb57fc760..4066360bc 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -3,8 +3,8 @@ import Locale from "../src/UI/i18n/Locale" import Translations from "../src/UI/i18n/Translations" import { Translation } from "../src/UI/i18n/Translation" import all_known_layouts from "../src/assets/generated/known_themes.json" -import { LayoutConfigJson } from "../src/Models/ThemeConfig/Json/LayoutConfigJson" -import LayoutConfig from "../src/Models/ThemeConfig/LayoutConfig" +import { ThemeConfigJson } from "../src/Models/ThemeConfig/Json/ThemeConfigJson" +import ThemeConfig from "../src/Models/ThemeConfig/ThemeConfig" import xml2js from "xml2js" import ScriptUtils from "./ScriptUtils" import { Utils } from "../src/Utils" @@ -100,7 +100,7 @@ class GenerateLayouts extends Script { return newname } - async createSocialImage(layout: LayoutConfig, template: "" | "Wide"): Promise { + async createSocialImage(layout: ThemeConfig, template: "" | "Wide"): Promise { if (!layout.icon.endsWith(".svg")) { console.warn( "Not creating a social image for " + @@ -160,7 +160,7 @@ class GenerateLayouts extends Script { } async createManifest( - layout: LayoutConfig, + layout: ThemeConfig, alreadyWritten: string[] ): Promise<{ manifest: any @@ -319,8 +319,8 @@ class GenerateLayouts extends Script { } async generateCsp( - layout: LayoutConfig, - layoutJson: LayoutConfigJson, + layout: ThemeConfig, + layoutJson: ThemeConfigJson, options: { scriptSrcs: string[] } @@ -441,8 +441,8 @@ class GenerateLayouts extends Script { } async createLandingPage( - layout: LayoutConfig, - layoutJson: LayoutConfigJson, + layout: ThemeConfig, + layoutJson: ThemeConfigJson, whiteIcons, alreadyWritten ) { @@ -456,7 +456,7 @@ class GenerateLayouts extends Script { .replace(/"/g, '\\"') let ogImage = layout.socialImage let twitterImage = ogImage - if (ogImage === LayoutConfig.defaultSocialImage && layout.official) { + if (ogImage === ThemeConfig.defaultSocialImage && layout.official) { try { ogImage = (await this.createSocialImage(layout, "")) ?? layout.socialImage twitterImage = (await this.createSocialImage(layout, "Wide")) ?? layout.socialImage @@ -573,7 +573,7 @@ class GenerateLayouts extends Script { ) } - async createIndexFor(theme: LayoutConfig) { + async createIndexFor(theme: ThemeConfig) { const filename = "index_" + theme.id + ".ts" const imports = [ @@ -628,18 +628,18 @@ class GenerateLayouts extends Script { "theme", ] // @ts-ignore - const all: LayoutConfigJson[] = all_known_layouts.themes + const all: ThemeConfigJson[] = all_known_layouts.themes const args = process.argv const theme = args[2] if (theme !== undefined) { console.warn("Only generating layout " + theme) } for (const i in all) { - const layoutConfigJson: LayoutConfigJson = all[i] + const layoutConfigJson: ThemeConfigJson = all[i] if (theme !== undefined && layoutConfigJson.id !== theme) { continue } - const layout = new LayoutConfig(layoutConfigJson, true) + const layout = new ThemeConfig(layoutConfigJson, true) const layoutName = layout.id if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) { console.log(`Skipping a layout with name ${layoutName}, it is on the blacklist`) @@ -668,7 +668,7 @@ class GenerateLayouts extends Script { } const { manifest } = await this.createManifest( - new LayoutConfig({ + new ThemeConfig({ icon: "./assets/svg/mapcomplete_logo.svg", id: "index", layers: [], diff --git a/scripts/generateTaginfoProjectFiles.ts b/scripts/generateTaginfoProjectFiles.ts index e5ebe8882..ce6cad2c6 100644 --- a/scripts/generateTaginfoProjectFiles.ts +++ b/scripts/generateTaginfoProjectFiles.ts @@ -2,7 +2,7 @@ import { AllKnownLayouts } from "../src/Customizations/AllKnownLayouts" import Locale from "../src/UI/i18n/Locale" import { Translation } from "../src/UI/i18n/Translation" import { readFileSync, writeFileSync } from "fs" -import LayoutConfig from "../src/Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../src/Models/ThemeConfig/ThemeConfig" import LayerConfig from "../src/Models/ThemeConfig/LayerConfig" import { Utils } from "../src/Utils" @@ -33,7 +33,7 @@ function generateTagOverview( return overview } -function generateLayerUsage(layer: LayerConfig, layout: LayoutConfig): any[] { +function generateLayerUsage(layer: LayerConfig, layout: ThemeConfig): any[] { if (layer.name === undefined) { return [] // Probably a duplicate or irrelevant layer } @@ -124,7 +124,7 @@ function generateLayerUsage(layer: LayerConfig, layout: LayoutConfig): any[] { * Generates the JSON-object representing the theme for inclusion on taginfo * @param layout */ -function generateTagInfoEntry(layout: LayoutConfig): any { +function generateTagInfoEntry(layout: ThemeConfig): any { const usedTags = [] for (const layer of layout.layers) { if (layer.source === null) { diff --git a/scripts/handleErrors.ts b/scripts/handleErrors.ts index 8247e1175..ae5a43796 100644 --- a/scripts/handleErrors.ts +++ b/scripts/handleErrors.ts @@ -15,7 +15,7 @@ type ErrorMessage = { message: { stacktrace: string message: string - layout: string + theme: string version: string language: string username: string @@ -40,7 +40,7 @@ class HandleErrors extends Script { ) { console.log( parsed.message.username, - parsed.message.layout, + parsed.message.theme, parsed.message.message, parsed.date ) @@ -82,7 +82,7 @@ class HandleErrors extends Script { } = changesObj.CreateChangesetObjects(toUpload, objects, true) const changeset = Changes.buildChangesetXML("", changes) - const path = "error_changeset_" + parsed.index + "_" + e.layout + "_" + e.username + ".osc" + const path = "error_changeset_" + parsed.index + "_" + e.theme + "_" + e.username + ".osc" if ( changeset === `` diff --git a/src/Customizations/AllKnownLayouts.ts b/src/Customizations/AllKnownLayouts.ts index 5882b3135..c4004e2da 100644 --- a/src/Customizations/AllKnownLayouts.ts +++ b/src/Customizations/AllKnownLayouts.ts @@ -1,7 +1,7 @@ import known_themes from "../assets/generated/known_themes.json" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import favourite from "../assets/generated/layers/favourite.json" -import { LayoutConfigJson } from "../Models/ThemeConfig/Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Models/ThemeConfig/Json/ThemeConfigJson" import { AllSharedLayers } from "./AllSharedLayers" import Constants from "../Models/Constants" @@ -9,8 +9,8 @@ import Constants from "../Models/Constants" * Somewhat of a dictionary, which lazily parses needed themes */ export class AllKnownLayoutsLazy { - private readonly raw: Map = new Map() - private readonly dict: Map = new Map() + private readonly raw: Map = new Map() + private readonly dict: Map = new Map() constructor(includeFavouriteLayer = true) { for (const layoutConfigJson of known_themes["themes"]) { @@ -32,7 +32,7 @@ export class AllKnownLayoutsLazy { } } - public getConfig(key: string): LayoutConfigJson { + public getConfig(key: string): ThemeConfigJson { return this.raw.get(key) } @@ -40,13 +40,13 @@ export class AllKnownLayoutsLazy { return this.raw.size } - public get(key: string): LayoutConfig { + public get(key: string): ThemeConfig { const cached = this.dict.get(key) if (cached !== undefined) { return cached } - const layout = new LayoutConfig(this.getConfig(key)) + const layout = new ThemeConfig(this.getConfig(key)) this.dict.set(key, layout) return layout } diff --git a/src/Logic/Actors/InitialMapPositioning.ts b/src/Logic/Actors/InitialMapPositioning.ts index f62a11fd8..d61ab3803 100644 --- a/src/Logic/Actors/InitialMapPositioning.ts +++ b/src/Logic/Actors/InitialMapPositioning.ts @@ -1,5 +1,5 @@ import { ImmutableStore, Store, UIEventSource } from "../UIEventSource" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" import { LocalStorageSource } from "../Web/LocalStorageSource" import { QueryParameters } from "../Web/QueryParameters" import Hash from "../Web/Hash" @@ -25,7 +25,7 @@ export default class InitialMapPositioning { public location: UIEventSource<{ lon: number; lat: number }> public useTerrain: Store - constructor(layoutToUse: LayoutConfig, geolocationState: GeoLocationState) { + constructor(layoutToUse: ThemeConfig, geolocationState: GeoLocationState) { function localStorageSynced( key: string, deflt: number, diff --git a/src/Logic/Actors/NoElementsInViewDetector.ts b/src/Logic/Actors/NoElementsInViewDetector.ts index bc5148335..46e24e494 100644 --- a/src/Logic/Actors/NoElementsInViewDetector.ts +++ b/src/Logic/Actors/NoElementsInViewDetector.ts @@ -14,7 +14,7 @@ export default class NoElementsInViewDetector { constructor(themeViewState: ThemeViewState) { const state = themeViewState const minZoom = Math.min( - ...themeViewState.layout.layers + ...themeViewState.theme.layers .filter((l) => Constants.priviliged_layers.indexOf(l.id) < 0) .map((l) => l.minzoom) ) @@ -43,7 +43,7 @@ export default class NoElementsInViewDetector { // Nope, no data loaded continue } - const layer = themeViewState.layout.getLayer(layerName) + const layer = themeViewState.theme.getLayer(layerName) if (mapProperties.zoom.data < layer.minzoom) { minzoomWithData = Math.min(layer.minzoom) continue @@ -67,7 +67,7 @@ export default class NoElementsInViewDetector { continue } - const layer = themeViewState.layout.getLayer(layerName) + const layer = themeViewState.theme.getLayer(layerName) if (mapProperties.zoom.data < layer.minzoom) { continue } diff --git a/src/Logic/Actors/SelectedElementTagsUpdater.ts b/src/Logic/Actors/SelectedElementTagsUpdater.ts index 9472d29b3..218b665e7 100644 --- a/src/Logic/Actors/SelectedElementTagsUpdater.ts +++ b/src/Logic/Actors/SelectedElementTagsUpdater.ts @@ -34,7 +34,7 @@ export default class SelectedElementTagsUpdater { public static applyUpdate(latestTags: OsmTags, id: string, state: SpecialVisualizationState) { try { - const leftRightSensitive = state.layout.isLeftRightSensitive() + const leftRightSensitive = state.theme.isLeftRightSensitive() if (leftRightSensitive) { SimpleMetaTagger.removeBothTagging(latestTags) @@ -111,7 +111,7 @@ export default class SelectedElementTagsUpdater { } private invalidateCache(s: Feature) { const state = this.state - const wasPartOfLayer = state.layout.getMatchingLayer(s.properties) + const wasPartOfLayer = state.theme.getMatchingLayer(s.properties) state.toCacheSavers?.get(wasPartOfLayer.id)?.invalidateCacheAround(BBox.get(s)) } private installCallback() { diff --git a/src/Logic/Actors/TitleHandler.ts b/src/Logic/Actors/TitleHandler.ts index aa26c61e2..387aab898 100644 --- a/src/Logic/Actors/TitleHandler.ts +++ b/src/Logic/Actors/TitleHandler.ts @@ -12,11 +12,11 @@ export default class TitleHandler { const currentTitle: Store = selectedElement.map( (selected) => { const lng = Locale.language.data - const defaultTitle = state.layout?.title?.textFor(lng) ?? "MapComplete" + const defaultTitle = state.theme?.title?.textFor(lng) ?? "MapComplete" if (selected === undefined) { return defaultTitle } - const layer = state.layout.getMatchingLayer(selected.properties) + const layer = state.theme.getMatchingLayer(selected.properties) if (layer === undefined) { return defaultTitle } diff --git a/src/Logic/DetermineLayout.ts b/src/Logic/DetermineTheme.ts similarity index 88% rename from src/Logic/DetermineLayout.ts rename to src/Logic/DetermineTheme.ts index 9a4e5f4e2..df03e3b29 100644 --- a/src/Logic/DetermineLayout.ts +++ b/src/Logic/DetermineTheme.ts @@ -1,4 +1,4 @@ -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import { QueryParameters } from "./Web/QueryParameters" import { AllKnownLayouts } from "../Customizations/AllKnownLayouts" import { FixedUiElement } from "../UI/Base/FixedUiElement" @@ -19,10 +19,10 @@ import { DesugaringContext } from "../Models/ThemeConfig/Conversion/Conversion" import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson" import Hash from "./Web/Hash" import { QuestionableTagRenderingConfigJson } from "../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" -import { LayoutConfigJson } from "../Models/ThemeConfig/Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Models/ThemeConfig/Json/ThemeConfigJson" import { ValidateThemeAndLayers } from "../Models/ThemeConfig/Conversion/ValidateThemeAndLayers" -export default class DetermineLayout { +export default class DetermineTheme { private static readonly _knownImages = new Set(Array.from(licenses).map((l) => l.path)) private static readonly loadCustomThemeParam = QueryParameters.GetQueryParameter( "userlayout", @@ -31,7 +31,7 @@ export default class DetermineLayout { ) public static getCustomDefinition(): string { - const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data) + const layoutFromBase64 = decodeURIComponent(DetermineTheme.loadCustomThemeParam.data) if (layoutFromBase64.startsWith("http")) { return layoutFromBase64 @@ -53,8 +53,8 @@ export default class DetermineLayout { } private static async expandRemoteLayers( - layoutConfig: LayoutConfigJson - ): Promise { + layoutConfig: ThemeConfigJson + ): Promise { if (!layoutConfig.layers) { // This is probably a layer in 'layer-only-mode' return layoutConfig @@ -79,16 +79,16 @@ export default class DetermineLayout { /** * Gets the correct layout for this website */ - public static async GetLayout(): Promise { - const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data) + public static async getTheme(): Promise { + const layoutFromBase64 = decodeURIComponent(DetermineTheme.loadCustomThemeParam.data) if (layoutFromBase64.startsWith("http")) { - return await DetermineLayout.LoadRemoteTheme(layoutFromBase64) + return await DetermineTheme.LoadRemoteTheme(layoutFromBase64) } if (layoutFromBase64 !== "false") { // We have to load something from the hash (or from disk) - return await DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam) + return await DetermineTheme.LoadLayoutFromHash(DetermineTheme.loadCustomThemeParam) } let layoutId: string = undefined @@ -127,7 +127,7 @@ export default class DetermineLayout { public static async LoadLayoutFromHash( userLayoutParam: UIEventSource - ): Promise { + ): Promise { let hash = location.hash.substr(1) let json: any @@ -157,7 +157,7 @@ export default class DetermineLayout { json = await this.expandRemoteLayers(json) - const layoutToUse = DetermineLayout.prepCustomTheme(json) + const layoutToUse = DetermineTheme.prepCustomTheme(json) userLayoutParam.setData(layoutToUse.id) return layoutToUse } @@ -166,7 +166,7 @@ export default class DetermineLayout { const dict = new Map() for (const tagRendering of questions.tagRenderings) { - dict.set(tagRendering.id, tagRendering) + dict.set(tagRendering.id, tagRendering) } return dict @@ -176,7 +176,7 @@ export default class DetermineLayout { return questions.tagRenderings.map((tr) => tr.id) } - private static prepCustomTheme(json: any, sourceUrl?: string, forceId?: string): LayoutConfig { + private static prepCustomTheme(json: any, sourceUrl?: string, forceId?: string): ThemeConfig { if (json.layers === undefined && json.tagRenderings !== undefined) { // We got fed a layer instead of a theme const layerConfig = json @@ -224,15 +224,15 @@ export default class DetermineLayout { knownLayersDict.set(layer.id, layer) } const convertState: DesugaringContext = { - tagRenderings: DetermineLayout.getSharedTagRenderings(), - tagRenderingOrder: DetermineLayout.getSharedTagRenderingOrder(), + tagRenderings: DetermineTheme.getSharedTagRenderings(), + tagRenderingOrder: DetermineTheme.getSharedTagRenderingOrder(), sharedLayers: knownLayersDict, publicLayers: new Set(), } json = new FixLegacyTheme().convertStrict(json) const raw = json - json = new FixImages(DetermineLayout._knownImages).convertStrict(json) + json = new FixImages(DetermineTheme._knownImages).convertStrict(json) json.enableNoteImports = json.enableNoteImports ?? false json = new PrepareTheme(convertState).convertStrict(json) console.log("The layoutconfig is ", json) @@ -249,20 +249,20 @@ export default class DetermineLayout { false ).convertStrict(json) } - return new LayoutConfig(json, false, { + return new ThemeConfig(json, false, { definitionRaw: JSON.stringify(raw, null, " "), definedAtUrl: sourceUrl, }) } - private static async LoadRemoteTheme(link: string): Promise { + private static async LoadRemoteTheme(link: string): Promise { console.log("Downloading map theme from ", link) new FixedUiElement(`Downloading the theme from the link...`).AttachTo( "maindiv" ) - let parsed = await Utils.downloadJson(link) + let parsed = await Utils.downloadJson(link) let forcedId = parsed.id const url = new URL(link) if (!(url.hostname === "localhost" || url.hostname === "127.0.0.1")) { @@ -270,6 +270,6 @@ export default class DetermineLayout { } console.log("Loaded remote link:", link) parsed = await this.expandRemoteLayers(parsed) - return DetermineLayout.prepCustomTheme(parsed, link, forcedId) + return DetermineTheme.prepCustomTheme(parsed, link, forcedId) } } diff --git a/src/Logic/FeatureSource/Sources/FavouritesFeatureSource.ts b/src/Logic/FeatureSource/Sources/FavouritesFeatureSource.ts index 595c1def3..5c48ac790 100644 --- a/src/Logic/FeatureSource/Sources/FavouritesFeatureSource.ts +++ b/src/Logic/FeatureSource/Sources/FavouritesFeatureSource.ts @@ -49,7 +49,7 @@ export default class FavouritesFeatureSource extends StaticFeatureSource { const featuresWithoutAlreadyPresent = features.map((features) => features.filter( - (feat) => !state.layout.layers.some((l) => l.id === feat.properties._orig_layer) + (feat) => !state.theme.layers.some((l) => l.id === feat.properties._orig_layer) ) ) diff --git a/src/Logic/FeatureSource/Sources/LastClickFeatureSource.ts b/src/Logic/FeatureSource/Sources/LastClickFeatureSource.ts index 830d20333..46b4fbb56 100644 --- a/src/Logic/FeatureSource/Sources/LastClickFeatureSource.ts +++ b/src/Logic/FeatureSource/Sources/LastClickFeatureSource.ts @@ -1,4 +1,4 @@ -import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource" import { Feature, Point } from "geojson" import { TagUtils } from "../../Tags/TagUtils" @@ -22,7 +22,7 @@ export class LastClickFeatureSource implements FeatureSource { private _usermode: UIEventSource private _enabledAddMorePoints: UIEventSource constructor( - layout: LayoutConfig, + layout: ThemeConfig, clickSource: Store<{ lon: number; lat: number; mode: "left" | "right" | "middle" }>, usermode?: UIEventSource, enabledAddMorePoints?: UIEventSource diff --git a/src/Logic/FeatureSource/Sources/LayoutSource.ts b/src/Logic/FeatureSource/Sources/ThemeSource.ts similarity index 93% rename from src/Logic/FeatureSource/Sources/LayoutSource.ts rename to src/Logic/FeatureSource/Sources/ThemeSource.ts index 196f926fc..9c7b5008c 100644 --- a/src/Logic/FeatureSource/Sources/LayoutSource.ts +++ b/src/Logic/FeatureSource/Sources/ThemeSource.ts @@ -18,7 +18,7 @@ import FeatureSourceMerger from "./FeatureSourceMerger" * * Note that special layers (with `source=null` will be ignored) */ -export default class LayoutSource extends FeatureSourceMerger { +export default class ThemeSource extends FeatureSourceMerger { /** * Indicates if a data source is loading something */ @@ -51,7 +51,7 @@ export default class LayoutSource extends FeatureSourceMerger { const src = new LocalStorageFeatureSource( backend, layer, - LayoutSource.fromCacheZoomLevel, + ThemeSource.fromCacheZoomLevel, mapProperties, { isActive: isDisplayed(layer.id), @@ -63,13 +63,13 @@ export default class LayoutSource extends FeatureSourceMerger { } const mvtSources: UpdatableFeatureSource[] = osmLayers .filter((f) => mvtAvailableLayers.has(f.id)) - .map((l) => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id))) + .map((l) => ThemeSource.setupMvtSource(l, mapProperties, isDisplayed(l.id))) const nonMvtSources = [] const nonMvtLayers = osmLayers.filter((l) => !mvtAvailableLayers.has(l.id)) const isLoading = new UIEventSource(false) - const osmApiSource = LayoutSource.setupOsmApiSource( + const osmApiSource = ThemeSource.setupOsmApiSource( osmLayers, bounds, zoom, @@ -86,7 +86,7 @@ export default class LayoutSource extends FeatureSourceMerger { nonMvtLayers.map((l) => l.id), " cannot be fetched from the cache server, defaulting to overpass/OSM-api" ) - overpassSource = LayoutSource.setupOverpass(osmLayers, bounds, zoom, featureSwitches) + overpassSource = ThemeSource.setupOverpass(osmLayers, bounds, zoom, featureSwitches) nonMvtSources.push(overpassSource) supportsForceDownload.push(overpassSource) } @@ -100,7 +100,7 @@ export default class LayoutSource extends FeatureSourceMerger { osmApiSource?.isRunning?.addCallbackAndRun(() => setIsLoading()) const geojsonSources: UpdatableFeatureSource[] = geojsonlayers.map((l) => - LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id)) + ThemeSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id)) ) super(...geojsonSources, ...Array.from(fromCache.values()), ...mvtSources, ...nonMvtSources) @@ -198,7 +198,7 @@ export default class LayoutSource extends FeatureSourceMerger { zoom, bounds, layers: osmLayers, - widenFactor: featureSwitches.layoutToUse.widenFactor, + widenFactor: 1.5, overpassUrl: featureSwitches.overpassUrl, overpassTimeout: featureSwitches.overpassTimeout, overpassMaxZoom: featureSwitches.overpassMaxZoom, diff --git a/src/Logic/ImageProviders/ImageUploadManager.ts b/src/Logic/ImageProviders/ImageUploadManager.ts index ed4ba8b50..0f0ac1a9d 100644 --- a/src/Logic/ImageProviders/ImageUploadManager.ts +++ b/src/Logic/ImageProviders/ImageUploadManager.ts @@ -2,7 +2,7 @@ import { ImageUploader, UploadResult } from "./ImageUploader" import LinkImageAction from "../Osm/Actions/LinkImageAction" import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" import { OsmId, OsmTags } from "../../Models/OsmFeature" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" import { Store, UIEventSource } from "../UIEventSource" import { OsmConnection } from "../Osm/OsmConnection" import { Changes } from "../Osm/Changes" @@ -17,7 +17,7 @@ import { GeoOperations } from "../GeoOperations" export class ImageUploadManager { private readonly _uploader: ImageUploader private readonly _featureProperties: FeaturePropertiesStore - private readonly _layout: LayoutConfig + private readonly _theme: ThemeConfig private readonly _indexedFeatures: IndexedFeatureSource private readonly _gps: Store private readonly _uploadStarted: Map> = new Map() @@ -31,7 +31,7 @@ export class ImageUploadManager { private readonly _reportError: (message: (string | Error | XMLHttpRequest), extramessage?: string) => Promise constructor( - layout: LayoutConfig, + layout: ThemeConfig, uploader: ImageUploader, featureProperties: FeaturePropertiesStore, osmConnection: OsmConnection, @@ -42,7 +42,7 @@ export class ImageUploadManager { ) { this._uploader = uploader this._featureProperties = featureProperties - this._layout = layout + this._theme = layout this._osmConnection = osmConnection this._changes = changes this._indexedFeatures = allFeatures @@ -131,7 +131,7 @@ export class ImageUploadManager { const properties = this._featureProperties.getStore(featureId) const action = new LinkImageAction(featureId, uploadResult. key, uploadResult . value, properties, { - theme: tags?.data?.["_orig_theme"] ?? this._layout.id, + theme: tags?.data?.["_orig_theme"] ?? this._theme.id, changeType: "add-image", }) diff --git a/src/Logic/MetaTagging.ts b/src/Logic/MetaTagging.ts index 3e5a239a0..b93acc30b 100644 --- a/src/Logic/MetaTagging.ts +++ b/src/Logic/MetaTagging.ts @@ -3,7 +3,7 @@ import { ExtraFuncParams, ExtraFunctions, ExtraFuncType } from "./ExtraFunctions import LayerConfig from "../Models/ThemeConfig/LayerConfig" import { Feature } from "geojson" import FeaturePropertiesStore from "./FeatureSource/Actors/FeaturePropertiesStore" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import { GeoIndexedStoreForLayer } from "./FeatureSource/Actors/GeoIndexedStore" import { IndexedFeatureSource } from "./FeatureSource/FeatureSource" import OsmObjectDownloader from "./Osm/OsmObjectDownloader" @@ -27,7 +27,7 @@ export default class MetaTagging { >() private state: { readonly selectedElement: Store - readonly layout: LayoutConfig + readonly theme: ThemeConfig readonly osmObjectDownloader: OsmObjectDownloader readonly perLayer: ReadonlyMap readonly indexedFeatures: IndexedFeatureSource @@ -40,7 +40,7 @@ export default class MetaTagging { constructor(state: { readonly selectedElement: Store - readonly layout: LayoutConfig + readonly theme: ThemeConfig readonly osmObjectDownloader: OsmObjectDownloader readonly perLayer: ReadonlyMap readonly indexedFeatures: IndexedFeatureSource @@ -48,7 +48,7 @@ export default class MetaTagging { }) { this.state = state const params = (this.params = MetaTagging.createExtraFuncParams(state)) - for (const layer of state.layout.layers) { + for (const layer of state.theme.layers) { if (layer.source === null) { continue } @@ -69,7 +69,7 @@ export default class MetaTagging { features, params, layer, - state.layout, + state.theme, state.osmObjectDownloader, state.featureProperties ) @@ -115,7 +115,7 @@ export default class MetaTagging { return } const state = this.state - const layer = state.layout.getMatchingLayer(feature.properties) + const layer = state.theme.getMatchingLayer(feature.properties) if (!layer) { return } @@ -124,7 +124,7 @@ export default class MetaTagging { [feature], this.params, layer, - state.layout, + state.theme, state.osmObjectDownloader, state.featureProperties, { @@ -161,7 +161,7 @@ export default class MetaTagging { features: Feature[], params: ExtraFuncParams, layer: LayerConfig, - layout: LayoutConfig, + theme: ThemeConfig, osmObjectDownloader: OsmObjectDownloader, featurePropertiesStores?: FeaturePropertiesStore, options?: { @@ -190,7 +190,7 @@ export default class MetaTagging { // The calculated functions - per layer - which add the new keys // Calculated functions are defined by the layer const layerFuncs = this.createRetaggingFunc(layer, ExtraFunctions.constructHelpers(params)) - const state: MetataggingState = { layout, osmObjectDownloader } + const state: MetataggingState = { theme: theme, osmObjectDownloader } let atLeastOneFeatureChanged = false let strictlyEvaluated = 0 @@ -424,7 +424,7 @@ export default class MetaTagging { } } - if (!window.location.pathname.endsWith("theme.html")) { + if (!Utils.runningFromConsole && !window.location.pathname.endsWith("theme.html")) { console.warn( "Static MetataggingObject for theme is not set; using `new Function` (aka `eval`) to get calculated tags. This might trip up the CSP" ) diff --git a/src/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts b/src/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts index 7b259e638..14582d405 100644 --- a/src/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts +++ b/src/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts @@ -7,7 +7,7 @@ import CreateWayWithPointReuseAction, { MergePointConfig } from "./CreateWayWith import { And } from "../../Tags/And" import { TagUtils } from "../../Tags/TagUtils" import { FeatureSource, IndexedFeatureSource } from "../../FeatureSource/FeatureSource" -import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import { Position } from "geojson" import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" @@ -32,7 +32,7 @@ export default class CreateMultiPolygonWithPointReuseAction outerRingCoordinates: Position[], innerRingsCoordinates: Position[][], state: { - layout: LayoutConfig + theme: ThemeConfig changes: Changes indexedFeatures: IndexedFeatureSource fullNodeDatabase?: FullNodeDatabaseSource @@ -43,7 +43,7 @@ export default class CreateMultiPolygonWithPointReuseAction super(null, true) this._tags = [...tags, new Tag("type", "multipolygon")] this.changeType = changeType - this.theme = state?.layout?.id ?? "" + this.theme = state?.theme?.id ?? "" this.createOuterWay = new CreateWayWithPointReuseAction( [], <[number, number][]>outerRingCoordinates, @@ -55,7 +55,7 @@ export default class CreateMultiPolygonWithPointReuseAction new CreateNewWayAction( [], ringCoordinates.map(([lon, lat]) => ({ lat, lon })), - { theme: state?.layout?.id } + { theme: state?.theme?.id } ) ) diff --git a/src/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts b/src/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts index 9a87f7589..eba4275ec 100644 --- a/src/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts +++ b/src/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts @@ -9,7 +9,7 @@ import { FeatureSource, IndexedFeatureSource } from "../../FeatureSource/Feature import StaticFeatureSource from "../../FeatureSource/Sources/StaticFeatureSource" import CreateNewNodeAction from "./CreateNewNodeAction" import CreateNewWayAction from "./CreateNewWayAction" -import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" import { Position } from "geojson" @@ -69,7 +69,7 @@ export default class CreateWayWithPointReuseAction */ private readonly _coordinateInfo: CoordinateInfo[] private readonly _state: { - layout: LayoutConfig + theme: ThemeConfig changes: Changes indexedFeatures: IndexedFeatureSource fullNodeDatabase?: FullNodeDatabaseSource @@ -80,7 +80,7 @@ export default class CreateWayWithPointReuseAction tags: Tag[], coordinates: Position[], state: { - layout: LayoutConfig + theme: ThemeConfig changes: Changes indexedFeatures: IndexedFeatureSource fullNodeDatabase?: FullNodeDatabaseSource @@ -203,7 +203,7 @@ export default class CreateWayWithPointReuseAction } public async CreateChangeDescriptions(changes: Changes): Promise { - const theme = this._state?.layout?.id + const theme = this._state?.theme?.id const allChanges: ChangeDescription[] = [] const nodeIdsToUse: { lat: number; lon: number; nodeId?: number }[] = [] for (let i = 0; i < this._coordinateInfo.length; i++) { diff --git a/src/Logic/Osm/Actions/ReplaceGeometryAction.ts b/src/Logic/Osm/Actions/ReplaceGeometryAction.ts index 07be721fb..9ea6f820b 100644 --- a/src/Logic/Osm/Actions/ReplaceGeometryAction.ts +++ b/src/Logic/Osm/Actions/ReplaceGeometryAction.ts @@ -217,7 +217,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction implements Pr const url = `${ this.state.osmConnection?._oauth_config?.url ?? "https://api.openstreetmap.org" }/api/0.6/${this.wayToReplaceId}/full` - const rawData = await Utils.downloadJsonCached(url, 1000) + const rawData = await Utils.downloadJsonCached<{elements: any[]}>(url, 1000) parsed = OsmObject.ParseObjects(rawData.elements) } const allNodes = parsed.filter((o) => o.type === "node") diff --git a/src/Logic/Search/FilterSearch.ts b/src/Logic/Search/FilterSearch.ts index a08b0bb5c..35711f3cc 100644 --- a/src/Logic/Search/FilterSearch.ts +++ b/src/Logic/Search/FilterSearch.ts @@ -4,7 +4,7 @@ import Constants from "../../Models/Constants" import FilterConfig, { FilterConfigOption } from "../../Models/ThemeConfig/FilterConfig" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import LayerState from "../State/LayerState" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" export type FilterSearchResult = { option: FilterConfigOption, filter: FilterConfig, layer: LayerConfig, index: number } @@ -13,9 +13,9 @@ export type FilterSearchResult = { option: FilterConfigOption, filter: FilterCon * Searches matching filters */ export default class FilterSearch { - private readonly _state: {layerState: LayerState, layout: LayoutConfig} + private readonly _state: {layerState: LayerState, theme: ThemeConfig} - constructor(state: {layerState: LayerState, layout: LayoutConfig}) { + constructor(state: {layerState: LayerState, theme: ThemeConfig}) { this._state = state } @@ -30,7 +30,7 @@ export default class FilterSearch { return query }).filter(q => q.length > 0) const possibleFilters: FilterSearchResult[] = [] - for (const layer of this._state.layout.layers) { + for (const layer of this._state.theme.layers) { if (!Array.isArray(layer.filters)) { continue } diff --git a/src/Logic/Search/LayerSearch.ts b/src/Logic/Search/LayerSearch.ts index 60ffbacb1..9397c0ee4 100644 --- a/src/Logic/Search/LayerSearch.ts +++ b/src/Logic/Search/LayerSearch.ts @@ -1,17 +1,17 @@ import SearchUtils from "./SearchUtils" import ThemeSearch from "./ThemeSearch" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" import { Utils } from "../../Utils" export default class LayerSearch { - private readonly _layout: LayoutConfig + private readonly _theme: ThemeConfig private readonly _layerWhitelist: Set - constructor(layout: LayoutConfig) { - this._layout = layout - this._layerWhitelist = new Set(layout.layers + constructor(theme: ThemeConfig) { + this._theme = theme + this._layerWhitelist = new Set(theme.layers .filter(l => l.isNormal()) .map(l => l.id)) } @@ -29,8 +29,7 @@ export default class LayerSearch { continue } const keywords = ThemeSearch.officialThemes.layers[id] - const distance = Math.min(...queryParts.map(q => SearchUtils.scoreKeywords(q, keywords))) - result[id] = distance + result[id] = Math.min(...queryParts.map(q => SearchUtils.scoreKeywords(q, keywords))) } return result } @@ -44,7 +43,7 @@ export default class LayerSearch { const asList: ({ layer: LayerConfig, score: number })[] = [] for (const layer in scores) { asList.push({ - layer: this._layout.getLayer(layer), + layer: this._theme.getLayer(layer), score: scores[layer], }) } diff --git a/src/Logic/Search/ThemeSearch.ts b/src/Logic/Search/ThemeSearch.ts index 30b4d25eb..3c4ef6be4 100644 --- a/src/Logic/Search/ThemeSearch.ts +++ b/src/Logic/Search/ThemeSearch.ts @@ -1,4 +1,4 @@ -import LayoutConfig, { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig, { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig" import { Store } from "../UIEventSource" import UserRelatedState from "../State/UserRelatedState" import { Utils } from "../../Utils" @@ -10,7 +10,7 @@ import { OsmConnection } from "../Osm/OsmConnection" type ThemeSearchScore = { - theme: MinimalLayoutInformation, + theme: MinimalThemeInformation, lowest: number, perLayer?: Record, other: number, @@ -20,10 +20,10 @@ type ThemeSearchScore = { export default class ThemeSearch { public static readonly officialThemes: { - themes: MinimalLayoutInformation[], + themes: MinimalThemeInformation[], layers: Record> } = themeOverview - public static readonly officialThemesById: Map = new Map() + public static readonly officialThemesById: Map = new Map() static { for (const th of ThemeSearch.officialThemes.themes ?? []) { ThemeSearch.officialThemesById.set(th.id, th) @@ -33,17 +33,17 @@ export default class ThemeSearch { private readonly _knownHiddenThemes: Store> private readonly _layersToIgnore: string[] - private readonly _otherThemes: MinimalLayoutInformation[] + private readonly _otherThemes: MinimalThemeInformation[] - constructor(state: {osmConnection: OsmConnection, layout: LayoutConfig}) { - this._layersToIgnore = state.layout.layers.filter(l => l.isNormal()).map(l => l.id) + constructor(state: {osmConnection: OsmConnection, theme: ThemeConfig}) { + this._layersToIgnore = state.theme.layers.filter(l => l.isNormal()).map(l => l.id) this._knownHiddenThemes = UserRelatedState.initDiscoveredHiddenThemes(state.osmConnection).map(list => new Set(list)) this._otherThemes = ThemeSearch.officialThemes.themes - .filter(th => th.id !== state.layout.id) + .filter(th => th.id !== state.theme.id) } - public search(query: string, limit: number, threshold: number = 3): MinimalLayoutInformation[] { + public search(query: string, limit: number, threshold: number = 3): MinimalThemeInformation[] { if (query.length < 1) { return [] } @@ -101,7 +101,7 @@ export default class ThemeSearch { * @param ignoreLayers * @private */ - private static scoreThemes(query: string, themes: MinimalLayoutInformation[], ignoreLayers: string[] = undefined): Record { + private static scoreThemes(query: string, themes: MinimalThemeInformation[], ignoreLayers: string[] = undefined): Record { if (query?.length < 1) { return undefined } @@ -147,13 +147,13 @@ export default class ThemeSearch { return results } - public static sortedByLowestScores(search: string, themes: MinimalLayoutInformation[], ignoreLayers: string[] = []): ThemeSearchScore[] { + public static sortedByLowestScores(search: string, themes: MinimalThemeInformation[], ignoreLayers: string[] = []): ThemeSearchScore[] { const scored = Object.values(this.scoreThemes(search, themes, ignoreLayers)) scored.sort((a, b) => a.lowest - b.lowest) return scored } - public static sortedByLowest(search: string, themes: MinimalLayoutInformation[], ignoreLayers: string[] = []): MinimalLayoutInformation[] { + public static sortedByLowest(search: string, themes: MinimalThemeInformation[], ignoreLayers: string[] = []): MinimalThemeInformation[] { return this.sortedByLowestScores(search, themes, ignoreLayers) .map(th => th.theme) } diff --git a/src/Logic/SimpleMetaTagger.ts b/src/Logic/SimpleMetaTagger.ts index 611207a47..3e0595b38 100644 --- a/src/Logic/SimpleMetaTagger.ts +++ b/src/Logic/SimpleMetaTagger.ts @@ -8,7 +8,7 @@ import { TagUtils } from "./Tags/TagUtils" import { Feature, LineString } from "geojson" import { OsmTags } from "../Models/OsmFeature" import { UIEventSource } from "./UIEventSource" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import OsmObjectDownloader from "./Osm/OsmObjectDownloader" import countryToCurrency from "country-to-currency" @@ -16,7 +16,7 @@ import countryToCurrency from "country-to-currency" * All elements that are needed to perform metatagging */ export interface MetataggingState { - layout: LayoutConfig + theme: ThemeConfig osmObjectDownloader: OsmObjectDownloader } @@ -399,7 +399,7 @@ export default class SimpleMetaTaggers { }, (feature, _, __, state) => { const units = Utils.NoNull( - [].concat(...(state?.layout?.layers?.map((layer) => layer.units) ?? [])) + [].concat(...(state?.theme?.layers?.map((layer) => layer.units) ?? [])) ) if (units.length == 0) { return diff --git a/src/Logic/State/FeatureSwitchState.ts b/src/Logic/State/FeatureSwitchState.ts index 054d9c841..e7d39702e 100644 --- a/src/Logic/State/FeatureSwitchState.ts +++ b/src/Logic/State/FeatureSwitchState.ts @@ -1,7 +1,7 @@ /** - * The part of the global state which initializes the feature switches, based on default values and on the layoutToUse + * The part of the global state which initializes the feature switches, based on default values and on the theme */ -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig" import { UIEventSource } from "../UIEventSource" import { QueryParameters } from "../Web/QueryParameters" import Constants from "../../Models/Constants" @@ -45,10 +45,6 @@ export class OsmConnectionFeatureSwitches { } export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { - /** - * The layout that is being used in this run - */ - public readonly layoutToUse: LayoutConfig public readonly featureSwitchEnableLogin: UIEventSource public readonly featureSwitchSearch: UIEventSource @@ -74,9 +70,8 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { public readonly featureSwitchMorePrivacy: UIEventSource public readonly featureSwitchLayerDefault: UIEventSource - public constructor(layoutToUse?: LayoutConfig) { + public constructor(theme?: ThemeConfig) { super() - this.layoutToUse = layoutToUse const legacyRewrite: Record = { "fs-userbadge": "fs-enable-login", @@ -102,7 +97,7 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { this.featureSwitchEnableLogin = FeatureSwitchUtils.initSwitch( "fs-enable-login", - layoutToUse?.enableUserBadge ?? true, + theme?.enableUserBadge ?? true, "Disables/Enables logging in and thus disables editing all together. This effectively puts MapComplete into read-only mode." ) { @@ -117,18 +112,18 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { this.featureSwitchSearch = FeatureSwitchUtils.initSwitch( "fs-search", - layoutToUse?.enableSearch ?? true, + theme?.enableSearch ?? true, "Disables/Enables the search bar" ) this.featureSwitchBackgroundSelection = FeatureSwitchUtils.initSwitch( "fs-background", - layoutToUse?.enableBackgroundLayerSelection ?? true, + theme?.enableBackgroundLayerSelection ?? true, "Disables/Enables the background layer control where a user can enable e.g. aerial imagery" ) this.featureSwitchFilter = FeatureSwitchUtils.initSwitch( "fs-filter", - layoutToUse?.enableLayers ?? true, + theme?.enableLayers ?? true, "Disables/Enables the filter view where a user can enable/disable MapComplete-layers or filter for certain properties" ) @@ -149,17 +144,17 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { ) this.featureSwitchBackToThemeOverview = FeatureSwitchUtils.initSwitch( "fs-homepage-link", - layoutToUse?.enableMoreQuests ?? true, + theme?.enableMoreQuests ?? true, "Disables/Enables the various links which go back to the index page with the theme overview" ) this.featureSwitchShareScreen = FeatureSwitchUtils.initSwitch( "fs-share-screen", - layoutToUse?.enableShareScreen ?? true, + theme?.enableShareScreen ?? true, "Disables/Enables the 'Share-screen'-tab in the welcome message" ) this.featureSwitchGeolocation = FeatureSwitchUtils.initSwitch( "fs-geolocation", - layoutToUse?.enableGeolocation ?? true, + theme?.enableGeolocation ?? true, "Disables/Enables the geolocation button" ) @@ -170,19 +165,19 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { ) this.featureSwitchShowAllQuestions = FeatureSwitchUtils.initSwitch( "fs-all-questions", - layoutToUse?.enableShowAllQuestions ?? false, + theme?.enableShowAllQuestions ?? false, "Always show all questions" ) this.featureSwitchEnableExport = FeatureSwitchUtils.initSwitch( "fs-export", - layoutToUse?.enableExportButton ?? true, + theme?.enableExportButton ?? true, "Enable the export as GeoJSON and CSV button" ) this.featureSwitchCache = FeatureSwitchUtils.initSwitch( "fs-cache", - layoutToUse?.enableCache ?? true, + theme?.enableCache ?? true, "Enable/disable caching from localStorage" ) @@ -209,13 +204,13 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { this.featureSwitchMorePrivacy = QueryParameters.GetBooleanQueryParameter( "moreprivacy", - layoutToUse.enableMorePrivacy, + theme.enableMorePrivacy, "If true, the location distance indication will not be written to the changeset and other privacy enhancing measures might be taken." ) this.overpassUrl = QueryParameters.GetQueryParameter( "overpassUrl", - (layoutToUse?.overpassUrl ?? Constants.defaultOverpassUrls).join(","), + (theme?.overpassUrl ?? Constants.defaultOverpassUrls).join(","), "Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter" ).sync( (param) => param?.split(","), @@ -226,7 +221,7 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { this.overpassTimeout = UIEventSource.asInt( QueryParameters.GetQueryParameter( "overpassTimeout", - "" + layoutToUse?.overpassTimeout, + "" + theme?.overpassTimeout, "Set a different timeout (in seconds) for queries in overpass" ) ) @@ -234,7 +229,7 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { this.overpassMaxZoom = UIEventSource.asFloat( QueryParameters.GetQueryParameter( "overpassMaxZoom", - "" + layoutToUse?.overpassMaxZoom, + "" + theme?.overpassMaxZoom, " point to switch between OSM-api and overpass" ) ) @@ -242,14 +237,14 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { this.osmApiTileSize = UIEventSource.asInt( QueryParameters.GetQueryParameter( "osmApiTileSize", - "" + layoutToUse?.osmApiTileSize, + "" + theme?.osmApiTileSize, "Tilesize when the OSM-API is used to fetch data within a BBOX" ) ) this.backgroundLayerId = QueryParameters.GetQueryParameter( "background", - layoutToUse?.defaultBackgroundId, + theme?.defaultBackgroundId, [ "When set, load this raster layer (or a layer of this category) as background layer instead of using the default background. This is as if the user opened the background selection menu and selected the layer with the given id or category.", "Most raster layers are based on the [editor layer index](https://github.com/osmlab/editor-layer-index)", diff --git a/src/Logic/State/SearchState.ts b/src/Logic/State/SearchState.ts index 68f6d5427..5e2310cf3 100644 --- a/src/Logic/State/SearchState.ts +++ b/src/Logic/State/SearchState.ts @@ -8,7 +8,7 @@ import ThemeSearch from "../Search/ThemeSearch" import OpenStreetMapIdSearch from "../Search/OpenStreetMapIdSearch" import PhotonSearch from "../Search/PhotonSearch" import ThemeViewState from "../../Models/ThemeViewState" -import type { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig" +import type { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig" import { Translation } from "../../UI/i18n/Translation" import GeocodingFeatureSource from "../Search/GeocodingFeatureSource" import LayerSearch from "../Search/LayerSearch" @@ -23,7 +23,7 @@ export default class SearchState { public readonly searchIsFocused = new UIEventSource(false) public readonly suggestions: Store public readonly filterSuggestions: Store - public readonly themeSuggestions: Store + public readonly themeSuggestions: Store public readonly layerSuggestions: Store public readonly locationSearchers: ReadonlyArray @@ -64,7 +64,7 @@ export default class SearchState { const themeSearch = new ThemeSearch(state) this.themeSuggestions = this.searchTerm.mapD(query => themeSearch.search(query, 3)) - const layerSearch = new LayerSearch(state.layout) + const layerSearch = new LayerSearch(state.theme) this.layerSuggestions = this.searchTerm.mapD(query => layerSearch.search(query, 5)) const filterSearch = new FilterSearch(state) diff --git a/src/Logic/State/UserRelatedState.ts b/src/Logic/State/UserRelatedState.ts index d958c3cf4..0d3d4eae0 100644 --- a/src/Logic/State/UserRelatedState.ts +++ b/src/Logic/State/UserRelatedState.ts @@ -1,4 +1,4 @@ -import LayoutConfig, { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig" +import ThemeConfig, { MinimalThemeInformation } from "../../Models/ThemeConfig/ThemeConfig" import { OsmConnection } from "../Osm/OsmConnection" import { MangroveIdentity } from "../Web/MangroveReviews" import { Store, Stores, UIEventSource } from "../UIEventSource" @@ -183,7 +183,7 @@ export default class UserRelatedState { constructor( osmConnection: OsmConnection, - layout?: LayoutConfig, + layout?: ThemeConfig, featureSwitches?: FeatureSwitchState, mapProperties?: MapProperties, ) { @@ -277,14 +277,14 @@ export default class UserRelatedState { * * @param themeInfo note that themeInfo.id should be the URL where it was found */ - public addUnofficialTheme(themeInfo: MinimalLayoutInformation) { + public addUnofficialTheme(themeInfo: MinimalThemeInformation) { const pref = this.osmConnection.getPreference("unofficial-theme-" + themeInfo.id) this.osmConnection.isLoggedIn.when( () => pref.set(JSON.stringify(themeInfo)) ) } - public getUnofficialTheme(id: string): MinimalLayoutInformation | undefined { + public getUnofficialTheme(id: string): MinimalThemeInformation | undefined { const pref = this.osmConnection.getPreference("unofficial-theme-" + id) const str = pref.data @@ -307,7 +307,7 @@ export default class UserRelatedState { } } - public markLayoutAsVisited(layout: LayoutConfig) { + public markLayoutAsVisited(layout: ThemeConfig) { if (!layout) { console.error("Trying to mark a layout as visited, but ", layout, " got passed") return @@ -399,7 +399,7 @@ export default class UserRelatedState { * This is inherently a dirty and chaotic method, as it shoves many properties into this EventSource * */ private initAmendedPrefs( - layout?: LayoutConfig, + layout?: ThemeConfig, featureSwitches?: FeatureSwitchState, ): UIEventSource> { const amendedPrefs = new UIEventSource>({ diff --git a/src/Logic/Web/LocalStorageSource.ts b/src/Logic/Web/LocalStorageSource.ts index e1453597e..1f4413e45 100644 --- a/src/Logic/Web/LocalStorageSource.ts +++ b/src/Logic/Web/LocalStorageSource.ts @@ -30,13 +30,16 @@ export class LocalStorageSource { return cached } let saved = defaultValue - try { - saved = localStorage.getItem(key) - if (saved === "undefined") { - saved = undefined + if (!Utils.runningFromConsole) { + + try { + saved = localStorage.getItem(key) + if (saved === "undefined") { + saved = undefined + } + } catch (e) { + console.error("Could not get value", key, "from local storage") } - } catch (e) { - console.error("Could not get value", key, "from local storage") } const source = new UIEventSource(saved ?? defaultValue, "localstorage:" + key) diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index afefc9cef..ddc05165c 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -55,7 +55,7 @@ export default class Constants { // The user journey states thresholds when a new feature gets unlocked public static userJourney = { moreScreenUnlock: 1, - personalLayoutUnlock: 5, + personalThemeUnlock: 5, historyLinkVisible: 10, deletePointsOfOthersUnlock: 20, tagsVisibleAt: 25, diff --git a/src/Models/ThemeConfig/Conversion/FixImages.ts b/src/Models/ThemeConfig/Conversion/FixImages.ts index 50c67153b..331e3d02e 100644 --- a/src/Models/ThemeConfig/Conversion/FixImages.ts +++ b/src/Models/ThemeConfig/Conversion/FixImages.ts @@ -1,5 +1,5 @@ import { Conversion, DesugaringStep } from "./Conversion" -import { LayoutConfigJson } from "../Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Json/ThemeConfigJson" import { Utils } from "../../../Utils" import metapaths from "../../../assets/schemas/layoutconfigmeta.json" import tagrenderingmetapaths from "../../../assets/schemas/questionabletagrenderingconfigmeta.json" @@ -9,7 +9,7 @@ import { parse as parse_html } from "node-html-parser" import { ConversionContext } from "./ConversionContext" export class ExtractImages extends Conversion< - LayoutConfigJson, + ThemeConfigJson, { path: string; context: string }[] > { private static readonly layoutMetaPaths = metapaths.filter((mp) => { @@ -109,7 +109,7 @@ export class ExtractImages extends Conversion< * */ convert( - json: LayoutConfigJson, + json: ThemeConfigJson, context: ConversionContext ): { path: string; context: string }[] { const allFoundImages: { path: string; context: string }[] = [] @@ -243,7 +243,7 @@ export class ExtractImages extends Conversion< } } -export class FixImages extends DesugaringStep { +export class FixImages extends DesugaringStep { private readonly _knownImages: Set constructor(knownImages: Set) { @@ -289,7 +289,7 @@ export class FixImages extends DesugaringStep { * fixed.layers[0]["pointRendering"][0].marker[0].icon // => "https://raw.githubusercontent.com/seppesantens/MapComplete-Themes/main/VerkeerdeBordenDatabank/TS_bolt.svg" * fixed.layers[0]["pointRendering"][0].iconBadges[0].then.mappings[0].then // => "https://raw.githubusercontent.com/seppesantens/MapComplete-Themes/main/VerkeerdeBordenDatabank/Something.svg" */ - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { let url: URL try { url = new URL(json.id) diff --git a/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts b/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts index 18c78ccf2..b7187a7c8 100644 --- a/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts +++ b/src/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts @@ -1,4 +1,4 @@ -import { LayoutConfigJson } from "../Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Json/ThemeConfigJson" import { Utils } from "../../../Utils" import LineRenderingConfigJson from "../Json/LineRenderingConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson" @@ -257,12 +257,12 @@ export class UpdateLegacyLayer extends DesugaringStep< } } -class UpdateLegacyTheme extends DesugaringStep { +class UpdateLegacyTheme extends DesugaringStep { constructor() { super("Small fixes in the theme config", ["roamingRenderings"], "UpdateLegacyTheme") } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { const oldThemeConfig = { ...json } if (oldThemeConfig.socialImage === "") { @@ -311,7 +311,7 @@ class UpdateLegacyTheme extends DesugaringStep { } } -export class FixLegacyTheme extends Fuse { +export class FixLegacyTheme extends Fuse { constructor() { super( "Fixes a legacy theme to the modern JSON format geared to humans. Syntactic sugars are kept (i.e. no tagRenderings are expandend, no dependencies are automatically gathered)", diff --git a/src/Models/ThemeConfig/Conversion/PrepareTheme.ts b/src/Models/ThemeConfig/Conversion/PrepareTheme.ts index 825f8c3db..21518a730 100644 --- a/src/Models/ThemeConfig/Conversion/PrepareTheme.ts +++ b/src/Models/ThemeConfig/Conversion/PrepareTheme.ts @@ -1,5 +1,5 @@ import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion" -import { LayoutConfigJson } from "../Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Json/ThemeConfigJson" import { PrepareLayer } from "./PrepareLayer" import { LayerConfigJson } from "../Json/LayerConfigJson" import { Utils } from "../../../Utils" @@ -165,7 +165,7 @@ class SubstituteLayer extends Conversion { +class AddDefaultLayers extends DesugaringStep { private readonly _state: DesugaringContext constructor(state: DesugaringContext) { @@ -177,7 +177,7 @@ class AddDefaultLayers extends DesugaringStep { this._state = state } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { const state = this._state json.layers = Utils.NoNull([...(json.layers ?? [])]) const alreadyLoaded = new Set(json.layers.map((l) => l["id"])) @@ -209,7 +209,7 @@ class AddDefaultLayers extends DesugaringStep { } } -class AddContextToTranslationsInLayout extends DesugaringStep { +class AddContextToTranslationsInLayout extends DesugaringStep { constructor() { super( "Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too", @@ -218,8 +218,8 @@ class AddContextToTranslationsInLayout extends DesugaringStep ) } - convert(json: LayoutConfigJson): LayoutConfigJson { - const conversion = new AddContextToTranslations("themes:") + convert(json: ThemeConfigJson): ThemeConfigJson { + const conversion = new AddContextToTranslations("themes:") // The context is used to generate the 'context' in the translation .It _must_ be `json.id` to correctly link into weblate return conversion.convert( json, @@ -228,7 +228,7 @@ class AddContextToTranslationsInLayout extends DesugaringStep } } -class ApplyOverrideAll extends DesugaringStep { +class ApplyOverrideAll extends DesugaringStep { constructor() { super( "Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards", @@ -237,7 +237,7 @@ class ApplyOverrideAll extends DesugaringStep { ) } - convert(json: LayoutConfigJson, ctx: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, ctx: ConversionContext): ThemeConfigJson { const overrideAll = json.overrideAll if (overrideAll === undefined) { return json @@ -278,7 +278,7 @@ class ApplyOverrideAll extends DesugaringStep { } } -class AddDependencyLayersToTheme extends DesugaringStep { +class AddDependencyLayersToTheme extends DesugaringStep { private readonly _state: DesugaringContext constructor(state: DesugaringContext) { @@ -390,7 +390,7 @@ class AddDependencyLayersToTheme extends DesugaringStep { return dependenciesToAdd } - convert(theme: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(theme: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { const state = this._state const allKnownLayers: Map = state.sharedLayers const knownTagRenderings: Map = state.tagRenderings @@ -428,7 +428,7 @@ class AddDependencyLayersToTheme extends DesugaringStep { } } -class PreparePersonalTheme extends DesugaringStep { +class PreparePersonalTheme extends DesugaringStep { private readonly _state: DesugaringContext constructor(state: DesugaringContext) { @@ -436,7 +436,7 @@ class PreparePersonalTheme extends DesugaringStep { this._state = state } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { if (json.id !== "personal") { return json } @@ -452,7 +452,7 @@ class PreparePersonalTheme extends DesugaringStep { } } -class WarnForUnsubstitutedLayersInTheme extends DesugaringStep { +class WarnForUnsubstitutedLayersInTheme extends DesugaringStep { constructor() { super( "Generates a warning if a theme uses an unsubstituted layer", @@ -461,7 +461,7 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep ) } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { if (json.hideFromOverview === true) { return json } @@ -503,7 +503,7 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep } } -class PostvalidateTheme extends DesugaringStep { +class PostvalidateTheme extends DesugaringStep { private readonly _state: DesugaringContext constructor(state: DesugaringContext) { @@ -511,7 +511,7 @@ class PostvalidateTheme extends DesugaringStep { this._state = state } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { for (const l of json.layers) { const layer = l const basedOn = layer["_basedOn"] @@ -582,7 +582,7 @@ class PostvalidateTheme extends DesugaringStep { } } -export class PrepareTheme extends Fuse { +export class PrepareTheme extends Fuse { private state: DesugaringContext constructor( @@ -616,7 +616,7 @@ export class PrepareTheme extends Fuse { this.state = state } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { const result = super.convert(json, context) if ((this.state.publicLayers?.size ?? 0) === 0) { // THis is a bootstrapping run, no need to already set this flag diff --git a/src/Models/ThemeConfig/Conversion/ValidateTheme.ts b/src/Models/ThemeConfig/Conversion/ValidateTheme.ts index d5aee78bb..dc89de029 100644 --- a/src/Models/ThemeConfig/Conversion/ValidateTheme.ts +++ b/src/Models/ThemeConfig/Conversion/ValidateTheme.ts @@ -1,13 +1,13 @@ import { DesugaringStep } from "./Conversion" -import { LayoutConfigJson } from "../Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Json/ThemeConfigJson" import { AvailableRasterLayers } from "../../RasterLayers" import { ExtractImages } from "./FixImages" import { ConversionContext } from "./ConversionContext" -import LayoutConfig from "../LayoutConfig" +import ThemeConfig from "../ThemeConfig" import { Utils } from "../../../Utils" import { DetectDuplicatePresets, DoesImageExist, ValidateLanguageCompleteness } from "./Validation" -export class ValidateTheme extends DesugaringStep { +export class ValidateTheme extends DesugaringStep { /** * The paths where this layer is originally saved. Triggers some extra checks * @private @@ -33,8 +33,8 @@ export class ValidateTheme extends DesugaringStep { } } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { - const theme = new LayoutConfig(json, this._isBuiltin) + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { + const theme = new ThemeConfig(json, this._isBuiltin) { // Legacy format checks if (this._isBuiltin) { diff --git a/src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers.ts b/src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers.ts index 556f3f37d..52b504d02 100644 --- a/src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers.ts +++ b/src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers.ts @@ -1,10 +1,10 @@ import { Bypass, Each, Fuse, On } from "./Conversion" -import { LayoutConfigJson } from "../Json/LayoutConfigJson" +import { ThemeConfigJson } from "../Json/ThemeConfigJson" import Constants from "../../Constants" import { DoesImageExist, ValidateLayerConfig } from "./Validation" import { ValidateTheme } from "./ValidateTheme" -export class ValidateThemeAndLayers extends Fuse { +export class ValidateThemeAndLayers extends Fuse { constructor( doesImageExist: DoesImageExist, path: string, diff --git a/src/Models/ThemeConfig/Conversion/Validation.ts b/src/Models/ThemeConfig/Conversion/Validation.ts index 6309d0866..dc0b55718 100644 --- a/src/Models/ThemeConfig/Conversion/Validation.ts +++ b/src/Models/ThemeConfig/Conversion/Validation.ts @@ -4,8 +4,8 @@ import LayerConfig from "../LayerConfig" import { Utils } from "../../../Utils" import Constants from "../../Constants" import { Translation } from "../../../UI/i18n/Translation" -import { LayoutConfigJson } from "../Json/LayoutConfigJson" -import LayoutConfig from "../LayoutConfig" +import { ThemeConfigJson } from "../Json/ThemeConfigJson" +import ThemeConfig from "../ThemeConfig" import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" import { TagUtils } from "../../../Logic/Tags/TagUtils" import { And } from "../../../Logic/Tags/And" @@ -23,7 +23,7 @@ import { PrevalidateLayer } from "./PrevalidateLayer" import { AvailableRasterLayers } from "../../RasterLayers" import { eliCategory } from "../../RasterLayerProperties" -export class ValidateLanguageCompleteness extends DesugaringStep { +export class ValidateLanguageCompleteness extends DesugaringStep { private readonly _languages: string[] constructor(...languages: string[]) { @@ -35,7 +35,7 @@ export class ValidateLanguageCompleteness extends DesugaringStep { this._languages = languages ?? ["en"] } - convert(obj: LayoutConfig, context: ConversionContext): LayoutConfig { + convert(obj: ThemeConfig, context: ConversionContext): ThemeConfig { const origLayers = obj.layers obj.layers = [...obj.layers].filter((l) => l["id"] !== "favourite") const translations = Translation.ExtractAllTranslationsFrom(obj) @@ -128,7 +128,7 @@ export class DoesImageExist extends DesugaringStep { } } -class OverrideShadowingCheck extends DesugaringStep { +class OverrideShadowingCheck extends DesugaringStep { constructor() { super( "Checks that an 'overrideAll' does not override a single override", @@ -137,7 +137,7 @@ class OverrideShadowingCheck extends DesugaringStep { ) } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { const overrideAll = json.overrideAll if (overrideAll === undefined) { return json @@ -170,12 +170,12 @@ class OverrideShadowingCheck extends DesugaringStep { } } -class MiscThemeChecks extends DesugaringStep { +class MiscThemeChecks extends DesugaringStep { constructor() { super("Miscelleanous checks on the theme", [], "MiscThemesChecks") } - convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson { + convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { if (json.id !== "personal" && (json.layers === undefined || json.layers.length === 0)) { context.err("The theme " + json.id + " has no 'layers' defined") } @@ -240,7 +240,7 @@ class MiscThemeChecks extends DesugaringStep { } } -export class PrevalidateTheme extends Fuse { +export class PrevalidateTheme extends Fuse { constructor() { super( "Various consistency checks on the raw JSON", @@ -905,7 +905,7 @@ export class ValidateFilter extends DesugaringStep { export class DetectDuplicateFilters extends DesugaringStep<{ layers: LayerConfigJson[] - themes: LayoutConfigJson[] + themes: ThemeConfigJson[] }> { constructor() { super( @@ -916,15 +916,15 @@ export class DetectDuplicateFilters extends DesugaringStep<{ } convert( - json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }, + json: { layers: LayerConfigJson[]; themes: ThemeConfigJson[] }, context: ConversionContext, - ): { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } { + ): { layers: LayerConfigJson[]; themes: ThemeConfigJson[] } { const { layers, themes } = json const perOsmTag = new Map< string, { layer: LayerConfigJson - layout: LayoutConfigJson | undefined + theme: ThemeConfigJson | undefined filter: FilterConfigJson }[] >() @@ -955,10 +955,10 @@ export class DetectDuplicateFilters extends DesugaringStep<{ return } let msg = "Possible duplicate filter: " + key - for (const { filter, layer, layout } of value) { + for (const { filter, layer, theme } of value) { let id = "" - if (layout !== undefined) { - id = layout.id + ":" + if (theme !== undefined) { + id = theme.id + ":" } msg += `\n - ${id}${layer.id}.${filter.id}` } @@ -977,11 +977,11 @@ export class DetectDuplicateFilters extends DesugaringStep<{ string, { layer: LayerConfigJson - layout: LayoutConfigJson | undefined + theme: ThemeConfigJson | undefined filter: FilterConfigJson }[] >, - layout?: LayoutConfigJson | undefined, + theme?: ThemeConfigJson | undefined, ): void { if (layer.filter === undefined || layer.filter === null) { return @@ -1009,14 +1009,14 @@ export class DetectDuplicateFilters extends DesugaringStep<{ perOsmTag.get(key).push({ layer, filter, - layout, + theme, }) } } } } -export class DetectDuplicatePresets extends DesugaringStep { +export class DetectDuplicatePresets extends DesugaringStep { constructor() { super( "Detects mappings which have identical (english) names or identical mappings.", @@ -1025,7 +1025,7 @@ export class DetectDuplicatePresets extends DesugaringStep { ) } - convert(json: LayoutConfig, context: ConversionContext): LayoutConfig { + convert(json: ThemeConfig, context: ConversionContext): ThemeConfig { const presets: PresetConfig[] = [].concat(...json.layers.map((l) => l.presets)) const enNames = presets.map((p) => p.title.textFor("en")) @@ -1074,7 +1074,7 @@ export class DetectDuplicatePresets extends DesugaringStep { } export class ValidateThemeEnsemble extends Conversion< - LayoutConfig[], + ThemeConfig[], Map< string, { @@ -1093,7 +1093,7 @@ export class ValidateThemeEnsemble extends Conversion< } convert( - json: LayoutConfig[], + json: ThemeConfig[], context: ConversionContext, ): Map< string, diff --git a/src/Models/ThemeConfig/FilterConfig.ts b/src/Models/ThemeConfig/FilterConfig.ts index 73eea0297..b44ff6558 100644 --- a/src/Models/ThemeConfig/FilterConfig.ts +++ b/src/Models/ThemeConfig/FilterConfig.ts @@ -62,7 +62,7 @@ export default class FilterConfig { const fields: { name: string; type: ValidatorType }[] = (option.fields ?? []).map((f, i) => { const type = f.type ?? "regex" if(Validators.availableTypes.indexOf(type) < 0){ - throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, Validators.availableTypes, x => x).slice(0, 3)}` + throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, >Validators.availableTypes, x => x).slice(0, 3)}` } // Type is validated against 'ValidatedTextField' in Validation.ts, in ValidateFilterConfig if (f.name === undefined || f.name === "" || f.name.match(/[a-z0-9_-]+/) == null) { diff --git a/src/Models/ThemeConfig/Json/LayoutConfigJson.ts b/src/Models/ThemeConfig/Json/ThemeConfigJson.ts similarity index 99% rename from src/Models/ThemeConfig/Json/LayoutConfigJson.ts rename to src/Models/ThemeConfig/Json/ThemeConfigJson.ts index b3449ad01..cbdeef07b 100644 --- a/src/Models/ThemeConfig/Json/LayoutConfigJson.ts +++ b/src/Models/ThemeConfig/Json/ThemeConfigJson.ts @@ -16,7 +16,7 @@ import { Translatable } from "./Translatable" * * General remark: a type (string | any) indicates either a fixed or a translatable string. */ -export interface LayoutConfigJson { +export interface ThemeConfigJson { /** * question: What is the id of this layout? * diff --git a/src/Models/ThemeConfig/LayoutConfig.ts b/src/Models/ThemeConfig/ThemeConfig.ts similarity index 96% rename from src/Models/ThemeConfig/LayoutConfig.ts rename to src/Models/ThemeConfig/ThemeConfig.ts index 2680a62af..b60375e12 100644 --- a/src/Models/ThemeConfig/LayoutConfig.ts +++ b/src/Models/ThemeConfig/ThemeConfig.ts @@ -1,5 +1,5 @@ import { Translation } from "../../UI/i18n/Translation" -import { LayoutConfigJson } from "./Json/LayoutConfigJson" +import { ThemeConfigJson } from "./Json/ThemeConfigJson" import LayerConfig from "./LayerConfig" import { LayerConfigJson } from "./Json/LayerConfigJson" import Constants from "../Constants" @@ -13,7 +13,7 @@ import { Translatable } from "./Json/Translatable" /** * Minimal information about a theme **/ -export class MinimalLayoutInformation { +export class MinimalThemeInformation { id: string icon: string title: Translatable @@ -27,7 +27,7 @@ export class MinimalLayoutInformation { /** * Minimal information about a theme **/ -export class LayoutInformation { +export class ThemeInformation { id: string icon: string title: Translatable | Translation @@ -39,7 +39,7 @@ export class LayoutInformation { } -export default class LayoutConfig implements LayoutInformation { +export default class ThemeConfig implements ThemeInformation { public static readonly defaultSocialImage = "assets/SocialImage.png" public readonly id: string public readonly credits?: string @@ -57,7 +57,6 @@ export default class LayoutConfig implements LayoutInformation { public readonly startZoom: number public readonly startLat: number public readonly startLon: number - public widenFactor: number public defaultBackgroundId?: string public layers: LayerConfig[] public tileLayerSources: (RasterLayerProperties & { defaultState?: true | boolean })[] @@ -92,11 +91,11 @@ export default class LayoutConfig implements LayoutInformation { public readonly definitionRaw?: string private readonly layersDict: Map - private readonly source: LayoutConfigJson + private readonly source: ThemeConfigJson public readonly enableCache: boolean constructor( - json: LayoutConfigJson, + json: ThemeConfigJson, official = true, options?: { definedAtUrl?: string @@ -167,7 +166,7 @@ export default class LayoutConfig implements LayoutInformation { ? undefined : new Translation(json.descriptionTail, "themes:" + context + ".descriptionTail") this.icon = json.icon - this.socialImage = json.socialImage ?? LayoutConfig.defaultSocialImage + this.socialImage = json.socialImage ?? ThemeConfig.defaultSocialImage if (this.socialImage === "") { if (official) { throw "Theme " + json.id + " has empty string as social image" @@ -176,7 +175,6 @@ export default class LayoutConfig implements LayoutInformation { this.startZoom = json.startZoom this.startLat = json.startLat this.startLon = json.startLon - this.widenFactor = 1.5 this.defaultBackgroundId = json.defaultBackgroundId this.tileLayerSources = json.tileLayerSources ?? [] diff --git a/src/Models/ThemeViewState.ts b/src/Models/ThemeViewState.ts index 933215c92..839b23b57 100644 --- a/src/Models/ThemeViewState.ts +++ b/src/Models/ThemeViewState.ts @@ -1,4 +1,4 @@ -import LayoutConfig from "./ThemeConfig/LayoutConfig" +import ThemeConfig from "./ThemeConfig/ThemeConfig" import { SpecialVisualizationState } from "../UI/SpecialVisualization" import { Changes } from "../Logic/Osm/Changes" import { Store, UIEventSource } from "../Logic/UIEventSource" @@ -18,7 +18,7 @@ import UserRelatedState from "../Logic/State/UserRelatedState" import LayerConfig from "./ThemeConfig/LayerConfig" import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler" import { AvailableRasterLayers, RasterLayerPolygon, RasterLayerUtils } from "./RasterLayers" -import LayoutSource from "../Logic/FeatureSource/Sources/LayoutSource" +import ThemeSource from "../Logic/FeatureSource/Sources/ThemeSource" import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSource" import FeaturePropertiesStore from "../Logic/FeatureSource/Actors/FeaturePropertiesStore" import PerLayerFeatureSourceSplitter from "../Logic/FeatureSource/PerLayerFeatureSourceSplitter" @@ -80,7 +80,7 @@ import { PanoramaxUploader } from "../Logic/ImageProviders/Panoramax" * It ties up all the needed elements and starts some actors. */ export default class ThemeViewState implements SpecialVisualizationState { - readonly layout: LayoutConfig + readonly theme: ThemeConfig readonly map: UIEventSource readonly changes: Changes readonly featureSwitches: FeatureSwitchState @@ -104,7 +104,7 @@ export default class ThemeViewState implements SpecialVisualizationState { readonly fullNodeDatabase?: FullNodeDatabaseSource readonly historicalUserLocations: WritableFeatureSource> - readonly indexedFeatures: IndexedFeatureSource & LayoutSource + readonly indexedFeatures: IndexedFeatureSource & ThemeSource readonly currentView: FeatureSource> readonly featuresInView: FeatureSource readonly favourites: FavouritesFeatureSource @@ -160,9 +160,9 @@ export default class ThemeViewState implements SpecialVisualizationState { */ public readonly featureSummary: SummaryTileSourceRewriter - constructor(layout: LayoutConfig, mvtAvailableLayers: Set) { + constructor(layout: ThemeConfig, mvtAvailableLayers: Set) { Utils.initDomPurify() - this.layout = layout + this.theme = layout this.featureSwitches = new FeatureSwitchState(layout) this.guistate = new MenuState( this.featureSwitches.featureSwitchWelcomeMessage.data, @@ -218,7 +218,7 @@ export default class ThemeViewState implements SpecialVisualizationState { { const overlayLayerStates = new Map }>() - for (const rasterInfo of this.layout.tileLayerSources) { + for (const rasterInfo of this.theme.tileLayerSources) { const isDisplayed = QueryParameters.GetBooleanQueryParameter( "overlay-" + rasterInfo.id, rasterInfo.defaultState ?? true, @@ -236,11 +236,11 @@ export default class ThemeViewState implements SpecialVisualizationState { * A bit tricky, as this is heavily intertwined with the 'changes'-element, which generates a stream of new and changed features too */ - if (this.layout.layers.some((l) => l._needsFullNodeDatabase)) { + if (this.theme.layers.some((l) => l._needsFullNodeDatabase)) { this.fullNodeDatabase = new FullNodeDatabaseSource() } - const layoutSource = new LayoutSource( + const layoutSource = new ThemeSource( layout.layers, this.featureSwitches, this.mapProperties, @@ -340,7 +340,7 @@ export default class ThemeViewState implements SpecialVisualizationState { }) this.lastClickObject = new LastClickFeatureSource( - this.layout, + this.theme, this.mapProperties.lastClickLocation, this.userRelatedState.addNewFeatureMode, ) @@ -414,7 +414,7 @@ export default class ThemeViewState implements SpecialVisualizationState { const storage = new SaveFeatureSourceToLocalStorage( this.osmConnection.Backend(), fs.layer.layerDef.id, - LayoutSource.fromCacheZoomLevel, + ThemeSource.fromCacheZoomLevel, fs, this.featureProperties, fs.layer.layerDef.maxAgeOfCache, @@ -509,7 +509,7 @@ export default class ThemeViewState implements SpecialVisualizationState { } }) - this.userRelatedState.markLayoutAsVisited(this.layout) + this.userRelatedState.markLayoutAsVisited(this.theme) this.selectedElement.addCallback((selected) => { if (selected === undefined) { @@ -517,8 +517,8 @@ export default class ThemeViewState implements SpecialVisualizationState { } }) - if (this.layout.customCss !== undefined && window.location.pathname.indexOf("theme") >= 0) { - Utils.LoadCustomCss(this.layout.customCss) + if (this.theme.customCss !== undefined && window.location.pathname.indexOf("theme") >= 0) { + Utils.LoadCustomCss(this.theme.customCss) } Hash.hash.addCallbackAndRunD((hash) => { @@ -738,11 +738,11 @@ export default class ThemeViewState implements SpecialVisualizationState { /** * MaxZoom for the summary layer */ - const normalLayers = this.layout.layers.filter(l => l.isNormal()) + const normalLayers = this.theme.layers.filter(l => l.isNormal()) const maxzoom = Math.min(...normalLayers.map((l) => l.minzoom)) - const layers = this.layout.layers.filter( + const layers = this.theme.layers.filter( (l) => Constants.priviliged_layers.indexOf(l.id) < 0 && l.source.geojsonSource === undefined && @@ -796,8 +796,8 @@ export default class ThemeViewState implements SpecialVisualizationState { this.closestFeatures.registerSource(specialLayers.favourite, "favourite") - if (this.layout?.lockLocation) { - const bbox = new BBox(this.layout.lockLocation) + if (this.theme?.lockLocation) { + const bbox = new BBox(this.theme.lockLocation) this.mapProperties.maxbounds.setData(bbox) ShowDataLayer.showRange( this.map, @@ -805,7 +805,7 @@ export default class ThemeViewState implements SpecialVisualizationState { this.featureSwitches.featureSwitchIsTesting, ) } - const currentViewLayer = this.layout.layers.find((l) => l.id === "current_view") + const currentViewLayer = this.theme.layers.find((l) => l.id === "current_view") if (currentViewLayer?.tagRenderings?.length > 0) { const params = MetaTagging.createExtraFuncParams(this) this.featureProperties.trackFeatureSource(specialLayers.current_view) @@ -814,7 +814,7 @@ export default class ThemeViewState implements SpecialVisualizationState { features, params, currentViewLayer, - this.layout, + this.theme, this.osmObjectDownloader, this.featureProperties, ) @@ -909,9 +909,9 @@ export default class ThemeViewState implements SpecialVisualizationState { */ private initActors() { - if (!this.layout.official) { + if (!this.theme.official) { // Add custom themes to the "visited custom themes" - const th = this.layout + const th = this.theme this.userRelatedState.addUnofficialTheme({ id: th.id, icon: th.icon, @@ -945,7 +945,7 @@ export default class ThemeViewState implements SpecialVisualizationState { this.selectedElement.addCallbackD(selected => { const [osm_type, osm_id] = selected.properties.id.split("/") const [lon, lat] = GeoOperations.centerpointCoordinates(selected) - const layer = this.layout.getMatchingLayer(selected.properties) + const layer = this.theme.getMatchingLayer(selected.properties) const nameOptions = [ selected?.properties?.name, @@ -987,7 +987,7 @@ export default class ThemeViewState implements SpecialVisualizationState { } /** - * Searches the appropriate layer - will first try if a special layer matches; if not, a normal layer will be used by delegating to the layout + * Searches the appropriate layer - will first try if a special layer matches; if not, a normal layer will be used by delegating to the theme */ public getMatchingLayer(properties: Record) { @@ -1002,15 +1002,15 @@ export default class ThemeViewState implements SpecialVisualizationState { return UserRelatedState.usersettingsConfig } if (id.startsWith(LastClickFeatureSource.newPointElementId)) { - return this.layout.layers.find((l) => l.id === "last_click") + return this.theme.layers.find((l) => l.id === "last_click") } if (id.startsWith("search_result")) { return GeocodingUtils.searchLayer } if (id === "location_track") { - return this.layout.layers.find((l) => l.id === "gps_track") + return this.theme.layers.find((l) => l.id === "gps_track") } - return this.layout.getMatchingLayer(properties) + return this.theme.getMatchingLayer(properties) } public async reportError(message: string | Error | XMLHttpRequest, extramessage: string = "") { @@ -1059,7 +1059,7 @@ export default class ThemeViewState implements SpecialVisualizationState { body: JSON.stringify({ stacktrace, message: "" + message, - layout: this.layout.id, + theme: this.theme.id, version: Constants.vNumber, language: this.userRelatedState.language.data, username: this.osmConnection.userDetails.data?.name, diff --git a/src/UI/AllThemesGui.svelte b/src/UI/AllThemesGui.svelte index ab6575b32..4a66b37c8 100644 --- a/src/UI/AllThemesGui.svelte +++ b/src/UI/AllThemesGui.svelte @@ -12,7 +12,7 @@ import Constants from "../Models/Constants" import { ImmutableStore, Store, Stores, UIEventSource } from "../Logic/UIEventSource" import ThemesList from "./BigComponents/ThemesList.svelte" - import { MinimalLayoutInformation } from "../Models/ThemeConfig/LayoutConfig" + import { MinimalThemeInformation } from "../Models/ThemeConfig/ThemeConfig" import Eye from "../assets/svg/Eye.svelte" import LoginButton from "./Base/LoginButton.svelte" import Mastodon from "../assets/svg/Mastodon.svelte" @@ -46,16 +46,16 @@ let searchIsFocused = new UIEventSource(true) - const officialThemes: MinimalLayoutInformation[] = ThemeSearch.officialThemes.themes.filter(th => th.hideFromOverview === false) - const hiddenThemes: MinimalLayoutInformation[] = ThemeSearch.officialThemes.themes.filter(th => th.hideFromOverview === true) - let visitedHiddenThemes: Store = UserRelatedState.initDiscoveredHiddenThemes(state.osmConnection) + const officialThemes: MinimalThemeInformation[] = ThemeSearch.officialThemes.themes.filter(th => th.hideFromOverview === false) + const hiddenThemes: MinimalThemeInformation[] = ThemeSearch.officialThemes.themes.filter(th => th.hideFromOverview === true) + let visitedHiddenThemes: Store = UserRelatedState.initDiscoveredHiddenThemes(state.osmConnection) .map((knownIds) => hiddenThemes.filter((theme) => knownIds.indexOf(theme.id) >= 0 || state.osmConnection.userDetails.data.name === "Pieter Vander Vennet" )) - const customThemes: Store = Stores.ListStabilized(state.installedUserThemes) + const customThemes: Store = Stores.ListStabilized(state.installedUserThemes) .mapD(stableIds => Utils.NoNullInplace(stableIds.map(id => state.getUnofficialTheme(id)))) - function filtered(themes: Store): Store { + function filtered(themes: Store): Store { return searchStable.map(search => { if (!search) { return themes.data @@ -74,9 +74,9 @@ } - let officialSearched : Store= filtered(new ImmutableStore(officialThemes)) - let hiddenSearched: Store = filtered(visitedHiddenThemes) - let customSearched: Store = filtered(customThemes) + let officialSearched : Store= filtered(new ImmutableStore(officialThemes)) + let hiddenSearched: Store = filtered(visitedHiddenThemes) + let customSearched: Store = filtered(customThemes) let searchIsFocussed = new UIEventSource(false) diff --git a/src/UI/BigComponents/CopyrightAllIcons.svelte b/src/UI/BigComponents/CopyrightAllIcons.svelte index 78dd6c129..a408bcfa2 100644 --- a/src/UI/BigComponents/CopyrightAllIcons.svelte +++ b/src/UI/BigComponents/CopyrightAllIcons.svelte @@ -6,7 +6,7 @@ export let state: SpecialVisualizationState - let layoutToUse = state.layout + let layoutToUse = state.theme let iconAttributions: string[] = layoutToUse.getUsedImages() const allLicenses = {} diff --git a/src/UI/BigComponents/CopyrightPanel.svelte b/src/UI/BigComponents/CopyrightPanel.svelte index 67410dba7..893b56882 100644 --- a/src/UI/BigComponents/CopyrightPanel.svelte +++ b/src/UI/BigComponents/CopyrightPanel.svelte @@ -18,7 +18,7 @@ export let state: SpecialVisualizationState const t = Translations.t.general.attribution - const layoutToUse = state.layout + const layoutToUse = state.theme let maintainer: Translation = undefined if (layoutToUse.credits !== undefined && layoutToUse.credits !== "") { @@ -122,7 +122,7 @@ {/if} {#if maintainer !== undefined}
- +
{/if} diff --git a/src/UI/BigComponents/ExtraLinkButton.svelte b/src/UI/BigComponents/ExtraLinkButton.svelte index eba6f3406..0c1c2bcba 100644 --- a/src/UI/BigComponents/ExtraLinkButton.svelte +++ b/src/UI/BigComponents/ExtraLinkButton.svelte @@ -9,8 +9,8 @@ import Icon from "../Map/Icon.svelte" export let state: SpecialVisualizationState - let theme = state.layout?.id ?? "" - let config: ExtraLinkConfig = state.layout.extraLink + let theme = state.theme?.id ?? "" + let config: ExtraLinkConfig = state.theme.extraLink let basepath = window.location.host let showWelcomeMessageSwitch = state.featureSwitches.featureSwitchWelcomeMessage const isIframe = Utils.isIframe @@ -42,7 +42,7 @@ {#if config.text} {:else} - + {/if} diff --git a/src/UI/BigComponents/FilterPage.svelte b/src/UI/BigComponents/FilterPage.svelte index fb3301c8d..693c6ad3d 100644 --- a/src/UI/BigComponents/FilterPage.svelte +++ b/src/UI/BigComponents/FilterPage.svelte @@ -14,7 +14,7 @@ export let state: ThemeViewState export let onlyLink: boolean - let layout = state.layout + let theme = state.theme let allEnabled: boolean let allDisabled: boolean @@ -70,7 +70,7 @@ - {#each layout.layers as layer} + {#each theme.layers as layer} {/each} - {#each layout.tileLayerSources as tilesource} + {#each theme.tileLayerSources as tilesource} usersettings, "usersettings", true) - let layout = state.layout + let theme = state.theme let featureSwitches = state.featureSwitches let showHome = featureSwitches.featureSwitchBackToThemeOverview let pg = state.guistate.pageStates @@ -108,7 +108,7 @@
- +
@@ -161,12 +161,12 @@ - + - - + + @@ -193,25 +193,25 @@ {/if} - {#if layout.official} + {#if theme.official} - + - + {/if} diff --git a/src/UI/BigComponents/ShareScreen.svelte b/src/UI/BigComponents/ShareScreen.svelte index 8c3160e66..e4c91b142 100644 --- a/src/UI/BigComponents/ShareScreen.svelte +++ b/src/UI/BigComponents/ShareScreen.svelte @@ -25,8 +25,8 @@ * In some cases (local deploys, custom themes), we need to set the URL to `/theme.html?layout=xyz` instead of `/xyz?...` * Note that the 'layout='-param will be included automatically */ - let needsThemeRedirect = url.port !== "" || url.hostname.match(/^[0-9]/) || !state.layout.official - let layoutId = state.layout.id + let needsThemeRedirect = url.port !== "" || url.hostname.match(/^[0-9]/) || !state.theme.official + let layoutId = state.theme.id let baseLink = `${url.protocol}//${url.host}/${needsThemeRedirect ? "theme.html" : layoutId}?` let showWelcomeMessage = true @@ -44,7 +44,7 @@ enableBackground: boolean, enableGeolocation: boolean ) { - const layout = state.layout + const layout = state.theme let excluded = Utils.NoNull([ showWelcomeMessage ? undefined : "fs-welcome-message", enableLogin ? undefined : "fs-enable-login", @@ -99,7 +99,7 @@ ${ enableGeolocation ? 'allow="geolocation"' : "" } width="100%" height="100%" style="min-width: 250px; min-height: 250px" - title="${state.layout.title?.txt ?? "MapComplete"} with MapComplete"> + title="${state.theme.title?.txt ?? "MapComplete"} with MapComplete"> ` Array.from(state.layerState.filteredLayers.values()).forEach((flayer) => @@ -163,7 +163,7 @@ state.guistate.filtersPanelIsOpened.set(true)} + on:click={() => state.guistate.pageStates.filter.set(true)} > diff --git a/src/UI/BigComponents/Summary.svelte b/src/UI/BigComponents/Summary.svelte index b1b765594..1b10aebee 100644 --- a/src/UI/BigComponents/Summary.svelte +++ b/src/UI/BigComponents/Summary.svelte @@ -10,7 +10,7 @@ export let i: number = undefined let id = feature.properties.id let tags = state.featureProperties.getStore(id) - let layer: LayerConfig = state.layout.getMatchingLayer(tags.data) + let layer: LayerConfig = state.theme.getMatchingLayer(tags.data) diff --git a/src/UI/BigComponents/ThemeButton.svelte b/src/UI/BigComponents/ThemeButton.svelte index 7acb3ad3a..5f06e68c6 100644 --- a/src/UI/BigComponents/ThemeButton.svelte +++ b/src/UI/BigComponents/ThemeButton.svelte @@ -1,12 +1,12 @@ diff --git a/src/UI/Popup/MarkAsFavouriteMini.svelte b/src/UI/Popup/MarkAsFavouriteMini.svelte index 3f9a5648f..67d4f1899 100644 --- a/src/UI/Popup/MarkAsFavouriteMini.svelte +++ b/src/UI/Popup/MarkAsFavouriteMini.svelte @@ -20,7 +20,7 @@ const t = Translations.t.favouritePoi function markFavourite(isFavourite: boolean) { - state.favourites.markAsFavourite(feature, layer.id, state.layout.id, tags, isFavourite) + state.favourites.markAsFavourite(feature, layer.id, state.theme.id, tags, isFavourite) } diff --git a/src/UI/Popup/MinimapViz.svelte b/src/UI/Popup/MinimapViz.svelte index 8cdba1440..e18a269e4 100644 --- a/src/UI/Popup/MinimapViz.svelte +++ b/src/UI/Popup/MinimapViz.svelte @@ -72,7 +72,7 @@ ShowDataLayer.showMultipleLayers( mlmap, new StaticFeatureSource(featuresToShow), - state.layout.layers, + state.theme.layers, { zoomToFeatures: true } ) diff --git a/src/UI/Popup/MoveWizardState.ts b/src/UI/Popup/MoveWizardState.ts index 23dbc8c97..c463b6747 100644 --- a/src/UI/Popup/MoveWizardState.ts +++ b/src/UI/Popup/MoveWizardState.ts @@ -94,7 +94,7 @@ export class MoveWizardState { const matchingPresets = this.layer.presets.filter(preset => preset.preciseInput.snapToLayers && new And(preset.tags).matchesProperties(tags)) const matchingPreset = matchingPresets.flatMap(pr => pr.preciseInput?.snapToLayers) for (const layerId of matchingPreset) { - const snapOntoLayer = this._state.layout.getLayer(layerId) + const snapOntoLayer = this._state.theme.getLayer(layerId) const text = t.reasons.reasonSnapTo.PartialSubsTr("name", snapOntoLayer.snapName) reasons.push({ text, @@ -133,7 +133,7 @@ export class MoveWizardState { snappedTo, { reason: reason.changesetCommentValue, - theme: state.layout.id, + theme: state.theme.id, }), ) featureToMove.properties._lat = loc.lat @@ -152,7 +152,7 @@ export class MoveWizardState { featureToMove.properties, { changeType: "relocated", - theme: state.layout.id, + theme: state.theme.id, }, ), ) diff --git a/src/UI/Popup/MultiApply.ts b/src/UI/Popup/MultiApply.ts index ca0a5382b..7ab22ee0c 100644 --- a/src/UI/Popup/MultiApply.ts +++ b/src/UI/Popup/MultiApply.ts @@ -64,7 +64,7 @@ class MultiApplyExecutor { const keysToChange = this.params.keysToApply const overwrite = this.params.overwrite const selfTags = this.params.tagsSource.data - const theme = this.params.state.layout.id + const theme = this.params.state.theme.id for (const id of featuresToChange) { const tagsToApply: Tag[] = [] const otherFeatureTags = allElements.getStore(id).data diff --git a/src/UI/Popup/Notes/CreateNewNote.svelte b/src/UI/Popup/Notes/CreateNewNote.svelte index 9bc1437ad..ab1a74c4a 100644 --- a/src/UI/Popup/Notes/CreateNewNote.svelte +++ b/src/UI/Popup/Notes/CreateNewNote.svelte @@ -47,7 +47,7 @@ return } const loc = coordinate.data - txt += "\n\n #MapComplete #" + state?.layout?.id + txt += "\n\n #MapComplete #" + state?.theme?.id const id = await state?.osmConnection?.openNote(loc.lat, loc.lon, txt) console.log("Created a note, got id", id) const feature = >{ diff --git a/src/UI/Popup/PlantNetDetectionViz.ts b/src/UI/Popup/PlantNetDetectionViz.ts index 101f37ec6..595a8262e 100644 --- a/src/UI/Popup/PlantNetDetectionViz.ts +++ b/src/UI/Popup/PlantNetDetectionViz.ts @@ -49,7 +49,7 @@ export class PlantNetDetectionViz implements SpecialVisualization { ]), tags.data, { - theme: state.layout.id, + theme: state.theme.id, changeType: "plantnet-ai-detection", } ) diff --git a/src/UI/Popup/QrCode.svelte b/src/UI/Popup/QrCode.svelte index ddaa095bf..f1c12d172 100644 --- a/src/UI/Popup/QrCode.svelte +++ b/src/UI/Popup/QrCode.svelte @@ -17,7 +17,7 @@ let [lon, lat] = GeoOperations.centerpointCoordinates(feature) const includeLayout = window.location.pathname.split("/").at(-1).startsWith("theme") - const layout = includeLayout ? "layout=" + state.layout.id + "&" : "" + const layout = includeLayout ? "layout=" + state.theme.id + "&" : "" let id: Store = tags.mapD((tags) => tags.id) let url = id.mapD( (id) => diff --git a/src/UI/Popup/ShareLinkViz.ts b/src/UI/Popup/ShareLinkViz.ts index f243c3cf8..123883c63 100644 --- a/src/UI/Popup/ShareLinkViz.ts +++ b/src/UI/Popup/ShareLinkViz.ts @@ -30,9 +30,9 @@ export class ShareLinkViz implements SpecialVisualization { const text = args[1] const generateShareData = () => { - const title = state?.layout?.title?.txt ?? "MapComplete" + const title = state?.theme?.title?.txt ?? "MapComplete" - let matchingLayer: LayerConfig = state?.layout?.getMatchingLayer(tagSource?.data) + let matchingLayer: LayerConfig = state?.theme?.getMatchingLayer(tagSource?.data) let name = matchingLayer?.title?.GetRenderValue(tagSource.data)?.Subs(tagSource.data)?.txt ?? tagSource.data?.name ?? @@ -49,7 +49,7 @@ export class ShareLinkViz implements SpecialVisualization { return { title: name, url: url, - text: state?.layout?.shortDescription?.txt ?? "MapComplete", + text: state?.theme?.shortDescription?.txt ?? "MapComplete", } } diff --git a/src/UI/Popup/SplitRoadWizard.svelte b/src/UI/Popup/SplitRoadWizard.svelte index ac0a705ed..48017e175 100644 --- a/src/UI/Popup/SplitRoadWizard.svelte +++ b/src/UI/Popup/SplitRoadWizard.svelte @@ -58,7 +58,7 @@ id, splitPoints.data.map((ff) => <[number, number]>(ff.geometry).coordinates), { - theme: state?.layout?.id, + theme: state?.theme?.id, }, 5 ) diff --git a/src/UI/Popup/TagApplyButton.ts b/src/UI/Popup/TagApplyButton.ts index c42d0debd..7389dd0de 100644 --- a/src/UI/Popup/TagApplyButton.ts +++ b/src/UI/Popup/TagApplyButton.ts @@ -144,7 +144,7 @@ export default class TagApplyButton implements AutoAction, SpecialVisualization new And(tagsToApply.data), tags.data, // We pass in the tags of the selected element, not the tags of the target element! { - theme: state.layout.id, + theme: state.theme.id, changeType: "answer", } ) diff --git a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte index 4d87e56cb..510a0a617 100644 --- a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte @@ -283,7 +283,7 @@ } dispatch("saved", { config, applied: selectedTags }) const change = new ChangeTagAction(tags.data.id, selectedTags, tags.data, { - theme: tags.data["_orig_theme"] ?? state.layout.id, + theme: tags.data["_orig_theme"] ?? state.theme.id, changeType: "answer", }) freeformInput.set(undefined) @@ -327,7 +327,7 @@ function clearAnswer() { const tagsToSet = settableKeys.data.map(k => new Tag(k, "")) const change = new ChangeTagAction(tags.data.id, new And(tagsToSet), tags.data, { - theme: tags.data["_orig_theme"] ?? state.layout.id, + theme: tags.data["_orig_theme"] ?? state.theme.id, changeType: "answer", }) freeformInput.set(undefined) diff --git a/src/UI/QueryParameterDocumentation.ts b/src/UI/QueryParameterDocumentation.ts index 37c3dc87f..f95ca4de0 100644 --- a/src/UI/QueryParameterDocumentation.ts +++ b/src/UI/QueryParameterDocumentation.ts @@ -5,7 +5,7 @@ import List from "./Base/List" import Translations from "./i18n/Translations" import { QueryParameters } from "../Logic/Web/QueryParameters" import FeatureSwitchState from "../Logic/State/FeatureSwitchState" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor" import MarkdownUtils from "../Utils/MarkdownUtils" @@ -27,7 +27,7 @@ export default class QueryParameterDocumentation { ] public static UrlParamDocs(): Map { - const dummyLayout = new LayoutConfig({ + const dummyLayout = new ThemeConfig({ id: ">theme<", title: { en: "" }, description: "A theme to generate docs with", diff --git a/src/UI/Search/GeocodeResult.svelte b/src/UI/Search/GeocodeResult.svelte index 5addea02c..d5add5893 100644 --- a/src/UI/Search/GeocodeResult.svelte +++ b/src/UI/Search/GeocodeResult.svelte @@ -20,7 +20,7 @@ let tags: UIEventSource> let descriptionTr: TagRenderingConfig = undefined if (entry.feature?.properties?.id) { - layer = state.layout.getMatchingLayer(entry.feature.properties) + layer = state.theme.getMatchingLayer(entry.feature.properties) tags = state.featureProperties.getStore(entry.feature.properties.id) descriptionTr = layer?.tagRenderings?.find(tr => tr.labels.indexOf("description") >= 0) } diff --git a/src/UI/Search/ThemeResult.svelte b/src/UI/Search/ThemeResult.svelte index 9e1f93127..c1d94aa5c 100644 --- a/src/UI/Search/ThemeResult.svelte +++ b/src/UI/Search/ThemeResult.svelte @@ -1,11 +1,11 @@ {#if entry} diff --git a/src/UI/Search/ThemeResults.svelte b/src/UI/Search/ThemeResults.svelte index 6b87516d9..5cb9d79b1 100644 --- a/src/UI/Search/ThemeResults.svelte +++ b/src/UI/Search/ThemeResults.svelte @@ -14,7 +14,7 @@ export let state: SpecialVisualizationState let searchTerm = state.searchState.searchTerm - let recentThemes = state.userRelatedState.recentlyVisitedThemes.value.map(themes => themes.filter(th => th !== state.layout.id).slice(0, 6)) + let recentThemes = state.userRelatedState.recentlyVisitedThemes.value.map(themes => themes.filter(th => th !== state.theme.id).slice(0, 6)) let themeResults = state.searchState.themeSuggestions const t =Translations.t.general.search diff --git a/src/UI/SpecialVisualization.ts b/src/UI/SpecialVisualization.ts index 561a349cb..2a9f6dabd 100644 --- a/src/UI/SpecialVisualization.ts +++ b/src/UI/SpecialVisualization.ts @@ -1,6 +1,6 @@ import { Store, UIEventSource } from "../Logic/UIEventSource" import BaseUIElement from "./BaseUIElement" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import { FeatureSource, IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource" import { OsmConnection } from "../Logic/Osm/OsmConnection" import { Changes } from "../Logic/Osm/Changes" @@ -19,7 +19,7 @@ import FavouritesFeatureSource from "../Logic/FeatureSource/Sources/FavouritesFe import { ProvidedImage } from "../Logic/ImageProviders/ImageProvider" import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler" import { SummaryTileSourceRewriter } from "../Logic/FeatureSource/TiledFeatureSource/SummaryTileSource" -import LayoutSource from "../Logic/FeatureSource/Sources/LayoutSource" +import ThemeSource from "../Logic/FeatureSource/Sources/ThemeSource" import { Map as MlMap } from "maplibre-gl" import ShowDataLayer from "./Map/ShowDataLayer" import { CombinedFetcher } from "../Logic/Web/NearbyImagesSearch" @@ -33,13 +33,13 @@ import FeaturePropertiesStore from "../Logic/FeatureSource/Actors/FeaturePropert */ export interface SpecialVisualizationState { readonly guistate: MenuState - readonly layout: LayoutConfig + readonly theme: ThemeConfig readonly featureSwitches: FeatureSwitchState readonly layerState: LayerState readonly featureProperties: FeaturePropertiesStore - readonly indexedFeatures: IndexedFeatureSource & LayoutSource + readonly indexedFeatures: IndexedFeatureSource & ThemeSource /** * Some features will create a new element that should be displayed. * These can be injected by appending them to this featuresource (and pinging it) diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index f79c117a3..5d848f48c 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -164,7 +164,7 @@ class StealViz implements SpecialVisualization { const tagRenderings: [LayerConfig, TagRenderingConfig][] = [] for (const layerAndTagRenderingId of layerAndtagRenderingIds.split(";")) { const [layerId, tagRenderingId] = layerAndTagRenderingId.trim().split(".") - const layer = state.layout.layers.find((l) => l.id === layerId) + const layer = state.theme.layers.find((l) => l.id === layerId) const tagRendering = layer.tagRenderings.find((tr) => tr.id === tagRenderingId) tagRenderings.push([layer, tagRendering]) } @@ -444,7 +444,7 @@ export default class SpecialVisualizations { Locale.showLinkToWeblate.map((showTranslations) => { const languages = showTranslations ? LanguageUtils.usedLanguagesSorted - : state.layout.language + : state.theme.language return new SvelteUIElement(LanguagePicker, { assignTo: state.userRelatedState.language, availableLanguages: languages, @@ -971,7 +971,7 @@ export default class SpecialVisualizations { return undefined } const allUnits: Unit[] = [].concat( - ...(state?.layout?.layers?.map((lyr) => lyr.units) ?? []) + ...(state?.theme?.layers?.map((lyr) => lyr.units) ?? []) ) const unit = allUnits.filter((unit) => unit.isApplicableToKey(key) @@ -1125,7 +1125,7 @@ export default class SpecialVisualizations { ) => new VariableUiElement( tagsSource.map((tags) => { - if (state.layout === undefined) { + if (state.theme === undefined) { return "" } const title = layer?.title?.GetRenderValue(tags) @@ -1276,7 +1276,7 @@ export default class SpecialVisualizations { constr: (state) => { return new Combine( - state.layout.layers + state.theme.layers .filter( (l) => l.name !== null && @@ -1995,7 +1995,7 @@ export default class SpecialVisualizations { layer: LayerConfig ): BaseUIElement { const translation = tagSource.map((tags) => { - const layer = state.layout.getMatchingLayer(tags) + const layer = state.theme.getMatchingLayer(tags) return layer?.getMostMatchingPreset(tags)?.description }) return new VariableUiElement(translation) diff --git a/src/UI/StatisticsGUI.ts b/src/UI/StatisticsGUI.ts index 297c95eb2..8051efdba 100644 --- a/src/UI/StatisticsGUI.ts +++ b/src/UI/StatisticsGUI.ts @@ -11,7 +11,7 @@ import BaseUIElement from "./BaseUIElement" import Title from "./Base/Title" import { FixedUiElement } from "./Base/FixedUiElement" import List from "./Base/List" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import ThemeConfig from "../Models/ThemeConfig/ThemeConfig" import mcChanges from "../../src/assets/generated/themes/mapcomplete-changes.json" import SvelteUIElement from "./Base/SvelteUIElement" import Filterview from "./BigComponents/Filterview.svelte" @@ -24,7 +24,7 @@ import { Feature } from "geojson" class StatsticsForOverviewFile extends Combine { constructor(homeUrl: string, paths: string[]) { paths = paths.filter((p) => !p.endsWith("file-overview.json")) - const layer = new LayoutConfig(mcChanges, true).layers[0] + const layer = new ThemeConfig(mcChanges, true).layers[0] const filteredLayer = new FilteredLayer(layer) const filterPanel = new Combine([ new Title("Filters"), diff --git a/src/UI/Studio/EditLayerState.ts b/src/UI/Studio/EditLayerState.ts index 33cde4885..df80ef7da 100644 --- a/src/UI/Studio/EditLayerState.ts +++ b/src/UI/Studio/EditLayerState.ts @@ -18,7 +18,7 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection" import { OsmTags } from "../../Models/OsmFeature" import { Feature, Point } from "geojson" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import { LayoutConfigJson } from "../../Models/ThemeConfig/Json/LayoutConfigJson" +import { ThemeConfigJson } from "../../Models/ThemeConfig/Json/ThemeConfigJson" import { PrepareTheme } from "../../Models/ThemeConfig/Conversion/PrepareTheme" import { ConversionContext } from "../../Models/ThemeConfig/Conversion/ConversionContext" import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource" @@ -334,7 +334,7 @@ export default class EditLayerState extends EditJsonState { return 0 } } - public readonly layout: { getMatchingLayer: (key: any) => LayerConfig } + public readonly theme: { getMatchingLayer: (key: any) => LayerConfig } public readonly featureSwitches: { featureSwitchIsDebugging: UIEventSource } @@ -359,7 +359,7 @@ export default class EditLayerState extends EditJsonState { options: { expertMode: UIEventSource } ) { super(schema, server, "layers", osmConnection, options) - this.layout = { + this.theme = { getMatchingLayer: () => { try { return new LayerConfig(this.configuration.data, "dynamic") @@ -458,7 +458,8 @@ export default class EditLayerState extends EditJsonState { } const state: DesugaringContext = { tagRenderings: sharedQuestions, - sharedLayers: layers + sharedLayers: layers, + tagRenderingOrder: [] } const prepare = this.buildValidation(state) const context = ConversionContext.construct([], ["prepare"]) @@ -472,7 +473,7 @@ export default class EditLayerState extends EditJsonState { } } -export class EditThemeState extends EditJsonState { +export class EditThemeState extends EditJsonState { constructor( schema: ConfigMeta[], server: StudioServer, @@ -483,7 +484,7 @@ export class EditThemeState extends EditJsonState { this.setupFixers() } - protected buildValidation(state: DesugaringContext): Conversion { + protected buildValidation(state: DesugaringContext): Conversion { return new Pipe( new PrevalidateTheme(), new Pipe( @@ -513,7 +514,7 @@ export class EditThemeState extends EditJsonState { }) } - protected async validate(configuration: Partial) { + protected async validate(configuration: Partial) { const layers = AllSharedLayers.getSharedLayersConfigs() for (const l of configuration.layers ?? []) { @@ -534,7 +535,8 @@ export class EditThemeState extends EditJsonState { } const state: DesugaringContext = { tagRenderings: sharedQuestions, - sharedLayers: layers + sharedLayers: layers, + tagRenderingOrder: [] } const prepare = this.buildValidation(state) const context = ConversionContext.construct([], ["prepare"]) @@ -542,7 +544,7 @@ export class EditThemeState extends EditJsonState { Utils.NoNullInplace(configuration.layers) } try { - prepare.convert(configuration, context) + prepare.convert(configuration, context) } catch (e) { console.error(e) context.err(e) diff --git a/src/UI/Studio/StudioServer.ts b/src/UI/Studio/StudioServer.ts index 216c22b18..bf6ad5ca2 100644 --- a/src/UI/Studio/StudioServer.ts +++ b/src/UI/Studio/StudioServer.ts @@ -2,7 +2,7 @@ import { Utils } from "../../Utils" import Constants from "../../Models/Constants" import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson" import { Store, UIEventSource } from "../../Logic/UIEventSource" -import { LayoutConfigJson } from "../../Models/ThemeConfig/Json/LayoutConfigJson" +import { ThemeConfigJson } from "../../Models/ThemeConfig/Json/ThemeConfigJson" /** * A small class wrapping around the Server API. @@ -71,12 +71,12 @@ export default class StudioServer { } async fetch(layerId: string, category: "layers", uid?: number): Promise - async fetch(layerId: string, category: "themes", uid?: number): Promise + async fetch(layerId: string, category: "themes", uid?: number): Promise async fetch( layerId: string, category: "layers" | "themes", uid?: number - ): Promise { + ): Promise { try { return await Utils.downloadJson(this.urlFor(layerId, category, uid)) } catch (e) { diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index f14ca14f8..e9b103de9 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -53,7 +53,7 @@ export let state: ThemeViewState - let layout = state.layout + let theme = state.theme let maplibremap: UIEventSource = state.map let state_selectedElement = state.selectedElement let selectedElement: UIEventSource = new UIEventSource(undefined) @@ -65,7 +65,7 @@ let gpsButtonAriaLabel = state.geolocation.geolocationState.gpsStateExplanation let debug = state.featureSwitches.featureSwitchIsDebugging let featureSwitches: FeatureSwitchState = state.featureSwitches - let currentViewLayer: LayerConfig = layout.layers.find((l) => l.id === "current_view") + let currentViewLayer: LayerConfig = theme.layers.find((l) => l.id === "current_view") let rasterLayer: Store = state.mapProperties.rasterLayer let currentZoom = state.mapProperties.zoom let showCrosshair = state.userRelatedState.showCrosshair @@ -213,7 +213,7 @@
- {#if $addNewFeatureMode.indexOf("button") >= 0 && ((state.layout.hasPresets() && state.layout.enableAddNewPoints) || state.layout.hasNoteLayer())} + {#if $addNewFeatureMode.indexOf("button") >= 0 && ((state.theme.hasPresets() && state.theme.enableAddNewPoints) || state.theme.hasNoteLayer())}