forked from MapComplete/MapComplete
Merge branches
This commit is contained in:
commit
00fb99defe
117 changed files with 3104 additions and 1424 deletions
|
@ -14,9 +14,9 @@ import {NatureReserves} from "./Layers/NatureReserves";
|
|||
import {Natuurpunt} from "./Layouts/Natuurpunt";
|
||||
|
||||
export class AllKnownLayouts {
|
||||
public static allSets: any = AllKnownLayouts.AllLayouts();
|
||||
public static allSets = AllKnownLayouts.AllLayouts();
|
||||
|
||||
private static AllLayouts(): any {
|
||||
private static AllLayouts(): Map<string, Layout> {
|
||||
const all = new All();
|
||||
const layouts: Layout[] = [
|
||||
new Groen(),
|
||||
|
@ -32,7 +32,7 @@ export class AllKnownLayouts {
|
|||
new Statues(),
|
||||
*/
|
||||
];
|
||||
const allSets = {};
|
||||
const allSets: Map<string, Layout> = new Map();
|
||||
for (const layout of layouts) {
|
||||
allSets[layout.name] = layout;
|
||||
all.layers = all.layers.concat(layout.layers);
|
||||
|
|
|
@ -15,7 +15,7 @@ export class LayerDefinition {
|
|||
/**
|
||||
* This name is shown in the 'add XXX button'
|
||||
*/
|
||||
name: string;
|
||||
name: string | UIElement;
|
||||
/**
|
||||
* These tags are added whenever a new point is added by the user on the map.
|
||||
* This is the ideal place to add extra info, such as "fixme=added by MapComplete, geometry should be checked"
|
||||
|
@ -72,7 +72,15 @@ export class LayerDefinition {
|
|||
*/
|
||||
maxAllowedOverlapPercentage: number = undefined;
|
||||
|
||||
|
||||
/**
|
||||
* If true, then ways (and polygons) will be converted to a 'point' at the center instead before further processing
|
||||
*/
|
||||
wayHandling: number = 0;
|
||||
|
||||
static WAYHANDLING_DEFAULT = 0;
|
||||
static WAYHANDLING_CENTER_ONLY = 1;
|
||||
static WAYHANDLING_CENTER_AND_WAY = 2;
|
||||
|
||||
constructor(options: {
|
||||
name: string,
|
||||
newElementTags: Tag[],
|
||||
|
@ -82,13 +90,13 @@ export class LayerDefinition {
|
|||
title?: TagRenderingOptions,
|
||||
elementsToShow?: TagDependantUIElementConstructor[],
|
||||
maxAllowedOverlapPercentage?: number,
|
||||
wayHandling?: number,
|
||||
style?: (tags: any) => {
|
||||
color: string,
|
||||
icon: any
|
||||
}
|
||||
} = undefined) {
|
||||
if (options === undefined) {
|
||||
console.log("No options!")
|
||||
return;
|
||||
}
|
||||
this.name = options.name;
|
||||
|
@ -100,11 +108,12 @@ export class LayerDefinition {
|
|||
this.title = options.title;
|
||||
this.elementsToShow = options.elementsToShow;
|
||||
this.style = options.style;
|
||||
console.log(this)
|
||||
this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT;
|
||||
}
|
||||
|
||||
asLayer(basemap: Basemap, allElements: ElementStorage, changes: Changes, userDetails: UIEventSource<UserDetails>, selectedElement: UIEventSource<any>,
|
||||
showOnPopup: (tags: UIEventSource<(any)>) => UIElement):
|
||||
asLayer(basemap: Basemap, allElements: ElementStorage, changes: Changes, userDetails: UIEventSource<UserDetails>,
|
||||
selectedElement: UIEventSource<{feature: any}>,
|
||||
showOnPopup: (tags: UIEventSource<(any)>, feature: any) => UIElement):
|
||||
FilteredLayer {
|
||||
return new FilteredLayer(
|
||||
this,
|
||||
|
|
|
@ -5,12 +5,15 @@ import * as L from "leaflet";
|
|||
import FixedText from "../Questions/FixedText";
|
||||
import ParkingType from "../Questions/bike/ParkingType";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import BikeStationOperator from "../Questions/bike/StationOperator";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
import ParkingOperator from "../Questions/bike/ParkingOperator";
|
||||
|
||||
|
||||
export default class BikeParkings extends LayerDefinition {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "bike_parking";
|
||||
this.name = Translations.t.cyclofix.parking.name;
|
||||
this.icon = "./assets/bike/parking.svg";
|
||||
this.overpassFilter = new Tag("amenity", "bicycle_parking");
|
||||
this.newElementTags = [
|
||||
|
@ -20,12 +23,13 @@ export default class BikeParkings extends LayerDefinition {
|
|||
|
||||
this.minzoom = 13;
|
||||
this.style = this.generateStyleFunction();
|
||||
this.title = new FixedText("Fietsparking");
|
||||
this.title = new FixedText(Translations.t.cyclofix.parking.title)
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new OperatorTag(),
|
||||
//new ParkingOperator(),
|
||||
new ParkingType()
|
||||
];
|
||||
this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY;
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,7 +40,8 @@ export default class BikeParkings extends LayerDefinition {
|
|||
color: "#00bb00",
|
||||
icon: L.icon({
|
||||
iconUrl: self.icon,
|
||||
iconSize: [50, 50]
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25,50]
|
||||
})
|
||||
};
|
||||
};
|
||||
|
|
82
Customizations/Layers/BikeShops.ts
Normal file
82
Customizations/Layers/BikeShops.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
import { LayerDefinition } from "../LayerDefinition";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
import {And, Tag} from "../../Logic/TagsFilter";
|
||||
import FixedText from "../Questions/FixedText";
|
||||
import { ImageCarouselWithUploadConstructor } from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import * as L from "leaflet";
|
||||
import ShopRetail from "../Questions/bike/ShopRetail";
|
||||
import ShopPump from "../Questions/bike/ShopPump";
|
||||
import ShopRental from "../Questions/bike/ShopRental";
|
||||
import ShopRepair from "../Questions/bike/ShopRepair";
|
||||
import ShopDiy from "../Questions/bike/ShopDiy";
|
||||
import ShopName from "../Questions/bike/ShopName";
|
||||
import ShopSecondHand from "../Questions/bike/ShopSecondHand";
|
||||
import { TagRenderingOptions } from "../TagRendering";
|
||||
|
||||
|
||||
export default class BikeShops extends LayerDefinition {
|
||||
private readonly sellsBikes = new Tag("service:bicycle:retail", "yes")
|
||||
private readonly repairsBikes = new Tag("service:bicycle:repair", "yes")
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.name = Translations.t.cyclofix.shop.name
|
||||
this.icon = "./assets/bike/repair_shop.svg"
|
||||
this.overpassFilter = new Tag("shop", "bicycle");
|
||||
this.newElementTags = [
|
||||
new Tag("shop", "bicycle"),
|
||||
]
|
||||
this.maxAllowedOverlapPercentage = 10
|
||||
this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY
|
||||
|
||||
this.minzoom = 13;
|
||||
this.style = this.generateStyleFunction();
|
||||
this.title = new TagRenderingOptions({
|
||||
mappings: [
|
||||
{k: new And([new Tag("name", "*"), this.sellsBikes]), txt: Translations.t.cyclofix.shop.titleShopNamed},
|
||||
{
|
||||
k: new And([new Tag("name", "*"), new Tag("service:bicycle:retail", "")]),
|
||||
txt: Translations.t.cyclofix.shop.titleShop
|
||||
},
|
||||
{
|
||||
k: new And([new Tag("name", "*"), new Tag("service:bicycle:retail", "no")]),
|
||||
txt: Translations.t.cyclofix.shop.titleRepairNamed
|
||||
},
|
||||
{k: this.sellsBikes, txt: Translations.t.cyclofix.shop.titleShop},
|
||||
{k: new Tag("service:bicycle:retail", " "), txt: Translations.t.cyclofix.shop.title},
|
||||
{k: new Tag("service:bicycle:retail", "no"), txt: Translations.t.cyclofix.shop.titleRepair},
|
||||
]
|
||||
})
|
||||
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new ShopName(),
|
||||
new ShopRetail(),
|
||||
new ShopRental(),
|
||||
new ShopRepair(),
|
||||
new ShopPump(),
|
||||
new ShopDiy(),
|
||||
new ShopSecondHand()
|
||||
]
|
||||
}
|
||||
|
||||
private generateStyleFunction() {
|
||||
const self = this;
|
||||
return function (tags: any) {
|
||||
let icon = "assets/bike/repair_shop.svg";
|
||||
|
||||
if (self.sellsBikes.matchesProperties(tags)) {
|
||||
icon = "assets/bike/shop.svg";
|
||||
}
|
||||
|
||||
return {
|
||||
color: "#00bb00",
|
||||
icon: L.icon({
|
||||
iconUrl: self.icon,
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25, 50]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import PumpManometer from "../Questions/bike/PumpManometer";
|
|||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import PumpOperational from "../Questions/bike/PumpOperational";
|
||||
import PumpValves from "../Questions/bike/PumpValves";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class BikeStations extends LayerDefinition {
|
||||
|
@ -22,7 +23,7 @@ export default class BikeStations extends LayerDefinition {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "bike station or pump";
|
||||
this.name = Translations.t.cyclofix.station.name;
|
||||
this.icon = "./assets/wrench.svg";
|
||||
|
||||
this.overpassFilter = new And([
|
||||
|
@ -36,7 +37,8 @@ export default class BikeStations extends LayerDefinition {
|
|||
|
||||
this.minzoom = 13;
|
||||
this.style = this.generateStyleFunction();
|
||||
this.title = new FixedText("Bike station");
|
||||
this.title = new FixedText(Translations.t.cyclofix.station.title)
|
||||
this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY
|
||||
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
|
@ -50,7 +52,7 @@ export default class BikeStations extends LayerDefinition {
|
|||
new PumpValves().OnlyShowIf(this.pump),
|
||||
new PumpOperational().OnlyShowIf(this.pump),
|
||||
|
||||
new BikeStationOperator(),
|
||||
// new BikeStationOperator(),
|
||||
// new BikeStationBrand() DISABLED
|
||||
];
|
||||
}
|
||||
|
@ -61,26 +63,26 @@ export default class BikeStations extends LayerDefinition {
|
|||
const hasPump = self.pump.matchesProperties(properties)
|
||||
const isOperational = self.pumpOperationalOk.matchesProperties(properties)
|
||||
const hasTools = self.tools.matchesProperties(properties)
|
||||
let iconName = ""
|
||||
if (hasPump) {
|
||||
if (hasTools) {
|
||||
iconName = "repair_station_pump.svg"
|
||||
let iconName = "repair_station.svg";
|
||||
if (hasTools && hasPump && isOperational) {
|
||||
iconName = "repair_station_pump.svg"
|
||||
}else if(hasTools){
|
||||
iconName = "repair_station.svg"
|
||||
}else if(hasPump){
|
||||
if (isOperational) {
|
||||
iconName = "pump.svg"
|
||||
} else {
|
||||
if (isOperational) {
|
||||
iconName = "pump.svg"
|
||||
} else {
|
||||
iconName = "pump_broken.svg"
|
||||
}
|
||||
iconName = "broken_pump.svg"
|
||||
}
|
||||
} else {
|
||||
iconName = "repair_station.svg"
|
||||
}
|
||||
|
||||
const iconUrl = `./assets/bike/${iconName}`
|
||||
return {
|
||||
color: "#00bb00",
|
||||
icon: L.icon({
|
||||
iconUrl: iconUrl,
|
||||
iconSize: [50, 50]
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25,50]
|
||||
})
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import L from "leaflet";
|
||||
import {And, Or, Regex, Tag} from "../../Logic/TagsFilter";
|
||||
import {QuestionDefinition} from "../../Logic/Question";
|
||||
import {And, Or, Tag} from "../../Logic/TagsFilter";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {NameInline} from "../Questions/NameInline";
|
||||
import {NameQuestion} from "../Questions/NameQuestion";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
|
||||
export class Bookcases extends LayerDefinition {
|
||||
|
@ -121,7 +119,10 @@ export class Bookcases extends LayerDefinition {
|
|||
key: "ref",
|
||||
template: "Het referentienummer is $$$",
|
||||
renderTemplate: "Gekend als {brand} <b>{ref}</b>"
|
||||
}
|
||||
},
|
||||
mappings: [
|
||||
{k: new And([new Tag("brand",""), new Tag("nobrand","yes"), new Tag("ref", "")]), txt: "Maakt geen deel uit van een groter netwerk"}
|
||||
]
|
||||
}).OnlyShowIf(new Tag("brand","*")),
|
||||
|
||||
new TagRenderingOptions({
|
||||
|
|
|
@ -10,8 +10,8 @@ export class DrinkingWater extends LayerDefinition {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "drinking_water";
|
||||
this.icon = "./assets/bug.svg";
|
||||
this.name = "drinking water";
|
||||
this.icon = "./assets/bike/drinking_water.svg";
|
||||
|
||||
this.overpassFilter = new Or([
|
||||
new And([
|
||||
|
@ -24,6 +24,7 @@ export class DrinkingWater extends LayerDefinition {
|
|||
new Tag("amenity", "drinking_water"),
|
||||
];
|
||||
this.maxAllowedOverlapPercentage = 10;
|
||||
this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY
|
||||
|
||||
this.minzoom = 13;
|
||||
this.style = this.generateStyleFunction();
|
||||
|
@ -52,7 +53,8 @@ export class DrinkingWater extends LayerDefinition {
|
|||
color: "#00bb00",
|
||||
icon: new L.icon({
|
||||
iconUrl: self.icon,
|
||||
iconSize: [40, 40]
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25,50]
|
||||
})
|
||||
};
|
||||
};
|
||||
|
|
|
@ -25,6 +25,13 @@ export class NatureReserves extends LayerDefinition {
|
|||
this.style = this.generateStyleFunction();
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new TagRenderingOptions({
|
||||
freeform: {
|
||||
key: "_surface",
|
||||
renderTemplate: "{_surface}m²",
|
||||
template: "$$$"
|
||||
}
|
||||
}),
|
||||
new NameQuestion(),
|
||||
new AccessTag(),
|
||||
new OperatorTag(),
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
import {LayerDefinition} from "./LayerDefinition";
|
||||
import {UIElement} from "../UI/UIElement";
|
||||
import {FixedUiElement} from "../UI/Base/FixedUiElement";
|
||||
import Translation from "../UI/i18n/Translation";
|
||||
import Translations from "../UI/i18n/Translations";
|
||||
import Locale from "../UI/i18n/Locale";
|
||||
import {VariableUiElement} from "../UI/Base/VariableUIElement";
|
||||
import {OsmConnection, UserDetails} from "../Logic/OsmConnection";
|
||||
import {UIEventSource} from "../UI/UIEventSource";
|
||||
|
||||
/**
|
||||
* A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers).
|
||||
*/
|
||||
export class Layout {
|
||||
|
||||
public name: string;
|
||||
public title: string;
|
||||
public title: UIElement;
|
||||
public layers: LayerDefinition[];
|
||||
public welcomeMessage: string;
|
||||
public gettingStartedPlzLogin: string;
|
||||
public welcomeBackMessage: string;
|
||||
public welcomeMessage: UIElement;
|
||||
public gettingStartedPlzLogin: UIElement;
|
||||
public welcomeBackMessage: UIElement;
|
||||
public welcomeTail: UIElement;
|
||||
|
||||
public startzoom: number;
|
||||
public supportedLanguages: string[];
|
||||
public startLon: number;
|
||||
public startLat: number;
|
||||
public welcomeTail: string;
|
||||
|
||||
public locationContains: string[];
|
||||
|
||||
|
@ -33,26 +43,79 @@ export class Layout {
|
|||
*/
|
||||
constructor(
|
||||
name: string,
|
||||
title: string,
|
||||
supportedLanguages: string[],
|
||||
title: UIElement | string,
|
||||
layers: LayerDefinition[],
|
||||
startzoom: number,
|
||||
startLat: number,
|
||||
startLon: number,
|
||||
welcomeMessage: string,
|
||||
gettingStartedPlzLogin: string = "Please login to get started",
|
||||
welcomeBackMessage: string = "You are logged in. Welcome back!",
|
||||
welcomeTail: string = ""
|
||||
welcomeMessage: UIElement | string,
|
||||
gettingStartedPlzLogin: UIElement | string = Translations.t.general.getStarted,
|
||||
welcomeBackMessage: UIElement | string = Translations.t.general.welcomeBack,
|
||||
welcomeTail: UIElement | string = ""
|
||||
) {
|
||||
this.title = title;
|
||||
this.supportedLanguages = supportedLanguages;
|
||||
this.title = typeof (title) === 'string' ? new FixedUiElement(title) : title;
|
||||
this.startLon = startLon;
|
||||
this.startLat = startLat;
|
||||
this.startzoom = startzoom;
|
||||
this.name = name;
|
||||
this.layers = layers;
|
||||
this.welcomeMessage = welcomeMessage;
|
||||
this.gettingStartedPlzLogin = gettingStartedPlzLogin;
|
||||
this.welcomeBackMessage = welcomeBackMessage;
|
||||
this.welcomeTail = welcomeTail;
|
||||
this.welcomeMessage = Translations.W(welcomeMessage)
|
||||
this.gettingStartedPlzLogin = Translations.W(gettingStartedPlzLogin);
|
||||
this.welcomeBackMessage = Translations.W(welcomeBackMessage);
|
||||
this.welcomeTail = Translations.W(welcomeTail);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class WelcomeMessage extends UIElement {
|
||||
private readonly layout: Layout;
|
||||
private readonly userDetails: UIEventSource<UserDetails>;
|
||||
private osmConnection: OsmConnection;
|
||||
|
||||
private readonly description: UIElement;
|
||||
private readonly plzLogIn: UIElement;
|
||||
private readonly welcomeBack: UIElement;
|
||||
private readonly tail: UIElement;
|
||||
|
||||
|
||||
constructor(layout: Layout, osmConnection: OsmConnection) {
|
||||
super(osmConnection.userDetails);
|
||||
this.ListenTo(Locale.language);
|
||||
this.osmConnection = osmConnection;
|
||||
this.layout = layout;
|
||||
this.userDetails = osmConnection.userDetails;
|
||||
|
||||
this.description = layout.welcomeMessage;
|
||||
console.log(" >>>>",this.description, "DESCR ")
|
||||
this.plzLogIn = layout.gettingStartedPlzLogin;
|
||||
this.welcomeBack = layout.welcomeBackMessage;
|
||||
this.tail = layout.welcomeTail;
|
||||
}
|
||||
|
||||
InnerRender(): string {
|
||||
return "<div id='welcomeMessage'>" +
|
||||
this.description.Render() +
|
||||
"<br/>"+
|
||||
(this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() +
|
||||
"<br/>"+
|
||||
this.tail.Render() +
|
||||
"</div>"
|
||||
|
||||
;
|
||||
/*
|
||||
return new VariableUiElement(
|
||||
this.userDetails.map((userdetails) => {
|
||||
}),
|
||||
function () {
|
||||
|
||||
}).ListenTo(Locale.language);*/
|
||||
}
|
||||
|
||||
protected InnerUpdate(htmlElement: HTMLElement) {
|
||||
this.osmConnection.registerActivateOsmAUthenticationClass()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ export class All extends Layout{
|
|||
constructor() {
|
||||
super(
|
||||
"all",
|
||||
["en"],
|
||||
"All quest layers",
|
||||
[],
|
||||
15,
|
||||
|
|
|
@ -4,6 +4,7 @@ import * as Layer from "../Layers/Bookcases";
|
|||
export class Bookcases extends Layout{
|
||||
constructor() {
|
||||
super( "bookcases",
|
||||
["nl"],
|
||||
"Open Bookcase Map",
|
||||
[new Layer.Bookcases()],
|
||||
14,
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import {Layout} from "../Layout";
|
||||
import BikeParkings from "../Layers/BikeParkings";
|
||||
import BikeServices from "../Layers/BikeStations";
|
||||
import {GhostBike} from "../Layers/GhostBike";
|
||||
import {DrinkingWater, DrinkingWaterLayer} from "../Layers/DrinkingWater";
|
||||
import BikeShops from "../Layers/BikeShops";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
import {DrinkingWater} from "../Layers/DrinkingWater";
|
||||
import Combine from "../../UI/Base/Combine";
|
||||
|
||||
|
||||
export default class Cyclofix extends Layout {
|
||||
constructor() {
|
||||
super(
|
||||
"pomp",
|
||||
"Cyclofix bicycle infrastructure",
|
||||
[new GhostBike(), new BikeServices(), new BikeParkings(), new DrinkingWater()],
|
||||
["en", "nl", "fr"],
|
||||
Translations.t.cyclofix.title,
|
||||
[new BikeServices(), new BikeShops(), new DrinkingWater(), new BikeParkings()],
|
||||
16,
|
||||
50.8465573,
|
||||
4.3516970,
|
||||
|
||||
|
||||
"<h3>Cyclofix bicycle infrastructure</h3>\n" +
|
||||
"\n" +
|
||||
"<p><b>EN></b> On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." +
|
||||
"As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.</p>" +
|
||||
"<p><b>NL></b> Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel." +
|
||||
"Hierdoor kunnen fietsers snel de dichtstbijzijnde infrastructuur vinden die voldoet aan hun behoeften.</p>" +
|
||||
"<p><b>FR></b> Sur cette carte, nous voulons collecter des données sur la localisation des pompes à vélo et des supports publics à Bruxelles." +
|
||||
"Les cyclistes pourront ainsi trouver rapidement l'infrastructure la plus proche de leurs besoins.</p>"
|
||||
,
|
||||
"", "");
|
||||
/* Translations.t.cyclofix.title/*/
|
||||
new Combine([
|
||||
"<h3>",
|
||||
Translations.t.cyclofix.title,
|
||||
"</h3><br/><p>",
|
||||
Translations.t.cyclofix.description,
|
||||
"</p>"
|
||||
])//*/
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import {GrbToFix} from "../Layers/GrbToFix";
|
|||
export class GRB extends Layout {
|
||||
constructor() {
|
||||
super("grb",
|
||||
["en"],
|
||||
"Grb import fix tool",
|
||||
[new GrbToFix()],
|
||||
15,
|
||||
|
|
|
@ -7,6 +7,7 @@ export class Groen extends Layout {
|
|||
|
||||
constructor() {
|
||||
super("buurtnatuur",
|
||||
["nl"],
|
||||
"Buurtnatuur",
|
||||
[new NatureReserves(), new Park(), new Bos()],
|
||||
10,
|
||||
|
|
|
@ -5,6 +5,7 @@ import {Map} from "../Layers/Map";
|
|||
export class MetaMap extends Layout{
|
||||
constructor() {
|
||||
super( "metamap",
|
||||
["en"],
|
||||
"Open Map Map",
|
||||
[new Map()],
|
||||
1,
|
||||
|
|
|
@ -7,6 +7,7 @@ export class Natuurpunt extends Layout{
|
|||
constructor() {
|
||||
super(
|
||||
"natuurpunt",
|
||||
["nl"],
|
||||
"De natuur in",
|
||||
[new Birdhide(), new InformationBoard(), new NatureReserves(true)],
|
||||
12,
|
||||
|
|
|
@ -5,6 +5,7 @@ export class Statues extends Layout{
|
|||
constructor() {
|
||||
super( "statues",
|
||||
"Open Artwork Map",
|
||||
["en"],
|
||||
[new Artwork()],
|
||||
10,
|
||||
50.8435,
|
||||
|
|
|
@ -7,6 +7,7 @@ export class StreetWidth extends Layout{
|
|||
|
||||
constructor() {
|
||||
super( "width",
|
||||
["nl"],
|
||||
"Straatbreedtes in Brugge",
|
||||
[new Widths(
|
||||
2,
|
||||
|
|
|
@ -4,6 +4,7 @@ import * as Layer from "../Layers/Toilets";
|
|||
export class Toilets extends Layout{
|
||||
constructor() {
|
||||
super( "toilets",
|
||||
["en"],
|
||||
"Open Toilet Map",
|
||||
[new Layer.Toilets()],
|
||||
12,
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Park } from "../Layers/Park";
|
|||
export class WalkByBrussels extends Layout {
|
||||
constructor() {
|
||||
super("walkbybrussels",
|
||||
["en","fr","nl"],
|
||||
"Drinking Water Spots",
|
||||
[new DrinkingWater(), new Park(), new NatureReserves()],
|
||||
10,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { TagRenderingOptions } from "../TagRendering";
|
||||
import {UIElement} from "../../UI/UIElement";
|
||||
|
||||
export default class FixedText extends TagRenderingOptions {
|
||||
constructor(category: string) {
|
||||
constructor(category: string | UIElement) {
|
||||
super({
|
||||
mappings: [
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {And, Tag} from "../../Logic/TagsFilter";
|
||||
import {UIElement} from "../../UI/UIElement";
|
||||
|
||||
|
||||
export class NameInline extends TagRenderingOptions{
|
||||
|
@ -8,7 +9,7 @@ export class NameInline extends TagRenderingOptions{
|
|||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
constructor(category: string) {
|
||||
constructor(category: string ) {
|
||||
super({
|
||||
question: "",
|
||||
|
||||
|
|
27
Customizations/Questions/bike/ParkingOperator.ts
Normal file
27
Customizations/Questions/bike/ParkingOperator.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag, And} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ParkingOperator extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.parking.operator
|
||||
super({
|
||||
priority: 15,
|
||||
question: to.question.Render(),
|
||||
freeform: {
|
||||
key: "operator",
|
||||
template: to.template,
|
||||
renderTemplate: to.render,
|
||||
placeholder: Translations.t.cyclofix.freeFormPlaceholder
|
||||
},
|
||||
mappings: [
|
||||
{k: new Tag("operator", "KU Leuven"), txt: "KU Leuven"},
|
||||
{k: new Tag("operator", "Stad Halle"), txt: "Stad Halle"},
|
||||
{k: new Tag("operator", "Saint Gilles - Sint Gillis"), txt: "Saint Gilles - Sint Gillis"},
|
||||
{k: new Tag("operator", "Jette"), txt: "Jette"},
|
||||
{k: new And([new Tag("operator", ""), new Tag("operator:type", "private")]), txt: to.private.Render()}
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,38 +1,61 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
import Combine from "../../../UI/Base/Combine";
|
||||
|
||||
class ParkingTypeHelper {
|
||||
static GenerateMappings() {
|
||||
const images = {
|
||||
stands: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg/100px-Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg",
|
||||
wall_loops: "https://wiki.openstreetmap.org/w/images/thumb/c/c2/Bike-parking-wheelbender.jpg/100px-Bike-parking-wheelbender.jpg",
|
||||
handlebar_holder: "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Bicycle_parking_handlebar_holder.jpg/100px-Bicycle_parking_handlebar_holder.jpg",
|
||||
shed: "https://wiki.openstreetmap.org/w/images/thumb/b/b2/Bike-shelter.jpg/100px-Bike-shelter.jpg",
|
||||
rack: "https://wiki.openstreetmap.org/w/images/thumb/4/41/Triton_Bike_Rack.png/100px-Triton_Bike_Rack.png",
|
||||
"two-tier": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG/100px-Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG"
|
||||
};
|
||||
|
||||
|
||||
const toImg = (url) => `<img src=${url}>`
|
||||
const mappings = [];
|
||||
const to = Translations.t.cyclofix.parking.type
|
||||
|
||||
for (const imagesKey in images) {
|
||||
const mapping =
|
||||
{
|
||||
k: new Tag("bicycle_parking", imagesKey),
|
||||
txt: new Combine([
|
||||
to[imagesKey],
|
||||
to.eg,
|
||||
toImg(images[imagesKey])
|
||||
])
|
||||
};
|
||||
|
||||
mappings.push(mapping);
|
||||
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
}
|
||||
|
||||
export default class ParkingType extends TagRenderingOptions {
|
||||
private static images = {
|
||||
stands: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg/100px-Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg",
|
||||
wall_loops: "https://wiki.openstreetmap.org/w/images/thumb/c/c2/Bike-parking-wheelbender.jpg/100px-Bike-parking-wheelbender.jpg",
|
||||
handlebar_holder: "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Bicycle_parking_handlebar_holder.jpg/100px-Bicycle_parking_handlebar_holder.jpg",
|
||||
shed: "https://wiki.openstreetmap.org/w/images/thumb/b/b2/Bike-shelter.jpg/100px-Bike-shelter.jpg",
|
||||
"two-tier": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG/100px-Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG"
|
||||
}
|
||||
|
||||
private static toImgTxt(url: string) {
|
||||
return `<img src=${url}>`
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
||||
const to = Translations.t.cyclofix.parking.type
|
||||
|
||||
|
||||
super({
|
||||
priority: 5,
|
||||
question: "Van welk type is deze fietsenparking?",
|
||||
question: to.question,
|
||||
freeform: {
|
||||
key: "bicycle_parking",
|
||||
extraTags: new Tag("fixme", "Freeform bicycle_parking= tag used: possibly a wrong value"),
|
||||
template: "Iets anders: $$$",
|
||||
renderTemplate: "Dit is een fietsenparking van het type: {bicycle_parking}",
|
||||
placeholder: "Specifieer"
|
||||
template: to.template.txt,
|
||||
renderTemplate: to.render.txt,
|
||||
placeholder: Translations.t.cyclofix.freeFormPlaceholder,
|
||||
},
|
||||
mappings: [
|
||||
{k: new Tag("bicycle_parking", "stands"), txt: ParkingType.toImgTxt(ParkingType.images.stands)},
|
||||
{k: new Tag("bicycle_parking", "wall_loops"), txt: ParkingType.toImgTxt(ParkingType.images.wall_loops)},
|
||||
{k: new Tag("bicycle_parking", "handlebar_holder"), txt: ParkingType.toImgTxt(ParkingType.images.handlebar_holder)},
|
||||
{k: new Tag("bicycle_parking", "shed"), txt: ParkingType.toImgTxt(ParkingType.images.shed)},
|
||||
{k: new Tag("bicycle_parking", "two-tier"), txt: ParkingType.toImgTxt(ParkingType.images["two-tier"])}
|
||||
]
|
||||
mappings: ParkingTypeHelper.GenerateMappings()
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class PumpManometer extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.manometer
|
||||
super({
|
||||
question: "Does the pump have a pressure indicator or manometer?",
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag("manometer", "yes"), txt: "Yes, there is a manometer"},
|
||||
{k: new Tag("manometer","broken"), txt: "Yes, but it is broken"},
|
||||
{k: new Tag("manometer", "yes"), txt: "No"}
|
||||
{k: new Tag("manometer", "yes"), txt: to.yes},
|
||||
{k: new Tag("manometer", "no"), txt: to.no},
|
||||
{k: new Tag("manometer", "broken"), txt: to.broken}
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class PumpManual extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.electric
|
||||
super({
|
||||
priority: 5,
|
||||
question: "Is this an electric bike pump?",
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag("manual", "yes"), txt: "Manual pump"},
|
||||
{k: new Tag("manual", "no"), txt: "Electric pump"}
|
||||
{k: new Tag("manual", "yes"), txt: to.manual},
|
||||
{k: new Tag("manual", "no"), txt: to.electric}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class PumpOperational extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.operational
|
||||
super({
|
||||
question: "Is the bicycle pump still operational?",
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag("service:bicycle:pump:operational_status","broken"), txt: "This pump is broken"},
|
||||
{k: new Tag("service:bicycle:pump:operational_status",""), txt: "This pump is operational"}
|
||||
{k: new Tag("service:bicycle:pump:operational_status","broken"), txt: to.broken},
|
||||
{k: new Tag("service:bicycle:pump:operational_status",""), txt: to.operational}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,24 +1,27 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class PumpValves extends TagRenderingOptions{
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.valves
|
||||
super({
|
||||
question: "What valves are supported?",
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{
|
||||
k: new Tag("valves", " sclaverand;schrader;dunlop"),
|
||||
txt: "There is a default head, so Presta, Dunlop and Auto"
|
||||
txt: to.default
|
||||
},
|
||||
{k: new Tag("valves", "dunlop"), txt: "Only dunlop"},
|
||||
{k: new Tag("valves", "sclaverand"), txt: "Only Sclaverand (also known as Dunlop)"},
|
||||
{k: new Tag("valves", "auto"), txt: "Only auto"},
|
||||
{k: new Tag("valves", "dunlop"), txt: to.dunlop},
|
||||
{k: new Tag("valves", "sclaverand"), txt: to.sclaverand},
|
||||
{k: new Tag("valves", "auto"), txt: to.auto},
|
||||
],
|
||||
freeform: {
|
||||
extraTags: new Tag("fixme", "Freeform valves= tag used: possibly a wrong value"),
|
||||
key: "valves",
|
||||
template: "Supported valves are $$$",
|
||||
renderTemplate: "Supported valves are {valves}"
|
||||
template: to.template,
|
||||
renderTemplate: to.render
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
19
Customizations/Questions/bike/ShopDiy.ts
Normal file
19
Customizations/Questions/bike/ShopDiy.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopPump extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const key = 'service:bicycle:diy'
|
||||
const to = Translations.t.cyclofix.shop.diy
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag(key, "yes"), txt: to.yes},
|
||||
{k: new Tag(key, "no"), txt: to.no},
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
18
Customizations/Questions/bike/ShopName.ts
Normal file
18
Customizations/Questions/bike/ShopName.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopPump extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.shop.qName
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
freeform: {
|
||||
key: "name",
|
||||
renderTemplate: to.render,
|
||||
template: to.template
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
19
Customizations/Questions/bike/ShopPump.ts
Normal file
19
Customizations/Questions/bike/ShopPump.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopPump extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const key = 'service:bicycle:pump'
|
||||
const to = Translations.t.cyclofix.shop.pump
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag(key, "yes"), txt: to.yes},
|
||||
{k: new Tag(key, "no"), txt: to.no},
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
19
Customizations/Questions/bike/ShopRental.ts
Normal file
19
Customizations/Questions/bike/ShopRental.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopRental extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const key = 'service:bicycle:rental'
|
||||
const to = Translations.t.cyclofix.shop.rental
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag(key, "yes"), txt: to.yes},
|
||||
{k: new Tag(key, "no"), txt: to.no},
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
21
Customizations/Questions/bike/ShopRepair.ts
Normal file
21
Customizations/Questions/bike/ShopRepair.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopRepair extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const key = 'service:bicycle:repair'
|
||||
const to = Translations.t.cyclofix.shop.repair
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag(key, "yes"), txt: to.yes},
|
||||
{k: new Tag(key, "only_sold"), txt: to.sold},
|
||||
{k: new Tag(key, "brand"), txt: to.brand},
|
||||
{k: new Tag(key, "no"), txt: to.no},
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
19
Customizations/Questions/bike/ShopRetail.ts
Normal file
19
Customizations/Questions/bike/ShopRetail.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopRetail extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const key = 'service:bicycle:retail'
|
||||
const to = Translations.t.cyclofix.shop.retail
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag(key, "yes"), txt: to.yes},
|
||||
{k: new Tag(key, "no"), txt: to.no},
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
20
Customizations/Questions/bike/ShopSecondHand.ts
Normal file
20
Customizations/Questions/bike/ShopSecondHand.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class ShopPump extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const key = 'service:bicycle:second_hand'
|
||||
const to = Translations.t.cyclofix.shop.secondHand
|
||||
super({
|
||||
priority: 5,
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag(key, "yes"), txt: to.yes},
|
||||
{k: new Tag(key, "no"), txt: to.no},
|
||||
{k: new Tag(key, "only"), txt: to.only},
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ import {Tag} from "../../../Logic/TagsFilter";
|
|||
|
||||
/**
|
||||
* Currently not used in Cyclofix because it's a little vague
|
||||
*
|
||||
* TODO: Translations
|
||||
*/
|
||||
export default class BikeStationBrand extends TagRenderingOptions {
|
||||
private static options = {
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class StationChain extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.chain
|
||||
super({
|
||||
priority: 5,
|
||||
question: "Does this bike station have a special tool to repair your bike chain?",
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag("service:bicycle:chain_tool", "yes"), txt: "There is a chain tool."},
|
||||
{k: new Tag("service:bicycle:chain_tool", "no"), txt: "There is no chain tool."},
|
||||
{k: new Tag("service:bicycle:chain_tool", "yes"), txt: to.yes},
|
||||
{k: new Tag("service:bicycle:chain_tool", "no"), txt: to.no},
|
||||
]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class BikeStationOperator extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.operator
|
||||
super({
|
||||
priority: 15,
|
||||
question: "Who operates this bike station (name of university, shop, city...)?",
|
||||
freeform: {
|
||||
key: "operator",
|
||||
template: "This bike station is operated by $$$",
|
||||
renderTemplate: "This bike station is operated by {operator}",
|
||||
placeholder: "organisatie"
|
||||
},
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new Tag("operator", "KU Leuven"), txt: "KU Leuven"},
|
||||
{k: new Tag("operator", "Stad Halle"), txt: "Stad Halle"},
|
||||
{k: new Tag("operator", "Saint Gilles - Sint Gillis"), txt: "Saint Gilles - Sint Gillis"},
|
||||
{k: new Tag("operator", "Jette"), txt: "Jette"},
|
||||
{k: new Tag("operator", "private"), txt: "Beheer door een privépersoon"}
|
||||
]
|
||||
{k: new Tag("operator", "private"), txt: to.private}
|
||||
],
|
||||
freeform: {
|
||||
key: "operator",
|
||||
template: to.template,
|
||||
renderTemplate: to.render,
|
||||
placeholder: "organisatie"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag, And} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class BikeStationPumpTools extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations.t.cyclofix.station.services
|
||||
super({
|
||||
priority: 15,
|
||||
question: "Which services are available at this bike station?",
|
||||
question: to.question,
|
||||
mappings: [
|
||||
{k: new And([new Tag("service:bicycle:tools", "no"), new Tag("service:bicycle:pump", "yes")]), txt: "There is only a pump available."},
|
||||
{k: new And([new Tag("service:bicycle:tools", "yes"), new Tag("service:bicycle:pump", "no")]), txt: "There are only tools (screwdrivers, pliers...) available."},
|
||||
{k: new And([new Tag("service:bicycle:tools", "yes"), new Tag("service:bicycle:pump", "yes")]), txt: "There are both tools and a pump available."}
|
||||
{k: new And([new Tag("service:bicycle:tools", "no"), new Tag("service:bicycle:pump", "yes")]), txt: to.pump},
|
||||
{k: new And([new Tag("service:bicycle:tools", "yes"), new Tag("service:bicycle:pump", "no")]), txt: to.tools},
|
||||
{k: new And([new Tag("service:bicycle:tools", "yes"), new Tag("service:bicycle:pump", "yes")]), txt: to.both}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import {TagRenderingOptions} from "../../TagRendering";
|
||||
import {Tag} from "../../../Logic/TagsFilter";
|
||||
import Translations from "../../../UI/i18n/Translations";
|
||||
|
||||
|
||||
export default class BikeStationStand extends TagRenderingOptions {
|
||||
constructor() {
|
||||
const to = Translations
|
||||
super({
|
||||
priority: 10,
|
||||
question: "Does this bike station have a hook to suspend your bike with or a stand to elevate it?",
|
||||
mappings: [
|
||||
{k: new Tag("service:bicycle:stand", "yes"), txt: "There is a hook or stand."},
|
||||
{k: new Tag("service:bicycle:stand", "yes"), txt: "There is a hook or stand"},
|
||||
{k: new Tag("service:bicycle:stand", "no"), txt: "There is no hook or stand"},
|
||||
]
|
||||
});
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
import {UIElement} from "../UI/UIElement";
|
||||
import {UIEventSource} from "../UI/UIEventSource";
|
||||
import {And, Tag, TagsFilter, TagUtils} from "../Logic/TagsFilter";
|
||||
import {UIRadioButton} from "../UI/Base/UIRadioButton";
|
||||
import {FixedUiElement} from "../UI/Base/FixedUiElement";
|
||||
import {SaveButton} from "../UI/SaveButton";
|
||||
import {Changes} from "../Logic/Changes";
|
||||
import {TextField} from "../UI/Base/TextField";
|
||||
import {UIInputElement} from "../UI/Base/UIInputElement";
|
||||
import {UIRadioButtonWithOther} from "../UI/Base/UIRadioButtonWithOther";
|
||||
import {VariableUiElement} from "../UI/Base/VariableUIElement";
|
||||
import {TagDependantUIElement, TagDependantUIElementConstructor} from "./UIElementConstructor";
|
||||
import {OnlyShowIfConstructor} from "./OnlyShowIf";
|
||||
import {UserDetails} from "../Logic/OsmConnection";
|
||||
import {TextField} from "../UI/Input/TextField";
|
||||
import {InputElement} from "../UI/Input/InputElement";
|
||||
import {InputElementWrapper} from "../UI/Input/InputElementWrapper";
|
||||
import {FixedInputElement} from "../UI/Input/FixedInputElement";
|
||||
import {RadioButton} from "../UI/Input/RadioButton";
|
||||
import Translations from "../UI/i18n/Translations";
|
||||
import Locale from "../UI/i18n/Locale";
|
||||
|
||||
export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
||||
|
||||
|
@ -20,8 +23,17 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
*/
|
||||
|
||||
public options: {
|
||||
priority?: number; question?: string; primer?: string;
|
||||
freeform?: { key: string; tagsPreprocessor?: (tags: any) => any; template: string; renderTemplate: string; placeholder?: string; extraTags?: TagsFilter }; mappings?: { k: TagsFilter; txt: string; priority?: number, substitute?: boolean }[]
|
||||
priority?: number;
|
||||
question?: string | UIElement;
|
||||
freeform?: {
|
||||
key: string;
|
||||
tagsPreprocessor?: (tags: any) => any;
|
||||
template: string | UIElement;
|
||||
renderTemplate: string | UIElement;
|
||||
placeholder?: string | UIElement;
|
||||
extraTags?: TagsFilter
|
||||
};
|
||||
mappings?: { k: TagsFilter; txt: string | UIElement; priority?: number, substitute?: boolean }[]
|
||||
};
|
||||
|
||||
|
||||
|
@ -35,7 +47,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
* If 'question' is undefined, then the question is never asked at all
|
||||
* If the question is "" (empty string) then the question is
|
||||
*/
|
||||
question?: string,
|
||||
question?: UIElement | string,
|
||||
|
||||
/**
|
||||
* What is the priority of the question.
|
||||
|
@ -56,7 +68,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
*
|
||||
*
|
||||
*/
|
||||
mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[],
|
||||
mappings?: { k: TagsFilter, txt: UIElement | string, priority?: number, substitute?: boolean }[],
|
||||
|
||||
|
||||
/**
|
||||
|
@ -65,19 +77,14 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
* In the question, it'll offer a textfield
|
||||
*/
|
||||
freeform?: {
|
||||
key: string, template: string,
|
||||
renderTemplate: string
|
||||
placeholder?: string,
|
||||
key: string,
|
||||
template: string | UIElement,
|
||||
renderTemplate: string | UIElement
|
||||
placeholder?: string | UIElement,
|
||||
extraTags?: TagsFilter,
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Optional:
|
||||
* if defined, this a common piece of tag that is shown in front of every mapping (except freeform)
|
||||
*/
|
||||
primer?: string,
|
||||
|
||||
/**
|
||||
* In some very rare cases, tags have to be rewritten before displaying
|
||||
* This function can be used for that.
|
||||
|
@ -85,6 +92,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
*/
|
||||
tagsPreprocessor?: ((tags: any) => void)
|
||||
}) {
|
||||
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
|
@ -129,29 +137,24 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
class TagRendering extends UIElement implements TagDependantUIElement {
|
||||
|
||||
|
||||
private _priority: number;
|
||||
private _userDetails: UIEventSource<UserDetails>;
|
||||
private _priority: number;
|
||||
|
||||
Priority(): number {
|
||||
return this._priority;
|
||||
}
|
||||
|
||||
private _question: string;
|
||||
private _primer: string;
|
||||
private _mapping: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[];
|
||||
private _renderMapping: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[];
|
||||
private _question: UIElement;
|
||||
private _mapping: { k: TagsFilter, txt: string | UIElement, priority?: number }[];
|
||||
|
||||
private _tagsPreprocessor?: ((tags: any) => any);
|
||||
private _freeform: {
|
||||
key: string, template: string,
|
||||
renderTemplate: string,
|
||||
|
||||
placeholder?: string,
|
||||
key: string,
|
||||
template: string | UIElement,
|
||||
renderTemplate: string | UIElement,
|
||||
placeholder?: string | UIElement,
|
||||
extraTags?: TagsFilter
|
||||
};
|
||||
|
||||
private readonly _questionElement: UIElement;
|
||||
private readonly _textField: TextField<TagsFilter>; // Only here to update
|
||||
|
||||
private readonly _questionElement: InputElement<TagsFilter>;
|
||||
|
||||
private readonly _saveButton: UIElement;
|
||||
private readonly _skipButton: UIElement;
|
||||
|
@ -165,19 +168,20 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
constructor(tags: UIEventSource<any>, changes: Changes, options: {
|
||||
priority?: number
|
||||
|
||||
question?: string,
|
||||
primer?: string,
|
||||
question?: string | UIElement,
|
||||
|
||||
freeform?: {
|
||||
key: string, template: string,
|
||||
renderTemplate: string
|
||||
placeholder?: string,
|
||||
key: string,
|
||||
template: string | UIElement,
|
||||
renderTemplate: string | UIElement,
|
||||
placeholder?: string | UIElement,
|
||||
extraTags?: TagsFilter,
|
||||
},
|
||||
tagsPreprocessor?: ((tags: any) => any),
|
||||
mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[]
|
||||
mappings?: { k: TagsFilter, txt: string | UIElement, priority?: number, substitute?: boolean }[]
|
||||
}) {
|
||||
super(tags);
|
||||
this.ListenTo(Locale.language);
|
||||
const self = this;
|
||||
this.ListenTo(this._questionSkipped);
|
||||
this.ListenTo(this._editMode);
|
||||
|
@ -185,9 +189,10 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
this._userDetails = changes.login.userDetails;
|
||||
this.ListenTo(this._userDetails);
|
||||
|
||||
this._question = options.question;
|
||||
if (options.question !== undefined) {
|
||||
this._question = Translations.W(options.question);
|
||||
}
|
||||
this._priority = options.priority ?? 0;
|
||||
this._primer = options.primer ?? "";
|
||||
this._tagsPreprocessor = function (properties) {
|
||||
if (options.tagsPreprocessor === undefined) {
|
||||
return properties;
|
||||
|
@ -201,97 +206,38 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
};
|
||||
|
||||
this._mapping = [];
|
||||
this._renderMapping = [];
|
||||
this._freeform = options.freeform;
|
||||
|
||||
// Prepare the choices for the Radio buttons
|
||||
const choices: UIElement[] = [];
|
||||
const usedChoices: string [] = [];
|
||||
|
||||
for (const choice of options.mappings ?? []) {
|
||||
if (choice.k === null) {
|
||||
this._mapping.push(choice);
|
||||
continue;
|
||||
}
|
||||
let choiceSubbed = choice;
|
||||
let choiceSubbed = {
|
||||
k: choice.k,
|
||||
txt: choice.txt,
|
||||
priority: choice.priority
|
||||
};
|
||||
|
||||
if (choice.substitute) {
|
||||
choiceSubbed = {
|
||||
k: choice.k.substituteValues(
|
||||
options.tagsPreprocessor(this._source.data)),
|
||||
txt: this.ApplyTemplate(choice.txt),
|
||||
substitute: false,
|
||||
txt: choice.txt,
|
||||
priority: choice.priority
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const txt = choiceSubbed.txt
|
||||
// Choices is what is shown in the radio buttons
|
||||
if (usedChoices.indexOf(txt) < 0) {
|
||||
|
||||
choices.push(new FixedUiElement(txt));
|
||||
usedChoices.push(txt);
|
||||
// This is used to convert the radio button index into tags needed to add
|
||||
this._mapping.push(choiceSubbed);
|
||||
} else {
|
||||
this._renderMapping.push(choiceSubbed); // only used while rendering
|
||||
}
|
||||
this._mapping.push({
|
||||
k: choiceSubbed.k,
|
||||
txt: choiceSubbed.txt
|
||||
});
|
||||
}
|
||||
|
||||
// Map radiobutton choice and textfield answer onto tagfilter. That tagfilter will be pushed into the changes later on
|
||||
const pickChoice = (i => {
|
||||
if (i === undefined || i === null) {
|
||||
return undefined
|
||||
}
|
||||
return self._mapping[i].k
|
||||
});
|
||||
const pickString =
|
||||
(string) => {
|
||||
if (string === "" || string === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const tag = new Tag(self._freeform.key, string);
|
||||
if (self._freeform.extraTags === undefined) {
|
||||
return tag;
|
||||
}
|
||||
return new And([
|
||||
self._freeform.extraTags,
|
||||
tag
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// Prepare the actual input element -> pick an appropriate implementation
|
||||
let inputElement: UIInputElement<TagsFilter>;
|
||||
|
||||
|
||||
if (this._freeform !== undefined && this._mapping !== undefined) {
|
||||
// Radio buttons with 'other'
|
||||
inputElement = new UIRadioButtonWithOther(
|
||||
choices,
|
||||
this._freeform.template,
|
||||
this._freeform.placeholder,
|
||||
pickChoice,
|
||||
pickString
|
||||
);
|
||||
this._questionElement = inputElement;
|
||||
} else if (this._mapping !== [] && this._mapping.length > 0) {
|
||||
// This is a classic radio selection element
|
||||
inputElement = new UIRadioButton(new UIEventSource(choices), pickChoice, false)
|
||||
this._questionElement = inputElement;
|
||||
} else if (this._freeform !== undefined) {
|
||||
this._textField = new TextField(new UIEventSource<string>(this._freeform.placeholder), pickString);
|
||||
inputElement = this._textField;
|
||||
this._questionElement = new FixedUiElement(
|
||||
"<div>" + this._freeform.template.replace("$$$", inputElement.Render()) + "</div>")
|
||||
} else {
|
||||
throw "Invalid questionRendering, expected at least choices or a freeform"
|
||||
}
|
||||
|
||||
|
||||
this._questionElement = this.InputElementFor(options);
|
||||
const save = () => {
|
||||
const selection = inputElement.GetValue().data;
|
||||
const selection = self._questionElement.GetValue().data;
|
||||
if (selection) {
|
||||
changes.addTag(tags.data.id, selection);
|
||||
}
|
||||
|
@ -305,54 +251,157 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
}
|
||||
|
||||
// Setup the save button and it's action
|
||||
this._saveButton = new SaveButton(inputElement.GetValue())
|
||||
this._saveButton = new SaveButton(this._questionElement.GetValue())
|
||||
.onClick(save);
|
||||
|
||||
this._editButton = new FixedUiElement("");
|
||||
if (this._question !== undefined) {
|
||||
this._editButton = new FixedUiElement("<img class='editbutton' src='./assets/pencil.svg' alt='edit'>")
|
||||
.onClick(() => {
|
||||
console.log("Click", self._editButton);
|
||||
if (self._textField) {
|
||||
self._textField.value.setData(self._source.data["name"] ?? "");
|
||||
}
|
||||
|
||||
self._editMode.setData(true);
|
||||
self._questionElement.GetValue().setData(self.CurrentValue());
|
||||
});
|
||||
} else {
|
||||
this._editButton = new FixedUiElement("");
|
||||
}
|
||||
|
||||
|
||||
const cancelContents = this._editMode.map((isEditing) => {
|
||||
if (isEditing) {
|
||||
return "<span class='skip-button'>Annuleren</span>";
|
||||
return "<span class='skip-button'>"+Translations.t.general.cancel.R()+"</span>";
|
||||
} else {
|
||||
return "<span class='skip-button'>Overslaan (Ik weet het niet zeker...)</span>";
|
||||
return "<span class='skip-button'>"+Translations.t.general.skip.R()+"</span>";
|
||||
}
|
||||
});
|
||||
}, [Locale.language]);
|
||||
// And at last, set up the skip button
|
||||
this._skipButton = new VariableUiElement(cancelContents).onClick(cancel);
|
||||
this._skipButton = new VariableUiElement(cancelContents).onClick(cancel) ;
|
||||
}
|
||||
|
||||
|
||||
private InputElementFor(options: {
|
||||
freeform?: {
|
||||
key: string,
|
||||
template: string | UIElement,
|
||||
renderTemplate: string | UIElement,
|
||||
placeholder?: string | UIElement,
|
||||
extraTags?: TagsFilter,
|
||||
},
|
||||
mappings?: { k: TagsFilter, txt: string | UIElement, priority?: number, substitute?: boolean }[]
|
||||
}):
|
||||
InputElement<TagsFilter> {
|
||||
|
||||
const elements = [];
|
||||
|
||||
if (options.mappings !== undefined) {
|
||||
|
||||
const previousTexts= [];
|
||||
for (const mapping of options.mappings) {
|
||||
if(mapping.k === null){
|
||||
continue;
|
||||
}
|
||||
if(previousTexts.indexOf(mapping.txt) >= 0){
|
||||
continue;
|
||||
}
|
||||
previousTexts.push(mapping.txt);
|
||||
|
||||
elements.push(this.InputElementForMapping(mapping));
|
||||
}
|
||||
}
|
||||
|
||||
if (options.freeform !== undefined) {
|
||||
elements.push(this.InputForFreeForm(options.freeform));
|
||||
}
|
||||
|
||||
|
||||
if (elements.length == 0) {
|
||||
console.warn("WARNING: no tagrendering with following options:", options);
|
||||
return new FixedInputElement("This should not happen: no tag renderings defined", undefined);
|
||||
}
|
||||
if (elements.length == 1) {
|
||||
return elements[0];
|
||||
}
|
||||
|
||||
return new RadioButton(elements, false);
|
||||
|
||||
}
|
||||
|
||||
private ApplyTemplate(template: string): string {
|
||||
const tags = this._tagsPreprocessor(this._source.data);
|
||||
return TagUtils.ApplyTemplate(template, tags);
|
||||
|
||||
private InputElementForMapping(mapping: { k: TagsFilter, txt: string | UIElement }) {
|
||||
return new FixedInputElement(mapping.txt, mapping.k);
|
||||
}
|
||||
|
||||
|
||||
private InputForFreeForm(freeform): InputElement<TagsFilter> {
|
||||
if (freeform === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
const pickString =
|
||||
(string) => {
|
||||
if (string === "" || string === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const tag = new Tag(freeform.key, string);
|
||||
if (freeform.extraTags === undefined) {
|
||||
return tag;
|
||||
}
|
||||
return new And([
|
||||
tag,
|
||||
freeform.extraTags
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
const toString =
|
||||
(tag) => {
|
||||
if (tag instanceof And) {
|
||||
return toString(tag.and[0])
|
||||
} else if (tag instanceof Tag) {
|
||||
return tag.value
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
let inputElement: InputElement<TagsFilter>;
|
||||
const textField = new TextField({
|
||||
placeholder: this._freeform.placeholder,
|
||||
fromString: pickString,
|
||||
toString: toString
|
||||
});
|
||||
|
||||
const prepost = Translations.W(freeform.template).InnerRender().split("$$$");
|
||||
return new InputElementWrapper(prepost[0], textField, prepost[1]);
|
||||
}
|
||||
|
||||
|
||||
IsKnown(): boolean {
|
||||
const tags = TagUtils.proprtiesToKV(this._source.data);
|
||||
|
||||
for (const oneOnOneElement of this._mapping.concat(this._renderMapping)) {
|
||||
for (const oneOnOneElement of this._mapping) {
|
||||
if (oneOnOneElement.k === null || oneOnOneElement.k.matches(tags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return this._freeform !== undefined && this._source.data[this._freeform.key] !== undefined;
|
||||
}
|
||||
|
||||
private CurrentValue(): TagsFilter {
|
||||
const tags = TagUtils.proprtiesToKV(this._source.data);
|
||||
|
||||
for (const oneOnOneElement of this._mapping) {
|
||||
if (oneOnOneElement.k !== null && oneOnOneElement.k.matches(tags)) {
|
||||
return oneOnOneElement.k;
|
||||
}
|
||||
}
|
||||
if (this._freeform === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return new Tag(this._freeform.key, this._source.data[this._freeform.key]);
|
||||
}
|
||||
|
||||
|
||||
IsQuestioning(): boolean {
|
||||
if (this.IsKnown()) {
|
||||
return false;
|
||||
|
@ -368,10 +417,10 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
return true;
|
||||
}
|
||||
|
||||
private RenderAnwser(): string {
|
||||
private RenderAnwser(): UIElement {
|
||||
const tags = TagUtils.proprtiesToKV(this._source.data);
|
||||
|
||||
let freeform = "";
|
||||
let freeform: UIElement = new FixedUiElement("");
|
||||
let freeformScore = -10;
|
||||
if (this._freeform !== undefined && this._source.data[this._freeform.key] !== undefined) {
|
||||
freeform = this.ApplyTemplate(this._freeform.renderTemplate);
|
||||
|
@ -379,58 +428,59 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
}
|
||||
|
||||
|
||||
let highestScore = -100;
|
||||
let highestTemplate = undefined;
|
||||
for (const oneOnOneElement of this._mapping.concat(this._renderMapping)) {
|
||||
if (oneOnOneElement.k == null ||
|
||||
oneOnOneElement.k.matches(tags)) {
|
||||
// We have found a matching key -> we use the template, but only if it scores better
|
||||
let score = oneOnOneElement.priority ??
|
||||
(oneOnOneElement.k === null ? -1 : 0);
|
||||
if (score > highestScore) {
|
||||
highestScore = score;
|
||||
highestTemplate = oneOnOneElement.txt
|
||||
}
|
||||
let highestScore = -100;
|
||||
let highestTemplate = undefined;
|
||||
for (const oneOnOneElement of this._mapping) {
|
||||
if (oneOnOneElement.k == null ||
|
||||
oneOnOneElement.k.matches(tags)) {
|
||||
// We have found a matching key -> we use the template, but only if it scores better
|
||||
let score = oneOnOneElement.priority ??
|
||||
(oneOnOneElement.k === null ? -1 : 0);
|
||||
if (score > highestScore) {
|
||||
highestScore = score;
|
||||
highestTemplate = oneOnOneElement.txt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (freeformScore > highestScore) {
|
||||
return freeform;
|
||||
}
|
||||
if (freeformScore > highestScore) {
|
||||
return freeform;
|
||||
}
|
||||
|
||||
if (highestTemplate !== undefined) {
|
||||
// we render the found template
|
||||
return this.ApplyTemplate(highestTemplate);
|
||||
}
|
||||
|
||||
if (highestTemplate !== undefined) {
|
||||
// we render the found template
|
||||
return this._primer + this.ApplyTemplate(highestTemplate);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected InnerRender(): string {
|
||||
|
||||
InnerRender(): string {
|
||||
if (this.IsQuestioning() || this._editMode.data) {
|
||||
// Not yet known or questioning, we have to ask a question
|
||||
|
||||
const question = this._question.Render();
|
||||
|
||||
return "<div class='question'>" +
|
||||
"<span class='question-text'>" + this._question + "</span>" +
|
||||
(this._question !== "" ? "<br/>" : "") +
|
||||
this._questionElement.Render() +
|
||||
"<span class='question-text'>" + question + "</span>" +
|
||||
(this._question.IsEmpty() ? "" : "<br/>") +
|
||||
"<div>" + this._questionElement.Render() + "</div>" +
|
||||
this._skipButton.Render() +
|
||||
this._saveButton.Render() +
|
||||
"</div>"
|
||||
}
|
||||
|
||||
if (this.IsKnown()) {
|
||||
const html = this.RenderAnwser();
|
||||
if (html == "") {
|
||||
const answer = this.RenderAnwser()
|
||||
if (answer.IsEmpty()) {
|
||||
return "";
|
||||
}
|
||||
const html = answer.Render();
|
||||
let editButton = "";
|
||||
if(this._userDetails.data.loggedIn){
|
||||
if (this._userDetails.data.loggedIn && this._question !== undefined) {
|
||||
editButton = this._editButton.Render();
|
||||
}
|
||||
|
||||
|
||||
return "<span class='answer'>" +
|
||||
"<span class='answer-text'>" + html + "</span>" +
|
||||
editButton +
|
||||
|
@ -441,13 +491,26 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
|
||||
}
|
||||
|
||||
|
||||
Priority(): number {
|
||||
return this._priority;
|
||||
}
|
||||
|
||||
private ApplyTemplate(template: string | UIElement): UIElement {
|
||||
if(template === undefined || template === null){
|
||||
throw "Trying to apply a template, but the template is null/undefined"
|
||||
}
|
||||
const tags = this._tagsPreprocessor(this._source.data);
|
||||
if (template instanceof UIElement) {
|
||||
template = template.Render();
|
||||
}
|
||||
return new FixedUiElement(TagUtils.ApplyTemplate(template, tags));
|
||||
}
|
||||
|
||||
|
||||
InnerUpdate(htmlElement: HTMLElement) {
|
||||
super.InnerUpdate(htmlElement);
|
||||
this._questionElement.Update();
|
||||
this._saveButton.Update();
|
||||
this._skipButton.Update();
|
||||
this._textField?.Update();
|
||||
this._editButton.Update();
|
||||
this._questionElement.Update(); // Another manual update for them
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue