Small tweaks and more layouts

This commit is contained in:
Pieter Vander Vennet 2020-07-30 09:59:30 +02:00
parent 5d5cf67820
commit e074d9c3e9
18 changed files with 235 additions and 134 deletions

View file

@ -1,18 +1,15 @@
import {Groen} from "./Layouts/Groen"; import {Groen} from "./Layouts/Groen";
import { Toilets } from "./Layouts/Toilets";
import {GRB} from "./Layouts/GRB"; import {GRB} from "./Layouts/GRB";
import { Statues } from "./Layouts/Statues"; import {Artworks} from "./Layouts/Artworks";
import {Bookcases} from "./Layouts/Bookcases"; import {Bookcases} from "./Layouts/Bookcases";
import Cyclofix from "./Layouts/Cyclofix"; import Cyclofix from "./Layouts/Cyclofix";
import {WalkByBrussels} from "./Layouts/WalkByBrussels"; import {WalkByBrussels} from "./Layouts/WalkByBrussels";
import {All} from "./Layouts/All"; import {All} from "./Layouts/All";
import {Layout} from "./Layout"; import {Layout} from "./Layout";
import {MetaMap} from "./Layouts/MetaMap"; import {MetaMap} from "./Layouts/MetaMap";
import {Widths} from "./Layers/Widths";
import {StreetWidth} from "./Layouts/StreetWidth"; import {StreetWidth} from "./Layouts/StreetWidth";
import {NatureReserves} from "./Layers/NatureReserves";
import {Natuurpunt} from "./Layouts/Natuurpunt"; import {Natuurpunt} from "./Layouts/Natuurpunt";
import Translations from "../UI/i18n/Translations"; import {ClimbingTrees} from "./Layouts/ClimbingTrees";
export class AllKnownLayouts { export class AllKnownLayouts {
public static allSets = AllKnownLayouts.AllLayouts(); public static allSets = AllKnownLayouts.AllLayouts();
@ -27,6 +24,8 @@ export class AllKnownLayouts {
new MetaMap(), new MetaMap(),
new StreetWidth(), new StreetWidth(),
new Natuurpunt(), new Natuurpunt(),
new ClimbingTrees(),
new Artworks()
/*new Toilets(), /*new Toilets(),
new Statues(), new Statues(),
*/ */

View file

@ -1,11 +1,5 @@
import {Tag, TagsFilter} from "../Logic/TagsFilter"; import {Tag, TagsFilter} from "../Logic/TagsFilter";
import {UIElement} from "../UI/UIElement"; import {UIElement} from "../UI/UIElement";
import {Basemap} from "../Logic/Basemap";
import {ElementStorage} from "../Logic/ElementStorage";
import {UIEventSource} from "../UI/UIEventSource";
import {FilteredLayer} from "../Logic/FilteredLayer";
import {Changes} from "../Logic/Changes";
import {UserDetails} from "../Logic/OsmConnection";
import {TagRenderingOptions} from "./TagRendering"; import {TagRenderingOptions} from "./TagRendering";
import {TagDependantUIElementConstructor} from "./UIElementConstructor"; import {TagDependantUIElementConstructor} from "./UIElementConstructor";
@ -61,7 +55,7 @@ export class LayerDefinition {
/** /**
* This UIElement is rendered as title element in the popup * This UIElement is rendered as title element in the popup
*/ */
title: TagRenderingOptions; title: TagRenderingOptions | UIElement | string;
/** /**
* These are the questions/shown attributes in the popup * These are the questions/shown attributes in the popup
*/ */

View file

@ -1,86 +1,88 @@
import {LayerDefinition} from "../LayerDefinition"; import {LayerDefinition} from "../LayerDefinition";
import {QuestionDefinition} from "../../Logic/Question";
import {Tag} from "../../Logic/TagsFilter"; import {Tag} from "../../Logic/TagsFilter";
import L from "leaflet"; import L from "leaflet";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
import Translations from "../../UI/i18n/Translations";
import {TagRenderingOptions} from "../TagRendering";
import Website from "../Questions/Website";
import FixedText from "../Questions/FixedText";
export class Artwork extends LayerDefinition { export class Artwork extends LayerDefinition {
constructor() { constructor() {
super(); super();
this.name = "artwork"; this.name = "artwork";
this.newElementTags = [new Tag("tourism", "artwork")]; const t = Translations.t.artwork;
this.icon = "./assets/statue.svg"; this.title = t.title;
this.overpassFilter = new Tag("tourism", "artwork"); const tag = new Tag("tourism", "artwork");
this.minzoom = 13; this.presets = [
this.questions = [ {
QuestionDefinition.radioAndTextQuestion("What kind of artwork is this?", 10, "artwork_type", title: this.title,
[ tags: [tag]
{text: "A statue", value: "statue"}, }
{text: "A bust (thus a statue, but only of the head and shoulders)", value: "bust"},
{text: "A sculpture", value: "sculpture"},
{text: "A mural painting", value: "mural"},
{text: "A painting", value: "painting"},
{text: "A graffiti", value: "graffiti"},
{text: "A relief", value: "relief"},
{text: "An installation", value: "installation"}]),
QuestionDefinition.textQuestion("Whom or what is depicted in this statue?", "subject", 20).addUnrequiredTag("subject:wikidata","*"),
QuestionDefinition.textQuestion("Is there an inscription on this artwork?", "inscription", 16),
QuestionDefinition.textQuestion("What is the name of this artwork? If there is no explicit name, skip the question", "name", 15),
]; ];
this.icon = "./assets/statue.svg";
this.overpassFilter = tag;
this.minzoom = 13;
const to = Translations.t.artwork.type;
const artworkType = new TagRenderingOptions({
priority: 5,
question: to.question,
freeform: {
key: "artwork_type",
extraTags: new Tag("fixme", "Freeform artwork_type= tag used: possibly a wrong value"),
template: to.template.txt,
renderTemplate: to.render.txt,
placeholder: Translations.t.cyclofix.freeFormPlaceholder,
},
mappings: [
{k: new Tag("artwork_type", "architecture"), txt: to.architecture},
{k: new Tag("artwork_type", "mural"), txt: to.mural},
{k: new Tag("artwork_type", "painting"), txt: to.painting},
{k: new Tag("artwork_type", "sculpture"), txt: to.sculpture},
{k: new Tag("artwork_type", "statue"), txt: to.statue},
{k: new Tag("artwork_type", "bust"), txt: to.bust},
{k: new Tag("artwork_type", "stone"), txt: to.stone},
{k: new Tag("artwork_type", "installation"), txt: to.installation},
{k: new Tag("artwork_type", "graffiti"), txt: to.graffiti},
{k: new Tag("artwork_type", "relief"), txt: to.relief},
{k: new Tag("artwork_type", "azulejo"), txt: to.azulejo},
{k: new Tag("artwork_type", "tilework"), txt: to.tilework}
]
});
const artistQuestion = new TagRenderingOptions({
question: t.artist.question,
freeform: {
key: "artist",
template: "$$$",
renderTemplate: "{artist}"
}
});
this.elementsToShow = [
new ImageCarouselWithUploadConstructor(),
artworkType,
artistQuestion,
new Website(t.title)
];
this.style = function (tags) { this.style = function (tags) {
return { return {
icon: new L.icon({ icon: {
iconUrl: "assets/statue.svg", iconUrl: "./assets/statue.svg",
iconSize: [40, 40], iconSize: [40, 40],
text: "hi" text: "hi"
}), },
color: "#0000ff" color: "#0000ff"
}; };
} }
this.elementsToShow = [
new TagMappingOptions(
{
key: "name",
template: "<h2>Artwork '{name}'</h2>",
missing: "Artwork"
}),
new TagMappingOptions({
key: "artwork_type",
template: "This artwork is a {artwork_type}"
}),
new TagMappingOptions({
key: "artist_name",
template: "This artwork was made by {artist_name}"
}),
new TagMappingOptions({
key: "subject",
template: "This artwork depicts {subject}"
}),
new TagMappingOptions({
key: "subject:wikidata",
template: "<a href='https://www.wikidata.org/wiki/{subject:wikidata}' target='_blank'>See more data about the subject</a>"
}),
new TagMappingOptions({
key: "website",
template: "<a href='{website}' target='_blank'>Website of the statue</a>"
}),
new TagMappingOptions({key: "image", template: "<img class='popupImg' alt='image' src='{image}' />"})
];
} }

View file

@ -0,0 +1,43 @@
import {LayerDefinition} from "../LayerDefinition";
import Translations from "../../UI/i18n/Translations";
import FixedText from "../Questions/FixedText";
import {And, Tag} from "../../Logic/TagsFilter";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
export class ClimbingTree extends LayerDefinition {
constructor() {
super();
const t = Translations.t.climbingTrees.layer;
this.title = new FixedText(t.title);
const icon = "assets/walkbybrussels/tree.svg";
this.icon = icon;
this.description = t.description;
this.style = (tags) => {
return {
color: "#00aa00",
icon: {
iconUrl: icon,
iconSize: [50, 50]
}
}
}
const tags = [new Tag("natural","tree"),new Tag("sport","climbing")];
this.overpassFilter = new And(tags);
this.presets = [
{
title: t.title,
description: t.description,
tags: tags
}
]
this.minzoom = 12;
this.elementsToShow = [
new ImageCarouselWithUploadConstructor()
]
}
}

View file

@ -5,8 +5,8 @@ import Translation from "../UI/i18n/Translation";
import Translations from "../UI/i18n/Translations"; import Translations from "../UI/i18n/Translations";
import Locale from "../UI/i18n/Locale"; import Locale from "../UI/i18n/Locale";
import {VariableUiElement} from "../UI/Base/VariableUIElement"; import {VariableUiElement} from "../UI/Base/VariableUIElement";
import {OsmConnection, UserDetails} from "../Logic/OsmConnection";
import {UIEventSource} from "../UI/UIEventSource"; import {UIEventSource} from "../UI/UIEventSource";
import {OsmConnection, UserDetails} from "../Logic/Osm/OsmConnection";
/** /**
* A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers). * A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers).
@ -114,10 +114,12 @@ export class WelcomeMessage extends UIElement {
let loginStatus = ""; let loginStatus = "";
if (this.userDetails !== undefined) { if (this.userDetails !== undefined) {
loginStatus = (this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render(); loginStatus = (this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render();
loginStatus = loginStatus + "<br/>"
} }
return "<span>" + return "<span>" +
this.description.Render() + this.description.Render() +
"<br/>" +
loginStatus + loginStatus +
this.tail.Render() + this.tail.Render() +
"<br/>" + "<br/>" +

View file

@ -0,0 +1,17 @@
import {Layout} from "../Layout";
import {Artwork} from "../Layers/Artwork";
export class Artworks extends Layout{
constructor() {
super( "artworks",
["en","nl","fr"],
"Open Artwork Map",
[new Artwork()],
10,
50.8435,
4.3688,
"<h3>Open Artwork Map</h3>");
this.icon = "./assets/statue.svg"
}
}

View file

@ -0,0 +1,21 @@
import {LayerDefinition} from "../LayerDefinition";
import Translations from "../../UI/i18n/Translations";
import {Layout} from "../Layout";
import {ClimbingTree} from "../Layers/ClimbingTree";
export class ClimbingTrees extends Layout {
constructor() {
super(
"climbing_trees",
["nl"],
Translations.t.climbingTrees.layout.title,
[new ClimbingTree()],
12,
50.8435,
4.3688,
Translations.t.climbingTrees.layout.welcome
);
this.icon = "./assets/walkbybrussels/tree.svg"
this.hideFromOverview = true;
}
}

View file

@ -1,27 +0,0 @@
import {Layout} from "../Layout";
import {Artwork} from "../Layers/Artwork";
export class Statues extends Layout{
constructor() {
super( "statues",
["en"],
"Open Artwork Map",
[new Artwork()],
10,
50.8435,
4.3688,
" <h3>Open Statue Map</h3>\n" +
"\n" +
"<p>" +
"Help with creating a map of all statues all over the world!"
,
" <p>Start by <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">creating an account\n" +
" </a> or by " +
" <span onclick=\"authOsm()\" class=\"activate-osm-authentication\">logging in</span>.</p>",
"Start by clicking a pin and answering the questions");
}
}

View file

@ -9,7 +9,7 @@ export default class Website extends TagRenderingOptions {
question: Translations.t.general.questions.websiteOf.Subs({category: category}), question: Translations.t.general.questions.websiteOf.Subs({category: category}),
freeform: { freeform: {
renderTemplate: Translations.t.general.questions.websiteIs, renderTemplate: Translations.t.general.questions.websiteIs,
template: "website", template: "$$$",
key: "website" key: "website"
} }
}); });

View file

@ -3,11 +3,11 @@ import {UIEventSource} from "../UI/UIEventSource";
import {And, Tag, TagsFilter, TagUtils} from "../Logic/TagsFilter"; import {And, Tag, TagsFilter, TagUtils} from "../Logic/TagsFilter";
import {FixedUiElement} from "../UI/Base/FixedUiElement"; import {FixedUiElement} from "../UI/Base/FixedUiElement";
import {SaveButton} from "../UI/SaveButton"; import {SaveButton} from "../UI/SaveButton";
import {Changes} from "../Logic/Changes"; import {Changes} from "../Logic/Osm/Changes";
import {VariableUiElement} from "../UI/Base/VariableUIElement"; import {VariableUiElement} from "../UI/Base/VariableUIElement";
import {TagDependantUIElement, TagDependantUIElementConstructor} from "./UIElementConstructor"; import {TagDependantUIElement, TagDependantUIElementConstructor} from "./UIElementConstructor";
import {OnlyShowIfConstructor} from "./OnlyShowIf"; import {OnlyShowIfConstructor} from "./OnlyShowIf";
import {UserDetails} from "../Logic/OsmConnection"; import {UserDetails} from "../Logic/Osm/OsmConnection";
import {TextField} from "../UI/Input/TextField"; import {TextField} from "../UI/Input/TextField";
import {InputElement} from "../UI/Input/InputElement"; import {InputElement} from "../UI/Input/InputElement";
import {InputElementWrapper} from "../UI/Input/InputElementWrapper"; import {InputElementWrapper} from "../UI/Input/InputElementWrapper";

View file

@ -1,14 +1,15 @@
import {Basemap} from "./Basemap";
import {TagsFilter, TagUtils} from "./TagsFilter"; import {TagsFilter, TagUtils} from "./TagsFilter";
import {UIEventSource} from "../UI/UIEventSource"; import {UIEventSource} from "../UI/UIEventSource";
import {ElementStorage} from "./ElementStorage"; import {ElementStorage} from "./ElementStorage";
import {Changes} from "./Changes";
import L from "leaflet" import L from "leaflet"
import {GeoOperations} from "./GeoOperations"; import {GeoOperations} from "./GeoOperations";
import {UIElement} from "../UI/UIElement"; import {UIElement} from "../UI/UIElement";
import {LayerDefinition} from "../Customizations/LayerDefinition"; import {LayerDefinition} from "../Customizations/LayerDefinition";
import {UserDetails} from "./OsmConnection";
import codegrid from "codegrid-js"; import codegrid from "codegrid-js";
import {Changes} from "./Osm/Changes";
import {UserDetails} from "./Osm/OsmConnection";
import {Basemap} from "./Leaflet/Basemap";
/*** /***
* A filtered layer is a layer which offers a 'set-data' function * A filtered layer is a layer which offers a 'set-data' function
* It is initialized with a tagfilter. * It is initialized with a tagfilter.

View file

@ -1,9 +0,0 @@
import {Bounds} from "../Bounds";
export class Notes {
queryGeoJson(bounds: Bounds, continuation: ((any) => void), onFail: ((reason) => void)): void {
}
}

View file

@ -1,6 +1,6 @@
import {UIElement} from "./UIElement"; import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {OsmConnection} from "../Logic/OsmConnection"; import {OsmConnection} from "../Logic/Osm/OsmConnection";
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";
export class CenterMessageBox extends UIElement { export class CenterMessageBox extends UIElement {

View file

@ -10,6 +10,7 @@ import {TagDependantUIElement, TagDependantUIElementConstructor} from "../Custom
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";
import {Changes} from "../Logic/Osm/Changes"; import {Changes} from "../Logic/Osm/Changes";
import {UserDetails} from "../Logic/Osm/OsmConnection"; import {UserDetails} from "../Logic/Osm/OsmConnection";
import {FixedUiElement} from "./Base/FixedUiElement";
export class FeatureInfoBox extends UIElement { export class FeatureInfoBox extends UIElement {
@ -38,7 +39,7 @@ export class FeatureInfoBox extends UIElement {
constructor( constructor(
feature: any, feature: any,
tagsES: UIEventSource<any>, tagsES: UIEventSource<any>,
title: TagRenderingOptions | UIElement, title: TagRenderingOptions | UIElement | string,
elementsToShow: TagDependantUIElementConstructor[], elementsToShow: TagDependantUIElementConstructor[],
changes: Changes, changes: Changes,
userDetails: UIEventSource<UserDetails> userDetails: UIEventSource<UserDetails>
@ -78,8 +79,9 @@ export class FeatureInfoBox extends UIElement {
mappings: [{k: new And([]), txt: ""}] mappings: [{k: new And([]), txt: ""}]
} }
) )
if (typeof (title) == "string") {
if (title instanceof UIElement) { this._title = new FixedUiElement(title);
} else if (title instanceof UIElement) {
this._title = title; this._title = title;
} else { } else {
this._title = new TagRenderingOptions(title.options).construct(deps); this._title = new TagRenderingOptions(title.options).construct(deps);

View file

@ -2,7 +2,7 @@ import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import $ from "jquery" import $ from "jquery"
import {Imgur} from "../Logic/Imgur"; import {Imgur} from "../Logic/Imgur";
import {UserDetails} from "../Logic/OsmConnection"; import {UserDetails} from "../Logic/Osm/OsmConnection";
import {DropDown} from "./Input/DropDown"; import {DropDown} from "./Input/DropDown";
import {VariableUiElement} from "./Base/VariableUIElement"; import {VariableUiElement} from "./Base/VariableUIElement";
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";

View file

@ -571,6 +571,55 @@ export default class Translations {
} }
},
climbingTrees: {
layer: {
title: new T({
nl: "Klimbomen"
}),
description: new T({
nl: "Een klimboom is een mooie boom waar men in kan klimmen, al dan niet officieel"
})
},
layout: {
title: new T({nl: "Open Klimbomenkaart"}),
welcome: new T({nl: "Markeer je favoriete klimboom"})
}
},
artwork: {
name: new T({ en: 'Artwork', nl: 'Kunstwerk', fr: "Oeuvre d'art" }),
title: new T({ en: 'Artwork', nl: 'Kunstwerk', fr: "Oeuvre d'art" }),
type: {
render: new T({
en: 'This is artwork of the type: {artwork_type}',
nl: 'Dit is een kunstwerk van het type: {artwork_type}',
fr: "Ceci est un travail d'art de type: {artwork_type}"
}),
template: new T({ en: 'Some other type: $$$', nl: 'Een ander type: $$$', fr: 'Un autre type: $$$' }),
question: new T({
en: 'What is the type of this artwork?',
nl: 'Wat voor type kunstwerk is dit?',
fr: "Quel est le type de cette oeuvre d'art?"
}),
architecture: new T({ en: "architecture", nl: "architectuur", fr: "architecture" }),
mural: new T({ en: "mural", nl: "muurschildering", fr: "mural" }),
painting: new T({ en: "painting", nl: "schilderij", fr: "peinture" }),
sculpture: new T({ en: "sculpture", nl: "beeldhouwwerk", fr: "sculpture" }),
statue: new T({ en: "statue", nl: "standbeeld", fr: "statue" }),
bust: new T({ en: "bust", nl: "buste", fr: "buste" }),
stone: new T({ en: "stone", nl: "steen", fr: "rocher" }),
installation: new T({ en: "installation", nl: "installatie", fr: "installation" }),
graffiti: new T({ en: "graffiti", nl: "graffiti", fr: "graffiti" }),
relief: new T({ en: "relief", nl: "verlichting", fr: "relief" }),
azulejo: new T({ en: "azulejo", nl: "azulejo", fr: "azulejo" }),
tilework: new T({ en: "tilework", nl: "tegelwerk", fr: "carrelage" })
}, artist: {
question: new T({en:"Which artist created this artwork?"})
}
}, },
image: { image: {

View file

@ -1144,20 +1144,27 @@ form {
.tab-single-header { .tab-single-header {
border-top-left-radius: 1em; border-top-left-radius: 1em;
border-top-right-radius: 1em; border-top-right-radius: 1em;
box-shadow: 0 0 10px black;
z-index: 5000; z-index: 5000;
border-bottom: 1px solid white; padding-bottom: 0;
padding-bottom: 1px; margin-bottom: 0;
} }
.tab-active { .tab-active {
background-color: white; background-color: white;
z-index: 5001; z-index: 5001;
box-shadow: 0 0 10px black;
border-bottom: 1px solid white;
border-left: 1px solid black;
border-right:1px solid black;
border-top: 1px solid black;
} }
.tab-non-active { .tab-non-active {
background-color: #e5f5ff; background-color: #e5f5ff;
opacity: 0.5; opacity: 0.5;
border-left: 1px solid gray;
border-right:1px solid gray;
border-top: 1px solid gray;
border-bottom: 1px solid lightgray; border-bottom: 1px solid lightgray;
} }

View file

@ -109,7 +109,7 @@ const lon = QueryParameters.GetQueryParameter("lon", undefined)
.syncWith(LocalStorageSource.Get("lon")); .syncWith(LocalStorageSource.Get("lon"));
function featSw(key: string, deflt: boolean): UIEventSource<boolean> { function featSw(key: string, deflt: boolean): UIEventSource<boolean> {
return QueryParameters.GetQueryParameter("fs-userbadge", "" + deflt).map((str) => { return QueryParameters.GetQueryParameter(key, "" + deflt).map((str) => {
return str !== "false"; return str !== "false";
}); });
} }