Use OSM-settings to keep track of the chosen license; change tree marker to circle (fix #24)

This commit is contained in:
Pieter Vander Vennet 2020-07-01 17:38:48 +02:00
parent b2704d0ab8
commit b1775d8184
15 changed files with 83 additions and 57 deletions

View file

@ -22,7 +22,7 @@ export class LayerDefinition {
elementsToShow: (TagMappingOptions | QuestionDefinition | UIElement)[]; elementsToShow: (TagMappingOptions | QuestionDefinition | UIElement)[];
questions: QuestionDefinition[]; // Questions are shown below elementsToShow in a questionPicker questions: QuestionDefinition[]; // Questions are shown below elementsToShow in a questionPicker
style: (tags: any) => any; style: (tags: any) => { color: string, icon: any };
/** /**
* If an object of the next layer is contained for this many percent in this feature, it is eaten and not shown * If an object of the next layer is contained for this many percent in this feature, it is eaten and not shown

View file

@ -43,11 +43,6 @@ export class Bos extends LayerDefinition {
} }
private readonly treeIcon = new L.icon({
iconUrl: "assets/tree_white_background.svg",
iconSize: [40, 40]
})
private generateStyleFunction() { private generateStyleFunction() {
const self = this; const self = this;
return function (properties: any) { return function (properties: any) {
@ -73,7 +68,7 @@ export class Bos extends LayerDefinition {
return { return {
color: colour, color: colour,
icon: self.treeIcon icon: undefined
}; };
}; };
} }

View file

@ -1,7 +1,6 @@
import {LayerDefinition} from "../LayerDefinition"; import {LayerDefinition} from "../LayerDefinition";
import {Quests} from "../Quests"; import {Quests} from "../Quests";
import {TagMappingOptions} from "../UI/TagMapping"; import {TagMappingOptions} from "../UI/TagMapping";
import L from "leaflet"
import {CommonTagMappings} from "./CommonTagMappings"; import {CommonTagMappings} from "./CommonTagMappings";
import {Or, Tag} from "../Logic/TagsFilter"; import {Or, Tag} from "../Logic/TagsFilter";
@ -32,11 +31,6 @@ export class NatureReserves extends LayerDefinition {
} }
private readonly treeIcon = new L.icon({
iconUrl: "assets/tree_white_background.svg",
iconSize: [40, 40]
})
private generateStyleFunction() { private generateStyleFunction() {
const self = this; const self = this;
return function (properties: any) { return function (properties: any) {
@ -62,7 +56,7 @@ export class NatureReserves extends LayerDefinition {
return { return {
color: colour, color: colour,
icon: self.treeIcon icon: undefined
}; };
}; };
} }

View file

@ -1,7 +1,6 @@
import {LayerDefinition} from "../LayerDefinition"; import {LayerDefinition} from "../LayerDefinition";
import {Quests} from "../Quests"; import {Quests} from "../Quests";
import {TagMappingOptions} from "../UI/TagMapping"; import {TagMappingOptions} from "../UI/TagMapping";
import L from "leaflet"
import {CommonTagMappings} from "./CommonTagMappings"; import {CommonTagMappings} from "./CommonTagMappings";
import {Or, Tag} from "../Logic/TagsFilter"; import {Or, Tag} from "../Logic/TagsFilter";
@ -34,10 +33,7 @@ export class Park extends LayerDefinition {
} }
private readonly treeIcon = new L.icon({
iconUrl: "assets/tree_white_background.svg",
iconSize: [40, 40]
})
private generateStyleFunction() { private generateStyleFunction() {
const self = this; const self = this;
@ -64,7 +60,7 @@ export class Park extends LayerDefinition {
return { return {
color: colour, color: colour,
icon: self.treeIcon icon: undefined
}; };
}; };
} }

View file

@ -24,7 +24,7 @@ export class FilteredLayer {
private readonly _map: Basemap; private readonly _map: Basemap;
private readonly _maxAllowedOverlap: number; private readonly _maxAllowedOverlap: number;
private readonly _style: (properties) => any; private readonly _style: (properties) => { color: string, icon: any };
private readonly _storage: ElementStorage; private readonly _storage: ElementStorage;
@ -170,9 +170,12 @@ export class FilteredLayer {
const style = self._style(feature.properties); const style = self._style(feature.properties);
let marker; let marker;
if (style.icon === undefined) { if (style.icon === undefined) {
marker = L.marker(latLng); marker = L.circle(latLng, {
} else { radius: 50,
color: style.color
});
} else {
marker = L.marker(latLng, { marker = L.marker(latLng, {
icon: style.icon icon: style.icon
}); });

View file

@ -12,9 +12,11 @@ export class OsmImageUploadHandler {
private _changeHandler: Changes; private _changeHandler: Changes;
private _userdetails: UIEventSource<UserDetails>; private _userdetails: UIEventSource<UserDetails>;
private _slideShow: SlideShow; private _slideShow: SlideShow;
private _preferedLicense: UIEventSource<string>;
constructor(tags: UIEventSource<any>, constructor(tags: UIEventSource<any>,
userdetails: UIEventSource<UserDetails>, userdetails: UIEventSource<UserDetails>,
preferedLicense: UIEventSource<string>,
changeHandler: Changes, changeHandler: Changes,
slideShow : SlideShow slideShow : SlideShow
) { ) {
@ -25,6 +27,7 @@ export class OsmImageUploadHandler {
this._tags = tags; this._tags = tags;
this._changeHandler = changeHandler; this._changeHandler = changeHandler;
this._userdetails = userdetails; this._userdetails = userdetails;
this._preferedLicense = preferedLicense;
} }
private generateOptions(license: string) { private generateOptions(license: string) {
@ -65,6 +68,7 @@ export class OsmImageUploadHandler {
const self = this; const self = this;
return new ImageUploadFlow( return new ImageUploadFlow(
this._userdetails, this._userdetails,
this._preferedLicense,
function (license) { function (license) {
return self.generateOptions(license) return self.generateOptions(license)
} }

View file

@ -40,7 +40,6 @@ export class Overpass {
$.getJSON(query, $.getJSON(query,
function (json, status) { function (json, status) {
console.log("status:", status)
if (status !== "success") { if (status !== "success") {
console.log("Query failed") console.log("Query failed")
onFail(status); onFail(status);

View file

@ -7,12 +7,19 @@ export class DropDownUI extends UIElement {
private _label: string; private _label: string;
private _values: { value: string; shown: string }[]; private _values: { value: string; shown: string }[];
constructor(label: string, values: { value: string, shown: string }[]) { constructor(label: string, values: { value: string, shown: string }[],
selectedElement: UIEventSource<string> = undefined) {
super(undefined); super(undefined);
this._label = label; this._label = label;
this._values = values; this._values = values;
this.selectedElement = new UIEventSource<string>(values[0].value); this.selectedElement = selectedElement ?? new UIEventSource<string>(values[0].value);
if(selectedElement.data === undefined){
this.selectedElement.setData(values[0].value)
}
const self = this;
this.selectedElement.addCallback(() => {
self.InnerUpdate();
});
} }
@ -31,17 +38,21 @@ export class DropDownUI extends UIElement {
"</form>"; "</form>";
} }
InnerUpdate(htmlElement: HTMLElement) { InnerUpdate() {
super.InnerUpdate(htmlElement);
const self = this; const self = this;
const e = document.getElementById("dropdown-" + this.id); const e = document.getElementById("dropdown-" + this.id);
// @ts-ignore
if (this.selectedElement.data !== e.value) {
// @ts-ignore
e.value = this.selectedElement.data;
}
e.onchange = function () { e.onchange = function () {
// @ts-ignore // @ts-ignore
const selectedValue = e.options[e.selectedIndex].value; const selectedValue = e.options[e.selectedIndex].value;
console.log("Putting data", selectedValue)
self.selectedElement.setData(selectedValue); self.selectedElement.setData(selectedValue);
} }
} }
} }

View file

@ -7,10 +7,7 @@ import {OsmImageUploadHandler} from "../Logic/OsmImageUploadHandler";
import {ImageCarousel} from "./Image/ImageCarousel"; import {ImageCarousel} from "./Image/ImageCarousel";
import {Changes} from "../Logic/Changes"; import {Changes} from "../Logic/Changes";
import {UserDetails} from "../Logic/OsmConnection"; import {UserDetails} from "../Logic/OsmConnection";
import {Img} from "./Img";
import {CommonTagMappings} from "../Layers/CommonTagMappings"; import {CommonTagMappings} from "../Layers/CommonTagMappings";
import {Tag} from "../Logic/TagsFilter";
import {ImageUploadFlow} from "./ImageUploadFlow";
import {VerticalCombine} from "./Base/VerticalCombine"; import {VerticalCombine} from "./Base/VerticalCombine";
export class FeatureInfoBox extends UIElement { export class FeatureInfoBox extends UIElement {
@ -38,6 +35,7 @@ export class FeatureInfoBox extends UIElement {
questions: QuestionDefinition[], questions: QuestionDefinition[],
changes: Changes, changes: Changes,
userDetails: UIEventSource<UserDetails>, userDetails: UIEventSource<UserDetails>,
preferedPictureLicense : UIEventSource<string>
) { ) {
super(tagsES); super(tagsES);
this._tagsES = tagsES; this._tagsES = tagsES;
@ -71,7 +69,8 @@ export class FeatureInfoBox extends UIElement {
this._osmLink = new TagMapping(CommonTagMappings.osmLink, this._tagsES); this._osmLink = new TagMapping(CommonTagMappings.osmLink, this._tagsES);
this._wikipedialink = new TagMapping(CommonTagMappings.wikipediaLink, this._tagsES); this._wikipedialink = new TagMapping(CommonTagMappings.wikipediaLink, this._tagsES);
this._pictureUploader = new OsmImageUploadHandler(tagsES, userDetails, changes, this._imageElement.slideshow).getUI(); this._pictureUploader = new OsmImageUploadHandler(tagsES, userDetails, preferedPictureLicense,
changes, this._imageElement.slideshow).getUI();
} }

View file

@ -16,6 +16,7 @@ export class ImageUploadFlow extends UIElement {
constructor( constructor(
userInfo: UIEventSource<UserDetails>, userInfo: UIEventSource<UserDetails>,
preferedLicense : UIEventSource<string>,
uploadOptions: ((license: string) => uploadOptions: ((license: string) =>
{ {
title: string, title: string,
@ -36,7 +37,8 @@ export class ImageUploadFlow extends UIElement {
{value: "CC0", shown: "in het publiek domein"}, {value: "CC0", shown: "in het publiek domein"},
{value: "CC-BY-SA 4.0", shown: "onder een CC-BY-SA-licentie"}, {value: "CC-BY-SA 4.0", shown: "onder een CC-BY-SA-licentie"},
{value: "CC-BY 4.0", shown: "onder een CC-BY-licentie"} {value: "CC-BY 4.0", shown: "onder een CC-BY-licentie"}
] ],
preferedLicense
); );
this._licensePicker = licensePicker; this._licensePicker = licensePicker;
this._selectedLicence = licensePicker.selectedElement; this._selectedLicence = licensePicker.selectedElement;

View file

@ -33,6 +33,7 @@ export abstract class UIElement {
public onClick(f: (() => void)) { public onClick(f: (() => void)) {
this._onClick = f; this._onClick = f;
this.Update(); this.Update();
return this;
} }
Update(): void { Update(): void {
@ -52,10 +53,8 @@ export abstract class UIElement {
} }
if (this._onClick !== undefined) { if (this._onClick !== undefined) {
console.log("Registering")
const self = this; const self = this;
element.onclick = () => { element.onclick = () => {
console.log("Clicked!")
self._onClick(); self._onClick();
} }
element.style.cursor = "pointer"; element.style.cursor = "pointer";

View file

@ -22,8 +22,8 @@ export class UIEventSource<T>{
} }
public ping(): void { public ping(): void {
for (let i in this._callbacks) { for (const callback of this._callbacks) {
this._callbacks[i](this.data); callback(this.data);
} }
} }

View file

@ -3,6 +3,7 @@ import {UserDetails} from "../Logic/OsmConnection";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {Basemap} from "../Logic/Basemap"; import {Basemap} from "../Logic/Basemap";
import L from "leaflet"; import L from "leaflet";
import {FixedUiElement} from "./Base/FixedUiElement";
/** /**
* Handles and updates the user badge * Handles and updates the user badge
@ -10,6 +11,7 @@ import L from "leaflet";
export class UserBadge extends UIElement { export class UserBadge extends UIElement {
private _userDetails: UIEventSource<UserDetails>; private _userDetails: UIEventSource<UserDetails>;
private _pendingChanges: UIElement; private _pendingChanges: UIElement;
private _logout: UIElement;
private _basemap: Basemap; private _basemap: Basemap;
@ -21,6 +23,9 @@ export class UserBadge extends UIElement {
this._pendingChanges = pendingChanges; this._pendingChanges = pendingChanges;
this._basemap = basemap; this._basemap = basemap;
this._logout = new FixedUiElement("<img src='assets/logout.svg' alt='logout'>")
.onClick(() => {userDetails.data.osmConnection.LogOut();});
userDetails.addCallback(function () { userDetails.addCallback(function () {
const profilePic = document.getElementById("profile-pic"); const profilePic = document.getElementById("profile-pic");
profilePic.onload = function () { profilePic.onload = function () {

View file

@ -67,6 +67,7 @@ const leftMessage = new UIEventSource<() => UIElement>(undefined);
const selectedElement = new UIEventSource<any>(undefined); const selectedElement = new UIEventSource<any>(undefined);
const preferedPictureLicense = new UIEventSource<string>(undefined);
const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({ const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({
zoom: questSetToRender.startzoom, zoom: questSetToRender.startzoom,
@ -101,6 +102,21 @@ const bm = new Basemap("leafletDiv", locationControl, new VariableUiElement(
)); ));
// ------------- Tie together user settings and UI -----------
const picturesPrefName = "mapcomplete-pictures-license";
preferedPictureLicense.addCallback((license) => {
osmConnection.SetPreference(picturesPrefName, license);
});
osmConnection.preferences.addCallback((prefs) => {
if (prefs[picturesPrefName] !== undefined) {
preferedPictureLicense.setData(prefs[picturesPrefName]);
}
})
// ------------- Setup the layers ------------------------------- // ------------- Setup the layers -------------------------------
const addButtons: { const addButtons: {
@ -122,7 +138,8 @@ for (const layer of questSetToRender.layers) {
layer.elementsToShow, layer.elementsToShow,
layer.questions, layer.questions,
changes, changes,
osmConnection.userDetails osmConnection.userDetails,
preferedPictureLicense
) )
}; };
@ -145,12 +162,6 @@ const layerUpdater = new LayerUpdater(bm, questSetToRender.startzoom, flayers);
// ------------------ Setup various UI elements ------------ // ------------------ Setup various UI elements ------------
/*
const addButton = new AddButton(bm, changes, addButtons);
addButton.AttachTo("bottomRight");
addButton.Update();*/
new StrayClickHandler(bm, selectedElement, leftMessage, () => { new StrayClickHandler(bm, selectedElement, leftMessage, () => {
return new SimpleAddUI(bm.Location, return new SimpleAddUI(bm.Location,
bm.LastClickLocation, bm.LastClickLocation,
@ -178,13 +189,12 @@ selectedElement.addCallback((data) => {
layer.elementsToShow, layer.elementsToShow,
layer.questions, layer.questions,
changes, changes,
osmConnection.userDetails osmConnection.userDetails,
preferedPictureLicense
)); ));
break; break;
} }
} }
} }
); );

23
test.ts
View file

@ -2,16 +2,25 @@ import {Geocoding} from "./Logic/Geocoding";
import {SearchAndGo} from "./UI/SearchAndGo"; import {SearchAndGo} from "./UI/SearchAndGo";
import {TextField} from "./UI/Base/TextField"; import {TextField} from "./UI/Base/TextField";
import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {VariableUiElement} from "./UI/Base/VariableUIElement";
import {DropDownUI} from "./UI/Base/DropDownUI";
import {UIEventSource} from "./UI/UIEventSource";
console.log("HI"); console.log("HI");
new SearchAndGo().AttachTo("maindiv");
/*const tf = new TextField(); var control = new UIEventSource<string>("b");
tf.AttachTo("maindiv"); control.addCallback((data) => {
tf.enterPressed.addCallback(() => {alert("Searching")}); console.log("> GOT", control.data)
new VariableUiElement(tf.value).AttachTo("extradiv"); })
/*/
new DropDownUI("Test",
[{value: "a", shown: "a"},
{value: "b", shown: "b"},
{value: "c", shown: "c"},
], control
).AttachTo("maindiv");
new VariableUiElement(control).AttachTo("extradiv");
//*/ window.setTimeout(() => {control.setData("a")}, 1000);