Move legacy theme handling into a rewritting class, various small fixes
This commit is contained in:
parent
4471319588
commit
c2682fc56d
8 changed files with 178 additions and 174 deletions
|
@ -10,6 +10,7 @@ import {UIEventSource} from "./UIEventSource";
|
|||
import {LocalStorageSource} from "./Web/LocalStorageSource";
|
||||
import LZString from "lz-string";
|
||||
import * as personal from "../assets/themes/personal/personal.json";
|
||||
import LegacyJsonConvert from "../Models/ThemeConfig/LegacyJsonConvert";
|
||||
|
||||
export default class DetermineLayout {
|
||||
|
||||
|
@ -74,6 +75,7 @@ export default class DetermineLayout {
|
|||
|
||||
const parsed = await Utils.downloadJson(link)
|
||||
console.log("Got ", parsed)
|
||||
LegacyJsonConvert.fixThemeConfig(parsed)
|
||||
try {
|
||||
parsed.id = link;
|
||||
return new LayoutConfig(parsed, false).patchImages(link, JSON.stringify(parsed));
|
||||
|
@ -136,6 +138,7 @@ export default class DetermineLayout {
|
|||
}
|
||||
}
|
||||
|
||||
LegacyJsonConvert.fixThemeConfig(json)
|
||||
const layoutToUse = new LayoutConfig(json, false);
|
||||
userLayoutParam.setData(layoutToUse.id);
|
||||
return [layoutToUse, btoa(Utils.MinifyJSON(JSON.stringify(json)))];
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {Translation} from "../../UI/i18n/Translation";
|
||||
import SourceConfig from "./SourceConfig";
|
||||
import TagRenderingConfig from "./TagRenderingConfig";
|
||||
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
||||
import PresetConfig from "./PresetConfig";
|
||||
import {LayerConfigJson} from "./Json/LayerConfigJson";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
|
@ -58,56 +57,43 @@ export default class LayerConfig extends WithContextLoader {
|
|||
context = context + "." + json.id;
|
||||
super(json, context)
|
||||
this.id = json.id;
|
||||
let legacy = undefined;
|
||||
if (json["overpassTags"] !== undefined) {
|
||||
// @ts-ignore
|
||||
legacy = TagUtils.Tag(json["overpassTags"], context + ".overpasstags");
|
||||
|
||||
if (json.source === undefined) {
|
||||
throw "Layer " + this.id + " does not define a source section ("+context+")"
|
||||
}
|
||||
|
||||
if (json.source !== undefined) {
|
||||
this.maxAgeOfCache = json.source.maxCacheAge ?? 24 * 60 * 60 * 30
|
||||
if (legacy !== undefined) {
|
||||
throw (
|
||||
context +
|
||||
"Both the legacy 'layer.overpasstags' and the new 'layer.source'-field are defined"
|
||||
);
|
||||
}
|
||||
if (json.source.osmTags === undefined) {
|
||||
throw "Layer " + this.id + " does not define a osmTags in the source section - these should always be present, even for geojson layers ("+context+")"
|
||||
|
||||
let osmTags: TagsFilter = legacy;
|
||||
if (json.source["osmTags"]) {
|
||||
osmTags = TagUtils.Tag(
|
||||
json.source["osmTags"],
|
||||
context + "source.osmTags"
|
||||
);
|
||||
}
|
||||
|
||||
if (json.source["geoJsonSource"] !== undefined) {
|
||||
throw context + "Use 'geoJson' instead of 'geoJsonSource'";
|
||||
}
|
||||
|
||||
if (json.source["geojson"] !== undefined) {
|
||||
throw context + "Use 'geoJson' instead of 'geojson' (the J is a capital letter)";
|
||||
}
|
||||
|
||||
this.source = new SourceConfig(
|
||||
{
|
||||
osmTags: osmTags,
|
||||
geojsonSource: json.source["geoJson"],
|
||||
geojsonSourceLevel: json.source["geoJsonZoomLevel"],
|
||||
overpassScript: json.source["overpassScript"],
|
||||
isOsmCache: json.source["isOsmCache"],
|
||||
mercatorCrs: json.source["mercatorCrs"]
|
||||
},
|
||||
json.id
|
||||
);
|
||||
}else if(legacy === undefined){
|
||||
throw "No valid source defined ("+context+")"
|
||||
} else {
|
||||
this.source = new SourceConfig({
|
||||
osmTags: legacy,
|
||||
});
|
||||
}
|
||||
|
||||
this.maxAgeOfCache = json.source.maxCacheAge ?? 24 * 60 * 60 * 30
|
||||
|
||||
const osmTags = TagUtils.Tag(
|
||||
json.source.osmTags,
|
||||
context + "source.osmTags"
|
||||
);
|
||||
|
||||
if (json.source["geoJsonSource"] !== undefined) {
|
||||
throw context + "Use 'geoJson' instead of 'geoJsonSource'";
|
||||
}
|
||||
|
||||
if (json.source["geojson"] !== undefined) {
|
||||
throw context + "Use 'geoJson' instead of 'geojson' (the J is a capital letter)";
|
||||
}
|
||||
|
||||
this.source = new SourceConfig(
|
||||
{
|
||||
osmTags: osmTags,
|
||||
geojsonSource: json.source["geoJson"],
|
||||
geojsonSourceLevel: json.source["geoJsonZoomLevel"],
|
||||
overpassScript: json.source["overpassScript"],
|
||||
isOsmCache: json.source["isOsmCache"],
|
||||
mercatorCrs: json.source["mercatorCrs"]
|
||||
},
|
||||
json.id
|
||||
);
|
||||
|
||||
|
||||
this.allowSplit = json.allowSplit ?? false;
|
||||
this.name = Translations.T(json.name, context + ".name");
|
||||
|
@ -284,11 +270,13 @@ export default class LayerConfig extends WithContextLoader {
|
|||
|
||||
const normalTagRenderings: (string | { builtin: string, override: any } | TagRenderingConfigJson)[] = []
|
||||
|
||||
|
||||
const renderingsToRewrite: ({ rewrite:{
|
||||
|
||||
const renderingsToRewrite: ({
|
||||
rewrite: {
|
||||
sourceString: string,
|
||||
into: string[]
|
||||
}, renderings: (string | { builtin: string, override: any } | TagRenderingConfigJson)[] })[] = []
|
||||
}, renderings: (string | { builtin: string, override: any } | TagRenderingConfigJson)[]
|
||||
})[] = []
|
||||
for (let i = 0; i < json.tagRenderings.length; i++) {
|
||||
const tr = json.tagRenderings[i];
|
||||
const rewriteDefined = tr["rewrite"] !== undefined
|
||||
|
@ -309,17 +297,17 @@ export default class LayerConfig extends WithContextLoader {
|
|||
|
||||
const allRenderings = this.ParseTagRenderings(normalTagRenderings, false);
|
||||
|
||||
if(renderingsToRewrite.length === 0){
|
||||
if (renderingsToRewrite.length === 0) {
|
||||
return allRenderings
|
||||
}
|
||||
|
||||
function prepConfig(keyToRewrite: string, target:string, tr: TagRenderingConfigJson){
|
||||
|
||||
function replaceRecursive(transl: string | any){
|
||||
if(typeof transl === "string"){
|
||||
|
||||
function prepConfig(keyToRewrite: string, target: string, tr: TagRenderingConfigJson) {
|
||||
|
||||
function replaceRecursive(transl: string | any) {
|
||||
if (typeof transl === "string") {
|
||||
return transl.replace(keyToRewrite, target)
|
||||
}
|
||||
if(transl.map !== undefined){
|
||||
if (transl.map !== undefined) {
|
||||
return transl.map(o => replaceRecursive(o))
|
||||
}
|
||||
transl = {...transl}
|
||||
|
@ -328,39 +316,39 @@ export default class LayerConfig extends WithContextLoader {
|
|||
}
|
||||
return transl
|
||||
}
|
||||
|
||||
|
||||
const orig = tr;
|
||||
tr = replaceRecursive(tr)
|
||||
|
||||
tr.id = target+"-"+orig.id
|
||||
|
||||
tr.id = target + "-" + orig.id
|
||||
tr.group = target
|
||||
return tr
|
||||
}
|
||||
|
||||
const rewriteGroups: Map<string, TagRenderingConfig[]> = new Map<string, TagRenderingConfig[]>()
|
||||
for (const rewriteGroup of renderingsToRewrite) {
|
||||
|
||||
|
||||
const tagRenderings = rewriteGroup.renderings
|
||||
const textToReplace = rewriteGroup.rewrite.sourceString
|
||||
const targets = rewriteGroup.rewrite.into
|
||||
for (const target of targets) {
|
||||
const parsedRenderings = this.ParseTagRenderings(tagRenderings, false, tr => prepConfig(textToReplace, target, tr))
|
||||
|
||||
if(!rewriteGroups.has(target)){
|
||||
|
||||
if (!rewriteGroups.has(target)) {
|
||||
rewriteGroups.set(target, [])
|
||||
}
|
||||
rewriteGroups.get(target).push(... parsedRenderings)
|
||||
rewriteGroups.get(target).push(...parsedRenderings)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
rewriteGroups.forEach((group, groupName) => {
|
||||
group.push(new TagRenderingConfig({
|
||||
id:"questions",
|
||||
group:groupName
|
||||
id: "questions",
|
||||
group: groupName
|
||||
}))
|
||||
})
|
||||
|
||||
|
||||
rewriteGroups.forEach(group => {
|
||||
allRenderings.push(...group)
|
||||
})
|
||||
|
|
108
Models/ThemeConfig/LegacyJsonConvert.ts
Normal file
108
Models/ThemeConfig/LegacyJsonConvert.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
import LineRenderingConfigJson from "./Json/LineRenderingConfigJson";
|
||||
|
||||
export default class LegacyJsonConvert {
|
||||
|
||||
/**
|
||||
* Updates the config file in-place
|
||||
* @param config
|
||||
* @private
|
||||
*/
|
||||
public static fixLayerConfig(config: any): void {
|
||||
if (config["overpassTags"]) {
|
||||
config.source = config.source ?? {}
|
||||
config.source.osmTags = config["overpassTags"]
|
||||
delete config["overpassTags"]
|
||||
}
|
||||
|
||||
if (config.tagRenderings !== undefined) {
|
||||
for (const tagRendering of config.tagRenderings) {
|
||||
if (tagRendering["#"] !== undefined) {
|
||||
tagRendering["id"] = tagRendering["#"]
|
||||
delete tagRendering["#"]
|
||||
}
|
||||
if (tagRendering["id"] === undefined) {
|
||||
if (tagRendering["freeform"]?.key !== undefined) {
|
||||
tagRendering["id"] = config.id + "-" + tagRendering["freeform"]["key"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.mapRendering === undefined && config.id !== "sidewalks") {
|
||||
// This is a legacy format, lets create a pointRendering
|
||||
let location: ("point" | "centroid")[] = ["point"]
|
||||
let wayHandling: number = config["wayHandling"] ?? 0
|
||||
if (wayHandling === 2) {
|
||||
location = ["point", "centroid"]
|
||||
}
|
||||
config.mapRendering = [
|
||||
{
|
||||
icon: config["icon"],
|
||||
iconBadges: config["iconOverlays"],
|
||||
label: config["label"],
|
||||
iconSize: config["iconSize"],
|
||||
location,
|
||||
rotation: config["rotation"]
|
||||
}
|
||||
]
|
||||
|
||||
if (wayHandling !== 1) {
|
||||
const lineRenderConfig = <LineRenderingConfigJson>{
|
||||
color: config["color"],
|
||||
width: config["width"],
|
||||
dashArray: config["dashArray"]
|
||||
}
|
||||
if (Object.keys(lineRenderConfig).length > 0) {
|
||||
config.mapRendering.push(lineRenderConfig)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete config["color"]
|
||||
delete config["width"]
|
||||
delete config["dashArray"]
|
||||
|
||||
delete config["icon"]
|
||||
delete config["iconOverlays"]
|
||||
delete config["label"]
|
||||
delete config["iconSize"]
|
||||
delete config["rotation"]
|
||||
delete config["wayHandling"]
|
||||
|
||||
}
|
||||
|
||||
for (const mapRenderingElement of config.mapRendering) {
|
||||
if (mapRenderingElement["iconOverlays"] !== undefined) {
|
||||
mapRenderingElement["iconBadges"] = mapRenderingElement["iconOverlays"]
|
||||
}
|
||||
for (const overlay of mapRenderingElement["iconBadges"] ?? []) {
|
||||
if (overlay["badge"] !== true) {
|
||||
console.log("Warning: non-overlay element for ", config.id)
|
||||
}
|
||||
delete overlay["badge"]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an old (parsed) JSON-config, will (in place) fix some issues
|
||||
* @param oldThemeConfig: the config to update to the latest format
|
||||
*/
|
||||
public static fixThemeConfig(oldThemeConfig: any): void {
|
||||
for (const layerConfig of oldThemeConfig.layers ?? []) {
|
||||
if (typeof layerConfig === "string" || layerConfig["builtin"] !== undefined) {
|
||||
continue
|
||||
}
|
||||
// @ts-ignore
|
||||
LegacyJsonConvert.fixLayerConfig(layerConfig)
|
||||
}
|
||||
|
||||
if (oldThemeConfig["roamingRenderings"] !== undefined && oldThemeConfig["roamingRenderings"].length == 0) {
|
||||
delete oldThemeConfig["roamingRenderings"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -90,8 +90,7 @@
|
|||
"id": "dispensing_dog_bags",
|
||||
"question": {
|
||||
"en": "Does this waste basket have a dispenser for dog excrement bags?",
|
||||
"nl": "Heeft deze vuilnisbak een verdeler voor hondenpoepzakjes?",
|
||||
"then": "Heeft deze vuilnisbak een verdeler voor hondenpoepzakjes?"
|
||||
"nl": "Heeft deze vuilnisbak een verdeler voor hondenpoepzakjes?"
|
||||
},
|
||||
"condition": {
|
||||
"or": [
|
||||
|
|
|
@ -555,6 +555,7 @@
|
|||
{
|
||||
"id": "GRB",
|
||||
"source": {
|
||||
"osmTags": "HUISNR~*",
|
||||
"geoJson": "https://betadata.grbosm.site/grb?bbox={x_min},{y_min},{x_max},{y_max}",
|
||||
"geoJsonZoomLevel": 18,
|
||||
"mercatorCrs": true,
|
||||
|
|
7
index.ts
7
index.ts
|
@ -1,7 +1,6 @@
|
|||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||
import {QueryParameters} from "./Logic/Web/QueryParameters";
|
||||
import Combine from "./UI/Base/Combine";
|
||||
import ValidatedTextField from "./UI/Input/ValidatedTextField";
|
||||
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
|
||||
import MinimapImplementation from "./UI/Base/MinimapImplementation";
|
||||
import CountryCoder from "latlon2country/index";
|
||||
|
@ -70,7 +69,6 @@ class Init {
|
|||
window.mapcomplete_state = State.state;
|
||||
new DefaultGUI(State.state, guiState)
|
||||
|
||||
|
||||
if (encoded !== undefined && encoded.length > 10) {
|
||||
// We save the layout to the user settings and local storage
|
||||
State.state.osmConnection.OnLoggedIn(() => {
|
||||
|
@ -78,13 +76,8 @@ class Init {
|
|||
.GetLongPreference("installed-theme-" + layoutToUse.id)
|
||||
.setData(encoded);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,9 @@ class TranslationPart {
|
|||
if (!translations.hasOwnProperty(translationsKey)) {
|
||||
continue;
|
||||
}
|
||||
if(translationsKey == "then"){
|
||||
throw "Suspicious translation at "+context
|
||||
}
|
||||
const v = translations[translationsKey]
|
||||
if (typeof (v) != "string") {
|
||||
console.error("Non-string object in translation while trying to add more translations to '", translationsKey, "': ", v)
|
||||
|
|
103
scripts/lint.ts
103
scripts/lint.ts
|
@ -1,114 +1,23 @@
|
|||
/*
|
||||
* This script reads all theme and layer files and reformats them inplace
|
||||
* Use with caution, make a commit beforehand!
|
||||
*/
|
||||
|
||||
|
||||
import ScriptUtils from "./ScriptUtils";
|
||||
import {writeFileSync} from "fs";
|
||||
import {LayerConfigJson} from "../Models/ThemeConfig/Json/LayerConfigJson";
|
||||
import LineRenderingConfigJson from "../Models/ThemeConfig/Json/LineRenderingConfigJson";
|
||||
import LegacyJsonConvert from "../Models/ThemeConfig/LegacyJsonConvert";
|
||||
|
||||
/**
|
||||
* In place fix
|
||||
/*
|
||||
* This script reads all theme and layer files and reformats them inplace
|
||||
* Use with caution, make a commit beforehand!
|
||||
*/
|
||||
function fixLayerConfig(config: LayerConfigJson): void {
|
||||
if(config["overpassTags"]){
|
||||
config.source.osmTags = config["overpassTags"]
|
||||
delete config["overpassTags"]
|
||||
}
|
||||
|
||||
if (config.tagRenderings !== undefined) {
|
||||
for (const tagRendering of config.tagRenderings) {
|
||||
if (tagRendering["#"] !== undefined) {
|
||||
tagRendering["id"] = tagRendering["#"]
|
||||
delete tagRendering["#"]
|
||||
}
|
||||
if (tagRendering["id"] === undefined) {
|
||||
if (tagRendering["freeform"]?.key !== undefined) {
|
||||
tagRendering["id"] = config.id + "-" + tagRendering["freeform"]["key"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.mapRendering === undefined && config.id !== "sidewalks") {
|
||||
// This is a legacy format, lets create a pointRendering
|
||||
let location: ("point" | "centroid")[] = ["point"]
|
||||
let wayHandling: number = config["wayHandling"] ?? 0
|
||||
if (wayHandling === 2) {
|
||||
location = ["point", "centroid"]
|
||||
}
|
||||
config.mapRendering = [
|
||||
{
|
||||
icon: config["icon"],
|
||||
iconBadges: config["iconOverlays"],
|
||||
label: config["label"],
|
||||
iconSize: config["iconSize"],
|
||||
location,
|
||||
rotation: config["rotation"]
|
||||
}
|
||||
]
|
||||
|
||||
if (wayHandling !== 1) {
|
||||
const lineRenderConfig = <LineRenderingConfigJson>{
|
||||
color: config["color"],
|
||||
width: config["width"],
|
||||
dashArray: config["dashArray"]
|
||||
}
|
||||
if (Object.keys(lineRenderConfig).length > 0) {
|
||||
config.mapRendering.push(lineRenderConfig)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete config["color"]
|
||||
delete config["width"]
|
||||
delete config["dashArray"]
|
||||
|
||||
delete config["icon"]
|
||||
delete config["iconOverlays"]
|
||||
delete config["label"]
|
||||
delete config["iconSize"]
|
||||
delete config["rotation"]
|
||||
delete config["wayHandling"]
|
||||
|
||||
}
|
||||
|
||||
for (const mapRenderingElement of config.mapRendering) {
|
||||
if (mapRenderingElement["iconOverlays"] !== undefined) {
|
||||
mapRenderingElement["iconBadges"] = mapRenderingElement["iconOverlays"]
|
||||
}
|
||||
for (const overlay of mapRenderingElement["iconBadges"] ?? []) {
|
||||
if (overlay["badge"] !== true) {
|
||||
console.log("Warning: non-overlay element for ", config.id)
|
||||
}
|
||||
delete overlay["badge"]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const layerFiles = ScriptUtils.getLayerFiles();
|
||||
for (const layerFile of layerFiles) {
|
||||
fixLayerConfig(layerFile.parsed)
|
||||
LegacyJsonConvert. fixLayerConfig(layerFile.parsed)
|
||||
writeFileSync(layerFile.path, JSON.stringify(layerFile.parsed, null, " "))
|
||||
}
|
||||
|
||||
const themeFiles = ScriptUtils.getThemeFiles()
|
||||
for (const themeFile of themeFiles) {
|
||||
for (const layerConfig of themeFile.parsed.layers ?? []) {
|
||||
if (typeof layerConfig === "string" || layerConfig["builtin"] !== undefined) {
|
||||
continue
|
||||
}
|
||||
// @ts-ignore
|
||||
fixLayerConfig(layerConfig)
|
||||
}
|
||||
|
||||
if (themeFile.parsed["roamingRenderings"] !== undefined && themeFile.parsed["roamingRenderings"].length == 0) {
|
||||
delete themeFile.parsed["roamingRenderings"]
|
||||
}
|
||||
|
||||
LegacyJsonConvert.fixThemeConfig(themeFile.parsed)
|
||||
writeFileSync(themeFile.path, JSON.stringify(themeFile.parsed, null, " "))
|
||||
}
|
||||
//*/
|
||||
|
|
Loading…
Reference in a new issue