From 9ad4a7eeba2472cff192860f7f3064fa6ba0097d Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 11 Nov 2025 11:50:23 +0000 Subject: [PATCH] Adds Clear Clipboard button & logic (#20757) * Adds new dictionary/localization item for the clipboard dialog clear all prompt * Removes the wrapping uui-box and moved inside the component itself * Adds Clear Clipboard button and logic * Adds uui-box from outer components consuimg this into this component * Adds a header to uui-box * Adds a conditional uui-button when we have items in clipboard * Adds confirm dialog/prompt to ask if user wants to clear all items * Adds in general_clipboard item to use in the UUI-box header * Removes extra space & moves the requestItems outside the for loop * Be a better citizen Make sure the promise for the modal is caught and we return out early if user explictiy cancels modal or presses ESC * Cleanup my noisy comments for a re-review --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> --- .../src/assets/lang/en.ts | 2 + .../block-catalogue-modal.element.ts | 8 +-- .../clipboard-entry-picker-modal.element.ts | 10 ++- .../picker/clipboard-entry-picker.element.ts | 66 +++++++++++++++---- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 6331f88335..a04d3fe3cc 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -1017,6 +1017,7 @@ export default { if (new Date(date).getTime() < new Date(now).getTime()) return `${duration} ago`; return `in ${duration}`; }, + clipboard: 'Clipboard', }, colors: { black: 'Black', @@ -2508,6 +2509,7 @@ export default { labelForCopyToClipboard: 'Copy to clipboard', confirmDeleteHeadline: 'Delete from clipboard', confirmDeleteDescription: 'Are you sure you want to delete {0} from the clipboard?', + confirmClearDescription: 'Are you sure you want to clear the clipboard?', copySuccessHeadline: 'Copied to clipboard', }, propertyActions: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts index 08d3760117..f6ceed0051 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts @@ -194,11 +194,9 @@ export class UmbBlockCatalogueModalElement extends UmbModalBaseElement< #renderClipboard() { return html` - - - + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker-modal/clipboard-entry-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker-modal/clipboard-entry-picker-modal.element.ts index b3e273cf94..cfd5de0ea0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker-modal/clipboard-entry-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker-modal/clipboard-entry-picker-modal.element.ts @@ -27,12 +27,10 @@ export class UmbClipboardEntryPickerModalElement extends UmbModalBaseElement< override render() { return html` - - - +
diff --git a/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker/clipboard-entry-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker/clipboard-entry-picker.element.ts index fda340058b..46e9c393d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker/clipboard-entry-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/clipboard/clipboard-entry/picker/clipboard-entry-picker.element.ts @@ -1,6 +1,7 @@ import { UmbClipboardCollectionRepository } from '../../collection/index.js'; import type { UmbClipboardEntryDetailModel } from '../types.js'; -import { css, customElement, html, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; +import UmbClipboardEntryDetailRepository from '../detail/clipboard-entry-detail.repository.js'; +import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { @@ -10,6 +11,7 @@ import { import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; +import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; // TODO: make this into an extension point (Picker) with two kinds of pickers: tree-item-picker and collection-item-picker; @customElement('umb-clipboard-entry-picker') @@ -28,6 +30,8 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { #entityContext = new UmbEntityContext(this); #actionEventContext?: typeof UMB_ACTION_EVENT_CONTEXT.TYPE; + #clipboardDetailRepository = new UmbClipboardEntryDetailRepository(this); + constructor() { super(); this.#entityContext.setEntityType('clipboard-entry'); @@ -117,17 +121,57 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { } }; + async #clearClipboard() { + try { + await umbConfirmModal(this, { + headline: '#clipboard_labelForClearClipboard', + content: '#clipboard_confirmClearDescription', + color: 'danger', + confirmLabel: '#general_clear', + cancelLabel: '#general_cancel', + }); + } catch { + return; + } + + for (const item of this._items) { + const { error } = await this.#clipboardDetailRepository.delete(item.unique); + if (error) { + console.error(`Unable to delete clipboard item with unique ${item.unique}`, error); + } + } + + this.#requestItems(); + } + override render() { - return when( - this._items.length > 0, - () => - repeat( - this._items, - (item) => item.unique, - (item) => this.#renderItem(item), - ), - () => html`

There are no items in the clipboard.

`, - ); + return html` + + + ${when( + this._items.length > 0, + () => html` + + + Clear Clipboard + + `, + () => nothing, + )} + + + ${when( + this._items.length > 0, + () => + repeat( + this._items, + (item) => item.unique, + (item) => this.#renderItem(item), + ), + () => html`

There are no items in the clipboard.

`, + )} +
+ `; } #renderItem(item: UmbClipboardEntryDetailModel) {