forked from MapComplete/MapComplete
Add minimap baseElement; add this as special rendering, add minimap beneath direction input element
This commit is contained in:
parent
89df28ae06
commit
eba1772ab9
16 changed files with 411 additions and 153 deletions
|
@ -352,6 +352,11 @@ export class InitUiElements {
|
||||||
|
|
||||||
State.state.backgroundLayer = State.state.backgroundLayerId
|
State.state.backgroundLayer = State.state.backgroundLayerId
|
||||||
.map((selectedId: string) => {
|
.map((selectedId: string) => {
|
||||||
|
if(selectedId === undefined){
|
||||||
|
return AvailableBaseLayers.osmCarto
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const available = State.state.availableBackgroundLayers.data;
|
const available = State.state.availableBackgroundLayers.data;
|
||||||
for (const layer of available) {
|
for (const layer of available) {
|
||||||
if (layer.id === selectedId) {
|
if (layer.id === selectedId) {
|
||||||
|
|
|
@ -14,18 +14,19 @@ import {Utils} from "../../Utils";
|
||||||
export default class AvailableBaseLayers {
|
export default class AvailableBaseLayers {
|
||||||
|
|
||||||
|
|
||||||
public static osmCarto: BaseLayer =
|
public static osmCarto: BaseLayer =
|
||||||
{
|
{
|
||||||
id: "osm",
|
id: "osm",
|
||||||
name: "OpenStreetMap",
|
name: "OpenStreetMap",
|
||||||
layer: AvailableBaseLayers.CreateBackgroundLayer("osm", "OpenStreetMap",
|
layer: () => AvailableBaseLayers.CreateBackgroundLayer("osm", "OpenStreetMap",
|
||||||
"https://tile.openstreetmap.org/{z}/{x}/{y}.png", "OpenStreetMap", "https://openStreetMap.org/copyright",
|
"https://tile.openstreetmap.org/{z}/{x}/{y}.png", "OpenStreetMap", "https://openStreetMap.org/copyright",
|
||||||
19,
|
19,
|
||||||
false, false),
|
false, false),
|
||||||
feature: null,
|
feature: null,
|
||||||
max_zoom: 19,
|
max_zoom: 19,
|
||||||
min_zoom: 0
|
min_zoom: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex());
|
public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex());
|
||||||
|
@ -123,7 +124,7 @@ export default class AvailableBaseLayers {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const leafletLayer = AvailableBaseLayers.CreateBackgroundLayer(
|
const leafletLayer: () => TileLayer = () => AvailableBaseLayers.CreateBackgroundLayer(
|
||||||
props.id,
|
props.id,
|
||||||
props.name,
|
props.name,
|
||||||
props.url,
|
props.url,
|
||||||
|
@ -150,10 +151,10 @@ export default class AvailableBaseLayers {
|
||||||
private static LoadProviderIndex(): BaseLayer[] {
|
private static LoadProviderIndex(): BaseLayer[] {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
X; // Import X to make sure the namespace is not optimized away
|
X; // Import X to make sure the namespace is not optimized away
|
||||||
function l(id: string, name: string) {
|
function l(id: string, name: string) : BaseLayer{
|
||||||
try {
|
try {
|
||||||
const layer: any = L.tileLayer.provider(id, undefined);
|
const layer: any = () => L.tileLayer.provider(id, undefined);
|
||||||
return {
|
const baseLayer : BaseLayer = {
|
||||||
feature: null,
|
feature: null,
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -161,6 +162,7 @@ export default class AvailableBaseLayers {
|
||||||
min_zoom: layer.minzoom,
|
min_zoom: layer.minzoom,
|
||||||
max_zoom: layer.maxzoom
|
max_zoom: layer.maxzoom
|
||||||
}
|
}
|
||||||
|
return baseLayer
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Could not find provided layer", name, e);
|
console.error("Could not find provided layer", name, e);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {TileLayer} from "leaflet";
|
||||||
export default interface BaseLayer {
|
export default interface BaseLayer {
|
||||||
id: string,
|
id: string,
|
||||||
name: string,
|
name: string,
|
||||||
layer: TileLayer,
|
layer: () => TileLayer,
|
||||||
max_zoom: number,
|
max_zoom: number,
|
||||||
min_zoom: number;
|
min_zoom: number;
|
||||||
feature: any,
|
feature: any,
|
||||||
|
|
19
Svg.ts
19
Svg.ts
|
@ -104,11 +104,26 @@ export default class Svg {
|
||||||
public static direction_svg() { return new Img(Svg.direction, true);}
|
public static direction_svg() { return new Img(Svg.direction, true);}
|
||||||
public static direction_ui() { return new FixedUiElement(Svg.direction_img);}
|
public static direction_ui() { return new FixedUiElement(Svg.direction_img);}
|
||||||
|
|
||||||
public static direction_gradient = " <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:xlink=\"http://www.w3.org/1999/xlink\" id=\"svg8\" version=\"1.1\" viewBox=\"0 0 100 100\" height=\"100\" width=\"100\"> <metadata id=\"metadata8\"> <rdf:RDF> <cc:Work rdf:about=\"\"> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" /> </cc:Work> </rdf:RDF> </metadata> <defs id=\"defs6\"> <linearGradient id=\"linearGradient820\"> <stop style=\"stop-color:#000000;stop-opacity:1;\" offset=\"0\" id=\"innercolor\" /> <stop style=\"stop-color:#000000;stop-opacity:0\" offset=\"1\" id=\"outercolor\" /> </linearGradient> <radialGradient xlink:href=\"#linearGradient820\" id=\"radialGradient828\" cx=\"49.787739\" cy=\"53.828533\" fx=\"49.787739\" fy=\"53.828533\" r=\"28.883806\" gradientTransform=\"matrix(1.5439431,-0.01852438,0.02075364,1.7297431,-27.986574,-42.187244)\" gradientUnits=\"userSpaceOnUse\" /> </defs> <path id=\"path821\" d=\"M 50,50 21.042889,9.3993342 C 36.191421,-2.001434 60.726552,-3.6768009 78.8105,9.1490935 Z\" style=\"fill:url(#radialGradient828);fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" /> </svg> "
|
public static direction_gradient = " <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:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" version=\"1.0\" width=\"860.50732pt\" height=\"860.50732pt\" viewBox=\"0 0 860.50732 860.50732\" preserveAspectRatio=\"xMidYMid meet\" id=\"svg14\" sodipodi:docname=\"direction_gradient.svg\" inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\"> <defs id=\"defs18\"> <linearGradient inkscape:collect=\"always\" id=\"linearGradient832\"> <stop style=\"stop-color:#000000;stop-opacity:1;\" offset=\"0\" id=\"stop828\" /> <stop style=\"stop-color:#000000;stop-opacity:0;\" offset=\"1\" id=\"stop830\" /> </linearGradient> <radialGradient inkscape:collect=\"always\" xlink:href=\"#linearGradient832\" id=\"radialGradient838\" cx=\"430.25363\" cy=\"519.61188\" fx=\"430.25363\" fy=\"519.61188\" r=\"305.54589\" gradientTransform=\"matrix(0.95288409,-0.94890664,0.94542304,0.94938587,-470.98122,345.21193)\" gradientUnits=\"userSpaceOnUse\" /> </defs> <sodipodi:namedview pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1\" objecttolerance=\"10\" gridtolerance=\"10\" guidetolerance=\"10\" inkscape:pageopacity=\"0\" inkscape:pageshadow=\"2\" inkscape:window-width=\"1920\" inkscape:window-height=\"999\" id=\"namedview16\" showgrid=\"false\" showguides=\"true\" inkscape:guide-bbox=\"true\" inkscape:zoom=\"0.70710678\" inkscape:cx=\"279.00239\" inkscape:cy=\"856.75313\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg14\"> <sodipodi:guide position=\"430.25363,862.49682\" orientation=\"1,0\" id=\"guide832\" inkscape:locked=\"false\" /> <sodipodi:guide position=\"-42.427977,430.25368\" orientation=\"0,1\" id=\"guide834\" inkscape:locked=\"false\" /> <sodipodi:guide position=\"398.27788,720.18823\" orientation=\"0,1\" id=\"guide840\" inkscape:locked=\"false\" /> </sodipodi:namedview> <metadata id=\"metadata2\"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <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 /> </cc:Work> </rdf:RDF> </metadata> <path style=\"fill:url(#radialGradient838);fill-opacity:1;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"M 735.79979,124.70799 C 654.79116,43.598883 544.88842,-2.0206645 430.25389,-2.121103 315.61937,-2.0206592 205.71663,43.598888 124.70801,124.70799 l 305.54588,305.54589 z\" id=\"path836\" inkscape:connector-curvature=\"0\" sodipodi:nodetypes=\"ccccc\" /> </svg> "
|
||||||
public static direction_gradient_img = Img.AsImageElement(Svg.direction_gradient)
|
public static direction_gradient_img = Img.AsImageElement(Svg.direction_gradient)
|
||||||
public static direction_gradient_svg() { return new Img(Svg.direction_gradient, true);}
|
public static direction_gradient_svg() { return new Img(Svg.direction_gradient, true);}
|
||||||
public static direction_gradient_ui() { return new FixedUiElement(Svg.direction_gradient_img);}
|
public static direction_gradient_ui() { return new FixedUiElement(Svg.direction_gradient_img);}
|
||||||
|
|
||||||
|
public static direction_masked = " <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\" version=\"1.0\" width=\"860.50732pt\" height=\"860.50732pt\" viewBox=\"0 0 860.50732 860.50732\" preserveAspectRatio=\"xMidYMid meet\" id=\"svg14\" sodipodi:docname=\"direction_masked.svg\" inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\"> <defs id=\"defs18\" /> <sodipodi:namedview pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1\" objecttolerance=\"10\" gridtolerance=\"10\" guidetolerance=\"10\" inkscape:pageopacity=\"0\" inkscape:pageshadow=\"2\" inkscape:window-width=\"1920\" inkscape:window-height=\"999\" id=\"namedview16\" showgrid=\"false\" showguides=\"true\" inkscape:guide-bbox=\"true\" inkscape:zoom=\"0.70710678\" inkscape:cx=\"418.71218\" inkscape:cy=\"725.43016\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg14\"> <sodipodi:guide position=\"430.25363,862.49682\" orientation=\"1,0\" id=\"guide832\" inkscape:locked=\"false\" /> <sodipodi:guide position=\"-42.427977,430.25368\" orientation=\"0,1\" id=\"guide834\" inkscape:locked=\"false\" /> </sodipodi:namedview> <metadata id=\"metadata2\"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <rdf:RDF> <cc:Work rdf:about=\"\"> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" /> </cc:Work> </rdf:RDF> </metadata> <path style=\"fill:#000000;fill-opacity:0.39163497;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"M 124.70776,124.7084 A 432.375,432.375 0 0 0 -2.121338,430.25429 432.375,432.375 0 0 0 430.25366,862.62929 432.375,432.375 0 0 0 862.62866,430.25429 432.375,432.375 0 0 0 735.79811,124.70986 L 430.25366,430.25429 Z\" id=\"path836\" inkscape:connector-curvature=\"0\" /> </svg> "
|
||||||
|
public static direction_masked_img = Img.AsImageElement(Svg.direction_masked)
|
||||||
|
public static direction_masked_svg() { return new Img(Svg.direction_masked, true);}
|
||||||
|
public static direction_masked_ui() { return new FixedUiElement(Svg.direction_masked_img);}
|
||||||
|
|
||||||
|
public static direction_outline = " <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\" version=\"1.0\" width=\"860.50732pt\" height=\"860.50732pt\" viewBox=\"0 0 860.50732 860.50732\" preserveAspectRatio=\"xMidYMid meet\" id=\"svg14\" sodipodi:docname=\"direction_outline.svg\" inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\"> <defs id=\"defs18\" /> <sodipodi:namedview pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1\" objecttolerance=\"10\" gridtolerance=\"10\" guidetolerance=\"10\" inkscape:pageopacity=\"0\" inkscape:pageshadow=\"2\" inkscape:window-width=\"1920\" inkscape:window-height=\"999\" id=\"namedview16\" showgrid=\"false\" showguides=\"true\" inkscape:guide-bbox=\"true\" inkscape:zoom=\"0.35355339\" inkscape:cx=\"72.756921\" inkscape:cy=\"792.67347\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg14\"> <sodipodi:guide position=\"430.25363,862.49682\" orientation=\"1,0\" id=\"guide832\" inkscape:locked=\"false\" /> <sodipodi:guide position=\"-42.427977,430.25368\" orientation=\"0,1\" id=\"guide834\" inkscape:locked=\"false\" /> </sodipodi:namedview> <metadata id=\"metadata2\"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <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> <path style=\"fill:#000000;fill-opacity:0.39163501;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"M 735.79979,124.70799 C 654.79116,43.598883 544.88842,-2.0206645 430.25389,-2.121103 315.61937,-2.0206592 205.71663,43.598888 124.70801,124.70799 l 305.54588,305.54589 z\" id=\"path836\" inkscape:connector-curvature=\"0\" sodipodi:nodetypes=\"ccccc\" /> </svg> "
|
||||||
|
public static direction_outline_img = Img.AsImageElement(Svg.direction_outline)
|
||||||
|
public static direction_outline_svg() { return new Img(Svg.direction_outline, true);}
|
||||||
|
public static direction_outline_ui() { return new FixedUiElement(Svg.direction_outline_img);}
|
||||||
|
|
||||||
|
public static direction_stroke = " <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\" version=\"1.0\" width=\"860.50732pt\" height=\"860.50732pt\" viewBox=\"0 0 860.50732 860.50732\" preserveAspectRatio=\"xMidYMid meet\" id=\"svg14\" sodipodi:docname=\"direction_stroke.svg\" inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\"> <defs id=\"defs18\" /> <sodipodi:namedview pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1\" objecttolerance=\"10\" gridtolerance=\"10\" guidetolerance=\"10\" inkscape:pageopacity=\"0\" inkscape:pageshadow=\"2\" inkscape:window-width=\"1920\" inkscape:window-height=\"999\" id=\"namedview16\" showgrid=\"false\" showguides=\"true\" inkscape:guide-bbox=\"true\" inkscape:zoom=\"1\" inkscape:cx=\"482.69344\" inkscape:cy=\"931.96415\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg14\"> <sodipodi:guide position=\"430.25363,862.49682\" orientation=\"1,0\" id=\"guide832\" inkscape:locked=\"false\" /> <sodipodi:guide position=\"-42.427977,430.25368\" orientation=\"0,1\" id=\"guide834\" inkscape:locked=\"false\" /> </sodipodi:namedview> <metadata id=\"metadata2\"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <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 /> </cc:Work> </rdf:RDF> </metadata> <path style=\"fill: none !important;fill-opacity:0.39163501;stroke:#000000;stroke-width:3.74999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"M 735.79953,129.20772 C 654.7909,48.098612 544.88816,2.4790648 430.25363,2.3786263 315.61911,2.4790701 205.71637,48.098617 124.70775,129.20772 l 305.54588,305.54589 z\" id=\"path836\" inkscape:connector-curvature=\"0\" sodipodi:nodetypes=\"ccccc\" /> </svg> "
|
||||||
|
public static direction_stroke_img = Img.AsImageElement(Svg.direction_stroke)
|
||||||
|
public static direction_stroke_svg() { return new Img(Svg.direction_stroke, true);}
|
||||||
|
public static direction_stroke_ui() { return new FixedUiElement(Svg.direction_stroke_img);}
|
||||||
|
|
||||||
public static down = " <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\" version=\"1.0\" width=\"700\" height=\"700\" id=\"svg6\" sodipodi:docname=\"down.svg\" inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"> <metadata id=\"metadata12\"> <rdf:RDF> <cc:Work rdf:about=\"\"> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" /> </cc:Work> </rdf:RDF> </metadata> <defs id=\"defs10\" /> <sodipodi:namedview pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1\" objecttolerance=\"10\" gridtolerance=\"10\" guidetolerance=\"10\" inkscape:pageopacity=\"0\" inkscape:pageshadow=\"2\" inkscape:window-width=\"1920\" inkscape:window-height=\"1001\" id=\"namedview8\" showgrid=\"false\" inkscape:zoom=\"0.33714286\" inkscape:cx=\"477.91309\" inkscape:cy=\"350\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg6\" /> <g transform=\"rotate(-180,342.1439,335.17672)\" id=\"g4\"> <path d=\"m -20,670.71582 c 0,-1.85843 349.99229,-699.98853 350.57213,-699.28671 1.94549,2.35478 350.06752,699.46087 349.427,699.71927 -0.41837,0.16878 -79.29725,-33.69092 -175.2864,-75.24377 l -174.52574,-75.55065 -174.2421,75.53732 c -95.83317,41.54551 -174.625237,75.5373 -175.093498,75.5373 -0.46826,0 -0.851382,-0.32075 -0.851382,-0.71276 z\" style=\"fill:#00ff00;stroke:none\" id=\"path2\" inkscape:connector-curvature=\"0\" /> </g> </svg> "
|
public static down = " <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\" version=\"1.0\" width=\"700\" height=\"700\" id=\"svg6\" sodipodi:docname=\"down.svg\" inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"> <metadata id=\"metadata12\"> <rdf:RDF> <cc:Work rdf:about=\"\"> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" /> </cc:Work> </rdf:RDF> </metadata> <defs id=\"defs10\" /> <sodipodi:namedview pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1\" objecttolerance=\"10\" gridtolerance=\"10\" guidetolerance=\"10\" inkscape:pageopacity=\"0\" inkscape:pageshadow=\"2\" inkscape:window-width=\"1920\" inkscape:window-height=\"1001\" id=\"namedview8\" showgrid=\"false\" inkscape:zoom=\"0.33714286\" inkscape:cx=\"477.91309\" inkscape:cy=\"350\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg6\" /> <g transform=\"rotate(-180,342.1439,335.17672)\" id=\"g4\"> <path d=\"m -20,670.71582 c 0,-1.85843 349.99229,-699.98853 350.57213,-699.28671 1.94549,2.35478 350.06752,699.46087 349.427,699.71927 -0.41837,0.16878 -79.29725,-33.69092 -175.2864,-75.24377 l -174.52574,-75.55065 -174.2421,75.53732 c -95.83317,41.54551 -174.625237,75.5373 -175.093498,75.5373 -0.46826,0 -0.851382,-0.32075 -0.851382,-0.71276 z\" style=\"fill:#00ff00;stroke:none\" id=\"path2\" inkscape:connector-curvature=\"0\" /> </g> </svg> "
|
||||||
public static down_img = Img.AsImageElement(Svg.down)
|
public static down_img = Img.AsImageElement(Svg.down)
|
||||||
public static down_svg() { return new Img(Svg.down, true);}
|
public static down_svg() { return new Img(Svg.down, true);}
|
||||||
|
@ -319,4 +334,4 @@ export default class Svg {
|
||||||
public static wikipedia_svg() { return new Img(Svg.wikipedia, true);}
|
public static wikipedia_svg() { return new Img(Svg.wikipedia, true);}
|
||||||
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
|
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
|
||||||
|
|
||||||
public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
|
public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
|
||||||
|
|
144
UI/Base/Minimap.ts
Normal file
144
UI/Base/Minimap.ts
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
import BaseUIElement from "../BaseUIElement";
|
||||||
|
import * as L from "leaflet";
|
||||||
|
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
|
import Loc from "../../Models/Loc";
|
||||||
|
import BaseLayer from "../../Models/BaseLayer";
|
||||||
|
import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
|
||||||
|
import {Map} from "leaflet";
|
||||||
|
|
||||||
|
export default class Minimap extends BaseUIElement {
|
||||||
|
|
||||||
|
private static _nextId = 0;
|
||||||
|
public readonly leafletMap: UIEventSource<Map> = new UIEventSource<Map>(undefined)
|
||||||
|
private readonly _id: string;
|
||||||
|
private readonly _background: UIEventSource<BaseLayer>;
|
||||||
|
private readonly _location: UIEventSource<Loc>;
|
||||||
|
private _isInited = false;
|
||||||
|
private _allowMoving: boolean;
|
||||||
|
|
||||||
|
constructor(options?: {
|
||||||
|
background?: UIEventSource<BaseLayer>,
|
||||||
|
location?: UIEventSource<Loc>,
|
||||||
|
allowMoving?: boolean
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
super()
|
||||||
|
options = options ?? {}
|
||||||
|
this._background = options?.background ?? new UIEventSource<BaseLayer>(AvailableBaseLayers.osmCarto)
|
||||||
|
this._location = options?.location ?? new UIEventSource<Loc>(undefined)
|
||||||
|
this._id = "minimap" + Minimap._nextId;
|
||||||
|
this._allowMoving = options.allowMoving ?? true;
|
||||||
|
Minimap._nextId++
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected InnerConstructElement(): HTMLElement {
|
||||||
|
const div = document.createElement("div")
|
||||||
|
div.id = this._id;
|
||||||
|
div.style.height = "100%"
|
||||||
|
div.style.width = "100%"
|
||||||
|
div.style.minWidth = "40px"
|
||||||
|
div.style.minHeight = "40px"
|
||||||
|
const wrapper = document.createElement("div")
|
||||||
|
wrapper.appendChild(div)
|
||||||
|
const self = this;
|
||||||
|
// @ts-ignore
|
||||||
|
const resizeObserver = new ResizeObserver(_ => {
|
||||||
|
console.log("Change in size detected!")
|
||||||
|
self.InitMap();
|
||||||
|
self.leafletMap?.data?.invalidateSize()
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeObserver.observe(div);
|
||||||
|
return wrapper;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private InitMap() {
|
||||||
|
if (this._constructedHtmlElement === undefined) {
|
||||||
|
// This element isn't initialized yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById(this._id) === null) {
|
||||||
|
// not yet attached, we probably got some other event
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isInited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._isInited = true;
|
||||||
|
const location = this._location;
|
||||||
|
|
||||||
|
let currentLayer = this._background.data.layer()
|
||||||
|
const map = L.map(this._id, {
|
||||||
|
center: [location.data?.lat ?? 0, location.data?.lon ?? 0],
|
||||||
|
zoom: location.data?.zoom ?? 2,
|
||||||
|
layers: [currentLayer],
|
||||||
|
zoomControl: false,
|
||||||
|
attributionControl: false,
|
||||||
|
dragging: this._allowMoving,
|
||||||
|
scrollWheelZoom: this._allowMoving,
|
||||||
|
doubleClickZoom: this._allowMoving,
|
||||||
|
keyboard: this._allowMoving,
|
||||||
|
touchZoom: this._allowMoving
|
||||||
|
});
|
||||||
|
|
||||||
|
map.setMaxBounds(
|
||||||
|
[[-100, -200], [100, 200]]
|
||||||
|
);
|
||||||
|
|
||||||
|
this._background.addCallbackAndRun(layer => {
|
||||||
|
const newLayer = layer.layer()
|
||||||
|
if (currentLayer !== undefined) {
|
||||||
|
map.removeLayer(currentLayer);
|
||||||
|
}
|
||||||
|
currentLayer = newLayer;
|
||||||
|
map.addLayer(newLayer);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
let isRecursing = false;
|
||||||
|
map.on("moveend", function () {
|
||||||
|
if (isRecursing) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (map.getZoom() === location.data.zoom &&
|
||||||
|
map.getCenter().lat === location.data.lat &&
|
||||||
|
map.getCenter().lng === location.data.lon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.trace(map.getZoom(), map.getCenter(), location.data)
|
||||||
|
|
||||||
|
location.data.zoom = map.getZoom();
|
||||||
|
location.data.lat = map.getCenter().lat;
|
||||||
|
location.data.lon = map.getCenter().lng;
|
||||||
|
isRecursing = true;
|
||||||
|
location.ping();
|
||||||
|
isRecursing = false; // This is ugly, I know
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
location.addCallback(loc => {
|
||||||
|
const mapLoc = map.getCenter()
|
||||||
|
const dlat = Math.abs(loc.lat - mapLoc[0])
|
||||||
|
const dlon = Math.abs(loc.lon - mapLoc[1])
|
||||||
|
|
||||||
|
if (dlat < 0.000001 && dlon < 0.000001 && map.getZoom() === loc.zoom) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map.setView([loc.lat, loc.lon], loc.zoom)
|
||||||
|
})
|
||||||
|
|
||||||
|
location.map(loc => loc.zoom)
|
||||||
|
.addCallback(zoom => {
|
||||||
|
if (Math.abs(map.getZoom() - zoom) > 0.1) {
|
||||||
|
map.setZoom(zoom, {});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
this.leafletMap.setData(map)
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,10 +14,14 @@ export class Basemap {
|
||||||
currentLayer: UIEventSource<BaseLayer>,
|
currentLayer: UIEventSource<BaseLayer>,
|
||||||
lastClickLocation?: UIEventSource<{ lat: number, lon: number }>,
|
lastClickLocation?: UIEventSource<{ lat: number, lon: number }>,
|
||||||
extraAttribution?: BaseUIElement) {
|
extraAttribution?: BaseUIElement) {
|
||||||
|
|
||||||
|
console.log("Currentlayer is" ,currentLayer, currentLayer.data, currentLayer.data?.id)
|
||||||
|
let previousLayer = currentLayer.data.layer();
|
||||||
|
|
||||||
this.map = L.map(leafletElementId, {
|
this.map = L.map(leafletElementId, {
|
||||||
center: [location.data.lat ?? 0, location.data.lon ?? 0],
|
center: [location.data.lat ?? 0, location.data.lon ?? 0],
|
||||||
zoom: location.data.zoom ?? 2,
|
zoom: location.data.zoom ?? 2,
|
||||||
layers: [currentLayer.data.layer],
|
layers: [previousLayer],
|
||||||
zoomControl: false,
|
zoomControl: false,
|
||||||
attributionControl: extraAttribution !== undefined
|
attributionControl: extraAttribution !== undefined
|
||||||
});
|
});
|
||||||
|
@ -42,16 +46,16 @@ export class Basemap {
|
||||||
extraAttribution.AttachTo('leaflet-attribution')
|
extraAttribution.AttachTo('leaflet-attribution')
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
let previousLayer = currentLayer.data;
|
|
||||||
currentLayer.addCallbackAndRun(layer => {
|
currentLayer.addCallbackAndRun(layer => {
|
||||||
if (layer === previousLayer) {
|
const newLayer = layer.layer()
|
||||||
|
if (newLayer === previousLayer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (previousLayer !== undefined) {
|
if (previousLayer !== undefined) {
|
||||||
self.map.removeLayer(previousLayer.layer);
|
self.map.removeLayer(previousLayer);
|
||||||
}
|
}
|
||||||
previousLayer = layer;
|
previousLayer = newLayer;
|
||||||
self.map.addLayer(layer.layer);
|
self.map.addLayer(newLayer);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,30 @@ import {InputElement} from "./InputElement";
|
||||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
import Combine from "../Base/Combine";
|
import Combine from "../Base/Combine";
|
||||||
import Svg from "../../Svg";
|
import Svg from "../../Svg";
|
||||||
|
import BaseUIElement from "../BaseUIElement";
|
||||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||||
|
import {Utils} from "../../Utils";
|
||||||
|
import Loc from "../../Models/Loc";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects a direction in degrees
|
* Selects a direction in degrees
|
||||||
*/
|
*/
|
||||||
export default class DirectionInput extends InputElement<string> {
|
export default class DirectionInput extends InputElement<string> {
|
||||||
|
public static constructMinimap: ((any) => BaseUIElement);
|
||||||
|
private readonly _location: UIEventSource<Loc>;
|
||||||
|
|
||||||
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
||||||
private readonly value: UIEventSource<string>;
|
private readonly value: UIEventSource<string>;
|
||||||
|
private background;
|
||||||
|
|
||||||
constructor(value?: UIEventSource<string>) {
|
constructor(mapBackground: UIEventSource<any>,
|
||||||
|
location: UIEventSource<Loc>,
|
||||||
|
value?: UIEventSource<string>) {
|
||||||
super();
|
super();
|
||||||
|
this._location = location;
|
||||||
this.value = value ?? new UIEventSource<string>(undefined);
|
this.value = value ?? new UIEventSource<string>(undefined);
|
||||||
|
this.background = mapBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetValue(): UIEventSource<string> {
|
GetValue(): UIEventSource<string> {
|
||||||
|
@ -30,16 +39,23 @@ export default class DirectionInput extends InputElement<string> {
|
||||||
|
|
||||||
protected InnerConstructElement(): HTMLElement {
|
protected InnerConstructElement(): HTMLElement {
|
||||||
|
|
||||||
|
let map: BaseUIElement = new FixedUiElement("")
|
||||||
|
if (!Utils.runningFromConsole) {
|
||||||
|
map = DirectionInput.constructMinimap({
|
||||||
|
background: this.background,
|
||||||
|
allowMoving: false,
|
||||||
|
location: this._location
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const element = new Combine([
|
const element = new Combine([
|
||||||
new FixedUiElement("").SetClass("w-full h-full absolute top-0 left-O rounded-full"),
|
Svg.direction_stroke_svg().SetStyle(
|
||||||
Svg.direction_svg().SetStyle(
|
|
||||||
`position: absolute;top: 0;left: 0;width: 100%;height: 100%;transform:rotate(${this.value.data ?? 0}deg);`)
|
`position: absolute;top: 0;left: 0;width: 100%;height: 100%;transform:rotate(${this.value.data ?? 0}deg);`)
|
||||||
.SetClass("direction-svg"),
|
.SetClass("direction-svg relative")
|
||||||
Svg.compass_svg().SetStyle(
|
.SetStyle("z-index: 1000"),
|
||||||
"position: absolute;top: 0;left: 0;width: 100%;height: 100%;")
|
map.SetClass("w-full h-full absolute top-0 left-O rounded-full overflow-hidden"),
|
||||||
])
|
])
|
||||||
.SetStyle("position:relative;display:block;width: min(100%, 25em); padding-top: min(100% , 25em); background:white; border: 1px solid black; border-radius: 999em")
|
.SetStyle("position:relative;display:block;width: min(100%, 25em); height: min(100% , 25em); background:white; border: 1px solid black; border-radius: 999em")
|
||||||
.ConstructElement()
|
.ConstructElement()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {DropDown} from "./DropDown";
|
import {DropDown} from "./DropDown";
|
||||||
import * as EmailValidator from "email-validator";
|
import * as EmailValidator from "email-validator";
|
||||||
import {parsePhoneNumberFromString} from "libphonenumber-js";
|
import {parsePhoneNumberFromString} from "libphonenumber-js";
|
||||||
import InputElementMap from "./InputElementMap";
|
|
||||||
import {InputElement} from "./InputElement";
|
import {InputElement} from "./InputElement";
|
||||||
import {TextField} from "./TextField";
|
import {TextField} from "./TextField";
|
||||||
import {UIElement} from "../UIElement";
|
import {UIElement} from "../UIElement";
|
||||||
|
@ -12,6 +11,7 @@ import OpeningHoursInput from "../OpeningHours/OpeningHoursInput";
|
||||||
import DirectionInput from "./DirectionInput";
|
import DirectionInput from "./DirectionInput";
|
||||||
import ColorPicker from "./ColorPicker";
|
import ColorPicker from "./ColorPicker";
|
||||||
import {Utils} from "../../Utils";
|
import {Utils} from "../../Utils";
|
||||||
|
import Loc from "../../Models/Loc";
|
||||||
|
|
||||||
interface TextFieldDef {
|
interface TextFieldDef {
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -19,7 +19,8 @@ interface TextFieldDef {
|
||||||
isValid: ((s: string, country?: () => string) => boolean),
|
isValid: ((s: string, country?: () => string) => boolean),
|
||||||
reformat?: ((s: string, country?: () => string) => string),
|
reformat?: ((s: string, country?: () => string) => string),
|
||||||
inputHelper?: (value: UIEventSource<string>, options?: {
|
inputHelper?: (value: UIEventSource<string>, options?: {
|
||||||
location: [number, number]
|
location: [number, number],
|
||||||
|
mapBackgroundLayer?: UIEventSource<any>
|
||||||
}) => InputElement<string>,
|
}) => InputElement<string>,
|
||||||
|
|
||||||
inputmode?: string
|
inputmode?: string
|
||||||
|
@ -118,8 +119,12 @@ export default class ValidatedTextField {
|
||||||
str = "" + str;
|
str = "" + str;
|
||||||
return str !== undefined && str.indexOf(".") < 0 && !isNaN(Number(str)) && Number(str) >= 0 && Number(str) <= 360
|
return str !== undefined && str.indexOf(".") < 0 && !isNaN(Number(str)) && Number(str) >= 0 && Number(str) <= 360
|
||||||
}, str => str,
|
}, str => str,
|
||||||
(value) => {
|
(value, options) => {
|
||||||
return new DirectionInput(value);
|
return new DirectionInput(options.mapBackgroundLayer , new UIEventSource<Loc>({
|
||||||
|
lat: options.location[0],
|
||||||
|
lon: options.location[1],
|
||||||
|
zoom: 19
|
||||||
|
}),value);
|
||||||
},
|
},
|
||||||
"numeric"
|
"numeric"
|
||||||
),
|
),
|
||||||
|
@ -235,7 +240,8 @@ export default class ValidatedTextField {
|
||||||
textAreaRows?: number,
|
textAreaRows?: number,
|
||||||
isValid?: ((s: string, country: () => string) => boolean),
|
isValid?: ((s: string, country: () => string) => boolean),
|
||||||
country?: () => string,
|
country?: () => string,
|
||||||
location?: [number /*lat*/, number /*lon*/]
|
location?: [number /*lat*/, number /*lon*/],
|
||||||
|
mapBackgroundLayer?: UIEventSource<any>
|
||||||
}): InputElement<string> {
|
}): InputElement<string> {
|
||||||
options = options ?? {};
|
options = options ?? {};
|
||||||
options.placeholder = options.placeholder ?? type;
|
options.placeholder = options.placeholder ?? type;
|
||||||
|
@ -269,87 +275,12 @@ export default class ValidatedTextField {
|
||||||
|
|
||||||
if (tp.inputHelper) {
|
if (tp.inputHelper) {
|
||||||
input = new CombinedInputElement(input, tp.inputHelper(input.GetValue(), {
|
input = new CombinedInputElement(input, tp.inputHelper(input.GetValue(), {
|
||||||
location: options.location
|
location: options.location,
|
||||||
|
mapBackgroundLayer: options.mapBackgroundLayer
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NumberInput(type: string = "int", extraValidation: (number: Number) => boolean = undefined): InputElement<number> {
|
|
||||||
const isValid = ValidatedTextField.AllTypes[type].isValid;
|
|
||||||
extraValidation = extraValidation ?? (() => true)
|
|
||||||
|
|
||||||
const fromString = str => {
|
|
||||||
if (!isValid(str)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const n = Number(str);
|
|
||||||
if (!extraValidation(n)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
};
|
|
||||||
const toString = num => {
|
|
||||||
if (num === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return "" + num;
|
|
||||||
};
|
|
||||||
const textField = ValidatedTextField.InputForType(type);
|
|
||||||
return new InputElementMap(textField, (n0, n1) => n0 === n1, fromString, toString)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KeyInput(allowEmpty: boolean = false): InputElement<string> {
|
|
||||||
|
|
||||||
function fromString(str) {
|
|
||||||
if (str?.match(/^[a-zA-Z][a-zA-Z0-9:_-]*$/)) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
if (str === "" && allowEmpty) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const toString = str => str
|
|
||||||
|
|
||||||
function isSame(str0, str1) {
|
|
||||||
return str0 === str1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const textfield = new TextField({
|
|
||||||
placeholder: "key",
|
|
||||||
isValid: str => fromString(str) !== undefined,
|
|
||||||
value: new UIEventSource<string>("")
|
|
||||||
});
|
|
||||||
|
|
||||||
return new InputElementMap(textfield, isSame, fromString, toString);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Mapped<T>(fromString: (str) => T, toString: (T) => string, options?: {
|
|
||||||
placeholder?: string | UIElement,
|
|
||||||
type?: string,
|
|
||||||
value?: UIEventSource<string>,
|
|
||||||
startValidated?: boolean,
|
|
||||||
textArea?: boolean,
|
|
||||||
textAreaRows?: number,
|
|
||||||
isValid?: ((string: string) => boolean),
|
|
||||||
country?: () => string
|
|
||||||
}): InputElement<T> {
|
|
||||||
let textField: InputElement<string>;
|
|
||||||
if (options?.type) {
|
|
||||||
textField = ValidatedTextField.InputForType(options.type, options);
|
|
||||||
} else {
|
|
||||||
textField = new TextField(options);
|
|
||||||
}
|
|
||||||
return new InputElementMap(
|
|
||||||
textField, (a, b) => a === b,
|
|
||||||
fromString, toString
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HelpText(): string {
|
public static HelpText(): string {
|
||||||
const explanations = ValidatedTextField.tpList.map(type => ["## " + type.name, "", type.explanation].join("\n")).join("\n\n")
|
const explanations = ValidatedTextField.tpList.map(type => ["## " + type.name, "", type.explanation].join("\n")).join("\n\n")
|
||||||
return "# Available types for text fields\n\nThe listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them\n\n" + explanations
|
return "# Available types for text fields\n\nThe listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them\n\n" + explanations
|
||||||
|
@ -360,7 +291,8 @@ export default class ValidatedTextField {
|
||||||
isValid?: ((s: string, country?: () => string) => boolean),
|
isValid?: ((s: string, country?: () => string) => boolean),
|
||||||
reformat?: ((s: string, country?: () => string) => string),
|
reformat?: ((s: string, country?: () => string) => string),
|
||||||
inputHelper?: (value: UIEventSource<string>, options?: {
|
inputHelper?: (value: UIEventSource<string>, options?: {
|
||||||
location: [number, number]
|
location: [number, number],
|
||||||
|
mapBackgroundLayer: UIEventSource<any>
|
||||||
}) => InputElement<string>,
|
}) => InputElement<string>,
|
||||||
inputmode?: string): TextFieldDef {
|
inputmode?: string): TextFieldDef {
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,8 @@ export default class TagRenderingQuestion extends UIElement {
|
||||||
const textField = ValidatedTextField.InputForType(this._configuration.freeform.type, {
|
const textField = ValidatedTextField.InputForType(this._configuration.freeform.type, {
|
||||||
isValid: (str) => (str.length <= 255),
|
isValid: (str) => (str.length <= 255),
|
||||||
country: () => this._tags.data._country,
|
country: () => this._tags.data._country,
|
||||||
location: [this._tags.data._lat, this._tags.data._lon]
|
location: [this._tags.data._lat, this._tags.data._lon],
|
||||||
|
mapBackgroundLayer: State.state.backgroundLayer
|
||||||
});
|
});
|
||||||
|
|
||||||
textField.GetValue().setData(this._tags.data[this._configuration.freeform.key]);
|
textField.GetValue().setData(this._tags.data[this._configuration.freeform.key]);
|
||||||
|
|
|
@ -15,13 +15,15 @@ export default class ShowDataLayer {
|
||||||
private _layerDict;
|
private _layerDict;
|
||||||
private readonly _leafletMap: UIEventSource<L.Map>;
|
private readonly _leafletMap: UIEventSource<L.Map>;
|
||||||
private _cleanCount = 0;
|
private _cleanCount = 0;
|
||||||
|
private readonly _enablePopups: boolean;
|
||||||
|
|
||||||
constructor(features: UIEventSource<{ feature: any, freshness: Date }[]>,
|
constructor(features: UIEventSource<{ feature: any, freshness: Date }[]>,
|
||||||
leafletMap: UIEventSource<L.Map>,
|
leafletMap: UIEventSource<L.Map>,
|
||||||
layoutToUse: UIEventSource<LayoutConfig>) {
|
layoutToUse: UIEventSource<LayoutConfig>,
|
||||||
|
enablePopups= true) {
|
||||||
this._leafletMap = leafletMap;
|
this._leafletMap = leafletMap;
|
||||||
|
this._enablePopups = enablePopups;
|
||||||
const self = this;
|
const self = this;
|
||||||
const mp = leafletMap.data;
|
|
||||||
self._layerDict = {};
|
self._layerDict = {};
|
||||||
|
|
||||||
layoutToUse.addCallbackAndRun(layoutToUse => {
|
layoutToUse.addCallbackAndRun(layoutToUse => {
|
||||||
|
@ -39,7 +41,9 @@ export default class ShowDataLayer {
|
||||||
if (features.data === undefined) {
|
if (features.data === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (leafletMap.data === undefined) {
|
const mp = leafletMap.data;
|
||||||
|
|
||||||
|
if(mp === undefined){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +123,11 @@ export default class ShowDataLayer {
|
||||||
// No popup action defined -> Don't do anything
|
// No popup action defined -> Don't do anything
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!this._enablePopups){
|
||||||
|
// Probably a map in the popup - no popups needed!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const popup = L.popup({
|
const popup = L.popup({
|
||||||
autoPan: true,
|
autoPan: true,
|
||||||
closeOnEscapeKey: true,
|
closeOnEscapeKey: true,
|
||||||
|
@ -171,15 +180,15 @@ export default class ShowDataLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private CreateGeojsonLayer(): L.Layer {
|
private CreateGeojsonLayer(): L.Layer {
|
||||||
const self = this;
|
const self = this;
|
||||||
const data = {
|
const data = {
|
||||||
type: "FeatureCollection",
|
type: "FeatureCollection",
|
||||||
features: []
|
features: []
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return L.geoJSON(data, {
|
return L.geoJSON(data, {
|
||||||
style: feature => self.createStyleFor(feature),
|
style: feature => self.createStyleFor(feature),
|
||||||
pointToLayer: (feature, latLng) => self.pointToLayer(feature, latLng),
|
pointToLayer: (feature, latLng) => self.pointToLayer(feature, latLng),
|
||||||
onEachFeature: (feature, leafletLayer) => self.postProcessFeature(feature, leafletLayer)
|
onEachFeature: (feature, leafletLayer) => self.postProcessFeature(feature, leafletLayer)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,13 @@ import LayerConfig from "../Customizations/JSON/LayerConfig";
|
||||||
import Title from "./Base/Title";
|
import Title from "./Base/Title";
|
||||||
import Table from "./Base/Table";
|
import Table from "./Base/Table";
|
||||||
import Histogram from "./BigComponents/Histogram";
|
import Histogram from "./BigComponents/Histogram";
|
||||||
|
import Loc from "../Models/Loc";
|
||||||
|
import ShowDataLayer from "./ShowDataLayer";
|
||||||
|
import Minimap from "./Base/Minimap";
|
||||||
|
|
||||||
export default class SpecialVisualizations {
|
export default class SpecialVisualizations {
|
||||||
|
|
||||||
|
|
||||||
public static specialVisualizations: {
|
public static specialVisualizations: {
|
||||||
funcName: string,
|
funcName: string,
|
||||||
constr: ((state: State, tagSource: UIEventSource<any>, argument: string[]) => BaseUIElement),
|
constr: ((state: State, tagSource: UIEventSource<any>, argument: string[]) => BaseUIElement),
|
||||||
|
@ -32,7 +35,6 @@ export default class SpecialVisualizations {
|
||||||
example?: string,
|
example?: string,
|
||||||
args: { name: string, defaultValue?: string, doc: string }[]
|
args: { name: string, defaultValue?: string, doc: string }[]
|
||||||
}[] =
|
}[] =
|
||||||
|
|
||||||
[{
|
[{
|
||||||
funcName: "all_tags",
|
funcName: "all_tags",
|
||||||
docs: "Prints all key-value pairs of the object - used for debugging",
|
docs: "Prints all key-value pairs of the object - used for debugging",
|
||||||
|
@ -85,7 +87,57 @@ export default class SpecialVisualizations {
|
||||||
return new ImageUploadFlow(tags, args[0])
|
return new ImageUploadFlow(tags, args[0])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
funcName: "minimap",
|
||||||
|
docs: "A small map showing the selected feature. Note that no styling is applied, wrap this in a div",
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
doc: "The zoomlevel: the higher, the more zoomed in with 1 being the entire world and 19 being really close",
|
||||||
|
name: "zoomlevel",
|
||||||
|
defaultValue: "18"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
example: "`{minimap()}`",
|
||||||
|
constr: (state, tagSource, args) => {
|
||||||
|
const properties = tagSource.data;
|
||||||
|
const feature = state.allElements.ContainingFeatures.get(properties.id)
|
||||||
|
|
||||||
|
let zoom = 18
|
||||||
|
if(args[0] ){
|
||||||
|
const parsed = Number(args[0])
|
||||||
|
if(!isNaN(parsed) && parsed > 0 && parsed < 25){
|
||||||
|
zoom = parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const minimap = new Minimap(
|
||||||
|
{
|
||||||
|
background: state.backgroundLayer,
|
||||||
|
location: new UIEventSource<Loc>({
|
||||||
|
lat: Number(properties._lat),
|
||||||
|
lon: Number(properties._lon),
|
||||||
|
zoom: zoom
|
||||||
|
}),
|
||||||
|
allowMoving: false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
new ShowDataLayer(
|
||||||
|
new UIEventSource<{ feature: any; freshness: Date }[]>([
|
||||||
|
{
|
||||||
|
freshness: new Date(),
|
||||||
|
feature: feature
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
minimap.leafletMap,
|
||||||
|
State.state.layoutToUse,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
minimap.SetStyle("overflow: hidden; pointer-events: none;")
|
||||||
|
return minimap;
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
funcName: "reviews",
|
funcName: "reviews",
|
||||||
docs: "Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten",
|
docs: "Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten",
|
||||||
|
|
|
@ -17,14 +17,14 @@ export class SubstitutedTranslation extends VariableUiElement {
|
||||||
super(
|
super(
|
||||||
tagsSource.map(tags => {
|
tagsSource.map(tags => {
|
||||||
const txt = Utils.SubstituteKeys(translation.txt, tags)
|
const txt = Utils.SubstituteKeys(translation.txt, tags)
|
||||||
if (txt === undefined) {
|
if (txt === undefined) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return new Combine(SubstitutedTranslation.EvaluateSpecialComponents(txt, tagsSource))
|
return new Combine(SubstitutedTranslation.EvaluateSpecialComponents(txt, tagsSource))
|
||||||
}, [Locale.language])
|
}, [Locale.language])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
this.SetClass("w-full")
|
this.SetClass("w-full")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +34,14 @@ export class SubstitutedTranslation extends VariableUiElement {
|
||||||
for (const knownSpecial of SpecialVisualizations.specialVisualizations) {
|
for (const knownSpecial of SpecialVisualizations.specialVisualizations) {
|
||||||
|
|
||||||
// Note: the '.*?' in the regex reads as 'any character, but in a non-greedy way'
|
// Note: the '.*?' in the regex reads as 'any character, but in a non-greedy way'
|
||||||
const matched = template.match(`(.*){${knownSpecial.funcName}\\((.*?)\\)}(.*)`);
|
const matched = template.match(`(.*){${knownSpecial.funcName}\\((.*?)\\)(:.*)?}(.*)`);
|
||||||
if (matched != null) {
|
if (matched != null) {
|
||||||
|
|
||||||
// We found a special component that should be brought to live
|
// We found a special component that should be brought to live
|
||||||
const partBefore = SubstitutedTranslation.EvaluateSpecialComponents(matched[1], tags);
|
const partBefore = SubstitutedTranslation.EvaluateSpecialComponents(matched[1], tags);
|
||||||
const argument = matched[2].trim();
|
const argument = matched[2].trim();
|
||||||
const partAfter = SubstitutedTranslation.EvaluateSpecialComponents(matched[3], tags);
|
const style = matched[3] ?? ""
|
||||||
|
const partAfter = SubstitutedTranslation.EvaluateSpecialComponents(matched[4], tags);
|
||||||
try {
|
try {
|
||||||
const args = knownSpecial.args.map(arg => arg.defaultValue ?? "");
|
const args = knownSpecial.args.map(arg => arg.defaultValue ?? "");
|
||||||
if (argument.length > 0) {
|
if (argument.length > 0) {
|
||||||
|
@ -56,13 +57,14 @@ export class SubstitutedTranslation extends VariableUiElement {
|
||||||
|
|
||||||
|
|
||||||
let element: BaseUIElement = new FixedUiElement(`Constructing ${knownSpecial}(${args.join(", ")})`)
|
let element: BaseUIElement = new FixedUiElement(`Constructing ${knownSpecial}(${args.join(", ")})`)
|
||||||
try{
|
try {
|
||||||
element = knownSpecial.constr(State.state, tags, args);
|
element = knownSpecial.constr(State.state, tags, args);
|
||||||
}catch(e){
|
element.SetStyle(style)
|
||||||
|
} catch (e) {
|
||||||
console.error("SPECIALRENDERING FAILED for", tags.data.id, e)
|
console.error("SPECIALRENDERING FAILED for", tags.data.id, e)
|
||||||
element = new FixedUiElement(`Could not generate special rendering for ${knownSpecial}(${args.join(", ")}) ${e}`).SetClass("alert")
|
element = new FixedUiElement(`Could not generate special rendering for ${knownSpecial}(${args.join(", ")}) ${e}`).SetClass("alert")
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...partBefore, element, ...partAfter]
|
return [...partBefore, element, ...partAfter]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"render": "{reviews()}"
|
"render": "{reviews()}"
|
||||||
},
|
},
|
||||||
"minimap": {
|
"minimap": {
|
||||||
"render": "<div class='w-full h-6 rounded-full'>{minimap(19, {id})}</div>"
|
"render": "{minimap(19, id): width:100%; height:6rem; border-radius:999rem; overflow: hidden; pointer-events: none;}"
|
||||||
},
|
},
|
||||||
"phone": {
|
"phone": {
|
||||||
"question": {
|
"question": {
|
||||||
|
|
6
index.ts
6
index.ts
|
@ -14,10 +14,12 @@ import Translations from "./UI/i18n/Translations";
|
||||||
import CountryCoder from "latlon2country"
|
import CountryCoder from "latlon2country"
|
||||||
|
|
||||||
import SimpleMetaTagger from "./Logic/SimpleMetaTagger";
|
import SimpleMetaTagger from "./Logic/SimpleMetaTagger";
|
||||||
|
import Minimap from "./UI/Base/Minimap";
|
||||||
|
import DirectionInput from "./UI/Input/DirectionInput";
|
||||||
|
|
||||||
// Workaround for a stupid crash: inject the function
|
// Workaround for a stupid crash: inject some functions which would give stupid circular dependencies or crash the other nodejs scripts
|
||||||
SimpleMetaTagger.coder = new CountryCoder("https://pietervdvn.github.io/latlon2country/");
|
SimpleMetaTagger.coder = new CountryCoder("https://pietervdvn.github.io/latlon2country/");
|
||||||
|
DirectionInput.constructMinimap = options => new Minimap(options)
|
||||||
|
|
||||||
let defaultLayout = ""
|
let defaultLayout = ""
|
||||||
// --------------------- Special actions based on the parameters -----------------
|
// --------------------- Special actions based on the parameters -----------------
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Small tests</title>
|
<title>Small tests</title>
|
||||||
<link href="index.css" rel="stylesheet"/>
|
<link href="index.css" rel="stylesheet"/>
|
||||||
|
<link rel="stylesheet" href="./vendor/leaflet.css"/>
|
||||||
<link href="css/tabbedComponent.css" rel="stylesheet"/>
|
<link href="css/tabbedComponent.css" rel="stylesheet"/>
|
||||||
<link href="css/openinghourstable.css" rel="stylesheet"/>
|
<link href="css/openinghourstable.css" rel="stylesheet"/>
|
||||||
<link href="css/tagrendering.css" rel="stylesheet"/>
|
<link href="css/tagrendering.css" rel="stylesheet"/>
|
||||||
|
|
101
test.ts
101
test.ts
|
@ -10,11 +10,15 @@ import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||||
import Img from "./UI/Base/Img";
|
import Img from "./UI/Base/Img";
|
||||||
import {AttributedImage} from "./UI/Image/AttributedImage";
|
import {AttributedImage} from "./UI/Image/AttributedImage";
|
||||||
import {Imgur} from "./Logic/ImageProviders/Imgur";
|
import {Imgur} from "./Logic/ImageProviders/Imgur";
|
||||||
import ReviewForm from "./UI/Reviews/ReviewForm";
|
import Minimap from "./UI/Base/Minimap";
|
||||||
import {OsmConnection} from "./Logic/Osm/OsmConnection";
|
import Loc from "./Models/Loc";
|
||||||
|
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
|
||||||
|
import ShowDataLayer from "./UI/ShowDataLayer";
|
||||||
|
import LayoutConfig from "./Customizations/JSON/LayoutConfig";
|
||||||
|
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
||||||
|
|
||||||
|
|
||||||
function TestSlideshow(){
|
function TestSlideshow() {
|
||||||
const elems = new UIEventSource([
|
const elems = new UIEventSource([
|
||||||
new FixedUiElement("A"),
|
new FixedUiElement("A"),
|
||||||
new FixedUiElement("qmsldkfjqmlsdkjfmqlskdjfmqlksdf").SetClass("text-xl"),
|
new FixedUiElement("qmsldkfjqmlsdkjfmqlskdjfmqlksdf").SetClass("text-xl"),
|
||||||
|
@ -25,17 +29,17 @@ function TestSlideshow(){
|
||||||
new SlideShow(elems).AttachTo("maindiv")
|
new SlideShow(elems).AttachTo("maindiv")
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestTagRendering(){
|
function TestTagRendering() {
|
||||||
State.state = new State(undefined)
|
State.state = new State(undefined)
|
||||||
const tagsSource = new UIEventSource({
|
const tagsSource = new UIEventSource({
|
||||||
id:"node/1"
|
id: "node/1"
|
||||||
})
|
})
|
||||||
new TagRenderingQuestion(
|
new TagRenderingQuestion(
|
||||||
tagsSource,
|
tagsSource,
|
||||||
new TagRenderingConfig({
|
new TagRenderingConfig({
|
||||||
multiAnswer: false,
|
multiAnswer: false,
|
||||||
freeform: {
|
freeform: {
|
||||||
key:"valve"
|
key: "valve"
|
||||||
},
|
},
|
||||||
question: "What valves are supported?",
|
question: "What valves are supported?",
|
||||||
render: "This pump supports {valve}",
|
render: "This pump supports {valve}",
|
||||||
|
@ -45,25 +49,94 @@ function TestTagRendering(){
|
||||||
then: "This pump supports dunlop"
|
then: "This pump supports dunlop"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
if:"valve=shrader",
|
if: "valve=shrader",
|
||||||
then:"shrader is supported",
|
then: "shrader is supported",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
}, undefined, "test")
|
}, undefined, "test")
|
||||||
).AttachTo("maindiv")
|
).AttachTo("maindiv")
|
||||||
new VariableUiElement(tagsSource.map(tags => tags["valves"])).SetClass("alert").AttachTo("extradiv")
|
new VariableUiElement(tagsSource.map(tags => tags["valves"])).SetClass("alert").AttachTo("extradiv")
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestAllInputMethods(){
|
function TestAllInputMethods() {
|
||||||
|
|
||||||
new Combine(ValidatedTextField.tpList.map(tp => {
|
new Combine(ValidatedTextField.tpList.map(tp => {
|
||||||
const tf = ValidatedTextField.InputForType(tp.name);
|
const tf = ValidatedTextField.InputForType(tp.name);
|
||||||
|
|
||||||
return new Combine([tf, new VariableUiElement(tf.GetValue()).SetClass("alert")]);
|
return new Combine([tf, new VariableUiElement(tf.GetValue()).SetClass("alert")]);
|
||||||
})).AttachTo("maindiv")
|
})).AttachTo("maindiv")
|
||||||
}
|
}
|
||||||
|
|
||||||
new ReviewForm(() => {
|
|
||||||
return undefined;
|
const location = new UIEventSource<Loc>({
|
||||||
}, new OsmConnection(true, new UIEventSource<string>(undefined), "test")).AttachTo("maindiv");
|
lon: 4.84771728515625,
|
||||||
|
lat: 51.17920846421931,
|
||||||
|
zoom: 14
|
||||||
|
})
|
||||||
|
const map0 = new Minimap({
|
||||||
|
location: location,
|
||||||
|
allowMoving: true,
|
||||||
|
background: new AvailableBaseLayers(location).availableEditorLayers.map(layers => layers[2])
|
||||||
|
})
|
||||||
|
map0.SetStyle("width: 500px; height: 250px; overflow: hidden; border: 2px solid red")
|
||||||
|
.AttachTo("maindiv")
|
||||||
|
|
||||||
|
const layout = AllKnownLayouts.layoutsList[1]
|
||||||
|
State.state = new State(layout)
|
||||||
|
console.log("LAYOUT is", layout.id)
|
||||||
|
|
||||||
|
const feature = {
|
||||||
|
"type": "Feature",
|
||||||
|
_matching_layer_id: "bike_repair_station",
|
||||||
|
"properties": {
|
||||||
|
id: "node/-1",
|
||||||
|
"amenity": "bicycle_repair_station"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
4.84771728515625,
|
||||||
|
51.17920846421931
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
State.state.allElements.addOrGetElement(feature)
|
||||||
|
|
||||||
|
const featureSource = new UIEventSource([{
|
||||||
|
freshness: new Date(),
|
||||||
|
feature: feature
|
||||||
|
}])
|
||||||
|
|
||||||
|
new ShowDataLayer(
|
||||||
|
featureSource,
|
||||||
|
map0.leafletMap,
|
||||||
|
new UIEventSource<LayoutConfig>(layout)
|
||||||
|
)
|
||||||
|
|
||||||
|
const map1 = new Minimap({
|
||||||
|
location: location,
|
||||||
|
allowMoving: true,
|
||||||
|
background: new AvailableBaseLayers(location).availableEditorLayers.map(layers => layers[5])
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
map1.SetStyle("width: 500px; height: 250px; overflow: hidden; border : 2px solid black")
|
||||||
|
.AttachTo("extradiv")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
new ShowDataLayer(
|
||||||
|
featureSource,
|
||||||
|
map1.leafletMap,
|
||||||
|
new UIEventSource<LayoutConfig>(layout)
|
||||||
|
)
|
||||||
|
|
||||||
|
featureSource.ping()
|
||||||
|
|
||||||
|
// */
|
Loading…
Reference in a new issue