Further work on infobox, styling everything, removing clutter

This commit is contained in:
Pieter Vander Vennet 2020-06-27 03:06:51 +02:00
parent 2acd53d150
commit 0b4016b65d
48 changed files with 1283 additions and 454 deletions

View file

@ -58,21 +58,36 @@ export class Basemap {
constructor(leafletElementId: string, location: UIEventSource<{ zoom: number, lat: number, lon: number }>) {
this. map = L.map(leafletElementId, {
this.map = L.map(leafletElementId, {
center: [location.data.lat, location.data.lon],
zoom: location.data.zoom,
layers: [this.osmLayer]
layers: [this.osmLayer],
attributionControl: false
});
L.control.attribution({
position: 'bottomleft'
}).addTo(this.map);
this.Location = location;
L.control.layers(this.baseLayers).addTo(this.map);
const layerControl = L.control.layers(this.baseLayers, null,
{
position: 'bottomleft',
hideSingleBase: true
})
layerControl.addTo(this.map);
this.map.zoomControl.setPosition("bottomleft");
const self = this;
this.map.on("moveend", function () {
location.data.zoom = self.map.getZoom();
location.data.lat = self.map.getCenter().lat;
location.data.lon = self.map.getCenter().lon;
location.ping();
})
});
}

View file

@ -16,16 +16,23 @@ export class Changes {
private readonly login: OsmConnection;
public readonly _allElements: ElementStorage;
public _pendingChanges: { elementId: string, key: string, value: string }[] = []; // Gets reset on uploadAll
private _pendingChanges: { elementId: string, key: string, value: string }[] = []; // Gets reset on uploadAll
private newElements: OsmObject[] = []; // Gets reset on uploadAll
public readonly pendingChangesES = new UIEventSource(this._pendingChanges);
private readonly centerMessage: UIEventSource<string>;
public readonly pendingChangesES = new UIEventSource<number>(this._pendingChanges.length);
public readonly isSaving = new UIEventSource(false);
private readonly _changesetComment: string;
private readonly _centerMessage: UIEventSource<string>;
constructor(login: OsmConnection, allElements: ElementStorage, centerMessage: UIEventSource<string>) {
constructor(
changesetComment: string,
login: OsmConnection,
allElements: ElementStorage,
centerMessage: UIEventSource<string>) {
this._changesetComment = changesetComment;
this.login = login;
this._allElements = allElements;
this.centerMessage = centerMessage;
this._centerMessage = centerMessage;
}
/**
@ -37,15 +44,15 @@ export class Changes {
addChange(elementId: string, key: string, value: string) {
if (!this.login.userDetails.data.loggedIn) {
this.centerMessage.setData(
this._centerMessage.setData(
"<p>Bedankt voor je antwoord!</p>" +
"<p>Gelieve <span class='activate-osm-authentication'>in te loggen op OpenStreetMap</span> om dit op te slaan.</p>"+
"<p>Gelieve <span class='activate-osm-authentication'>in te loggen op OpenStreetMap</span> om dit op te slaan.</p>" +
"<p>Nog geen account? <a href=\'https://www.openstreetmap.org/user/new\' target=\'_blank\'>Registreer hier</a></p>"
);
const self = this;
this.login.userDetails.addCallback(() => {
if (self.login.userDetails.data.loggedIn) {
self.centerMessage.setData("");
self._centerMessage.setData("");
}
});
return;
@ -67,7 +74,7 @@ export class Changes {
eventSource.ping();
// We get the id from the event source, as that ID might be rewritten
this._pendingChanges.push({elementId: eventSource.data.id, key: key, value: value});
this.pendingChangesES.ping();
this.pendingChangesES.setData(this._pendingChanges.length);
}
@ -114,9 +121,18 @@ export class Changes {
public uploadAll(optionalContinuation: (() => void)) {
const self = this;
this.isSaving.setData(true);
const optionalContinuationWrapped = function () {
self.isSaving.setData(false);
if (optionalContinuation) {
optionalContinuation();
}
}
const pending: { elementId: string; key: string; value: string }[] = this._pendingChanges;
this._pendingChanges = [];
this.pendingChangesES.setData(this._pendingChanges);
this.pendingChangesES.setData(this._pendingChanges.length);
const newElements = this.newElements;
this.newElements = [];
@ -203,7 +219,7 @@ export class Changes {
console.log("Beginning upload...");
// At last, we build the changeset and upload
self.login.UploadChangeset("Updaten van metadata met Mapcomplete",
self.login.UploadChangeset(self._changesetComment,
function (csId) {
let modifications = "";
@ -243,7 +259,7 @@ export class Changes {
return changes;
},
handleMapping,
optionalContinuation);
optionalContinuationWrapped);
});
}

View file

@ -25,8 +25,6 @@ export class FilteredLayer {
private readonly _removeContainedElements;
private readonly _removeTouchingElements;
private readonly _popupContent: ((source: UIEventSource<any>) => UIElement);
private readonly _style: (properties) => any;
private readonly _storage: ElementStorage;
@ -41,6 +39,7 @@ export class FilteredLayer {
* The leaflet layer object which should be removed on rerendering
*/
private _geolayer;
private _selectedElement: UIEventSource<any>;
constructor(
name: string,
@ -49,8 +48,9 @@ export class FilteredLayer {
filters: TagsFilter,
removeContainedElements: boolean,
removeTouchingElements: boolean,
popupContent: ((source: UIEventSource<any>) => UIElement),
style: ((properties) => any)) {
style: ((properties) => any),
selectedElement: UIEventSource<any>) {
this._selectedElement = selectedElement;
if (style === undefined) {
style = function () {
@ -60,7 +60,6 @@ export class FilteredLayer {
this.name = name;
this._map = map;
this.filters = filters;
this._popupContent = popupContent;
this._style = style;
this._storage = storage;
this._removeContainedElements = removeContainedElements;
@ -167,8 +166,6 @@ export class FilteredLayer {
},
pointToLayer: function (feature, latLng) {
const eventSource = self._storage.addOrGetElement(feature);
const style = self._style(feature.properties);
let marker;
if (style.icon === undefined) {
@ -180,19 +177,6 @@ export class FilteredLayer {
});
}
eventSource.addCallback(function () {
self.updateStyle();
});
const content = self._popupContent(eventSource)
marker.bindPopup(
"<div class='popupcontent'>" +
content.Render() +
"</div>"
).on("popupopen", function () {
content.Activate();
content.Update();
});
return marker;
},
@ -203,14 +187,9 @@ export class FilteredLayer {
eventSource.addCallback(function () {
self.updateStyle();
});
const content = self._popupContent(eventSource)
layer.bindPopup(
"<div class='popupcontent'>" +
content.Render() +
"</div>"
).on("popupopen", function () {
content.Activate();
content.Update();
layer.on("click", function(){
console.log("Selected ",feature)
self._selectedElement.setData(feature.properties);
});
}
});

View file

@ -34,7 +34,9 @@ export class ImageSearcher extends UIEventSource<string[]> {
self.AddImage(wd.image);
Wikimedia.GetCategoryFiles(wd.commonsWiki, (images: ImagesInCategory) => {
for (const image of images.images) {
self.AddImage(image.filename);
if (image.startsWith("File:")) {
self.AddImage(image);
}
}
})
})
@ -48,7 +50,10 @@ export class ImageSearcher extends UIEventSource<string[]> {
if (commons.startsWith("Category:")) {
Wikimedia.GetCategoryFiles(commons, (images: ImagesInCategory) => {
for (const image of images.images) {
self.AddImage(image.filename);
// @ts-ignore
if (image.startsWith("File:")) {
self.AddImage(image);
}
}
})
} else { // @ts-ignore
@ -125,7 +130,7 @@ export class ImageSearcher extends UIEventSource<string[]> {
const urlSource = new UIEventSource<string>(url);
// @ts-ignore
if (url.startsWith("File:")) {
return new WikimediaImage(urlSource);
return new WikimediaImage(urlSource.data);
} else {
return new SimpleImageElement(urlSource);
}

View file

@ -57,9 +57,13 @@ export class LayerUpdater {
}
private handleFail(reason: any) {
this.runningQuery.setData(false);
console.log("QUERY FAILED", reason);
// TODO
console.log("Retrying in 1s")
this.previousBounds = undefined;
const self = this;
window.setTimeout(
function(){self.update()}, 1000
)
}
@ -89,7 +93,7 @@ export class LayerUpdater {
}
buildBboxFor(): string {
private buildBboxFor(): string {
const b = this._map.map.getBounds();
const latDiff = Math.abs(b.getNorth() - b.getSouth());
const lonDiff = Math.abs(b.getEast() - b.getWest());
@ -101,8 +105,7 @@ export class LayerUpdater {
this.previousBounds = {north: n, east: e, south: s, west: w};
const bbox = "[bbox:" + s + "," + w + "," + n + "," + e + "]";
return bbox;
return "[bbox:" + s + "," + w + "," + n + "," + e + "]";
}
private IsInBounds(): boolean {

View file

@ -9,6 +9,9 @@ export class UserDetails {
public csCount = 0;
public img: string;
public unreadMessages = 0;
public totalMessages = 0;
public osmConnection : OsmConnection;
public dryRun : boolean;
}
@ -26,10 +29,9 @@ export class OsmConnection {
constructor(dryRun: boolean) {
this.userDetails = new UIEventSource<UserDetails>(new UserDetails());
this.userDetails.data.osmConnection = this;
this.userDetails.data.dryRun = dryRun;
this._dryRun = dryRun;
if(dryRun){
alert("Opgelet: testmode actief. Wijzigingen worden NIET opgeslaan")
}
if (this.auth.authenticated()) {
this.AttemptLogin(); // Also updates the user badge
@ -61,23 +63,43 @@ export class OsmConnection {
self.userDetails.ping();
}
if(details == null){
if (details == null) {
return;
}
// details is an XML DOM of user details
let userInfo = details.getElementsByTagName("user")[0];
// let moreDetails = new DOMParser().parseFromString(userInfo.innerHTML, "text/xml");
let data = self.userDetails.data;
data.loggedIn = true;
console.log(userInfo);
data.name = userInfo.getAttribute('display_name');
data.csCount = userInfo.getElementsByTagName("changesets")[0].getAttribute("count");
data.img = userInfo.getElementsByTagName("img")[0].getAttribute("href");
data.unreadMessages = userInfo.getElementsByTagName("received")[0].getAttribute("unread");
const messages = userInfo.getElementsByTagName("messages")[0].getElementsByTagName("received")[0];
data.unreadMessages = parseInt(messages.getAttribute("unread"));
data.totalMessages = parseInt(messages.getAttribute("count"));
self.userDetails.ping();
});
}
/**
* All elements with class 'activate-osm-authentication' are loaded and get an 'onclick' to authenticate
* @param osmConnection
*/
registerActivateOsmAUthenticationClass() {
const authElements = document.getElementsByClassName("activate-osm-authentication");
for (let i = 0; i < authElements.length; i++) {
let element = authElements.item(i);
// @ts-ignore
element.onclick = function () {
this.AttemptLogin();
}
}
}
private static parseUploadChangesetResponse(response: XMLDocument) {
const nodes = response.getElementsByTagName("node");
const mapping = {};
@ -102,6 +124,7 @@ export class OsmConnection {
console.log("NOT UPLOADING as dryrun is true");
var changesetXML = generateChangeXML("123456");
console.log(changesetXML);
continuation();
return;
}

View file

@ -9,29 +9,26 @@ import {UserDetails} from "./OsmConnection";
export class OsmImageUploadHandler {
private _tags: UIEventSource<any>;
private _changeHandler: Changes;
private _userdetails: UserDetails;
private _userdetails: UIEventSource<UserDetails>;
constructor(tags: UIEventSource<any>,
userdetails: UserDetails,
userdetails: UIEventSource<UserDetails>,
changeHandler: Changes
) {
if (tags === undefined || userdetails === undefined || changeHandler === undefined) {
throw "Something is undefined"
}
console.log(tags, changeHandler, userdetails)
this._tags = tags;
this._changeHandler = changeHandler;
this._userdetails = userdetails;
}
private generateOptions(license: string) {
console.log(this)
console.log(this._tags, this._changeHandler, this._userdetails)
const tags = this._tags.data;
const title = tags.name ?? "Unknown area";
const description = [
"author:" + this._userdetails.name,
"author:" + this._userdetails.data.name,
"license:" + license,
"wikidata:" + tags.wikidata,
"osmid:" + tags.id,
@ -60,7 +57,9 @@ export class OsmImageUploadHandler {
getUI(): ImageUploadFlow {
const self = this;
return new ImageUploadFlow(function (license) {
return new ImageUploadFlow(
this._userdetails,
function (license) {
return self.generateOptions(license)
}
);

View file

@ -26,8 +26,7 @@ export class Overpass {
const query =
'[out:json][timeout:25]' + bbox + ';(' + filter + ');out body;>;out skel qt;';
console.log(query);
const url = "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query);
return url;
return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query);
}

View file

@ -81,7 +81,7 @@ export class QuestionUI extends UIElement {
const embeddedScriptSave = 'questionAnswered(' + this._qid + ', "' + this._tags.data.id + '", false )';
const embeddedScriptSkip = 'questionAnswered(' + this._qid + ', "' + this._tags.data.id + '", true )';
const saveButton = "<input class='save-button' type='button' onclick='" + embeddedScriptSave + "' value='Opslaan' />";
const skip = "<input class='skip-button' type='button' onclick='" + embeddedScriptSkip + "' value='Ik ben het niet zeker (vraag overslaan)' />";
const skip = "<input class='skip-button' type='button' onclick='" + embeddedScriptSkip + "' value='Ik ben niet zeker (vraag overslaan)' />";
return q.question + "<br/> " + answers + saveButton + skip;
}

View file

@ -68,8 +68,7 @@ export class Wikimedia {
for (const member of members) {
imageOverview.images.push(
{filename: member.title, fileid: member.pageid});
imageOverview.images.push(member.title);
}
if (response.continue === undefined || alreadyLoaded > 30) {
handleCategory(imageOverview);
@ -96,7 +95,10 @@ export class Wikimedia {
wd.commonsWiki = commons?.title;
// P18 is the claim 'depicted in this image'
wd.image = "File:" + entity.claims.P18?.[0]?.mainsnak?.datavalue?.value;
const image = entity.claims.P18?.[0]?.mainsnak?.datavalue?.value;
if (image) {
wd.image = "File:" + image;
}
handleWikidata(wd);
});
}
@ -114,7 +116,7 @@ export class Wikidata {
export class ImagesInCategory {
// Filenames of relevant images
images: { filename: string, fileid: number }[] = [];
images: string[] = [];
}
export class LicenseInfo {