From 6c27acd9cc46aeba47a9c9d9300510fcc0eef0dc Mon Sep 17 00:00:00 2001 From: Tim Berners-Lee Date: Fri, 11 Jun 2021 19:30:41 +0100 Subject: [PATCH 1/3] container.appendChild(butttonDiv) --- src/widgets/buttons.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widgets/buttons.ts b/src/widgets/buttons.ts index a05a1f0e2..2623a1938 100644 --- a/src/widgets/buttons.ts +++ b/src/widgets/buttons.ts @@ -441,7 +441,7 @@ export function faviconOrDefault (dom: HTMLDocument, x: NamedNode) { */ export function deleteButtonWithCheck ( dom: HTMLDocument, - _container: HTMLElement, // Used to interfere with style of this + container?: HTMLElement, // Used to interfere with style of this noun: string, deleteFunction: () => any ) { @@ -509,6 +509,9 @@ export function deleteButtonWithCheck ( }, false ) + if (container) { // Old API + container.appendChild(buttonDiv) + } return buttonDiv // deleteButtonElt } From bae40da8df07b942c6a5e4884cb12c92666986da Mon Sep 17 00:00:00 2001 From: Tim Berners-Lee Date: Fri, 11 Jun 2021 19:44:34 +0100 Subject: [PATCH 2/3] delete buttons were missing from autocomplete tests --- package-lock.json | 30 ++++++++++++- src/widgets/buttons.ts | 2 +- .../__snapshots__/autocomplete.test.ts.snap | 45 +++++++++++++++++-- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index aaf166918..36d54f3eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5805,6 +5805,16 @@ "dev": true, "optional": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -9302,6 +9312,13 @@ } } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "filesize": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", @@ -14264,6 +14281,13 @@ "readable-stream": "^3.6.0" } }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -19663,7 +19687,11 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", diff --git a/src/widgets/buttons.ts b/src/widgets/buttons.ts index 2623a1938..cb41bd184 100644 --- a/src/widgets/buttons.ts +++ b/src/widgets/buttons.ts @@ -441,7 +441,7 @@ export function faviconOrDefault (dom: HTMLDocument, x: NamedNode) { */ export function deleteButtonWithCheck ( dom: HTMLDocument, - container?: HTMLElement, // Used to interfere with style of this + container: HTMLElement | null, // Used to interfere with style of this noun: string, deleteFunction: () => any ) { diff --git a/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap b/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap index 9632c05a8..360a3f67e 100644 --- a/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap +++ b/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap @@ -95,7 +95,20 @@ exports[`autocompleteField clicking on row of greenn table then accecpt button s title="Edit" /> -
+
+
+ +
+
@@ -176,7 +189,20 @@ exports[`autocompleteField creates a autocomplete field 1`] = ` title="Edit" /> -
+
+
+ +
+
@@ -292,7 +318,20 @@ exports[`autocompleteField typing more search term till unique selects the whole title="Edit" /> -
+
+
+ +
+
From 45614d959190f13d08d33529bc1abecabbbb5dfb Mon Sep 17 00:00:00 2001 From: Tim Berners-Lee Date: Sat, 12 Jun 2021 15:39:00 +0100 Subject: [PATCH 3/3] Revamped pop-up for deleteButtonWithCheck, returns a plain img elelemnt as it used to --- src/style.js | 2 + src/widgets/buttons.ts | 164 ++++++++++-------- test/unit/utils/label.test.ts | 2 +- .../__snapshots__/autocomplete.test.ts.snap | 63 +++---- 4 files changed, 118 insertions(+), 113 deletions(-) diff --git a/src/style.js b/src/style.js index 6b9d32147..e0a1b4475 100644 --- a/src/style.js +++ b/src/style.js @@ -22,7 +22,9 @@ export const style = { // styleModule 'background-color: #fff; padding: 0.7em; border: .01em solid white; border-radius:0.2em; font-size: 100%; margin: 0.3em;', // 'background-color: #eef; commentStyle: 'padding: 0.7em; border: none; font-size: 100%; white-space: pre-wrap;', iconStyle: 'width: 3em; height: 3em; margin: 0.1em; border-radius: 1em;', + smallButtonStyle: 'margin: 0.2em; width: 1em; height:1em', 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 + confirmPopupStyle: 'padding: 0.7em; border-radius: 0.2em; border: 0.1em solid orange; background-color: white; box-shadow: 0.5em 0.9em #888;', tabBorderRadius: '0.2em', messageBodyStyle: '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;', diff --git a/src/widgets/buttons.ts b/src/widgets/buttons.ts index cb41bd184..bcf0d5e27 100644 --- a/src/widgets/buttons.ts +++ b/src/widgets/buttons.ts @@ -435,84 +435,96 @@ export function faviconOrDefault (dom: HTMLDocument, x: NamedNode) { } } +/* Two-option dialog pop-up +*/ + +function renderDeleteConfirmPopup (dom, refererenceElement, prompt, deleteFunction) { + function removePopup () { + refererenceElement.parentElement.removeChild(refererenceElement) + } + function removePopupAndDoDeletion () { + removePopup() + deleteFunction() + } + const popup = dom.createElement('div') + popup.style = style.confirmPopupStyle + popup.style.position = 'absolute' + popup.style.top = '-1em' // try leaving original button clear + + popup.style.display = 'grid' + popup.style.gridTemplateColumns = 'auto auto' + const affirm = dom.createElement('div') + affirm.style.gridColumn = '1/2' + affirm.style.gridRow = '1' // @@ sigh; TS. could pass number in fact + const cancel = dom.createElement('div') + cancel.style.gridColumn = '1/2' + cancel.style.gridRow = '2' + + const xButton = cancelButton(dom, removePopup) + popup.appendChild(xButton) + xButton.style.gridColumn = '1' + xButton.style.gridRow = '2' + + const cancelPrompt = popup.appendChild(dom.createElement('button')) + cancelPrompt.style = style.buttonStyle + cancelPrompt.style.gridRow = '2' + cancelPrompt.style.gridColumn = '2' + cancelPrompt.textContent = 'Cancel' // @@ I18n + + const affirmIcon = button(dom, icons.iconBase + 'noun_925021.svg', 'Delete it') // trashcan + popup.appendChild(affirmIcon) + affirmIcon.style.gridRow = '1' + affirmIcon.style.gridColumn = '1' + + const sureButtonElt = popup.appendChild(dom.createElement('button')) + sureButtonElt.style = style.buttonStyle + sureButtonElt.style.gridRow = '1' + sureButtonElt.style.gridColumn = '2' + sureButtonElt.textContent = prompt + popup.appendChild(sureButtonElt) + + affirmIcon.addEventListener('click', removePopupAndDoDeletion) + sureButtonElt.addEventListener('click', removePopupAndDoDeletion) + + // xButton.addEventListener('click', removePopup) + cancelPrompt.addEventListener('click', removePopup) + + return popup +} /** * Delete button with a check you really mean it * @@ Supress check if command key held down? */ export function deleteButtonWithCheck ( dom: HTMLDocument, - container: HTMLElement | null, // Used to interfere with style of this + container: HTMLElement, noun: string, deleteFunction: () => any ) { - function setStyle () { - buttonDiv.style.border = '' - buttonDiv.style.margin = '0.3em' - buttonDiv.style.borderRadius = '0' - buttonDiv.style.padding = '0.3em white' - buttonDiv.style.boxShadow = '' + function createPopup () { + const refererenceElement = dom.createElement('div') + container.insertBefore(refererenceElement, deleteButton) + refererenceElement.style.position = 'relative' // Needed as reference for popup + refererenceElement.appendChild(renderDeleteConfirmPopup(dom, refererenceElement, prompt, deleteFunction)) } - const buttonDiv = dom.createElement('div') const minusIconURI = iconBase + 'noun_2188_red.svg' // white minus in red #cc0000 circle - const img = dom.createElement('img') - let sureButtonElt, cancelButtonElt - img.setAttribute('src', minusIconURI) // plus sign - img.setAttribute('style', 'margin: 0.2em; width: 1em; height:1em') - img.title = 'Remove this ' + noun - const deleteButtonElt = img - - buttonDiv.appendChild(deleteButtonElt) - buttonDiv.setAttribute('class', 'hoverControl') // See tabbedtab.css (sigh global CSS) - setStyle() - - deleteButtonElt.setAttribute('class', 'hoverControlHide') - - deleteButtonElt.addEventListener( - 'click', - function (_event) { - buttonDiv.style.borderRadius = '0.5em' - buttonDiv.style.border = 'orange 0.05em;' - buttonDiv.style.boxShadow = '0.2em 0.5em #888888' - buttonDiv.style.padding = '0.3em' - - buttonDiv.removeChild(deleteButtonElt) // Ask -- are you sure? - cancelButtonElt = dom.createElement('button') - // cancelButton.textContent = 'cancel' - cancelButtonElt.setAttribute('style', style.buttonStyle) - const img = cancelButtonElt.appendChild(dom.createElement('img')) - img.setAttribute('src', cancelIconURI) - img.setAttribute('style', style.buttonStyle) - - buttonDiv.appendChild(cancelButtonElt).addEventListener( - 'click', - function (_event) { - buttonDiv.removeChild(sureButtonElt) - buttonDiv.removeChild(cancelButtonElt) - setStyle() - buttonDiv.appendChild(deleteButtonElt) - }, - false - ) - sureButtonElt = dom.createElement('button') - sureButtonElt.textContent = 'Delete ' + noun - sureButtonElt.setAttribute('style', style.buttonStyle) - buttonDiv.appendChild(sureButtonElt).addEventListener( - 'click', - function (_event) { - buttonDiv.removeChild(sureButtonElt) - buttonDiv.removeChild(cancelButtonElt) - setStyle() - deleteFunction() - }, - false - ) - }, - false - ) - if (container) { // Old API - container.appendChild(buttonDiv) - } - return buttonDiv // deleteButtonElt + const deleteButton = dom.createElement('img') + deleteButton.setAttribute('src', minusIconURI) + + deleteButton.setAttribute('style', style.smallButtonStyle) // @@tsc - would set deleteButton.style + deleteButton.style.float = 'right' // Historically this has alwaus floated right + + const prompt = 'Remove this ' + noun + deleteButton.title = prompt + // @@ In an ideal world, make use of hover an accessibility option + deleteButton.classList.add('hoverControlHide') + + deleteButton.addEventListener('click', createPopup) + + container.classList.add('hoverControl') + container.appendChild(deleteButton) + deleteButton.setAttribute('data-testid', 'deleteButtonWithCheck') + return deleteButton // or button div? caller may change size of image } /** @@ -567,7 +579,7 @@ function getButtonStyle (options: ButtonWidgetOptions = {}) { * @returns - the button */ export function button (dom: HTMLDocument, iconURI: string | undefined, text: string, - handler?: (event: any) => void, + handler?: (_event: any) => void, options: ButtonWidgetOptions = { buttonColor: 'Primary', needsBorder: false }) { const button = dom.createElement('button') button.setAttribute('type', 'button') @@ -600,7 +612,7 @@ export function button (dom: HTMLDocument, iconURI: string | undefined, text: st * * @returns - the button */ -export function cancelButton (dom: HTMLDocument, handler: (event: any) => void) { +export function cancelButton (dom: HTMLDocument, handler: (_event?: any) => void) { return button(dom, cancelIconURI, 'Cancel', handler) } @@ -611,7 +623,7 @@ export function cancelButton (dom: HTMLDocument, handler: (event: any) => void) * * @returns - the button */ -export function continueButton (dom: HTMLDocument, handler: (event: any) => void) { +export function continueButton (dom: HTMLDocument, handler: (_event: any) => void) { return button(dom, checkIconURI, 'Continue', handler) } @@ -1093,8 +1105,8 @@ export function selectorPanel ( inverse: boolean, possible: NamedNode[], options: { connectIcon?: string }, - callbackFunction: (x: NamedNode, e: Event, selected: boolean) => void, - linkCallback: (x: NamedNode, e: Event, inverse: boolean, setStyleFunction: () => void) => void + callbackFunction: (_x: NamedNode, _e: Event, _selected: boolean) => void, + linkCallback: (_x: NamedNode, _e: Event, _inverse: boolean, _setStyleFunction: () => void) => void ) { return selectorPanelRefresh( dom.createElement('div'), @@ -1119,8 +1131,8 @@ export function selectorPanelRefresh ( inverse: boolean, possible: NamedNode[], options: { connectIcon?: string }, - callbackFunction: (x: NamedNode, e: Event, selected: boolean) => void, - linkCallback: (x: NamedNode, e: Event, inverse: boolean, setStyleFunction: () => void) => void + callbackFunction: (_x: NamedNode, _e: Event, _selected: boolean) => void, + linkCallback: (_x: NamedNode, _e: Event, _inverse: boolean, _setStyleFunction: () => void) => void ) { const style0 = 'border: 0.1em solid #ddd; border-bottom: none; width: 95%; height: 2em; padding: 0.5em;' @@ -1223,7 +1235,7 @@ function twoLineDefault (dom: HTMLDocument, x: NamedNode): HTMLElement { * Find a function that can create a widget for a given class * @param c The RDF class for which we want a widget generator function */ -function twoLineWidgetForClass (c: NamedNode): (dom: HTMLDocument, x: NamedNode) => HTMLElement { +function twoLineWidgetForClass (c: NamedNode): (_dom: HTMLDocument, _x: NamedNode) => HTMLElement { let widget = index.twoLine[c.uri] const kb = store if (widget) return widget @@ -1355,7 +1367,7 @@ export function isImage (file?: NamedNode, kind?: string): boolean { // See https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications export function fileUploadButtonDiv ( dom: HTMLDocument, - droppedFileHandler: (files: FileList) => void + droppedFileHandler: (_files: FileList) => void ) { const div = dom.createElement('div') const input = div.appendChild(dom.createElement('input')) diff --git a/test/unit/utils/label.test.ts b/test/unit/utils/label.test.ts index 995907341..7652c44b5 100644 --- a/test/unit/utils/label.test.ts +++ b/test/unit/utils/label.test.ts @@ -2,7 +2,7 @@ import { lit, sym } from 'rdflib' import { label } from '../../../src/utils' import { silenceDebugMessages } from '../../helpers/setup' import { store } from '../../../src/logic' -import * as ns from '../../../src/ns' + silenceDebugMessages() jest.mock('solid-auth-client', () => ({ currentSession: () => Promise.resolve(), diff --git a/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap b/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap index 360a3f67e..43cc50280 100644 --- a/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap +++ b/test/unit/widgets/forms/autocomplete/__snapshots__/autocomplete.test.ts.snap @@ -95,19 +95,16 @@ exports[`autocompleteField clicking on row of greenn table then accecpt button s title="Edit" /> -
-
+ - -
+ src="https://solid.github.io/solid-ui/src/icons/noun_2188_red.svg" + style="margin: 0.2em; width: 1em; height: 1em; float: right;" + title="Remove this Q6881511" + />
@@ -189,19 +186,16 @@ exports[`autocompleteField creates a autocomplete field 1`] = ` title="Edit" /> -
-
+ - -
+ src="https://solid.github.io/solid-ui/src/icons/noun_2188_red.svg" + style="margin: 0.2em; width: 1em; height: 1em; float: right;" + title="Remove this Q6881511" + />
@@ -318,19 +312,16 @@ exports[`autocompleteField typing more search term till unique selects the whole title="Edit" /> -
-
+ - -
+ src="https://solid.github.io/solid-ui/src/icons/noun_2188_red.svg" + style="margin: 0.2em; width: 1em; height: 1em; float: right;" + title="Remove this Q6881511" + />