Skip to content

Commit

Permalink
Add MapComplete
Browse files Browse the repository at this point in the history
  • Loading branch information
pietervdvn committed Jun 23, 2020
0 parents commit 6187122
Show file tree
Hide file tree
Showing 61 changed files with 107,059 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/*
node_modules
90 changes: 90 additions & 0 deletions Helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {OsmConnection} from "./Logic/OsmConnection";
import {Changes} from "./Logic/Changes";
import {UIEventSource} from "./UI/UIEventSource";
import {PendingChanges} from "./UI/PendingChanges";

export class Helpers {


static SetupAutoSave(changes: Changes, secondsTillChangesAreSaved : UIEventSource<number>) {

// This little function triggers the actual upload:
// Either when more then three answers are selected, or when no new answer has been added for the last 20s
// @ts-ignore
window.decreaseTime = function () {
var time = secondsTillChangesAreSaved.data;
if (time <= 0) {
if (changes._pendingChanges.length > 0) {
changes.uploadAll(undefined);
}
} else {
secondsTillChangesAreSaved.setData(time - 1000);

}
window.setTimeout('decreaseTime()', 1000);
};


changes.pendingChangesES.addCallback(function () {

var c = changes._pendingChanges.length;
if (c > 10) {
secondsTillChangesAreSaved.setData(0);
changes.uploadAll(undefined);
return;
}

if (c > 0) {
secondsTillChangesAreSaved.setData(5000);
}

});

// @ts-ignore
window.decreaseTime(); // The timer keeps running...
}

/**
* All elements with class 'activate-osm-authentication' are loaded and get an 'onclick' to authenticate
* @param osmConnection
*/
static registerActivateOsmAUthenticationClass(osmConnection: OsmConnection) {

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 () {
osmConnection.AttemptLogin();
}
}
}



/*
* Registers an action that:
* -> Upload everything to OSM
* -> Asks the user not to close. The 'not to close' dialog should profide enough time to upload
* -> WHen uploading is done, the window is closed anyway
*/
static LastEffortSave(changes : Changes){

window.addEventListener("beforeunload", function (e) {
// Quickly save everyting!
if (changes._pendingChanges.length == 0) {
return "";
}

changes.uploadAll(function () {
window.close()
});
var confirmationMessage = "Nog even geduld - je laatset wijzigingen worden opgeslaan!";

(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Webkit, Safari, Chrome
});

}

}
77 changes: 77 additions & 0 deletions LayerDefinition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {Basemap} from "./Logic/Basemap";
import {ElementStorage} from "./Logic/ElementStorage";
import {Changes} from "./Logic/Changes";
import {Question, QuestionDefinition} from "./Logic/Question";
import {TagMapping, TagMappingOptions} from "./UI/TagMapping";
import {UIEventSource} from "./UI/UIEventSource";
import {QuestionPicker} from "./UI/QuestionPicker";
import {VerticalCombine} from "./UI/VerticalCombine";
import {UIElement} from "./UI/UIElement";
import {Tag, TagsFilter} from "./Logic/TagsFilter";
import {FilteredLayer} from "./Logic/FilteredLayer";
import {ImageCarousel} from "./UI/Image/ImageCarousel";
import {FixedUiElement} from "./UI/FixedUiElement";


export class LayerDefinition {


name: string;
newElementTags: Tag[]
icon: string;
minzoom: number;
overpassFilter: TagsFilter;

elementsToShow: (TagMappingOptions | QuestionDefinition | UIElement)[];
questions: QuestionDefinition[]; // Questions are shown below elementsToShow in a questionPicker

style: (tags: any) => any;

removeContainedElements : boolean = false;
removeTouchingElements: boolean = false;


asLayer(basemap: Basemap, allElements: ElementStorage, changes: Changes):
FilteredLayer {
const self = this;

function generateInfoBox(tagsES: UIEventSource<any>) {

var infoboxes: UIElement[] = [];
for (const uiElement of self.elementsToShow) {
if (uiElement instanceof QuestionDefinition) {
const questionDef = uiElement as QuestionDefinition;
const question = new Question(changes, questionDef);
infoboxes.push(question.CreateHtml(tagsES));
} else if (uiElement instanceof TagMappingOptions) {
const tagMappingOpt = uiElement as TagMappingOptions;
infoboxes.push(new TagMapping(tagMappingOpt, tagsES))
} else {
const ui = uiElement as UIElement;
infoboxes.push(ui);
}

}
infoboxes.push(new ImageCarousel(tagsES));

infoboxes.push(new FixedUiElement("<div style='width:750px'></div>"));


const qbox = new QuestionPicker(changes.asQuestions(self.questions), tagsES);
infoboxes.push(qbox);

return new VerticalCombine(infoboxes);

}

return new FilteredLayer(
this.name,
basemap, allElements, changes,
this.overpassFilter,
this.removeContainedElements, this.removeTouchingElements,
generateInfoBox,
this.style);

}

}
90 changes: 90 additions & 0 deletions Layers/Artwork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {LayerDefinition} from "../LayerDefinition";
import {FixedUiElement} from "../UI/FixedUiElement";
import L from "leaflet";
import {CommonTagMappings} from "./CommonTagMappings";
import {TagMappingOptions} from "../UI/TagMapping";
import {QuestionDefinition} from "../Logic/Question";
import {Tag} from "../Logic/TagsFilter";

