forked from MapComplete/MapComplete
Studio: studio now supports loading self-made layers in themes
This commit is contained in:
parent
9716bc5425
commit
28bf8cca9f
24 changed files with 826 additions and 464 deletions
|
@ -17,12 +17,13 @@ import questions from "../assets/generated/layers/questions.json"
|
|||
import {
|
||||
DoesImageExist,
|
||||
PrevalidateTheme,
|
||||
ValidateThemeAndLayers,
|
||||
ValidateThemeAndLayers
|
||||
} from "../Models/ThemeConfig/Conversion/Validation"
|
||||
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"
|
||||
|
||||
export default class DetermineLayout {
|
||||
private static readonly _knownImages = new Set(Array.from(licenses).map((l) => l.path))
|
||||
|
@ -31,6 +32,7 @@ export default class DetermineLayout {
|
|||
"false",
|
||||
"If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: \n\n- The hash of the URL contains a base64-encoded .json-file containing the theme definition\n- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator\n- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme"
|
||||
)
|
||||
|
||||
public static getCustomDefinition(): string {
|
||||
const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data)
|
||||
|
||||
|
@ -53,6 +55,25 @@ export default class DetermineLayout {
|
|||
return undefined
|
||||
}
|
||||
|
||||
private static async expandRemoteLayers(layoutConfig: LayoutConfigJson): Promise<LayoutConfigJson> {
|
||||
for (let i = 0; i < layoutConfig.layers.length; i++) {
|
||||
const l = layoutConfig.layers[i]
|
||||
if (typeof l !== "string") {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
new URL(l)
|
||||
console.log("Downloading remote layer " + l)
|
||||
const layerConfig = <LayerConfigJson>await Utils.downloadJson(l)
|
||||
layoutConfig.layers[i] = layerConfig
|
||||
} catch (_) {
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
return layoutConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correct layout for this website
|
||||
*/
|
||||
|
@ -65,7 +86,7 @@ export default class DetermineLayout {
|
|||
|
||||
if (layoutFromBase64 !== "false") {
|
||||
// We have to load something from the hash (or from disk)
|
||||
return DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam)
|
||||
return await DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam)
|
||||
}
|
||||
|
||||
let layoutId: string = undefined
|
||||
|
@ -90,7 +111,7 @@ export default class DetermineLayout {
|
|||
return layout
|
||||
}
|
||||
|
||||
public static LoadLayoutFromHash(userLayoutParam: UIEventSource<string>): LayoutConfig | null {
|
||||
public static async LoadLayoutFromHash(userLayoutParam: UIEventSource<string>): Promise<LayoutConfig | null> {
|
||||
let hash = location.hash.substr(1)
|
||||
let json: any
|
||||
|
||||
|
@ -118,6 +139,8 @@ export default class DetermineLayout {
|
|||
json = JSON.parse(Utils.UnMinify(LZString.decompressFromBase64(hash)))
|
||||
}
|
||||
|
||||
json = await this.expandRemoteLayers(json)
|
||||
|
||||
const layoutToUse = DetermineLayout.prepCustomTheme(json)
|
||||
userLayoutParam.setData(layoutToUse.id)
|
||||
return layoutToUse
|
||||
|
@ -148,11 +171,11 @@ export default class DetermineLayout {
|
|||
id: json.id,
|
||||
description: json.description,
|
||||
descriptionTail: {
|
||||
en: "<div class='alert'>Layer only mode.</div> The loaded custom theme actually isn't a custom theme, but only contains a layer.",
|
||||
en: "<div class='alert'>Layer only mode.</div> The loaded custom theme actually isn't a custom theme, but only contains a layer."
|
||||
},
|
||||
icon,
|
||||
title: json.name,
|
||||
layers: [json],
|
||||
layers: [json]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +187,7 @@ export default class DetermineLayout {
|
|||
const convertState: DesugaringContext = {
|
||||
tagRenderings: DetermineLayout.getSharedTagRenderings(),
|
||||
sharedLayers: knownLayersDict,
|
||||
publicLayers: new Set<string>(),
|
||||
publicLayers: new Set<string>()
|
||||
}
|
||||
json = new FixLegacyTheme().convertStrict(json)
|
||||
const raw = json
|
||||
|
@ -188,7 +211,7 @@ export default class DetermineLayout {
|
|||
}
|
||||
return new LayoutConfig(json, false, {
|
||||
definitionRaw: JSON.stringify(raw, null, " "),
|
||||
definedAtUrl: sourceUrl,
|
||||
definedAtUrl: sourceUrl
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -199,13 +222,14 @@ export default class DetermineLayout {
|
|||
"maindiv"
|
||||
)
|
||||
|
||||
let parsed = await Utils.downloadJson(link)
|
||||
let parsed = <LayoutConfigJson>await Utils.downloadJson(link)
|
||||
let forcedId = parsed.id
|
||||
const url = new URL(link)
|
||||
if (!(url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
|
||||
forcedId = link
|
||||
}
|
||||
console.log("Loaded remote link:", link)
|
||||
parsed = await this.expandRemoteLayers(parsed)
|
||||
return DetermineLayout.prepCustomTheme(parsed, link, forcedId)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue