More work on the custom theme generator, kindof works now

This commit is contained in:
Pieter Vander Vennet 2020-09-03 00:00:37 +02:00
parent 1fa6a8edfb
commit ee9c9e201f
24 changed files with 1192 additions and 2265 deletions

View file

@ -3,18 +3,9 @@ import {TabbedComponent} from "../Base/TabbedComponent";
import {SubtleButton} from "../Base/SubtleButton";
import {UIEventSource} from "../../Logic/UIEventSource";
import {LayoutConfigJson} from "../../Customizations/JSON/LayoutConfigJson";
import LayerPanel from "./LayerPanel";
import SingleSetting from "./SingleSetting";
import Combine from "../Base/Combine";
import {GenerateEmpty} from "./GenerateEmpty";
import PageSplit from "../Base/PageSplit";
import {VariableUiElement} from "../Base/VariableUIElement";
import HelpText from "../../Customizations/HelpText";
import {MultiTagInput} from "../Input/MultiTagInput";
import {FromJSON} from "../../Customizations/JSON/FromJSON";
import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson";
import {FixedUiElement} from "../Base/FixedUiElement";
import TagRenderingPanel from "./TagRenderingPanel";
import LayerPanelWithPreview from "./LayerPanelWithPreview";
export default class AllLayersPanel extends UIElement {
@ -42,72 +33,13 @@ export default class AllLayersPanel extends UIElement {
const layers = this._config.data.layers;
for (let i = 0; i < layers.length; i++) {
const currentlySelected = new UIEventSource<(SingleSetting<any>)>(undefined);
const layer = new LayerPanel(this._config, this.languages, i, currentlySelected);
const helpText = new HelpText(currentlySelected);
const previewTagInput = new MultiTagInput();
previewTagInput.GetValue().setData(["id=123456"]);
const previewTagValue = previewTagInput.GetValue().map(tags => {
const properties = {};
for (const str of tags) {
const tag = FromJSON.SimpleTag(str);
if (tag !== undefined) {
properties[tag.key] = tag.value;
}
}
return properties;
});
const preview = new VariableUiElement(layer.selectedTagRendering.map(
(tagRenderingPanel: TagRenderingPanel) => {
if (tagRenderingPanel === undefined) {
return "No tag rendering selected at the moment";
}
let es = tagRenderingPanel.GetValue();
let tagRenderingConfig: TagRenderingConfigJson = es.data;
let rendering: UIElement;
try {
rendering = FromJSON.TagRendering(tagRenderingConfig)
.construct({tags: previewTagValue})
} catch (e) {
console.error("User defined tag rendering incorrect:", e);
rendering = new FixedUiElement(e).SetClass("alert");
}
return new Combine([
"<h3>",
tagRenderingPanel.options.title ?? "Extra tag rendering",
"</h3>",
tagRenderingPanel.options.description ?? "This tag rendering will appear in the popup",
"<br/>",
rendering]).Render();
},
[this._config]
)).ListenTo(layer.selectedTagRendering);
tabs.push({
header: "<img src='./assets/bug.svg'>",
content:
new PageSplit(
layer.SetClass("scrollable"),
new Combine([
helpText,
"</br>",
"<h2>Testing tags</h2>",
previewTagInput,
"<h2>Tag Rendering preview</h2>",
preview
]), 60
)
});
content: new LayerPanelWithPreview(this._config, this.languages, i)});
}
tabs.push({
header: "<img src='./assets/add.svg'>",
header: "<img src='./assets/layersAdd.svg'>",
content: new Combine([
"<h2>Layer editor</h2>",
"In this tab page, you can add and edit the layers of the theme. Click the layers above or add a new layer to get started.",

View file

@ -11,6 +11,7 @@ export class GenerateEmpty {
overpassTags: {and: [""]},
title: undefined,
description: {},
tagRenderings: []
}
}
@ -47,10 +48,10 @@ export class GenerateEmpty {
socialImage: "",
layers: [{
id: "testlayer",
name: "Testing layer",
name: {en:"Testing layer"},
minzoom: 15,
overpassTags: {and: ["highway=residential"]},
title: "Some Title",
title: {},
description: {"en": "Some Description"},
icon: {render: {en: "./assets/pencil.svg"}},
width: {render: {en: "5"}},

View file

@ -11,11 +11,9 @@ import MultiLingualTextFields from "../Input/MultiLingualTextFields";
import {CheckBox} from "../Input/CheckBox";
import {AndOrTagInput} from "../Input/AndOrTagInput";
import TagRenderingPanel from "./TagRenderingPanel";
import {GenerateEmpty} from "./GenerateEmpty";
import {DropDown} from "../Input/DropDown";
import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson";
import {MultiInput} from "../Input/MultiInput";
import {Tag} from "../../Logic/Tags";
import {LayerConfigJson} from "../../Customizations/JSON/LayerConfigJson";
/**
@ -25,10 +23,12 @@ export default class LayerPanel extends UIElement {
private readonly _config: UIEventSource<LayoutConfigJson>;
private readonly settingsTable: UIElement;
private readonly renderingOptions: UIElement;
private readonly mapRendering: UIElement;
private readonly deleteButton: UIElement;
public readonly titleRendering: UIElement;
public readonly selectedTagRendering: UIEventSource<TagRenderingPanel>
= new UIEventSource<TagRenderingPanel>(undefined);
private tagRenderings: UIElement;
@ -39,7 +39,7 @@ export default class LayerPanel extends UIElement {
currentlySelected: UIEventSource<SingleSetting<any>>) {
super();
this._config = config;
this.renderingOptions = this.setupRenderOptions(config, languages, index, currentlySelected);
this.mapRendering = this.setupRenderOptions(config, languages, index, currentlySelected);
const actualDeleteButton = new SubtleButton(
"./assets/delete.svg",
@ -81,7 +81,7 @@ export default class LayerPanel extends UIElement {
this.settingsTable = new SettingsTable([
setting(TextField.StringInput(), "id", "Id", "An identifier for this layer<br/>This should be a simple, lowercase, human readable string that is used to identify the layer."),
setting(new MultiLingualTextFields(languages), "title", "Title", "The human-readable name of this layer<br/>Used in the layer control panel and the 'Personal theme'"),
setting(new MultiLingualTextFields(languages), "name", "Name", "The human-readable name of this layer<br/>Used in the layer control panel and the 'Personal theme'"),
setting(new MultiLingualTextFields(languages, true), "description", "Description", "A description for this layer.<br/>Shown in the layer selections and in the personal theme"),
setting(TextField.NumberInput("nat", n => n < 23), "minzoom", "Minimal zoom",
"The minimum zoomlevel needed to load and show this layer."),
@ -98,6 +98,16 @@ export default class LayerPanel extends UIElement {
currentlySelected);
const self = this;
const popupTitleRendering = new TagRenderingPanel(languages, currentlySelected, {
title: "Popup title",
description: "This is the rendering shown as title in the popup for this element",
disableQuestions: true
});
new SingleSetting(config, popupTitleRendering, ["layers", index, "title"], "Popup title", "This is the rendering shown as title in the popup");
this.titleRendering = popupTitleRendering;
this.registerTagRendering(popupTitleRendering);
const tagRenderings = new MultiInput<TagRenderingConfigJson>("Add a tag rendering/question",
() => ({}),
() => {
@ -192,10 +202,11 @@ export default class LayerPanel extends UIElement {
return new Combine([
"<h2>General layer settings</h2>",
this.settingsTable,
"<h2>Map rendering options</h2>",
this.renderingOptions,
"<h2>Tag rendering and questions</h2>",
"<h2>Popup contents</h2>",
this.titleRendering,
this.tagRenderings,
"<h2>Map rendering options</h2>",
this.mapRendering,
"<h2>Layer delete</h2>",
this.deleteButton
]).Render();

View file

@ -0,0 +1,62 @@
import {UIElement} from "../UIElement";
import {UIEventSource} from "../../Logic/UIEventSource";
import SingleSetting from "./SingleSetting";
import LayerPanel from "./LayerPanel";
import HelpText from "../../Customizations/HelpText";
import {MultiTagInput} from "../Input/MultiTagInput";
import {FromJSON} from "../../Customizations/JSON/FromJSON";
import {VariableUiElement} from "../Base/VariableUIElement";
import TagRenderingPanel from "./TagRenderingPanel";
import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson";
import {FixedUiElement} from "../Base/FixedUiElement";
import Combine from "../Base/Combine";
import PageSplit from "../Base/PageSplit";
import TagRenderingPreview from "./TagRenderingPreview";
export default class LayerPanelWithPreview extends UIElement{
private panel: UIElement;
constructor(config: UIEventSource<any>, languages: UIEventSource<string[]>, index: number) {
super();
const currentlySelected = new UIEventSource<(SingleSetting<any>)>(undefined);
const layer = new LayerPanel(config, languages, index, currentlySelected);
const helpText = new HelpText(currentlySelected);
const previewTagInput = new MultiTagInput();
previewTagInput.GetValue().setData(["id=123456"]);
const previewTagValue = previewTagInput.GetValue().map(tags => {
const properties = {};
for (const str of tags) {
const tag = FromJSON.SimpleTag(str);
if (tag !== undefined) {
properties[tag.key] = tag.value;
}
}
return properties;
});
const preview = new TagRenderingPreview(layer.selectedTagRendering, previewTagValue);
this.panel = new PageSplit(
layer.SetClass("scrollable"),
new Combine([
helpText,
"</br>",
"<h2>Testing tags</h2>",
previewTagInput,
"<h2>Tag Rendering preview</h2>",
preview
]), 60
);
}
InnerRender(): string {
return this.panel.Render();
}
}

View file

@ -56,7 +56,7 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs
"Only show this tag rendering if these tags matches. Optional field.<br/>Note that the Overpass-tags are already always included in this object"),
"<h3>Freeform key</h3>",
setting(TextField.KeyInput(), ["freeform", "key"], "Freeform key<br/>",
setting(TextField.KeyInput(true), ["freeform", "key"], "Freeform key<br/>",
"If specified, the rendering will search if this key is present." +
"If it is, the rendering above will be used to display the element.<br/>" +
"The rendering will go into question mode if <ul><li>this key is not present</li><li>No single mapping matches</li><li>A question is given</li>"),

View file

@ -1,15 +1,67 @@
import {UIElement} from "../UIElement";
import {UIEventSource} from "../../Logic/UIEventSource";
import TagRenderingPanel from "./TagRenderingPanel";
import {VariableUiElement} from "../Base/VariableUIElement";
import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson";
import {FromJSON} from "../../Customizations/JSON/FromJSON";
import {FixedUiElement} from "../Base/FixedUiElement";
import Combine from "../Base/Combine";
export default class TagRenderingPreview extends UIElement{
constructor(selectedTagRendering: UIEventSource<TagRenderingPanel>) {
export default class TagRenderingPreview extends UIElement {
private readonly previewTagValue: UIEventSource<any>;
private selectedTagRendering: UIEventSource<TagRenderingPanel>;
private panel: UIElement;
constructor(selectedTagRendering: UIEventSource<TagRenderingPanel>,
previewTagValue: UIEventSource<any>) {
super(selectedTagRendering);
this.selectedTagRendering = selectedTagRendering;
this.previewTagValue = previewTagValue;
this.panel = this.GetPanel(undefined);
const self = this;
this.selectedTagRendering.addCallback(trp => {
self.panel = self.GetPanel(trp);
self.Update();
})
}
private GetPanel(tagRenderingPanel: TagRenderingPanel): UIElement {
if (tagRenderingPanel === undefined) {
return new FixedUiElement("No tag rendering selected at the moment. Hover over a tag rendering to see what it looks like");
}
let es = tagRenderingPanel.GetValue();
let tagRenderingConfig: TagRenderingConfigJson = es.data;
let rendering: UIElement;
try {
rendering =
new VariableUiElement(es.map(tagRenderingConfig => {
const tr = FromJSON.TagRendering(tagRenderingConfig)
.construct({tags: this.previewTagValue});
return tr.Render();
}
));
} catch (e) {
console.error("User defined tag rendering incorrect:", e);
rendering = new FixedUiElement(e).SetClass("alert");
}
return new Combine([
"<h3>",
tagRenderingPanel.options.title ?? "Extra tag rendering",
"</h3>",
tagRenderingPanel.options.description ?? "This tag rendering will appear in the popup",
"<br/><br/>",
rendering]);
}
InnerRender(): string {
return "";
return this.panel.Render();
}
}