export class Artwork extends LayerDefinition {

constructor() {
super();

this.name = "artwork";
this.newElementTags = [new Tag("tourism", "artwork")];
this.icon = "./assets/statue.svg";
this.overpassFilter = new Tag("tourism", "artwork");
this.minzoom = 13;
this.questions = [
QuestionDefinition.radioAndTextQuestion("What kind of artwork is this?", 10, "artwork_type",
[
{text: "A statue", value: "statue"},
{text: "A bust (thus a statue, but only of the head and shoulders)", value: "bust"},
{text: "A sculpture", value: "sculpture"},
{text: "A mural painting", value: "mural"},
{text: "A painting", value: "painting"},
{text: "A graffiti", value: "graffiti"},
{text: "A relief", value: "relief"},
{text: "An installation", value: "installation"}]),
QuestionDefinition.textQuestion("Whom or what is depicted in this statue?", "subject", 20).addUnrequiredTag("subject:wikidata","*"),
QuestionDefinition.textQuestion("Is there an inscription on this artwork?", "inscription", 16),
QuestionDefinition.textQuestion("What is the name of this artwork? If there is no explicit name, skip the question", "name", 15),


];

this.style = function (tags) {
return {
icon: new L.icon({
iconUrl: "assets/statue.svg",
iconSize: [40, 40],
text: "hi"
})
};

}

this.elementsToShow = [


new TagMappingOptions(
{
key: "name",
template: "<h2>Artwork '{name}'</h2>",
missing: "Artwork"
}),
new TagMappingOptions({
key: "artwork_type",
template: "This artwork is a {artwork_type}"
}),
new TagMappingOptions({
key: "artist_name",
template: "This artwork was made by {artist_name}"
}),
new TagMappingOptions({
key: "subject",
template: "This artwork depicts {subject}"
}),

new TagMappingOptions({
key: "subject:wikidata",
template: "<a href='https://www.wikidata.org/wiki/{subject:wikidata}' target='_blank'>See more data about the subject</a>"
}),

new TagMappingOptions({
key: "website",
template: "<a href='{website}' target='_blank'>Website of the statue</a>"
}),




new TagMappingOptions({key: "image", template: "<img class='popupImg' alt='image' src='{image}' />"}),
CommonTagMappings.osmLink

];
}


}
69 changes: 69 additions & 0 deletions Layers/Bookcases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {LayerDefinition} from "../LayerDefinition";
import {Quests} from "../Quests";
import {FixedUiElement} from "../UI/FixedUiElement";
import {TagMapping, TagMappingOptions} from "../UI/TagMapping";
import L from "leaflet";
import {QuestionDefinition} from "../Logic/Question";
import {CommonTagMappings} from "./CommonTagMappings";
import {Tag} from "../Logic/TagsFilter";

export class Bookcases extends LayerDefinition {

constructor() {
super();

this.name = "boekenkast";
this.newElementTags = [new Tag( "amenity", "public_bookcase")];
this.icon = "./assets/bookcase.svg";
this.overpassFilter = new Tag("amenity","public_bookcase");
this.minzoom = 13;


this.questions = [
QuestionDefinition.noNameOrNameQuestion("Wat is de naam van dit boekenruilkastje?", "Dit boekenruilkastje heeft niet echt een naam", 20),
QuestionDefinition.textQuestion("Hoeveel boeken kunnen er in?", "capacity", 15),
QuestionDefinition.textQuestion("Heeft dit boekenkastje een peter, meter of voogd?", "operator", 10),
// QuestionDefinition.textQuestion("Wie kunnen we (per email) contacteren voor dit boekenruilkastje?", "email", 5),


]
;

this.style = function (tags) {
return {
icon: new L.icon({
iconUrl: "assets/bookcase.svg",
iconSize: [40, 40]
})
};
}

this.elementsToShow = [


new TagMappingOptions({
key: "name",
template: "<h2>{name}</h2>",
missing: "<h2>Boekenruilkastje</h2>"
}
),
new TagMappingOptions({key: "capacity", template: "Plaats voor {capacity} boeken"}),
new TagMappingOptions({key: "operator", template: "Onder de hoede van {operator}"}),
new TagMappingOptions({
key: "website",
mapping: "Meer informatie beschikbaar op <a href='{website}'>{website}</a>"
}),
new TagMappingOptions({key: "start_date", template: "Geplaatst op {start_date}"}),
new TagMappingOptions({key: "brand", template: "Deel van het netwerk {brand}"}),
new TagMappingOptions({key: "ref", template: "Referentienummer {ref}"}),

new TagMappingOptions({key: "description", template: "Extra beschrijving: <br /> <p>{description}</p>"}),

CommonTagMappings.osmLink

]
;
}


}
Loading

0 comments on commit 6187122

Please sign in to comment.