Add image delete button

This commit is contained in:
Pieter Vander Vennet 2020-07-08 11:23:36 +02:00
parent f548ddea84
commit 0fe6b67976
13 changed files with 303 additions and 54 deletions

View file

@ -9,6 +9,18 @@ import {NameInline} from "../Questions/NameInline";
export class Park extends LayerDefinition {
private accessByDefault = new TagRenderingOptions({
question: "Is dit park publiek toegankelijk?",
mappings: [
{k: new Tag("access","yes"), txt: "Publiek toegankelijk"},
{k: new Tag("access",""), txt: "Publiek toegankelijk"},
{k: new Tag("access","no"), txt: "Niet-publiek toegankelijk park"},
{k: new Tag("access","guided"), txt: "Enkel toegankelijk met een gids of op een activiteit"}
]
})
constructor() {
super();
this.name = "park";
@ -22,7 +34,10 @@ export class Park extends LayerDefinition {
this.minzoom = 13;
this.style = this.generateStyleFunction();
this.title = new NameInline("park");
this.elementsToShow = [new NameQuestion()];
this.elementsToShow = [new NameQuestion(),
this.accessByDefault
];
}

View file

@ -6,16 +6,16 @@ export class BikePumpsLayout extends Layout {
constructor() {
super(
"pomp",
"Grb import fix tool",
"Cyclofix",
[new BikePumps()],
15,
51.2083,
3.2279,
"<h3>GRB Fix tool</h3>\n" +
"<h3>Open CycloFix</h3>\n" +
"\n" +
"Expert use only"
"Something something bikes"
,
"", "");

View file

@ -65,7 +65,6 @@ export class TagRenderingOptions {
mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[]
}) {
this.options = options;
}
@ -150,6 +149,7 @@ export class TagRendering extends UIElement {
// Prepare the choices for the Radio buttons
let i = 0;
const choices: UIElement[] = [];
const alreadyUsedTexts: string[] = [];
for (const choice of options.mappings ?? []) {
if (choice.k === null) {
@ -159,16 +159,21 @@ export class TagRendering extends UIElement {
let choiceSubbed = choice;
if (choice.substitute) {
choiceSubbed = {
k : choice.k.substituteValues(
k: choice.k.substituteValues(
options.tagsPreprocessor(this._source.data)),
txt : this.ApplyTemplate(choice.txt),
txt: this.ApplyTemplate(choice.txt),
substitute: false,
priority: choice.priority
}
}
choices.push(new FixedUiElement(choiceSubbed.txt));
const txt = choiceSubbed.txt;
if (alreadyUsedTexts.indexOf(txt) < 0) {
choices.push(new FixedUiElement(txt));
alreadyUsedTexts.push(txt);
}
this._mapping.push(choiceSubbed);
i++;
}

View file

@ -105,9 +105,8 @@ export class ImageSearcher extends UIEventSource<string[]> {
if(key === undefined){
return;
}
console.log("Deleting image...");
// this._changes.addChange(this._tags.data.id, key, "");
console.log("Deleting image...", key, " --> ", url);
this._changes.addChange(this._tags.data.id, key, "");
}
@ -133,16 +132,11 @@ export class ImageSearcher extends UIEventSource<string[]> {
}
}
const image0 = this._tags.data["image:0"];
if (image0 !== undefined) {
this.AddImage(image0);
}
let imageIndex = 1;
let imagei = this._tags.data["image:" + imageIndex];
while (imagei !== undefined) {
this.AddImage(imagei);
imageIndex++;
imagei = this._tags.data["image:" + imageIndex];
for (const key in this._tags.data) {
// @ts-ignore
if(key.startsWith("image:")){
this.AddImage(this._tags.data[key]);
}
}
const wdItem = this._tags.data.wikidata;

View file

@ -78,7 +78,8 @@ Camera Icon, Dave Gandy, CC-BY-SA 3.0
https://commons.wikimedia.org/wiki/File:OOjs_UI_indicator_search-rtl.svg
Search Icon, MIT
https://commons.wikimedia.org/wiki/File:Trash_font_awesome.svg
Trash icon by Dave Gandy, CC-BY-SA
https://commons.wikimedia.org/wiki/File:Home-icon.svg
Home icon by Timothy Miller, CC-BY-SA 3.0

69
UI/ConfirmDialog.ts Normal file
View file

@ -0,0 +1,69 @@
import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource";
import {FixedUiElement} from "./Base/FixedUiElement";
import {VariableUiElement} from "./Base/VariableUIElement";
export class ConfirmDialog extends UIElement {
private _showOptions: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private _question: UIElement;
private _optionA: UIElement;
private _optionB: UIElement;
constructor(
show: UIEventSource<boolean>,
question: string,
optionA: string, optionB: string,
executeA: () => void,
executeB: () => void,
classA: string = "",
classB: string = "") {
super(show);
this.ListenTo(this._showOptions);
const self = this;
show.addCallback(() => {
self._showOptions.setData(false);
})
this._question = new FixedUiElement("<span class='ui-question'>" + question + "</span>")
.onClick(() => {
self._showOptions.setData(!self._showOptions.data);
});
this._optionA = new VariableUiElement(
this._showOptions.map(
(show) => show ? "<div class='" + classA + "'>" + optionA + "</div>" : ""))
.onClick(() => {
self._showOptions.setData(false);
executeA();
}
);
this._optionB = new VariableUiElement(
this._showOptions.map((show) =>
show ? "<div class='" + classB + "'>" + optionB + "</div>" : "") )
.onClick(() => {
self._showOptions.setData(false);
executeB();
});
}
protected InnerRender(): string {
if (!this._source.data) {
return "";
}
return this._question.Render() +
this._optionA.Render() +
this._optionB.Render();
}
Update() {
super.Update();
this._question.Update();
this._optionA.Update();
this._optionB.Update();
}
}

View file

@ -6,6 +6,7 @@ import {FixedUiElement} from "../Base/FixedUiElement";
import {VerticalCombine} from "../Base/VerticalCombine";
import {Changes} from "../../Logic/Changes";
import {VariableUiElement} from "../Base/VariableUIElement";
import {ConfirmDialog} from "../ConfirmDialog";
export class ImageCarousel extends UIElement {
/**
@ -25,7 +26,6 @@ export class ImageCarousel extends UIElement {
private readonly _uiElements: UIEventSource<UIElement[]>;
private readonly _deleteButtonText = new UIEventSource<string>("");
private readonly _deleteButton: UIElement;
constructor(tags: UIEventSource<any>, changes: Changes) {
@ -48,24 +48,33 @@ export class ImageCarousel extends UIElement {
new FixedUiElement("")).HideOnEmpty(true);
this._deleteButtonText = this.slideshow._currentSlide.map((i) => {
if(self.searcher.IsDeletable(self.searcher.data[i])){
return "DELETE";
}else{
return "";
}
});
const showDeleteButton = this.slideshow._currentSlide.map((i) => {
return self.searcher.IsDeletable(self.searcher.data[i]);
}, [this.searcher]);
this.slideshow._currentSlide.addCallback(() => {
showDeleteButton.ping(); // This pings the showDeleteButton, which indicates that it has to hide it's subbuttons
})
this._deleteButton = new VariableUiElement(this._deleteButtonText)
.HideOnEmpty(true)
.onClick(() => {
self.searcher.Delete(self.searcher.data[self.slideshow._currentSlide.data]);
});
const deleteCurrent = () => self.searcher.Delete(self.searcher.data[self.slideshow._currentSlide.data]);
this._deleteButton = new ConfirmDialog(showDeleteButton,
"<img src='assets/delete.svg' alt='Afbeelding verwijderen' class='delete-image'>",
"<span>Afbeelding verwijderen</span>",
"<span>Terug</span>",
deleteCurrent,
() => {},
'delete-image-confirm',
'delete-image-cancel');
}
InnerRender(): string {
return this.slideshow.Render() ;
// + this._deleteButton.Render();
return "<span class='image-carousel-container'>" +
"<div class='image-delete-container'>" +
this._deleteButton.Render() +
"</div>" +
this.slideshow.Render() +
"</span>";
}
InnerUpdate(htmlElement: HTMLElement) {

View file

@ -58,6 +58,17 @@ export abstract class UIElement {
}
element.style.pointerEvents = "all";
element.style.cursor = "pointer";
/*
const childs = element.children;
for (let i = 0; i < childs.length; i++) {
const ch = childs[i];
console.log(ch);
ch.style.cursor = "pointer";
ch.onclick = () => {
self._onClick();
}
ch.style.pointerEvents = "all";
}*/
}
this.InnerUpdate(element);

View file

@ -27,15 +27,23 @@ export class UIEventSource<T>{
}
}
public map<J>(f: ((T) => J)): UIEventSource<J> {
public map<J>(f: ((T) => J),
extraSources : UIEventSource<any>[] = []): UIEventSource<J> {
const self = this;
this.addCallback(function () {
const update = function () {
newSource.setData(f(self.data));
newSource.ping();
});
}
this.addCallback(update);
for (const extraSource of extraSources) {
extraSource.addCallback(update);
}
const newSource = new UIEventSource<J>(
f(this.data)
);
return newSource;

55
assets/delete.svg Normal file
View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 -256 1792 1792"
id="svg3741"
version="1.1"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
width="100%"
height="100%"
sodipodi:docname="delete.svg">
<metadata
id="metadata3751">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3749" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1001"
id="namedview3747"
showgrid="false"
inkscape:zoom="0.18624688"
inkscape:cx="795.91988"
inkscape:cy="822.60792"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3741" />
<path
style="fill:#ff0000;fill-opacity:1"
inkscape:connector-curvature="0"
id="path3745"
d="m 709.42373,455.0508 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 v -576 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 256,0 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 v -576 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 255.99997,0 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 v -576 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 128,724 v -948 H 453.42373 v 948 q 0,22 7,40.5 7,18.5 14.5,27 7.5,8.5 10.5,8.5 h 831.99997 q 3,0 10.5,-8.5 7.5,-8.5 14.5,-27 7,-18.5 7,-40.5 z m -671.99997,-1076 h 447.99997 l -48,-117 q -7,-9 -17,-11 H 743.42373 q -10,2 -17,11 z m 927.99997,32 v 64 q 0,14 -9,23 -9,9 -23,9 h -96 v 948 q 0,83 -47,143.5 -47,60.5 -113,60.5 H 485.42373 q -66,0 -113,-58.5 -47,-58.5 -47,-141.5 v -952 h -96 q -14,0 -23,-9 -9,-9 -9,-23 v -64 q 0,-14 9,-23 9,-9 23,-9 h 309 l 70,-167 q 15,-37 54,-63 39,-26 79,-26 h 319.99997 q 40,0 79,26 39,26 54,63 l 70,167 h 309 q 14,0 23,9 9,9 9,23 z" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -682,6 +682,84 @@ body {
display: inline-block
}
/******* THe remove image buttons ****/
.image-carousel-container {
position: relative;
}
.image-delete-container {
position: absolute;
left: 6em;
top: 1.5em;
display: inline-block;
z-index: 7000;
}
.delete-image {
width: 1.5em;
height: 1.5em;
padding: 0.5em;
border-radius: 3em;
background-color: black;
}
.delete-image-confirm {
position: absolute;
display: inline-block;
left: 0;
top: 2.5em;
padding: 0.5em;
padding-left: 0.75em;
z-index: -1;
height: 3em;
width: 14em;
border-radius: 1em;
border-top-left-radius: 0;
border-top-right-radius: 0;
background-color: #ff8c8c;
color: white;
height: 1.5em; /* same as .delete-image */
z-index: 7000;
}
.delete-image-confirm span {
font-size: larger;
font-weight: bold;
}
.delete-image-cancel {
display: inline-block;
position: absolute;
left: 0em;
padding: 0.5em;
padding-left: 0.75em;
border-radius: 1em;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
height: 1.5em; /* same as .delete-image */
width: 14em; /* Same as delete-image-confirm */
background-color: black;
color: white;
z-index: 7000;
}
.delete-image-cancel span {
font-size: larger;
font-weight: bold;
}
/**** The save button *****/

View file

@ -5,7 +5,9 @@
<link href="index.css" rel="stylesheet"/>
</head>
<body>
<span class="image-delete-container">
<div id="maindiv">'maindiv' not attached</div>
</span>
<div id="extradiv">'extradiv' not attached</div>
<script src="./test.ts"></script>
</body>

28
test.ts
View file

@ -4,18 +4,20 @@ import {OsmConnection} from "./Logic/OsmConnection";
import {ElementStorage} from "./Logic/ElementStorage";
import {WikipediaLink} from "./Customizations/Questions/WikipediaLink";
import {OsmLink} from "./Customizations/Questions/OsmLink";
const tags = {name: "Test",
wikipedia: "nl:Pieter",
id: "node/-1"};
const tagsES = new UIEventSource(tags);
const login = new OsmConnection(true);
const allElements = new ElementStorage();
allElements.addElementById(tags.id, tagsES);
const changes = new Changes("Test", login, allElements)
import {ConfirmDialog} from "./UI/ConfirmDialog";
new OsmLink(tagsES, changes).AttachTo("maindiv");
new ConfirmDialog(new UIEventSource<boolean>(true),
"<img src='assets/delete.svg' alt='Afbeelding verwijderen' class='delete-image'>",
"Deze afbeelding verwijderen",
"Terug",
() => {
console.log("Verwijderen");
},
() => {
console.log("terug")
},
'delete-image-confirm',
'delete-image-cancel')
.AttachTo("maindiv")