Skip to content

Commit 4ab6bf5

Browse files
authored
Merge pull request #413 from solid/deleteButtonWithCheck
Delete button with check
2 parents be77785 + 45614d9 commit 4ab6bf5

File tree

5 files changed

+153
-78
lines changed

5 files changed

+153
-78
lines changed

package-lock.json

Lines changed: 29 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/style.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export const style = { // styleModule
2222
'background-color: #fff; padding: 0.7em; border: .01em solid white; border-radius:0.2em; font-size: 100%; margin: 0.3em;', // 'background-color: #eef;
2323
commentStyle: 'padding: 0.7em; border: none; font-size: 100%; white-space: pre-wrap;',
2424
iconStyle: 'width: 3em; height: 3em; margin: 0.1em; border-radius: 1em;',
25+
smallButtonStyle: 'margin: 0.2em; width: 1em; height:1em',
2526
classIconStyle: 'width: 3em; height: 3em; margin: 0.1em; border-radius: 0.2em; border: 0.1em solid green; padding: 0.2em; background-color: #efe;', // combine with buttonStyle
27+
confirmPopupStyle: 'padding: 0.7em; border-radius: 0.2em; border: 0.1em solid orange; background-color: white; box-shadow: 0.5em 0.9em #888;',
2628
tabBorderRadius: '0.2em',
2729
messageBodyStyle:
2830
'white-space: pre-wrap; width: 99%; font-size:100%; border: 0.07em solid #eee; border-radius:0.2em; padding: .3em 0.5em; margin: 0.1em;',

src/widgets/buttons.ts

Lines changed: 88 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -435,81 +435,96 @@ export function faviconOrDefault (dom: HTMLDocument, x: NamedNode) {
435435
}
436436
}
437437

