Add image delete button
This commit is contained in:
parent
f548ddea84
commit
0fe6b67976
13 changed files with 303 additions and 54 deletions
|
@ -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
|
||||
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
,
|
||||
"", "");
|
||||
|
|
|
@ -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) {
|
||||
|
@ -167,8 +167,13 @@ export class TagRendering extends UIElement {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
for (const key in this._tags.data) {
|
||||
// @ts-ignore
|
||||
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;
|
||||
|
|
|
@ -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
69
UI/ConfirmDialog.ts
Normal 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
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
55
assets/delete.svg
Normal 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 |
78
index.css
78
index.css
|
@ -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 *****/
|
||||
|
||||
|
|
|
@ -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
28
test.ts
|
@ -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")
|
Loading…
Reference in a new issue