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 { 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() { constructor() {
super(); super();
this.name = "park"; this.name = "park";
@ -22,7 +34,10 @@ export class Park extends LayerDefinition {
this.minzoom = 13; this.minzoom = 13;
this.style = this.generateStyleFunction(); this.style = this.generateStyleFunction();
this.title = new NameInline("park"); 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() { constructor() {
super( super(
"pomp", "pomp",
"Grb import fix tool", "Cyclofix",
[new BikePumps()], [new BikePumps()],
15, 15,
51.2083, 51.2083,
3.2279, 3.2279,
"<h3>GRB Fix tool</h3>\n" + "<h3>Open CycloFix</h3>\n" +
"\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 }[] mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[]
}) { }) {
this.options = options; this.options = options;
} }
@ -150,6 +149,7 @@ export class TagRendering extends UIElement {
// Prepare the choices for the Radio buttons // Prepare the choices for the Radio buttons
let i = 0; let i = 0;
const choices: UIElement[] = []; const choices: UIElement[] = [];
const alreadyUsedTexts: string[] = [];
for (const choice of options.mappings ?? []) { for (const choice of options.mappings ?? []) {
if (choice.k === null) { if (choice.k === null) {
@ -159,16 +159,21 @@ export class TagRendering extends UIElement {
let choiceSubbed = choice; let choiceSubbed = choice;
if (choice.substitute) { if (choice.substitute) {
choiceSubbed = { choiceSubbed = {
k : choice.k.substituteValues( k: choice.k.substituteValues(
options.tagsPreprocessor(this._source.data)), options.tagsPreprocessor(this._source.data)),
txt : this.ApplyTemplate(choice.txt), txt: this.ApplyTemplate(choice.txt),
substitute: false, substitute: false,
priority: choice.priority priority: choice.priority
} }
} }
const txt = choiceSubbed.txt;
if (alreadyUsedTexts.indexOf(txt) < 0) {
choices.push(new FixedUiElement(txt));
alreadyUsedTexts.push(txt);
}
choices.push(new FixedUiElement(choiceSubbed.txt));
this._mapping.push(choiceSubbed); this._mapping.push(choiceSubbed);
i++; i++;
} }

View file

@ -105,9 +105,8 @@ export class ImageSearcher extends UIEventSource<string[]> {
if(key === undefined){ if(key === undefined){
return; return;
} }
console.log("Deleting image..."); console.log("Deleting image...", key, " --> ", url);
this._changes.addChange(this._tags.data.id, key, "");
// 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"]; for (const key in this._tags.data) {
if (image0 !== undefined) { // @ts-ignore
this.AddImage(image0); if(key.startsWith("image:")){
} this.AddImage(this._tags.data[key]);
let imageIndex = 1; }
let imagei = this._tags.data["image:" + imageIndex];
while (imagei !== undefined) {
this.AddImage(imagei);
imageIndex++;
imagei = this._tags.data["image:" + imageIndex];
} }
const wdItem = this._tags.data.wikidata; 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 https://commons.wikimedia.org/wiki/File:OOjs_UI_indicator_search-rtl.svg
Search Icon, MIT 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 https://commons.wikimedia.org/wiki/File:Home-icon.svg
Home icon by Timothy Miller, CC-BY-SA 3.0 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 {VerticalCombine} from "../Base/VerticalCombine";
import {Changes} from "../../Logic/Changes"; import {Changes} from "../../Logic/Changes";
import {VariableUiElement} from "../Base/VariableUIElement"; import {VariableUiElement} from "../Base/VariableUIElement";
import {ConfirmDialog} from "../ConfirmDialog";
export class ImageCarousel extends UIElement { export class ImageCarousel extends UIElement {
/** /**
@ -25,7 +26,6 @@ export class ImageCarousel extends UIElement {
private readonly _uiElements: UIEventSource<UIElement[]>; private readonly _uiElements: UIEventSource<UIElement[]>;
private readonly _deleteButtonText = new UIEventSource<string>("");
private readonly _deleteButton: UIElement; private readonly _deleteButton: UIElement;
constructor(tags: UIEventSource<any>, changes: Changes) { constructor(tags: UIEventSource<any>, changes: Changes) {
@ -48,24 +48,33 @@ export class ImageCarousel extends UIElement {
new FixedUiElement("")).HideOnEmpty(true); new FixedUiElement("")).HideOnEmpty(true);
this._deleteButtonText = this.slideshow._currentSlide.map((i) => { const showDeleteButton = this.slideshow._currentSlide.map((i) => {
if(self.searcher.IsDeletable(self.searcher.data[i])){ return self.searcher.IsDeletable(self.searcher.data[i]);
return "DELETE"; }, [this.searcher]);
}else{ this.slideshow._currentSlide.addCallback(() => {
return ""; showDeleteButton.ping(); // This pings the showDeleteButton, which indicates that it has to hide it's subbuttons
} })
});
this._deleteButton = new VariableUiElement(this._deleteButtonText)
.HideOnEmpty(true) const deleteCurrent = () => self.searcher.Delete(self.searcher.data[self.slideshow._currentSlide.data]);
.onClick(() => {
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 { InnerRender(): string {
return this.slideshow.Render() ; return "<span class='image-carousel-container'>" +
// + this._deleteButton.Render(); "<div class='image-delete-container'>" +
this._deleteButton.Render() +
"</div>" +
this.slideshow.Render() +
"</span>";
} }
InnerUpdate(htmlElement: HTMLElement) { InnerUpdate(htmlElement: HTMLElement) {

View file

@ -58,6 +58,17 @@ export abstract class UIElement {
} }
element.style.pointerEvents = "all"; element.style.pointerEvents = "all";
element.style.cursor = "pointer"; 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); this.InnerUpdate(element);

View file

@ -27,16 +27,24 @@ 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; const self = this;
this.addCallback(function () {
const update = function () {
newSource.setData(f(self.data)); newSource.setData(f(self.data));
newSource.ping(); newSource.ping();
}); }
this.addCallback(update);
for (const extraSource of extraSources) {
extraSource.addCallback(update);
}
const newSource = new UIEventSource<J>( const newSource = new UIEventSource<J>(
f(this.data) f(this.data)
); );
return newSource; 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 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 *****/ /**** The save button *****/

View file

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

28
test.ts
View file

@ -4,18 +4,20 @@ import {OsmConnection} from "./Logic/OsmConnection";
import {ElementStorage} from "./Logic/ElementStorage"; import {ElementStorage} from "./Logic/ElementStorage";
import {WikipediaLink} from "./Customizations/Questions/WikipediaLink"; import {WikipediaLink} from "./Customizations/Questions/WikipediaLink";
import {OsmLink} from "./Customizations/Questions/OsmLink"; import {OsmLink} from "./Customizations/Questions/OsmLink";
import {ConfirmDialog} from "./UI/ConfirmDialog";
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)
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")