438+
/* Two-option dialog pop-up
439+
*/
440+
441+
function renderDeleteConfirmPopup (dom, refererenceElement, prompt, deleteFunction) {
442+
function removePopup () {
443+
refererenceElement.parentElement.removeChild(refererenceElement)
444+
}
445+
function removePopupAndDoDeletion () {
446+
removePopup()
447+
deleteFunction()
448+
}
449+
const popup = dom.createElement('div')
450+
popup.style = style.confirmPopupStyle
451+
popup.style.position = 'absolute'
452+
popup.style.top = '-1em' // try leaving original button clear
453+
454+
popup.style.display = 'grid'
455+
popup.style.gridTemplateColumns = 'auto auto'
456+
const affirm = dom.createElement('div')
457+
affirm.style.gridColumn = '1/2'
458+
affirm.style.gridRow = '1' // @@ sigh; TS. could pass number in fact
459+
const cancel = dom.createElement('div')
460+
cancel.style.gridColumn = '1/2'
461+
cancel.style.gridRow = '2'
462+
463+
const xButton = cancelButton(dom, removePopup)
464+
popup.appendChild(xButton)
465+
xButton.style.gridColumn = '1'
466+
xButton.style.gridRow = '2'
467+
468+
const cancelPrompt = popup.appendChild(dom.createElement('button'))
469+
cancelPrompt.style = style.buttonStyle
470+
cancelPrompt.style.gridRow = '2'
471+
cancelPrompt.style.gridColumn = '2'
472+
cancelPrompt.textContent = 'Cancel' // @@ I18n
473+
474+
const affirmIcon = button(dom, icons.iconBase + 'noun_925021.svg', 'Delete it') // trashcan
475+
popup.appendChild(affirmIcon)
476+
affirmIcon.style.gridRow = '1'
477+
affirmIcon.style.gridColumn = '1'
478+
479+
const sureButtonElt = popup.appendChild(dom.createElement('button'))
480+
sureButtonElt.style = style.buttonStyle
481+
sureButtonElt.style.gridRow = '1'
482+
sureButtonElt.style.gridColumn = '2'
483+
sureButtonElt.textContent = prompt
484+
popup.appendChild(sureButtonElt)
485+
486+
affirmIcon.addEventListener('click', removePopupAndDoDeletion)
487+
sureButtonElt.addEventListener('click', removePopupAndDoDeletion)
488+
489+
// xButton.addEventListener('click', removePopup)
490+
cancelPrompt.addEventListener('click', removePopup)
491+
492+
return popup
493+
}
438494
/**
439495
* Delete button with a check you really mean it
440496
* @@ Supress check if command key held down?
441497
*/
442498
export function deleteButtonWithCheck (
443499
dom: HTMLDocument,
444-
_container: HTMLElement, // Used to interfere with style of this
500+
container: HTMLElement,
445501
noun: string,
446502
deleteFunction: () => any
447503
) {
448-
function setStyle () {
449-
buttonDiv.style.border = ''
450-
buttonDiv.style.margin = '0.3em'
451-
buttonDiv.style.borderRadius = '0'
452-
buttonDiv.style.padding = '0.3em white'
453-
buttonDiv.style.boxShadow = ''
504+
function createPopup () {
505+
const refererenceElement = dom.createElement('div')
506+
container.insertBefore(refererenceElement, deleteButton)
507+
refererenceElement.style.position = 'relative' // Needed as reference for popup
508+
refererenceElement.appendChild(renderDeleteConfirmPopup(dom, refererenceElement, prompt, deleteFunction))
454509
}
455-
const buttonDiv = dom.createElement('div')
456510
const minusIconURI = iconBase + 'noun_2188_red.svg' // white minus in red #cc0000 circle
457-
const img = dom.createElement('img')
458-
let sureButtonElt, cancelButtonElt
459-
img.setAttribute('src', minusIconURI) // plus sign
460-
img.setAttribute('style', 'margin: 0.2em; width: 1em; height:1em')
461-
img.title = 'Remove this ' + noun
462-
const deleteButtonElt = img
463-
464-
buttonDiv.appendChild(deleteButtonElt)
465-
buttonDiv.setAttribute('class', 'hoverControl') // See tabbedtab.css (sigh global CSS)
466-
setStyle()
467-
468-
deleteButtonElt.setAttribute('class', 'hoverControlHide')
469-
470-
deleteButtonElt.addEventListener(
471-
'click',
472-
function (_event) {
473-
buttonDiv.style.borderRadius = '0.5em'
474-
buttonDiv.style.border = 'orange 0.05em;'
475-
buttonDiv.style.boxShadow = '0.2em 0.5em #888888'
476-
buttonDiv.style.padding = '0.3em'
477-
478-
buttonDiv.removeChild(deleteButtonElt) // Ask -- are you sure?
479-
cancelButtonElt = dom.createElement('button')
480-
// cancelButton.textContent = 'cancel'
481-
cancelButtonElt.setAttribute('style', style.buttonStyle)
482-
const img = cancelButtonElt.appendChild(dom.createElement('img'))
483-
img.setAttribute('src', cancelIconURI)
484-
img.setAttribute('style', style.buttonStyle)
485-
486-
buttonDiv.appendChild(cancelButtonElt).addEventListener(
487-
'click',
488-
function (_event) {
489-
buttonDiv.removeChild(sureButtonElt)
490-
buttonDiv.removeChild(cancelButtonElt)
491-
setStyle()
492-
buttonDiv.appendChild(deleteButtonElt)
493-
},
494-
false
495-
)
496-
sureButtonElt = dom.createElement('button')
497-
sureButtonElt.textContent = 'Delete ' + noun
498-
sureButtonElt.setAttribute('style', style.buttonStyle)
499-
buttonDiv.appendChild(sureButtonElt).addEventListener(
500-
'click',
501-
function (_event) {
502-
buttonDiv.removeChild(sureButtonElt)
503-
buttonDiv.removeChild(cancelButtonElt)
504-
setStyle()
505-
deleteFunction()
506-
},
507-
false
508-
)
509-
},
510-
false
511-
)
512-
return buttonDiv // deleteButtonElt
511+
const deleteButton = dom.createElement('img')
512+
deleteButton.setAttribute('src', minusIconURI)
513+
514+
deleteButton.setAttribute('style', style.smallButtonStyle) // @@tsc - would set deleteButton.style
515+
deleteButton.style.float = 'right' // Historically this has alwaus floated right
516+
517+
const prompt = 'Remove this ' + noun
518+
deleteButton.title = prompt
519+
// @@ In an ideal world, make use of hover an accessibility option
520+
deleteButton.classList.add('hoverControlHide')
521+
522+
deleteButton.addEventListener('click', createPopup)
523+
524+
container.classList.add('hoverControl')
525+
container.appendChild(deleteButton)
526+
deleteButton.setAttribute('data-testid', 'deleteButtonWithCheck')
527+
return deleteButton // or button div? caller may change size of image
513528
}
514529

515530
/**
@@ -564,7 +579,7 @@ function getButtonStyle (options: ButtonWidgetOptions = {}) {
564579
* @returns <dDomElement> - the button
565580
*/
566581
export function button (dom: HTMLDocument, iconURI: string | undefined, text: string,
567-
handler?: (event: any) => void,
582+
handler?: (_event: any) => void,
568583
options: ButtonWidgetOptions = { buttonColor: 'Primary', needsBorder: false }) {
569584
const button = dom.createElement('button')
570585
button.setAttribute('type', 'button')
@@ -597,7 +612,7 @@ export function button (dom: HTMLDocument, iconURI: string | undefined, text: st
597612
*
598613
* @returns <dDomElement> - the button
599614
*/
600-
export function cancelButton (dom: HTMLDocument, handler: (event: any) => void) {
615+
export function cancelButton (dom: HTMLDocument, handler: (_event?: any) => void) {
601616
return button(dom, cancelIconURI, 'Cancel', handler)
602617
}
603618

@@ -608,7 +623,7 @@ export function cancelButton (dom: HTMLDocument, handler: (event: any) => void)
608623
*
609624
* @returns <dDomElement> - the button
610625
*/
611-
export function continueButton (dom: HTMLDocument, handler: (event: any) => void) {
626+
export function continueButton (dom: HTMLDocument, handler: (_event: any) => void) {
612627
return button(dom, checkIconURI, 'Continue', handler)
613628
}
614629

@@ -1090,8 +1105,8 @@ export function selectorPanel (
10901105
inverse: boolean,
10911106
possible: NamedNode[],
10921107
options: { connectIcon?: string },
1093-
callbackFunction: (x: NamedNode, e: Event, selected: boolean) => void,
1094-
linkCallback: (x: NamedNode, e: Event, inverse: boolean, setStyleFunction: () => void) => void
1108+
callbackFunction: (_x: NamedNode, _e: Event, _selected: boolean) => void,
1109+
linkCallback: (_x: NamedNode, _e: Event, _inverse: boolean, _setStyleFunction: () => void) => void
10951110
) {
10961111
return selectorPanelRefresh(
10971112
dom.createElement('div'),
@@ -1116,8 +1131,8 @@ export function selectorPanelRefresh (
11161131
inverse: boolean,
11171132
possible: NamedNode[],
11181133
options: { connectIcon?: string },
1119-
callbackFunction: (x: NamedNode, e: Event, selected: boolean) => void,
1120-
linkCallback: (x: NamedNode, e: Event, inverse: boolean, setStyleFunction: () => void) => void
1134+
callbackFunction: (_x: NamedNode, _e: Event, _selected: boolean) => void,
1135+
linkCallback: (_x: NamedNode, _e: Event, _inverse: boolean, _setStyleFunction: () => void) => void
11211136
) {
11221137
const style0 =
11231138
'border: 0.1em solid #ddd; border-bottom: none; width: 95%; height: 2em; padding: 0.5em;'
@@ -1220,7 +1235,7 @@ function twoLineDefault (dom: HTMLDocument, x: NamedNode): HTMLElement {
12201235
* Find a function that can create a widget for a given class
12211236
* @param c The RDF class for which we want a widget generator function
12221237
*/
1223-
function twoLineWidgetForClass (c: NamedNode): (dom: HTMLDocument, x: NamedNode) => HTMLElement {
1238+
function twoLineWidgetForClass (c: NamedNode): (_dom: HTMLDocument, _x: NamedNode) => HTMLElement {
12241239
let widget = index.twoLine[c.uri]
12251240
const kb = store
12261241
if (widget) return widget
@@ -1352,7 +1367,7 @@ export function isImage (file?: NamedNode, kind?: string): boolean {
13521367
// See https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications
13531368
export function fileUploadButtonDiv (
13541369
dom: HTMLDocument,
1355-
droppedFileHandler: (files: FileList) => void
1370+
droppedFileHandler: (_files: FileList) => void
13561371
) {
13571372
const div = dom.createElement('div')
13581373
const input = div.appendChild(dom.createElement('input'))

test/unit/utils/label.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { lit, sym } from 'rdflib'
22
import { label } from '../../../src/utils'
33
import { silenceDebugMessages } from '../../helpers/setup'
44
import { store } from '../../../src/logic'
5-
import * as ns from '../../../src/ns'
5+
66
silenceDebugMessages()
77
jest.mock('solid-auth-client', () => ({
88
currentSession: () => Promise.resolve(),

test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,17 @@ exports[`autocompleteField clicking on row of greenn table then accecpt button s
9595
title="Edit"
9696
/>
9797
</button>
98-
<div />
98+
<div
99+
class="hoverControl"
100+
>
101+
<img
102+
class="hoverControlHide"
103+
data-testid="delete-button"
104+
src="https://solid.github.io/solid-ui/src/icons/noun_2188_red.svg"
105+
style="margin: 0.2em; width: 1em; height: 1em; float: right;"
106+
title="Remove this Q6881511"
107+
/>
108+
</div>
99109
</div>
100110
</div>
101111
</div>
@@ -176,7 +186,17 @@ exports[`autocompleteField creates a autocomplete field 1`] = `
176186
title="Edit"
177187
/>
178188
</button>
179-
<div />
189+
<div
190+
class="hoverControl"
191+
>
192+
<img
193+
class="hoverControlHide"
194+
data-testid="delete-button"
195+
src="https://solid.github.io/solid-ui/src/icons/noun_2188_red.svg"
196+
style="margin: 0.2em; width: 1em; height: 1em; float: right;"
197+
title="Remove this Q6881511"
198+
/>
199+
</div>
180200
</div>
181201
</div>
182202
</div>
@@ -292,7 +312,17 @@ exports[`autocompleteField typing more search term till unique selects the whole
292312
title="Edit"
293313
/>
294314
</button>
295-
<div />
315+
<div
316+
class="hoverControl"
317+
>
318+
<img
319+
class="hoverControlHide"
320+
data-testid="delete-button"
321+
src="https://solid.github.io/solid-ui/src/icons/noun_2188_red.svg"
322+
style="margin: 0.2em; width: 1em; height: 1em; float: right;"
323+
title="Remove this Q6881511"
324+
/>
325+
</div>
296326
</div>
297327
</div>
298328
</div>

0 commit comments

Comments
 (0)