diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts
index ba69d30..12e8bc0 100644
--- a/Customizations/AllKnownLayouts.ts
+++ b/Customizations/AllKnownLayouts.ts
@@ -40,7 +40,6 @@ export class AllKnownLayouts {
if (knownKeys.indexOf(key) >= 0) {
continue;
}
- console.log(key)
knownKeys.push(key);
all.layers.push(layer);
}
diff --git a/Customizations/LayerDefinition.ts b/Customizations/LayerDefinition.ts
index bdf480f..e1dbc86 100644
--- a/Customizations/LayerDefinition.ts
+++ b/Customizations/LayerDefinition.ts
@@ -70,7 +70,10 @@ export class LayerDefinition {
*/
style: (tags: any) => {
color: string,
- icon: any,
+ icon: {
+ iconUrl: string,
+ iconSize: number[],
+ },
};
/**
@@ -119,16 +122,6 @@ export class LayerDefinition {
this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT;
}
- asLayer(basemap: Basemap, allElements: ElementStorage, changes: Changes, userDetails: UIEventSource,
- selectedElement: UIEventSource<{feature: any}>,
- showOnPopup: (tags: UIEventSource, feature: any) => UIElement):
- FilteredLayer {
- return new FilteredLayer(
- this,
- basemap, allElements, changes,
- selectedElement,
- showOnPopup);
- }
}
\ No newline at end of file
diff --git a/Customizations/Layers/BikeParkings.ts b/Customizations/Layers/BikeParkings.ts
index 67b0b89..765a954 100644
--- a/Customizations/Layers/BikeParkings.ts
+++ b/Customizations/Layers/BikeParkings.ts
@@ -1,7 +1,6 @@
import {LayerDefinition} from "../LayerDefinition";
import {And, Or, Tag} from "../../Logic/TagsFilter";
import {OperatorTag} from "../Questions/OperatorTag";
-import * as L from "leaflet";
import FixedText from "../Questions/FixedText";
import ParkingType from "../Questions/bike/ParkingType";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
@@ -47,11 +46,11 @@ export default class BikeParkings extends LayerDefinition {
return function (properties: any) {
return {
color: "#00bb00",
- icon: L.icon({
+ icon: {
iconUrl: self.icon,
iconSize: [50, 50],
iconAnchor: [25,50]
- })
+ }
};
};
}
diff --git a/Customizations/Layers/BikeShops.ts b/Customizations/Layers/BikeShops.ts
index 6fa764b..e07b981 100644
--- a/Customizations/Layers/BikeShops.ts
+++ b/Customizations/Layers/BikeShops.ts
@@ -3,7 +3,6 @@ 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";
@@ -71,11 +70,11 @@ export default class BikeShops extends LayerDefinition {
return {
color: "#00bb00",
- icon: L.icon({
+ icon: {
iconUrl: icon,
iconSize: [50, 50],
iconAnchor: [25, 50]
- })
+ }
}
}
}
diff --git a/Customizations/Layers/BikeStations.ts b/Customizations/Layers/BikeStations.ts
index ff2987b..cac60ae 100644
--- a/Customizations/Layers/BikeStations.ts
+++ b/Customizations/Layers/BikeStations.ts
@@ -1,6 +1,5 @@
import {LayerDefinition} from "../LayerDefinition";
import {And, Tag, TagsFilter, Or} from "../../Logic/TagsFilter";
-import * as L from "leaflet";
import BikeStationChain from "../Questions/bike/StationChain";
import BikeStationPumpTools from "../Questions/bike/StationPumpTools";
import BikeStationStand from "../Questions/bike/StationStand";
@@ -72,18 +71,18 @@ export default class BikeStations extends LayerDefinition {
if (isOperational) {
iconName = "pump.svg"
} else {
- iconName = "broken_pump.svg"
+ iconName = "broken_pump_2.svg"
}
}
const iconUrl = `./assets/bike/${iconName}`
return {
color: "#00bb00",
- icon: L.icon({
+ icon: {
iconUrl: iconUrl,
iconSize: [50, 50],
iconAnchor: [25, 50]
- })
+ }
};
};
}
diff --git a/Customizations/Layers/Birdhide.ts b/Customizations/Layers/Birdhide.ts
index a917e79..ea9e642 100644
--- a/Customizations/Layers/Birdhide.ts
+++ b/Customizations/Layers/Birdhide.ts
@@ -3,7 +3,6 @@ import {And, Or, Tag} from "../../Logic/TagsFilter";
import {TagRenderingOptions} from "../TagRendering";
import FixedText from "../Questions/FixedText";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
-import L from "leaflet";
export class Birdhide extends LayerDefinition {
@@ -13,8 +12,9 @@ export class Birdhide extends LayerDefinition {
constructor() {
super({
name: "vogelkijkplaats",
+ description: "Een plaats om vogels te kijken, zoals een vogelkijkhut of kijkwand",
overpassFilter: Birdhide.birdhide,
- elementsToShow: [new FixedText("hi")],
+ elementsToShow: [],
icon: "assets/nature/birdhide.svg",
minzoom: 12,
wayHandling: LayerDefinition.WAYHANDLING_CENTER_AND_WAY,
@@ -90,11 +90,11 @@ export class Birdhide extends LayerDefinition {
return {
color: "#0000bb",
- icon: L.icon({
+ icon: {
iconUrl: icon,
iconSize: [40,40],
iconAnchor: [20,20]
- })
+ }
}
}
diff --git a/Customizations/Layers/Bookcases.ts b/Customizations/Layers/Bookcases.ts
index 1f67cbd..6092291 100644
--- a/Customizations/Layers/Bookcases.ts
+++ b/Customizations/Layers/Bookcases.ts
@@ -1,9 +1,9 @@
import {LayerDefinition} from "../LayerDefinition";
-import L from "leaflet";
import {And, Or, Tag} from "../../Logic/TagsFilter";
import {TagRenderingOptions} from "../TagRendering";
import {NameInline} from "../Questions/NameInline";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
+import Translations from "../../UI/i18n/Translations";
export class Bookcases extends LayerDefinition {
@@ -16,7 +16,7 @@ export class Bookcases extends LayerDefinition {
this.overpassFilter = new Tag("amenity", "public_bookcase");
this.minzoom = 11;
- this.title = new NameInline("ruilboekenkastje");
+ this.title = new NameInline(Translations.t.bookcases.bookcase);
this.elementsToShow = [
new ImageCarouselWithUploadConstructor(),
new TagRenderingOptions({
@@ -38,7 +38,7 @@ export class Bookcases extends LayerDefinition {
question: "Hoeveel boeken passen in dit boekenruilkastje?",
freeform: {
renderTemplate: "Er passen {capacity} boeken in dit boekenruilkastje",
- template: "Er passen $$$ boeken in dit boekenruilkastje",
+ template: "Er passen $nat$ boeken in dit boekenruilkastje",
key: "capacity",
placeholder: "aantal"
},
@@ -159,10 +159,11 @@ export class Bookcases extends LayerDefinition {
this.style = function (tags) {
return {
- icon: new L.icon({
+ icon: {
iconUrl: "assets/bookcase.svg",
- iconSize: [40, 40]
- }),
+ iconSize: [40, 40],
+ iconAnchor: [20,20]
+ },
color: "#0000ff"
};
}
diff --git a/Customizations/Layers/DrinkingWater.ts b/Customizations/Layers/DrinkingWater.ts
index bfefdf8..579eed4 100644
--- a/Customizations/Layers/DrinkingWater.ts
+++ b/Customizations/Layers/DrinkingWater.ts
@@ -52,11 +52,11 @@ export class DrinkingWater extends LayerDefinition {
return {
color: "#00bb00",
- icon: new L.icon({
+ icon: {
iconUrl: self.icon,
iconSize: [50, 50],
iconAnchor: [25,50]
- })
+ }
};
};
}
diff --git a/Customizations/Layers/GrbToFix.ts b/Customizations/Layers/GrbToFix.ts
index 5c7fcf9..d92f8b3 100644
--- a/Customizations/Layers/GrbToFix.ts
+++ b/Customizations/Layers/GrbToFix.ts
@@ -1,5 +1,4 @@
import {LayerDefinition} from "../LayerDefinition";
-import L from "leaflet"
import {And, Regex, Tag} from "../../Logic/TagsFilter";
import {TagRenderingOptions} from "../TagRendering";
@@ -18,11 +17,10 @@ export class GrbToFix extends LayerDefinition {
this.style = function (tags) {
return {
- icon: new L.icon({
+ icon: {
iconUrl: "assets/star.svg",
iconSize: [40, 40],
- text: "hi"
- }),
+ },
color: "#ff0000"
};
diff --git a/Customizations/Layers/InformationBoard.ts b/Customizations/Layers/InformationBoard.ts
index 240e9e1..7b696db 100644
--- a/Customizations/Layers/InformationBoard.ts
+++ b/Customizations/Layers/InformationBoard.ts
@@ -3,12 +3,12 @@ import FixedText from "../Questions/FixedText";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
import {TagRenderingOptions} from "../TagRendering";
import {And, Tag} from "../../Logic/TagsFilter";
-import L from "leaflet";
export class InformationBoard extends LayerDefinition {
constructor() {
super({
name: "Informatiebord",
+ description: "Een informatiebord of kaart",
minzoom: 12,
overpassFilter: new Tag("tourism", "information"),
newElementTags: [new Tag("tourism", "information")],
@@ -44,12 +44,10 @@ export class InformationBoard extends LayerDefinition {
return {
color: "#000000",
- icon: L.icon(
- {
- iconUrl: icon,
- iconSize: [50, 50]
- }
- )
+ icon: {
+ iconUrl: icon,
+ iconSize: [50, 50]
+ }
};
}
diff --git a/Customizations/Layers/Map.ts b/Customizations/Layers/Map.ts
index aeadf29..183db79 100644
--- a/Customizations/Layers/Map.ts
+++ b/Customizations/Layers/Map.ts
@@ -3,7 +3,6 @@ import FixedText from "../Questions/FixedText";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
import {TagRenderingOptions} from "../TagRendering";
import {And, Tag} from "../../Logic/TagsFilter";
-import L from "leaflet";
export class Map extends LayerDefinition {
constructor() {
@@ -36,12 +35,10 @@ export class Map extends LayerDefinition {
return {
color: "#000000",
- icon: L.icon(
- {
- iconUrl: icon,
- iconSize: [50, 50]
- }
- )
+ icon: {
+ iconUrl: icon,
+ iconSize: [50, 50]
+ }
};
}
diff --git a/Customizations/Layers/NatureReserves.ts b/Customizations/Layers/NatureReserves.ts
index 3481042..d3f13c6 100644
--- a/Customizations/Layers/NatureReserves.ts
+++ b/Customizations/Layers/NatureReserves.ts
@@ -72,7 +72,7 @@ export class NatureReserves extends LayerDefinition {
freeform: {
renderTemplate: "Bij problemen of vragen, de conservator kan bereikt worden via " +
"{email}",
- template: "$$$",
+ template: "$email$",
key: "email"
}
}),
@@ -83,7 +83,7 @@ export class NatureReserves extends LayerDefinition {
freeform: {
renderTemplate: "Bij problemen of vragen, de {conservator} kan bereikt worden via " +
"{phone}",
- template: "$$$",
+ template: "$phone$",
key: "phone"
}
diff --git a/Customizations/Layers/Viewpoint.ts b/Customizations/Layers/Viewpoint.ts
index 5012e79..442d94e 100644
--- a/Customizations/Layers/Viewpoint.ts
+++ b/Customizations/Layers/Viewpoint.ts
@@ -1,5 +1,4 @@
import {LayerDefinition} from "../LayerDefinition";
-import L from "leaflet"
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
import FixedText from "../Questions/FixedText";
import {Tag} from "../../Logic/TagsFilter";
@@ -17,10 +16,10 @@ export class Viewpoint extends LayerDefinition {
wayHandling: LayerDefinition.WAYHANDLING_CENTER_ONLY,
style: tags => {
return {
- color: undefined, icon: new L.icon({
+ color: undefined, icon:{
iconUrl: "assets/viewpoint.svg",
iconSize: [20, 20]
- })
+ }
}
},
maxAllowedOverlapPercentage: 0,
diff --git a/Customizations/Layout.ts b/Customizations/Layout.ts
index 077fbe5..5d11f29 100644
--- a/Customizations/Layout.ts
+++ b/Customizations/Layout.ts
@@ -14,8 +14,11 @@ import {UIEventSource} from "../UI/UIEventSource";
export class Layout {
public name: string;
- public icon: string = "./assets/add.svg";
+ public icon: string = "./assets/logo.svg";
public title: UIElement;
+ public description: string | UIElement = Translations.t.general.about;
+ public socialImage: string = ""
+
public layers: LayerDefinition[];
public welcomeMessage: UIElement;
public gettingStartedPlzLogin: UIElement;
diff --git a/Customizations/Layouts/Bookcases.ts b/Customizations/Layouts/Bookcases.ts
index d833d6e..0a4f1aa 100644
--- a/Customizations/Layouts/Bookcases.ts
+++ b/Customizations/Layouts/Bookcases.ts
@@ -1,29 +1,20 @@
import {Layout} from "../Layout";
import * as Layer from "../Layers/Bookcases";
+import Translations from "../../UI/i18n/Translations";
+import Combine from "../../UI/Base/Combine";
-export class Bookcases extends Layout{
+export class Bookcases extends Layout {
constructor() {
- super( "bookcases",
- ["nl"],
- "Open Bookcase Map",
+ super("bookcases",
+ ["nl", "en"],
+ Translations.t.bookcases.title,
[new Layer.Bookcases()],
14,
51.2,
3.2,
-
- "
Open BoekenkastjesKaart
\n" +
- "\n" +
- "
" +
- "Help mee met het creëeren van een volledige kaart met alle boekenruilkastjes!" +
- "Een boekenruilkastje is een vaste plaats in publieke ruimte waar iedereen een boek in kan zetten of uit kan meenemen." +
- "Meestal een klein kastje of doosje dat op straat staat, maar ook een oude telefooncellen of een schap in een station valt hieronder."+
- "
",
- "Klik op een boekenruilkastje om vragen te beantwoorden");
- this.locationContains= ["Bookcases.html", "Bookcase.html","bookcase"]
+ new Combine(["
",Translations.t.bookcases.title,"
", Translations.t.bookcases.description])
+ );
+ this.icon = "assets/bookcase.svg"
}
}
\ No newline at end of file
diff --git a/Customizations/Layouts/Cyclofix.ts b/Customizations/Layouts/Cyclofix.ts
index 2cadb07..398e211 100644
--- a/Customizations/Layouts/Cyclofix.ts
+++ b/Customizations/Layouts/Cyclofix.ts
@@ -10,7 +10,7 @@ import Combine from "../../UI/Base/Combine";
export default class Cyclofix extends Layout {
constructor() {
super(
- "pomp",
+ "cyclofix",
["en", "nl", "fr"],
Translations.t.cyclofix.title,
[new BikeServices(), new BikeShops(), new DrinkingWater(), new BikeParkings()],
@@ -25,6 +25,8 @@ export default class Cyclofix extends Layout {
"
"
])
);
- this.icon = "./assets/bike/pump.svg"
+ this.icon = "./assets/bike/logo.svg"
+ this.description = "Easily search and contribute bicycle data nearby";
+ this.socialImage = "./assets/bike/cyclofix.jpeg"
}
}
diff --git a/Customizations/Layouts/Groen.ts b/Customizations/Layouts/Groen.ts
index 6faef2c..3ca7fe0 100644
--- a/Customizations/Layouts/Groen.ts
+++ b/Customizations/Layouts/Groen.ts
@@ -9,7 +9,7 @@ export class Groen extends Layout {
constructor() {
super("buurtnatuur",
["nl"],
- "Buurtnatuur",
+ "Buurtnatuur.be",
[new NatureReserves(), new Park(), new Bos(), new Viewpoint()],
10,
50.8435,
@@ -52,6 +52,9 @@ export class Groen extends Layout {
""
);
+ this.icon = "assets/groen.svg"
this.locationContains = ["buurtnatuur.be"]
+ this.socialImage = "assets/BuurtnatuurFront.jpg"
+ this.description = "Met deze tool kan je natuur in je buurt in kaart brengen en meer informatie geven over je favoriete plekje"
}
}
\ No newline at end of file
diff --git a/Customizations/Layouts/MetaMap.ts b/Customizations/Layouts/MetaMap.ts
index c174bc6..6486e9b 100644
--- a/Customizations/Layouts/MetaMap.ts
+++ b/Customizations/Layouts/MetaMap.ts
@@ -15,5 +15,6 @@ export class MetaMap extends Layout{
"
Open Map Map
\n" +
"This map is a map of physical maps, as known by OpenStreetMap.");
+ this.icon = "assets/osm-logo-buggy-attr.svg"
}
}
\ No newline at end of file
diff --git a/Customizations/Layouts/Natuurpunt.ts b/Customizations/Layouts/Natuurpunt.ts
index a03d4b9..26566e4 100644
--- a/Customizations/Layouts/Natuurpunt.ts
+++ b/Customizations/Layouts/Natuurpunt.ts
@@ -18,5 +18,6 @@ export class Natuurpunt extends Layout{
"",
""
);
+ this.icon = "./assets/nature/birdhide.svg"
}
}
\ No newline at end of file
diff --git a/Customizations/Layouts/Statues.ts b/Customizations/Layouts/Statues.ts
index d355fa4..90740bb 100644
--- a/Customizations/Layouts/Statues.ts
+++ b/Customizations/Layouts/Statues.ts
@@ -4,8 +4,8 @@ import {Artwork} from "../Layers/Artwork";
export class Statues extends Layout{
constructor() {
super( "statues",
- "Open Artwork Map",
["en"],
+ "Open Artwork Map",
[new Artwork()],
10,
50.8435,
diff --git a/Customizations/Layouts/StreetWidth.ts b/Customizations/Layouts/StreetWidth.ts
index faaea76..7ad592c 100644
--- a/Customizations/Layouts/StreetWidth.ts
+++ b/Customizations/Layouts/StreetWidth.ts
@@ -84,9 +84,9 @@ export class StreetWidth extends Layout{
"
Het aantal woonerven uitbreiden
" +
"
Grotere auto's meer belasten - ze nemen immers meer parkeerruimte in.
" +
"
Laat toeristen verplicht parkeren onder het zand; een (fiets)taxi kan hen naar hun hotel brengen
" +
- "
Voorzie in elke straat enkele parkeerplaatsen voor kortparkeren. Zo kunnen leveringen, iemand afzetten,... gebeuren zonder dat er een fietspad of een straat geblokkeerd wordt
"+
- "",
- "",
- "");
+ "
Voorzie in elke straat enkele parkeerplaatsen voor kortparkeren. Zo kunnen leveringen, iemand afzetten,... gebeuren zonder dat er een fietspad of een straat geblokkeerd wordt
" +
+ "");
+ this.icon = "assets/bug.svg";
+
}
}
\ No newline at end of file
diff --git a/Customizations/Questions/NameInline.ts b/Customizations/Questions/NameInline.ts
index 5c9d4e6..2e28cf9 100644
--- a/Customizations/Questions/NameInline.ts
+++ b/Customizations/Questions/NameInline.ts
@@ -1,28 +1,25 @@
import {TagRenderingOptions} from "../TagRendering";
import {And, Tag} from "../../Logic/TagsFilter";
import {UIElement} from "../../UI/UIElement";
+import Translations from "../../UI/i18n/Translations";
export class NameInline extends TagRenderingOptions{
- static Upper(string){
- return string.charAt(0).toUpperCase() + string.slice(1);
- }
-
- constructor(category: string ) {
+ constructor(category: string | UIElement ) {
super({
question: "",
freeform: {
renderTemplate: "{name}",
- template: "De naam van dit "+category+" is $$$",
+ template: Translations.t.general.nameInlineQuestion.Subs({category: category}),
key: "name",
extraTags: new Tag("noname", "") // Remove 'noname=yes'
},
mappings: [
- {k: new Tag("noname","yes"), txt: NameInline.Upper(category)+" zonder naam"},
- {k: null, txt: NameInline.Upper(category)}
+ {k: new Tag("noname","yes"), txt: Translations.t.general.noNameCategory.Subs({category: category})},
+ {k: null, txt: category}
]
});
}
diff --git a/Customizations/TagRendering.ts b/Customizations/TagRendering.ts
index 73798d0..193e24e 100644
--- a/Customizations/TagRendering.ts
+++ b/Customizations/TagRendering.ts
@@ -15,7 +15,8 @@ import {FixedInputElement} from "../UI/Input/FixedInputElement";
import {RadioButton} from "../UI/Input/RadioButton";
import Translations from "../UI/i18n/Translations";
import Locale from "../UI/i18n/Locale";
-
+import * as EmailValidator from 'email-validator';
+import { parsePhoneNumberFromString } from 'libphonenumber-js'
export class TagRenderingOptions implements TagDependantUIElementConstructor {
@@ -25,6 +26,12 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
"int": (str) => str.indexOf(".") < 0 && !isNaN(Number(str)),
"nat": (str) => str.indexOf(".") < 0 && !isNaN(Number(str)) && Number(str) > 0,
"float": (str) => !isNaN(Number(str)),
+ "email": (str) => EmailValidator.validate(str),
+ "phone": (str) => parsePhoneNumberFromString(str).isValid()
+ }
+
+ public static formatting = {
+ "phone": (str) => parsePhoneNumberFromString(str).formatInternational()
}
/**
@@ -345,7 +352,12 @@ class TagRendering extends UIElement implements TagDependantUIElement {
const prepost = Translations.W(freeform.template).InnerRender().split("$");
const type = prepost[1];
- const isValid = TagRenderingOptions.inputValidation[type];
+ let isValid = TagRenderingOptions.inputValidation[type];
+ if(isValid === undefined){
+ console.log("Invalid type for field type", type)
+ isValid = (str) => true;
+ }
+ let formatter = TagRenderingOptions.formatting[type] ?? ((str) => str);
const pickString =
(string: any) => {
@@ -355,7 +367,7 @@ class TagRendering extends UIElement implements TagDependantUIElement {
if (!isValid(string)) {
return undefined;
}
- const tag = new Tag(freeform.key, string);
+ const tag = new Tag(freeform.key, formatter(string));
if (freeform.extraTags === undefined) {
return tag;
diff --git a/Helpers.ts b/Helpers.ts
index 49043bd..22e7d38 100644
--- a/Helpers.ts
+++ b/Helpers.ts
@@ -70,6 +70,21 @@ export class Helpers {
return confirmationMessage; //Webkit, Safari, Chrome
});
+
+ document.addEventListener('visibilitychange',() => {
+ if(document.visibilityState === "visible"){
+ return;
+ }
+ if (changes.pendingChangesES.data == 0) {
+ return;
+ }
+
+ console.log("Upmoading: loss of focus")
+ changes.uploadAll(function () {
+ window.close()
+ });
+ })
+
}
}
\ No newline at end of file
diff --git a/Logic/Basemap.ts b/Logic/Basemap.ts
index f5c37e9..2c3edea 100644
--- a/Logic/Basemap.ts
+++ b/Logic/Basemap.ts
@@ -104,6 +104,5 @@ export class Basemap {
self.LastClickLocation.setData({lat: e.latlng.lat, lon: e.latlng.lng})
});
}
-
-
+
}
diff --git a/Logic/FilteredLayer.ts b/Logic/FilteredLayer.ts
index 3053fd3..15fddf7 100644
--- a/Logic/FilteredLayer.ts
+++ b/Logic/FilteredLayer.ts
@@ -1,12 +1,13 @@
-import { Basemap } from "./Basemap";
-import { TagsFilter, TagUtils } from "./TagsFilter";
-import { UIEventSource } from "../UI/UIEventSource";
-import { ElementStorage } from "./ElementStorage";
-import { Changes } from "./Changes";
+import {Basemap} from "./Basemap";
+import {TagsFilter, TagUtils} from "./TagsFilter";
+import {UIEventSource} from "../UI/UIEventSource";
+import {ElementStorage} from "./ElementStorage";
+import {Changes} from "./Changes";
import L from "leaflet"
-import { GeoOperations } from "./GeoOperations";
-import { UIElement } from "../UI/UIElement";
-import { LayerDefinition } from "../Customizations/LayerDefinition";
+import {GeoOperations} from "./GeoOperations";
+import {UIElement} from "../UI/UIElement";
+import {LayerDefinition} from "../Customizations/LayerDefinition";
+import {UserDetails} from "./OsmConnection";
/***
* A filtered layer is a layer which offers a 'set-data' function
@@ -26,7 +27,7 @@ export class FilteredLayer {
private readonly _map: Basemap;
private readonly _maxAllowedOverlap: number;
- private readonly _style: (properties) => { color: string, icon: any };
+ private readonly _style: (properties) => { color: string, icon: { iconUrl: string } };
private readonly _storage: ElementStorage;
@@ -59,7 +60,7 @@ export class FilteredLayer {
this._style = layerDef.style;
if (this._style === undefined) {
this._style = function () {
- return {icon: "", color: "#000000"};
+ return {icon: {iconUrl: "./assets/bug.svg"}, color: "#000000"};
}
}
this.name = name;
@@ -78,6 +79,20 @@ export class FilteredLayer {
}
})
}
+
+ static fromDefinition(
+ definition,
+ basemap: Basemap, allElements: ElementStorage, changes: Changes, userDetails: UIEventSource,
+ selectedElement: UIEventSource<{feature: any}>,
+ showOnPopup: (tags: UIEventSource, feature: any) => UIElement):
+ FilteredLayer {
+ return new FilteredLayer(
+ definition,
+ basemap, allElements, changes,
+ selectedElement,
+ showOnPopup);
+
+ }
/**
@@ -187,7 +202,7 @@ export class FilteredLayer {
} else {
marker = L.marker(latLng, {
- icon: style.icon
+ icon: new L.icon(style.icon)
});
}
return marker;
@@ -197,7 +212,7 @@ export class FilteredLayer {
let eventSource = self._storage.addOrGetElement(feature);
eventSource.addCallback(function () {
if (layer.setIcon) {
- layer.setIcon(self._style(feature.properties).icon)
+ layer.setIcon(L.icon(self._style(feature.properties).icon))
} else {
console.log("UPdating", layer);
@@ -212,7 +227,12 @@ export class FilteredLayer {
console.log("Selected ", feature)
self._selectedElement.setData({feature: feature});
const uiElement = self._showOnPopup(eventSource, feature);
- const popup = L.popup()
+
+ const iconInfo = self._style(feature.properties).icon;
+
+ const popup = L.popup({
+ autoPan: true,
+ })
.setContent(uiElement.Render())
.setLatLng(e.latlng)
.openOn(self._map.map);
diff --git a/Logic/GeoLocationHandler.ts b/Logic/GeoLocationHandler.ts
index 8c4075c..e84c3c1 100644
--- a/Logic/GeoLocationHandler.ts
+++ b/Logic/GeoLocationHandler.ts
@@ -3,7 +3,6 @@ import {UIEventSource} from "../UI/UIEventSource";
import {UIElement} from "../UI/UIElement";
import L from "leaflet";
import {Helpers} from "../Helpers";
-import {UserDetails} from "./OsmConnection";
export class GeoLocationHandler extends UIElement {
@@ -81,7 +80,7 @@ export class GeoLocationHandler extends UIElement {
this.HideOnEmpty(true);
}
- protected InnerRender(): string {
+ InnerRender(): string {
if (this.currentLocation.data) {
return "";
}
@@ -114,6 +113,12 @@ export class GeoLocationHandler extends UIElement {
if (!self._isActive.data) {
self._isActive.setData(true);
Helpers.DoEvery(60000, () => {
+
+ if(document.visibilityState !== "visible"){
+ console.log("Not starting gps: document not visible")
+ return;
+ }
+
self._map.map.findAccuratePosition({
maxWait: 10000, // defaults to 10000
desiredAccuracy: 50 // defaults to 20
diff --git a/Logic/LocalStorageSource.ts b/Logic/LocalStorageSource.ts
index 3b1146c..f3ed37d 100644
--- a/Logic/LocalStorageSource.ts
+++ b/Logic/LocalStorageSource.ts
@@ -3,15 +3,19 @@ import {UIEventSource} from "../UI/UIEventSource";
export class LocalStorageSource {
static Get(key: string, defaultValue: string = undefined): UIEventSource {
-
+
+ //*
+ // ignore when running from the console
+ return new UIEventSource(defaultValue);
+ /*/
const saved = localStorage.getItem(key);
const source = new UIEventSource(saved ?? defaultValue);
- // ignore when running from the console
source.addCallback((data) => {
localStorage.setItem(key, data);
console.log("Wriging ", key, data)
});
return source;
+ //*/
}
}
\ No newline at end of file
diff --git a/UI/Image/ImgurImage.ts b/UI/Image/ImgurImage.ts
index cf0e07d..c2d1041 100644
--- a/UI/Image/ImgurImage.ts
+++ b/UI/Image/ImgurImage.ts
@@ -32,7 +32,7 @@ export class ImgurImage extends UIElement {
}
- protected InnerRender(): string {
+ InnerRender(): string {
const image = "";
if(this._imageMeta.data === null){
diff --git a/UI/Image/SimpleImageElement.ts b/UI/Image/SimpleImageElement.ts
index 4c07045..1509ac1 100644
--- a/UI/Image/SimpleImageElement.ts
+++ b/UI/Image/SimpleImageElement.ts
@@ -8,7 +8,7 @@ export class SimpleImageElement extends UIElement {
super(source);
}
- protected InnerRender(): string {
+ InnerRender(): string {
return "";
}
diff --git a/UI/Image/WikimediaImage.ts b/UI/Image/WikimediaImage.ts
index abdf132..ed71b3c 100644
--- a/UI/Image/WikimediaImage.ts
+++ b/UI/Image/WikimediaImage.ts
@@ -29,7 +29,7 @@ export class WikimediaImage extends UIElement {
}
- protected InnerRender(): string {
+ InnerRender(): string {
let url = Wikimedia.ImageNameToUrl(this._imageLocation, 500, 400);
url = url.replace(/'/g, '%27');
diff --git a/UI/Input/InputElementWrapper.ts b/UI/Input/InputElementWrapper.ts
index 905a948..baf6b07 100644
--- a/UI/Input/InputElementWrapper.ts
+++ b/UI/Input/InputElementWrapper.ts
@@ -26,10 +26,6 @@ export class InputElementWrapper extends InputElement{
return this.input.GetValue();
}
- ShowValue(t: T) {
- return this.input.ShowValue(t);
- }
-
InnerRender(): string {
return this.pre.Render() + this.input.Render() + this.post.Render();
}
diff --git a/UI/SlideShow.ts b/UI/SlideShow.ts
index 8602d4c..254c03a 100644
--- a/UI/SlideShow.ts
+++ b/UI/SlideShow.ts
@@ -39,7 +39,7 @@ export class SlideShow extends UIElement {
}
- protected InnerRender(): string {
+ InnerRender(): string {
if (this._embeddedElements.data.length == 0) {
return this._noimages.Render();
}
diff --git a/UI/UIElement.ts b/UI/UIElement.ts
index 8bae413..f67e209 100644
--- a/UI/UIElement.ts
+++ b/UI/UIElement.ts
@@ -8,6 +8,9 @@ export abstract class UIElement {
public readonly _source: UIEventSource;
private _hideIfEmpty = false;
+
+ // WOrkaround as document is not defined
+ public static runningFromConsole = false;
protected constructor(source: UIEventSource) {
this.id = "ui-element-" + UIElement.nextId;
@@ -37,9 +40,10 @@ export abstract class UIElement {
}
Update(): void {
- if(document === undefined){
- return ; // Running from console
+ if(UIElement.runningFromConsole){
+ return;
}
+
let element = document.getElementById(this.id);
if (element === undefined || element === null) {
// The element is not painted
diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts
index d0f6375..58a1d8b 100644
--- a/UI/i18n/Translation.ts
+++ b/UI/i18n/Translation.ts
@@ -18,13 +18,11 @@ export default class Translation extends UIElement {
const parts = template.split("{" + k + "}");
const el: string | UIElement = text[k];
let rtext: string = "";
- console.log(parts)
if (typeof (el) === "string") {
rtext = el;
} else {
Translation.forcedLanguage = lang; // This is a very dirty hack - it'll bite me one day
rtext = el.InnerRender();
- console.log(rtext)
}
for (let i = 0; i < parts.length - 1; i++) {
combined.push(parts[i]);
diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts
index 9a5c871..a13e316 100644
--- a/UI/i18n/Translations.ts
+++ b/UI/i18n/Translations.ts
@@ -14,14 +14,14 @@ export default class Translations {
static t = {
cyclofix: {
title: new T({
- en: 'Cyclofix bicycle infrastructure',
- nl: 'Cyclofix fietsinfrastructuur',
+ en: 'Cyclofix - an open map for cyclists',
+ nl: 'Cyclofix - een open kaart voor fietsers',
fr: 'TODO: FRENCH TRANSLATION'
}),
description: new T({
- en: "On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." +
+ en: "On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels and everywhere else." +
"As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.",
- nl: "Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel." +
+ nl: "Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel en overal ter wereld." +
"Hierdoor kunnen fietsers snel de dichtstbijzijnde infrastructuur vinden die voldoet aan hun behoeften.",
fr: "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."
@@ -293,9 +293,21 @@ export default class Translations {
only: new T({en: 'This shop only sells second-hand bikes', nl: 'Deze winkel verkoopt enkel tweedehands fietsen', fr: 'TODO: fr'}),
},
diy: {
- question: new T({en: 'Are there tools here to repair your own bike?', nl: 'Biedt deze winkel gereedschap aan om je fiets zelf te herstellen?', fr: 'TODO: fr'}),
- yes: new T({en: 'This shop offers tools for DIY repair', nl: 'Deze winkel biedt gereedschap aan om je fiets zelf te herstellen', fr: 'TODO: fr'}),
- no: new T({en: 'This shop doesn\'t offer tools for DIY repair', nl: 'Deze winkel biedt geen gereedschap aan om je fiets zelf te herstellen', fr: 'TODO: fr'}),
+ question: new T({
+ en: 'Are there tools here to repair your own bike?',
+ nl: 'Biedt deze winkel gereedschap aan om je fiets zelf te herstellen?',
+ fr: 'TODO: fr'
+ }),
+ yes: new T({
+ en: 'This shop offers tools for DIY repair',
+ nl: 'Deze winkel biedt gereedschap aan om je fiets zelf te herstellen',
+ fr: 'TODO: fr'
+ }),
+ no: new T({
+ en: 'This shop doesn\'t offer tools for DIY repair',
+ nl: 'Deze winkel biedt geen gereedschap aan om je fiets zelf te herstellen',
+ fr: 'TODO: fr'
+ }),
}
},
drinking_water: {
@@ -305,6 +317,20 @@ export default class Translations {
})
}
},
+ bookcases: {
+ title: new T({en: "Open Bookcase Map", nl: "Open Boekenkastjes kaart"}),
+ description: new T({
+ en: "Search a bookcase near you and add information about them in the biggest shared map of the world.",
+ nl: "Help mee met het creëeren van een volledige kaart met alle boekenruilkastjes!" +
+ "Een boekenruilkastje is een vaste plaats in publieke ruimte waar iedereen een boek in kan zetten of uit kan meenemen." +
+ "Meestal een klein kastje of doosje dat op straat staat, maar ook een oude telefooncellen of een schap in een station valt hieronder."
+ }
+ ),
+ bookcase: new T({
+ nl: "Boekenruilkastje"
+ })
+ },
+
image: {
addPicture: new T({en: 'Add picture', nl: 'Voeg foto toe', fr: 'TODO: fr'}),
uploadingPicture: new T({
@@ -424,8 +450,19 @@ export default class Translations {
pickLanguage: new T({
en: "Choose a language",
nl: "Kies je taal"
+ }),
+ about: new T({
+ en: "Easily edit and add OpenStreetMap for a certain theme",
+ nl: "Easily edit and add OpenStreetMap for a certain theme"
+
+ }),
+ nameInlineQuestion: new T({
+ nl: "De naam van dit {category} is $$$"
+ }),
+ noNameCategory: new T({
+ nl: "{category} zonder naam"
})
- }
+ }
}
public static W(s: string | UIElement): UIElement {
@@ -435,4 +472,35 @@ export default class Translations {
return new FixedUiElement(s);
}
+ public static CountTranslations() {
+ const queue: any = [Translations.t];
+ const tr: Translation[] = [];
+ while (queue.length > 0) {
+ const item = queue.pop();
+ if (item instanceof Translation || item.translations !== undefined) {
+ tr.push(item);
+ } else {
+ for (const t in item) {
+ const x = item[t];
+ queue.push(x)
+ }
+ }
+ }
+
+ const langaugeCounts = {};
+ for (const translation of tr) {
+ for (const language in translation.translations) {
+ if (langaugeCounts[language] === undefined) {
+ langaugeCounts[language] = 1
+ } else {
+ langaugeCounts[language]++;
+ }
+ }
+ }
+ for (const language in langaugeCounts) {
+ console.log("Total translations in ", language, langaugeCounts[language], "/", tr.length)
+ }
+
+ }
+
}
diff --git a/assets/add.svg b/assets/add.svg
new file mode 100644
index 0000000..cc4b162
--- /dev/null
+++ b/assets/add.svg
@@ -0,0 +1,289 @@
+
+
diff --git a/assets/bike/broken_pump_2.svg b/assets/bike/broken_pump_2.svg
new file mode 100644
index 0000000..72d4719
--- /dev/null
+++ b/assets/bike/broken_pump_2.svg
@@ -0,0 +1,219 @@
+
+
diff --git a/assets/bike/logo.svg b/assets/bike/logo.svg
new file mode 100644
index 0000000..059b16e
--- /dev/null
+++ b/assets/bike/logo.svg
@@ -0,0 +1,165 @@
+
+
diff --git a/assets/logo.svg b/assets/logo.svg
new file mode 100644
index 0000000..bd2eb3c
--- /dev/null
+++ b/assets/logo.svg
@@ -0,0 +1,297 @@
+
+
diff --git a/assets/logos/logo.svg b/assets/logos/logo.svg
deleted file mode 100644
index 7e4cba1..0000000
--- a/assets/logos/logo.svg
+++ /dev/null
@@ -1,3300 +0,0 @@
-
-
-
-
diff --git a/assets/logos/logo192.png b/assets/logos/logo192.png
deleted file mode 100644
index 0b71451..0000000
Binary files a/assets/logos/logo192.png and /dev/null differ
diff --git a/assets/logos/logo512.png b/assets/logos/logo512.png
deleted file mode 100644
index 9c9015d..0000000
Binary files a/assets/logos/logo512.png and /dev/null differ
diff --git a/clean.sh b/clean.sh
index 4fac85d..5021175 100755
--- a/clean.sh
+++ b/clean.sh
@@ -10,3 +10,16 @@ rm UI/*/*/*.js
rm Customizations/*.js
rm Customizations/*/*.js
rm Customizations/*/*/*.js
+
+rm *.webmanifest
+rm q*.html
+rm assets/generated/*
+
+for f in ./*.html; do
+ if [[ "$f" == "./index.html" ]] || [[ "$f" == "./land.html" ]] || [[ "$f" == "./test.html" ]]
+ then
+ echo "Not removing $f"
+ else
+ rm $f
+ fi
+done
\ No newline at end of file
diff --git a/createLayouts.ts b/createLayouts.ts
index e1bdd71..8d92d73 100644
--- a/createLayouts.ts
+++ b/createLayouts.ts
@@ -1,12 +1,199 @@
-/*
-*/
-import {Bookcases} from "./Customizations/Layers/Bookcases";
+import {Groen} from "./Customizations/Layouts/Groen";
+import {Bookcases} from "./Customizations/Layouts/Bookcases";
+import {GRB} from "./Customizations/Layouts/GRB";
+import Cyclofix from "./Customizations/Layouts/Cyclofix";
+import {WalkByBrussels} from "./Customizations/Layouts/WalkByBrussels";
+import {MetaMap} from "./Customizations/Layouts/MetaMap";
+import {StreetWidth} from "./Customizations/Layouts/StreetWidth";
+import {Natuurpunt} from "./Customizations/Layouts/Natuurpunt";
+import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
+import {Layout} from "./Customizations/Layout";
+import {readFileSync, writeFile, writeFileSync} from "fs";
+import {Utils} from "./Utils";
+import svg2img from 'promise-svg2img';
+import Translation from "./UI/i18n/Translation";
+import Locale from "./UI/i18n/Locale";
+import Translations from "./UI/i18n/Translations";
+import {UIElement} from "./UI/UIElement";
+import {LayerDefinition} from "./Customizations/LayerDefinition";
console.log("Building routers")
-new Bookcases()
-/*
-for(const layout in AllKnownLayouts.allSets){
- console.log(layout)
+UIElement.runningFromConsole = true;
+
+function enc(str: string): string {
+ return encodeURIComponent(str.toLowerCase());
}
-*/
\ No newline at end of file
+
+function validate(layout: Layout) {
+
+ const translations: Translation[] = [];
+ const queue: any[] = [layout]
+
+ while (queue.length > 0) {
+ const item = queue.pop();
+ for (const key in item) {
+ const v = item[key];
+ if (v === undefined) {
+ continue;
+ }
+ if (v instanceof Translation || v?.translations !== undefined) {
+ translations.push(v);
+ } else if (
+ ["string", "function", "boolean", "number"].indexOf(typeof (v)) < 0) {
+ queue.push(v)
+ }
+ }
+ }
+
+ const missing = {}
+ const present = {}
+ for (const ln of layout.supportedLanguages) {
+ missing[ln] = 0;
+ present[ln] = 0;
+ for (const translation of translations) {
+ const txt = translation.translations[ln];
+ const isMissing = txt === undefined || txt === "" || txt.toLowerCase().indexOf("todo") >= 0;
+ if (isMissing) {
+ console.log("Missing or suspicious translation for '", translation.txt, "'in", ln, ":", txt)
+ missing[ln]++
+ } else {
+ present[ln]++;
+ }
+ }
+ }
+
+ console.log("Translation completenes for", layout.name);
+ for (const ln of layout.supportedLanguages) {
+ const amiss = missing[ln];
+ const ok = present[ln];
+ const total = amiss + ok;
+ console.log(`${ln}: ${ok}/${total}`)
+ }
+
+}
+
+
+const alreadyWritten = []
+
+function createIcon(iconPath: string, size: number) {
+
+ let name = iconPath.split(".").slice(0, -1).join(".");
+ if(name.startsWith("./")){
+ name = name.substr(2)
+ }
+ const newname = `${name}${size}.png`
+ .replace(/\//g,"_")
+ .replace("assets_","assets/generated/");
+
+ if (alreadyWritten.indexOf(newname) >= 0) {
+ return newname;
+ }
+ alreadyWritten.push(newname);
+ try {
+ readFileSync(newname);
+ return newname; // File already exists - nothing to do
+ } catch (e) {
+
+ }
+
+ svg2img(iconPath,
+ // @ts-ignore
+ {width: size, height: size, preserveAspectRatio: true})
+ .then((buffer) => {
+ console.log("Writing icon", newname)
+ writeFileSync(newname, buffer);
+ }).catch((error) => {
+ console.log("ERROR", error)
+ });
+ return newname;
+}
+
+function createManifest(layout: Layout, relativePath: string) {
+ const name = Utils.Upper(layout.name);
+
+ const icons = [];
+
+ if (layout.icon.endsWith(".svg")) {
+ // This is an svg. Lets create the needed pngs!
+ const sizes = [72, 96, 120, 128, 144, 152, 180, 192, 384, 512];
+ for (const size of sizes) {
+ const name = createIcon(layout.icon, size);
+ icons.push({
+ src: name,
+ sizes: size + "x" + size,
+ type: "image/png"
+ })
+ }
+ icons.push({
+ src: layout.icon,
+ sizes: "513x513",
+ type: "image/svg"
+ })
+ } else {
+
+ throw "Icon is not an svg for " + layout.name
+ }
+ const ogTitle = Translations.W(layout.title).InnerRender();
+ const ogDescr = Translations.W(layout.description).InnerRender();
+
+ const manif = {
+ name: name,
+ short_name: ogTitle,
+ start_url: `${relativePath}/${layout.name.toLowerCase()}.html`,
+ display: "standalone",
+ background_color: "#fff",
+ description: ogDescr,
+ orientation: "portrait-primary, landscape-primary",
+ icons: icons
+ }
+ return manif;
+}
+
+const template = readFileSync("index.html", "utf8");
+
+function createLandingPage(layout: Layout) {
+
+ Locale.language.setData(layout.supportedLanguages[0]);
+
+ const ogTitle = Translations.W(layout.title).InnerRender();
+ const ogDescr = Translations.W(layout.description).InnerRender();
+ const ogImage = layout.socialImage;
+
+ const og = `
+
+
+ `
+
+ return template
+ .replace(`./manifest.manifest`, `./${enc(layout.name)}.webmanifest`)
+ .replace("", og)
+ .replace(``,
+ ``)
+}
+
+
+const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap"]
+const all = AllKnownLayouts.allSets;
+for (const layoutName in all) {
+ if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) {
+ console.log(`Skipping a layout with name${layoutName}, it is on the blacklist`);
+ continue;
+ }
+ const err = err => {
+ if (err !== null) {
+ console.log("Could not write manifest for ", layoutName, " because ", err)
+ }
+ };
+ const layout = all[layoutName];
+ validate(layout)
+ const manif = JSON.stringify(createManifest(layout, "/MapComplete"));
+
+ const manifestLocation = encodeURIComponent(layout.name.toLowerCase()) + ".webmanifest";
+ writeFile(manifestLocation, manif, err);
+
+ const landing = createLandingPage(layout);
+ writeFile(enc(layout.name) + ".html", landing, err)
+}
+
+Translations.CountTranslations();
\ No newline at end of file
diff --git a/deploy.sh b/deploy.sh
index ff4b3be..4799663 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -1,10 +1,10 @@
#! /bin/bash
-npx ts-node createLayout.ts
-
+ts-node createLayouts.ts
npm run build
rm -rf /home/pietervdvn/git/pietervdvn.github.io/MapComplete/*
cp -r dist/* /home/pietervdvn/git/pietervdvn.github.io/MapComplete/
+./clean.sh
cd /home/pietervdvn/git/pietervdvn.github.io/MapComplete/
git add .
git commit -m "New mapcomplete version"
diff --git a/index.css b/index.css
index b07c605..67af8a1 100644
--- a/index.css
+++ b/index.css
@@ -855,6 +855,13 @@ form {
}
.featureinfobox {
+ max-height: 80vh;
+ overflow-y: auto;
+}
+
+.featureinfobox > div {
+ width: calc(100% - 2em);
+ padding-left: 1em;
}
.featureinfoboxtitle {
diff --git a/index.html b/index.html
index 319f83d..4e30fb9 100644
--- a/index.html
+++ b/index.html
@@ -1,5 +1,5 @@
-
+
@@ -7,23 +7,12 @@
MapComplete
-
-
+
+
-
-
-
+
+