From ceb8086e79bfed9ab8d466a347eac1b0e91b380d Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Nov 2025 14:02:53 +0000 Subject: [PATCH 1/7] Adds new dictionary/localization item for the clipboard dialog clear all prompt --- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + 1 file changed, 1 insertion(+) 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 6331f883356f..aa8fbb9f69cc 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2508,6 +2508,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: { From 122a5a5a2cd94615d7bb4f7433738943d70a6cc7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Nov 2025 14:03:34 +0000 Subject: [PATCH 2/7] Removes the wrapping uui-box and moved inside the component itself --- .../block-catalogue/block-catalogue-modal.element.ts | 8 +++----- .../clipboard-entry-picker-modal.element.ts | 10 ++++------ 2 files changed, 7 insertions(+), 11 deletions(-) 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 08d3760117dd..f6ceed0051c0 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 b3e273cf94e5..cfd5de0ea05c 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` - - - +
From e7481e8e105cfd7f481e4159d6ebaa4060cd53a7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Nov 2025 14:19:35 +0000 Subject: [PATCH 3/7] 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 --- .../picker/clipboard-entry-picker.element.ts | 75 ++++++++++++++++--- 1 file changed, 64 insertions(+), 11 deletions(-) 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 fda340058b6c..77765b2d8a08 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,66 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { } }; + async #clearClipboard() { + // Prompt the user to confirm clearing the clipboard + await umbConfirmModal(this, { + headline: '#clipboard_labelForClearClipboard', + content: '#clipboard_confirmClearDescription', + color: 'danger', + confirmLabel: '#general_clear', + cancelLabel: '#general_cancel', + }); + + for (const item of this._items) { + // Clipboard items are a collection of items and the UmbClipboardContext + // does not expose a method to use the delete from the underlying clipboardDetailRepository + const { error } = await this.#clipboardDetailRepository.delete(item.unique); + if (error) { + console.error(`Unable to delete clipboard item with unique ${item.unique}`, error); + } + + // It did not update/refresh the UI of items/collection after calling delete + // Should I dispatch an event to notify this same component to refresh? + // Or explictly call request items again which just works + this.#requestItems(); + + // const event = new UmbRequestReloadStructureForEntityEvent({ + // unique: item.unique, + // entityType: item.entityType, + // }); + + // this.dispatchEvent(event); + } + } + 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) { From 9c3485b4611b9f7cc01c63e0f17cf99f353ab74b Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Nov 2025 14:19:52 +0000 Subject: [PATCH 4/7] Adds in general_clipboard item to use in the UUI-box header --- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + 1 file changed, 1 insertion(+) 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 aa8fbb9f69cc..a04d3fe3cc3c 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', From 63f0fc5489d278e25bfaa9e54302ee16a17cddfb Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Nov 2025 14:57:20 +0000 Subject: [PATCH 5/7] Removes extra space & moves the requestItems outside the for loop --- .../picker/clipboard-entry-picker.element.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 77765b2d8a08..c22a784dbcf9 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 @@ -142,7 +142,6 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { // It did not update/refresh the UI of items/collection after calling delete // Should I dispatch an event to notify this same component to refresh? // Or explictly call request items again which just works - this.#requestItems(); // const event = new UmbRequestReloadStructureForEntityEvent({ // unique: item.unique, @@ -151,11 +150,14 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { // this.dispatchEvent(event); } + + // Update the list after clearing out items + this.#requestItems(); } override render() { return html` - + ${when( this._items.length > 0, From 7e53ccea1aa3969c93c385561f6c198cdd84b5a3 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 6 Nov 2025 15:01:58 +0000 Subject: [PATCH 6/7] 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 --- .../picker/clipboard-entry-picker.element.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) 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 c22a784dbcf9..c841e14106f3 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 @@ -123,13 +123,18 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { async #clearClipboard() { // Prompt the user to confirm clearing the clipboard - await umbConfirmModal(this, { - headline: '#clipboard_labelForClearClipboard', - content: '#clipboard_confirmClearDescription', - color: 'danger', - confirmLabel: '#general_clear', - cancelLabel: '#general_cancel', - }); + try { + await umbConfirmModal(this, { + headline: '#clipboard_labelForClearClipboard', + content: '#clipboard_confirmClearDescription', + color: 'danger', + confirmLabel: '#general_clear', + cancelLabel: '#general_cancel', + }); + } catch { + // User closed or explictly canceled the modal + return; + } for (const item of this._items) { // Clipboard items are a collection of items and the UmbClipboardContext From ec3964f73d60ad1bbe7b627528e62e812843ea68 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 11 Nov 2025 08:52:25 +0000 Subject: [PATCH 7/7] Cleanup my noisy comments for a re-review --- .../picker/clipboard-entry-picker.element.ts | 16 ---------------- 1 file changed, 16 deletions(-) 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 c841e14106f3..46e9c393d73e 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 @@ -122,7 +122,6 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { }; async #clearClipboard() { - // Prompt the user to confirm clearing the clipboard try { await umbConfirmModal(this, { headline: '#clipboard_labelForClearClipboard', @@ -132,31 +131,16 @@ export class UmbClipboardEntryPickerElement extends UmbLitElement { cancelLabel: '#general_cancel', }); } catch { - // User closed or explictly canceled the modal return; } for (const item of this._items) { - // Clipboard items are a collection of items and the UmbClipboardContext - // does not expose a method to use the delete from the underlying clipboardDetailRepository const { error } = await this.#clipboardDetailRepository.delete(item.unique); if (error) { console.error(`Unable to delete clipboard item with unique ${item.unique}`, error); } - - // It did not update/refresh the UI of items/collection after calling delete - // Should I dispatch an event to notify this same component to refresh? - // Or explictly call request items again which just works - - // const event = new UmbRequestReloadStructureForEntityEvent({ - // unique: item.unique, - // entityType: item.entityType, - // }); - - // this.dispatchEvent(event); } - // Update the list after clearing out items this.#requestItems(); }