Merge pull request #183 from tordans/add-tailwind-for-homepage

Add TailwindCSS and apply it on the homepage
This commit is contained in:
Pieter Vander Vennet 2021-01-21 23:58:10 +01:00 committed by GitHub
commit 9959b8ef51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 1718 additions and 14176 deletions

1
.tool-versions Normal file
View file

@ -0,0 +1 @@
nodejs 14.14.0

View file

@ -22,7 +22,11 @@ export default class AllTranslationAssets {
ready: new Translation( {"en":"Done!","ca":"Fet.","es":"Hecho.","nl":"Klaar!","fr":"Finis!","gl":"Feito!","de":"Erledigt!"} ),
retrying: new Translation( {"en":"Loading data failed. Trying again... ({count})","ca":"La càrrega de dades ha fallat.Tornant-ho a intentar... ({count})","es":"La carga de datos ha fallado.Volviéndolo a probar... ({count})","gl":"A carga dos datos fallou. Tentándoo de novo... ({count})","fr":"Le chargement a échoué. Essayer à nouveau... ({count})","de":"Laden von Daten fehlgeschlagen. Erneuter Versuch... ({count})"} ),
},
general: { index: new Translation( {"#":"This text is shown above the theme buttons when no theme is loaded","en":"<h3>Welcome to MapComplete</h3> MapComplete is an OpenStreetMap-viewer and editor, which shows you information about a specific theme.<br/><br/>Pick a theme below to get started.","nl":"<h3>Welkom bij MapComplete</h3> MapComplete is een OpenStreetMap applicatie waar informatie over een specifiek thema bekeken en aangepast kan worden.<br/><br/>Kies hieronder een thema om te beginnen."} ),
index: { title: new Translation( {"en":"Welcome to MapComplete","nl":"Welkom bij MapComplete"} ),
intro: new Translation( {"nl":"MapComplete is een OpenStreetMap applicatie waar informatie over een specifiek thema bekeken en aangepast kan worden.","en":"MapComplete is an OpenStreetMap-viewer and editor, which shows you information about a specific theme."} ),
pickTheme: new Translation( {"en":"Pick a theme below to get started.","nl":"Kies hieronder een thema om te beginnen."} ),
},
general: { indexTitle: new Translation( {"en":"<h1 class=''><span class='block text-gray-800 xl:inline'>Welcome to</span> <span class='block text-green-600 xl:inline'>MapComplete</span></h1><p class='mt-3 text-base font-semibold text-gray-500 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0'>MapComplete is an OpenStreetMap-viewer and editor, which shows you information about a specific theme.</p><p class='mt-3 text-base text-green-600 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0'>Pick a theme below to get started.</p>"} ),
loginWithOpenStreetMap: new Translation( {"en":"Login with OpenStreetMap","ca":"Entra a OpenStreetMap","es":"Entra en OpenStreetMap","nl":"Aanmelden met OpenStreetMap","fr":"Se connecter avec OpenStreeMap","gl":"Inicia a sesión no OpenStreetMap","de":"Anmeldung mit OpenStreetMap"} ),
welcomeBack: new Translation( {"en":"You are logged in, welcome back!","ca":"Has entrat, benvingut.","es":"Has entrado, bienvenido.","nl":"Je bent aangemeld. Welkom terug!","fr":"Vous êtes connecté. Bienvenue!","gl":"Iniciaches a sesión, benvido.","de":"Sie sind eingeloggt, willkommen zurück!"} ),
loginToStart: new Translation( {"en":"Login to answer this question","ca":"Entra per contestar aquesta pregunta","es":"Entra para contestar esta pregunta","nl":"Meld je aan om deze vraag te beantwoorden","fr":"Connectez-vous pour répondre à cette question","gl":"Inicia a sesión para responder esta pregunta","de":"Anmelden, um diese Frage zu beantworten"} ),

View file

@ -281,7 +281,7 @@ export default class LayerConfig {
let sourceParts = iconUrl.split(";");
function genHtmlFromString(sourcePart: string): UIElement {
const style = `width:100%;height:100%;transform: rotate( ${rotation} );display:block;position: absolute; top: 0, left: 0`;
const style = `width:100%;height:100%;transform: rotate( ${rotation} );display:block;position: absolute; top: 0; left: 0`;
let html: UIElement = new FixedUiElement(`<img src="${sourcePart}" style="${style}" />`);
const match = sourcePart.match(/([a-zA-Z0-9_]*):([^;]*)/)
if (match !== null && Svg.All[match[1] + ".svg"] !== undefined) {

View file

@ -43,6 +43,7 @@ export class InitUiElements {
static InitAll(layoutToUse: LayoutConfig, layoutFromBase64: string, testing: UIEventSource<string>, layoutName: string,
layoutDefinition: string = "") {
if (layoutToUse === undefined) {
console.log("Incorrect layout")
new FixedUiElement(`Error: incorrect layout <i>${layoutName}</i><br/><a href='https://${window.location.host}/'>Go back</a>`).AttachTo("centermessage").onClick(() => {
@ -78,8 +79,6 @@ export class InitUiElements {
InitUiElements.InitBaseMap();
new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration
InitUiElements.setupAllLayerElements();
if (layoutToUse.customCss !== undefined) {
@ -148,6 +147,8 @@ export class InitUiElements {
continue;
}
console.log("Creating the featureInfobox");
let start = new Date()
// This layer is the layer that gives the questions
const featureBox = new FeatureInfoBox(
State.state.allElements.getEventSourceById(data.id),
@ -159,6 +160,8 @@ export class InitUiElements {
hashText: feature.properties.id.replace("/", "_"),
titleText: featureBox.title
});
let end = new Date();
console.log("Creating featureInfoBox took", (end.getTime() - start.getTime()) , "ms")
break;
}
}
@ -215,6 +218,9 @@ export class InitUiElements {
.AttachTo("geolocate-button");
State.state.locationControl.ping();
// Reset the loading message once things are loaded
new CenterMessageBox().AttachTo("centermessage");
}
static LoadLayoutFromHash(userLayoutParam: UIEventSource<string>) {
@ -258,7 +264,8 @@ export class InitUiElements {
const fullOptions = new FullWelcomePaneWithTabs();
const help = Svg.help_svg().SetClass("open-welcome-button");
// ?-Button on Desktop, opens panel with close-X.
const help = Svg.help_svg().SetClass("open-welcome-button block");
const close = Svg.close_svg().SetClass("close-welcome-button");
const checkbox = new CheckBox(
new Combine([
@ -287,14 +294,15 @@ export class InitUiElements {
const fullOptions2 = new FullWelcomePaneWithTabs();
if (Hash.hash.data === undefined) {
if (Hash.Current() === "") {
State.state.fullScreenMessage.setData({content: fullOptions2, hashText: "welcome"})
}
// ?-Button on Mobile, opens full screen layer with close-button at the bottom
Svg.help_svg()
.SetClass("open-welcome-button")
.SetClass("shadow")
.SetClass("open-welcome-button block rounded-3xl overflow-hidden shadow ml-3")
.onClick(() => {
State.state.fullScreenMessage.setData({content: fullOptions2, hashText: "welcome"})
}).AttachTo("help-button-mobile");
@ -404,12 +412,17 @@ export class InitUiElements {
source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
if(featuresFreshness === undefined){
if (featuresFreshness === undefined) {
return;
}
let features = featuresFreshness.map(ff => ff.feature);
features.forEach(feature => {
State.state.allElements.addElement(feature);
if(Hash.hash.data === feature.properties.id.replace("/","_")){
State.state.selectedElement.setData(feature);
}
})
MetaTagging.addMetatags(features);
})
@ -456,7 +469,5 @@ export class InitUiElements {
);
});
new CenterMessageBox().AttachTo("centermessage");
}
}

View file

@ -9,11 +9,11 @@ export default class HistoryHandling {
fullscreenMessage.setData(undefined);
}
})
fullscreenMessage.addCallback(fs => {
hash.setData(fs?.hashText);
})
}
}

View file

@ -1,5 +1,5 @@
export class UIEventSource<T>{
public data: T;
private _callbacks = [];
@ -7,7 +7,6 @@ export class UIEventSource<T>{
this.data = data;
}
public addCallback(callback: ((latestData: T) => void)): UIEventSource<T> {
if(callback === console.log){
// This ^^^ actually works!
@ -49,19 +48,19 @@ export class UIEventSource<T>{
sink.setData(source.data?.data);
})
}
return sink;
}
public map<J>(f: ((T) => J),
extraSources: UIEventSource<any>[] = [],
g: ((J) => T) = undefined ): UIEventSource<J> {
const self = this;
const newSource = new UIEventSource<J>(
f(this.data)
);
const update = function () {
newSource.setData(f(self.data));
}
@ -70,17 +69,17 @@ export class UIEventSource<T>{
for (const extraSource of extraSources) {
extraSource?.addCallback(update);
}
if(g !== undefined) {
newSource.addCallback((latest) => {
self.setData(g(latest));
})
}
return newSource;
}
public syncWith(otherSource: UIEventSource<T>, reverseOverride = false): UIEventSource<T> {
this.addCallback((latest) => otherSource.setData(latest));
const self = this;
@ -94,11 +93,11 @@ export class UIEventSource<T>{
}
return this;
}
public stabilized(millisToStabilize) : UIEventSource<T>{
const newSource = new UIEventSource<T>(this.data);
let currentCallback = 0;
this.addCallback(latestData => {
currentCallback++;
@ -109,10 +108,10 @@ export class UIEventSource<T>{
}
}, millisToStabilize)
});
return newSource;
}
public static Chronic(millis: number, asLong: () => boolean = undefined): UIEventSource<Date> {
const source = new UIEventSource<Date>(undefined);
@ -125,7 +124,7 @@ export class UIEventSource<T>{
run();
return source;
}
}

View file

@ -2,7 +2,7 @@ import { Utils } from "../Utils";
export default class Constants {
public static vNumber = "0.4.9";
public static vNumber = "0.5.0-alpha-tailwind";
// The user journey states thresholds when a new feature gets unlocked
public static userJourney = {

View file

@ -81,7 +81,7 @@ I love it to see where the project ends up. You are free to reuse the software (
To develop:
0. Make sure you have a recent version of nodejs - at least 12.0, preferably 15
0. Make a fork and clone the repository.
1. Install `npm`. Linux: `sudo apt install npm` (or your favourite package manager), Windows: install nodeJS: https://nodejs.org/en/download/
2. Run `npm install` to install the package dependencies

View file

@ -81,6 +81,7 @@ export default class State {
The latest element that was selected - used to generate the right UI at the right place
*/
public readonly selectedElement = new UIEventSource<any>(undefined)
publ
public readonly featureSwitchUserbadge: UIEventSource<boolean>;
public readonly featureSwitchSearch: UIEventSource<boolean>;
@ -209,7 +210,7 @@ export default class State {
if (selected === undefined) {
h.setData("");
} else {
h.setData(selected.id)
h.setData(selected.id.replace("/","_"))
}
}
)

4
Svg.ts
View file

@ -179,7 +179,7 @@ export default class Svg {
public static josm_logo_svg() { return new FixedUiElement(Svg.josm_logo);}
public static josm_logo_ui() { return new FixedUiElement(Svg.josm_logo_img);}
public static layers = " <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\" width=\"27\" height=\"27\" viewBox=\"0 0 27 27\" fill=\"none\" version=\"1.1\" id=\"svg8\" sodipodi:docname=\"layers.svg\" inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"> <metadata id=\"metadata14\"> <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=\"defs12\" /> <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=\"namedview10\" showgrid=\"false\" inkscape:zoom=\"12.361274\" inkscape:cx=\"13.100126\" inkscape:cy=\"2.3570853\" inkscape:window-x=\"1560\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg8\" /> <path d=\"M26.5353 8.13481C26.4422 8.35428 26.2683 8.47598 26.0632 8.58537C21.9977 10.7452 17.935 12.9085 13.8758 15.0799C13.6475 15.2016 13.4831 15.1962 13.2568 15.0751C9.19822 12.903 5.13484 10.7404 1.07215 8.5758C0.490599 8.26608 0.448478 7.52562 0.991303 7.13796C1.0803 7.07438 1.17813 7.0231 1.2746 6.97045C5.15862 4.86462 9.04536 2.7629 12.9246 0.648187C13.3805 0.399316 13.7779 0.406837 14.2311 0.65434C18.0954 2.76153 21.9658 4.85779 25.8383 6.94926C26.1569 7.12155 26.411 7.32872 26.5353 7.67604C26.5353 7.82919 26.5353 7.98166 26.5353 8.13481Z\" fill=\"#003B8B\" id=\"path2\" style=\"fill:#030000;fill-opacity:1\" /> <path d=\"M13.318 26.535C12.1576 25.9046 10.9972 25.2736 9.83614 24.6439C6.96644 23.0877 4.09674 21.533 1.22704 19.9762C0.694401 19.6876 0.466129 19.2343 0.669943 18.7722C0.759621 18.5691 0.931505 18.3653 1.11969 18.2512C1.66659 17.9182 2.23727 17.6228 2.80863 17.3329C2.89423 17.2892 3.04981 17.3206 3.14493 17.3712C6.40799 19.1031 9.66969 20.837 12.9239 22.5845C13.3703 22.8238 13.7609 22.83 14.208 22.59C17.4554 20.8472 20.7117 19.1202 23.9605 17.3801C24.1493 17.2789 24.2838 17.283 24.4632 17.3876C24.8926 17.6386 25.3301 17.8772 25.7751 18.1001C26.11 18.2683 26.3838 18.4857 26.5346 18.8385C26.5346 18.9916 26.5346 19.1441 26.5346 19.2972C26.4049 19.6528 26.1399 19.8613 25.8152 20.0363C22.9964 21.5549 20.1831 23.0829 17.3684 24.609C16.1863 25.2496 15.0055 25.893 13.8248 26.535C13.6556 26.535 13.4865 26.535 13.318 26.535Z\" fill=\"#003B8B\" id=\"path4\" style=\"fill:#030000;fill-opacity:1\" /> <path d=\"M26.3988 13.7412C26.2956 13.9661 26.1026 14.081 25.8927 14.1924C21.8198 16.3577 17.749 18.5258 13.6815 20.7013C13.492 20.8025 13.3602 20.7902 13.1795 20.6938C9.09638 18.5114 5.01059 16.3359 0.924798 14.1582C0.399637 13.8786 0.307921 13.2646 0.735251 12.838C0.829005 12.7443 0.947217 12.6705 1.06407 12.6055C1.56545 12.3279 2.07635 12.0654 2.57297 11.7789C2.74214 11.6812 2.86579 11.6921 3.03291 11.7817C6.27492 13.5155 9.52303 15.2378 12.761 16.9792C13.2352 17.2343 13.6394 17.2322 14.1129 16.9772C17.3509 15.2358 20.5996 13.5142 23.8416 11.7796C24.0095 11.69 24.1338 11.6818 24.3016 11.7789C24.7384 12.0339 25.1821 12.2794 25.6352 12.5037C25.9701 12.6691 26.2426 12.8831 26.3995 13.2304C26.3988 13.4014 26.3988 13.5716 26.3988 13.7412Z\" fill=\"#003B8B\" id=\"path6\" style=\"fill:#030000;fill-opacity:1\" /> </svg> "
public static layers = " <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\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\" version=\"1.1\" id=\"svg8\" sodipodi:docname=\"layers.svg\" inkscape:version=\"0.92.5 (2060ec1f9f, 2020-04-08)\" style=\"fill:none\"> <metadata id=\"metadata14\"> <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=\"defs12\" /> <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=\"namedview10\" showgrid=\"false\" inkscape:zoom=\"5.6568542\" inkscape:cx=\"83.509105\" inkscape:cy=\"42.25915\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\" inkscape:current-layer=\"svg8\" /> <path d=\"m 99.121956,29.976384 c -0.352319,0.827558 -1.010404,1.286454 -1.786559,1.698932 C 81.950425,39.819417 66.576048,47.9766 51.214917,56.164327 50.350967,56.623222 49.728833,56.602861 48.87245,56.14622 33.513666,47.955862 18.136716,39.801316 2.7623776,31.639232 0.56162839,30.471367 0.40223092,27.679304 2.4564303,26.217549 2.7932195,25.977807 3.1634352,25.784445 3.5285042,25.585917 18.226706,17.645436 32.935202,9.7204527 47.615314,1.7464766 49.340565,0.80805546 50.844437,0.83641499 52.55947,1.769855 67.183046,9.7154641 81.829706,17.61986 96.484313,25.506193 c 1.20567,0.649657 2.167256,1.430835 2.637643,2.740479 0,0.577483 0,1.152406 0,1.72989 z\" id=\"path2\" style=\"fill:#030000;fill-opacity:1;stroke-width:3.77748823;stroke:none\" inkscape:connector-curvature=\"0\" /> <path d=\"M 49.104049,99.358227 C 44.712775,96.981166 40.321502,94.601846 35.927731,92.227428 25.067995,86.359443 14.208259,80.497116 3.3485241,74.626869 1.3328713,73.538641 0.46902716,71.829377 1.2403155,70.086931 1.5796818,69.321099 2.2301382,68.552628 2.942282,68.122389 c 2.0696204,-1.255646 4.2292307,-2.369516 6.3914144,-3.462645 0.323934,-0.164782 0.9126916,-0.04637 1.2726516,0.144418 12.348318,6.530498 24.69149,13.068538 37.006317,19.657859 1.689301,0.902332 3.167439,0.925709 4.859388,0.02073 12.289057,-6.571599 24.611793,-13.08362 36.906148,-19.645038 0.714471,-0.381596 1.223456,-0.366137 1.902355,0.02827 1.624968,0.946449 3.280589,1.846142 4.964592,2.686634 1.267353,0.634234 2.303488,1.453988 2.874156,2.784294 0,0.577297 0,1.152331 0,1.729627 -0.490824,1.340866 -1.493653,2.127059 -2.722407,2.786934 -10.667116,5.726205 -21.313419,11.487855 -31.965019,17.24234 -4.473392,2.415518 -8.941865,4.841595 -13.409958,7.262401 -0.6403,0 -1.280221,0 -1.917871,0 z\" id=\"path4\" style=\"fill:#030000;fill-opacity:1;stroke-width:3.77748823;stroke:none\" inkscape:connector-curvature=\"0\" /> <path d=\"m 98.605401,51.116473 c -0.390539,0.848033 -1.120903,1.281288 -1.915223,1.701345 C 81.277202,60.982544 65.872173,69.157826 50.479632,77.361013 49.762513,77.742609 49.263744,77.69623 48.579926,77.332731 33.128275,69.10353 17.66652,60.900342 2.204757,52.68886 0.21740311,51.63457 -0.1296755,49.319351 1.487459,47.710765 c 0.3547909,-0.353316 0.8021377,-0.631594 1.2443416,-0.876692 1.8973601,-1.046748 3.8307465,-2.03656 5.7100934,-3.11687 0.640186,-0.368399 1.1081116,-0.327298 1.74054,0.01056 12.268659,6.537662 24.560402,13.031962 36.813773,19.598282 1.794503,0.961908 3.324108,0.95399 5.115962,-0.0076 12.253485,-6.566321 24.54746,-13.05798 36.816082,-19.598659 0.63538,-0.337856 1.105765,-0.368776 1.740767,-0.0027 1.652971,0.961532 3.332054,1.887241 5.04671,2.733013 1.267354,0.623676 2.298568,1.430608 2.892325,2.740177 -0.003,0.644792 -0.003,1.286567 -0.003,1.926081 z\" id=\"path6\" style=\"fill:#030000;fill-opacity:1;stroke-width:3.77748823;stroke:none\" inkscape:connector-curvature=\"0\" /> </svg> "
public static layers_img = Img.AsImageElement(Svg.layers)
public static layers_svg() { return new FixedUiElement(Svg.layers);}
public static layers_ui() { return new FixedUiElement(Svg.layers_img);}
@ -255,7 +255,7 @@ export default class Svg {
public static ring_ui() { return new FixedUiElement(Svg.ring_img);}
public static search = " <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\"> <g id=\"search\"> <path id=\"magnifying-glass\" d=\"M1.63 9.474L4.006 7.1l.17-.1a3.45 3.45 0 0 1-.644-2.01A3.478 3.478 0 1 1 7.01 8.47 3.43 3.43 0 0 1 5 7.822l-.098.17-2.375 2.373c-.19.188-.543.142-.79-.105s-.293-.6-.104-.79zm5.378-2.27A2.21 2.21 0 1 0 4.8 4.994 2.21 2.21 0 0 0 7.01 7.21z\"/> </g> </svg>"
public static search_img = Img.AsImageElement(Svg.search)
public static search_img = Img.AsImageElement(Svg.search, 'rounded-3xl')
public static search_svg() { return new FixedUiElement(Svg.search);}
public static search_ui() { return new FixedUiElement(Svg.search_img);}

View file

@ -25,7 +25,11 @@ export default class Combine extends UIElement {
console.error("Not a UI-element", ui);
return "";
}
return ui.Render();
let rendered = ui.Render();
if(ui.IsEmpty()){
return "";
}
return rendered;
}).join("");
}

View file

@ -12,5 +12,4 @@ export class FixedUiElement extends UIElement {
return this._html;
}
}

View file

@ -4,16 +4,16 @@ import {Utils} from "../../Utils";
export default class Img {
public static runningFromConsole = false;
static AsData(source:string){
if(Utils.runningFromConsole){
return source;
}
return `data:image/svg+xml;base64,${(btoa(source))}`;
}
static AsImageElement(source: string): string{
return `<img src="${Img.AsData(source)}">`;
static AsImageElement(source: string, css_class: string = ""): string{
return `<img class="${css_class}" alt="" src="${Img.AsData(source)}">`;
}
}

View file

@ -8,25 +8,27 @@ import Ornament from "./Ornament";
* Wraps some contents into a panel that scrolls the content _under_ the title
*/
export default class ScrollableFullScreen extends UIElement {
private _component: Combine;
private _component: UIElement;
constructor(title: UIElement, content: UIElement) {
super();
const returnToTheMap = Svg.back_svg().onClick(() => {
const returnToTheMap = Svg.back_ui().onClick(() => {
State.state.fullScreenMessage.setData(undefined);
State.state.selectedElement.setData(undefined);
}).SetClass("only-on-mobile")
.SetClass("featureinfobox-back-to-the-map")
title.SetStyle("width: 100%; display: block;")
const ornament = new Combine([new Ornament().SetStyle("height:5em;")]).SetClass("only-on-mobile")
}).SetClass("block sm:hidden mb-2 bg-blue-50 rounded-full w-12 h-12 p-1.5")
title.SetClass("block w-full")
const ornament = new Combine([new Ornament().SetStyle("height:5em;")]).SetClass("sm:hidden")
this._component = new Combine([
new Combine([returnToTheMap, title]).SetClass("featureinfobox-titlebar"),
new Combine(["<span>",content,"</span>", ornament]).SetClass("featureinfobox-content"),
new Combine([returnToTheMap, title])
.AddClass("border-b-2 border-black shadow sm:shadow-none z-50 bg-white p-2 pb-0 sm:p-0 flex overflow-x-hidden flex-shrink-0 max-h-20vh"),
new Combine(["<span>", content, "</span>", ornament])
.SetClass("block p-2 sm:pt-4 w-full max-h-screen landscape:max-h-screen overflow-y-auto overflow-x-hidden"),
// We add an ornament which takes around 5em. This is in order to make sure the Web UI doesn't hide
])
this.SetClass("featureinfobox");
]).SetClass("block flex flex-col fixed max-h-screen sm:max-h-65vh sm:relative top-0 left-0 right-0");
}

View file

@ -14,20 +14,25 @@ export class SubtleButton extends UIElement{
this.linkTo = linkTo;
this.message = Translations.W(message);
if(this.message !== null){
this.message.dumbMode = false;
this.message.dumbMode = false;
}
let img;
if ((imageUrl ?? "") === "") {
this.image = new FixedUiElement("");
img = new FixedUiElement("");
} else if (typeof (imageUrl) === "string") {
this.image = new FixedUiElement(`<img style="height:3em" src="${imageUrl}">`);
img = new FixedUiElement(`<img style="width: 100%;" src="${imageUrl}" alt="">`);
} else {
this.image = imageUrl;
img = imageUrl;
}
img.AddClass("block flex items-center justify-center h-11 w-11 flex-shrink0")
this.image = new Combine([img])
.AddClass("flex-shrink-0");
}
InnerRender(): string {
if(this.message !== null && this.message.IsEmpty()){
// Message == null: special case to force empty text
return "";
@ -35,19 +40,21 @@ export class SubtleButton extends UIElement{
if(this.linkTo != undefined){
return new Combine([
`<a class="subtle-button" href="${this.linkTo.url}" ${this.linkTo.newTab ? 'target="_blank"' : ""}>`,
`<a class='block flex group p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200' href="${this.linkTo.url}" ${this.linkTo.newTab ? 'target="_blank"' : ""}>`,
this.image,
`<div class='ml-4'>`,
this.message,
'</a>'
`</div>`,
`</a>`
]).Render();
}
// Styling todo
return new Combine([
'<span class="subtle-button">',
this.image,
this.message,
'</span>'
]).Render();
]).AddClass("block flex p-3 my-2 bg-blue-100 rounded-lg hover:shadow-xl hover:bg-blue-200")
.Render();
}

View file

@ -74,7 +74,7 @@ export default class FullWelcomePaneWithTabs extends UIElement {
const backButton = new Combine([
new Combine([Translations.t.general.returnToTheMap.Clone().SetClass("to-the-map")])
.SetClass("to-the-map-inner")
]).SetClass("only-on-mobile")
.onClick(() => State.state.fullScreenMessage.setData(undefined));

View file

@ -0,0 +1,28 @@
import {UIElement} from "../UIElement";
import Combine from "../Base/Combine";
import Translations from "../i18n/Translations";
import {FixedUiElement} from "../Base/FixedUiElement";
export default class IndexText extends Combine {
constructor() {
super([
new FixedUiElement(`<img class="w-12 h-12 sm:h-24 sm:w-24" src="./assets/svg/logo.svg" alt="MapComplete Logo">`)
.AddClass("flex-none m-3"),
new Combine([
Translations.t.index.title
.AddClass("text-2xl tracking-tight font-extrabold text-gray-900 sm:text-5xl md:text-6xl block text-gray-800 xl:inline"),
Translations.t.index.intro.AddClass(
"mt-3 text-base font-semibold text-gray-500 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0"),
Translations.t.index.pickTheme.AddClass("mt-3 text-base text-green-600 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0")
]).AddClass("flex flex-col sm:text-center lg:text-left m-1 mt-2 md:m-2 md:mt-4")
]);
this.AddClass("flex flex-row");
}
}

View file

@ -29,7 +29,7 @@ export default class LayerControlPanel extends UIElement {
}
const title =Translations.t.general.layerSelection.title.SetClass("featureinfobox-title")
const title = Translations.t.general.layerSelection.title.SetClass("text-2xl break-words font-bold p-2")
this._panel = new ScrollableFullScreen(title, layerControlPanel);
}

View file

@ -11,13 +11,14 @@ import Translations from "../i18n/Translations";
import * as personal from "../../assets/themes/personalLayout/personalLayout.json"
import Constants from "../../Models/Constants";
import LanguagePicker from "../LanguagePicker";
import IndexText from "./IndexText";
export default class MoreScreen extends UIElement {
private readonly _onMainScreen: boolean;
private _component: UIElement;
constructor(onMainScreen: boolean = false) {
super(State.state.locationControl);
this._onMainScreen = onMainScreen;
@ -65,15 +66,14 @@ export default class MoreScreen extends UIElement {
}
let description = Translations.W(layout.shortDescription);
if (description !== undefined) {
description = new Combine(["<br/>", description]);
}
return new SubtleButton(layout.icon,
new Combine([
"<b>",
`<dt class='text-lg leading-6 font-medium text-gray-900 group-hover:text-blue-800'>`,
Translations.W(layout.title),
"</b>",
`</dt>`,
`<dd class='mt-1 text-base text-gray-500 group-hover:text-blue-900'>`,
description ?? "",
`</dd>`,
]), {url: linkText, newTab: false});
}
@ -83,21 +83,10 @@ export default class MoreScreen extends UIElement {
const els: UIElement[] = []
els.push(new VariableUiElement(
State.state.osmConnection.userDetails.map(userDetails => {
if (userDetails.csCount < Constants.userJourney.themeGeneratorReadOnlyUnlock) {
return tr.requestATheme.Render();
}
return new SubtleButton(Svg.pencil_ui(), tr.createYourOwnTheme, {
url: "./customGenerator.html",
newTab: false
}).Render();
})
));
const linkButton: UIElement[] = []
for (const k in AllKnownLayouts.allSets) {
const layout : LayoutConfig = AllKnownLayouts.allSets[k];
const layout: LayoutConfig = AllKnownLayouts.allSets[k];
if (k === personal.id) {
if (State.state.osmConnection.userDetails.data.csCount < Constants.userJourney.personalLayoutUnlock) {
continue;
@ -106,12 +95,25 @@ export default class MoreScreen extends UIElement {
if (layout.id !== k) {
continue; // This layout was added multiple time due to an uppercase
}
els.push(this.createLinkButton(layout));
linkButton.push(this.createLinkButton(layout));
}
els.push(new Combine(linkButton))
els.push(new VariableUiElement(
State.state.osmConnection.userDetails.map(userDetails => {
if (userDetails.csCount < Constants.userJourney.themeGeneratorReadOnlyUnlock) {
return tr.requestATheme.SetClass("block text-base mx-10 my-3").Render();
}
return new SubtleButton(Svg.pencil_ui(), tr.createYourOwnTheme, {
url: "./customGenerator.html",
newTab: false
}).Render();
})
));
const customThemesNames = State.state.installedThemes.data ?? [];
if (customThemesNames.length > 0) {
els.push(Translations.t.general.customThemeIntro)
@ -123,18 +125,19 @@ export default class MoreScreen extends UIElement {
let intro : UIElement= tr.intro;
if(this._onMainScreen){
intro = new Combine([
LanguagePicker.CreateLanguagePicker(Translations.t.general.index.SupportedLanguages())
.SetStyle("position: absolute; right: 1.5em; top: 1.5em;"),
Translations.t.general.index.SetStyle("margin-top: 2em;display:block; margin-bottom: 1em;")
])
}
this._component = new VerticalCombine([
intro,
new VerticalCombine(els),
tr.streetcomplete
LanguagePicker.CreateLanguagePicker(Translations.t.index.title.SupportedLanguages())
.SetClass("absolute top-2 right-3 dropdown-ui-element-2226"),
new IndexText()
])
}
this._component = new Combine([
intro,
new Combine(els),
tr.streetcomplete.SetClass("block text-base mx-10 my-3 mb-10")
]);
return this._component.Render();
}

View file

@ -22,7 +22,7 @@ export default class SearchAndGo extends UIElement {
);
private _foundEntries = new UIEventSource([]);
private _goButton = Svg.search_ui().SetClass('search-go');
private _goButton = Svg.search_ui().AddClass('w-8 h-8 full-rounded border-black float-right');
constructor() {
super(undefined);

View file

@ -29,7 +29,7 @@ export default class UserBadge extends UIElement {
this._loginButton = Translations.t.general.loginWithOpenStreetMap
.Clone()
.SetClass("userbadge-login")
.SetClass("userbadge-login pt-3 w-full")
.onClick(() => State.state.osmConnection.AttemptLogin());
this._logout =
Svg.logout_svg()
@ -50,7 +50,7 @@ export default class UserBadge extends UIElement {
this._homeButton = new VariableUiElement(
this._userDetails.map((userinfo) => {
if (userinfo.home) {
return Svg.home;
return Svg.home_svg().Render();
}
return "";
})

View file

@ -40,7 +40,6 @@ export default class CenterMessageBox extends UIElement {
return CenterMessageBox.prep().innerHtml;
}
InnerUpdate(htmlElement: HTMLElement) {
const pstyle = htmlElement.parentElement.style;
if (State.state.centerMessage.data != "") {

View file

@ -20,14 +20,12 @@ export default class FullScreenMessageBox extends UIElement {
return "";
}
this._content = State.state.fullScreenMessage.data.content;
return new Combine([this._content]).SetClass("fullscreenmessage-content").Render();
return new Combine([this._content])
.SetClass("block max-h-screen h-screen overflow-x-hidden overflow-y-auto bg-white p-0").Render();
}
protected InnerUpdate(htmlElement: HTMLElement) {
super.InnerUpdate(htmlElement);
// This is a bit out of place, and it is a fix specifically for the featureinfobox-titlebar
const height = htmlElement.getElementsByClassName("featureinfobox-titlebar")[0]?.clientHeight ?? 0;
htmlElement.style.setProperty("--variable-title-height", height + "px")
}

View file

@ -28,5 +28,5 @@ export default class CheckBox extends UIElement{
return Translations.W(this._showDisabled).Render();
}
}
}

View file

@ -11,13 +11,19 @@ export class DropDown<T> extends InputElement<T> {
private readonly _value: UIEventSource<T>;
public IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly _label_class: string;
private readonly _select_class: string;
constructor(label: string | UIElement,
values: { value: T, shown: string | UIElement }[],
value: UIEventSource<T> = undefined) {
value: UIEventSource<T> = undefined,
label_class: string = "",
select_class: string = "") {
super(undefined);
this._value = value ?? new UIEventSource<T>(undefined);
this._label = Translations.W(label);
this._label_class = label_class || '';
this._select_class = select_class || '';
this._values = values.map(v => {
return {
value: v.value,
@ -29,10 +35,8 @@ export class DropDown<T> extends InputElement<T> {
this.ListenTo(v.shown._source);
}
this.ListenTo(this._value);
this.onClick(() => {}) // by registering a click, the click event is consumed and doesn't bubble furter to other elements, e.g. checkboxes
this.onClick(() => {}) // by registering a click, the click event is consumed and doesn't bubble furter to other elements, e.g. checkboxes
}
GetValue(): UIEventSource<T> {
@ -52,18 +56,18 @@ export class DropDown<T> extends InputElement<T> {
if(this._values.length <=1){
return "";
}
let options = "";
for (let i = 0; i < this._values.length; i++) {
options += "<option value='" + i + "'>" + this._values[i].shown.InnerRender() + "</option>"
}
return "<form>" +
"<label for='dropdown-" + this.id + "'>" + this._label.Render() + " </label>" +
"<select name='dropdown-" + this.id + "' id='dropdown-" + this.id + "'>" +
return `<form>` +
`<label class='${this._label_class}' for='dropdown-${this.id}'>${this._label.Render()}</label>` +
`<select class='${this._select_class}' name='dropdown-${this.id}' id='dropdown-${this.id}'>` +
options +
"</select>" +
"</form>";
`</select>` +
`</form>`;
}
protected InnerUpdate(element) {

View file

@ -11,7 +11,7 @@ export class RadioButton<T> extends InputElement<T> {
private readonly value: UIEventSource<T>;
private readonly _elements: InputElement<T>[]
private readonly _selectFirstAsDefault: boolean;
constructor(elements: InputElement<T>[],
selectFirstAsDefault = true) {
super(undefined);
@ -74,14 +74,14 @@ export class RadioButton<T> extends InputElement<T> {
for (let i = 0; i < this._elements.length; i++){
const el = this._elements[i];
const htmlElement =
'<input type="radio" id="' + this.IdFor(i) + '" name="radiogroup-' + this.id + '">' +
'<label for="' + this.IdFor(i) + '">' + el.Render() + '</label>' +
'<br>';
`<label for="${this.IdFor(i)}" class="question-option-with-border">` +
`<input type="radio" id="${this.IdFor(i)}" name="radiogroup-${this.id}">` +
el.Render() +
`</label>`;
body += htmlElement;
}
return "<form id='" + this.id + "-form'>" + body + "</form>";
return `<form id='${this.id}-form'>${body}</form>`;
}
public ShowValue(t: T): boolean {

View file

@ -13,10 +13,10 @@ export default class LanguagePicker {
return undefined;
}
return new DropDown(label, languages.map(lang => {
return new DropDown("Change Language", languages.map(lang => {
return {value: lang, shown: lang}
}
), Locale.language);
), Locale.language, 'sr-only', 'bg-indigo-100 p-1 rounded hover:bg-indigo-200');
}

View file

@ -64,7 +64,7 @@ export default class EditableTagRendering extends UIElement {
return new Combine([this._answer,
(State.state?.osmConnection?.userDetails?.data?.loggedIn ?? true) ? this._editButton : undefined
]).SetClass("answer")
]).SetClass("flex w-full break-word justify-between text-default landscape:w-1/2 landscape:p-2 pb-2 border-b border-gray-300 mb-2")
.Render();
}

View file

@ -13,7 +13,7 @@ export default class FeatureInfoBox extends UIElement {
private _component: UIElement;
public title: UIElement ;
constructor(
tags: UIEventSource<any>,
layerConfig: LayerConfig
@ -25,11 +25,12 @@ export default class FeatureInfoBox extends UIElement {
const title = new TagRenderingAnswer(tags, layerConfig.title ?? new TagRenderingConfig("POI", undefined))
.SetClass("featureinfobox-title");
.AddClass("text-2xl break-words font-bold p-2");
this.title = title;
const titleIcons = new Combine(
layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon)))
.SetClass("featureinfobox-icons");
layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon)
.AddClass("block w-8 h-8 align-baseline box-content p-0.5")))
.AddClass("flex flex-row flex-wrap pt-1 items-center mr-2");
let questionBox: UIElement = undefined;
if (State.state.featureSwitchUserbadge.data) {
@ -57,7 +58,7 @@ export default class FeatureInfoBox extends UIElement {
]
)
const titleBar = new Combine([
new Combine([title, titleIcons]).SetClass("featureinfobox-titlebar-title")
new Combine([title, titleIcons]).SetClass("flex flex-grow justify-between")
])
this._component = new ScrollableFullScreen(titleBar, content)

View file

@ -40,7 +40,6 @@ export default class QuestionBox extends UIElement {
})
));
this._skippedQuestionsButton = Translations.t.general.skippedQuestions.Clone()
.onClick(() => {
self._skippedQuestions.setData([]);
@ -64,19 +63,19 @@ export default class QuestionBox extends UIElement {
}
}
}
if (tagRendering.GetRenderValue(this._tags.data) !== undefined) {
// This value is known and can be rendered
return true;
}
return false;
}
InnerRender(): string {
for (let i = 0; i < this._tagRenderingQuestions.length; i++) {
let tagRendering = this._tagRenderings[i];
if(this.IsKnown(tagRendering)){
continue;
}

View file

@ -21,6 +21,7 @@ export default class TagRenderingAnswer extends UIElement {
if (configuration === undefined) {
throw "Trying to generate a tagRenderingAnswer without configuration..."
}
this.AddClass("flex items-center flex-row text-lg")
}
InnerRender(): string {
@ -34,11 +35,6 @@ export default class TagRenderingAnswer extends UIElement {
if (tags === undefined) {
return "";
}
const tr = this._configuration.GetRenderValue(tags);
if (tr !== undefined) {
this._content = new SubstitutedTranslation(tr, this._tags);
return this._content.Render();
}
// The render value doesn't work well with multi-answers (checkboxes), so we have to check for them manually
if (this._configuration.multiAnswer) {
@ -65,6 +61,14 @@ export default class TagRenderingAnswer extends UIElement {
return this._content.Render();
}
}
const tr = this._configuration.GetRenderValue(tags);
if (tr !== undefined) {
this._content = new SubstitutedTranslation(tr, this._tags);
return this._content.Render();
}
return "";
}

View file

@ -78,7 +78,6 @@ export default class TagRenderingQuestion extends UIElement {
if (csCount < Constants.userJourney.tagsVisibleAt) {
return "";
}
if (tags === undefined) {
return Translations.t.general.noTagsSelected.SetClass("subtle").Render();
}
@ -89,8 +88,7 @@ export default class TagRenderingQuestion extends UIElement {
return tags.asHumanString(true, true);
}
)
)
).AddClass("block")
}
private GenerateInputElement(): InputElement<TagsFilter> {
@ -104,9 +102,6 @@ export default class TagRenderingQuestion extends UIElement {
return ff;
}
mappings = Utils.NoNull([...mappings, ff]);
mappings.forEach(el => el.SetClass("question-option-with-border"))
if (this._configuration.multiAnswer) {
return this.GenerateMultiAnswer(mappings, ff)
} else {
@ -268,16 +263,16 @@ export default class TagRenderingQuestion extends UIElement {
}
InnerRender(): string {
return new Combine([
this._question,
this._inputElement, "<br/>",
this._inputElement,
this._cancelButton,
this._saveButton, "<br/>",
this._appliedTags])
.SetClass("question")
.Render()
this._saveButton,
this._appliedTags]
)
.SetClass("question")
.Render()
}
}

View file

@ -87,11 +87,11 @@ export default class ReviewForm extends InputElement<Review> {
}
InnerRender(): string {
if(!this.userDetails.data.loggedIn){
return Translations.t.reviews.plz_login.Render();
}
return new Combine([
new Combine([this._stars, this._postingAs]).SetClass("review-form-top"),
this._comment,

View file

@ -69,7 +69,7 @@ export default class ShowDataLayer {
action();
}
});
Hash.hash.addCallback(id => {
Hash.hash.addCallbackAndRun(id => {
// This is a bit of an edge case: if the hash becomes an id to search, we have to show the corresponding popup
if(State.state.selectedElement !== undefined){
return; // Something is already selected, we don't have to apply this fix
@ -130,6 +130,9 @@ export default class ShowDataLayer {
"<div style='height: 90vh'>Rendering</div>");
popup.setContent(uiElement.Render());
popup.on('remove', () => {
if(!popup.isOpen()){
return;
}
State.state.selectedElement.setData(undefined);
});
leafletLayer.bindPopup(popup);

View file

@ -1,5 +1,4 @@
import {UIEventSource} from "../Logic/UIEventSource";
import Constants from "../Models/Constants";
import {Utils} from "../Utils";
export abstract class UIElement extends UIEventSource<string> {
@ -8,7 +7,7 @@ export abstract class UIElement extends UIEventSource<string> {
public readonly id: string;
public readonly _source: UIEventSource<any>;
public dumbMode = false;
private clss: string[] = []
private clss: Set<string> = new Set<string>();
private style: string;
private _hideIfEmpty = false;
private lastInnerRender: string;
@ -110,7 +109,7 @@ export abstract class UIElement extends UIEventSource<string> {
}
HideOnEmpty(hide: boolean) {
HideOnEmpty(hide: boolean): UIElement {
this._hideIfEmpty = hide;
this.Update();
return this;
@ -127,8 +126,8 @@ export abstract class UIElement extends UIEventSource<string> {
style = `style="${this.style}" `;
}
let clss = "";
if (this.clss.length > 0) {
clss = `class='${this.clss.join(" ")}' `;
if (this.clss.size > 0) {
clss = `class='${Array.from(this.clss).join(" ")}' `;
}
return `<span ${clss}${style}id='${this.id}'>${this.lastInnerRender}</span>`
}
@ -151,20 +150,34 @@ export abstract class UIElement extends UIEventSource<string> {
}
public SetClass(clss: string): UIElement {
return this.AddClass(clss);
}
/**
* Adds all the relevant classes, space seperated
* @param clss
* @constructor
*/
public AddClass(clss: string) {
this.dumbMode = false;
if (clss === "" && this.clss.length > 0) {
throw "Use RemoveClass instead";
} else if (this.clss.indexOf(clss) < 0) {
this.clss.push(clss);
const all = clss.split(" ");
let recordedChange = false;
for (const c of all) {
if (this.clss.has(clss)) {
continue;
}
this.clss.add(c);
recordedChange = true;
}
if (recordedChange) {
this.Update();
}
return this;
}
public RemoveClass(clss: string): UIElement {
const i = this.clss.indexOf(clss);
if (i >= 0) {
this.clss.splice(i, 1);
if (this.clss.has(clss)) {
this.clss.delete(clss);
this.Update();
}
return this;

View file

@ -73,68 +73,68 @@
{
"if": "bicycle_parking=stands",
"then": {
"en": "Staple racks <img width='150px' src='./assets/layers/bike_parking/staple.svg'>",
"nl": "Nietjes <img width='150px' src='./assets/layers/bike_parking/staple.svg'>",
"fr": "Arceaux <img width='150px' src='./assets/layers/bike_parking/staple.svg'>",
"gl": "De roda (Stands) <img width='150px' src='./assets/layers/bike_parking/staple.svg'>",
"de": "Fahrradbügel <img width='150px' src='./assets/layers/bike_parking/staple.svg'>"
"en": "Staple racks <img style='width: 25%' src='./assets/layers/bike_parking/staple.svg'>",
"nl": "Nietjes <img style='width: 25%'' src='./assets/layers/bike_parking/staple.svg'>",
"fr": "Arceaux <img style='width: 25%'' src='./assets/layers/bike_parking/staple.svg'>",
"gl": "De roda (Stands) <img style='width: 25%'' src='./assets/layers/bike_parking/staple.svg'>",
"de": "Fahrradbügel <img style='width: 25%'' src='./assets/layers/bike_parking/staple.svg'>"
}
},
{
"if": "bicycle_parking=wall_loops",
"then": {
"en": "Wheel rack/loops <img width='150px' src='./assets/layers/bike_parking/wall_loops.svg'>",
"nl": "Wielrek/lussen <img width='150px' src='./assets/layers/bike_parking/wall_loops.svg'>",
"fr": "Pinces-roues <img width='150px' src='./assets/layers/bike_parking/wall_loops.svg'>",
"gl": "Aros <img width='150px' src='./assets/layers/bike_parking/wall_loops.svg'>",
"de": "Metallgestänge <img width='150px' src='./assets/layers/bike_parking/wall_loops.svg'>"
"en": "Wheel rack/loops <img style='width: 25%'' src='./assets/layers/bike_parking/wall_loops.svg'>",
"nl": "Wielrek/lussen <img style='width: 25%'' src='./assets/layers/bike_parking/wall_loops.svg'>",
"fr": "Pinces-roues <img style='width: 25%'' src='./assets/layers/bike_parking/wall_loops.svg'>",
"gl": "Aros <img style='width: 25%'' src='./assets/layers/bike_parking/wall_loops.svg'>",
"de": "Metallgestänge <img style='width: 25%'' src='./assets/layers/bike_parking/wall_loops.svg'>"
}
},
{
"if": "bicycle_parking=handlebar_holder",
"then": {
"en": "Handlebar holder <img width='150px' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"nl": "Stuurhouder <img width='150px' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"fr": "Support guidon <img width='150px' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"gl": "Cadeado para guiador <img width='150px' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"de": "Halter für Fahrradlenker <img width='150px' src='./assets/layers/bike_parking/handlebar_holder.svg'>"
"en": "Handlebar holder <img style='width: 25%'' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"nl": "Stuurhouder <img style='width: 25%'' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"fr": "Support guidon <img style='width: 25%'' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"gl": "Cadeado para guiador <img style='width: 25%'' src='./assets/layers/bike_parking/handlebar_holder.svg'>",
"de": "Halter für Fahrradlenker <img style='width: 25%'' src='./assets/layers/bike_parking/handlebar_holder.svg'>"
}
},
{
"if": "bicycle_parking=rack",
"then": {
"en": "Rack <img width='150px' src='./assets/layers/bike_parking/rack.svg'>",
"nl": "Rek <img width='150px' src='./assets/layers/bike_parking/rack.svg'>",
"fr": "Râtelier <img width='150px' src='./assets/layers/bike_parking/rack.svg'>",
"gl": "Cremalleira <img width='150px' src='./assets/layers/bike_parking/rack.svg'>",
"de": "Gestell <img width='150px' src='./assets/layers/bike_parking/rack.svg'>"
"en": "Rack <img style='width: 25%'' src='./assets/layers/bike_parking/rack.svg'>",
"nl": "Rek <img style='width: 25%'' src='./assets/layers/bike_parking/rack.svg'>",
"fr": "Râtelier <img style='width: 25%'' src='./assets/layers/bike_parking/rack.svg'>",
"gl": "Cremalleira <img style='width: 25%'' src='./assets/layers/bike_parking/rack.svg'>",
"de": "Gestell <img style='width: 25%'' src='./assets/layers/bike_parking/rack.svg'>"
}
},
{
"if": "bicycle_parking=two_tier",
"then": {
"en": "Two-tiered <img width='150px' src='./assets/layers/bike_parking/two_tier.svg'>",
"nl": "Dubbel (twee verdiepingen) <img width='150px' src='./assets/layers/bike_parking/two_tier.svg'>",
"fr": "Superposé <img width='150px' src='./assets/layers/bike_parking/two_tier.svg'>",
"gl": "Dobre cremalleira <img width='150px' src='./assets/layers/bike_parking/two_tier.svg'>",
"de": "Zweistufig <img width='150px' src='./assets/layers/bike_parking/two_tier.svg'>"
"en": "Two-tiered <img style='width: 25%'' src='./assets/layers/bike_parking/two_tier.svg'>",
"nl": "Dubbel (twee verdiepingen) <img style='width: 25%'' src='./assets/layers/bike_parking/two_tier.svg'>",
"fr": "Superposé <img style='width: 25%'' src='./assets/layers/bike_parking/two_tier.svg'>",
"gl": "Dobre cremalleira <img style='width: 25%'' src='./assets/layers/bike_parking/two_tier.svg'>",
"de": "Zweistufig <img style='width: 25%'' src='./assets/layers/bike_parking/two_tier.svg'>"
}
},
{
"if": "bicycle_parking=shed",
"then": {
"en": "Shed <img width='150px' src='./assets/layers/bike_parking/shed.svg'>",
"nl": "Schuur <img width='150px' src='./assets/layers/bike_parking/shed.svg'>",
"fr": "Abri <img width='150px' src='./assets/layers/bike_parking/shed.svg'>",
"gl": "Abeiro <img width='150px' src='./assets/layers/bike_parking/shed.svg'>",
"de": "Schuppen <img width='150px' src='./assets/layers/bike_parking/shed.svg'>"
"en": "Shed <img style='width: 25%'' src='./assets/layers/bike_parking/shed.svg'>",
"nl": "Schuur <img style='width: 25%'' src='./assets/layers/bike_parking/shed.svg'>",
"fr": "Abri <img style='width: 25%'' src='./assets/layers/bike_parking/shed.svg'>",
"gl": "Abeiro <img style='width: 25%'' src='./assets/layers/bike_parking/shed.svg'>",
"de": "Schuppen <img style='width: 25%'' src='./assets/layers/bike_parking/shed.svg'>"
}
},
{
"if": "bicycle_parking=bollard",
"then": {
"en": "Bollard <img width='150px' src='./assets/layers/bike_parking/bollard.svg'>",
"nl": "Paal met ring <img width='150px' src='./assets/layers/bike_parking/bollard.svg'>"
"en": "Bollard <img style='width: 25%'' src='./assets/layers/bike_parking/bollard.svg'>",
"nl": "Paal met ring <img style='width: 25%'' src='./assets/layers/bike_parking/bollard.svg'>"
}
},
{

View file

@ -7,14 +7,14 @@
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"
width="27"
height="27"
viewBox="0 0 27 27"
fill="none"
width="100"
height="100"
viewBox="0 0 100 100"
version="1.1"
id="svg8"
sodipodi:docname="layers.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
style="fill:none">
<metadata
id="metadata14">
<rdf:RDF>
@ -23,6 +23,7 @@
<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>
@ -37,30 +38,30 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1680"
inkscape:window-height="1013"
inkscape:window-width="1920"
inkscape:window-height="999"
id="namedview10"
showgrid="false"
inkscape:zoom="12.361274"
inkscape:cx="13.100126"
inkscape:cy="2.3570853"
inkscape:window-x="1560"
inkscape:zoom="5.6568542"
inkscape:cx="83.509105"
inkscape:cy="42.25915"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<path
d="M26.5353 8.13481C26.4422 8.35428 26.2683 8.47598 26.0632 8.58537C21.9977 10.7452 17.935 12.9085 13.8758 15.0799C13.6475 15.2016 13.4831 15.1962 13.2568 15.0751C9.19822 12.903 5.13484 10.7404 1.07215 8.5758C0.490599 8.26608 0.448478 7.52562 0.991303 7.13796C1.0803 7.07438 1.17813 7.0231 1.2746 6.97045C5.15862 4.86462 9.04536 2.7629 12.9246 0.648187C13.3805 0.399316 13.7779 0.406837 14.2311 0.65434C18.0954 2.76153 21.9658 4.85779 25.8383 6.94926C26.1569 7.12155 26.411 7.32872 26.5353 7.67604C26.5353 7.82919 26.5353 7.98166 26.5353 8.13481Z"
fill="#003B8B"
d="m 99.121956,29.976384 c -0.352319,0.827558 -1.010404,1.286454 -1.786559,1.698932 C 81.950425,39.819417 66.576048,47.9766 51.214917,56.164327 50.350967,56.623222 49.728833,56.602861 48.87245,56.14622 33.513666,47.955862 18.136716,39.801316 2.7623776,31.639232 0.56162839,30.471367 0.40223092,27.679304 2.4564303,26.217549 2.7932195,25.977807 3.1634352,25.784445 3.5285042,25.585917 18.226706,17.645436 32.935202,9.7204527 47.615314,1.7464766 49.340565,0.80805546 50.844437,0.83641499 52.55947,1.769855 67.183046,9.7154641 81.829706,17.61986 96.484313,25.506193 c 1.20567,0.649657 2.167256,1.430835 2.637643,2.740479 0,0.577483 0,1.152406 0,1.72989 z"
id="path2"
style="fill:#030000;fill-opacity:1" />
style="fill:#030000;fill-opacity:1;stroke-width:3.77748823;stroke:none"
inkscape:connector-curvature="0" />
<path
d="M13.318 26.535C12.1576 25.9046 10.9972 25.2736 9.83614 24.6439C6.96644 23.0877 4.09674 21.533 1.22704 19.9762C0.694401 19.6876 0.466129 19.2343 0.669943 18.7722C0.759621 18.5691 0.931505 18.3653 1.11969 18.2512C1.66659 17.9182 2.23727 17.6228 2.80863 17.3329C2.89423 17.2892 3.04981 17.3206 3.14493 17.3712C6.40799 19.1031 9.66969 20.837 12.9239 22.5845C13.3703 22.8238 13.7609 22.83 14.208 22.59C17.4554 20.8472 20.7117 19.1202 23.9605 17.3801C24.1493 17.2789 24.2838 17.283 24.4632 17.3876C24.8926 17.6386 25.3301 17.8772 25.7751 18.1001C26.11 18.2683 26.3838 18.4857 26.5346 18.8385C26.5346 18.9916 26.5346 19.1441 26.5346 19.2972C26.4049 19.6528 26.1399 19.8613 25.8152 20.0363C22.9964 21.5549 20.1831 23.0829 17.3684 24.609C16.1863 25.2496 15.0055 25.893 13.8248 26.535C13.6556 26.535 13.4865 26.535 13.318 26.535Z"
fill="#003B8B"
d="M 49.104049,99.358227 C 44.712775,96.981166 40.321502,94.601846 35.927731,92.227428 25.067995,86.359443 14.208259,80.497116 3.3485241,74.626869 1.3328713,73.538641 0.46902716,71.829377 1.2403155,70.086931 1.5796818,69.321099 2.2301382,68.552628 2.942282,68.122389 c 2.0696204,-1.255646 4.2292307,-2.369516 6.3914144,-3.462645 0.323934,-0.164782 0.9126916,-0.04637 1.2726516,0.144418 12.348318,6.530498 24.69149,13.068538 37.006317,19.657859 1.689301,0.902332 3.167439,0.925709 4.859388,0.02073 12.289057,-6.571599 24.611793,-13.08362 36.906148,-19.645038 0.714471,-0.381596 1.223456,-0.366137 1.902355,0.02827 1.624968,0.946449 3.280589,1.846142 4.964592,2.686634 1.267353,0.634234 2.303488,1.453988 2.874156,2.784294 0,0.577297 0,1.152331 0,1.729627 -0.490824,1.340866 -1.493653,2.127059 -2.722407,2.786934 -10.667116,5.726205 -21.313419,11.487855 -31.965019,17.24234 -4.473392,2.415518 -8.941865,4.841595 -13.409958,7.262401 -0.6403,0 -1.280221,0 -1.917871,0 z"
id="path4"
style="fill:#030000;fill-opacity:1" />
style="fill:#030000;fill-opacity:1;stroke-width:3.77748823;stroke:none"
inkscape:connector-curvature="0" />
<path
d="M26.3988 13.7412C26.2956 13.9661 26.1026 14.081 25.8927 14.1924C21.8198 16.3577 17.749 18.5258 13.6815 20.7013C13.492 20.8025 13.3602 20.7902 13.1795 20.6938C9.09638 18.5114 5.01059 16.3359 0.924798 14.1582C0.399637 13.8786 0.307921 13.2646 0.735251 12.838C0.829005 12.7443 0.947217 12.6705 1.06407 12.6055C1.56545 12.3279 2.07635 12.0654 2.57297 11.7789C2.74214 11.6812 2.86579 11.6921 3.03291 11.7817C6.27492 13.5155 9.52303 15.2378 12.761 16.9792C13.2352 17.2343 13.6394 17.2322 14.1129 16.9772C17.3509 15.2358 20.5996 13.5142 23.8416 11.7796C24.0095 11.69 24.1338 11.6818 24.3016 11.7789C24.7384 12.0339 25.1821 12.2794 25.6352 12.5037C25.9701 12.6691 26.2426 12.8831 26.3995 13.2304C26.3988 13.4014 26.3988 13.5716 26.3988 13.7412Z"
fill="#003B8B"
d="m 98.605401,51.116473 c -0.390539,0.848033 -1.120903,1.281288 -1.915223,1.701345 C 81.277202,60.982544 65.872173,69.157826 50.479632,77.361013 49.762513,77.742609 49.263744,77.69623 48.579926,77.332731 33.128275,69.10353 17.66652,60.900342 2.204757,52.68886 0.21740311,51.63457 -0.1296755,49.319351 1.487459,47.710765 c 0.3547909,-0.353316 0.8021377,-0.631594 1.2443416,-0.876692 1.8973601,-1.046748 3.8307465,-2.03656 5.7100934,-3.11687 0.640186,-0.368399 1.1081116,-0.327298 1.74054,0.01056 12.268659,6.537662 24.560402,13.031962 36.813773,19.598282 1.794503,0.961908 3.324108,0.95399 5.115962,-0.0076 12.253485,-6.566321 24.54746,-13.05798 36.816082,-19.598659 0.63538,-0.337856 1.105765,-0.368776 1.740767,-0.0027 1.652971,0.961532 3.332054,1.887241 5.04671,2.733013 1.267354,0.623676 2.298568,1.430608 2.892325,2.740177 -0.003,0.644792 -0.003,1.286567 -0.003,1.926081 z"
id="path6"
style="fill:#030000;fill-opacity:1" />
style="fill:#030000;fill-opacity:1;stroke-width:3.77748823;stroke:none"
inkscape:connector-curvature="0" />
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -24,7 +24,6 @@
"startZoom": 1,
"widenFactor": 0.05,
"socialImage": "",
"customCss": "./assets/themes/surveillance_cameras/custom_theme.css",
"defaultBackgroundId": "Stadia.AlidadeSmoothDark",
"layers": [
"direction",

View file

@ -161,14 +161,29 @@
"de": "Laden von Daten fehlgeschlagen. Erneuter Versuch... ({count})"
}
},
"general": {
"index": {
"#": "This text is shown above the theme buttons when no theme is loaded",
"en": "<h3>Welcome to MapComplete</h3> MapComplete is an OpenStreetMap-viewer and editor, which shows you information about a specific theme.<br/><br/>Pick a theme below to get started.",
"nl": "<h3>Welkom bij MapComplete</h3> MapComplete is een OpenStreetMap applicatie waar informatie over een specifiek thema bekeken en aangepast kan worden.<br/><br/>Kies hieronder een thema om te beginnen."
"index": {
"#": "These texts are shown above the theme buttons when no theme is loaded",
"title": {
"en": "Welcome to MapComplete",
"nl": "Welkom bij MapComplete"
},
"intro": {
"nl": "MapComplete is een OpenStreetMap applicatie waar informatie over een specifiek thema bekeken en aangepast kan worden.",
"en": "MapComplete is an OpenStreetMap-viewer and editor, which shows you information about a specific theme."
},
"pickTheme": {
"en": "Pick a theme below to get started.",
"nl": "Kies hieronder een thema om te beginnen."
}
},
"general": {
"indexTitle": {
"en": "<h1 class=''><span class='block text-gray-800 xl:inline'>Welcome to</span> <span class='block text-green-600 xl:inline'>MapComplete</span></h1><p class='mt-3 text-base font-semibold text-gray-500 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0'>MapComplete is an OpenStreetMap-viewer and editor, which shows you information about a specific theme.</p><p class='mt-3 text-base text-green-600 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0'>Pick a theme below to get started.</p>"
},
"loginWithOpenStreetMap": {
"en": "Login with OpenStreetMap",
"ca": "Entra a OpenStreetMap",
@ -661,22 +676,22 @@
"de": "<h3>Weitere Quests</h3>Sammeln Sie gerne Geodaten? <br/>Es sind weitere Themen verfügbar."
},
"requestATheme": {
"en": "If you want a custom-built quest, request it <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>here</a>",
"ca": "Si vols que et fem una petició pròpia , demana-la <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>aquí</a>",
"es": "Si quieres que te hagamos una petición propia , pídela <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>aquí</a>",
"nl": "Wil je een eigen kaartthema, vraag dit <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>hier aan</a>",
"fr": "Si vous voulez une autre carte thématique, demande-la <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>ici</a>",
"gl": "Se queres que che fagamos unha tarefa propia , pídea <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>aquí</a>",
"de": "Wenn Sie einen speziell angefertigte Quest wünschen, können Sie diesen <a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'>hier</a> anfragen"
"en": "If you want a custom-built quest, request it <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>here</a>.",
"ca": "Si vols que et fem una petició pròpia , demana-la <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>aquí</a>.",
"es": "Si quieres que te hagamos una petición propia , pídela <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>aquí</a>.",
"nl": "Wil je een eigen kaartthema, vraag dit <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>hier aan</a>.",
"fr": "Si vous voulez une autre carte thématique, demande-la <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>ici</a>.",
"gl": "Se queres que che fagamos unha tarefa propia , pídea <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>aquí</a>.",
"de": "Wenn Sie einen speziell angefertigte Quest wünschen, können Sie diesen <a href='https://github.com/pietervdvn/MapComplete/issues' class='underline hover:text-blue-800' target='_blank'>hier</a> anfragen."
},
"streetcomplete": {
"en": "Another, similar application is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
"ca": "Una altra aplicació similar és <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
"es": "Otra aplicación similar es <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>",
"gl": "Outra aplicación semellante é <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' target='_blank'>StreetComplete</a>",
"de": "Eine andere, ähnliche Anwendung ist <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' class='underline hover:text-blue-800' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>..",
"ca": "Una altra aplicació similar és <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.",
"es": "Otra aplicación similar es <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.",
"fr": "Une autre application similaire est <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.",
"nl": "Een andere, gelijkaardige Android-applicatie is <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.",
"gl": "Outra aplicación semellante é <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>.",
"de": "Eine andere, ähnliche Anwendung ist <a href='https://play.google.com/store/apps/details?id=de.westnordost.streetcomplete' class='underline hover:text-blue-800' target='_blank'>StreetComplete</a>."
},
"createYourOwnTheme": {
"en": "Create your own MapComplete theme from scratch",
@ -775,7 +790,7 @@
"nl": "Selecteer lagen"
}
},
"weekdays": {
"abbreviations": {
"monday": {

View file

@ -1,44 +0,0 @@
.fullscreenmessage-content {
max-height: calc(100vh);
height: 100%;
overflow-y: auto;
overflow-x: hidden;
background-color: var(--background-color);
display: block;
}
.fullscreenmessage-content .featureinfobox {
padding-top: 1em;
position: relative;
}
.fullscreenmessage-content .featureinfobox-content {
padding: 1em;
top: var(--variable-title-height);
max-height: calc(100vh - var(--variable-title-height)) !important;
min-height: calc(100vh - var(--variable-title-height)) !important;
position: absolute;
overflow-y: auto;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: space-between
}
.fullscreenmessage-content .featureinfobox-titlebar {
position: fixed;
top: 0;
left: 0;
z-index: 10001;
background-color: var(--background-color);
padding: 0.5em;
width: 100%;
box-sizing: border-box;
}
.fullscreenmessage-content .featureinfobox-tail {
/*THe ornament to give the URL bar some room...*/
}

View file

@ -11,11 +11,11 @@ Contains tweaks for small screens
@media only screen and (max-width: 600px), only screen and (max-height: 600px) {
.only-on-mobile {
display: unset !important;
display: unset !important;
background-color: var(--background-color);
color: var(--foreground-color);
}
.hidden-on-mobile {
display: none !important;
}
@ -39,7 +39,7 @@ Contains tweaks for small screens
#geolocate-button {
display: block;
}
.leaflet-popup {
/* On mobile, the popups are shown as a full-screen element */
display: none;
@ -52,7 +52,7 @@ Contains tweaks for small screens
width: 60%;
}
.add-popup-all-buttons {
/* Buttons in the 'add new point' have a default of 50vh maxheight which is ugly in the new context*/
max-height: unset !important;
@ -60,7 +60,7 @@ Contains tweaks for small screens
#messagesboxmobile {
display: block;
position: absolute;
z-index: 10000;
width: 100vw;
@ -92,12 +92,6 @@ Contains tweaks for small screens
.userbadge-login {
min-width: unset;
width: calc(100vw - 5px);
}
#topleft-tools {
padding: 0.2em !important;
padding-top: 0.3em !important;
}
#userbadge {

View file

@ -1,99 +1,19 @@
.featureinfobox {
display: flex;
flex-direction: column;
}
.featureinfobox-title {
font-size: xx-large;
word-break: break-word;
}
.featureinfobox-icons img {
max-height: 1.5em;
width: 1.5em;
}
.featureinfobox-icons {
margin-left: auto;
}
.featureinfobox-icons span {
display: inline-block;
padding-right: 0.1em;
}
.featureinfobox-titlebar {
border-bottom: 2px solid var(--foreground-color);
box-shadow: 0 10px 10px -10px var(--shadow-color);
display: flex;
justify-content: space-between;
width: 100%;
overflow-x: hidden;
}
.featureinfobox-titlebar-title {
font-size: large;
font-weight: bold;
display: flex;
justify-content: space-between;
flex-grow: 2;
word-break: break-all;
}
.featureinfobox-back-to-the-map {
padding: 0.5em;
border-radius: 999em;
margin-right: 0.4em;
width: 2em;
height: 2em;
background: var(--subtle-detail-color);
flex-shrink: 0;
}
.featureinfobox-back-to-the-map svg {
width: 1.75em;
height: 1.75em;
margin-left: 0.15em;
margin-top: 0.15em
}
.featureinfobox-back-to-the-map svg path{
stroke: var(--subtle-detail-color-contrast) !important;
}
.featureinfobox-content {
display: block;
max-height: 75vh;
overflow-y: auto;
padding-top: 1em;
width:100%;
overflow-x: hidden;
}
@media only screen and (max-width: 600px), only screen and (max-height: 600px) {
.featureinfobox-content {
display: block;
max-height: unset !important;
overflow-y: auto;
}
}
@media only screen and (max-height: 600px) and (min-width: 600px) {
/* landscape mode: the first tagrendering of the infobox gets a special treatment and is placed on the right*/
.featureinfobox-content {
position: relative;
width: 100% !important;
max-width: unset !important;
max-height: unset !important;
height: 100vh;
.landscape\:max-h-screen {
max-height: 100vh;
}
.answer {
max-width: 48% !important;
padding-right: 0.3em;
box-sizing: border-box;
.landscape\:w-1\/2 {
width: 50%
}
.landscape\:p-2 {
padding: 0.5rem;
}
.question {
@ -111,15 +31,6 @@
}
}
.answer {
display: flex;
width: 100%;
font-size: large;
justify-content: space-between;
word-break: break-word;
}
.question .form-text-field > input {
width: 100%;
box-sizing: border-box;
@ -165,13 +76,11 @@
.question-option-with-border {
border: 2px solid lightgray;
border-radius: 0.5em;
display: inline-block;
display: block;
width: 100%;
margin: 0;
margin-left: -2em;
margin: 5px 0;
box-sizing: border-box;
padding: 0.5em;
padding-left: 2em;
}
input:checked + label .question-option-with-border {
@ -268,6 +177,7 @@ input:checked + label .question-option-with-border {
position: fixed;
width: 100vw;
bottom: 0;
z-index: 100000;
}
.to-the-map-inner{

View file

@ -2,16 +2,12 @@
display: inline-block;
background-color: var(--background-color);
color: var(--foreground-color);
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
border-bottom-right-radius: 1.5em;
border-top-right-radius: 1.5em;
margin: 0;
margin-bottom: 0.5em;
width: 100%;
min-width: 20em;
pointer-events: all;
border-radius: 999em;
}
#userbadge a {
@ -63,11 +59,9 @@
height: 4em;
padding: 0;
margin: 0;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
opacity: 0;
transition: opacity 500ms linear;
border-radius: 999em;
}
.usertext {
@ -101,11 +95,6 @@
display: inline-block;
text-align: center;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
border-bottom-right-radius: 1.5em;
border-top-right-radius: 1.5em;
margin: 0;
min-width: 20em;

158
index.css
View file

@ -1,3 +1,20 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
@variants responsive {
.max-h-65vh {
max-height: 65vh;
}
.max-h-20vh {
max-height: 20vh;
}
}
}
:root {
--subtle-detail-color: #e5f5ff;
--subtle-detail-color-contrast: black;
@ -25,10 +42,20 @@ html, body {
font-family: 'Helvetica Neue', Arial, sans-serif;
}
svg, img {
box-sizing: content-box;
width: 100%;
height: 100%;
}
a {
color: var(--foreground-color)
}
#topleft-tools svg {
fill: var(--foreground-color) !important;
stroke: var(--foreground-color) !important;
@ -87,14 +114,10 @@ a {
}
#layer-selection {
position: absolute;
bottom: 1em;
left: 1em;
z-index: 9000;
background-color: var(--background-color);
color: var(--foreground-color);
border-radius: 1em;
cursor: pointer;
box-shadow: 0 0 10px var(--shadow-color);
}
@ -119,10 +142,8 @@ a {
.simple-add-ui-icon {
position: relative;
display: block;
width: 3.5em;
width: 4em;
height: 3.5em;
padding-right: 0.3em;
padding-left: 0.3em;
}
.simple-add-ui-icon img {
@ -136,7 +157,6 @@ a {
}
.layer-selection-toggle {
border-radius: 1em;
display: flex;
flex-direction: column-reverse;
background: var(--subtle-detail-color);
@ -238,7 +258,6 @@ a {
transition: all 500ms linear;
pointer-events: all;
border-radius: 1.3em;
margin: 0 0 0.5em;
width: 100%;
}
@ -271,17 +290,6 @@ a {
color: var(--foreground-color);
}
.search-go img {
position: relative;
float: right;
height: 1.2em;
border: 2px solid black;
border-radius: 2em;
padding: 0.4em;
margin-left: 0.5em;
margin-right: 0;
}
.add-popup-all-buttons {
max-height: 50vh;
@ -300,8 +308,8 @@ a {
z-index: 5000;
transition: all 500ms linear;
pointer-events: none;
/* Shadow offset */
padding: 0.5em 10px 0 0.5em;
left: 0;
right: 0;
}
.welcomeMessage {
@ -336,7 +344,6 @@ a {
}
.open-welcome-button {
display: inline-block;
box-sizing: border-box;
background: var(--subtle-detail-color);
color: var(--foreground-color);
@ -344,7 +351,6 @@ a {
height: 3.5em;
width: 3.5em;
padding: 0.75em;
border-radius: 1em;
}
.open-welcome-button svg {
@ -358,7 +364,6 @@ a {
padding: 0;
pointer-events: all;
box-shadow: 0 0 10px var(--shadow-color);
border-radius: 1em;
width: min-content;
background-color: var(--background-color);
color: var(--foreground-color);
@ -366,30 +371,9 @@ a {
#centermessage {
position: absolute;
top: 30%;
left: 25%;
width: 50%;
font-size: large;
padding: 2em;
border-radius: 2em;
z-index: 4000;
pointer-events: none;
opacity: 1;
background-color: var(--background-color);
color: var(--foreground-color);
transition: opacity 500ms linear;
text-align: center;
horiz-align: center;
font-weight: bold;
}
@ -445,6 +429,7 @@ a {
height: 1em;
fill: black;
border-radius: 0;
display: inline;
}
.leaflet-popup-content {
@ -490,91 +475,12 @@ a {
}
/** Switch layout **/
.subtle-button {
display: flex;
flex-wrap: nowrap;
flex-direction: row;
font-size: large;
margin: 0.5em;
background-color: var(--subtle-detail-color);
color: var(--subtle-detail-color-contrast);
border-radius: 1em;
align-items: center;
text-decoration: none;
}
.subtle-button a {
text-decoration: unset !important;
color: unset !important;
display: block ruby;
}
.round-button .subtle-button {
width: 2em;
height: 2em;
border-radius: 1em;
display: block !important;
margin: 0;
padding: 0.5em;
}
.small-button .subtle-button {
height: 2em;
}
.small-button .subtle-button img {
max-height: 1.8em;
}
.subtle-button img {
max-width: 3em;
height: 3em;
margin-right: 0.5em;
padding: 0;
padding-bottom: 0.2em;
}
.small-image img {
height: 1em;
max-width: 1em;
}
.share-button {
background-color: var(--subtle-detail-color);
border: none;
color: var(--subtle-detail-color-contrast);
text-decoration: none;
display: inline-block;
border-radius: 3em;
height: 2.5em;
width: 2.5em;
box-sizing: border-box;
padding: 0;
}
.share-button svg {
height: 1.5em;
width: 1.5em;
padding: 0.5em;
padding-left: 0.4em;
fill: var(--subtle-detail-color-contrast) !important;
stroke: var(--subtle-detail-color-contrast) !important;
}
.share-button svg path {
fill: var(--subtle-detail-color-contrast) !important;
stroke: var(--subtle-detail-color-contrast) !important;
}
.share-button svg circle {
fill: var(--subtle-detail-color-contrast) !important;
stroke: var(--subtle-detail-color-contrast) !important;
}
.ornament {
padding-top: 1em;
padding-bottom: 1em;
@ -594,4 +500,4 @@ a {
.ornament svg polygon {
fill: var(--subtle-detail-color-light-contrast);
}
}

View file

@ -14,7 +14,7 @@
<link rel="stylesheet" href="./css/openinghourstable.css"/>
<link rel="stylesheet" href="./css/tagrendering.css"/>
<link rel="stylesheet" href="./css/imageUploadFlow.css"/>
<link rel="stylesheet" href="./css/fullscreenmessagebox.css"/>
<link href="css/ReviewElement.css" rel="stylesheet"/>
<link rel="stylesheet" href="vendor/MarkerCluster.css"/>
<link rel="stylesheet" href="vendor/MarkerCluster.Default.css"/>
@ -37,8 +37,7 @@
</head>
<body>
<div style="position: fixed; left: 1em; bottom: 1em; width:35vh; height:35vh;"
id="decoration-desktop">
<div style="position: fixed; left: 1em; bottom: 1em; width:35vh; height:35vh;" id="decoration-desktop">
<!-- A nice decoration while loading or on errors -->
<!-- DECORATION 0 START -->
<img src="./assets/svg/add.svg"/>
@ -46,27 +45,25 @@
</div>
<div class="only-on-mobile">
<div id="messagesboxmobile">
</div>
<div id="messagesboxmobile"></div>
</div>
<div id="topleft-tools">
<div id="userbadge-and-search">
<div id="userbadge" class="shadow">
</div>
<div id="searchbox" class="shadow"></div>
<div id="userbadge-and-search" class="p-3">
<div id="userbadge" class="shadow rounded-3xl overflow-hidden"></div>
<div id="searchbox" class="shadow rounded-3xl overflow-hidden"></div>
</div>
<div id="messagesbox"></div>
<br/>
<div id="messagesbox" class="rounded-3xl overflow-hidden ml-3"></div>
<div id="help-button-mobile"></div>
</div>
<div id="layer-selection">
<div id="layer-selection" class="absolute bottom-3 left-3 rounded-3xl overflow-hidden"></div>
<div id="centermessage" class="absolute rounded-3xl h-24 left-24 right-24 top-56 bg-white p-3 pt-5 sm:pt-8 text-xl font-bold text-center">
Loading MapComplete, hang on...
</div>
<div id="centermessage">Loading MapComplete, hang on...</div>
<span id="geolocate-button"></span>
<div id="geolocate-button"></div>
<div id="leafletDiv"></div>
<script src="./index.ts"></script>

View file

@ -58,6 +58,11 @@ let layoutToUse: LayoutConfig = AllKnownLayouts.allSets[defaultLayout.toLowerCas
const userLayoutParam = QueryParameters.GetQueryParameter("userlayout", "false");
const layoutFromBase64 = decodeURIComponent(userLayoutParam.data);
document.getElementById('centermessage').innerText = '';
document.getElementById("decoration-desktop").remove();
if (layoutFromBase64.startsWith("wiki:")) {
console.log("Downloading map theme from the wiki");
const themeName = layoutFromBase64.substr("wiki:".length);
@ -83,7 +88,7 @@ if (layoutFromBase64.startsWith("wiki:")) {
try {
const parsed = JSON.parse(data);
// Overwrite the id to the wiki:value
parsed.id = layoutFromBase64.replace(/[: \/]/g, '-')
parsed.id = layoutFromBase64.replace(/[: \/]/g, '-')
const layout = new LayoutConfig(parsed);
InitUiElements.InitAll(layout, layoutFromBase64, testing, layoutFromBase64, btoa(data));
} catch (e) {
@ -111,13 +116,12 @@ if (layoutFromBase64.startsWith("wiki:")) {
InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout);
} else {
// We fall through: no theme loaded: just show a few buttons
document.getElementById("decoration-desktop").remove();
State.state = new State(undefined);
document.getElementById("messagesboxmobile").remove();
new MoreScreen(true)
.SetStyle("background: var(--background-color); display: block; margin-left: 5vw; margin-right: 5vw; pointer-events: all;")
.SetStyle("pointer-events: all;")
.AddClass("block m-5 lg:w-3/4 lg:ml-40")
.AttachTo("topleft-tools");
}
window.addEventListener('contextmenu', function (e) { // Not compatible with IE < 9
e.preventDefault();

14897
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -29,9 +29,11 @@
"author": "pietervdvn",
"license": "GPL",
"dependencies": {
"@tailwindcss/postcss7-compat": "^2.0.2",
"@types/leaflet-markercluster": "^1.0.3",
"@types/leaflet-providers": "^1.2.0",
"@types/leaflet.markercluster": "^1.4.3",
"autoprefixer": "^9.8.6",
"country-language": "^0.1.7",
"email-validator": "^2.0.4",
"escape-html": "^1.0.3",
@ -49,6 +51,8 @@
"osm-auth": "^1.0.2",
"osmtogeojson": "^3.0.0-beta.4",
"parcel": "^1.12.4",
"postcss": "^7.0.35",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.2",
"sharp": "^0.27.0",
"turf": "^3.0.14"
},
@ -56,7 +60,6 @@
"@babel/polyfill": "^7.10.4",
"@types/node": "^7.0.5",
"assert": "^2.0.0",
"canvas": "^2.6.1",
"fs": "0.0.1-security",
"marked": "^1.1.1",
"read-file": "^0.2.0",

6
postcss.config.js Normal file
View file

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}

View file

@ -122,7 +122,8 @@ async function createIcon(iconPath: string, size: number, layout: LayoutConfig)
}
try {
console.log("Creating icon ", name, newname)
console.log("Could not create icon! ", name, newname)
/*
// We already read to file, in order to crash here if the file is not found
readFileSync(iconPath);
@ -163,7 +164,6 @@ async function createManifest(layout: LayoutConfig, relativePath: string) {
writeFileSync(path, layout.icon)
}
const sizes = [72, 96, 120, 128, 144, 152, 180, 192, 384, 512];
for (const size of sizes) {
const name = await createIcon(path, size, layout);

View file

@ -18,6 +18,12 @@ function transformTranslation(obj: any, depth = 1) {
let values = ""
for (const key in obj) {
if(key === "#"){
continue;
}
if(key.match("^[a-zA-Z0-9_]*$") === null){
throw "Invalid character in key: "+key
}
values += (Utils.Times((_) => " ", depth)) + key + ": " + transformTranslation(obj[key], depth + 1) + ",\n"
}
return `{${values}}`;

20
tailwind.config.js Normal file
View file

@ -0,0 +1,20 @@
module.exports = {
purge: [
// './**/*.html',
// './**/*.js',
],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {
// This does not work and I don't know why.
// Luckily index.css "@layer utilities" has the same effekt.
// maxHeight: {
// '65vh': '65vh',
// },
},
},
variants: {
extend: {},
},
plugins: [],
}