Add custom generator link in morescreen, fix #95
This commit is contained in:
parent
1625b21138
commit
5d1754bcd6
10 changed files with 147 additions and 30 deletions
|
@ -38,9 +38,6 @@ export class AllKnownLayouts {
|
||||||
new Smoothness(),
|
new Smoothness(),
|
||||||
new Groen(),
|
new Groen(),
|
||||||
|
|
||||||
/*
|
|
||||||
new Toilets(),
|
|
||||||
*/
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,17 +9,18 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi
|
||||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
import {TagDependantUIElementConstructor} from "../UIElementConstructor";
|
import {TagDependantUIElementConstructor} from "../UIElementConstructor";
|
||||||
import {Map} from "../Layers/Map";
|
import {Map} from "../Layers/Map";
|
||||||
|
import {UIElement} from "../../UI/UIElement";
|
||||||
|
|
||||||
|
|
||||||
export interface TagRenderingConfigJson {
|
export interface TagRenderingConfigJson {
|
||||||
// If this key is present, then...
|
// If this key is present, then...
|
||||||
key?: string,
|
key?: string,
|
||||||
// Use this string to render
|
// Use this string to render
|
||||||
render: string,
|
render?: string | any,
|
||||||
// One of string, int, nat, float, pfloat, email, phone. Default: string
|
// One of string, int, nat, float, pfloat, email, phone. Default: string
|
||||||
type?: string,
|
type?: string,
|
||||||
// If it is not known (and no mapping below matches), this question is asked; a textfield is inserted in the rendering above
|
// If it is not known (and no mapping below matches), this question is asked; a textfield is inserted in the rendering above
|
||||||
question?: string,
|
question?: string | any,
|
||||||
// If a value is added with the textfield, this extra tag is addded. Optional field
|
// If a value is added with the textfield, this extra tag is addded. Optional field
|
||||||
addExtraTags?: string | { k: string, v: string }[];
|
addExtraTags?: string | { k: string, v: string }[];
|
||||||
// Extra tags: rendering is only shown/asked if these tags are present
|
// Extra tags: rendering is only shown/asked if these tags are present
|
||||||
|
@ -29,7 +30,7 @@ export interface TagRenderingConfigJson {
|
||||||
mappings?:
|
mappings?:
|
||||||
{
|
{
|
||||||
if: string,
|
if: string,
|
||||||
then: string
|
then: string | any
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,23 +44,27 @@ export interface LayerConfigJson {
|
||||||
color?: TagRenderingConfigJson;
|
color?: TagRenderingConfigJson;
|
||||||
width?: TagRenderingConfigJson;
|
width?: TagRenderingConfigJson;
|
||||||
overpassTags: string | { k: string, v: string }[];
|
overpassTags: string | { k: string, v: string }[];
|
||||||
wayHandling: number,
|
wayHandling?: number,
|
||||||
presets: Preset[]
|
presets: {
|
||||||
,
|
tags: string,
|
||||||
|
title: string | any,
|
||||||
|
description?: string | any,
|
||||||
|
icon?: string
|
||||||
|
}[],
|
||||||
tagRenderings: TagRenderingConfigJson []
|
tagRenderings: TagRenderingConfigJson []
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LayoutConfigJson {
|
export interface LayoutConfigJson {
|
||||||
widenFactor: number;
|
widenFactor?: number;
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string | any;
|
||||||
description: string;
|
description: string | any;
|
||||||
maintainer: string;
|
maintainer: string;
|
||||||
language: string[];
|
language: string | string[];
|
||||||
layers: LayerConfigJson[],
|
layers: LayerConfigJson[],
|
||||||
startZoom: number;
|
startZoom: string | number;
|
||||||
startLat: number;
|
startLat: string | number;
|
||||||
startLon: number;
|
startLon: string | number;
|
||||||
/**
|
/**
|
||||||
* Either a URL or a base64 encoded value (which should include 'data:image/svg+xml;base64,'
|
* Either a URL or a base64 encoded value (which should include 'data:image/svg+xml;base64,'
|
||||||
*/
|
*/
|
||||||
|
@ -271,17 +276,19 @@ export class CustomLayoutFromJSON {
|
||||||
|
|
||||||
public static LayoutFromJSON(json: LayoutConfigJson) {
|
public static LayoutFromJSON(json: LayoutConfigJson) {
|
||||||
const t = CustomLayoutFromJSON.MaybeTranslation;
|
const t = CustomLayoutFromJSON.MaybeTranslation;
|
||||||
let languages = json.language;
|
let languages : string[] ;
|
||||||
if(typeof (json.language) === "string"){
|
if(typeof (json.language) === "string"){
|
||||||
languages = [json.language];
|
languages = [json.language];
|
||||||
|
}else{
|
||||||
|
languages = json.language
|
||||||
}
|
}
|
||||||
const layout = new Layout(json.name,
|
const layout = new Layout(json.name,
|
||||||
languages,
|
languages,
|
||||||
t(json.title),
|
t(json.title),
|
||||||
json.layers.map(CustomLayoutFromJSON.LayerFromJson),
|
json.layers.map(CustomLayoutFromJSON.LayerFromJson),
|
||||||
json.startZoom,
|
parseInt(""+json.startZoom),
|
||||||
json.startLat,
|
parseFloat(""+json.startLat),
|
||||||
json.startLon,
|
parseFloat(""+json.startLon),
|
||||||
new Combine(['<h3>', t(json.title), '</h3><br/>', t(json.description)])
|
new Combine(['<h3>', t(json.title), '</h3><br/>', t(json.description)])
|
||||||
);
|
);
|
||||||
layout.icon = json.icon;
|
layout.icon = json.icon;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {UIElement} from "../UI/UIElement";
|
||||||
import {TagDependantUIElementConstructor} from "./UIElementConstructor";
|
import {TagDependantUIElementConstructor} from "./UIElementConstructor";
|
||||||
import {TagRenderingOptions} from "./TagRenderingOptions";
|
import {TagRenderingOptions} from "./TagRenderingOptions";
|
||||||
import Translation from "../UI/i18n/Translation";
|
import Translation from "../UI/i18n/Translation";
|
||||||
import {LayerConfigJson} from "./JSON/CustomLayoutFromJSON";
|
import {LayerConfigJson, TagRenderingConfigJson} from "./JSON/CustomLayoutFromJSON";
|
||||||
|
|
||||||
export interface Preset {
|
export interface Preset {
|
||||||
tags: Tag[],
|
tags: Tag[],
|
||||||
|
@ -128,7 +128,7 @@ export class LayerDefinition {
|
||||||
this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT;
|
this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
ToJson() {
|
ToJson() {
|
||||||
|
|
||||||
function t(translation: string | Translation | UIElement) {
|
function t(translation: string | Translation | UIElement) {
|
||||||
|
@ -144,8 +144,16 @@ export class LayerDefinition {
|
||||||
return translation.InnerRender();
|
return translation.InnerRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tr(tagRendering : TagRenderingOptions) : TagRenderingConfigJson{
|
||||||
|
const o = tagRendering.options;
|
||||||
|
return {
|
||||||
|
key: o.freeform.key,
|
||||||
|
render: o.freeform.renderTemplate,
|
||||||
|
type: o.freeform.template.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const layerConfig /* : LayerConfigJson */= {
|
const layerConfig : LayerConfigJson = {
|
||||||
name: t(this.name),
|
name: t(this.name),
|
||||||
description: t(this.description),
|
description: t(this.description),
|
||||||
maxAllowedOverlapPercentage: this.maxAllowedOverlapPercentage,
|
maxAllowedOverlapPercentage: this.maxAllowedOverlapPercentage,
|
||||||
|
@ -161,5 +169,5 @@ export class LayerDefinition {
|
||||||
};
|
};
|
||||||
|
|
||||||
return JSON.stringify(layerConfig)
|
return JSON.stringify(layerConfig)
|
||||||
}
|
}*/
|
||||||
}
|
}
|
|
@ -227,7 +227,10 @@ export class FilteredLayer {
|
||||||
// We monky-patch the feature element with an update-style
|
// We monky-patch the feature element with an update-style
|
||||||
feature.updateStyle = () => {
|
feature.updateStyle = () => {
|
||||||
if (layer.setIcon) {
|
if (layer.setIcon) {
|
||||||
layer.setIcon(L.icon(self._style(feature.properties).icon))
|
const icon = self._style(feature.properties).icon;
|
||||||
|
if (icon.iconUrl) {
|
||||||
|
layer.setIcon(L.icon(icon))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self._geolayer.setStyle(function (featureX) {
|
self._geolayer.setStyle(function (featureX) {
|
||||||
const style = self._style(featureX.properties);
|
const style = self._style(featureX.properties);
|
||||||
|
|
2
State.ts
2
State.ts
|
@ -24,7 +24,7 @@ export class State {
|
||||||
// The singleton of the global state
|
// The singleton of the global state
|
||||||
public static state: State;
|
public static state: State;
|
||||||
|
|
||||||
public static vNumber = "0.0.5h";
|
public static vNumber = "0.0.6";
|
||||||
|
|
||||||
// The user journey states thresholds when a new feature gets unlocked
|
// The user journey states thresholds when a new feature gets unlocked
|
||||||
public static userJourney = {
|
public static userJourney = {
|
||||||
|
|
|
@ -395,6 +395,18 @@ class LayerGenerator extends UIElement {
|
||||||
});
|
});
|
||||||
self.CreateElements(fullConfig, layerConfig);
|
self.CreateElements(fullConfig, layerConfig);
|
||||||
self.Update();
|
self.Update();
|
||||||
|
}),
|
||||||
|
|
||||||
|
new Button("Remove this layer", () => {
|
||||||
|
const layers = fullConfig.data.layers;
|
||||||
|
for (let i = 0; i < layers.length; i++) {
|
||||||
|
if(layers[i] === layerConfig){
|
||||||
|
layers.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.Update();
|
||||||
|
pingThemeObject();
|
||||||
})
|
})
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -469,7 +481,7 @@ class AllLayerComponent extends UIElement {
|
||||||
minzoom: 12,
|
minzoom: 12,
|
||||||
overpassTags: "",
|
overpassTags: "",
|
||||||
wayHandling: LayerDefinition.WAYHANDLING_CENTER_AND_WAY,
|
wayHandling: LayerDefinition.WAYHANDLING_CENTER_AND_WAY,
|
||||||
presets: [{}],
|
presets: [],
|
||||||
tagRenderings: []
|
tagRenderings: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Combine from "./Base/Combine";
|
||||||
import {SubtleButton} from "./Base/SubtleButton";
|
import {SubtleButton} from "./Base/SubtleButton";
|
||||||
import {State} from "../State";
|
import {State} from "../State";
|
||||||
import {CustomLayout} from "../Logic/CustomLayers";
|
import {CustomLayout} from "../Logic/CustomLayers";
|
||||||
|
import {VariableUiElement} from "./Base/VariableUIElement";
|
||||||
|
|
||||||
|
|
||||||
export class MoreScreen extends UIElement {
|
export class MoreScreen extends UIElement {
|
||||||
|
@ -20,6 +21,19 @@ export class MoreScreen extends UIElement {
|
||||||
const tr = Translations.t.general.morescreen;
|
const tr = Translations.t.general.morescreen;
|
||||||
|
|
||||||
const els: UIElement[] = []
|
const els: UIElement[] = []
|
||||||
|
|
||||||
|
els.push(new VariableUiElement(
|
||||||
|
State.state.osmConnection.userDetails.map(userDetails => {
|
||||||
|
if (userDetails.csCount < State.userJourney.themeGeneratorUnlock) {
|
||||||
|
return tr.requestATheme.Render();
|
||||||
|
}
|
||||||
|
return new SubtleButton("./assets/pencil.svg", tr.createYourOwnTheme, {
|
||||||
|
url: "https://pietervdvn.github.io/MapComplete/customGenerator.html",
|
||||||
|
newTab: false
|
||||||
|
}).Render();
|
||||||
|
})
|
||||||
|
));
|
||||||
|
|
||||||
for (const k in AllKnownLayouts.allSets) {
|
for (const k in AllKnownLayouts.allSets) {
|
||||||
const layout = AllKnownLayouts.allSets[k]
|
const layout = AllKnownLayouts.allSets[k]
|
||||||
if (layout.hideFromOverview && State.state.osmConnection.userDetails.data.name !== "Pieter Vander Vennet") {
|
if (layout.hideFromOverview && State.state.osmConnection.userDetails.data.name !== "Pieter Vander Vennet") {
|
||||||
|
@ -28,6 +42,7 @@ export class MoreScreen extends UIElement {
|
||||||
if (layout.name === State.state.layoutToUse.data.name) {
|
if (layout.name === State.state.layoutToUse.data.name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout.name === CustomLayout.NAME) {
|
if (layout.name === CustomLayout.NAME) {
|
||||||
if (!State.state.osmConnection.userDetails.data.loggedIn) {
|
if (!State.state.osmConnection.userDetails.data.loggedIn) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -60,7 +75,6 @@ export class MoreScreen extends UIElement {
|
||||||
|
|
||||||
return new VerticalCombine([
|
return new VerticalCombine([
|
||||||
tr.intro,
|
tr.intro,
|
||||||
tr.requestATheme,
|
|
||||||
new VerticalCombine(els),
|
new VerticalCombine(els),
|
||||||
tr.streetcomplete
|
tr.streetcomplete
|
||||||
]).Render();
|
]).Render();
|
||||||
|
|
|
@ -901,6 +901,9 @@ export default class Translations {
|
||||||
en: "Another, similar application is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
|
en: "Another, similar application is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
|
||||||
fr: "Une autre application similaire est <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
|
fr: "Une autre application similaire est <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
|
||||||
nl: "Een andere, gelijkaardige Android-applicatie is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>"
|
nl: "Een andere, gelijkaardige Android-applicatie is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>"
|
||||||
|
}),
|
||||||
|
createYourOwnTheme: new T({
|
||||||
|
en: "Create your own MapComplete theme from scratch"
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
readYourMessages: new T({
|
readYourMessages: new T({
|
||||||
|
|
72
assets/statue.svg
Normal file
72
assets/statue.svg
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
viewBox="0 0 64 64"
|
||||||
|
height="64"
|
||||||
|
width="64"
|
||||||
|
id="svg109"
|
||||||
|
version="1.1"
|
||||||
|
sodipodi:docname="Statue.svg"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="1013"
|
||||||
|
id="namedview6"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="5.9599"
|
||||||
|
inkscape:cx="18.575009"
|
||||||
|
inkscape:cy="24.82515"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer2" />
|
||||||
|
<metadata
|
||||||
|
id="metadata115">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs113" />
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="icon">
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="background">
|
||||||
|
<circle
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.484;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path824"
|
||||||
|
cx="32.215305"
|
||||||
|
cy="32.12027"
|
||||||
|
r="31.87973" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
id="rect4517-0"
|
||||||
|
d="m 31.580949,1.8448297 c -2.450028,0 -4.438737,1.9887079 -4.438737,4.4387347 0,2.4500309 1.988708,4.4303956 4.438737,4.4303956 2.450028,0 4.438737,-1.9803647 4.438737,-4.4303956 0,-2.4500268 -1.988708,-4.4387347 -4.438737,-4.4387347 z M 27.142212,13.675897 c -1.559562,0 -2.953595,1.417115 -2.953595,2.953595 0,2.957448 5.172963,11.883099 5.172964,14.79301 v 8.86913 h 4.438736 v -8.86913 c 0,-2.85233 5.172964,-11.835562 5.172964,-14.79301 0,-1.636599 -1.323142,-2.953595 -2.953595,-2.953595 z m -8.376864,30.887602 v 4.271867 H 44.39655 v -4.271867 z m 4.271867,8.543734 v 8.543734 h 17.087468 v -8.543734 z"
|
||||||
|
style="opacity:1;fill:#734a08;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:9.03008842;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -54,7 +54,8 @@
|
||||||
"title": {
|
"title": {
|
||||||
"en": "Bookcase",
|
"en": "Bookcase",
|
||||||
"nl": "Boekenruilkast"
|
"nl": "Boekenruilkast"
|
||||||
}
|
},
|
||||||
|
"tags": "amenity=public_bookcase"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tagRenderings": [
|
"tagRenderings": [
|
||||||
|
|
Loading…
Reference in a new issue