From 89f20946dcadb1478c1d5b917f305c3cbc8be246 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 08:31:31 +0200 Subject: [PATCH 001/246] add select all option --- ...ocument-variant-language-picker.element.ts | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index ccfd6c36d4..59fc9ebe61 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -1,4 +1,5 @@ import { UmbDocumentVariantState, type UmbDocumentVariantOptionModel } from '../../types.js'; +import type { UUIBooleanInputElement } from '@umbraco-cms/backoffice/external/uui'; import { css, customElement, @@ -57,16 +58,30 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { } } + #onSelectAllChange(event: Event) { + const allUniques = this.variantLanguageOptions.map((o) => o.unique); + if ((event.target as UUIBooleanInputElement).checked) { + this.selectionManager.setSelection(allUniques); + } else { + this.selectionManager.setSelection([]); + } + } + override render() { - return this.variantLanguageOptions.length - ? repeat( - this.variantLanguageOptions, - (option) => option.unique, - (option) => html` ${this.#renderItem(option)} `, - ) - : html` - There are no available variants - `; + if (this.variantLanguageOptions.length === 0) { + return html` + There are no available variants + `; + } + + return html` + + ${repeat( + this.variantLanguageOptions, + (option) => option.unique, + (option) => html` ${this.#renderItem(option)} `, + )} + `; } #renderItem(option: UmbDocumentVariantOptionModel) { @@ -124,6 +139,14 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { .label-status { font-size: 0.8rem; } + + uui-menu-item { + --uui-menu-item-flat-structure: 1; + } + + uui-checkbox { + margin-bottom: var(--uui-size-space-2); + } `, ]; } From bf0a9d5b340815b48e42d516486656c5a1fed51a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 10:02:26 +0200 Subject: [PATCH 002/246] prevent selection if it contains a not allowed item --- .../core/utils/selection-manager/selection.manager.test.ts | 6 ++++++ .../core/utils/selection-manager/selection.manager.ts | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts index 18d8647457..579094b7b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts @@ -238,6 +238,12 @@ describe('UmbSelectionManager', () => { expect(manager.getSelection()).to.deep.equal(['1', '2']); }); + it('cant do the selection if the selection contains an item that is not allowed', () => { + manager.setAllowLimitation((item) => item !== '2'); + expect(() => manager.setSelection(['1', '2'])).to.throw(); + expect(manager.getSelection()).to.deep.equal([]); + }); + it('deselects multiple items', () => { manager.setSelection(['1', '2', '3']); manager.deselect('1'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts index 3e1cd91ca1..a02effb8f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts @@ -60,6 +60,13 @@ export class UmbSelectionManager) { if (this.getSelectable() === false) return; if (value === undefined) throw new Error('Value cannot be undefined'); + + value.forEach((unique) => { + if (this.#allow(unique) === false) { + throw new Error(`${unique} is now allowed to be selected`); + } + }); + const newSelection = this.getMultiple() ? value : value.slice(0, 1); this.#selection.setValue(newSelection); } From 72f9bedf1541ecc56913c8181c7a50cced4782ae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 10:36:44 +0200 Subject: [PATCH 003/246] add get filter method --- .../core/utils/selection-manager/selection.manager.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts index a02effb8f9..9deb92249d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts @@ -168,4 +168,13 @@ export class UmbSelectionManager boolean): void { this.#allow = compareFn; } + + /** + * Returns the function that determines if an item is selectable or not. + * @returns {*} + * @memberof UmbSelectionManager + */ + public getAllowLimitation() { + return this.#allow; + } } From cffed6fdb21b4b7a2fd816fdf449e413dfcf688b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 10:45:07 +0200 Subject: [PATCH 004/246] filter uniques --- .../shared/document-variant-language-picker.element.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index 59fc9ebe61..55db917f94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -60,8 +60,11 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { #onSelectAllChange(event: Event) { const allUniques = this.variantLanguageOptions.map((o) => o.unique); + const filter = this.selectionManager.getAllowLimitation(); + const allowedUniques = allUniques.filter((unique) => filter(unique)); + if ((event.target as UUIBooleanInputElement).checked) { - this.selectionManager.setSelection(allUniques); + this.selectionManager.setSelection(allowedUniques); } else { this.selectionManager.setSelection([]); } From 8dd5263dae3e988dbe41f1221efdd4c20f1c6f89 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 11:13:22 +0200 Subject: [PATCH 005/246] toggle checkbox when everything is selected --- .../document-variant-language-picker.element.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index 55db917f94..594337dfff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -70,6 +70,13 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { } } + #isAllSelected() { + const allUniques = this.variantLanguageOptions.map((o) => o.unique); + const filter = this.selectionManager.getAllowLimitation(); + const allowedUniques = allUniques.filter((unique) => filter(unique)); + return this._selection.length === allowedUniques.length; + } + override render() { if (this.variantLanguageOptions.length === 0) { return html` @@ -78,7 +85,10 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { } return html` - + ${repeat( this.variantLanguageOptions, (option) => option.unique, From eb0ebb20be2ac9f9ae6fbccdbd87802a59202208 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 11:15:07 +0200 Subject: [PATCH 006/246] update save headline --- src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts index 08ac94fae7..6a2f47c6b9 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts @@ -294,7 +294,7 @@ export default { languagesToUnpublish: 'Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages.', readyToPublish: 'Ready to Publish?', - readyToSave: 'Ready to Save?', + readyToSave: 'Save', sendForApproval: 'Send for approval', schedulePublishHelp: 'Select the date and time to publish and/or unpublish the content item.', createEmpty: 'Create new', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 3a8de51a46..6f79bf2640 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -310,7 +310,7 @@ export default { publishRequiresVariants: 'De følgende varianter er krævet for at en udgivelse kan finde sted:', notReadyToPublish: 'Vi er ikke klar til at udgive', readyToPublish: 'Klar til at udgive?', - readyToSave: 'Klar til at gemme?', + readyToSave: 'Gem', sendForApproval: 'Send til godkendelse', schedulePublishHelp: 'Vælg dato og klokkeslæt for at udgive og/eller afpublicere indholdet.', createEmpty: 'Opret ny', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index cd803070bb..50de20d5a1 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -321,7 +321,7 @@ export default { publishRequiresVariants: 'The following variants is required for publishing to take place:', notReadyToPublish: 'We are not ready to Publish', readyToPublish: 'Ready to publish?', - readyToSave: 'Ready to Save?', + readyToSave: 'Save', resetFocalPoint: 'Reset focal point', sendForApproval: 'Send for approval', schedulePublishHelp: 'Select the date and time to publish and/or unpublish the content item.', 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 88e2129900..28dd31ab7b 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -327,7 +327,7 @@ export default { publishRequiresVariants: 'The following variants is required for publishing to take place:', notReadyToPublish: 'We are not ready to Publish', readyToPublish: 'Ready to publish?', - readyToSave: 'Ready to Save?', + readyToSave: 'Save', resetFocalPoint: 'Reset focal point', sendForApproval: 'Send for approval', schedulePublishHelp: 'Select the date and time to publish and/or unpublish the content item.', From 7df449538bdccab6aa7c1f5305abe977c3989034 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 11:42:03 +0200 Subject: [PATCH 007/246] fix spacing --- .../modals/schedule-modal/document-schedule-modal.element.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts index dc850eb0ad..61750880ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts @@ -209,6 +209,10 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< .publish-date > uui-form-layout-item:first-child { border-right: 1px dashed var(--uui-color-border); } + + uui-menu-item { + --uui-menu-item-flat-structure: 1; + } `, ]; } From b1f6768ab35ca936d8b3155284d9459db516e2fb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 12:06:16 +0200 Subject: [PATCH 008/246] add select all option to schedule --- .../document-schedule-modal.element.ts | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts index 61750880ce..7780a27d70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts @@ -6,6 +6,7 @@ import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; import type { UmbInputDateElement } from '@umbraco-cms/backoffice/components'; +import type { UUIBooleanInputElement } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-document-schedule-modal') export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< @@ -77,6 +78,25 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< return this._selection.some((s) => s.unique === unique); } + #onSelectAllChange(event: Event) { + const allUniques = this._options.map((o) => o.unique); + const filter = this.#selectionManager.getAllowLimitation(); + const allowedUniques = allUniques.filter((unique) => filter(unique)); + + if ((event.target as UUIBooleanInputElement).checked) { + this.#selectionManager.setSelection(allowedUniques); + } else { + this.#selectionManager.setSelection([]); + } + } + + #isAllSelected() { + const allUniques = this._options.map((o) => o.unique); + const filter = this.#selectionManager.getAllowLimitation(); + const allowedUniques = allUniques.filter((unique) => filter(unique)); + return this._selection.length === allowedUniques.length; + } + override render() { return html`

@@ -107,11 +127,18 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< } #renderOptions() { - return repeat( - this._options, - (option) => option.unique, - (option) => this.#renderItem(option), - ); + return html` + + + ${repeat( + this._options, + (option) => option.unique, + (option) => this.#renderItem(option), + )} + `; } #renderItem(option: UmbDocumentVariantOptionModel) { @@ -210,6 +237,10 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< border-right: 1px dashed var(--uui-color-border); } + uui-checkbox { + margin-bottom: var(--uui-size-space-3); + } + uui-menu-item { --uui-menu-item-flat-structure: 1; } From 12d1d766d1de3f9fb6c3e9c2952a7a0e034772be Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 12:17:55 +0200 Subject: [PATCH 009/246] localize select all --- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + .../schedule-modal/document-schedule-modal.element.ts | 2 +- .../shared/document-variant-language-picker.element.ts | 2 +- .../components/log-viewer-log-level-filter-menu.element.ts | 7 ++++--- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 50de20d5a1..25d297e308 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -917,6 +917,7 @@ export default { header: 'Header', systemField: 'system field', lastUpdated: 'Last Updated', + selectAll: 'Select all', skipToMenu: 'Skip to menu', skipToContent: 'Skip to content', restore: 'Restore', 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 28dd31ab7b..8b31dc00d1 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -950,6 +950,7 @@ export default { addChild: 'Add child', editDataType: 'Edit data type', navigateSections: 'Navigate sections', + selectAll: 'Select all', shortcut: 'Shortcuts', showShortcuts: 'show shortcuts', toggleListView: 'Toggle list view', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts index 7780a27d70..33955f03c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts @@ -130,7 +130,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< return html` ${repeat( diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index 594337dfff..d181d6c820 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -87,7 +87,7 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { return html` ${repeat( this.variantLanguageOptions, diff --git a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/views/search/components/log-viewer-log-level-filter-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/views/search/components/log-viewer-log-level-filter-menu.element.ts index 6658abc6d9..1db43e7f7e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/views/search/components/log-viewer-log-level-filter-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/views/search/components/log-viewer-log-level-filter-menu.element.ts @@ -76,9 +76,10 @@ export class UmbLogViewerLogLevelFilterMenuElement extends UmbLitElement { `, )} - Select all + Deselect all From be813bcd14eb1e7a59d1d3bf59be1608910862e8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 4 Oct 2024 13:02:14 +0200 Subject: [PATCH 010/246] Update document-variant-language-picker.element.ts --- .../modals/shared/document-variant-language-picker.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index d181d6c820..83b5925c6d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -158,7 +158,7 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { } uui-checkbox { - margin-bottom: var(--uui-size-space-2); + margin-bottom: var(--uui-size-space-3); } `, ]; From 771b55cdaf48f0ab20288d63b961021db51c2bc5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 9 Oct 2024 11:33:36 +0200 Subject: [PATCH 011/246] Revert "update save headline" This reverts commit eb0ebb20be2ac9f9ae6fbccdbd87802a59202208. --- src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 2 +- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts index af0a03f54a..5190da61f0 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts @@ -294,7 +294,7 @@ export default { languagesToUnpublish: 'Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages.', readyToPublish: 'Ready to Publish?', - readyToSave: 'Save', + readyToSave: 'Ready to Save?', sendForApproval: 'Send for approval', schedulePublishHelp: 'Select the date and time to publish and/or unpublish the content item.', createEmpty: 'Create new', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 4c49b058aa..17d2f3271e 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -310,7 +310,7 @@ export default { publishRequiresVariants: 'De følgende varianter er krævet for at en udgivelse kan finde sted:', notReadyToPublish: 'Vi er ikke klar til at udgive', readyToPublish: 'Klar til at udgive?', - readyToSave: 'Gem', + readyToSave: 'Klar til at gemme?', sendForApproval: 'Send til godkendelse', schedulePublishHelp: 'Vælg dato og klokkeslæt for at udgive og/eller afpublicere indholdet.', createEmpty: 'Opret ny', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 94cecc220c..69186e18ec 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -329,7 +329,7 @@ export default { publishRequiresVariants: 'The following variants is required for publishing to take place:', notReadyToPublish: 'We are not ready to Publish', readyToPublish: 'Ready to publish?', - readyToSave: 'Save', + readyToSave: 'Ready to Save?', resetFocalPoint: 'Reset focal point', sendForApproval: 'Send for approval', schedulePublishHelp: 'Select the date and time to publish and/or unpublish the content item.', 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 3127bcb0fc..d511c4eec4 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -327,7 +327,7 @@ export default { publishRequiresVariants: 'The following variants is required for publishing to take place:', notReadyToPublish: 'We are not ready to Publish', readyToPublish: 'Ready to publish?', - readyToSave: 'Save', + readyToSave: 'Ready to Save?', resetFocalPoint: 'Reset focal point', sendForApproval: 'Send for approval', schedulePublishHelp: 'Select the date and time to publish and/or unpublish the content item.', From 26f83d73b28e9a7e4da2e234b01b8b3924354ec1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 9 Oct 2024 11:52:53 +0200 Subject: [PATCH 012/246] add specific localization to save modal title --- src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/es-es.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts | 1 + .../documents/modals/save-modal/document-save-modal.element.ts | 2 +- 25 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts index d7b50553cf..159d15d541 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts @@ -318,6 +318,7 @@ export default { createEmpty: 'Napravi novi', createFromClipboard: 'Zalijepi iz međuspremnika', nodeIsInTrash: 'Ova stavka je u korpi za otpatke', + saveModalTitle: 'Spremi', }, blueprints: { createBlueprintFrom: 'Kreirajte novi predložak sadržaja iz %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts index 5190da61f0..0f47ba053f 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts @@ -300,6 +300,7 @@ export default { createEmpty: 'Create new', createFromClipboard: 'Paste from clipboard', nodeIsInTrash: 'This item is in the Recycle Bin', + saveModalTitle: 'Uložit', }, blueprints: { createBlueprintFrom: 'Vytvořit novou šablonu obsahu z %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts index afea7d0aff..01ca531714 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts @@ -331,6 +331,7 @@ export default { variantSendForApprovalNotAllowed: 'Ni chaniateir anfon am gymeradwyaeth', variantScheduleNotAllowed: 'Ni chaniateir amserlennu', variantUnpublishNotAllowed: 'Ni chaniateir dad-gyhoeddi', + saveModalTitle: 'Achub', }, blueprints: { createBlueprintFrom: "Creu Templed Cynnwys newydd o '%0%'", diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 17d2f3271e..bfdbadbe68 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -326,6 +326,7 @@ export default { variantSendForApprovalNotAllowed: 'Send for approval is not allowed', variantScheduleNotAllowed: 'Schedule is not allowed', variantUnpublishNotAllowed: 'Unpublish is not allowed', + saveModalTitle: 'Gem', }, blueprints: { createBlueprintFrom: "Opret en ny indholdsskabelon fra '%0%'", diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts index fed36b1c08..66000861c1 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts @@ -332,6 +332,7 @@ export default { variantSendForApprovalNotAllowed: 'Zur Genehmigung senden ist nicht erlaubt.', variantScheduleNotAllowed: 'Plannung ist nicht erlaubt', variantUnpublishNotAllowed: 'Veröffentlichung zurücknehmen ist nicht erlaubt.', + saveModalTitle: 'Speichern', }, blueprints: { createBlueprintFrom: 'Erzeuge eine neue Inhaltsvorlage von %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 69186e18ec..4d0f4a33bc 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -342,6 +342,7 @@ export default { variantScheduleNotAllowed: 'Schedule is not allowed', variantUnpublishNotAllowed: 'Unpublish is not allowed', selectAllVariants: 'Select all variants', + saveModalTitle: 'Save', }, blueprints: { createBlueprintFrom: "Create a new Document Blueprint from '%0%'", 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 d511c4eec4..9888de4347 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -341,6 +341,7 @@ export default { variantScheduleNotAllowed: 'Schedule is not allowed', variantUnpublishNotAllowed: 'Unpublish is not allowed', selectAllVariants: 'Select all variants', + saveModalTitle: 'Save', }, blueprints: { createBlueprintFrom: "Create a new Document Blueprint from '%0%'", diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/es-es.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/es-es.ts index 1e815027ef..bb2d4bd9b2 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/es-es.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/es-es.ts @@ -202,6 +202,7 @@ export default { addTextBox: 'Añadir otra caja de texto', removeTextBox: 'Eliminar caja de texto', contentRoot: 'Raíz de contenido', + saveModalTitle: 'Guardar', }, blueprints: { createBlueprintFrom: 'Crear nueva Plantilla de Contenido desde %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts index 88ec99abfa..f465f3c76d 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts @@ -297,6 +297,7 @@ export default { schedulePublishHelp: "Sélectionnez la date et l'heure de publication/dépublication de l'élément de contenu.", createEmpty: 'Créer nouveau', createFromClipboard: 'Copier du clipboard', + saveModalTitle: 'Sauver', }, blueprints: { createBlueprintFrom: 'Créer un nouveau Modèle de Contenu à partir de %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts index 146ec4f545..827b5e8b09 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts @@ -113,6 +113,7 @@ export default { updateDate: 'נערך לאחרונה', uploadClear: 'הסר קובץ', urls: 'קשר למסמך', + saveModalTitle: 'שמור', }, create: { chooseNode: 'היכן ברצונך ליצור את %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts index d08b4d332e..3519e19060 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts @@ -319,6 +319,7 @@ export default { createEmpty: 'Kreiraj novo', createFromClipboard: 'Zalijepi iz međuspremnika', nodeIsInTrash: 'Ova stavka je u košu za smeće', + saveModalTitle: 'Spremi', }, blueprints: { createBlueprintFrom: 'Kreirajte novi predložak sadržaja iz %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts index bef4e1f0eb..9a7dfb9eec 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts @@ -331,6 +331,7 @@ export default { createEmpty: 'Crea nuovo/a', createFromClipboard: 'Incolla dagli appunti', nodeIsInTrash: 'Questo articolo è nel cestino', + saveModalTitle: 'Salva', }, blueprints: { createBlueprintFrom: "Crea un nuovo modello di contenuto da '%0%'", diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts index d16087a107..8f1c6130e6 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts @@ -148,6 +148,7 @@ export default { notmemberof: 'グループのメンバーではありません', childItems: '子コンテンツ', target: 'ターゲット', + saveModalTitle: '保存', }, media: { clickToUpload: 'クリックしてアップロードする', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts index 16ab5e6ba9..961d322c5a 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts @@ -113,6 +113,7 @@ export default { updateDate: '마지막 수정일', uploadClear: '파일 삭제', urls: '문서에 링크', + saveModalTitle: '저장', }, create: { chooseNode: '새로운 %0% (을)를 생성할 위치를 지정하십시오', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts index 94c3cb5eb2..92e082b4db 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts @@ -146,6 +146,7 @@ export default { notmemberof: 'Ikke medlem av gruppe(ne)', childItems: 'Undersider', target: 'Åpne i vindu', + saveModalTitle: 'Lagre', }, media: { clickToUpload: 'Klikk for å laste opp', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts index 8cb9748c6a..9833b8905d 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts @@ -317,6 +317,7 @@ export default { createEmpty: 'Maak nieuw', createFromClipboard: 'Plakken vanaf het klembord', nodeIsInTrash: 'Dit item is in de prullenbak', + saveModalTitle: 'Opslaan', }, blueprints: { createBlueprintFrom: 'Nieuw Inhoudssjabloon aanmaken voor %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts index c91545622e..b02b668dcc 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts @@ -199,6 +199,7 @@ export default { addTextBox: 'Dodaj kolejne pole tekstowe', removeTextBox: 'Usuń te pole tekstowe', contentRoot: 'Korzeń zawartości', + saveModalTitle: 'Zapisz', }, blueprints: { createBlueprintFrom: 'Stwórz nowy Szablon Zawartości z %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts index 501692b6d4..5ab8d07bc2 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts @@ -113,6 +113,7 @@ export default { updateDate: 'Última edição', uploadClear: 'Remover arquivo', urls: 'Link ao documento', + saveModalTitle: 'Salvar', }, create: { chooseNode: 'Onde você quer criar seu novo(a) %0%', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts index 042853eed7..7dd7d145de 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts @@ -250,6 +250,7 @@ export default { urls: 'Ссылка на документ', addTextBox: 'Добавить новое поле текста', removeTextBox: 'Удалить это поле текста', + saveModalTitle: 'Сохранить', }, contentPicker: { pickedTrashedItem: 'Выбран элемент содержимого, который в настоящее время удален или находится в корзине', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts index e33916c100..12e5c2b75b 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts @@ -233,6 +233,7 @@ export default { listViewNoContent: 'Inga undernoder har lagts till', noChanges: 'Inga ändringar har gjorts', notCreated: 'Ej skapad', + saveModalTitle: 'Spara', }, contentTypeEditor: { yesDelete: 'Ja, ta bort', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts index a7a1c8186b..681a683680 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts @@ -305,6 +305,7 @@ export default { createEmpty: 'Yeni oluştur', createFromClipboard: 'Panodan yapıştır', nodeIsInTrash: "Bu öğe Geri Dönüşüm Kutusu'nda", + saveModalTitle: 'Kaydet', }, blueprints: { createBlueprintFrom: '%0% den yeni bir İçerik Şablonu oluşturun', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts index f54696ab06..687193843a 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts @@ -250,6 +250,7 @@ export default { urls: 'Посилання на документ', addTextBox: 'Додати нове текстове поле', removeTextBox: 'Видалити це текстове поле', + saveModalTitle: 'Зберегти', }, contentPicker: { pickedTrashedItem: 'Вибрано елемент вмісту, який вилучено або знаходиться в корзині.', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts index b9038734bd..1681a72f11 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts @@ -154,6 +154,7 @@ export default { scheduledPublishServerTime: '这将转换到服务器上的以下时间:', scheduledPublishDocumentation: '这是什么意思?', + saveModalTitle: '保存', }, media: { clickToUpload: '点击上传', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts index da9413e108..6dfd7f5186 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts @@ -153,6 +153,7 @@ export default { scheduledPublishServerTime: '預計發表的時間(伺服器端)', scheduledPublishDocumentation: '這是什麼意思?', + saveModalTitle: '保存', }, media: { clickToUpload: '點選以便上傳', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.element.ts index 337c8867d1..fb9c8d70f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.element.ts @@ -46,7 +46,7 @@ export class UmbDocumentSaveModalElement extends UmbModalBaseElement< } override render() { - return html` + return html`

Choose which variants to be saved.

From a0e050d0907623e44c7f789d5961d49eba048c71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 9 Oct 2024 12:14:49 +0200 Subject: [PATCH 013/246] implement properties observable for base property dataset --- .../property-dataset-base-context.ts | 48 ++++++++++++++----- .../property-dataset-context.interface.ts | 5 +- .../property-dataset.element.ts | 2 +- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts index d51def11c0..2989a8e596 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts @@ -19,8 +19,13 @@ export class UmbPropertyDatasetContextBase #name = new UmbStringState(undefined); name = this.#name.asObservable(); - #values = new UmbArrayState([], (x) => x.alias); - public readonly values = this.#values.asObservable(); + #properties = new UmbArrayState([], (x) => x.alias); + public readonly properties = this.#properties.asObservable(); + /** + * @deprecated - use `properties` instead. + */ + readonly values = this.properties; + private _entityType!: string; private _unique!: string; @@ -51,12 +56,11 @@ export class UmbPropertyDatasetContextBase /** * @function propertyValueByAlias - * @param {string} propertyAlias - * @returns {Promise | undefined>} - * @description Get an Observable for the value of this property. + * @param {string} propertyAlias - the alias to observe + * @returns {Promise | undefined>} - an Observable for the value of this property. */ async propertyValueByAlias(propertyAlias: string) { - return this.#values.asObservablePart((values) => { + return this.#properties.asObservablePart((values) => { const valueObj = values.find((x) => x.alias === propertyAlias); return valueObj ? (valueObj.value as ReturnType) : undefined; }); @@ -64,20 +68,40 @@ export class UmbPropertyDatasetContextBase /** * @function setPropertyValue - * @param {string} alias + * @param {string} alias - The alias to set this value for * @param {PromiseLike} value - value can be a promise resolving into the actual value or the raw value it self. - * @returns {Promise} * @description Set the value of this property. */ setPropertyValue(alias: string, value: unknown) { - this.#values.appendOne({ alias, value }); + this.#properties.appendOne({ alias, value }); } + /** + * @deprecated Use `getProperties` + * @returns {Array} - Array of properties as objects with alias and value properties. + */ getValues() { - return this.#values.getValue(); + return this.#properties.getValue(); } - setValues(map: Array) { - this.#values.setValue(map); + /** + * @param {Array} properties - Properties array with alias and value properties. + * @deprecated Use `setProperties` + */ + setValues(properties: Array) { + this.#properties.setValue(properties); + } + + /** + * @returns {Array} - Array of properties as objects with alias and value properties. + */ + getProperties() { + return this.#properties.getValue(); + } + /** + * @param {Array} properties - Properties array with alias and value properties. + */ + setProperties(properties: Array) { + this.#properties.setValue(properties); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts index c33b0896ed..001a10a876 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts @@ -1,4 +1,5 @@ import type { UmbVariantId } from '../../variant/variant-id.class.js'; +import type { UmbPropertyValueData } from '../types.js'; import type { UmbContext } from '@umbraco-cms/backoffice/class-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; @@ -29,7 +30,9 @@ export interface UmbPropertyDatasetContext extends UmbContext { readonly readOnly: Observable; // Should it be possible to get the properties as a list of property aliases? - //readonly properties: Observable>; + readonly properties: Observable>; + getProperties(): Array; + setProperties(properties: Array): void; // Property methods: propertyVariantId?: (propertyAlias: string) => Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts index 04e4cb7c54..e11efdbb81 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset.element.ts @@ -96,7 +96,7 @@ export class UmbPropertyDatasetElement extends UmbLitElement { this.observe(this.context.name, this.#observerCallback); // prevent the first change event from firing: this.#allowChangeEvent = false; - this.observe(this.context.values, this.#observerCallback); + this.observe(this.context.properties, this.#observerCallback); } #observerCallback = () => { From ae0d5416e847330271966c10f5319bc235d5d207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 9 Oct 2024 12:15:01 +0200 Subject: [PATCH 014/246] optimize observable part --- .../structure/content-type-structure-manager.class.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 3ff0363183..01f231bae3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -70,9 +70,9 @@ export class UmbContentTypeStructureManager< // Notice this may need to use getValue to avoid resetting it self. [NL] return contentTypes.some((x) => x.properties.length > 0); }); - readonly contentTypePropertyAliases = this.#contentTypes.asObservablePart((contentTypes) => { - return contentTypes.flatMap((x) => x.properties ?? []).map((x) => x.alias); - }); + readonly contentTypePropertyAliases = createObservablePart(this.contentTypeProperties, (properties) => + properties.map((x) => x.alias), + ); readonly contentTypeUniques = this.#contentTypes.asObservablePart((x) => x.map((y) => y.unique)); readonly contentTypeAliases = this.#contentTypes.asObservablePart((x) => x.map((y) => y.alias)); From 685ed0b65ad712e400c3da39538ce76b72eb3120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 9 Oct 2024 12:15:07 +0200 Subject: [PATCH 015/246] JSDocs --- .../workspace/block-element-property-dataset.context.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts index 8daff7f3fb..291444df3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts @@ -59,8 +59,8 @@ export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase imp /** * @function propertyValueByAlias - * @param {string} propertyAlias - * @returns {Promise | undefined>} + * @param {string} propertyAlias - The alias of the property + * @returns {Promise | undefined>} - An observable of the property value. * @description Get an Observable for the value of this property. */ async propertyValueByAlias(propertyAlias: string) { @@ -69,7 +69,7 @@ export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase imp /** * @function setPropertyValue - * @param {string} alias + * @param {string} alias - The alias of the property * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. * @returns {Promise} * @description Set the value of this property. From c8cee5c028ffc4350aa887a51db3b35736a5ef5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 9 Oct 2024 12:15:16 +0200 Subject: [PATCH 016/246] JSDocs + await --- .../content-property-dataset.context.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index 13551548c1..f952768d75 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -93,7 +93,7 @@ export class UmbContentPropertyDatasetContext< /** * @function propertyVariantId - * @param {string} propertyAlias + * @param {string} propertyAlias - The property alias to observe the variantId of. * @returns {Promise | undefined>} * @description Get an Observable for the variant id of this property. */ @@ -105,8 +105,8 @@ export class UmbContentPropertyDatasetContext< /** * @function propertyValueByAlias - * @param {string} propertyAlias - * @returns {Promise | undefined>} + * @param {string} propertyAlias The alias of the property + * @returns {Promise | undefined>} - An observable of the property value * @description Get an Observable for the value of this property. */ async propertyValueByAlias( @@ -130,10 +130,10 @@ export class UmbContentPropertyDatasetContext< /** * @function setPropertyValueByVariant - * @param {string} propertyAlias + * @param {string} propertyAlias - The alias of the property * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. * @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for. - * @returns {Promise} + * @returns {Promise} - A promise that resolves once the value has been set. * @description Get the value of this property. */ setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise { @@ -142,7 +142,7 @@ export class UmbContentPropertyDatasetContext< /** * @function setPropertyValue - * @param {string} propertyAlias + * @param {string} propertyAlias - The alias for the value to be set * @param {PromiseLike} value - value can be a promise resolving into the actual value or the raw value it self. * @returns {Promise} * @description Set the value of this property. @@ -155,7 +155,7 @@ export class UmbContentPropertyDatasetContext< const variantId = this.#createPropertyVariantId(property); // This is not reacting to if the property variant settings changes while running. - this.#workspace.setPropertyValue(propertyAlias, await value, variantId); + await this.#workspace.setPropertyValue(propertyAlias, await value, variantId); } this.#workspace.finishPropertyValueChange(); } From b588cc890c2708e24a6f06b3eafc6d855443c85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 9 Oct 2024 12:30:00 +0200 Subject: [PATCH 017/246] implementation in progress --- .../content-property-dataset.context.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index f952768d75..d881abc1bd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -1,11 +1,15 @@ import type { UmbContentWorkspaceContext } from '../workspace/index.js'; import type { UmbContentDetailModel } from '../types.js'; -import type { UmbNameablePropertyDatasetContext, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import type { + UmbNameablePropertyDatasetContext, + UmbPropertyDatasetContext, + UmbPropertyValueData, +} from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { type Observable, map } from '@umbraco-cms/backoffice/external/rxjs'; -import { UmbBooleanState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; @@ -91,6 +95,25 @@ export class UmbContentPropertyDatasetContext< }); } + #propertiesObservable?: Observable>; + // Should it be possible to get the properties as a list of property aliases? + get properties(): Observable> { + if (!this.#propertiesObservable) { + const propertiesObservable = this.#workspace.structure.contentTypeProperties; + const propertyVariantIds = createObservablePart(propertiesObservable, (props: UmbPropertyTypeModel[]) => + props.map((prop) => this.#createPropertyVariantId(prop)), + ); + } + + return this.#propertiesObservable; + } + getProperties(): Array { + return []; + } + setProperties(properties: Array): void { + throw new Error('not implemented'); + } + /** * @function propertyVariantId * @param {string} propertyAlias - The property alias to observe the variantId of. From 882c22d2c8490867881d8d827f292adedd433724 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 10 Oct 2024 11:33:05 +0200 Subject: [PATCH 018/246] pass workspace path --- .../src/packages/documents/document-types/paths.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts index 2fcd3c5725..010c2f6759 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts @@ -26,4 +26,7 @@ export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN = new UmbPathPatter presetAlias?: UmbCreateDocumentTypeWorkspacePresetType | null; }>('create/parent/:parentEntityType/:parentUnique/:presetAlias', UMB_DOCUMENT_TYPE_WORKSPACE_PATH); -export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{ unique: string }>('edit/:unique'); +export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{ unique: string }>( + 'edit/:unique', + UMB_DOCUMENT_TYPE_WORKSPACE_PATH, +); From 8ef41d6e023856094cf5c6e0546404182a38c107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 10 Oct 2024 12:37:27 +0200 Subject: [PATCH 019/246] refactor --- .../libs/observable-api/states/basic-state.ts | 15 +++++++------- .../libs/observable-api/states/class-state.ts | 13 +++++------- .../utils/class-equal-memoization.function.ts | 20 +++++++++++++++++++ .../utils/create-observable-part.function.ts | 1 + .../src/libs/observable-api/utils/index.ts | 1 + 5 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/class-equal-memoization.function.ts diff --git a/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/basic-state.ts b/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/basic-state.ts index 7f5f609da4..d37def15d7 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/basic-state.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/basic-state.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from '@umbraco-cms/backoffice/external/rxjs'; +import { BehaviorSubject, type Observable } from '@umbraco-cms/backoffice/external/rxjs'; /** * @class UmbBasicState @@ -20,30 +20,31 @@ export class UmbBasicState { * * this.observe(myState, (latestStateValue) => console.log("Value is: ", latestStateValue)); */ - public asObservable(): ReturnType['asObservable']> { + public asObservable(): Observable { return this._subject.asObservable(); } /** - * @property value + * @property {unknown} value - the value of the State. * @description - Holds the current data of this state. + * @returns {unknown} Observable that * @example Example retrieve the current data of a state * const myState = new UmbArrayState('Hello world'); * console.log("Value is: ", myState.value); */ - public get value(): BehaviorSubject['value'] { + public get value(): T { return this.getValue(); } /** * @function getValue - * @returns {T} The current data of this state. + * @returns {unknown} The current data of this state. * @description - Provides the current data of this state. * @example Example retrieve the current data of a state * const myState = new UmbArrayState('Hello world'); * console.log("Value is: ", myState.value); */ - public getValue(): ReturnType['getValue']> { + public getValue(): T { return this._subject.getValue(); } @@ -58,7 +59,7 @@ export class UmbBasicState { /** * @function setValue - * @param {T} data - The next data for this state to hold. + * @param {unknown} data - The next data for this state to hold. * @description - Set the data of this state, if data is different than current this will trigger observations to update. * @example Example change the data of a state * const myState = new UmbArrayState('Good morning'); diff --git a/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/class-state.ts b/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/class-state.ts index 26fc104415..fad45c4175 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/class-state.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/observable-api/states/class-state.ts @@ -1,12 +1,9 @@ import type { MappingFunction } from '../types/mapping-function.type.js'; import type { MemoizationFunction } from '../types/memoization-function.type.js'; +import type { UmbClassStateData } from '../utils/class-equal-memoization.function.js'; import { createObservablePart } from '../utils/create-observable-part.function.js'; import { UmbBasicState } from './basic-state.js'; -export interface UmbClassStateData { - equal(otherClass: this | undefined): boolean; -} - /** * @class UmbClassState * @augments {UmbBasicState} @@ -18,10 +15,10 @@ export class UmbClassState extends UmbB } /** - * @function createObservablePart - * @param {(mappable: T) => R} mappingFunction - Method to return the part for this Observable to return. - * @param {(previousResult: R, currentResult: R) => boolean} [memoizationFunction] - Method to Compare if the data has changed. Should return true when data is different. + * @param {(mappable: UmbClassStateData | undefined) => unknown} mappingFunction - Method to return the part for this Observable to return. + * @param {(previousResult: unknown, currentResult: unknown) => boolean} [memoizationFunction] - Method to Compare if the data has changed. Should return true when data is different. + * @returns {Observable} - an observable. * @description - Creates an Observable from this State. */ asObservablePart( @@ -33,7 +30,7 @@ export class UmbClassState extends UmbB /** * @function setValue - * @param {T} data - The next data for this state to hold. + * @param {UmbClassStateData | undefined} data - The next data for this state to hold. * @description - Set the data of this state, if data is different than current this will trigger observations to update. */ override setValue(data: T): void { diff --git a/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/class-equal-memoization.function.ts b/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/class-equal-memoization.function.ts new file mode 100644 index 0000000000..ab4cdada11 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/class-equal-memoization.function.ts @@ -0,0 +1,20 @@ +/** + * @function classEqualMemoization + * @param {UmbClassStateData | undefined} previousValue - The previous value to compare. + * @param {UmbClassStateData | undefined} currentValue - The current value to compare. + * @returns {boolean} - Returns true if the values are identical. + * @description - Compares the two values using strict equality. + */ +export function classEqualMemoization( + previousValue: UmbClassStateData | undefined, + currentValue: UmbClassStateData | undefined, +): boolean { + return ( + (previousValue && currentValue && previousValue.equal(currentValue)) || + (previousValue === undefined && currentValue === undefined) + ); +} + +export interface UmbClassStateData { + equal(otherClass: this | undefined): boolean; +} diff --git a/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/create-observable-part.function.ts b/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/create-observable-part.function.ts index d8762bf36d..f878d7cced 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/create-observable-part.function.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/create-observable-part.function.ts @@ -9,6 +9,7 @@ import { distinctUntilChanged, map, shareReplay } from '@umbraco-cms/backoffice/ * @param {Observable} source - RxJS Subject to use for this Observable. * @param {(mappable: T) => R} mappingFunction - Method to return the part for this Observable to return. * @param {(previousResult: R, currentResult: R) => boolean} [memoizationFunction] - Method to Compare if the data has changed. Should return true when data is different. + * @returns {Observable} * @description - Creates a RxJS Observable from RxJS Subject. * @example Example create a Observable for part of the data Subject. * public readonly myPart = CreateObservablePart(this._data, (data) => data.myPart); diff --git a/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/index.ts b/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/index.ts index ff6dfc7e0d..03ffd9d6e6 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/observable-api/utils/index.ts @@ -1,5 +1,6 @@ export * from './append-to-frozen-array.function.js'; export * from './assign-to-frozen-object.function.js'; +export * from './class-equal-memoization.function.js'; export * from './create-observable-part.function.js'; export * from './deep-freeze.function.js'; export * from './default-memoization.function.js'; From 40db46c920bfc2b98d98fbffeb633fb580ece32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 10 Oct 2024 14:53:37 +0200 Subject: [PATCH 020/246] object-to-property-value-array --- .../src/packages/core/workspace/index.ts | 2 +- .../object-to-property-value-array.function.ts | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts index a568fc8775..974168832c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts @@ -7,10 +7,10 @@ export * from './entity/index.js'; export * from './modals/index.js'; export * from './paths.js'; export * from './submittable/index.js'; +export * from './utils/object-to-property-value-array.function.js'; export * from './workspace-context.interface.js'; export * from './workspace-property-dataset/index.js'; export * from './workspace.context-token.js'; export * from './workspace.element.js'; -export * from './workspace.element.js'; export type * from './conditions/index.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts new file mode 100644 index 0000000000..d35f34033f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts @@ -0,0 +1,14 @@ +import type { UmbPropertyValueData } from '../../property/types'; + +/** + * @function UmbObjectToPropertyValueArray + * @param {object} data - an object with properties to be converted. + * @returns {Array | undefined} - and array of property values or undefined + */ +export function umbObjectToPropertyValueArray(data: object | undefined): Array | undefined { + if (!data) return; + return Object.keys(data).map((key) => ({ + alias: key, + value: (data as any)[key], + })); +} From 4cefc40988ba175c62abc493f9307969ab48b259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 10 Oct 2024 14:55:18 +0200 Subject: [PATCH 021/246] content dataset impl --- .../block/workspace/block-element-manager.ts | 5 + .../content-property-dataset.context.ts | 95 ++++++++++++++----- .../content-workspace-context.interface.ts | 2 + .../property-dataset-context.interface.ts | 6 +- ...ant-dataset-workspace-context.interface.ts | 7 +- ...y-structure-workspace-context.interface.ts | 2 +- .../document-blueprint-workspace.context.ts | 5 + .../workspace/document-workspace.context.ts | 4 + .../workspace/media-workspace.context.ts | 5 + .../member/member-workspace.context.ts | 8 +- 10 files changed, 106 insertions(+), 33 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index d2c642d652..67e9f1c087 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -30,6 +30,11 @@ export class UmbBlockElementManager extends UmbControllerBase { readonly unique = this.#data.asObservablePart((data) => data?.key); readonly contentTypeId = this.#data.asObservablePart((data) => data?.contentTypeKey); + readonly values = this.#data.asObservablePart((data) => data?.values); + getValues() { + return this.#data.getValue()?.values; + } + readonly structure = new UmbContentTypeStructureManager( this, new UmbDocumentTypeDetailRepository(this), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index d881abc1bd..e5187fc269 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -1,20 +1,25 @@ import type { UmbContentWorkspaceContext } from '../workspace/index.js'; import type { UmbContentDetailModel } from '../types.js'; -import type { - UmbNameablePropertyDatasetContext, - UmbPropertyDatasetContext, - UmbPropertyValueData, -} from '@umbraco-cms/backoffice/property'; +import type { UmbNameablePropertyDatasetContext, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { type Observable, map } from '@umbraco-cms/backoffice/external/rxjs'; -import { UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; +import { + UmbBasicState, + UmbBooleanState, + UmbObjectState, + classEqualMemoization, + createObservablePart, + mergeObservables, +} from '@umbraco-cms/backoffice/observable-api'; import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { UmbWorkspaceUniqueType } from '@umbraco-cms/backoffice/workspace'; +type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>; + export class UmbContentPropertyDatasetContext< ContentModel extends UmbContentDetailModel = UmbContentDetailModel, ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, @@ -36,6 +41,12 @@ export class UmbContentPropertyDatasetContext< culture = this.#currentVariant.asObservablePart((x) => x?.culture); segment = this.#currentVariant.asObservablePart((x) => x?.segment); + // eslint-disable-next-line no-unused-private-class-members + #propertyVariantIdPromise?: Promise; + #propertyVariantIdPromiseResolver?: () => void; + #propertyVariantIdMap = new UmbBasicState([]); + private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable(); + #readOnly = new UmbBooleanState(false); public readOnly = this.#readOnly.asObservable(); @@ -86,6 +97,21 @@ export class UmbContentPropertyDatasetContext< }, 'umbObserveReadOnlyStates', ); + + // TODO: Refactor this into a separate manager/controller of some sort? [NL] + this.observe(this.#workspace.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { + this.#propertyVariantIdPromise ??= new Promise((resolve) => { + this.#propertyVariantIdPromiseResolver = resolve as any; + }); + const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); + this.#propertyVariantIdMap.setValue(map); + // Resolve promise, to let the once waiting on this know. + if (this.#propertyVariantIdPromiseResolver) { + this.#propertyVariantIdPromise = undefined; + this.#propertyVariantIdPromiseResolver(); + this.#propertyVariantIdPromiseResolver = undefined; + } + }); } #createPropertyVariantId(property: UmbPropertyTypeModel) { @@ -95,35 +121,54 @@ export class UmbContentPropertyDatasetContext< }); } - #propertiesObservable?: Observable>; + #propertiesObservable?: Observable; // Should it be possible to get the properties as a list of property aliases? - get properties(): Observable> { + get properties(): Observable { if (!this.#propertiesObservable) { - const propertiesObservable = this.#workspace.structure.contentTypeProperties; - const propertyVariantIds = createObservablePart(propertiesObservable, (props: UmbPropertyTypeModel[]) => - props.map((prop) => this.#createPropertyVariantId(prop)), + this.#propertiesObservable = mergeObservables( + [this._propertyVariantIdMap, this.#workspace.values], + this.#mergeVariantIdsAndValues, ); } return this.#propertiesObservable; } - getProperties(): Array { - return []; + + #mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, ContentModel['values'] | undefined]) { + const r: ContentModel['values'] = []; + if (values) { + for (const prop of props) { + const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v)); + if (f) { + r.push(f); + } + } + } + return r; } - setProperties(properties: Array): void { - throw new Error('not implemented'); + + async getProperties(): Promise { + await this.#propertyVariantIdPromise; + return this.#mergeVariantIdsAndValues([this.#propertyVariantIdMap.getValue(), this.#workspace.getValues()]); } /** * @function propertyVariantId * @param {string} propertyAlias - The property alias to observe the variantId of. - * @returns {Promise | undefined>} + * @returns {Promise | undefined>} - The observable for this properties variantId. * @description Get an Observable for the variant id of this property. */ async propertyVariantId(propertyAlias: string) { + /* return (await this.#workspace.structure.propertyStructureByAlias(propertyAlias)).pipe( map((property) => (property ? this.#createPropertyVariantId(property) : undefined)), ); + */ + return createObservablePart( + this._propertyVariantIdMap, + (x) => x.find((v) => v.alias === propertyAlias)?.variantId, + classEqualMemoization, + ); } /** @@ -136,9 +181,10 @@ export class UmbContentPropertyDatasetContext< propertyAlias: string, ): Promise | undefined> { await this.#workspace.isLoaded(); - const structure = await this.#workspace.structure.getPropertyStructureByAlias(propertyAlias); - if (structure) { - return this.#workspace.propertyValueByAlias(propertyAlias, this.#createPropertyVariantId(structure)); + await this.#propertyVariantIdPromise; + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + if (propVariantId) { + return this.#workspace.propertyValueByAlias(propertyAlias, propVariantId.variantId); } return; } @@ -172,13 +218,10 @@ export class UmbContentPropertyDatasetContext< */ async setPropertyValue(propertyAlias: string, value: PromiseLike) { this.#workspace.initiatePropertyValueChange(); - // This is not reacting to if the property variant settings changes while running. - const property = await this.#workspace.structure.getPropertyStructureByAlias(propertyAlias); - if (property) { - const variantId = this.#createPropertyVariantId(property); - - // This is not reacting to if the property variant settings changes while running. - await this.#workspace.setPropertyValue(propertyAlias, await value, variantId); + await this.#propertyVariantIdPromise; + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + if (propVariantId) { + return this.#workspace.setPropertyValue(propertyAlias, await value, propVariantId.variantId); } this.#workspace.finishPropertyValueChange(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts index c9fd0665cb..1d092e2c73 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts @@ -18,6 +18,8 @@ export interface UmbContentWorkspaceContext< UmbPropertyStructureWorkspaceContext { readonly IS_CONTENT_WORKSPACE_CONTEXT: true; readonly readOnlyState: UmbReadOnlyVariantStateManager; + readonly values: Observable; + getValues(): ContentModel['values'] | undefined; // Data: getData(): ContentModel | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts index 001a10a876..6bdb7565ef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-context.interface.ts @@ -30,9 +30,9 @@ export interface UmbPropertyDatasetContext extends UmbContext { readonly readOnly: Observable; // Should it be possible to get the properties as a list of property aliases? - readonly properties: Observable>; - getProperties(): Array; - setProperties(properties: Array): void; + readonly properties: Observable | undefined>; + getProperties(): Promise | undefined>; + //setProperties(properties: Array): void; // Property methods: propertyVariantId?: (propertyAlias: string) => Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/invariant-dataset-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/invariant-dataset-workspace-context.interface.ts index faec9d65a3..0ee14795cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/invariant-dataset-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/invariant-dataset-workspace-context.interface.ts @@ -1,8 +1,8 @@ -import type { UmbVariantId } from '../../../variant/variant-id.class.js'; -import type { UmbPropertyDatasetContext } from '../../../property/property-dataset/property-dataset-context.interface.js'; import type { UmbSubmittableWorkspaceContext } from './submittable-workspace-context.interface.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import type { UmbPropertyDatasetContext, UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; +import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; export interface UmbInvariantDatasetWorkspaceContext extends UmbSubmittableWorkspaceContext { // Name: @@ -10,6 +10,9 @@ export interface UmbInvariantDatasetWorkspaceContext extends UmbSubmittableWorks getName(): string | undefined; setName(name: string): void; + readonly values: Observable | undefined>; + getValues(): Promise | undefined>; + // Property: propertyValueByAlias(alias: string): Promise>; getPropertyValue(alias: string): ReturnType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/property-structure-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/property-structure-workspace-context.interface.ts index 566299a425..52ee7e88bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/property-structure-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/property-structure-workspace-context.interface.ts @@ -9,7 +9,7 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; export interface UmbPropertyStructureWorkspaceContext< ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, > extends UmbEntityWorkspaceContext { - structure: UmbContentTypeStructureManager; + readonly structure: UmbContentTypeStructureManager; // TODO: propertyStructureById is not used by anything in the codebase, should we remove it? [NL] propertyStructureById(id: string): Promise>; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts index a3959a1686..c318a9c505 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts @@ -84,6 +84,11 @@ export class UmbDocumentBlueprintWorkspaceContext readonly variants = this.#data.createObservablePartOfCurrent((data) => data?.variants || []); + readonly values = this.#data.createObservablePartOfCurrent((data) => data?.values); + getValues() { + return this.#data.getCurrent()?.values; + } + //readonly urls = this.#data.current.asObservablePart((data) => data?.urls || []); readonly structure = new UmbContentTypeStructureManager(this, new UmbDocumentTypeDetailRepository(this)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 9766f8261f..ff92c1aa1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -120,6 +120,10 @@ export class UmbDocumentWorkspaceContext readonly unique = this.#data.createObservablePartOfCurrent((data) => data?.unique); readonly entityType = this.#data.createObservablePartOfCurrent((data) => data?.entityType); readonly isTrashed = this.#data.createObservablePartOfCurrent((data) => data?.isTrashed); + readonly values = this.#data.createObservablePartOfCurrent((data) => data?.values); + getValues() { + return this.#data.getCurrent()?.values; + } readonly contentTypeUnique = this.#data.createObservablePartOfCurrent((data) => data?.documentType.unique); readonly contentTypeHasCollection = this.#data.createObservablePartOfCurrent( diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts index 173dad9b46..c26549700e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts @@ -81,6 +81,11 @@ export class UmbMediaWorkspaceContext readonly variants = this.#data.createObservablePartOfCurrent((data) => data?.variants || []); + readonly values = this.#data.createObservablePartOfCurrent((data) => data?.values); + getValues() { + return this.#data.getCurrent()?.values; + } + readonly urls = this.#data.createObservablePartOfCurrent((data) => data?.urls || []); readonly structure = new UmbContentTypeStructureManager(this, new UmbMediaTypeDetailRepository(this)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts index 12ecd26c37..b4ac6079e3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts @@ -18,6 +18,7 @@ import { UmbWorkspaceIsNewRedirectController, UmbWorkspaceIsNewRedirectControllerAlias, UmbWorkspaceSplitViewManager, + umbObjectToPropertyValueArray, } from '@umbraco-cms/backoffice/workspace'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { @@ -34,7 +35,7 @@ import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; import { UmbContentWorkspaceDataManager, type UmbContentWorkspaceContext } from '@umbraco-cms/backoffice/content'; import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type'; -import { map } from '@umbraco-cms/backoffice/external/rxjs'; +import { firstValueFrom, map } from '@umbraco-cms/backoffice/external/rxjs'; import { UmbEntityContext, type UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UmbRequestReloadChildrenOfEntityEvent, @@ -77,6 +78,11 @@ export class UmbMemberWorkspaceContext readonly variants = this.#data.createObservablePartOfCurrent((data) => data?.variants ?? []); + readonly values = this.#data.createObservablePartOfCurrent((data) => data?.values); + getValues() { + return this.#data.getCurrent()?.values; + } + readonly structure = new UmbContentTypeStructureManager(this, new UmbMemberTypeDetailRepository(this)); readonly variesByCulture = this.structure.ownerContentTypeObservablePart((x) => x?.variesByCulture); readonly variesBySegment = this.structure.ownerContentTypeObservablePart((x) => x?.variesBySegment); From 7fef7ffcdb1cdfc6daa93241f3046866f5061968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 10 Oct 2024 14:55:24 +0200 Subject: [PATCH 022/246] invariant dataset impl --- .../block-grid-area-type-workspace.context.ts | 11 +++++++++- ...iant-workspace-property-dataset-context.ts | 21 ++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts index 0acaf4f569..906c503a57 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts @@ -1,5 +1,5 @@ import type { UmbBlockGridTypeAreaType } from '../../../types.js'; -import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import type { UmbPropertyDatasetContext, UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbInvariantDatasetWorkspaceContext, @@ -10,12 +10,14 @@ import type { import { UmbSubmittableWorkspaceContextBase, UmbInvariantWorkspacePropertyDatasetContext, + umbObjectToPropertyValueArray, } from '@umbraco-cms/backoffice/workspace'; import { UmbArrayState, UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { PropertyEditorSettingsProperty } from '@umbraco-cms/backoffice/property-editor'; import { UmbId } from '@umbraco-cms/backoffice/id'; +import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; export class UmbBlockGridAreaTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase @@ -28,6 +30,13 @@ export class UmbBlockGridAreaTypeWorkspaceContext #data = new UmbObjectState(undefined); readonly data = this.#data.asObservable(); + readonly values = this.#data.asObservablePart((data) => { + return umbObjectToPropertyValueArray(data); + }); + async getValues(): Promise | undefined> { + return umbObjectToPropertyValueArray(await firstValueFrom(this.data)); + } + // TODO: Get the name of the contentElementType.. readonly name = this.#data.asObservablePart((data) => data?.alias); readonly unique = this.#data.asObservablePart((data) => data?.key); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts index 8039e78632..6a5a35038d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts @@ -1,10 +1,14 @@ -import type { UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import type { + UmbPropertyDatasetContext, + UmbNameablePropertyDatasetContext, + UmbPropertyValueData, +} from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import type { UmbInvariantDatasetWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; -import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbBooleanState, type Observable } from '@umbraco-cms/backoffice/observable-api'; /** * A property dataset context that hooks directly into the workspace context. @@ -47,6 +51,13 @@ export class UmbInvariantWorkspacePropertyDatasetContext< this.name = this.#workspace.name; } + get properties(): Observable | undefined> { + return this.#workspace.values; + } + getProperties(): Promise | undefined> { + return this.#workspace.getValues(); + } + /** * @function propertyValueByAlias * @param {string} propertyAlias @@ -58,9 +69,9 @@ export class UmbInvariantWorkspacePropertyDatasetContext< } /** - * TODO: Write proper JSDocs here. - * @param propertyAlias - * @param value + * @param {string} propertyAlias - The alias of the property + * @param {unknown} value - The value to be set for this property + * @returns {Promise} - an promise which resolves once the value has been set. */ async setPropertyValue(propertyAlias: string, value: unknown) { return this.#workspace.setPropertyValue(propertyAlias, value); From c4d17a8d33e1f92a80e955314ae421d1f7f5c5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 10:35:18 +0200 Subject: [PATCH 023/246] refactor block workspace and co --- .../workspace/block-type-workspace.context.ts | 16 +- .../block-value-resolver.api.ts | 12 +- .../standard-block-value-resolver.api.ts | 6 +- .../src/packages/block/block/types.ts | 4 +- .../block/workspace/block-element-manager.ts | 165 +++++++------ .../block-element-property-dataset.context.ts | 95 ++------ .../workspace/block-workspace.context.ts | 4 +- ...ace-view-edit-content-no-router.element.ts | 2 +- .../edit/block-workspace-view-edit.element.ts | 12 +- .../merge-content-variant-data.controller.ts | 19 +- .../src/packages/core/content/index.ts | 8 +- .../content/manager/content-data-manager.ts | 81 +------ .../content/manager/element-data-manager.ts | 70 ++++++ .../element-data-properties.manager.tempts | 160 +++++++++++++ .../packages/core/content/manager/index.ts | 2 + .../content-property-dataset.context.ts | 219 ++---------------- .../element-property-data-owner.interface.ts | 36 +++ .../element-property-dataset.context.ts | 208 +++++++++++++++++ .../content/property-dataset-context/index.ts | 3 + .../src/packages/core/content/types.ts | 15 +- .../content-workspace-context.interface.ts | 15 +- .../property-type-workspace.context.ts | 11 +- .../property-dataset-base-context.ts | 2 +- .../workspace-entity-action-menu.element.ts | 8 +- .../entity-workspace-context.interface.ts | 6 +- .../workspace-data-manager.interface.ts | 3 +- .../entity/entity-workspace-data-manager.ts | 3 +- .../src/packages/core/workspace/types.ts | 7 +- .../workspace/data-type-workspace.context.ts | 5 + .../documents/document-blueprints/types.ts | 4 +- .../src/packages/documents/documents/types.ts | 4 +- .../workspace/document-workspace.context.ts | 1 + .../src/packages/media/media/types.ts | 4 +- .../src/packages/members/member/types.ts | 4 +- .../member/member-workspace.context.ts | 3 +- .../rte-block-value-resolver.api.ts | 6 +- 36 files changed, 733 insertions(+), 490 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/manager/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-data-owner.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts index 8b9d425241..1d17eb81ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts @@ -1,6 +1,6 @@ import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js'; import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js'; -import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import type { UmbPropertyDatasetContext, UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbInvariantDatasetWorkspaceContext, @@ -12,9 +12,11 @@ import { UmbInvariantWorkspacePropertyDatasetContext, UmbWorkspaceIsNewRedirectController, UmbWorkspaceIsNewRedirectControllerAlias, + umbObjectToPropertyValueArray, } from '@umbraco-cms/backoffice/workspace'; import { UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; export class UmbBlockTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase @@ -25,12 +27,18 @@ export class UmbBlockTypeWorkspaceContext(undefined); - //readonly data = this.#data.asObservable(); + readonly data = this.#data.asObservable(); - // TODO: Get the name of the contentElementType.. - readonly name = this.#data.asObservablePart(() => 'block'); + readonly name = this.#data.asObservablePart(() => 'block type'); readonly unique = this.#data.asObservablePart((data) => data?.contentElementTypeKey); + readonly values = this.#data.asObservablePart((data) => { + return umbObjectToPropertyValueArray(data); + }); + async getValues(): Promise | undefined> { + return umbObjectToPropertyValueArray(await firstValueFrom(this.data)); + } + constructor(host: UmbControllerHost, args: { manifest: ManifestWorkspace }) { super(host, args.manifest.alias); const manifest = args.manifest; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/block-value-resolver.api.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/block-value-resolver.api.ts index 08ffcdc3f6..7abc94574f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/block-value-resolver.api.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/block-value-resolver.api.ts @@ -1,14 +1,14 @@ import type { UmbBlockDataValueModel, UmbBlockExposeModel, UmbBlockValueDataPropertiesBaseType } from '../types.js'; -import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; import type { UmbPropertyValueResolver } from '@umbraco-cms/backoffice/property'; export abstract class UmbBlockValueResolver - implements UmbPropertyValueResolver, UmbBlockDataValueModel, UmbBlockExposeModel> + implements UmbPropertyValueResolver, UmbBlockDataValueModel, UmbBlockExposeModel> { abstract processValues( - property: UmbContentValueModel, + property: UmbElementValueModel, valuesCallback: (values: Array) => Promise | undefined>, - ): Promise>; + ): Promise>; protected async _processValueBlockData( value: ValueType, @@ -30,9 +30,9 @@ export abstract class UmbBlockValueResolver } abstract processVariants( - property: UmbContentValueModel, + property: UmbElementValueModel, variantsCallback: (values: Array) => Promise | undefined>, - ): Promise>; + ): Promise>; protected async _processVariantBlockData( value: ValueType, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/standard-block-value-resolver.api.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/standard-block-value-resolver.api.ts index 7837845e70..2f3c42d1f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/standard-block-value-resolver.api.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/property-value-resolver/standard-block-value-resolver.api.ts @@ -1,10 +1,10 @@ import type { UmbBlockDataValueModel, UmbBlockExposeModel, UmbBlockValueType } from '../types.js'; import { UmbBlockValueResolver } from './block-value-resolver.api.js'; -import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export class UmbStandardBlockValueResolver extends UmbBlockValueResolver { async processValues( - property: UmbContentValueModel, + property: UmbElementValueModel, valuesCallback: (values: Array) => Promise | undefined>, ) { if (property.value) { @@ -17,7 +17,7 @@ export class UmbStandardBlockValueResolver extends UmbBlockValueResolver, + property: UmbElementValueModel, variantsCallback: (values: Array) => Promise | undefined>, ) { if (property.value) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index a95b0dab57..77f43f22d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,4 +1,4 @@ -import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export interface UmbBlockLayoutBaseModel { contentKey: string; @@ -6,7 +6,7 @@ export interface UmbBlockLayoutBaseModel { } // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbBlockDataValueModel extends UmbContentValueModel {} +export interface UmbBlockDataValueModel extends UmbElementValueModel {} export interface UmbBlockDataModel { key: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index 67e9f1c087..9c9f33b029 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -5,7 +5,6 @@ import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content- import { type Observable, UmbClassState, - UmbObjectState, appendToFrozenArray, mergeObservables, } from '@umbraco-cms/backoffice/observable-api'; @@ -14,27 +13,41 @@ import { type UmbClassInterface, UmbControllerBase } from '@umbraco-cms/backoffi import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { UmbValidationController } from '@umbraco-cms/backoffice/validation'; +import { UmbElementWorkspaceDataManager, type UmbElementPropertyDataOwner } from '@umbraco-cms/backoffice/content'; +import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; -export class UmbBlockElementManager extends UmbControllerBase { +import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type'; + +export class UmbBlockElementManager + extends UmbControllerBase + implements UmbElementPropertyDataOwner +{ // - #data = new UmbObjectState(undefined); - readonly data = this.#data.asObservable(); + + readonly #data = new UmbElementWorkspaceDataManager(this); + //#data = new UmbObjectState(undefined); + readonly data = this.#data.current; #getDataPromise = new Promise((resolve) => { this.#getDataResolver = resolve; }); #getDataResolver!: () => void; + public readonly readOnlyState = new UmbReadOnlyVariantStateManager(this); + #variantId = new UmbClassState(undefined); readonly variantId = this.#variantId.asObservable(); - readonly unique = this.#data.asObservablePart((data) => data?.key); - readonly contentTypeId = this.#data.asObservablePart((data) => data?.contentTypeKey); + readonly unique = this.#data.createObservablePartOfCurrent((data) => data?.key); + readonly contentTypeId = this.#data.createObservablePartOfCurrent((data) => data?.contentTypeKey); - readonly values = this.#data.asObservablePart((data) => data?.values); + readonly values = this.#data.createObservablePartOfCurrent((data) => data?.values); getValues() { - return this.#data.getValue()?.values; + return this.#data.getCurrent()?.values; } + readonly #dataTypeItemManager = new UmbDataTypeItemRepositoryManager(this); + #dataTypeSchemaAliasMap = new Map(); + readonly structure = new UmbContentTypeStructureManager( this, new UmbDocumentTypeDetailRepository(this), @@ -51,10 +64,34 @@ export class UmbBlockElementManager extends UmbControllerBase { this.validation.setDataPath('$.' + dataPathPropertyName + `[?(@.key = '${key}')]`); } }); + + this.observe( + this.structure.contentTypeDataTypeUniques, + (dataTypeUniques: Array) => { + this.#dataTypeItemManager.setUniques(dataTypeUniques); + }, + null, + ); + this.observe( + this.#dataTypeItemManager.items, + (dataTypes) => { + // Make a map of the data type unique and editorAlias: + this.#dataTypeSchemaAliasMap = new Map( + dataTypes.map((dataType) => { + return [dataType.unique, dataType.propertyEditorSchemaAlias]; + }), + ); + }, + null, + ); } - reset() { - this.#data.setValue(undefined); + public isLoaded() { + return this.#getDataPromise; + } + + resetState() { + this.#data.clear(); } setVariantId(variantId: UmbVariantId | undefined) { @@ -66,12 +103,13 @@ export class UmbBlockElementManager extends UmbControllerBase { // TODO: rename to currentData: setData(data: UmbBlockDataModel | undefined) { - this.#data.setValue(data); + this.#data.setPersisted(data); + this.#data.setCurrent(data); this.#getDataResolver(); } getData() { - return this.#data.getValue(); + return this.#data.getCurrent(); } getUnique() { @@ -105,100 +143,79 @@ export class UmbBlockElementManager extends UmbControllerBase { /** * @function propertyValueByAlias - * @param {string} propertyAlias - Property Alias to observe the value of. - * @returns {Promise | undefined>} - Promise which resolves to an Observable + * @param {string} propertyAlias - The alias of the property + * @param {UmbVariantId} variantId - The variant + * @returns {Promise | undefined>} - An observable for the value of the property * @description Get an Observable for the value of this property. */ async propertyValueByAlias( propertyAlias: string, + variantId?: UmbVariantId, ): Promise | undefined> { - await this.#getDataPromise; - - return mergeObservables( - [ - this.#data.asObservablePart((data) => data?.values?.filter((x) => x?.alias === propertyAlias)), - await this.propertyVariantId(propertyAlias), - ], - ([propertyValues, propertyVariantId]) => { - if (!propertyValues || !propertyVariantId) return; - - return propertyValues.find((x) => propertyVariantId.compare(x))?.value as PropertyValueType; - }, + return this.#data.createObservablePartOfCurrent( + (data) => + data?.values?.find((x) => x?.alias === propertyAlias && (variantId ? variantId.compare(x) : true)) + ?.value as PropertyValueType, ); } /** * Get the current value of the property with the given alias and variantId. * @param {string} alias - The alias of the property - * @returns {ReturnType} The value or undefined if not set or found. + * @param {UmbVariantId | undefined} variantId - The variant id of the property + * @returns {ReturnType | undefined} The value or undefined if not set or found. */ - async getPropertyValue(alias: string) { - await this.#getDataPromise; - const managerVariantId = this.#variantId.getValue(); - if (!managerVariantId) return; - const property = await this.structure.getPropertyStructureByAlias(alias); - if (!property) return; - const variantId = this.#createPropertyVariantId(property, managerVariantId); - const currentData = this.getData(); - if (!currentData) return; - const newDataSet = currentData.values?.find((x) => x.alias === alias && (variantId ? variantId.compare(x) : true)); - return newDataSet?.value as ReturnType; + getPropertyValue(alias: string, variantId?: UmbVariantId) { + const currentData = this.#data.getCurrent(); + if (currentData) { + const newDataSet = currentData.values?.find( + (x) => x.alias === alias && (variantId ? variantId.compare(x) : true), + ); + return newDataSet?.value as ReturnType; + } + return undefined; } - - /** - * @function setPropertyValue - * @param {string} alias - The alias of the property - * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. - * @returns {Promise} - * @description Set the value of this property. - */ - async setPropertyValue(alias: string, value: ValueType) { + async setPropertyValue(alias: string, value: ValueType, variantId?: UmbVariantId) { this.initiatePropertyValueChange(); - await this.#getDataPromise; - const managerVariantId = this.#variantId.getValue(); - if (!managerVariantId) return; + variantId ??= UmbVariantId.CreateInvariant(); const property = await this.structure.getPropertyStructureByAlias(alias); - if (!property) return; - const variantId = this.#createPropertyVariantId(property, managerVariantId); - const entry = { ...variantId.toObject(), alias, value } as UmbBlockDataValueModel; + if (!property) { + throw new Error(`Property alias "${alias}" not found.`); + } + + const editorAlias = this.#dataTypeSchemaAliasMap.get(property.dataType.unique); + if (!editorAlias) { + throw new Error(`Editor Alias of "${property.dataType.unique}" not found.`); + } + + const entry = { ...variantId.toObject(), alias, editorAlias, value } as UmbBlockDataValueModel; + const currentData = this.getData(); if (currentData) { const values = appendToFrozenArray( currentData.values ?? [], entry, - (x) => x.alias === alias && variantId.compare(x), + (x) => x.alias === alias && variantId!.compare(x), ); - this.#data.update({ values }); + this.#data.updateCurrent({ values }); } this.finishPropertyValueChange(); } - #updateLock = 0; initiatePropertyValueChange() { - this.#updateLock++; - this.#data.mute(); - // TODO: When ready enable this code will enable handling a finish automatically by this implementation 'using myState.initiatePropertyValueChange()' (Relies on TS support of Using) [NL] - /*return { - [Symbol.dispose]: this.finishPropertyValueChange, - };*/ + this.#data.initiatePropertyValueChange(); } finishPropertyValueChange = () => { - this.#updateLock--; - this.#triggerPropertyValueChanges(); + this.#data.finishPropertyValueChange(); }; - #triggerPropertyValueChanges() { - if (this.#updateLock === 0) { - this.#data.unmute(); - } + + public createPropertyDatasetContext(host: UmbControllerHost, variantId: UmbVariantId) { + return new UmbBlockElementPropertyDatasetContext(host, this, variantId); } - public createPropertyDatasetContext(host: UmbControllerHost) { - return new UmbBlockElementPropertyDatasetContext(host, this, this.getVariantId()); - } - - public setup(host: UmbClassInterface) { - this.createPropertyDatasetContext(host); + public setup(host: UmbClassInterface, variantId: UmbVariantId) { + this.createPropertyDatasetContext(host, variantId); // Provide Validation Context for this view: this.validation.provideAt(host); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts index 291444df3a..89e7a7fd9f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts @@ -1,89 +1,28 @@ -import { UMB_BLOCK_ELEMENT_PROPERTY_DATASET_CONTEXT } from './block-element-property-dataset.context-token.js'; import type { UmbBlockElementManager } from './block-element-manager.js'; -import { UMB_BLOCK_WORKSPACE_CONTEXT } from './block-workspace.context-token.js'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; -import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import { UmbElementPropertyDatasetContext } from '@umbraco-cms/backoffice/content'; +import { createObservablePart } from '@umbraco-cms/backoffice/observable-api'; -export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase implements UmbPropertyDatasetContext { - #elementManager: UmbBlockElementManager; - public getVariantId() { - return this.#elementManager.getVariantId(); +export class UmbBlockElementPropertyDatasetContext + extends UmbElementPropertyDatasetContext + implements UmbPropertyDatasetContext +{ + name; + culture; + segment; + + getName(): string { + return 'Block'; } - #variantId: UmbVariantId; - - #readOnly = new UmbBooleanState(false); - public readOnly = this.#readOnly.asObservable(); - - // default data: - - getEntityType() { - return this.#elementManager.getEntityType(); - } - getUnique() { - return this.#elementManager.getUnique(); - } - - getName(): string | undefined { - return 'TODO: get label'; - } - readonly name: Observable = 'TODO: get label observable' as any; constructor(host: UmbControllerHost, elementManager: UmbBlockElementManager, variantId?: UmbVariantId) { // The controller alias, is a very generic name cause we want only one of these for this controller host. - super(host, UMB_PROPERTY_DATASET_CONTEXT.toString()); - this.#elementManager = elementManager; - this.#variantId = variantId ?? UmbVariantId.CreateInvariant(); + super(host, elementManager, variantId); - this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspace) => { - this.observe( - workspace.readOnlyState.states, - (states) => { - const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId)); - this.#readOnly.setValue(isReadOnly); - }, - 'umbObserveReadOnlyStates', - ); - }); - - this.provideContext(UMB_BLOCK_ELEMENT_PROPERTY_DATASET_CONTEXT, this); - } - - propertyVariantId?(propertyAlias: string): Promise> { - return this.#elementManager.propertyVariantId(propertyAlias); - } - - /** - * @function propertyValueByAlias - * @param {string} propertyAlias - The alias of the property - * @returns {Promise | undefined>} - An observable of the property value. - * @description Get an Observable for the value of this property. - */ - async propertyValueByAlias(propertyAlias: string) { - return await this.#elementManager.propertyValueByAlias(propertyAlias); - } - - /** - * @function setPropertyValue - * @param {string} alias - The alias of the property - * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. - * @returns {Promise} - * @description Set the value of this property. - */ - async setPropertyValue(alias: string, value: PromiseLike) { - this.#elementManager.setPropertyValue(alias, value); - } - - /** - * Gets the read-only state of the current variant culture. - * @returns {*} {boolean} - * @memberof UmbBlockGridInlinePropertyDatasetContext - */ - getReadOnly(): boolean { - return this.#readOnly.getValue(); + this.name = elementManager.name; + this.culture = createObservablePart(elementManager.variantId, (v) => v?.culture); + this.segment = createObservablePart(elementManager.variantId, (v) => v?.segment); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index 4c0ad16a16..d850970f3c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -204,8 +204,8 @@ export class UmbBlockWorkspaceContext { if (variantId) { + context.content.setup(this, variantId); // TODO: Support segment name? const culture = variantId.culture; if (culture) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts index bdf60dd194..669bb6fbb1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts @@ -69,8 +69,16 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U const blockManager = this.#blockWorkspace[this.#managerName]; this.#tabsStructureHelper.setStructureManager(blockManager.structure); - // Create Data Set & setup Validation Context: - blockManager.setup(this); + this.observe( + this.#blockWorkspace.variantId, + (variantId) => { + if (variantId) { + // Create Data Set & setup Validation Context: + blockManager.setup(this, variantId); + } + }, + 'observeVariantId', + ); this.observe( await this.#blockWorkspace![this.#managerName!].structure.hasRootContainers('Group'), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.ts index e4ecfc2c04..aa50029af8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.ts @@ -1,5 +1,5 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbContentDetailModel, UmbPotentialContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbContentLikeDetailModel, UmbPotentialContentValueModel } from '@umbraco-cms/backoffice/content'; import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbVariantId, type UmbVariantDataModel } from '@umbraco-cms/backoffice/variant'; @@ -17,13 +17,13 @@ function defaultCompareVariantMethod(a: UmbVariantDataModel, b: UmbVariantDataMo export class UmbMergeContentVariantDataController extends UmbControllerBase { /** * Merges content variant data based on selected variants and variants to store. - * @param {UmbContentDetailModel | undefined} persistedData - The persisted content variant data. - * @param {UmbContentDetailModel} currentData - The current content variant data. + * @param {UmbContentLikeDetailModel | undefined} persistedData - The persisted content variant data. + * @param {UmbContentLikeDetailModel} currentData - The current content variant data. * @param {Array} selectedVariants - The selected variants. * @param {Array} variantsToStore - The variants to store, we sometimes have additional variants that we like to process. This is typically the invariant variant, which we do not want to have as part of the variants data therefore a difference. - * @returns {Promise} - A promise that resolves to the merged content variant data. + * @returns {Promise} - A promise that resolves to the merged content variant data. */ - async process( + async process( persistedData: ModelType | undefined, currentData: ModelType, selectedVariants: Array, @@ -39,14 +39,17 @@ export class UmbMergeContentVariantDataController extends UmbControllerBase { currentData.values, variantsToStore, ), + }; + + if (currentData.variants) { // Notice for variants we do not want to include all the variants that we are processing. but just the once selected for the process. (Not include invariant if we are in a variant document) [NL] - variants: this.#processVariants( + result.variants = this.#processVariants( persistedData?.variants, currentData.variants, selectedVariants, defaultCompareVariantMethod, - ), - }; + ); + } this.destroy(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts index b955ee1cfe..a70ac6e23c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts @@ -1,8 +1,8 @@ export { UMB_CONTENT_PROPERTY_CONTEXT } from './content-property.context-token.js'; export { UmbContentPropertyContext } from './content-property.context.js'; -export * from './manager/content-data-manager.js'; -export * from './controller/merge-content-variant-data.controller.js'; -export * from './property-dataset-context/content-property-dataset.context.js'; -export * from './workspace/index.js'; export * from './collection/index.js'; +export * from './controller/merge-content-variant-data.controller.js'; +export * from './manager/index.js'; +export * from './property-dataset-context/index.js'; +export * from './workspace/index.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/content-data-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/content-data-manager.ts index e9cad5be02..3c6601037f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/content-data-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/content-data-manager.ts @@ -1,63 +1,24 @@ -import { UmbMergeContentVariantDataController } from '../controller/merge-content-variant-data.controller.js'; +import { UmbElementWorkspaceDataManager } from './element-data-manager.js'; import type { UmbContentDetailModel } from '@umbraco-cms/backoffice/content'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { appendToFrozenArray, jsonStringComparison } from '@umbraco-cms/backoffice/observable-api'; import { UmbVariantId, type UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; -import { UmbEntityWorkspaceDataManager, type UmbWorkspaceDataManager } from '@umbraco-cms/backoffice/workspace'; export class UmbContentWorkspaceDataManager< - ModelType extends UmbContentDetailModel, - ModelVariantType extends UmbEntityVariantModel = ModelType extends { variants: UmbEntityVariantModel[] } - ? ModelType['variants'][0] - : never, - > - extends UmbEntityWorkspaceDataManager - implements UmbWorkspaceDataManager -{ + ModelType extends UmbContentDetailModel, + ModelVariantType extends UmbEntityVariantModel = ModelType extends { variants: UmbEntityVariantModel[] } + ? ModelType['variants'][0] + : never, +> extends UmbElementWorkspaceDataManager { // //#repository; #variantScaffold?: ModelVariantType; - #varies?: boolean; - //#variesByCulture?: boolean; - //#variesBySegment?: boolean; - constructor(host: UmbControllerHost, variantScaffold: ModelVariantType) { super(host); this.#variantScaffold = variantScaffold; } - #updateLock = 0; - initiatePropertyValueChange() { - this.#updateLock++; - this._current.mute(); - // TODO: When ready enable this code will enable handling a finish automatically by this implementation 'using myState.initiatePropertyValueChange()' (Relies on TS support of Using) [NL] - /*return { - [Symbol.dispose]: this.finishPropertyValueChange, - };*/ - } - finishPropertyValueChange = () => { - this.#updateLock--; - this.#triggerPropertyValueChanges(); - }; - #triggerPropertyValueChanges() { - if (this.#updateLock === 0) { - this._current.unmute(); - } - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - setVariesByCulture(vary: boolean | undefined) { - //this.#variesByCulture = vary; - } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - setVariesBySegment(vary: boolean | undefined) { - //this.#variesBySegment = vary; - } - setVaries(vary: boolean | undefined) { - this.#varies = vary; - } - ensureVariantData(variantId: UmbVariantId) { this.updateVariantData(variantId); } @@ -66,7 +27,7 @@ export class UmbContentWorkspaceDataManager< const currentData = this.getCurrent(); if (!currentData) throw new Error('Data is missing'); if (!this.#variantScaffold) throw new Error('Variant scaffold data is missing'); - if (this.#varies === true) { + if (this._varies === true) { // If variant Id is invariant, we don't to have the variant appended to our data. if (variantId.isInvariant()) return; const variant = currentData.variants.find((x) => variantId.compare(x)); @@ -82,7 +43,7 @@ export class UmbContentWorkspaceDataManager< ) as Array; // TODO: I have some trouble with TypeScript here, I does not look like me, but i had to give up. [NL] this._current.update({ variants: newVariants } as any); - } else if (this.#varies === false) { + } else if (this._varies === false) { // TODO: Beware about segments, in this case we need to also consider segments, if its allowed to vary by segments. const invariantVariantId = UmbVariantId.CreateInvariant(); const variant = currentData.variants.find((x) => invariantVariantId.compare(x)); @@ -102,32 +63,6 @@ export class UmbContentWorkspaceDataManager< } } - async constructData(selectedVariants: Array): Promise { - // Lets correct the selected variants, so invariant is included, or the only one if invariant. - // TODO: VDIVD: Could a document be set to invariant but hold variant data inside it? - const invariantVariantId = UmbVariantId.CreateInvariant(); - let variantsToStore = [invariantVariantId]; - if (this.#varies === false) { - // If we do not vary, we wil just pick the invariant variant id. - selectedVariants = [invariantVariantId]; - } else { - variantsToStore = [...selectedVariants, invariantVariantId]; - } - - const data = this._current.getValue(); - if (!data) throw new Error('Current data is missing'); - if (!data.unique) throw new Error('Unique of current data is missing'); - - const persistedData = this.getPersisted(); - - return await new UmbMergeContentVariantDataController(this).process( - persistedData, - data, - selectedVariants, - variantsToStore, - ); - } - getChangedVariants() { const persisted = this.getPersisted(); const current = this.getCurrent(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-manager.ts new file mode 100644 index 0000000000..7dd3ddc91e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-manager.ts @@ -0,0 +1,70 @@ +import { UmbMergeContentVariantDataController } from '../controller/merge-content-variant-data.controller.js'; +import type { UmbElementDetailModel } from '@umbraco-cms/backoffice/content'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import { UmbEntityWorkspaceDataManager, type UmbWorkspaceDataManager } from '@umbraco-cms/backoffice/workspace'; + +export class UmbElementWorkspaceDataManager + extends UmbEntityWorkspaceDataManager + implements UmbWorkspaceDataManager +{ + protected _varies?: boolean; + //#variesByCulture?: boolean; + //#variesBySegment?: boolean; + + #updateLock = 0; + initiatePropertyValueChange() { + this.#updateLock++; + this._current.mute(); + // TODO: When ready enable this code will enable handling a finish automatically by this implementation 'using myState.initiatePropertyValueChange()' (Relies on TS support of Using) [NL] + /*return { + [Symbol.dispose]: this.finishPropertyValueChange, + };*/ + } + finishPropertyValueChange = () => { + this.#updateLock--; + this.#triggerPropertyValueChanges(); + }; + #triggerPropertyValueChanges() { + if (this.#updateLock === 0) { + this._current.unmute(); + } + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setVariesByCulture(vary: boolean | undefined) { + //this.#variesByCulture = vary; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setVariesBySegment(vary: boolean | undefined) { + //this.#variesBySegment = vary; + } + setVaries(vary: boolean | undefined) { + this._varies = vary; + } + + async constructData(selectedVariants: Array): Promise { + // Lets correct the selected variants, so invariant is included, or the only one if invariant. + // TODO: VDIVD: Could a document be set to invariant but hold variant data inside it? + const invariantVariantId = UmbVariantId.CreateInvariant(); + let variantsToStore = [invariantVariantId]; + if (this._varies === false) { + // If we do not vary, we wil just pick the invariant variant id. + selectedVariants = [invariantVariantId]; + } else { + variantsToStore = [...selectedVariants, invariantVariantId]; + } + + const data = this._current.getValue(); + if (!data) throw new Error('Current data is missing'); + //if (!data.unique) throw new Error('Unique of current data is missing'); + + const persistedData = this.getPersisted(); + + return await new UmbMergeContentVariantDataController(this).process( + persistedData, + data, + selectedVariants, + variantsToStore, + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts new file mode 100644 index 0000000000..ed8f8e9b87 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts @@ -0,0 +1,160 @@ +import type { UmbElementPropertyDataOwner } from '../property-dataset-context/element-property-data-owner.interface.js'; +import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import { + UmbBasicState, + classEqualMemoization, + createObservablePart, + mergeObservables, +} from '@umbraco-cms/backoffice/observable-api'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; + +type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>; + +export class UmbElementDataPropertyManager< + ContentModel extends { values: Array }, + ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, +> extends UmbControllerBase { + #dataOwner: UmbElementPropertyDataOwner; + #variantId: UmbVariantId; + + // eslint-disable-next-line no-unused-private-class-members + #propertyVariantIdPromise?: Promise; + #propertyVariantIdPromiseResolver?: () => void; + #propertyVariantIdMap = new UmbBasicState([]); + private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable(); + + constructor( + host: UmbControllerHost, + dataOwner: UmbElementPropertyDataOwner, + variantId?: UmbVariantId, + ) { + // The controller alias, is a very generic name cause we want only one of these for this controller host. + super(host); + this.#dataOwner = dataOwner; + this.#variantId = variantId ?? UmbVariantId.CreateInvariant(); + + this.observe(this.#dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { + this.#propertyVariantIdPromise ??= new Promise((resolve) => { + this.#propertyVariantIdPromiseResolver = resolve as any; + }); + const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); + this.#propertyVariantIdMap.setValue(map); + // Resolve promise, to let the once waiting on this know. + if (this.#propertyVariantIdPromiseResolver) { + this.#propertyVariantIdPromise = undefined; + this.#propertyVariantIdPromiseResolver(); + this.#propertyVariantIdPromiseResolver = undefined; + } + }); + } + + #createPropertyVariantId(property: UmbPropertyTypeModel) { + return UmbVariantId.Create({ + culture: property.variesByCulture ? this.#variantId.culture : null, + segment: property.variesBySegment ? this.#variantId.segment : null, + }); + } + + #propertiesObservable?: Observable>; + // Should it be possible to get the properties as a list of property aliases? + get properties(): Observable> { + if (!this.#propertiesObservable) { + this.#propertiesObservable = mergeObservables( + [this._propertyVariantIdMap, this.#dataOwner.values], + this.#mergeVariantIdsAndValues, + ); + } + + return this.#propertiesObservable; + } + + #mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, Array | undefined]) { + const r: Array = []; + if (values) { + for (const prop of props) { + const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v)); + if (f) { + r.push(f); + } + } + } + return r; + } + + async getProperties(): Promise> { + await this.#propertyVariantIdPromise; + return this.#mergeVariantIdsAndValues([this.#propertyVariantIdMap.getValue(), this.#dataOwner.getValues()]); + } + + /** + * @function propertyVariantId + * @param {string} propertyAlias - The property alias to observe the variantId of. + * @returns {Promise | undefined>} - The observable for this properties variantId. + * @description Get an Observable for the variant id of this property. + */ + async propertyVariantId(propertyAlias: string) { + return createObservablePart( + this._propertyVariantIdMap, + (x) => x.find((v) => v.alias === propertyAlias)?.variantId, + classEqualMemoization, + ); + } + + /** + * @function propertyValueByAlias + * @param {string} propertyAlias The alias of the property + * @returns {Promise | undefined>} - An observable of the property value + * @description Get an Observable for the value of this property. + */ + async propertyValueByAlias( + propertyAlias: string, + ): Promise | undefined> { + await this.#dataOwner.isLoaded(); + await this.#propertyVariantIdPromise; + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + if (propVariantId) { + return this.#dataOwner.propertyValueByAlias(propertyAlias, propVariantId.variantId); + } + return; + } + + async propertyValueByAliasAndVariantId( + propertyAlias: string, + propertyVariantId: UmbVariantId, + ): Promise | undefined> { + return this.#dataOwner.propertyValueByAlias(propertyAlias, propertyVariantId); + } + + /** + * @function setPropertyValueByVariant + * @param {string} propertyAlias - The alias of the property + * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. + * @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for. + * @returns {Promise} - A promise that resolves once the value has been set. + * @description Get the value of this property. + */ + setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise { + return this.#dataOwner.setPropertyValue(propertyAlias, value, propertyVariantId); + } + + /** + * @function setPropertyValue + * @param {string} propertyAlias - The alias for the value to be set + * @param {PromiseLike} value - value can be a promise resolving into the actual value or the raw value it self. + * @returns {Promise} + * @description Set the value of this property. + */ + async setPropertyValue(propertyAlias: string, value: PromiseLike) { + this.#dataOwner.initiatePropertyValueChange(); + await this.#propertyVariantIdPromise; + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + if (propVariantId) { + return this.#dataOwner.setPropertyValue(propertyAlias, await value, propVariantId.variantId); + } + this.#dataOwner.finishPropertyValueChange(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/index.ts new file mode 100644 index 0000000000..f590f322ce --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/index.ts @@ -0,0 +1,2 @@ +export * from './content-data-manager.js'; +export * from './element-data-manager.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index e5187fc269..09a35613ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -1,228 +1,57 @@ import type { UmbContentWorkspaceContext } from '../workspace/index.js'; import type { UmbContentDetailModel } from '../types.js'; -import type { UmbNameablePropertyDatasetContext, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; -import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { UmbElementPropertyDatasetContext } from './element-property-dataset.context.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -import { type Observable, map } from '@umbraco-cms/backoffice/external/rxjs'; -import { - UmbBasicState, - UmbBooleanState, - UmbObjectState, - classEqualMemoization, - createObservablePart, - mergeObservables, -} from '@umbraco-cms/backoffice/observable-api'; -import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; -import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import type { UmbWorkspaceUniqueType } from '@umbraco-cms/backoffice/workspace'; - -type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>; +import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbEntityVariantModel, UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; export class UmbContentPropertyDatasetContext< - ContentModel extends UmbContentDetailModel = UmbContentDetailModel, - ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, - VariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel, - > - extends UmbContextBase - implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext -{ - #workspace: UmbContentWorkspaceContext; - #variantId: UmbVariantId; - public getVariantId() { - return this.#variantId; - } - - #currentVariant = new UmbObjectState(undefined); + ContentModel extends UmbContentDetailModel = UmbContentDetailModel, + ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, + VariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel, +> extends UmbElementPropertyDatasetContext< + ContentModel, + ContentTypeModel, + UmbContentWorkspaceContext +> { + // + #currentVariant = new UmbObjectState(undefined); currentVariant = this.#currentVariant.asObservable(); name = this.#currentVariant.asObservablePart((x) => x?.name); culture = this.#currentVariant.asObservablePart((x) => x?.culture); segment = this.#currentVariant.asObservablePart((x) => x?.segment); - // eslint-disable-next-line no-unused-private-class-members - #propertyVariantIdPromise?: Promise; - #propertyVariantIdPromiseResolver?: () => void; - #propertyVariantIdMap = new UmbBasicState([]); - private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable(); - - #readOnly = new UmbBooleanState(false); - public readOnly = this.#readOnly.asObservable(); - - getEntityType(): string { - return this.#workspace.getEntityType(); - } - getUnique(): UmbWorkspaceUniqueType | undefined { - return this.#workspace.getUnique(); - } getName(): string | undefined { - return this.#workspace.getName(this.#variantId); + return this._dataOwner.getName(this.getVariantId()); } setName(name: string) { - this.#workspace.setName(name, this.#variantId); + this._dataOwner.setName(name, this.getVariantId()); } + /** + * @deprecated Its not clear why we have this. We should either document the need better or get rid of it. + * @returns {UmbEntityVariantModel | undefined} - gives information about the current variant. + */ getVariantInfo() { - return this.#workspace.getVariant(this.#variantId); - } - - getReadOnly() { - return this.#readOnly.getValue(); + return this._dataOwner.getVariant(this.getVariantId()); } constructor( host: UmbControllerHost, - workspace: UmbContentWorkspaceContext, + dataOwner: UmbContentWorkspaceContext, variantId?: UmbVariantId, ) { // The controller alias, is a very generic name cause we want only one of these for this controller host. - super(host, UMB_PROPERTY_DATASET_CONTEXT); - this.#workspace = workspace; - this.#variantId = variantId ?? UmbVariantId.CreateInvariant(); + super(host, dataOwner, variantId); this.observe( - this.#workspace.variantById(this.#variantId), + this._dataOwner.variantById(this.getVariantId()), async (variantInfo) => { if (!variantInfo) return; this.#currentVariant.setValue(variantInfo); }, '_observeActiveVariant', ); - - this.observe( - this.#workspace.readOnlyState.states, - (states) => { - const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId)); - this.#readOnly.setValue(isReadOnly); - }, - 'umbObserveReadOnlyStates', - ); - - // TODO: Refactor this into a separate manager/controller of some sort? [NL] - this.observe(this.#workspace.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { - this.#propertyVariantIdPromise ??= new Promise((resolve) => { - this.#propertyVariantIdPromiseResolver = resolve as any; - }); - const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); - this.#propertyVariantIdMap.setValue(map); - // Resolve promise, to let the once waiting on this know. - if (this.#propertyVariantIdPromiseResolver) { - this.#propertyVariantIdPromise = undefined; - this.#propertyVariantIdPromiseResolver(); - this.#propertyVariantIdPromiseResolver = undefined; - } - }); - } - - #createPropertyVariantId(property: UmbPropertyTypeModel) { - return UmbVariantId.Create({ - culture: property.variesByCulture ? this.#variantId.culture : null, - segment: property.variesBySegment ? this.#variantId.segment : null, - }); - } - - #propertiesObservable?: Observable; - // Should it be possible to get the properties as a list of property aliases? - get properties(): Observable { - if (!this.#propertiesObservable) { - this.#propertiesObservable = mergeObservables( - [this._propertyVariantIdMap, this.#workspace.values], - this.#mergeVariantIdsAndValues, - ); - } - - return this.#propertiesObservable; - } - - #mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, ContentModel['values'] | undefined]) { - const r: ContentModel['values'] = []; - if (values) { - for (const prop of props) { - const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v)); - if (f) { - r.push(f); - } - } - } - return r; - } - - async getProperties(): Promise { - await this.#propertyVariantIdPromise; - return this.#mergeVariantIdsAndValues([this.#propertyVariantIdMap.getValue(), this.#workspace.getValues()]); - } - - /** - * @function propertyVariantId - * @param {string} propertyAlias - The property alias to observe the variantId of. - * @returns {Promise | undefined>} - The observable for this properties variantId. - * @description Get an Observable for the variant id of this property. - */ - async propertyVariantId(propertyAlias: string) { - /* - return (await this.#workspace.structure.propertyStructureByAlias(propertyAlias)).pipe( - map((property) => (property ? this.#createPropertyVariantId(property) : undefined)), - ); - */ - return createObservablePart( - this._propertyVariantIdMap, - (x) => x.find((v) => v.alias === propertyAlias)?.variantId, - classEqualMemoization, - ); - } - - /** - * @function propertyValueByAlias - * @param {string} propertyAlias The alias of the property - * @returns {Promise | undefined>} - An observable of the property value - * @description Get an Observable for the value of this property. - */ - async propertyValueByAlias( - propertyAlias: string, - ): Promise | undefined> { - await this.#workspace.isLoaded(); - await this.#propertyVariantIdPromise; - const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); - if (propVariantId) { - return this.#workspace.propertyValueByAlias(propertyAlias, propVariantId.variantId); - } - return; - } - - // TODO: Refactor: Not used currently, but should investigate if we can implement this, to spare some energy. - async propertyValueByAliasAndVariantId( - propertyAlias: string, - propertyVariantId: UmbVariantId, - ): Promise | undefined> { - return this.#workspace.propertyValueByAlias(propertyAlias, propertyVariantId); - } - - /** - * @function setPropertyValueByVariant - * @param {string} propertyAlias - The alias of the property - * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. - * @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for. - * @returns {Promise} - A promise that resolves once the value has been set. - * @description Get the value of this property. - */ - setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise { - return this.#workspace.setPropertyValue(propertyAlias, value, propertyVariantId); - } - - /** - * @function setPropertyValue - * @param {string} propertyAlias - The alias for the value to be set - * @param {PromiseLike} value - value can be a promise resolving into the actual value or the raw value it self. - * @returns {Promise} - * @description Set the value of this property. - */ - async setPropertyValue(propertyAlias: string, value: PromiseLike) { - this.#workspace.initiatePropertyValueChange(); - await this.#propertyVariantIdPromise; - const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); - if (propVariantId) { - return this.#workspace.setPropertyValue(propertyAlias, await value, propVariantId.variantId); - } - this.#workspace.finishPropertyValueChange(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-data-owner.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-data-owner.interface.ts new file mode 100644 index 0000000000..142f7172de --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-data-owner.interface.ts @@ -0,0 +1,36 @@ +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; +import type { UmbContentTypeModel, UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type'; +import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; +import type { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; + +/** + * The data supplier for a Element Property Dataset + */ +export interface UmbElementPropertyDataOwner< + ContentModel extends { values: Array }, + ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, +> extends UmbApi { + unique: Observable; + getUnique(): UmbEntityUnique | undefined; + getEntityType(): string; + readonly structure: UmbContentTypeStructureManager; + readonly values: Observable; + getValues(): ContentModel['values'] | undefined; + + isLoaded(): Promise | undefined; + readonly readOnlyState: UmbReadOnlyVariantStateManager; + + // Same as from UmbVariantDatasetWorkspaceContext, could be refactored later [NL] + propertyValueByAlias( + alias: string, + variantId?: UmbVariantId, + ): Promise | undefined>; + getPropertyValue(alias: string, variantId?: UmbVariantId): ReturnValue | undefined; + setPropertyValue(alias: string, value: unknown, variantId?: UmbVariantId): Promise; + + initiatePropertyValueChange(): void; + finishPropertyValueChange(): void; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts new file mode 100644 index 0000000000..7cf6c376e0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts @@ -0,0 +1,208 @@ +import type { UmbElementDetailModel } from '../types.js'; +import type { UmbElementPropertyDataOwner } from './element-property-data-owner.interface.js'; +import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import { + UmbBasicState, + UmbBooleanState, + classEqualMemoization, + createObservablePart, + mergeObservables, +} from '@umbraco-cms/backoffice/observable-api'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; + +type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>; + +export abstract class UmbElementPropertyDatasetContext< + ContentModel extends UmbElementDetailModel = UmbElementDetailModel, + ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, + DataOwnerType extends UmbElementPropertyDataOwner = UmbElementPropertyDataOwner< + ContentModel, + ContentTypeModel + >, + > + extends UmbContextBase + implements UmbPropertyDatasetContext +{ + protected readonly _dataOwner: DataOwnerType; + #variantId: UmbVariantId; + public getVariantId() { + return this.#variantId; + } + + abstract name: Observable; + abstract culture: Observable; + abstract segment: Observable; + + // eslint-disable-next-line no-unused-private-class-members + #propertyVariantIdPromise?: Promise; + #propertyVariantIdPromiseResolver?: () => void; + #propertyVariantIdMap = new UmbBasicState([]); + private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable(); + + #readOnly = new UmbBooleanState(false); + public readOnly = this.#readOnly.asObservable(); + + getEntityType(): string { + return this._dataOwner.getEntityType(); + } + getUnique(): UmbEntityUnique | undefined { + return this._dataOwner.getUnique(); + } + abstract getName(): string | undefined; + + getReadOnly() { + return this.#readOnly.getValue(); + } + + constructor(host: UmbControllerHost, dataOwner: DataOwnerType, variantId?: UmbVariantId) { + // The controller alias, is a very generic name cause we want only one of these for this controller host. + super(host, UMB_PROPERTY_DATASET_CONTEXT); + this._dataOwner = dataOwner; + this.#variantId = variantId ?? UmbVariantId.CreateInvariant(); + + this.observe( + this._dataOwner.readOnlyState.states, + (states) => { + const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId)); + this.#readOnly.setValue(isReadOnly); + }, + 'umbObserveReadOnlyStates', + ); + + // TODO: Refactor this into a separate manager/controller of some sort? [NL] + this.observe(this._dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { + this.#propertyVariantIdPromise ??= new Promise((resolve) => { + this.#propertyVariantIdPromiseResolver = resolve as any; + }); + const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); + this.#propertyVariantIdMap.setValue(map); + // Resolve promise, to let the once waiting on this know. + if (this.#propertyVariantIdPromiseResolver) { + this.#propertyVariantIdPromise = undefined; + this.#propertyVariantIdPromiseResolver(); + this.#propertyVariantIdPromiseResolver = undefined; + } + }); + } + + #createPropertyVariantId(property: UmbPropertyTypeModel) { + return UmbVariantId.Create({ + culture: property.variesByCulture ? this.#variantId.culture : null, + segment: property.variesBySegment ? this.#variantId.segment : null, + }); + } + + #propertiesObservable?: Observable; + // Should it be possible to get the properties as a list of property aliases? + get properties(): Observable { + if (!this.#propertiesObservable) { + this.#propertiesObservable = mergeObservables( + [this._propertyVariantIdMap, this._dataOwner.values], + this.#mergeVariantIdsAndValues, + ); + } + + return this.#propertiesObservable; + } + + #mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, ContentModel['values'] | undefined]) { + const r: ContentModel['values'] = []; + if (values) { + for (const prop of props) { + const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v)); + if (f) { + r.push(f); + } + } + } + return r as ContentModel['values']; + } + + async getProperties(): Promise { + await this.#propertyVariantIdPromise; + return this.#mergeVariantIdsAndValues([ + this.#propertyVariantIdMap.getValue(), + this._dataOwner.getValues(), + ]) as ContentModel['values']; + } + + /** + * @function propertyVariantId + * @param {string} propertyAlias - The property alias to observe the variantId of. + * @returns {Promise | undefined>} - The observable for this properties variantId. + * @description Get an Observable for the variant id of this property. + */ + async propertyVariantId(propertyAlias: string) { + /* + return (await this.#workspace.structure.propertyStructureByAlias(propertyAlias)).pipe( + map((property) => (property ? this.#createPropertyVariantId(property) : undefined)), + ); + */ + return createObservablePart( + this._propertyVariantIdMap, + (x) => x.find((v) => v.alias === propertyAlias)?.variantId, + classEqualMemoization, + ); + } + + /** + * @function propertyValueByAlias + * @param {string} propertyAlias The alias of the property + * @returns {Promise | undefined>} - An observable of the property value + * @description Get an Observable for the value of this property. + */ + async propertyValueByAlias( + propertyAlias: string, + ): Promise | undefined> { + await this._dataOwner.isLoaded(); + await this.#propertyVariantIdPromise; + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + if (propVariantId) { + return this._dataOwner.propertyValueByAlias(propertyAlias, propVariantId.variantId); + } + return; + } + + // TODO: Refactor: Not used currently, but should investigate if we can implement this, to spare some energy. + async propertyValueByAliasAndVariantId( + propertyAlias: string, + propertyVariantId: UmbVariantId, + ): Promise | undefined> { + return this._dataOwner.propertyValueByAlias(propertyAlias, propertyVariantId); + } + + /** + * @function setPropertyValueByVariant + * @param {string} propertyAlias - The alias of the property + * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. + * @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for. + * @returns {Promise} - A promise that resolves once the value has been set. + * @description Get the value of this property. + */ + setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise { + return this._dataOwner.setPropertyValue(propertyAlias, value, propertyVariantId); + } + + /** + * @function setPropertyValue + * @param {string} propertyAlias - The alias for the value to be set + * @param {PromiseLike} value - value can be a promise resolving into the actual value or the raw value it self. + * @returns {Promise} + * @description Set the value of this property. + */ + async setPropertyValue(propertyAlias: string, value: PromiseLike) { + this._dataOwner.initiatePropertyValueChange(); + await this.#propertyVariantIdPromise; + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + if (propVariantId) { + return this._dataOwner.setPropertyValue(propertyAlias, await value, propVariantId.variantId); + } + this._dataOwner.finishPropertyValueChange(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/index.ts new file mode 100644 index 0000000000..69c6bea4c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/index.ts @@ -0,0 +1,3 @@ +export * from './content-property-dataset.context.js'; +export * from './element-property-data-owner.interface.js'; +export * from './element-property-dataset.context.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts index e049e2250a..a1e7c8cd01 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts @@ -1,11 +1,17 @@ import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; -export interface UmbContentValueModel extends UmbPropertyValueData { +export interface UmbElementDetailModel { + values: Array; +} + +export interface UmbElementValueModel extends UmbPropertyValueData { editorAlias: string; culture: string | null; segment: string | null; } +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbContentValueModel extends UmbElementValueModel {} export interface UmbPotentialContentValueModel extends UmbPropertyValueData { editorAlias?: string; @@ -13,9 +19,12 @@ export interface UmbPotentialContentValueModel extends UmbP segment?: string | null; } -export interface UmbContentDetailModel { +export interface UmbContentDetailModel extends UmbElementDetailModel { unique: string; entityType: string; - values: Array; variants: Array; } + +export interface UmbContentLikeDetailModel + extends UmbElementDetailModel, + Partial> {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts index 1d092e2c73..ecaeca41a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace-context.interface.ts @@ -1,7 +1,6 @@ -import type { UmbContentDetailModel } from '@umbraco-cms/backoffice/content'; +import type { UmbContentDetailModel, UmbElementPropertyDataOwner } from '@umbraco-cms/backoffice/content'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; import type { UmbVariantId, UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant'; import type { UmbPropertyStructureWorkspaceContext, @@ -13,13 +12,13 @@ export interface UmbContentWorkspaceContext< ContentModel extends UmbContentDetailModel = UmbContentDetailModel, ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, VariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel, -> extends UmbRoutableWorkspaceContext, +> extends UmbElementPropertyDataOwner, + UmbRoutableWorkspaceContext, UmbVariantDatasetWorkspaceContext, UmbPropertyStructureWorkspaceContext { readonly IS_CONTENT_WORKSPACE_CONTEXT: true; - readonly readOnlyState: UmbReadOnlyVariantStateManager; - readonly values: Observable; - getValues(): ContentModel['values'] | undefined; + //readonly values: Observable; + //getValues(): ContentModel['values'] | undefined; // Data: getData(): ContentModel | undefined; @@ -27,6 +26,6 @@ export interface UmbContentWorkspaceContext< isLoaded(): Promise | undefined; variantById(variantId: UmbVariantId): Observable; - initiatePropertyValueChange(): void; - finishPropertyValueChange(): void; + //initiatePropertyValueChange(): void; + //finishPropertyValueChange(): void; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts index 858c6197e1..b9bcfe9751 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts @@ -1,6 +1,6 @@ import { UmbPropertyTypeWorkspaceEditorElement } from './property-type-workspace-editor.element.js'; import type { UmbPropertyTypeWorkspaceData } from './property-type-workspace.modal-token.js'; -import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import type { UmbPropertyDatasetContext, UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; import type { UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext, @@ -11,6 +11,7 @@ import { UmbInvariantWorkspacePropertyDatasetContext, UmbWorkspaceIsNewRedirectController, UmbWorkspaceIsNewRedirectControllerAlias, + umbObjectToPropertyValueArray, } from '@umbraco-cms/backoffice/workspace'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -18,6 +19,7 @@ import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type' import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content-type'; import { UmbId } from '@umbraco-cms/backoffice/id'; import { UmbValidationContext } from '@umbraco-cms/backoffice/validation'; +import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; export class UmbPropertyTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase @@ -39,6 +41,13 @@ export class UmbPropertyTypeWorkspaceContext data?.name); readonly unique = this.#data.asObservablePart((data) => data?.id); + readonly values = this.#data.asObservablePart((data) => { + return umbObjectToPropertyValueArray(data); + }); + async getValues(): Promise | undefined> { + return umbObjectToPropertyValueArray(await firstValueFrom(this.data)); + } + constructor(host: UmbControllerHost, args: { manifest: ManifestWorkspace }) { super(host, args.manifest.alias); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts index 2989a8e596..6338b44a49 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts @@ -94,7 +94,7 @@ export class UmbPropertyDatasetContextBase /** * @returns {Array} - Array of properties as objects with alias and value properties. */ - getProperties() { + async getProperties() { return this.#properties.getValue(); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts index 377cc7cf7f..d7647ae806 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts @@ -1,16 +1,16 @@ import { UMB_ENTITY_WORKSPACE_CONTEXT } from '../../contexts/index.js'; -import type { UmbWorkspaceUniqueType } from '../../types.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state, nothing, query } from '@umbraco-cms/backoffice/external/lit'; import type { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UUIPopoverContainerElement } from '@umbraco-cms/backoffice/external/uui'; +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; @customElement('umb-workspace-entity-action-menu') export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement { private _workspaceContext?: typeof UMB_ENTITY_WORKSPACE_CONTEXT.TYPE; @state() - private _unique?: UmbWorkspaceUniqueType; + private _unique?: UmbEntityUnique; @state() private _entityType?: string; @@ -39,14 +39,14 @@ export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement { #onActionExecuted(event: UmbActionExecutedEvent) { event.stopPropagation(); - // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // TODO: This ignorer is just needed for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._popover?.hidePopover(); } #onPopoverToggle(event: ToggleEvent) { - // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // TODO: This ignorer is just needed for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._popoverOpen = event.newState === 'open'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/entity-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/entity-workspace-context.interface.ts index 46fa7a12c7..022b385e73 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/entity-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/tokens/entity-workspace-context.interface.ts @@ -1,8 +1,8 @@ import type { UmbWorkspaceContext } from '../../workspace-context.interface.js'; -import type { UmbWorkspaceUniqueType } from './../../types.js'; +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; export interface UmbEntityWorkspaceContext extends UmbWorkspaceContext { - unique: Observable; - getUnique(): UmbWorkspaceUniqueType | undefined; + unique: Observable; + getUnique(): UmbEntityUnique | undefined; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts index 568895229a..a07f81ae54 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/data-manager/workspace-data-manager.interface.ts @@ -1,8 +1,7 @@ import type { UmbController } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import type { MappingFunction, Observable } from '@umbraco-cms/backoffice/observable-api'; -export interface UmbWorkspaceDataManager extends UmbController { +export interface UmbWorkspaceDataManager extends UmbController { getPersisted(): ModelType | undefined; getCurrent(): ModelType | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts index baceb7e7c8..552dd59903 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts @@ -1,6 +1,5 @@ import type { UmbWorkspaceDataManager } from '../data-manager/workspace-data-manager.interface.js'; import { jsonStringComparison, UmbObjectState, type MappingFunction } from '@umbraco-cms/backoffice/observable-api'; -import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; /** @@ -10,7 +9,7 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; * @implements {UmbWorkspaceDataManager} * @template ModelType */ -export class UmbEntityWorkspaceDataManager +export class UmbEntityWorkspaceDataManager extends UmbControllerBase implements UmbWorkspaceDataManager { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts index 93c0e81b21..eae653cf08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/types.ts @@ -1,2 +1,7 @@ +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; + export type * from './extensions/types.js'; -export type UmbWorkspaceUniqueType = string | null; +/** + * @deprecated Use `UmbEntityUnique`instead. + */ +export type UmbWorkspaceUniqueType = UmbEntityUnique; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index d2c01bc008..cd1b9b5839 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -49,6 +49,11 @@ export class UmbDataTypeWorkspaceContext readonly propertyEditorUiAlias = this._data.createObservablePartOfCurrent((data) => data?.editorUiAlias); readonly propertyEditorSchemaAlias = this._data.createObservablePartOfCurrent((data) => data?.editorAlias); + readonly values = this._data.createObservablePartOfCurrent((data) => data?.values); + async getValues() { + return this._data.getCurrent()?.values; + } + #properties = new UmbArrayState([], (x) => x.alias).sortBy( (a, b) => (a.weight || 0) - (b.weight || 0), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts index 0c93761201..5b8d1ac93e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts @@ -2,7 +2,7 @@ import type { UmbDocumentBlueprintEntityType } from './entity.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export { UmbDocumentBlueprintVariantState }; export interface UmbDocumentBlueprintDetailModel { @@ -27,7 +27,7 @@ export interface UmbDocumentBlueprintUrlInfoModel { } // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbDocumentBlueprintValueModel extends UmbContentValueModel {} +export interface UmbDocumentBlueprintValueModel extends UmbElementValueModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbDocumentBlueprintVariantOptionModel diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts index 39c63629e1..02ef1bbdb4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts @@ -6,7 +6,7 @@ import type { } from '@umbraco-cms/backoffice/variant'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { DocumentVariantStateModel as UmbDocumentVariantState } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export { UmbDocumentVariantState }; export interface UmbDocumentDetailModel extends UmbContentDetailModel { @@ -34,7 +34,7 @@ export interface UmbDocumentUrlInfoModel { } // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbDocumentValueModel extends UmbContentValueModel {} +export interface UmbDocumentValueModel extends UmbElementValueModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbDocumentVariantOptionModel extends UmbEntityVariantOptionModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index ff92c1aa1f..4813b6a90e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -302,6 +302,7 @@ export class UmbDocumentWorkspaceContext async load(unique: string) { this.resetState(); this.#getDataPromise = this.repository.requestByUnique(unique); + type GetDataType = Awaited>; const { data, asObservable } = (await this.#getDataPromise) as GetDataType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts index c1bde82de5..b622c93b33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts @@ -1,7 +1,7 @@ import type { UmbMediaEntityType } from './entity.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export interface UmbMediaDetailModel extends UmbContentDetailModel { mediaType: { @@ -25,7 +25,7 @@ export interface UmbMediaUrlInfoModel { export interface UmbMediaVariantModel extends UmbEntityVariantModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbMediaValueModel extends UmbContentValueModel {} +export interface UmbMediaValueModel extends UmbElementValueModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbMediaVariantOptionModel extends UmbEntityVariantOptionModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index ca70bdbb59..db66e77104 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -1,7 +1,7 @@ import type { UmbMemberEntityType } from './entity.js'; import type { UmbMemberKindType } from './utils/index.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; -import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export interface UmbMemberDetailModel extends UmbContentDetailModel { email: string; @@ -28,7 +28,7 @@ export interface UmbMemberDetailModel extends UmbContentDetailModel { export interface UmbMemberVariantModel extends UmbEntityVariantModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbMemberValueModel extends UmbContentValueModel {} +export interface UmbMemberValueModel extends UmbElementValueModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbMemberVariantOptionModel extends UmbEntityVariantOptionModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts index b4ac6079e3..06a24a07ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts @@ -18,7 +18,6 @@ import { UmbWorkspaceIsNewRedirectController, UmbWorkspaceIsNewRedirectControllerAlias, UmbWorkspaceSplitViewManager, - umbObjectToPropertyValueArray, } from '@umbraco-cms/backoffice/workspace'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { @@ -35,7 +34,7 @@ import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; import { UmbContentWorkspaceDataManager, type UmbContentWorkspaceContext } from '@umbraco-cms/backoffice/content'; import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type'; -import { firstValueFrom, map } from '@umbraco-cms/backoffice/external/rxjs'; +import { map } from '@umbraco-cms/backoffice/external/rxjs'; import { UmbEntityContext, type UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UmbRequestReloadChildrenOfEntityEvent, diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/property-value-resolver/rte-block-value-resolver.api.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/property-value-resolver/rte-block-value-resolver.api.ts index fbf8f45d17..b9d77a5d15 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/property-value-resolver/rte-block-value-resolver.api.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/property-value-resolver/rte-block-value-resolver.api.ts @@ -4,11 +4,11 @@ import { type UmbBlockDataValueModel, type UmbBlockExposeModel, } from '@umbraco-cms/backoffice/block'; -import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export class UmbRteBlockValueResolver extends UmbBlockValueResolver { async processValues( - property: UmbContentValueModel, + property: UmbElementValueModel, valuesCallback: (values: Array) => Promise | undefined>, ) { if (property.value) { @@ -24,7 +24,7 @@ export class UmbRteBlockValueResolver extends UmbBlockValueResolver, + property: UmbElementValueModel, variantsCallback: (values: Array) => Promise | undefined>, ) { if (property.value) { From bb878d33f92062f808474b95db644d7d09f16b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 10:38:36 +0200 Subject: [PATCH 024/246] get name from entry context use it for block workspace --- .../block/block/context/block-entry.context.ts | 6 +++--- .../block/workspace/block-workspace.context.ts | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts index 3c30a4299d..a165867854 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts @@ -374,10 +374,10 @@ export abstract class UmbBlockEntryContext< /** * Get the current value of this Blocks label. - * @function getLabel + * @function getName * @returns {string} - the value of the label. */ - getLabel() { + getName() { return this.#labelRender.toString(); } @@ -610,7 +610,7 @@ export abstract class UmbBlockEntryContext< } async requestDelete() { - const blockName = this.getLabel(); + const blockName = this.getName(); // TODO: Localizations missing [NL] await umbConfirmModal(this, { headline: `Delete ${blockName}`, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index d850970f3c..5780c43426 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -23,6 +23,7 @@ import { UMB_BLOCK_MANAGER_CONTEXT, type UmbBlockWorkspaceOriginData, type UmbBlockWorkspaceData, + UMB_BLOCK_ENTRY_CONTEXT, } from '@umbraco-cms/backoffice/block'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; @@ -60,9 +61,8 @@ export class UmbBlockWorkspaceContext(undefined); - readonly name = this.#label.asObservable(); + #name = new UmbStringState(undefined); + readonly name = this.#name.asObservable(); #variantId = new UmbClassState(undefined); readonly variantId = this.#variantId.asObservable(); @@ -138,6 +138,10 @@ export class UmbBlockWorkspaceContext { + this.#name.setValue(context.getName()); + }); + this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { // TODO: Ideally we move this into the Block Manager [NL] To avoid binding the Block Manager to a Property... // If the current property is readonly all inner block content should also be readonly. @@ -199,7 +203,7 @@ export class UmbBlockWorkspaceContext Date: Fri, 11 Oct 2024 11:58:18 +0200 Subject: [PATCH 025/246] refactor inline --- .../block-grid-block-inline.element.ts | 148 ++++++++++++++++-- ...d-inline-property-dataset.context-token.ts | 6 - ...ck-grid-inline-property-dataset.context.ts | 73 --------- .../context/block-grid-entry.context.ts | 9 +- .../inline-list-block.element.ts | 113 ++++++++++--- .../block/workspace/block-element-manager.ts | 13 +- .../block-element-property-dataset.context.ts | 13 +- ...ace-view-edit-content-no-router.element.ts | 56 ------- .../property-dataset-base-context.ts | 1 - 9 files changed, 240 insertions(+), 192 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context-token.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 36be37cd9b..38dfb7f95e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -1,12 +1,26 @@ import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; -import { UmbBlockGridInlinePropertyDatasetContext } from './block-grid-inline-property-dataset.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import '../block-grid-areas-container/index.js'; import '../ref-grid-block/index.js'; import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; -import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import { + type UMB_BLOCK_WORKSPACE_CONTEXT, + UMB_BLOCK_WORKSPACE_ALIAS, + type UmbBlockDataType, +} from '@umbraco-cms/backoffice/block'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { + UmbExtensionApiInitializer, + UmbExtensionsApiInitializer, + type UmbApiConstructorArgumentsMethodType, +} from '@umbraco-cms/backoffice/extension-api'; +import { UmbLanguageItemRepository } from '@umbraco-cms/backoffice/language'; + +const apiArgsCreator: UmbApiConstructorArgumentsMethodType = (manifest: unknown) => { + return [{ manifest }]; +}; /** * @element umb-block-grid-block-inline @@ -14,15 +28,19 @@ import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; @customElement('umb-block-grid-block-inline') export class UmbBlockGridBlockInlineElement extends UmbLitElement { // + #blockContext?: typeof UMB_BLOCK_GRID_ENTRY_CONTEXT.TYPE; + #workspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; + #contentKey?: string; + @property({ attribute: false }) + config?: UmbBlockEditorCustomViewConfiguration; + + @property({ type: String, reflect: false }) label?: string; @property({ type: String, reflect: false }) icon?: string; - @property({ attribute: false }) - config?: UmbBlockEditorCustomViewConfiguration; - @property({ type: Boolean, reflect: true }) unpublished?: boolean; @@ -30,37 +48,133 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { content?: UmbBlockDataType; @state() - _inlineProperty: UmbPropertyTypeModel | undefined; + private _exposed?: boolean; + + @state() + _isOpen = false; + + @state() + _inlineProperty?: UmbPropertyTypeModel; + + @state() + private _ownerContentTypeName?: string; + + @state() + private _variantName?: string; constructor() { super(); - this.consumeContext(UMB_BLOCK_GRID_ENTRY_CONTEXT, (context) => { - new UmbBlockGridInlinePropertyDatasetContext(this, context); - + this.consumeContext(UMB_BLOCK_GRID_ENTRY_CONTEXT, (blockContext) => { + this.#blockContext = blockContext; this.observe( - context.firstPropertyType, - (property) => { - this._inlineProperty = property; + this.#blockContext.unique, + (contentKey) => { + this.#contentKey = contentKey; + this.#load(); }, - 'inlineProperty', + 'observeContentKey', ); }); + new UmbExtensionApiInitializer( + this, + umbExtensionsRegistry, + UMB_BLOCK_WORKSPACE_ALIAS, + apiArgsCreator, + (permitted, ctrl) => { + const context = ctrl.api as typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; + if (permitted && context) { + this.#workspaceContext = context; + this.#workspaceContext.establishLiveSync(); + + this.#load(); + + this.observe( + this.#workspaceContext.content.structure.contentTypeProperties, + (contentTypeProperties) => { + this._inlineProperty = contentTypeProperties[0]; + }, + 'observeProperties', + ); + + this.observe( + this.#workspaceContext.exposed, + (exposed) => { + this._exposed = exposed; + }, + 'observeExposed', + ); + + this.observe( + context.content.structure.ownerContentTypeName, + (name) => { + this._ownerContentTypeName = name; + }, + 'observeContentTypeName', + ); + + this.observe( + context.variantId, + async (variantId) => { + if (variantId) { + context.content.setup(this, variantId); + // TODO: Support segment name? + const culture = variantId.culture; + if (culture) { + const languageRepository = new UmbLanguageItemRepository(this); + const { data } = await languageRepository.requestItems([culture]); + const name = data?.[0].name; + this._variantName = name ? this.localize.string(name) : undefined; + } + } + }, + 'observeVariant', + ); + + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [ + this, + this.#workspaceContext, + ]); + } + }, + ); } + #load() { + if (!this.#workspaceContext || !this.#contentKey) return; + this.#workspaceContext.load(this.#contentKey); + } + + #expose = () => { + this.#workspaceContext?.expose(); + }; + override render() { return html` - - + ${this.#renderInside()} `; } + #renderInside() { + if (this._exposed === false) { + return html` + `; + } else { + return html` + `; + } + } + static override styles = [ css` umb-block-grid-areas-container { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context-token.ts deleted file mode 100644 index 56cb885b93..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context-token.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { UmbBlockGridInlinePropertyDatasetContext } from './block-grid-inline-property-dataset.context.js'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; - -// TODO: Add discriminator: -export const UMB_BLOCK_GRID_INLINE_PROPERTY_DATASET_CONTEXT = - new UmbContextToken('UmbPropertyDatasetContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts deleted file mode 100644 index a320f9914a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; -import { UMB_BLOCK_GRID_INLINE_PROPERTY_DATASET_CONTEXT } from './block-grid-inline-property-dataset.context-token.js'; -import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; -import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; - -export class UmbBlockGridInlinePropertyDatasetContext extends UmbControllerBase implements UmbPropertyDatasetContext { - #entryContext: UmbBlockGridEntryContext; - - #readOnly = new UmbBooleanState(false); - public readOnly = this.#readOnly.asObservable(); - - // default data: - - getVariantId() { - return UmbVariantId.CreateInvariant(); - } - getEntityType() { - return this.#entryContext.getEntityType(); - } - getUnique() { - return this.#entryContext.getUnique(); - } - - getName(): string | undefined { - return 'TODO: get label'; - } - readonly name: Observable = 'TODO: get label observable' as any; - - constructor(host: UmbControllerHost, entryContext: UmbBlockGridEntryContext) { - // The controller alias, is a very generic name cause we want only one of these for this controller host. - super(host, UMB_PROPERTY_DATASET_CONTEXT.toString()); - this.#entryContext = entryContext; - - this.provideContext(UMB_BLOCK_GRID_INLINE_PROPERTY_DATASET_CONTEXT, this); - } - - /** - * @function propertyValueByAlias - * @param {string} propertyAlias - * @returns {Promise | undefined>} - * @description Get an Observable for the value of this property. - */ - async propertyValueByAlias(propertyAlias: string) { - // TODO: Investigate how I do that with the workspaces.. - return await this.#entryContext.contentPropertyValueByAlias(propertyAlias); - } - - /** - * @function setPropertyValue - * @param {string} propertyAlias - * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. - * @returns {Promise} - * @description Set the value of this property. - */ - async setPropertyValue(propertyAlias: string, value: unknown) { - // TODO: Investigate how I do that with the workspaces.. - return this.#entryContext.setContentPropertyValue(propertyAlias, value); - } - - /** - * Gets the read-only state of the current variant culture. - * @returns {*} {boolean} - * @memberof UmbBlockGridInlinePropertyDatasetContext - */ - getReadOnly(): boolean { - return this.#readOnly.getValue(); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts index fdda04c514..a458b7f49c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts @@ -9,13 +9,11 @@ import { UmbArrayState, UmbBooleanState, UmbNumberState, - UmbObjectState, appendToFrozenArray, mergeObservables, observeMultiple, } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbBlockEntryContext } from '@umbraco-cms/backoffice/block'; import type { UmbBlockGridTypeModel, UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; @@ -68,9 +66,6 @@ export class UmbBlockGridEntryContext ([a, b]) => a === true && b === false, ); - #firstPropertyType = new UmbObjectState(undefined); - readonly firstPropertyType = this.#firstPropertyType.asObservable(); - readonly scaleManager = new UmbBlockGridScaleManager(this); constructor(host: UmbControllerHost) { @@ -253,9 +248,7 @@ export class UmbBlockGridEntryContext ); } - _gotContentType(contentType: UmbContentTypeModel | undefined) { - this.#firstPropertyType.setValue(contentType?.properties[0]); - } + _gotContentType() {} #calcColumnSpan(columnSpan: number, relevantColumnSpanOptions: number[], layoutColumns: number) { if (relevantColumnSpanOptions.length > 0) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts index 9c7ae7378f..b0685a4828 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts @@ -4,13 +4,22 @@ import { type UmbBlockDataType, type UMB_BLOCK_WORKSPACE_CONTEXT, } from '@umbraco-cms/backoffice/block'; -import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; +import { + UmbExtensionApiInitializer, + UmbExtensionsApiInitializer, + type UmbApiConstructorArgumentsMethodType, +} from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import '../../../block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.js'; +import { UmbLanguageItemRepository } from '@umbraco-cms/backoffice/language'; + +const apiArgsCreator: UmbApiConstructorArgumentsMethodType = (manifest: unknown) => { + return [{ manifest }]; +}; /** * @element umb-inline-list-block @@ -33,9 +42,18 @@ export class UmbInlineListBlockElement extends UmbLitElement { @property({ attribute: false }) content?: UmbBlockDataType; + @state() + private _exposed?: boolean; + @state() _isOpen = false; + @state() + private _ownerContentTypeName?: string; + + @state() + private _variantName?: string; + constructor() { super(); @@ -50,22 +68,60 @@ export class UmbInlineListBlockElement extends UmbLitElement { 'observeContentKey', ); }); - this.observe(umbExtensionsRegistry.byTypeAndAlias('workspace', UMB_BLOCK_WORKSPACE_ALIAS), (manifest) => { - if (manifest) { - createExtensionApi(this, manifest, [{ manifest: manifest }]).then((context) => { - if (context) { - this.#workspaceContext = context as typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; - this.#workspaceContext.establishLiveSync(); - this.#load(); - new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [ - this, - this.#workspaceContext, - ]); - } - }); - } - }); + new UmbExtensionApiInitializer( + this, + umbExtensionsRegistry, + UMB_BLOCK_WORKSPACE_ALIAS, + apiArgsCreator, + (permitted, ctrl) => { + const context = ctrl.api as typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; + if (permitted && context) { + this.#workspaceContext = context; + this.#workspaceContext.establishLiveSync(); + this.#load(); + + this.observe( + this.#workspaceContext.exposed, + (exposed) => { + this._exposed = exposed; + }, + 'observeExposed', + ); + + this.observe( + context.content.structure.ownerContentTypeName, + (name) => { + this._ownerContentTypeName = name; + }, + 'observeContentTypeName', + ); + + this.observe( + context.variantId, + async (variantId) => { + if (variantId) { + context.content.setup(this, variantId); + // TODO: Support segment name? + const culture = variantId.culture; + if (culture) { + const languageRepository = new UmbLanguageItemRepository(this); + const { data } = await languageRepository.requestItems([culture]); + const name = data?.[0].name; + this._variantName = name ? this.localize.string(name) : undefined; + } + } + }, + 'observeVariant', + ); + + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [ + this, + this.#workspaceContext, + ]); + } + }, + ); } #load() { @@ -73,6 +129,10 @@ export class UmbInlineListBlockElement extends UmbLitElement { this.#workspaceContext.load(this.#contentKey); } + #expose = () => { + this.#workspaceContext?.expose(); + }; + override render() { return html`
@@ -89,18 +149,16 @@ export class UmbInlineListBlockElement extends UmbLitElement { this._isOpen = !this._isOpen; }}> - ${this.#renderContent()} + ${this.#renderBlockInfo()} - ${this._isOpen === true - ? html`` - : ''} + ${this._isOpen === true ? this.#renderInside() : ''}
`; } - #renderContent() { + #renderBlockInfo() { return html` @@ -113,6 +171,19 @@ export class UmbInlineListBlockElement extends UmbLitElement { `; } + #renderInside() { + if (this._exposed === false) { + return html` + `; + } else { + return html``; + } + } + static override styles = [ UmbTextStyles, css` diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index 9c9f33b029..352701d1c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -1,5 +1,6 @@ -import type { UmbBlockDataModel, UmbBlockDataValueModel } from '../types.js'; +import type { UmbBlockDataModel, UmbBlockDataValueModel, UmbBlockLayoutBaseModel } from '../types.js'; import { UmbBlockElementPropertyDatasetContext } from './block-element-property-dataset.context.js'; +import type { UmbBlockWorkspaceContext } from './block-workspace.context.js'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type'; import { @@ -18,7 +19,7 @@ import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type'; -export class UmbBlockElementManager +export class UmbBlockElementManager extends UmbControllerBase implements UmbElementPropertyDataOwner { @@ -37,6 +38,8 @@ export class UmbBlockElementManager #variantId = new UmbClassState(undefined); readonly variantId = this.#variantId.asObservable(); + readonly name; + readonly getName; readonly unique = this.#data.createObservablePartOfCurrent((data) => data?.key); readonly contentTypeId = this.#data.createObservablePartOfCurrent((data) => data?.contentTypeKey); @@ -55,9 +58,13 @@ export class UmbBlockElementManager readonly validation = new UmbValidationController(this); - constructor(host: UmbControllerHost, dataPathPropertyName: string) { + constructor(host: UmbBlockWorkspaceContext, dataPathPropertyName: string) { super(host); + // Ugly, but we just inherit these from the workspace context: [NL] + this.name = host.name; + this.getName = host.getName; + this.observe(this.contentTypeId, (id) => this.structure.loadType(id)); this.observe(this.unique, (key) => { if (key) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts index 89e7a7fd9f..34e17f069a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts @@ -9,19 +9,18 @@ export class UmbBlockElementPropertyDatasetContext extends UmbElementPropertyDatasetContext implements UmbPropertyDatasetContext { - name; - culture; - segment; - - getName(): string { - return 'Block'; - } + readonly name; + readonly culture; + readonly segment; + readonly getName; constructor(host: UmbControllerHost, elementManager: UmbBlockElementManager, variantId?: UmbVariantId) { // The controller alias, is a very generic name cause we want only one of these for this controller host. super(host, elementManager, variantId); + // Ugly, but we just inherit these from the workspace context: [NL] this.name = elementManager.name; + this.getName = elementManager.getName; this.culture = createObservablePart(elementManager.variantId, (v) => v?.culture); this.segment = createObservablePart(elementManager.variantId, (v) => v?.segment); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts index 3d1b2dcdb9..652400020c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts @@ -6,7 +6,6 @@ import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbPropertyTypeContainerModel } from '@umbraco-cms/backoffice/content-type'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/workspace'; -import { UmbLanguageItemRepository } from '@umbraco-cms/backoffice/language'; /** * @element umb-block-workspace-view-edit-content-no-router @@ -29,15 +28,6 @@ export class UmbBlockWorkspaceViewEditContentNoRouterElement extends UmbLitEleme //@state() //private _activeTabName?: string | null | undefined; - @state() - private _ownerContentTypeName?: string; - - @state() - private _variantName?: string; - - @state() - private _exposed?: boolean; - #blockWorkspace?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; #tabsStructureHelper = new UmbContentTypeContainerStructureHelper(this); @@ -58,40 +48,6 @@ export class UmbBlockWorkspaceViewEditContentNoRouterElement extends UmbLitEleme this.#tabsStructureHelper.setStructureManager(context.content.structure); this.#observeRootGroups(); - - this.observe( - context.content.structure.ownerContentTypeName, - (name) => { - this._ownerContentTypeName = name; - }, - 'observeContentTypeName', - ); - - this.observe( - context.variantId, - async (variantId) => { - if (variantId) { - context.content.setup(this, variantId); - // TODO: Support segment name? - const culture = variantId.culture; - if (culture) { - const languageRepository = new UmbLanguageItemRepository(this); - const { data } = await languageRepository.requestItems([culture]); - const name = data?.[0].name; - this._variantName = name ? this.localize.string(name) : undefined; - } - } - }, - 'observeVariant', - ); - - this.observe( - context.exposed, - (exposed) => { - this._exposed = exposed; - }, - 'observeExposed', - ); }); } @@ -128,19 +84,7 @@ export class UmbBlockWorkspaceViewEditContentNoRouterElement extends UmbLitEleme this._activeTabId = tabId; } - #expose = () => { - this.#blockWorkspace?.expose(); - }; - override render() { - if (this._exposed === false) { - return html` - `; - } if (!this._tabs) return; return html` ${this._tabs.length > 1 || (this._tabs.length === 1 && this._hasRootGroups) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts index 6338b44a49..7b7a4c2822 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts @@ -107,7 +107,6 @@ export class UmbPropertyDatasetContextBase /** * Gets the read-only state of the current variant culture. * @returns {*} {boolean} - * @memberof UmbBlockGridInlinePropertyDatasetContext */ getReadOnly(): boolean { return this.#readOnly.getValue(); From 01d6103822a4b559df5ad6fb064e61b73b9ae7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 13:02:58 +0200 Subject: [PATCH 026/246] lint --- .../src/assets/lang/ar.ts | 3160 +++++++++-------- .../element-property-dataset.context.ts | 1 - .../packages/core/localization/manifests.ts | 2 +- .../section-sidebar-menu.element.ts | 2 +- .../section-sidebar-context-menu.element.ts | 2 +- ...object-to-property-value-array.function.ts | 2 +- ...-tiny-mce-toolbar-configuration.element.ts | 14 +- .../grid/user-grid-collection-view.element.ts | 3 +- 8 files changed, 1637 insertions(+), 1549 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts index 64bb555510..5f57427859 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts @@ -1,541 +1,561 @@ import type { UmbLocalizationDictionary } from '@umbraco-cms/backoffice/localization-api'; export default { - actions: { - assigndomain: 'الثقافة وأسماء النطاقات', - auditTrail: 'سجل التدقيق', - browse: 'تصفح ', - changeDataType: 'تغيير نوع البيانات', - changeDocType: 'تغيير نوع الوثيقة', - chooseWhereToCopy: 'اختر مكان النسخ', - chooseWhereToImport: 'اختر مكان الاستيراد', - chooseWhereToMove: 'اختر مكان النقل', - copy: 'نسخ', - copyTo: 'نسخ إلى', - create: 'إنشاء', - createblueprint: 'إنشاء مخطط انشائي للمستند', - createGroup: 'إنشاء مجموعة', - createPackage: 'إنشاء حزمة', - delete: 'حذف', - disable: 'تعطيل', - editContent: 'تحرير المحتوى', - editSettings: 'تحرير الإعدادات', - emptyrecyclebin: 'إفراغ سلة المحذوفات', - enable: 'تمكين', - export: 'تصدير', - exportDocumentType: 'تصدير نوع الوثيقة', - folderCreate: 'إنشاء مجلد', - folderDelete: 'حذف مجلد', - folderRename: 'إعادة تسمية مجلد', - import: 'استيراد', - importdocumenttype: 'استيراد نوع وثيقة', - importPackage: 'استيراد حزمة', - infiniteEditorChooseWhereToCopy: 'اختر مكان نسخ العنصر (العناصر) المحددة', - infiniteEditorChooseWhereToMove: 'اختر مكان نقل العنصر (العناصر) المحددة', - liveEdit: 'تحرير مباشر', - logout: 'تسجيل خروج', - move: 'نقل إلى', - notify: 'الإشعارات', - protect: 'الوصول العام', - publish: 'نشر', - refreshNode: 'إعادة تحميل', - remove: 'إزالة', - rename: 'إعادة تسمية', - republish: 'إعادة نشر الموقع بالكامل', - resendInvite: 'إعادة إرسال الدعوة', - restore: 'استعادة', - rights: 'الأذونات', - rollback: 'التراجع', - sendtopublish: 'إرسال للنشر', - sendToTranslate: 'إرسال للترجمة', - setGroup: 'تعيين مجموعة', - setPermissions: 'تعيين الأذونات', - sort: 'ترتيب الابناء', - toInTheTreeStructureBelow: 'في هيكل الشجري أدناه', - translate: 'ترجمة', - trash: 'سلة المهملات', - unlock: 'فتح القفل', - unpublish: 'إلغاء النشر', - update: 'تحديث', - wasCopiedTo: 'تم نسخه إلى', - wasDeleted: 'تم حذفه', - wasMovedTo: 'تم نقله إلى', - }, - actionCategories: { - content: 'المحتوى', - administration: 'الإدارة', - structure: 'الهيكل', - other: 'أخرى', - }, - actionDescriptions: { - assignDomain: 'السماح بالوصول لتعيين الثقافة وأسماء النطاقات', - auditTrail: 'السماح بالوصول لعرض سجل تاريخ العقدة', - browse: 'السماح بالوصول لعرض العقدة', - changeDocType: 'السماح بالوصول لتغيير نوع وثيقة للعقدة', - copy: 'السماح بالوصول لنسخ العقدة', - create: 'السماح بالوصول لإنشاء العقد', - delete: 'السماح بالوصول لحذف العقد', - move: 'السماح بالوصول لنقل العقدة', - protect: 'السماح بالوصول لتعيين وتغيير قيود الوصول للعقدة', - publish: 'السماح بالوصول لنشر العقدة', - unpublish: 'السماح بالوصول لإلغاء نشر العقدة', - rights: 'السماح بالوصول لتغيير الأذونات للعقدة', - rollback: 'السماح بالوصول للتراجع عن العقدة إلى حالة سابقة', - sendtopublish: 'السماح بالوصول لإرسال العقدة للموافقة قبل النشر', - sendToTranslate: 'السماح بالوصول لإرسال العقدة للترجمة', - sort: 'السماح بالوصول لتغيير ترتيب العقد', - translate: 'السماح بالوصول لترجمة العقدة', - update: 'السماح بالوصول لحفظ العقدة', - createblueprint: 'السماح بالوصول لإنشاء مخطط الوثيقة', - notify: 'السماح بالوصول لإعداد الإشعارات لعقد المحتوى', - }, - apps: { - umbContent: 'المحتوى', - umbInfo: 'المعلومات', - }, - assignDomain: { - permissionDenied: 'تم رفض الإذن.', - addNew: 'إضافة نطاق جديد', - addCurrent: 'إضافة النطاق الحالي', - remove: 'إزالة', - invalidNode: 'عقدة غير صالحة.', - invalidDomain: 'واحد أو أكثر من النطاقات لها تنسيق غير صالح.', - duplicateDomain: 'تم تعيين النطاق بالفعل.', - language: 'اللغة', - domain: 'النطاق', - domainCreated: "تم إنشاء النطاق الجديد '%0%'", - domainDeleted: "تم حذف النطاق '%0%'", - domainExists: "تم تعيين النطاق '%0%' بالفعل", - domainUpdated: "تم تحديث النطاق '%0%'", - orEdit: 'تحرير النطاقات الحالية', - domainHelpWithVariants: 'أسماء النطاقات الصالحة هي: "example.com"، "www.example.com"، "example.com:8080"، أو "https://www.example.com/".\\n علاوة على ذلك، يتم دعم المسارات ذات المستوى الواحد في النطاقات، مثل "example.com/en" أو "/en".', - inherit: 'وراثة', - setLanguage: 'الثقافة', - setLanguageHelp: 'تعيين الثقافة للعقد أدناه العقدة الحالية،
أو وراثة الثقافة من العقد الأصلية. سيتم تطبيقها أيضًا
\\n على العقدة الحالية، ما لم يتم تطبيق نطاق أدناه أيضًا.', - setDomains: 'النطاقات', - }, - buttons: { - clearSelection: 'مسح التحديد', - select: 'تحديد', - somethingElse: 'افعل شيئًا آخر', - bold: 'غامق', - deindent: 'إلغاء الفقرة', - formFieldInsert: 'إدراج حقل النموذج', - graphicHeadline: 'إدراج عنوان رسومي', - htmlEdit: 'تحرير HTML', - indent: 'فقرة', - italic: 'مائل', - justifyCenter: 'توسيط', - justifyLeft: 'محاذاة لليسار', - justifyRight: 'محاذاة لليمين', - linkInsert: 'إدراج رابط', - linkLocal: 'إدراج رابط محلي (مرساة)', - listBullet: 'قائمة نقطية', - listNumeric: 'قائمة رقمية', - macroInsert: 'إدراج ماكرو', - pictureInsert: 'إدراج صورة', - publishAndClose: 'نشر وإغلاق', - publishDescendants: 'نشر مع الفروع', - relations: 'تحرير العلاقات', - returnToList: 'العودة إلى القائمة', - save: 'حفظ', - saveAndClose: 'حفظ وإغلاق', - saveAndPublish: 'حفظ ونشر', - saveToPublish: 'إرسال للموافقة', - saveListView: 'حفظ عرض القائمة', - schedulePublish: 'جدولة', - saveAndPreview: 'حفظ ومعاينة', - showPageDisabled: "تم تعطيل المعاينة لأنه لم يتم تعيين قالب", - styleChoose: 'اختر النمط', - styleShow: 'عرض الأنماط', - tableInsert: 'إدراج جدول', - generateModelsAndClose: 'توليد النماذج وإغلاق', - saveAndGenerateModels: 'حفظ وتوليد النماذج', - undo: 'تراجع', - redo: 'إعادة', - deleteTag: 'حذف العلامة', - confirmActionCancel: 'إلغاء', - confirmActionConfirm: 'تأكيد', - morePublishingOptions: 'خيارات نشر إضافية', - submitChanges: 'إرسال التغييرات', - }, - auditTrails: { - atViewingFor: "عرض ل", - delete: "تم حذف المحتوى", - unpublish: "تم إلغاء نشر المحتوى", - unpublishvariant: "تم إلغاء نشر المحتوى للغات: %0%", - publish: "تم نشر المحتوى", - publishvariant: "تم نشر المحتوى للغات: %0%", - save: "تم حفظ المحتوى", - savevariant: "تم حفظ المحتوى للغات: %0%", - move: "تم نقل المحتوى", - copy: "تم نسخ المحتوى", - rollback: "تم التراجع عن المحتوى", - sendtopublish: "تم إرسال المحتوى للنشر", - sendtopublishvariant: "تم إرسال المحتوى للنشر للغات: %0%", - sort: "ترتيب العناصر الفرعية بواسطة المستخدم", - custom: "%0%", - contentversionpreventcleanup: "إيقاف التنظيف للإصدار: %0%", - contentversionenablecleanup: "تفعيل التنظيف للإصدار: %0%", - smallCopy: "نسخ", - smallPublish: "نشر", - smallPublishVariant: "نشر", - smallMove: "نقل", - smallSave: "حفظ", - smallSaveVariant: "حفظ", - smallDelete: "حذف", - smallUnpublish: "إلغاء نشر", - smallUnpublishVariant: "إلغاء نشر", - smallRollBack: "التراجع", - smallSendToPublish: "إرسال للنشر", - smallSendToPublishVariant: "إرسال للنشر", - smallSort: "ترتيب", - smallCustom: "مخصص", - smallContentVersionPreventCleanup: "حفظ", - smallContentVersionEnableCleanup: "حفظ", - historyIncludingVariants: "التاريخ (جميع النسخ)" - }, - codefile: { - createFolderIllegalChars: "لا يمكن أن يحتوي اسم المجلد على أحرف غير قانونية.", - deleteItemFailed: "فشل في حذف العنصر: %0%" - }, - content: { - isPublished: "تم نشره", - about: "حول هذه الصفحة", - alias: "اللقب", - alternativeTextHelp: "(كيف يمكنك وصف الصورة عبر الهاتف)", - alternativeUrls: "روابط بديلة", - clickToEdit: "انقر لتحرير هذا العنصر", - createBy: "أنشأه", - createByDesc: "المؤلف الأصلي", - updatedBy: "تم التحديث بواسطة", - createDate: "تاريخ الإنشاء", - createDateDesc: "تاريخ/وقت إنشاء هذه الوثيقة", - documentType: "نوع الوثيقة", - editing: "تحرير", - expireDate: "إزالة في", - itemChanged: "تم تغيير هذا العنصر بعد النشر", - itemNotPublished: "هذا العنصر غير منشور", - lastPublished: "تم نشره آخر مرة", - noItemsToShow: "لا توجد عناصر لعرضها", - listViewNoItems: "لا توجد عناصر لعرضها في القائمة.", - listViewNoContent: "لم تتم إضافة عناصر فرعية", - listViewNoMembers: "لم تتم إضافة أعضاء", - mediatype: "نوع الوسائط", - mediaLinks: "رابط إلى عنصر/عناصر الوسائط", - membergroup: "مجموعة الأعضاء", - memberrole: "دور", - membertype: "نوع العضو", - noChanges: "لم يتم إجراء تغييرات", - noDate: "لم يتم اختيار تاريخ", - nodeName: "عنوان الصفحة", - noMediaLink: "لا يحتوي هذا العنصر الإعلامي على رابط", - noProperties: "لا يمكن إضافة محتوى لهذا العنصر", - otherElements: "الخصائص", - parentNotPublished: "هذه الوثيقة منشورة ولكنها غير مرئية لأن الأصل '%0%' غير منشور", - parentCultureNotPublished: "هذه الثقافة منشورة ولكنها غير مرئية لأنها غير منشورة على الأصل '%0%'", - parentNotPublishedAnomaly: "هذه الوثيقة منشورة ولكنها ليست في الذاكرة المؤقتة", - getUrlException: "لم يتمكن من الحصول على عنوان URL", - routeError: "هذه الوثيقة منشورة ولكن عنوان URL الخاص بها يتداخل مع المحتوى %0%", - routeErrorCannotRoute: "هذه الوثيقة منشورة ولكن لا يمكن توجيه عنوان URL الخاص بها", - publish: "نشر", - published: "منشور", - publishedPendingChanges: "منشور (تغييرات معلقة)", - publishStatus: "حالة النشر", - publishDescendantsHelp: "نشر %0% وجميع عناصر المحتوى أسفله وبالتالي جعل محتواها متاحًا للعامة.", - publishDescendantsWithVariantsHelp: "نشر النسخ ونسخ نفس النوع أسفله وبالتالي جعل محتواها متاحًا للعامة.", - noVariantsToProcess: "لا توجد نسخ متاحة", - releaseDate: "نشر في", - unpublishDate: "إلغاء نشر في", - removeDate: "مسح التاريخ", - setDate: "تعيين التاريخ", - sortDone: "تم تحديث ترتيب الفرز", - sortHelp: 'لترتيب العقد، ببساطة اسحب العقد أو انقر على أحد رؤوس الأعمدة. يمكنك تحديد عناصر متعددة عن طريق الضغط على مفتاح "shift" أو "control" أثناء التحديد', - statistics: "الإحصاءات", - titleOptional: "العنوان (اختياري)", - altTextOptional: "نص بديل (اختياري)", - captionTextOptional: "التعليق (اختياري)", - type: "النوع", - unpublish: "إلغاء نشر", - unpublished: "غير منشور", - notCreated: "لم يتم إنشاؤه", - updateDate: "آخر تعديل", - updateDateDesc: "تاريخ/وقت تعديل هذه الوثيقة", - uploadClear: "إزالة الملف/الملفات", - uploadClearImageContext: "انقر هنا لإزالة الصورة من عنصر الوسائط", - uploadClearFileContext: "انقر هنا لإزالة الملف من عنصر الوسائط", - urls: "رابط إلى الوثيقة", - memberof: "عضو في المجموعة(s)", - notmemberof: "ليس عضوًا في المجموعة(s)", - childItems: "العناصر الفرعية", - target: "الهدف", - scheduledPublishServerTime: "يترجم هذا إلى الوقت التالي على الخادم:", - scheduledPublishDocumentation: "ماذا يعني هذا؟", - nestedContentDeleteItem: "هل أنت متأكد أنك تريد حذف هذا العنصر؟", - nestedContentDeleteAllItems: "هل أنت متأكد أنك تريد حذف جميع العناصر؟", - nestedContentEditorNotSupported: "الخاصية %0% تستخدم محرر %1% والذي لا يدعمه المحتوى المتداخل.", - nestedContentNoContentTypes: "لم يتم تكوين أنواع المحتوى لهذه الخاصية.", - nestedContentAddElementType: "إضافة نوع عنصر", - nestedContentSelectElementTypeModalTitle: "اختر نوع العنصر", - nestedContentGroupHelpText: "حدد المجموعة التي يجب عرض خصائصها. إذا تركت فارغة، ستستخدم المجموعة الأولى على نوع العنصر.", - nestedContentTemplateHelpTextPart1: "أدخل تعبير Angular لتقييمه لكل عنصر للحصول على اسمه. استخدم", - nestedContentTemplateHelpTextPart2: "لعرض مؤشر العنصر", - nestedContentNoGroups: "نوع العنصر المحدد لا يحتوي على أي مجموعات مدعومة (التبويبات غير مدعومة بواسطة هذا المحرر، إما قم بتغييرها إلى مجموعات أو استخدم محرر قائمة الكتل).", - addTextBox: "إضافة مربع نص آخر", - removeTextBox: "إزالة هذا مربع النص", - contentRoot: "جذر المحتوى", - includeUnpublished: "تضمين عناصر المحتوى غير المنشورة.", - isSensitiveValue: "هذه القيمة مخفية. إذا كنت بحاجة إلى الوصول لعرض هذه القيمة، يرجى الاتصال بمدير موقعك.", - isSensitiveValue_short: "هذه القيمة مخفية.", - languagesToPublish: "ما اللغات التي ترغب في نشرها؟", - languagesToSendForApproval: "ما اللغات التي ترغب في إرسالها للموافقة؟", - languagesToSchedule: "ما اللغات التي ترغب في جدولتها؟", - languagesToUnpublish: "حدد اللغات التي ترغب في إلغاء نشرها. إلغاء نشر لغة إلزامية سيؤدي إلى إلغاء نشر جميع اللغات.", - variantsWillBeSaved: "جميع النسخ الجديدة سيتم حفظها.", - variantsToPublish: "أي النسخ ترغب في نشرها؟", - variantsToSave: "اختر النسخ التي سيتم حفظها.", - publishRequiresVariants: "النسخ التالية مطلوبة لعملية النشر:", - notReadyToPublish: "لسنا جاهزين للنشر", - readyToPublish: "جاهز للنشر؟", - readyToSave: "جاهز للحفظ؟", - resetFocalPoint: "إعادة تعيين نقطة التركيز", - sendForApproval: "إرسال للموافقة", - schedulePublishHelp: "حدد التاريخ والوقت للنشر و/أو إلغاء نشر عنصر المحتوى.", - createEmpty: "إنشاء جديد", - createFromClipboard: "الصق من الحافظة", - nodeIsInTrash: "هذا العنصر في سلة المهملات", - variantSaveNotAllowed: "الحفظ غير مسموح به", - variantPublishNotAllowed: "النشر غير مسموح به", - variantSendForApprovalNotAllowed: "إرسال للموافقة غير مسموح به", - variantScheduleNotAllowed: "الجدولة غير مسموح بها", - variantUnpublishNotAllowed: "إلغاء النشر غير مسموح به" - }, - blueprints: { - createBlueprintFrom: "إنشاء نموذج وثيقة جديد من '%0%'", - createBlueprintItemUnder: "إنشاء عنصر جديد تحت '%0%'", - createBlueprintFolderUnder: "إنشاء مجلد جديد تحت '%0%'", - blankBlueprint: "فارغ", - selectBlueprint: "حدد نموذج وثيقة", - createdBlueprintHeading: "تم إنشاء نموذج الوثيقة", - createdBlueprintMessage: "تم إنشاء نموذج وثيقة من '%0%'", - duplicateBlueprintMessage: "يوجد نموذج وثيقة آخر بنفس الاسم بالفعل", - blueprintDescription: "نموذج الوثيقة هو محتوى محدد مسبقًا يمكن للمحرر تحديده لاستخدامه كأساس لإنشاء محتوى جديد" - }, - media: { - clickToUpload: "انقر لتحميل", - orClickHereToUpload: "أو انقر هنا لاختيار الملفات", - disallowedFileType: "لا يمكن تحميل هذا الملف، فهو لا يحتوي على نوع ملف معتمد", - disallowedMediaType: "لا يمكن تحميل هذا الملف، نوع الوسائط باللقب '%0%' غير مسموح به هنا", - invalidFileName: "لا يمكن تحميل هذا الملف، فهو لا يحتوي على اسم ملف صحيح", - maxFileSize: "أقصى حجم للملف هو", - mediaRoot: "جذر الوسائط", - moveToSameFolderFailed: "لا يمكن أن تكون المجلدات الأصلية والوجهة هي نفسها", - createFolderFailed: "فشل في إنشاء مجلد تحت المعرف %0%", - renameFolderFailed: "فشل في إعادة تسمية المجلد بالمعرف %0%", - dragAndDropYourFilesIntoTheArea: "اسحب وأفلت ملفاتك في المنطقة", - uploadNotAllowed: "التحميل غير مسموح به في هذا الموقع" - }, - member: { - createNewMember: "إنشاء عضو جديد", - allMembers: "جميع الأعضاء", - duplicateMemberLogin: "يوجد عضو بهذا تسجيل الدخول بالفعل", - memberGroupNoProperties: "مجموعات الأعضاء لا تحتوي على خصائص إضافية للتعديل.", - memberHasGroup: "العضو بالفعل في المجموعة '%0%'", - memberHasPassword: "العضو لديه كلمة مرور محددة بالفعل", - memberLockoutNotEnabled: "التحقق من القفل غير مفعل لهذا العضو", - memberNotInGroup: "العضو ليس في المجموعة '%0%'", - '2fa': "التحقق بخطوتين" - }, - contentType: { - copyFailed: "فشل في نسخ نوع المحتوى", - moveFailed: "فشل في نقل نوع المحتوى" - }, - mediaType: { - copyFailed: "فشل في نسخ نوع الوسائط", - moveFailed: "فشل في نقل نوع الوسائط", - autoPickMediaType: "اختيار تلقائي" - }, - memberType: { - copyFailed: "فشل في نسخ نوع العضو" - }, + actions: { + assigndomain: 'الثقافة وأسماء النطاقات', + auditTrail: 'سجل التدقيق', + browse: 'تصفح ', + changeDataType: 'تغيير نوع البيانات', + changeDocType: 'تغيير نوع الوثيقة', + chooseWhereToCopy: 'اختر مكان النسخ', + chooseWhereToImport: 'اختر مكان الاستيراد', + chooseWhereToMove: 'اختر مكان النقل', + copy: 'نسخ', + copyTo: 'نسخ إلى', + create: 'إنشاء', + createblueprint: 'إنشاء مخطط انشائي للمستند', + createGroup: 'إنشاء مجموعة', + createPackage: 'إنشاء حزمة', + delete: 'حذف', + disable: 'تعطيل', + editContent: 'تحرير المحتوى', + editSettings: 'تحرير الإعدادات', + emptyrecyclebin: 'إفراغ سلة المحذوفات', + enable: 'تمكين', + export: 'تصدير', + exportDocumentType: 'تصدير نوع الوثيقة', + folderCreate: 'إنشاء مجلد', + folderDelete: 'حذف مجلد', + folderRename: 'إعادة تسمية مجلد', + import: 'استيراد', + importdocumenttype: 'استيراد نوع وثيقة', + importPackage: 'استيراد حزمة', + infiniteEditorChooseWhereToCopy: 'اختر مكان نسخ العنصر (العناصر) المحددة', + infiniteEditorChooseWhereToMove: 'اختر مكان نقل العنصر (العناصر) المحددة', + liveEdit: 'تحرير مباشر', + logout: 'تسجيل خروج', + move: 'نقل إلى', + notify: 'الإشعارات', + protect: 'الوصول العام', + publish: 'نشر', + refreshNode: 'إعادة تحميل', + remove: 'إزالة', + rename: 'إعادة تسمية', + republish: 'إعادة نشر الموقع بالكامل', + resendInvite: 'إعادة إرسال الدعوة', + restore: 'استعادة', + rights: 'الأذونات', + rollback: 'التراجع', + sendtopublish: 'إرسال للنشر', + sendToTranslate: 'إرسال للترجمة', + setGroup: 'تعيين مجموعة', + setPermissions: 'تعيين الأذونات', + sort: 'ترتيب الابناء', + toInTheTreeStructureBelow: 'في هيكل الشجري أدناه', + translate: 'ترجمة', + trash: 'سلة المهملات', + unlock: 'فتح القفل', + unpublish: 'إلغاء النشر', + update: 'تحديث', + wasCopiedTo: 'تم نسخه إلى', + wasDeleted: 'تم حذفه', + wasMovedTo: 'تم نقله إلى', + }, + actionCategories: { + content: 'المحتوى', + administration: 'الإدارة', + structure: 'الهيكل', + other: 'أخرى', + }, + actionDescriptions: { + assignDomain: 'السماح بالوصول لتعيين الثقافة وأسماء النطاقات', + auditTrail: 'السماح بالوصول لعرض سجل تاريخ العقدة', + browse: 'السماح بالوصول لعرض العقدة', + changeDocType: 'السماح بالوصول لتغيير نوع وثيقة للعقدة', + copy: 'السماح بالوصول لنسخ العقدة', + create: 'السماح بالوصول لإنشاء العقد', + delete: 'السماح بالوصول لحذف العقد', + move: 'السماح بالوصول لنقل العقدة', + protect: 'السماح بالوصول لتعيين وتغيير قيود الوصول للعقدة', + publish: 'السماح بالوصول لنشر العقدة', + unpublish: 'السماح بالوصول لإلغاء نشر العقدة', + rights: 'السماح بالوصول لتغيير الأذونات للعقدة', + rollback: 'السماح بالوصول للتراجع عن العقدة إلى حالة سابقة', + sendtopublish: 'السماح بالوصول لإرسال العقدة للموافقة قبل النشر', + sendToTranslate: 'السماح بالوصول لإرسال العقدة للترجمة', + sort: 'السماح بالوصول لتغيير ترتيب العقد', + translate: 'السماح بالوصول لترجمة العقدة', + update: 'السماح بالوصول لحفظ العقدة', + createblueprint: 'السماح بالوصول لإنشاء مخطط الوثيقة', + notify: 'السماح بالوصول لإعداد الإشعارات لعقد المحتوى', + }, + apps: { + umbContent: 'المحتوى', + umbInfo: 'المعلومات', + }, + assignDomain: { + permissionDenied: 'تم رفض الإذن.', + addNew: 'إضافة نطاق جديد', + addCurrent: 'إضافة النطاق الحالي', + remove: 'إزالة', + invalidNode: 'عقدة غير صالحة.', + invalidDomain: 'واحد أو أكثر من النطاقات لها تنسيق غير صالح.', + duplicateDomain: 'تم تعيين النطاق بالفعل.', + language: 'اللغة', + domain: 'النطاق', + domainCreated: "تم إنشاء النطاق الجديد '%0%'", + domainDeleted: "تم حذف النطاق '%0%'", + domainExists: "تم تعيين النطاق '%0%' بالفعل", + domainUpdated: "تم تحديث النطاق '%0%'", + orEdit: 'تحرير النطاقات الحالية', + domainHelpWithVariants: + 'أسماء النطاقات الصالحة هي: "example.com"، "www.example.com"، "example.com:8080"، أو "https://www.example.com/".\\n علاوة على ذلك، يتم دعم المسارات ذات المستوى الواحد في النطاقات، مثل "example.com/en" أو "/en".', + inherit: 'وراثة', + setLanguage: 'الثقافة', + setLanguageHelp: + 'تعيين الثقافة للعقد أدناه العقدة الحالية،
أو وراثة الثقافة من العقد الأصلية. سيتم تطبيقها أيضًا
\\n على العقدة الحالية، ما لم يتم تطبيق نطاق أدناه أيضًا.', + setDomains: 'النطاقات', + }, + buttons: { + clearSelection: 'مسح التحديد', + select: 'تحديد', + somethingElse: 'افعل شيئًا آخر', + bold: 'غامق', + deindent: 'إلغاء الفقرة', + formFieldInsert: 'إدراج حقل النموذج', + graphicHeadline: 'إدراج عنوان رسومي', + htmlEdit: 'تحرير HTML', + indent: 'فقرة', + italic: 'مائل', + justifyCenter: 'توسيط', + justifyLeft: 'محاذاة لليسار', + justifyRight: 'محاذاة لليمين', + linkInsert: 'إدراج رابط', + linkLocal: 'إدراج رابط محلي (مرساة)', + listBullet: 'قائمة نقطية', + listNumeric: 'قائمة رقمية', + macroInsert: 'إدراج ماكرو', + pictureInsert: 'إدراج صورة', + publishAndClose: 'نشر وإغلاق', + publishDescendants: 'نشر مع الفروع', + relations: 'تحرير العلاقات', + returnToList: 'العودة إلى القائمة', + save: 'حفظ', + saveAndClose: 'حفظ وإغلاق', + saveAndPublish: 'حفظ ونشر', + saveToPublish: 'إرسال للموافقة', + saveListView: 'حفظ عرض القائمة', + schedulePublish: 'جدولة', + saveAndPreview: 'حفظ ومعاينة', + showPageDisabled: 'تم تعطيل المعاينة لأنه لم يتم تعيين قالب', + styleChoose: 'اختر النمط', + styleShow: 'عرض الأنماط', + tableInsert: 'إدراج جدول', + generateModelsAndClose: 'توليد النماذج وإغلاق', + saveAndGenerateModels: 'حفظ وتوليد النماذج', + undo: 'تراجع', + redo: 'إعادة', + deleteTag: 'حذف العلامة', + confirmActionCancel: 'إلغاء', + confirmActionConfirm: 'تأكيد', + morePublishingOptions: 'خيارات نشر إضافية', + submitChanges: 'إرسال التغييرات', + }, + auditTrails: { + atViewingFor: 'عرض ل', + delete: 'تم حذف المحتوى', + unpublish: 'تم إلغاء نشر المحتوى', + unpublishvariant: 'تم إلغاء نشر المحتوى للغات: %0%', + publish: 'تم نشر المحتوى', + publishvariant: 'تم نشر المحتوى للغات: %0%', + save: 'تم حفظ المحتوى', + savevariant: 'تم حفظ المحتوى للغات: %0%', + move: 'تم نقل المحتوى', + copy: 'تم نسخ المحتوى', + rollback: 'تم التراجع عن المحتوى', + sendtopublish: 'تم إرسال المحتوى للنشر', + sendtopublishvariant: 'تم إرسال المحتوى للنشر للغات: %0%', + sort: 'ترتيب العناصر الفرعية بواسطة المستخدم', + custom: '%0%', + contentversionpreventcleanup: 'إيقاف التنظيف للإصدار: %0%', + contentversionenablecleanup: 'تفعيل التنظيف للإصدار: %0%', + smallCopy: 'نسخ', + smallPublish: 'نشر', + smallPublishVariant: 'نشر', + smallMove: 'نقل', + smallSave: 'حفظ', + smallSaveVariant: 'حفظ', + smallDelete: 'حذف', + smallUnpublish: 'إلغاء نشر', + smallUnpublishVariant: 'إلغاء نشر', + smallRollBack: 'التراجع', + smallSendToPublish: 'إرسال للنشر', + smallSendToPublishVariant: 'إرسال للنشر', + smallSort: 'ترتيب', + smallCustom: 'مخصص', + smallContentVersionPreventCleanup: 'حفظ', + smallContentVersionEnableCleanup: 'حفظ', + historyIncludingVariants: 'التاريخ (جميع النسخ)', + }, + codefile: { + createFolderIllegalChars: 'لا يمكن أن يحتوي اسم المجلد على أحرف غير قانونية.', + deleteItemFailed: 'فشل في حذف العنصر: %0%', + }, + content: { + isPublished: 'تم نشره', + about: 'حول هذه الصفحة', + alias: 'اللقب', + alternativeTextHelp: '(كيف يمكنك وصف الصورة عبر الهاتف)', + alternativeUrls: 'روابط بديلة', + clickToEdit: 'انقر لتحرير هذا العنصر', + createBy: 'أنشأه', + createByDesc: 'المؤلف الأصلي', + updatedBy: 'تم التحديث بواسطة', + createDate: 'تاريخ الإنشاء', + createDateDesc: 'تاريخ/وقت إنشاء هذه الوثيقة', + documentType: 'نوع الوثيقة', + editing: 'تحرير', + expireDate: 'إزالة في', + itemChanged: 'تم تغيير هذا العنصر بعد النشر', + itemNotPublished: 'هذا العنصر غير منشور', + lastPublished: 'تم نشره آخر مرة', + noItemsToShow: 'لا توجد عناصر لعرضها', + listViewNoItems: 'لا توجد عناصر لعرضها في القائمة.', + listViewNoContent: 'لم تتم إضافة عناصر فرعية', + listViewNoMembers: 'لم تتم إضافة أعضاء', + mediatype: 'نوع الوسائط', + mediaLinks: 'رابط إلى عنصر/عناصر الوسائط', + membergroup: 'مجموعة الأعضاء', + memberrole: 'دور', + membertype: 'نوع العضو', + noChanges: 'لم يتم إجراء تغييرات', + noDate: 'لم يتم اختيار تاريخ', + nodeName: 'عنوان الصفحة', + noMediaLink: 'لا يحتوي هذا العنصر الإعلامي على رابط', + noProperties: 'لا يمكن إضافة محتوى لهذا العنصر', + otherElements: 'الخصائص', + parentNotPublished: "هذه الوثيقة منشورة ولكنها غير مرئية لأن الأصل '%0%' غير منشور", + parentCultureNotPublished: "هذه الثقافة منشورة ولكنها غير مرئية لأنها غير منشورة على الأصل '%0%'", + parentNotPublishedAnomaly: 'هذه الوثيقة منشورة ولكنها ليست في الذاكرة المؤقتة', + getUrlException: 'لم يتمكن من الحصول على عنوان URL', + routeError: 'هذه الوثيقة منشورة ولكن عنوان URL الخاص بها يتداخل مع المحتوى %0%', + routeErrorCannotRoute: 'هذه الوثيقة منشورة ولكن لا يمكن توجيه عنوان URL الخاص بها', + publish: 'نشر', + published: 'منشور', + publishedPendingChanges: 'منشور (تغييرات معلقة)', + publishStatus: 'حالة النشر', + publishDescendantsHelp: 'نشر %0% وجميع عناصر المحتوى أسفله وبالتالي جعل محتواها متاحًا للعامة.', + publishDescendantsWithVariantsHelp: 'نشر النسخ ونسخ نفس النوع أسفله وبالتالي جعل محتواها متاحًا للعامة.', + noVariantsToProcess: 'لا توجد نسخ متاحة', + releaseDate: 'نشر في', + unpublishDate: 'إلغاء نشر في', + removeDate: 'مسح التاريخ', + setDate: 'تعيين التاريخ', + sortDone: 'تم تحديث ترتيب الفرز', + sortHelp: + 'لترتيب العقد، ببساطة اسحب العقد أو انقر على أحد رؤوس الأعمدة. يمكنك تحديد عناصر متعددة عن طريق الضغط على مفتاح "shift" أو "control" أثناء التحديد', + statistics: 'الإحصاءات', + titleOptional: 'العنوان (اختياري)', + altTextOptional: 'نص بديل (اختياري)', + captionTextOptional: 'التعليق (اختياري)', + type: 'النوع', + unpublish: 'إلغاء نشر', + unpublished: 'غير منشور', + notCreated: 'لم يتم إنشاؤه', + updateDate: 'آخر تعديل', + updateDateDesc: 'تاريخ/وقت تعديل هذه الوثيقة', + uploadClear: 'إزالة الملف/الملفات', + uploadClearImageContext: 'انقر هنا لإزالة الصورة من عنصر الوسائط', + uploadClearFileContext: 'انقر هنا لإزالة الملف من عنصر الوسائط', + urls: 'رابط إلى الوثيقة', + memberof: 'عضو في المجموعة(s)', + notmemberof: 'ليس عضوًا في المجموعة(s)', + childItems: 'العناصر الفرعية', + target: 'الهدف', + scheduledPublishServerTime: 'يترجم هذا إلى الوقت التالي على الخادم:', + scheduledPublishDocumentation: + 'ماذا يعني هذا؟', + nestedContentDeleteItem: 'هل أنت متأكد أنك تريد حذف هذا العنصر؟', + nestedContentDeleteAllItems: 'هل أنت متأكد أنك تريد حذف جميع العناصر؟', + nestedContentEditorNotSupported: 'الخاصية %0% تستخدم محرر %1% والذي لا يدعمه المحتوى المتداخل.', + nestedContentNoContentTypes: 'لم يتم تكوين أنواع المحتوى لهذه الخاصية.', + nestedContentAddElementType: 'إضافة نوع عنصر', + nestedContentSelectElementTypeModalTitle: 'اختر نوع العنصر', + nestedContentGroupHelpText: + 'حدد المجموعة التي يجب عرض خصائصها. إذا تركت فارغة، ستستخدم المجموعة الأولى على نوع العنصر.', + nestedContentTemplateHelpTextPart1: 'أدخل تعبير Angular لتقييمه لكل عنصر للحصول على اسمه. استخدم', + nestedContentTemplateHelpTextPart2: 'لعرض مؤشر العنصر', + nestedContentNoGroups: + 'نوع العنصر المحدد لا يحتوي على أي مجموعات مدعومة (التبويبات غير مدعومة بواسطة هذا المحرر، إما قم بتغييرها إلى مجموعات أو استخدم محرر قائمة الكتل).', + addTextBox: 'إضافة مربع نص آخر', + removeTextBox: 'إزالة هذا مربع النص', + contentRoot: 'جذر المحتوى', + includeUnpublished: 'تضمين عناصر المحتوى غير المنشورة.', + isSensitiveValue: 'هذه القيمة مخفية. إذا كنت بحاجة إلى الوصول لعرض هذه القيمة، يرجى الاتصال بمدير موقعك.', + isSensitiveValue_short: 'هذه القيمة مخفية.', + languagesToPublish: 'ما اللغات التي ترغب في نشرها؟', + languagesToSendForApproval: 'ما اللغات التي ترغب في إرسالها للموافقة؟', + languagesToSchedule: 'ما اللغات التي ترغب في جدولتها؟', + languagesToUnpublish: 'حدد اللغات التي ترغب في إلغاء نشرها. إلغاء نشر لغة إلزامية سيؤدي إلى إلغاء نشر جميع اللغات.', + variantsWillBeSaved: 'جميع النسخ الجديدة سيتم حفظها.', + variantsToPublish: 'أي النسخ ترغب في نشرها؟', + variantsToSave: 'اختر النسخ التي سيتم حفظها.', + publishRequiresVariants: 'النسخ التالية مطلوبة لعملية النشر:', + notReadyToPublish: 'لسنا جاهزين للنشر', + readyToPublish: 'جاهز للنشر؟', + readyToSave: 'جاهز للحفظ؟', + resetFocalPoint: 'إعادة تعيين نقطة التركيز', + sendForApproval: 'إرسال للموافقة', + schedulePublishHelp: 'حدد التاريخ والوقت للنشر و/أو إلغاء نشر عنصر المحتوى.', + createEmpty: 'إنشاء جديد', + createFromClipboard: 'الصق من الحافظة', + nodeIsInTrash: 'هذا العنصر في سلة المهملات', + variantSaveNotAllowed: 'الحفظ غير مسموح به', + variantPublishNotAllowed: 'النشر غير مسموح به', + variantSendForApprovalNotAllowed: 'إرسال للموافقة غير مسموح به', + variantScheduleNotAllowed: 'الجدولة غير مسموح بها', + variantUnpublishNotAllowed: 'إلغاء النشر غير مسموح به', + }, + blueprints: { + createBlueprintFrom: "إنشاء نموذج وثيقة جديد من '%0%'", + createBlueprintItemUnder: "إنشاء عنصر جديد تحت '%0%'", + createBlueprintFolderUnder: "إنشاء مجلد جديد تحت '%0%'", + blankBlueprint: 'فارغ', + selectBlueprint: 'حدد نموذج وثيقة', + createdBlueprintHeading: 'تم إنشاء نموذج الوثيقة', + createdBlueprintMessage: "تم إنشاء نموذج وثيقة من '%0%'", + duplicateBlueprintMessage: 'يوجد نموذج وثيقة آخر بنفس الاسم بالفعل', + blueprintDescription: 'نموذج الوثيقة هو محتوى محدد مسبقًا يمكن للمحرر تحديده لاستخدامه كأساس لإنشاء محتوى جديد', + }, + media: { + clickToUpload: 'انقر لتحميل', + orClickHereToUpload: 'أو انقر هنا لاختيار الملفات', + disallowedFileType: 'لا يمكن تحميل هذا الملف، فهو لا يحتوي على نوع ملف معتمد', + disallowedMediaType: "لا يمكن تحميل هذا الملف، نوع الوسائط باللقب '%0%' غير مسموح به هنا", + invalidFileName: 'لا يمكن تحميل هذا الملف، فهو لا يحتوي على اسم ملف صحيح', + maxFileSize: 'أقصى حجم للملف هو', + mediaRoot: 'جذر الوسائط', + moveToSameFolderFailed: 'لا يمكن أن تكون المجلدات الأصلية والوجهة هي نفسها', + createFolderFailed: 'فشل في إنشاء مجلد تحت المعرف %0%', + renameFolderFailed: 'فشل في إعادة تسمية المجلد بالمعرف %0%', + dragAndDropYourFilesIntoTheArea: 'اسحب وأفلت ملفاتك في المنطقة', + uploadNotAllowed: 'التحميل غير مسموح به في هذا الموقع', + }, + member: { + createNewMember: 'إنشاء عضو جديد', + allMembers: 'جميع الأعضاء', + duplicateMemberLogin: 'يوجد عضو بهذا تسجيل الدخول بالفعل', + memberGroupNoProperties: 'مجموعات الأعضاء لا تحتوي على خصائص إضافية للتعديل.', + memberHasGroup: "العضو بالفعل في المجموعة '%0%'", + memberHasPassword: 'العضو لديه كلمة مرور محددة بالفعل', + memberLockoutNotEnabled: 'التحقق من القفل غير مفعل لهذا العضو', + memberNotInGroup: "العضو ليس في المجموعة '%0%'", + '2fa': 'التحقق بخطوتين', + }, + contentType: { + copyFailed: 'فشل في نسخ نوع المحتوى', + moveFailed: 'فشل في نقل نوع المحتوى', + }, + mediaType: { + copyFailed: 'فشل في نسخ نوع الوسائط', + moveFailed: 'فشل في نقل نوع الوسائط', + autoPickMediaType: 'اختيار تلقائي', + }, + memberType: { + copyFailed: 'فشل في نسخ نوع العضو', + }, create: { - chooseNode: "أين تريد إنشاء %0% الجديد", - createUnder: "إنشاء عنصر تحت", - createContentBlueprint: "حدد نوع الوثيقة الذي تريد إنشاء نموذج وثيقة له", - enterFolderName: "أدخل اسم المجلد", - updateData: "اختر نوعًا وعنوانًا", - noDocumentTypes: "لا توجد أنواع وثائق مسموح بها متاحة لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.", - noDocumentTypesAtRoot: "لا توجد أنواع وثائق متاحة لإنشاء المحتوى هنا. يجب عليك إنشاء هذه الأنواع في أنواع الوثائق ضمن قسم الإعدادات.", - noDocumentTypesWithNoSettingsAccess: "الصفحة المحددة في شجرة المحتوى لا تسمح بإنشاء أي صفحات أسفلها.", - noDocumentTypesEditPermissions: "تعديل الأذونات لهذا النوع من الوثائق", - noDocumentTypesCreateNew: "إنشاء نوع وثيقة جديد", - noDocumentTypesAllowedAtRoot: "لا توجد أنواع وثائق مسموح بها لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تغيير خيار السماح كجذر ضمن الأذونات.", - noMediaTypes: "لا توجد أنواع وسائط مسموح بها لإنشاء الوسائط هنا. يجب تمكينها في أنواع الوسائط ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.", - noMediaTypesWithNoSettingsAccess: "الوسائط المحددة في الشجرة لا تسمح بإنشاء أي وسائط أخرى أسفلها.", - noMediaTypesEditPermissions: "تعديل الأذونات لهذا النوع من الوسائط", - documentTypeWithoutTemplate: "نوع الوثيقة بدون قالب", - documentTypeWithTemplate: "نوع الوثيقة مع قالب", - documentTypeWithTemplateDescription: "تعريف البيانات لصفحة محتوى يمكن إنشاؤها من قبل المحررين في شجرة المحتوى ويمكن الوصول إليها مباشرة عبر URL.", - documentType: "نوع الوثيقة", - documentTypeDescription: "تعريف البيانات لمكون محتوى يمكن إنشاؤه من قبل المحررين في شجرة المحتوى ويمكن اختياره في صفحات أخرى ولكنه لا يحتوي على URL مباشر.", - elementType: "نوع العنصر", - elementTypeDescription: "يحدد المخطط لمجموعة متكررة من الخصائص، على سبيل المثال، في محرر 'قائمة الكتل' أو 'شبكة الكتل'.", - composition: "تركيب", - compositionDescription: "يحدد مجموعة قابلة لإعادة الاستخدام من الخصائص يمكن تضمينها في تعريف أنواع وثائق متعددة. على سبيل المثال، مجموعة من 'إعدادات الصفحة المشتركة'.", - folder: "مجلد", - folderDescription: "يستخدم لتنظيم أنواع الوثائق، والتركيبات، وأنواع العناصر التي تم إنشاؤها في شجرة نوع الوثيقة هذه.", - newFolder: "مجلد جديد", - newDataType: "نوع بيانات جديد", - newJavascriptFile: "ملف JavaScript جديد", - newEmptyPartialView: "عرض جزئي فارغ جديد", - newPartialViewMacro: "ماكرو عرض جزئي جديد", - newPartialViewFromSnippet: "عرض جزئي جديد من مقطع", - newPartialViewMacroFromSnippet: "ماكرو عرض جزئي جديد من مقطع", - newPartialViewMacroNoMacro: "ماكرو عرض جزئي جديد (بدون ماكرو)", - newStyleSheetFile: "ملف ورقة أنماط جديد", - newRteStyleSheetFile: "ملف ورقة أنماط محرر النصوص الغني الجديد" - }, - dashboard: { - browser: "تصفح موقعك", - dontShowAgain: "- إخفاء", - nothinghappens: "إذا لم يفتح Umbraco، قد تحتاج إلى السماح بالنوافذ المنبثقة من هذا الموقع", - openinnew: "تم فتحه في نافذة جديدة", - restart: "إعادة تشغيل", - visit: "زيارة", - welcome: "مرحبا" - }, - prompt: { - stay: "ابق", - discardChanges: "تجاهل التغييرات", - unsavedChanges: "لديك تغييرات غير محفوظة", - unsavedChangesWarning: "هل أنت متأكد أنك تريد الانتقال بعيدًا عن هذه الصفحة؟ - لديك تغييرات غير محفوظة", - confirmListViewPublish: "النشر سيجعل العناصر المحددة مرئية على الموقع.", - confirmListViewUnpublish: "إلغاء النشر سيزيل العناصر المحددة وجميع نسلها من الموقع.", - confirmUnpublish: "إلغاء النشر سيزيل هذه الصفحة وجميع نسلها من الموقع.", - doctypeChangeWarning: "لديك تغييرات غير محفوظة. إجراء تغييرات على نوع الوثيقة سيتسبب في تجاهل التغييرات." - }, - bulk: { - done: "تم", - deletedItem: "تم حذف %0% عنصر", - deletedItems: "تم حذف %0% عناصر", - deletedItemOfItem: "تم حذف %0% من %1% عنصر", - deletedItemOfItems: "تم حذف %0% من %1% عناصر", - publishedItem: "تم نشر %0% عنصر", - publishedItems: "تم نشر %0% عناصر", - publishedItemOfItem: "تم نشر %0% من %1% عنصر", - publishedItemOfItems: "تم نشر %0% من %1% عناصر", - unpublishedItem: "تم إلغاء نشر %0% عنصر", - unpublishedItems: "تم إلغاء نشر %0% عناصر", - unpublishedItemOfItem: "تم إلغاء نشر %0% من %1% عنصر", - unpublishedItemOfItems: "تم إلغاء نشر %0% من %1% عناصر", - movedItem: "تم نقل %0% عنصر", - movedItems: "تم نقل %0% عناصر", - movedItemOfItem: "تم نقل %0% من %1% عنصر", - movedItemOfItems: "تم نقل %0% من %1% عناصر", - copiedItem: "تم نسخ %0% عنصر", - copiedItems: "تم نسخ %0% عناصر", - copiedItemOfItem: "تم نسخ %0% من %1% عنصر", - copiedItemOfItems: "تم نسخ %0% من %1% عناصر" - }, - defaultdialogs: { - nodeNameLinkPicker: "عنوان الرابط", - urlLinkPicker: "الرابط", - anchorLinkPicker: "مرساة / سلسلة استعلام", - anchorInsert: "اسم", - closeThisWindow: "أغلق هذه النافذة", - confirmdelete: "هل أنت متأكد أنك تريد الحذف", - confirmdeleteNumberOfItems: "هل أنت متأكد أنك تريد حذف %0% من %1% العناصر", - confirmdisable: "هل أنت متأكد أنك تريد التعطيل", - confirmremove: "هل أنت متأكد أنك تريد الإزالة", - confirmremoveusageof: "هل أنت متأكد أنك تريد إزالة استخدام %0%", - confirmlogout: "هل أنت متأكد؟", - confirmSure: "هل أنت متأكد؟", - cut: "قص", - editDictionary: "تحرير عنصر القاموس", - editLanguage: "تحرير اللغة", - editSelectedMedia: "تحرير الوسائط المحددة", - insertAnchor: "إدراج رابط محلي", - insertCharacter: "إدراج حرف", - insertgraphicheadline: "إدراج عنوان رسومي", - insertimage: "إدراج صورة", - insertlink: "إدراج رابط", - insertMacro: "انقر لإضافة ماكرو", - inserttable: "إدراج جدول", - languagedeletewarning: "سيؤدي هذا إلى حذف اللغة", - languageChangeWarning: "قد يكون تغيير الثقافة للغة عملية مكلفة وستؤدي إلى إعادة بناء ذاكرة التخزين المؤقت للمحتوى والفهارس", - lastEdited: "آخر تحرير", - link: "رابط", - linkinternal: "رابط داخلي:", - linklocaltip: "عند استخدام الروابط المحلية، أدخل \"#\" أمام الرابط", - linknewwindow: "فتح في نافذة جديدة؟", - macroDoesNotHaveProperties: "هذا الماكرو لا يحتوي على خصائص يمكنك تحريرها", - paste: "لصق", - permissionsEdit: "تحرير الأذونات لـ", - permissionsSet: "تعيين الأذونات لـ", - permissionsSetForGroup: "تعيين الأذونات لـ %0% لمجموعة المستخدمين %1%", - permissionsHelp: "اختر مجموعات المستخدمين التي تريد تعيين الأذونات لها", - recycleBinDeleting: "يتم الآن حذف العناصر في سلة المهملات. يرجى عدم إغلاق هذه النافذة أثناء تنفيذ هذه العملية", - recycleBinIsEmpty: "سلة المهملات فارغة الآن", - recycleBinWarning: "عند حذف العناصر من سلة المهملات، ستختفي إلى الأبد", - regexSearchError: "خدمة الويب الخاصة بـ regexlib.com تواجه حالياً بعض المشاكل، ونحن لا نملك السيطرة على ذلك. نحن آسفون لهذا الإزعاج.", - regexSearchHelp: "ابحث عن تعبير منتظم لإضافته كتحقق لحقل النموذج. مثال: 'بريد إلكتروني،' 'رمز بريدي'، 'عنوان URL'.", - removeMacro: "إزالة الماكرو", - requiredField: "حقل مطلوب", - sitereindexed: "تمت إعادة فهرسة الموقع", - siterepublished: "تم تحديث ذاكرة التخزين المؤقت للموقع. جميع المحتويات المنشورة محدثة الآن، بينما تظل جميع المحتويات غير المنشورة كما هي", - siterepublishHelp: "سيتم تحديث ذاكرة التخزين المؤقت للموقع. سيتم تحديث جميع المحتويات المنشورة، بينما ستظل المحتويات غير المنشورة كما هي.", - tableColumns: "عدد الأعمدة", - tableRows: "عدد الصفوف", - thumbnailimageclickfororiginal: "انقر على الصورة لرؤية الحجم الكامل", - treepicker: "اختيار العنصر", - viewCacheItem: "عرض عنصر ذاكرة التخزين المؤقت", - relateToOriginalLabel: "يرتبط بالأصل", - includeDescendants: "تضمين الأحفاد", - theFriendliestCommunity: "أكثر مجتمع ودود", - linkToPage: "رابط إلى الصفحة", - openInNewWindow: "فتح الوثيقة المرتبطة في نافذة أو علامة تبويب جديدة", - linkToMedia: "رابط إلى الوسائط", - selectContentStartNode: "اختر العقدة الأساسية للمحتوى", - selectMedia: "اختر الوسائط", - selectMediaType: "اختر نوع الوسائط", - selectIcon: "اختر الأيقونة", - selectItem: "اختر العنصر", - selectLink: "اختر الرابط", - selectMacro: "اختر الماكرو", - selectContent: "اختر المحتوى", - selectContentType: "اختر نوع المحتوى", - selectMediaStartNode: "اختر العقدة الأساسية للوسائط", - selectMember: "اختر العضو", - selectMembers: "اختر الأعضاء", - selectMemberGroup: "اختر مجموعة الأعضاء", - selectMemberType: "اختر نوع العضو", - selectNode: "اختر العقدة", - selectLanguages: "اختر اللغات", - selectSections: "اختر الأقسام", - selectUser: "اختر المستخدم", - selectUsers: "اختر المستخدمين", - noIconsFound: "لم يتم العثور على أيقونات", - noMacroParams: "لا توجد معلمات لهذا الماكرو", - noMacros: "لا توجد ماكروات لإدراجها", - externalLoginProviders: "تسجيل الدخول الخارجي", - exceptionDetail: "تفاصيل الاستثناء", - stacktrace: "التتبع الكامل", - innerException: "الاستثناء الداخلي", - linkYour: "ربط حساب {0} الخاص بك", - linkYourConfirm: "أنت على وشك ربط حسابك في Umbraco وحسابك في {0} وسيتم توجيهك إلى {0} للتأكيد.", - unLinkYour: "إلغاء ربط حساب {0} الخاص بك", - unLinkYourConfirm: "أنت على وشك إلغاء ربط حسابك في Umbraco وحسابك في {0} وسيتم تسجيل خروجك.", - linkedToService: "حسابك مرتبط بهذه الخدمة", - selectEditor: "اختر المحرر", - selectEditorConfiguration: "اختر التكوين", - selectSnippet: "اختر الشريحة", - variantdeletewarning: "سيؤدي ذلك إلى حذف العقدة وجميع اللغات المرتبطة بها. إذا كنت ترغب فقط في حذف لغة واحدة، يجب عليك إلغاء نشر العقدة في تلك اللغة بدلاً من ذلك.", - propertyuserpickerremovewarning: "سيتم إزالة المستخدم %0%.", - userremovewarning: "سيتم إزالة المستخدم %0% من المجموعة %1%", - yesRemove: "نعم، أزل", - deleteLayout: "أنت تقوم بحذف التخطيط", - deletingALayout: "سيؤدي تعديل التخطيط إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين." - }, + chooseNode: 'أين تريد إنشاء %0% الجديد', + createUnder: 'إنشاء عنصر تحت', + createContentBlueprint: 'حدد نوع الوثيقة الذي تريد إنشاء نموذج وثيقة له', + enterFolderName: 'أدخل اسم المجلد', + updateData: 'اختر نوعًا وعنوانًا', + noDocumentTypes: + 'لا توجد أنواع وثائق مسموح بها متاحة لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.', + noDocumentTypesAtRoot: + 'لا توجد أنواع وثائق متاحة لإنشاء المحتوى هنا. يجب عليك إنشاء هذه الأنواع في أنواع الوثائق ضمن قسم الإعدادات.', + noDocumentTypesWithNoSettingsAccess: 'الصفحة المحددة في شجرة المحتوى لا تسمح بإنشاء أي صفحات أسفلها.', + noDocumentTypesEditPermissions: 'تعديل الأذونات لهذا النوع من الوثائق', + noDocumentTypesCreateNew: 'إنشاء نوع وثيقة جديد', + noDocumentTypesAllowedAtRoot: + 'لا توجد أنواع وثائق مسموح بها لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تغيير خيار السماح كجذر ضمن الأذونات.', + noMediaTypes: + 'لا توجد أنواع وسائط مسموح بها لإنشاء الوسائط هنا. يجب تمكينها في أنواع الوسائط ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.', + noMediaTypesWithNoSettingsAccess: 'الوسائط المحددة في الشجرة لا تسمح بإنشاء أي وسائط أخرى أسفلها.', + noMediaTypesEditPermissions: 'تعديل الأذونات لهذا النوع من الوسائط', + documentTypeWithoutTemplate: 'نوع الوثيقة بدون قالب', + documentTypeWithTemplate: 'نوع الوثيقة مع قالب', + documentTypeWithTemplateDescription: + 'تعريف البيانات لصفحة محتوى يمكن إنشاؤها من قبل المحررين في شجرة المحتوى ويمكن الوصول إليها مباشرة عبر URL.', + documentType: 'نوع الوثيقة', + documentTypeDescription: + 'تعريف البيانات لمكون محتوى يمكن إنشاؤه من قبل المحررين في شجرة المحتوى ويمكن اختياره في صفحات أخرى ولكنه لا يحتوي على URL مباشر.', + elementType: 'نوع العنصر', + elementTypeDescription: + "يحدد المخطط لمجموعة متكررة من الخصائص، على سبيل المثال، في محرر 'قائمة الكتل' أو 'شبكة الكتل'.", + composition: 'تركيب', + compositionDescription: + "يحدد مجموعة قابلة لإعادة الاستخدام من الخصائص يمكن تضمينها في تعريف أنواع وثائق متعددة. على سبيل المثال، مجموعة من 'إعدادات الصفحة المشتركة'.", + folder: 'مجلد', + folderDescription: + 'يستخدم لتنظيم أنواع الوثائق، والتركيبات، وأنواع العناصر التي تم إنشاؤها في شجرة نوع الوثيقة هذه.', + newFolder: 'مجلد جديد', + newDataType: 'نوع بيانات جديد', + newJavascriptFile: 'ملف JavaScript جديد', + newEmptyPartialView: 'عرض جزئي فارغ جديد', + newPartialViewMacro: 'ماكرو عرض جزئي جديد', + newPartialViewFromSnippet: 'عرض جزئي جديد من مقطع', + newPartialViewMacroFromSnippet: 'ماكرو عرض جزئي جديد من مقطع', + newPartialViewMacroNoMacro: 'ماكرو عرض جزئي جديد (بدون ماكرو)', + newStyleSheetFile: 'ملف ورقة أنماط جديد', + newRteStyleSheetFile: 'ملف ورقة أنماط محرر النصوص الغني الجديد', + }, + dashboard: { + browser: 'تصفح موقعك', + dontShowAgain: '- إخفاء', + nothinghappens: 'إذا لم يفتح Umbraco، قد تحتاج إلى السماح بالنوافذ المنبثقة من هذا الموقع', + openinnew: 'تم فتحه في نافذة جديدة', + restart: 'إعادة تشغيل', + visit: 'زيارة', + welcome: 'مرحبا', + }, + prompt: { + stay: 'ابق', + discardChanges: 'تجاهل التغييرات', + unsavedChanges: 'لديك تغييرات غير محفوظة', + unsavedChangesWarning: 'هل أنت متأكد أنك تريد الانتقال بعيدًا عن هذه الصفحة؟ - لديك تغييرات غير محفوظة', + confirmListViewPublish: 'النشر سيجعل العناصر المحددة مرئية على الموقع.', + confirmListViewUnpublish: 'إلغاء النشر سيزيل العناصر المحددة وجميع نسلها من الموقع.', + confirmUnpublish: 'إلغاء النشر سيزيل هذه الصفحة وجميع نسلها من الموقع.', + doctypeChangeWarning: 'لديك تغييرات غير محفوظة. إجراء تغييرات على نوع الوثيقة سيتسبب في تجاهل التغييرات.', + }, + bulk: { + done: 'تم', + deletedItem: 'تم حذف %0% عنصر', + deletedItems: 'تم حذف %0% عناصر', + deletedItemOfItem: 'تم حذف %0% من %1% عنصر', + deletedItemOfItems: 'تم حذف %0% من %1% عناصر', + publishedItem: 'تم نشر %0% عنصر', + publishedItems: 'تم نشر %0% عناصر', + publishedItemOfItem: 'تم نشر %0% من %1% عنصر', + publishedItemOfItems: 'تم نشر %0% من %1% عناصر', + unpublishedItem: 'تم إلغاء نشر %0% عنصر', + unpublishedItems: 'تم إلغاء نشر %0% عناصر', + unpublishedItemOfItem: 'تم إلغاء نشر %0% من %1% عنصر', + unpublishedItemOfItems: 'تم إلغاء نشر %0% من %1% عناصر', + movedItem: 'تم نقل %0% عنصر', + movedItems: 'تم نقل %0% عناصر', + movedItemOfItem: 'تم نقل %0% من %1% عنصر', + movedItemOfItems: 'تم نقل %0% من %1% عناصر', + copiedItem: 'تم نسخ %0% عنصر', + copiedItems: 'تم نسخ %0% عناصر', + copiedItemOfItem: 'تم نسخ %0% من %1% عنصر', + copiedItemOfItems: 'تم نسخ %0% من %1% عناصر', + }, + defaultdialogs: { + nodeNameLinkPicker: 'عنوان الرابط', + urlLinkPicker: 'الرابط', + anchorLinkPicker: 'مرساة / سلسلة استعلام', + anchorInsert: 'اسم', + closeThisWindow: 'أغلق هذه النافذة', + confirmdelete: 'هل أنت متأكد أنك تريد الحذف', + confirmdeleteNumberOfItems: 'هل أنت متأكد أنك تريد حذف %0% من %1% العناصر', + confirmdisable: 'هل أنت متأكد أنك تريد التعطيل', + confirmremove: 'هل أنت متأكد أنك تريد الإزالة', + confirmremoveusageof: 'هل أنت متأكد أنك تريد إزالة استخدام %0%', + confirmlogout: 'هل أنت متأكد؟', + confirmSure: 'هل أنت متأكد؟', + cut: 'قص', + editDictionary: 'تحرير عنصر القاموس', + editLanguage: 'تحرير اللغة', + editSelectedMedia: 'تحرير الوسائط المحددة', + insertAnchor: 'إدراج رابط محلي', + insertCharacter: 'إدراج حرف', + insertgraphicheadline: 'إدراج عنوان رسومي', + insertimage: 'إدراج صورة', + insertlink: 'إدراج رابط', + insertMacro: 'انقر لإضافة ماكرو', + inserttable: 'إدراج جدول', + languagedeletewarning: 'سيؤدي هذا إلى حذف اللغة', + languageChangeWarning: + 'قد يكون تغيير الثقافة للغة عملية مكلفة وستؤدي إلى إعادة بناء ذاكرة التخزين المؤقت للمحتوى والفهارس', + lastEdited: 'آخر تحرير', + link: 'رابط', + linkinternal: 'رابط داخلي:', + linklocaltip: 'عند استخدام الروابط المحلية، أدخل "#" أمام الرابط', + linknewwindow: 'فتح في نافذة جديدة؟', + macroDoesNotHaveProperties: 'هذا الماكرو لا يحتوي على خصائص يمكنك تحريرها', + paste: 'لصق', + permissionsEdit: 'تحرير الأذونات لـ', + permissionsSet: 'تعيين الأذونات لـ', + permissionsSetForGroup: 'تعيين الأذونات لـ %0% لمجموعة المستخدمين %1%', + permissionsHelp: 'اختر مجموعات المستخدمين التي تريد تعيين الأذونات لها', + recycleBinDeleting: 'يتم الآن حذف العناصر في سلة المهملات. يرجى عدم إغلاق هذه النافذة أثناء تنفيذ هذه العملية', + recycleBinIsEmpty: 'سلة المهملات فارغة الآن', + recycleBinWarning: 'عند حذف العناصر من سلة المهملات، ستختفي إلى الأبد', + regexSearchError: + "خدمة الويب الخاصة بـ regexlib.com تواجه حالياً بعض المشاكل، ونحن لا نملك السيطرة على ذلك. نحن آسفون لهذا الإزعاج.", + regexSearchHelp: "ابحث عن تعبير منتظم لإضافته كتحقق لحقل النموذج. مثال: 'بريد إلكتروني،' 'رمز بريدي'، 'عنوان URL'.", + removeMacro: 'إزالة الماكرو', + requiredField: 'حقل مطلوب', + sitereindexed: 'تمت إعادة فهرسة الموقع', + siterepublished: + 'تم تحديث ذاكرة التخزين المؤقت للموقع. جميع المحتويات المنشورة محدثة الآن، بينما تظل جميع المحتويات غير المنشورة كما هي', + siterepublishHelp: + 'سيتم تحديث ذاكرة التخزين المؤقت للموقع. سيتم تحديث جميع المحتويات المنشورة، بينما ستظل المحتويات غير المنشورة كما هي.', + tableColumns: 'عدد الأعمدة', + tableRows: 'عدد الصفوف', + thumbnailimageclickfororiginal: 'انقر على الصورة لرؤية الحجم الكامل', + treepicker: 'اختيار العنصر', + viewCacheItem: 'عرض عنصر ذاكرة التخزين المؤقت', + relateToOriginalLabel: 'يرتبط بالأصل', + includeDescendants: 'تضمين الأحفاد', + theFriendliestCommunity: 'أكثر مجتمع ودود', + linkToPage: 'رابط إلى الصفحة', + openInNewWindow: 'فتح الوثيقة المرتبطة في نافذة أو علامة تبويب جديدة', + linkToMedia: 'رابط إلى الوسائط', + selectContentStartNode: 'اختر العقدة الأساسية للمحتوى', + selectMedia: 'اختر الوسائط', + selectMediaType: 'اختر نوع الوسائط', + selectIcon: 'اختر الأيقونة', + selectItem: 'اختر العنصر', + selectLink: 'اختر الرابط', + selectMacro: 'اختر الماكرو', + selectContent: 'اختر المحتوى', + selectContentType: 'اختر نوع المحتوى', + selectMediaStartNode: 'اختر العقدة الأساسية للوسائط', + selectMember: 'اختر العضو', + selectMembers: 'اختر الأعضاء', + selectMemberGroup: 'اختر مجموعة الأعضاء', + selectMemberType: 'اختر نوع العضو', + selectNode: 'اختر العقدة', + selectLanguages: 'اختر اللغات', + selectSections: 'اختر الأقسام', + selectUser: 'اختر المستخدم', + selectUsers: 'اختر المستخدمين', + noIconsFound: 'لم يتم العثور على أيقونات', + noMacroParams: 'لا توجد معلمات لهذا الماكرو', + noMacros: 'لا توجد ماكروات لإدراجها', + externalLoginProviders: 'تسجيل الدخول الخارجي', + exceptionDetail: 'تفاصيل الاستثناء', + stacktrace: 'التتبع الكامل', + innerException: 'الاستثناء الداخلي', + linkYour: 'ربط حساب {0} الخاص بك', + linkYourConfirm: 'أنت على وشك ربط حسابك في Umbraco وحسابك في {0} وسيتم توجيهك إلى {0} للتأكيد.', + unLinkYour: 'إلغاء ربط حساب {0} الخاص بك', + unLinkYourConfirm: 'أنت على وشك إلغاء ربط حسابك في Umbraco وحسابك في {0} وسيتم تسجيل خروجك.', + linkedToService: 'حسابك مرتبط بهذه الخدمة', + selectEditor: 'اختر المحرر', + selectEditorConfiguration: 'اختر التكوين', + selectSnippet: 'اختر الشريحة', + variantdeletewarning: + 'سيؤدي ذلك إلى حذف العقدة وجميع اللغات المرتبطة بها. إذا كنت ترغب فقط في حذف لغة واحدة، يجب عليك إلغاء نشر العقدة في تلك اللغة بدلاً من ذلك.', + propertyuserpickerremovewarning: 'سيتم إزالة المستخدم %0%.', + userremovewarning: 'سيتم إزالة المستخدم %0% من المجموعة %1%', + yesRemove: 'نعم، أزل', + deleteLayout: 'أنت تقوم بحذف التخطيط', + deletingALayout: 'سيؤدي تعديل التخطيط إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.', + }, dictionary: { importDictionaryItemHelp: '\n لاستيراد عنصر قاموس، ابحث عن ملف ".udt" على جهاز الكمبيوتر الخاص بك بالنقر على زر "استيراد"\n (سيُطلب منك التأكيد في الشاشة التالية)\n ', @@ -554,8 +574,7 @@ export default { }, examineManagement: { configuredSearchers: 'باحثون مكوّنون', - configuredSearchersDescription: - 'يعرض الخصائص والأدوات لأي باحث مكوّن (مثل الباحث متعدد الفهارس)', + configuredSearchersDescription: 'يعرض الخصائص والأدوات لأي باحث مكوّن (مثل الباحث متعدد الفهارس)', fieldValues: 'قيم الحقول', healthStatus: 'حالة الصحة', healthStatusDescription: 'حالة صحة الفهرس وما إذا كان يمكن قراءته', @@ -564,8 +583,7 @@ export default { contentInIndex: 'المحتوى في الفهرس', indexInfoDescription: 'يعرض خصائص الفهرس', manageIndexes: 'إدارة فهارس Examine', - manageIndexesDescription: - 'يسمح لك بمشاهدة تفاصيل كل فهرس ويوفر بعض الأدوات لإدارة الفهارس', + manageIndexesDescription: 'يسمح لك بمشاهدة تفاصيل كل فهرس ويوفر بعض الأدوات لإدارة الفهارس', rebuildIndex: 'إعادة بناء الفهرس', rebuildIndexWarning: 'سيؤدي هذا إلى إعادة بناء الفهرس.
بناءً على حجم المحتوى الموجود في موقعك، قد يستغرق هذا بعض الوقت.
لا يُنصح بإعادة بناء الفهرس في أوقات حركة المرور العالية على الموقع أو عند قيام المحررين بتحرير المحتوى.', @@ -630,8 +648,7 @@ export default { selectFolder: 'اختر المجلد للتحريك', inTheTree: 'إلى في هيكل الشجرة أدناه', wasMoved: 'تم نقله تحت', - hasReferencesDeleteConsequence: - 'حذف %0% سيؤدي إلى حذف الخصائص وبياناتها من العناصر التالية', + hasReferencesDeleteConsequence: 'حذف %0% سيؤدي إلى حذف الخصائص وبياناتها من العناصر التالية', acceptDeleteConsequence: 'أفهم أن هذا الإجراء سيؤدي إلى حذف الخصائص والبيانات الوثائق إلى هذا النوع من البيانات\n \n ', }, @@ -657,19 +674,19 @@ export default { receivedErrorFromServer: 'تم استلام خطأ من الخادم', dissallowedMediaType: 'تم رفض نوع الملف المحدد من قبل المسؤول', codemirroriewarning: - "ملاحظة! حتى مع تمكين CodeMirror عن طريق التكوين، فإنه معطل في\n Internet Explorer لأنه ليس مستقرًا بما فيه الكفاية.\n ", + 'ملاحظة! حتى مع تمكين CodeMirror عن طريق التكوين، فإنه معطل في\n Internet Explorer لأنه ليس مستقرًا بما فيه الكفاية.\n ', contentTypeAliasAndNameNotNull: 'يرجى ملء كل من الاسم المستعار والاسم في نوع الخاصية الجديد!', filePermissionsError: 'هناك مشكلة في الوصول للقراءة/الكتابة لملف أو مجلد محدد', macroErrorLoadingPartialView: 'خطأ في تحميل برنامج عرض جزئي (الملف: %0%)', missingTitle: 'يرجى إدخال عنوان', missingType: 'يرجى اختيار نوع', pictureResizeBiggerThanOrg: - "أنت على وشك جعل الصورة أكبر من حجمها الأصلي. هل أنت متأكد\n أنك تريد المتابعة؟\n ", + 'أنت على وشك جعل الصورة أكبر من حجمها الأصلي. هل أنت متأكد\n أنك تريد المتابعة؟\n ', startNodeDoesNotExists: 'تم حذف العقدة البداية، يرجى الاتصال بالمسؤول الخاص بك', stylesMustMarkBeforeSelect: 'يرجى تمييز المحتوى قبل تغيير النمط', stylesNoStylesOnPage: 'لا توجد أنماط نشطة متاحة', tableColMergeLeft: 'يرجى وضع المؤشر على يسار الخليتين اللتين ترغب في دمجهما', - tableSplitNotSplittable: "لا يمكنك تقسيم خلية لم يتم دمجها.", + tableSplitNotSplittable: 'لا يمكنك تقسيم خلية لم يتم دمجها.', propertyHasErrors: 'هذه الخاصية غير صالحة', externalLoginError: 'تسجيل الدخول الخارجي', unauthorized: 'لم تكن مصرحًا لك قبل القيام بهذا الإجراء', @@ -691,7 +708,7 @@ export default { serverError: 'خطأ في الخادم', temporarilyUnavailable: 'الخدمة غير متاحة مؤقتًا', }, - general: { + general: { options: 'خيارات', about: 'حول', action: 'إجراء', @@ -908,690 +925,745 @@ export default { headers: { page: 'صفحة', }, - installer: { - databaseErrorCannotConnect: "لا يمكن للمثبت الاتصال بقاعدة البيانات.", - databaseErrorWebConfig: "تعذر حفظ ملف web.config. يرجى تعديل سلسلة الاتصال يدويًا.", - databaseFound: "تم العثور على قاعدة بياناتك وتم التعرف عليها كـ", - databaseHeader: "تكوين قاعدة البيانات", - databaseInstall: "اضغط على زر التثبيت لتثبيت قاعدة بيانات Umbraco %0%", - databaseInstallDone: "تم نسخ Umbraco %0% الآن إلى قاعدة بياناتك. اضغط على التالي للمتابعة.", - databaseNotFound: "

لم يتم العثور على قاعدة البيانات! يرجى التحقق من أن المعلومات في سلسلة الاتصال في ملف \"web.config\" صحيحة.

\n

للمتابعة، يرجى تعديل ملف \"web.config\" (باستخدام Visual Studio أو محرر النصوص المفضل لديك)، والتمرير إلى الأسفل، وإضافة سلسلة الاتصال لقاعدة البيانات الخاصة بك في المفتاح المسمى \"UmbracoDbDSN\" وحفظ الملف.

\n

اضغط على زر إعادة المحاولة عند الانتهاء.
\n\t\t\t مزيد من المعلومات حول تحرير web.config هنا.

", - databaseText: "لإكمال هذه الخطوة، يجب أن تكون لديك بعض المعلومات حول خادم قاعدة البيانات الخاص بك (\"سلسلة الاتصال\").
\n يرجى الاتصال بمزود خدمة الإنترنت الخاص بك إذا لزم الأمر.\n إذا كنت تقوم بالتثبيت على جهاز محلي أو خادم، قد تحتاج إلى معلومات من مسؤول النظام الخاص بك.", - databaseUpgrade: "

اضغط على زر الترقية لترقية قاعدة البيانات إلى Umbraco %0%

\n

لا تقلق - لن يتم حذف أي محتوى وكل شيء سيستمر في العمل بعد ذلك!

", - databaseUpgradeDone: "تم ترقية قاعدة البيانات الخاصة بك إلى الإصدار النهائي %0%.
اضغط على التالي للمتابعة.", - databaseUpToDate: "قاعدة البيانات الحالية محدثة! اضغط على التالي لمتابعة معالج التكوين", - defaultUserChangePass: "يجب تغيير كلمة مرور المستخدم الافتراضي!", - defaultUserDisabled: "تم تعطيل المستخدم الافتراضي أو لا يمكنه الوصول إلى Umbraco!

لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.", - defaultUserPassChanged: "تم تغيير كلمة مرور المستخدم الافتراضي بنجاح منذ التثبيت!

لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.", - defaultUserPasswordChanged: "تم تغيير كلمة المرور!", - greatStart: "ابدأ بداية رائعة، شاهد مقاطع الفيديو التمهيدية الخاصة بنا", - licenseText: "بالنقر على الزر التالي (أو تعديل umbracoConfigurationStatus في web.config)، فإنك توافق على رخصة هذا البرنامج كما هو موضح في الصندوق أدناه. لاحظ أن توزيع Umbraco يتكون من رخصتين مختلفتين، رخصة MIT مفتوحة المصدر للإطار ورخصة البرمجيات المجانية الخاصة بـ Umbraco التي تغطي واجهة المستخدم.", - None: "لم يتم تثبيته بعد.", - permissionsAffectedFolders: "الملفات والمجلدات المتأثرة", - permissionsAffectedFoldersMoreInfo: "مزيد من المعلومات حول إعداد الأذونات لـ Umbraco هنا", - permissionsAffectedFoldersText: "يجب منح أذونات تعديل لـ ASP.NET على الملفات/المجلدات التالية", - permissionsAlmostPerfect: "إعدادات الأذونات الخاصة بك تقريبًا مثالية!

\n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.", - permissionsHowtoResolve: "كيفية الحل", - permissionsHowtoResolveLink: "اضغط هنا لقراءة النسخة النصية", - permissionsHowtoResolveText: "شاهد الفيديو التعليمي الخاص بإعداد أذونات المجلدات لـ Umbraco أو اقرأ النسخة النصية.", - permissionsMaybeAnIssue: "قد تكون إعدادات الأذونات الخاصة بك مشكلة!\n

\n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من إنشاء مجلدات أو تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.", - permissionsNotReady: "إعدادات الأذونات الخاصة بك غير جاهزة لـ Umbraco!\n

\n لتشغيل Umbraco، ستحتاج إلى تحديث إعدادات الأذونات الخاصة بك.", - permissionsPerfect: "إعدادات الأذونات الخاصة بك مثالية!

\n أنت جاهز لتشغيل Umbraco وتثبيت الحزم!", - permissionsResolveFolderIssues: "حل مشكلة المجلد", - permissionsResolveFolderIssuesLink: "اتبع هذا الرابط للحصول على مزيد من المعلومات حول مشاكل ASP.NET وإنشاء المجلدات", - permissionsSettingUpPermissions: "إعداد أذونات المجلدات", - permissionsText: "يحتاج Umbraco إلى أذونات الكتابة/التعديل لبعض الأدلة لتخزين الملفات مثل الصور وملفات PDF. كما أنه يخزن بيانات مؤقتة (المعروفة باسم: ذاكرة التخزين المؤقت) لتحسين أداء موقع الويب الخاص بك.", - runwayFromScratch: "أريد البدء من الصفر", - runwayFromScratchText: "موقع الويب الخاص بك فارغ تمامًا في الوقت الحالي، وهذا مثالي إذا كنت ترغب في البدء من الصفر وإنشاء الأنواع الوثائق والقوالب الخاصة بك. (تعرف على الكيفية) لا يزال بإمكانك اختيار تثبيت Runway لاحقًا. يرجى الانتقال إلى قسم المطور واختيار الحزم.", - runwayHeader: "لقد قمت بإعداد منصة Umbraco نظيفة. ماذا تريد أن تفعل بعد ذلك؟", - runwayInstalled: "تم تثبيت Runway", - runwayInstalledText: "لديك الأساس في مكانه. اختر الوحدات التي ترغب في تثبيتها فوقه.
\n هذه هي قائمتنا الموصى بها من الوحدات، قم بتحديد الوحدات التي ترغب في تثبيتها، أو عرض القائمة الكاملة للوحدات", - runwayOnlyProUsers: "يوصى بها فقط للمستخدمين ذوي الخبرة", - runwaySimpleSite: "أريد البدء بموقع ويب بسيط", - runwaySimpleSiteText: "

\"Runway\" هو موقع ويب بسيط يوفر بعض الأنواع الوثائق والقوالب الأساسية. يمكن للمثبت إعداد Runway لك تلقائيًا، لكن يمكنك بسهولة تحريره أو توسيعه أو إزالته. ليس ضروريًا ويمكنك استخدام Umbraco بشكل مثالي بدونها. ومع ذلك، يوفر Runway أساسًا سهلًا يعتمد على أفضل الممارسات لبدء التشغيل بسرعة أكبر من أي وقت مضى. إذا اخترت تثبيت Runway، يمكنك اختيار الوحدات الأساسية الاختيارية المعروفة باسم وحدات Runway لتعزيز صفحات Runway الخاصة بك.

\n متضمن مع Runway: الصفحة الرئيسية، صفحة البدء، صفحة تثبيت الوحدات.
\n الوحدات الاختيارية: التنقل العلوي، خريطة الموقع، الاتصال، المعرض.
", - runwayWhatIsRunway: "ما هو Runway", - step1: "الخطوة 1/5 قبول الترخيص", - step2: "الخطوة 2/5: تكوين قاعدة البيانات", - step3: "الخطوة 3/5: التحقق من أذونات الملفات", - step4: "الخطوة 4/5: التحقق من أمان Umbraco", - step5: "الخطوة 5/5: Umbraco جاهز للبدء", - thankYou: "شكرًا لاختيارك Umbraco", - theEndBrowseSite: "

تصفح موقعك الجديد

\nلقد قمت بتثبيت Runway، فلماذا لا ترى كيف يبدو موقع الويب الجديد الخاص بك.", - theEndFurtherHelp: "

مزيد من المساعدة والمعلومات

\nاحصل على المساعدة من مجتمعنا الحائز على جوائز، تصفح الوثائق أو شاهد بعض مقاطع الفيديو المجانية حول كيفية بناء موقع بسيط، كيفية استخدام الحزم ودليل سريع لمصطلحات Umbraco", - theEndHeader: "تم تثبيت Umbraco %0% وهو جاهز للاستخدام", - theEndInstallFailed: "لإكمال التثبيت، ستحتاج إلى تحرير /web.config file يدويًا وتحديث المفتاح AppSetting UmbracoConfigurationStatus في الأسفل إلى القيمة '%0%'.", - theEndInstallSuccess: "يمكنك البدء فورًا بالنقر على زر \"إطلاق Umbraco\" أدناه.
إذا كنت جديدًا على Umbraco، يمكنك العثور على الكثير من الموارد على صفحات البدء الخاصة بنا.", - theEndOpenUmbraco: "

إطلاق Umbraco

\nلإدارة موقع الويب الخاص بك، افتح ببساطة الخلفية لـ Umbraco وابدأ بإضافة المحتوى أو تحديث القوالب والأنماط أو إضافة ميزات جديدة", - Unavailable: "فشل الاتصال بقاعدة البيانات.", - Version3: "إصدار Umbraco 3", - Version4: "إصدار Umbraco 4", - watch: "شاهد", - welcomeIntro: "سيقوم هذا المعالج بتوجيهك خلال عملية تكوين Umbraco %0% لتثبيت جديد أو الترقية من الإصدار 3.0.\n

\n اضغط على التالي لبدء المعالج." - }, + installer: { + databaseErrorCannotConnect: 'لا يمكن للمثبت الاتصال بقاعدة البيانات.', + databaseErrorWebConfig: 'تعذر حفظ ملف web.config. يرجى تعديل سلسلة الاتصال يدويًا.', + databaseFound: 'تم العثور على قاعدة بياناتك وتم التعرف عليها كـ', + databaseHeader: 'تكوين قاعدة البيانات', + databaseInstall: 'اضغط على زر التثبيت لتثبيت قاعدة بيانات Umbraco %0%', + databaseInstallDone: 'تم نسخ Umbraco %0% الآن إلى قاعدة بياناتك. اضغط على التالي للمتابعة.', + databaseNotFound: + '

لم يتم العثور على قاعدة البيانات! يرجى التحقق من أن المعلومات في سلسلة الاتصال في ملف "web.config" صحيحة.

\n

للمتابعة، يرجى تعديل ملف "web.config" (باستخدام Visual Studio أو محرر النصوص المفضل لديك)، والتمرير إلى الأسفل، وإضافة سلسلة الاتصال لقاعدة البيانات الخاصة بك في المفتاح المسمى "UmbracoDbDSN" وحفظ الملف.

\n

اضغط على زر إعادة المحاولة عند الانتهاء.
\n\t\t\t مزيد من المعلومات حول تحرير web.config هنا.

', + databaseText: + 'لإكمال هذه الخطوة، يجب أن تكون لديك بعض المعلومات حول خادم قاعدة البيانات الخاص بك ("سلسلة الاتصال").
\n يرجى الاتصال بمزود خدمة الإنترنت الخاص بك إذا لزم الأمر.\n إذا كنت تقوم بالتثبيت على جهاز محلي أو خادم، قد تحتاج إلى معلومات من مسؤول النظام الخاص بك.', + databaseUpgrade: + '

اضغط على زر الترقية لترقية قاعدة البيانات إلى Umbraco %0%

\n

لا تقلق - لن يتم حذف أي محتوى وكل شيء سيستمر في العمل بعد ذلك!

', + databaseUpgradeDone: + 'تم ترقية قاعدة البيانات الخاصة بك إلى الإصدار النهائي %0%.
اضغط على التالي للمتابعة.', + databaseUpToDate: 'قاعدة البيانات الحالية محدثة! اضغط على التالي لمتابعة معالج التكوين', + defaultUserChangePass: 'يجب تغيير كلمة مرور المستخدم الافتراضي!', + defaultUserDisabled: + 'تم تعطيل المستخدم الافتراضي أو لا يمكنه الوصول إلى Umbraco!

لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.', + defaultUserPassChanged: + 'تم تغيير كلمة مرور المستخدم الافتراضي بنجاح منذ التثبيت!

لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.', + defaultUserPasswordChanged: 'تم تغيير كلمة المرور!', + greatStart: 'ابدأ بداية رائعة، شاهد مقاطع الفيديو التمهيدية الخاصة بنا', + licenseText: + 'بالنقر على الزر التالي (أو تعديل umbracoConfigurationStatus في web.config)، فإنك توافق على رخصة هذا البرنامج كما هو موضح في الصندوق أدناه. لاحظ أن توزيع Umbraco يتكون من رخصتين مختلفتين، رخصة MIT مفتوحة المصدر للإطار ورخصة البرمجيات المجانية الخاصة بـ Umbraco التي تغطي واجهة المستخدم.', + None: 'لم يتم تثبيته بعد.', + permissionsAffectedFolders: 'الملفات والمجلدات المتأثرة', + permissionsAffectedFoldersMoreInfo: 'مزيد من المعلومات حول إعداد الأذونات لـ Umbraco هنا', + permissionsAffectedFoldersText: 'يجب منح أذونات تعديل لـ ASP.NET على الملفات/المجلدات التالية', + permissionsAlmostPerfect: + 'إعدادات الأذونات الخاصة بك تقريبًا مثالية!

\n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.', + permissionsHowtoResolve: 'كيفية الحل', + permissionsHowtoResolveLink: 'اضغط هنا لقراءة النسخة النصية', + permissionsHowtoResolveText: + 'شاهد الفيديو التعليمي الخاص بإعداد أذونات المجلدات لـ Umbraco أو اقرأ النسخة النصية.', + permissionsMaybeAnIssue: + 'قد تكون إعدادات الأذونات الخاصة بك مشكلة!\n

\n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من إنشاء مجلدات أو تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.', + permissionsNotReady: + 'إعدادات الأذونات الخاصة بك غير جاهزة لـ Umbraco!\n

\n لتشغيل Umbraco، ستحتاج إلى تحديث إعدادات الأذونات الخاصة بك.', + permissionsPerfect: + 'إعدادات الأذونات الخاصة بك مثالية!

\n أنت جاهز لتشغيل Umbraco وتثبيت الحزم!', + permissionsResolveFolderIssues: 'حل مشكلة المجلد', + permissionsResolveFolderIssuesLink: + 'اتبع هذا الرابط للحصول على مزيد من المعلومات حول مشاكل ASP.NET وإنشاء المجلدات', + permissionsSettingUpPermissions: 'إعداد أذونات المجلدات', + permissionsText: + 'يحتاج Umbraco إلى أذونات الكتابة/التعديل لبعض الأدلة لتخزين الملفات مثل الصور وملفات PDF. كما أنه يخزن بيانات مؤقتة (المعروفة باسم: ذاكرة التخزين المؤقت) لتحسين أداء موقع الويب الخاص بك.', + runwayFromScratch: 'أريد البدء من الصفر', + runwayFromScratchText: + 'موقع الويب الخاص بك فارغ تمامًا في الوقت الحالي، وهذا مثالي إذا كنت ترغب في البدء من الصفر وإنشاء الأنواع الوثائق والقوالب الخاصة بك. (تعرف على الكيفية) لا يزال بإمكانك اختيار تثبيت Runway لاحقًا. يرجى الانتقال إلى قسم المطور واختيار الحزم.', + runwayHeader: 'لقد قمت بإعداد منصة Umbraco نظيفة. ماذا تريد أن تفعل بعد ذلك؟', + runwayInstalled: 'تم تثبيت Runway', + runwayInstalledText: + 'لديك الأساس في مكانه. اختر الوحدات التي ترغب في تثبيتها فوقه.
\n هذه هي قائمتنا الموصى بها من الوحدات، قم بتحديد الوحدات التي ترغب في تثبيتها، أو عرض القائمة الكاملة للوحدات', + runwayOnlyProUsers: 'يوصى بها فقط للمستخدمين ذوي الخبرة', + runwaySimpleSite: 'أريد البدء بموقع ويب بسيط', + runwaySimpleSiteText: + '

"Runway" هو موقع ويب بسيط يوفر بعض الأنواع الوثائق والقوالب الأساسية. يمكن للمثبت إعداد Runway لك تلقائيًا، لكن يمكنك بسهولة تحريره أو توسيعه أو إزالته. ليس ضروريًا ويمكنك استخدام Umbraco بشكل مثالي بدونها. ومع ذلك، يوفر Runway أساسًا سهلًا يعتمد على أفضل الممارسات لبدء التشغيل بسرعة أكبر من أي وقت مضى. إذا اخترت تثبيت Runway، يمكنك اختيار الوحدات الأساسية الاختيارية المعروفة باسم وحدات Runway لتعزيز صفحات Runway الخاصة بك.

\n متضمن مع Runway: الصفحة الرئيسية، صفحة البدء، صفحة تثبيت الوحدات.
\n الوحدات الاختيارية: التنقل العلوي، خريطة الموقع، الاتصال، المعرض.
', + runwayWhatIsRunway: 'ما هو Runway', + step1: 'الخطوة 1/5 قبول الترخيص', + step2: 'الخطوة 2/5: تكوين قاعدة البيانات', + step3: 'الخطوة 3/5: التحقق من أذونات الملفات', + step4: 'الخطوة 4/5: التحقق من أمان Umbraco', + step5: 'الخطوة 5/5: Umbraco جاهز للبدء', + thankYou: 'شكرًا لاختيارك Umbraco', + theEndBrowseSite: + '

تصفح موقعك الجديد

\nلقد قمت بتثبيت Runway، فلماذا لا ترى كيف يبدو موقع الويب الجديد الخاص بك.', + theEndFurtherHelp: + '

مزيد من المساعدة والمعلومات

\nاحصل على المساعدة من مجتمعنا الحائز على جوائز، تصفح الوثائق أو شاهد بعض مقاطع الفيديو المجانية حول كيفية بناء موقع بسيط، كيفية استخدام الحزم ودليل سريع لمصطلحات Umbraco', + theEndHeader: 'تم تثبيت Umbraco %0% وهو جاهز للاستخدام', + theEndInstallFailed: + "لإكمال التثبيت، ستحتاج إلى تحرير /web.config file يدويًا وتحديث المفتاح AppSetting UmbracoConfigurationStatus في الأسفل إلى القيمة '%0%'.", + theEndInstallSuccess: + 'يمكنك البدء فورًا بالنقر على زر "إطلاق Umbraco" أدناه.
إذا كنت جديدًا على Umbraco، يمكنك العثور على الكثير من الموارد على صفحات البدء الخاصة بنا.', + theEndOpenUmbraco: + '

إطلاق Umbraco

\nلإدارة موقع الويب الخاص بك، افتح ببساطة الخلفية لـ Umbraco وابدأ بإضافة المحتوى أو تحديث القوالب والأنماط أو إضافة ميزات جديدة', + Unavailable: 'فشل الاتصال بقاعدة البيانات.', + Version3: 'إصدار Umbraco 3', + Version4: 'إصدار Umbraco 4', + watch: 'شاهد', + welcomeIntro: + 'سيقوم هذا المعالج بتوجيهك خلال عملية تكوين Umbraco %0% لتثبيت جديد أو الترقية من الإصدار 3.0.\n

\n اضغط على التالي لبدء المعالج.', + }, language: { - cultureCode: 'رمز الثقافة', - displayName: 'اسم الثقافة', - noFallbackLanguages: 'لا توجد لغات أخرى للاختيار من بينها', - }, - lockout: { - lockoutWillOccur: "لقد كنت غير نشط وسيتم تسجيل خروجك تلقائيًا في", - renewSession: 'جدد الآن لحفظ عملك', - }, - login: { - greeting0: 'مرحبًا! بداية أسبوع مثمرة مع Umbraco!', - greeting1: 'مرحبًا! يوم ثلاثاء إبداعي في Umbraco!', - greeting2: 'مرحبًا! يوم أربعاء موفق في إدارة محتواك!', - greeting3: 'مرحبًا! يوم خميس مليء بالإنجازات مع Umbraco!', - greeting4: 'مرحبًا! إنه يوم جمعة رائع لإدارة محتوى موقعك!', - greeting5: 'مرحبًا! عطلة نهاية أسبوع سعيدة مع Umbraco!', - greeting6: 'مرحبًا! يوم أحد جديد، فرص جديدة في Umbraco!', - instruction: 'سجل الدخول إلى Umbraco', - signInWith: 'سجل الدخول باستخدام {0}', - timeout: 'انتهت جلستك. يرجى تسجيل الدخول مرة أخرى أدناه.', - }, - main: { - dashboard: 'لوحة التحكم', - sections: 'الأقسام', - tree: 'المحتوى', - }, - moveOrCopy: { - choose: 'اختر الصفحة أعلاه...', - copyDone: '%0% تم نسخه إلى %1%', - copyTo: 'حدد المكان الذي يجب نسخ الوثيقة %0% إليه أدناه', - moveDone: '%0% تم نقله إلى %1%', - moveTo: 'حدد المكان الذي يجب نقل الوثيقة %0% إليه أدناه', - nodeSelected: "تم تحديده كجذر لمحتواك الجديد، انقر على 'موافق' أدناه.", - noNodeSelected: "لم يتم تحديد أي عقدة بعد، يرجى تحديد عقدة في القائمة أعلاه قبل النقر على 'موافق'", - notAllowedByContentType: 'العقدة الحالية غير مسموح بها تحت العقدة المحددة بسبب نوعها', - notAllowedByPath: 'لا يمكن نقل العقدة الحالية إلى إحدى صفحاتها الفرعية، ولا يمكن أن تكون الوالد والوجهة هي نفسها', - notAllowedAtRoot: 'لا يمكن أن توجد العقدة الحالية في الجذر', - notValid: "لا يُسمح بالإجراء نظرًا لأن لديك أذونات غير كافية على 1 أو أكثر من الوثيقة الفرعية.\n", - relateToOriginal: 'ربط العناصر المنسوخة بالأصل', - }, - notifications: { - editNotifications: 'حدد إشعارك لـ %0%', - notificationsSavedFor: 'تم حفظ إعدادات الإشعارات لـ', - notifications: 'الإشعارات', - }, - packager: { - actions: 'إجراءات', - created: 'أنشئ', - createPackage: 'إنشاء حزمة', - chooseLocalPackageText: '\n اختر حزمة من جهازك، بالنقر على زر تصفح
\n وتحديد الحزمة. عادةً ما تحتوي حزم Umbraco على امتداد ".umb" أو ".zip".\n ', - deletewarning: 'سيؤدي ذلك إلى حذف الحزمة', - includeAllChildNodes: 'تضمين جميع العقد الفرعية', - installed: 'مثبتة', - installedPackages: 'الحزم المثبتة', - installInstructions: 'تعليمات التثبيت', - noConfigurationView: 'لا تحتوي هذه الحزمة على عرض تكوين', - noPackagesCreated: 'لم يتم إنشاء أي حزم بعد', - noPackages: 'لم يتم تثبيت أي حزم', - noPackagesDescription: "تصفح الحزم المتاحة باستخدام أيقونة 'الحزم' في أعلى يمين الشاشة", - packageContent: 'محتوى الحزمة', - packageLicense: 'الرخصة', - packageSearch: 'البحث عن الحزم', - packageSearchResults: 'نتائج البحث عن', - packageNoResults: 'لم نجد شيئًا لـ', - packageNoResultsDescription: 'يرجى محاولة البحث عن حزمة أخرى أو تصفح الفئات\n', - packagesPopular: 'الأكثر شيوعًا', - packagesPromoted: 'مروج لها', - packagesNew: 'الإصدارات الجديدة', - packageHas: 'لديه', - packageKarmaPoints: 'نقاط الكارما', - packageInfo: 'معلومات', - packageOwner: 'المالك', - packageContrib: 'المساهمون', - packageCreated: 'أنشئ', - packageCurrentVersion: 'الإصدار الحالي', - packageNetVersion: 'إصدار .NET', - packageDownloads: 'التنزيلات', - packageLikes: 'الإعجابات', - packageCompatibility: 'التوافق', - packageCompatibilityDescription: 'تكون هذه الحزمة متوافقة مع الإصدارات التالية من Umbraco، حسب\n ما أبلغ عنه أعضاء المجتمع. لا يمكن ضمان التوافق الكامل للإصدارات المبلغ عنها أقل من 100%\n ', - packageExternalSources: 'المصادر الخارجية', - packageAuthor: 'المؤلف', - packageDocumentation: 'الوثائق', - packageMetaData: 'بيانات الحزمة', - packageName: 'اسم الحزمة', - packageNoItemsHeader: "لا تحتوي الحزمة على أي عناصر", - packageNoItemsText: 'لا تحتوي هذه الحزمة على أي عناصر لإلغاء التثبيت.

\n يمكنك إزالة هذا بأمان من النظام بالنقر على "إلغاء تثبيت الحزمة" أدناه.', - packageOptions: 'خيارات الحزمة', - packageMigrationsRun: 'تشغيل ترحيلات الحزمة المعلقة', - packageMigrationsComplete: 'تم إكمال ترحيلات الحزمة بنجاح.', - packageMigrationsNonePending: 'تم إكمال جميع ترحيلات الحزمة بنجاح.', - packageReadme: 'ملف README الخاص بالحزمة', - packageRepository: 'مستودع الحزمة', - packageUninstallConfirm: 'تأكيد إلغاء تثبيت الحزمة', - packageUninstalledHeader: 'تم إلغاء تثبيت الحزمة', - packageUninstalledText: 'تم إلغاء تثبيت الحزمة بنجاح', - packageUninstallHeader: 'إلغاء تثبيت الحزمة', - packageUninstallText: 'يمكنك إلغاء تحديد العناصر التي لا ترغب في إزالتها في الوقت الحالي أدناه. عند النقر على "تأكيد الإلغاء"، ستتم إزالة جميع العناصر المحددة.
\n ملاحظة: أي مستندات أو وسائط تعتمد على العناصر التي تقوم بإزالتها، ستتوقف عن العمل، وقد يؤدي ذلك إلى عدم استقرار النظام، لذا قم بإلغاء التثبيت بحذر. إذا كان لديك أي شكوك، اتصل بمؤلف الحزمة.', - packageVersion: 'إصدار الحزمة', - verifiedToWorkOnUmbracoCloud: 'تم التحقق من عمله على Umbraco Cloud', - }, + cultureCode: 'رمز الثقافة', + displayName: 'اسم الثقافة', + noFallbackLanguages: 'لا توجد لغات أخرى للاختيار من بينها', + }, + lockout: { + lockoutWillOccur: 'لقد كنت غير نشط وسيتم تسجيل خروجك تلقائيًا في', + renewSession: 'جدد الآن لحفظ عملك', + }, + login: { + greeting0: 'مرحبًا! بداية أسبوع مثمرة مع Umbraco!', + greeting1: 'مرحبًا! يوم ثلاثاء إبداعي في Umbraco!', + greeting2: 'مرحبًا! يوم أربعاء موفق في إدارة محتواك!', + greeting3: 'مرحبًا! يوم خميس مليء بالإنجازات مع Umbraco!', + greeting4: 'مرحبًا! إنه يوم جمعة رائع لإدارة محتوى موقعك!', + greeting5: 'مرحبًا! عطلة نهاية أسبوع سعيدة مع Umbraco!', + greeting6: 'مرحبًا! يوم أحد جديد، فرص جديدة في Umbraco!', + instruction: 'سجل الدخول إلى Umbraco', + signInWith: 'سجل الدخول باستخدام {0}', + timeout: 'انتهت جلستك. يرجى تسجيل الدخول مرة أخرى أدناه.', + }, + main: { + dashboard: 'لوحة التحكم', + sections: 'الأقسام', + tree: 'المحتوى', + }, + moveOrCopy: { + choose: 'اختر الصفحة أعلاه...', + copyDone: '%0% تم نسخه إلى %1%', + copyTo: 'حدد المكان الذي يجب نسخ الوثيقة %0% إليه أدناه', + moveDone: '%0% تم نقله إلى %1%', + moveTo: 'حدد المكان الذي يجب نقل الوثيقة %0% إليه أدناه', + nodeSelected: "تم تحديده كجذر لمحتواك الجديد، انقر على 'موافق' أدناه.", + noNodeSelected: "لم يتم تحديد أي عقدة بعد، يرجى تحديد عقدة في القائمة أعلاه قبل النقر على 'موافق'", + notAllowedByContentType: 'العقدة الحالية غير مسموح بها تحت العقدة المحددة بسبب نوعها', + notAllowedByPath: 'لا يمكن نقل العقدة الحالية إلى إحدى صفحاتها الفرعية، ولا يمكن أن تكون الوالد والوجهة هي نفسها', + notAllowedAtRoot: 'لا يمكن أن توجد العقدة الحالية في الجذر', + notValid: 'لا يُسمح بالإجراء نظرًا لأن لديك أذونات غير كافية على 1 أو أكثر من الوثيقة الفرعية.\n', + relateToOriginal: 'ربط العناصر المنسوخة بالأصل', + }, + notifications: { + editNotifications: 'حدد إشعارك لـ %0%', + notificationsSavedFor: 'تم حفظ إعدادات الإشعارات لـ', + notifications: 'الإشعارات', + }, + packager: { + actions: 'إجراءات', + created: 'أنشئ', + createPackage: 'إنشاء حزمة', + chooseLocalPackageText: + '\n اختر حزمة من جهازك، بالنقر على زر تصفح
\n وتحديد الحزمة. عادةً ما تحتوي حزم Umbraco على امتداد ".umb" أو ".zip".\n ', + deletewarning: 'سيؤدي ذلك إلى حذف الحزمة', + includeAllChildNodes: 'تضمين جميع العقد الفرعية', + installed: 'مثبتة', + installedPackages: 'الحزم المثبتة', + installInstructions: 'تعليمات التثبيت', + noConfigurationView: 'لا تحتوي هذه الحزمة على عرض تكوين', + noPackagesCreated: 'لم يتم إنشاء أي حزم بعد', + noPackages: 'لم يتم تثبيت أي حزم', + noPackagesDescription: "تصفح الحزم المتاحة باستخدام أيقونة 'الحزم' في أعلى يمين الشاشة", + packageContent: 'محتوى الحزمة', + packageLicense: 'الرخصة', + packageSearch: 'البحث عن الحزم', + packageSearchResults: 'نتائج البحث عن', + packageNoResults: 'لم نجد شيئًا لـ', + packageNoResultsDescription: 'يرجى محاولة البحث عن حزمة أخرى أو تصفح الفئات\n', + packagesPopular: 'الأكثر شيوعًا', + packagesPromoted: 'مروج لها', + packagesNew: 'الإصدارات الجديدة', + packageHas: 'لديه', + packageKarmaPoints: 'نقاط الكارما', + packageInfo: 'معلومات', + packageOwner: 'المالك', + packageContrib: 'المساهمون', + packageCreated: 'أنشئ', + packageCurrentVersion: 'الإصدار الحالي', + packageNetVersion: 'إصدار .NET', + packageDownloads: 'التنزيلات', + packageLikes: 'الإعجابات', + packageCompatibility: 'التوافق', + packageCompatibilityDescription: + 'تكون هذه الحزمة متوافقة مع الإصدارات التالية من Umbraco، حسب\n ما أبلغ عنه أعضاء المجتمع. لا يمكن ضمان التوافق الكامل للإصدارات المبلغ عنها أقل من 100%\n ', + packageExternalSources: 'المصادر الخارجية', + packageAuthor: 'المؤلف', + packageDocumentation: 'الوثائق', + packageMetaData: 'بيانات الحزمة', + packageName: 'اسم الحزمة', + packageNoItemsHeader: 'لا تحتوي الحزمة على أي عناصر', + packageNoItemsText: + 'لا تحتوي هذه الحزمة على أي عناصر لإلغاء التثبيت.

\n يمكنك إزالة هذا بأمان من النظام بالنقر على "إلغاء تثبيت الحزمة" أدناه.', + packageOptions: 'خيارات الحزمة', + packageMigrationsRun: 'تشغيل ترحيلات الحزمة المعلقة', + packageMigrationsComplete: 'تم إكمال ترحيلات الحزمة بنجاح.', + packageMigrationsNonePending: 'تم إكمال جميع ترحيلات الحزمة بنجاح.', + packageReadme: 'ملف README الخاص بالحزمة', + packageRepository: 'مستودع الحزمة', + packageUninstallConfirm: 'تأكيد إلغاء تثبيت الحزمة', + packageUninstalledHeader: 'تم إلغاء تثبيت الحزمة', + packageUninstalledText: 'تم إلغاء تثبيت الحزمة بنجاح', + packageUninstallHeader: 'إلغاء تثبيت الحزمة', + packageUninstallText: + 'يمكنك إلغاء تحديد العناصر التي لا ترغب في إزالتها في الوقت الحالي أدناه. عند النقر على "تأكيد الإلغاء"، ستتم إزالة جميع العناصر المحددة.
\n ملاحظة: أي مستندات أو وسائط تعتمد على العناصر التي تقوم بإزالتها، ستتوقف عن العمل، وقد يؤدي ذلك إلى عدم استقرار النظام، لذا قم بإلغاء التثبيت بحذر. إذا كان لديك أي شكوك، اتصل بمؤلف الحزمة.', + packageVersion: 'إصدار الحزمة', + verifiedToWorkOnUmbracoCloud: 'تم التحقق من عمله على Umbraco Cloud', + }, paste: { - doNothing: 'الصق مع التنسيق الكامل (غير موصى به)', - errorMessage: "النص الذي تحاول لصقه يحتوي على أحرف خاصة أو تنسيق. قد يكون ذلك بسبب نسخ النص من Microsoft Word. يمكن لـ Umbraco إزالة الأحرف الخاصة أو التنسيق تلقائيًا، بحيث يكون المحتوى الملصق أكثر ملاءمة للويب.\n", - removeAll: 'الصق كـ نص خام بدون أي تنسيق على الإطلاق', - removeSpecialFormattering: 'الصق، ولكن قم بإزالة التنسيق (موصى به)', - }, - publicAccess: { - paGroups: 'حماية قائمة على المجموعة', - paGroupsHelp: 'إذا كنت ترغب في منح الوصول إلى جميع أعضاء مجموعات الأعضاء المحددة', - paGroupsNoGroups: 'تحتاج إلى إنشاء مجموعة أعضاء قبل أن تتمكن من استخدام المصادقة القائمة على المجموعة', - paErrorPage: 'صفحة الخطأ', - paErrorPageHelp: 'تستخدم عندما يكون الأشخاص مسجلين الدخول، ولكن ليس لديهم وصول', - paHowWould: 'اختر كيفية تقييد الوصول إلى الصفحة %0%', - paIsProtected: '%0% محمية الآن', - paIsRemoved: 'تمت إزالة الحماية من %0%', - paLoginPage: 'صفحة تسجيل الدخول', - paLoginPageHelp: 'اختر الصفحة التي تحتوي على نموذج تسجيل الدخول', - paRemoveProtection: 'إزالة الحماية...', - paRemoveProtectionConfirm: 'هل أنت متأكد أنك تريد إزالة الحماية من الصفحة %0%؟', - paSelectPages: 'اختر الصفحات التي تحتوي على نموذج تسجيل الدخول ورسائل الخطأ', - paSelectGroups: 'اختر المجموعات التي لديها وصول إلى الصفحة %0%', - paSelectMembers: 'اختر الأعضاء الذين لديهم وصول إلى الصفحة %0%', - paMembers: 'حماية الأعضاء المحددين', - paMembersHelp: 'إذا كنت ترغب في منح الوصول إلى أعضاء محددين', - }, - publish: { - invalidPublishBranchPermissions: 'أذونات المستخدم غير كافية لنشر جميع الوثائق التابعة', - contentPublishedFailedIsTrashed: '\n %0% لم يتم نشره لأن العنصر في سلة المهملات.\n ', - contentPublishedFailedAwaitingRelease: '\n %0% لم يتم نشره لأن العنصر مجدول للإصدار.\n ', - contentPublishedFailedExpired: '\n %0% لم يتم نشره لأن العنصر منتهي الصلاحية.\n ', - contentPublishedFailedInvalid: '\n %0% لم يتم نشره لأن بعض الخصائص لم تتجاوز قواعد التحقق.\n ', - contentPublishedFailedByEvent: '\n %0% لم يتم نشره، ألغى ملحق طرف ثالث الإجراء.\n ', - contentPublishedFailedByParent: '\n %0% لا يمكن نشره، لأن صفحة الوالد غير منشورة.\n ', - contentPublishedFailedByMissingName: '%0% لا يمكن نشره، لأنه يفتقر إلى اسم.', - contentPublishedFailedReqCultureValidationError: "فشل التحقق من اللغة المطلوبة '%0%'. تم حفظ هذه اللغة ولكن لم يتم نشرها.\n", - inProgress: 'النشر جارٍ - يرجى الانتظار...', - inProgressCounter: '%0% من أصل %1% صفحات تم نشرها...', - nodePublish: '%0% تم نشره', - nodePublishAll: '%0% والصفحات الفرعية تم نشرها', - publishAll: 'نشر %0% وجميع الصفحات الفرعية الخاصة به', - publishHelp: 'انقر على نشر لنشر %0% وجعل محتواه متاحًا علنًا.

\n يمكنك نشر هذه الصفحة وجميع صفحاتها الفرعية عن طريق تحديد تضمين الصفحات الفرعية غير المنشورة أدناه.\n ', - }, - colorpicker: { - noColors: 'لم تقم بتكوين أي ألوان معتمدة', - }, - contentPicker: { - allowedItemTypes: 'يمكنك فقط اختيار العناصر من النوع(s): %0%', - defineDynamicRoot: 'حدد الجذر', - defineRootNode: 'اختر جذر العقدة', - pickedTrashedItem: 'لقد اخترت عنصر محتوى محذوف حاليًا أو في سلة المهملات', - pickedTrashedItems: 'لقد اخترت عناصر محتوى محذوفة حاليًا أو في سلة المهملات', - }, - dynamicRoot: { - configurationTitle: 'استعلام الجذر الديناميكي', - pickDynamicRootOriginTitle: 'اختر الأصل', - pickDynamicRootOriginDesc: 'حدد الأصل لاستعلام الجذر الديناميكي الخاص بك', - originRootTitle: 'الجذر', - originRootDesc: 'العقدة الجذرية لجلسة التحرير هذه', - originParentTitle: 'الوالد', - originParentDesc: 'العقدة الأم للمصدر في جلسة التحرير هذه', - originCurrentTitle: 'الحالي', - originCurrentDesc: 'عقدة المحتوى التي هي المصدر لجلسة التحرير هذه', - originSiteTitle: 'الموقع', - originSiteDesc: 'ابحث عن أقرب عقدة بها اسم مضيف', - originByKeyTitle: 'عقدة محددة', - originByKeyDesc: 'اختر عقدة محددة كأصل لهذا الاستعلام', - pickDynamicRootQueryStepTitle: 'أضف خطوة إلى الاستعلام', - pickDynamicRootQueryStepDesc: 'حدد الخطوة التالية لاستعلام الجذر الديناميكي الخاص بك', - queryStepNearestAncestorOrSelfTitle: 'أقرب سلف أو نفس', - queryStepNearestAncestorOrSelfDesc: 'استعلام أقرب سلف أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepFurthestAncestorOrSelfTitle: 'أبعد سلف أو نفس', - queryStepFurthestAncestorOrSelfDesc: 'استعلام أبعد سلف أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepNearestDescendantOrSelfTitle: 'أقرب نسل أو نفس', - queryStepNearestDescendantOrSelfDesc: 'استعلام أقرب نسل أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepFurthestDescendantOrSelfTitle: 'أبعد نسل أو نفس', - queryStepFurthestDescendantOrSelfDesc: 'استعلام أبعد نسل أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepCustomTitle: 'مخصص', - queryStepCustomDesc: 'استعلام باستخدام خطوة استعلام مخصصة', - addQueryStep: 'إضافة خطوة استعلام', - queryStepTypes: 'التي تتطابق مع الأنواع: ', - noValidStartNodeTitle: 'لا توجد محتويات متطابقة', - noValidStartNodeDesc: 'تكوين هذه الخاصية لا يتطابق مع أي محتوى. أنشئ المحتوى المفقود أو اتصل بمسؤولك لضبط إعدادات الجذر الديناميكي لهذه الخاصية.', - }, - mediaPicker: { - deletedItem: 'عنصر محذوف', - pickedTrashedItem: 'لقد اخترت عنصر وسائط محذوف حاليًا أو في سلة المهملات', - pickedTrashedItems: 'لقد اخترت عناصر وسائط محذوفة حاليًا أو في سلة المهملات', - trashed: 'محذوف', - openMedia: 'افتح في مكتبة الوسائط', - changeMedia: 'تغيير عنصر الوسائط', - editMediaEntryLabel: 'تحرير %0% على %1%', - confirmCancelMediaEntryCreationHeadline: 'تجاهل الإنشاء؟', - confirmCancelMediaEntryCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', - confirmCancelMediaEntryHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد\n تجاهلها؟\n ', - confirmRemoveAllMediaEntryMessage: 'إزالة جميع الوسائط؟', - tabClipboard: 'الحافظة', - notAllowed: 'غير مسموح', - openMediaPicker: 'افتح محدد الوسائط', - }, - propertyEditorPicker: { - title: 'اختر محرر الخصائص', - openPropertyEditorPicker: 'اختر واجهة مستخدم محرر الخصائص', - }, - relatedlinks: { - enterExternal: 'أدخل رابط خارجي', - chooseInternal: 'اختر صفحة داخلية', - caption: 'التسمية التوضيحية', - link: 'رابط', - newWindow: 'فتح في نافذة جديدة', - captionPlaceholder: 'أدخل التسمية التوضيحية للعرض', - externalLinkPlaceholder: 'أدخل الرابط', - }, - imagecropper: { - reset: 'إعادة تعيين', - updateEditCrop: 'تم', - undoEditCrop: 'تراجع عن التعديلات', - customCrop: 'مخصص', - }, - rollback: { - changes: 'التغييرات', - created: 'أنشئ', - headline: 'اختر إصدارًا للمقارنة مع الإصدار الحالي', - currentVersion: 'الإصدار الحالي', - diffHelp: 'يظهر هذا الاختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد
النص الأحمر سيتم حذفه في الإصدار المحدد، النص الأخضر سيتم إضافته', - noDiff: 'لا توجد اختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد', - documentRolledBack: 'تمت استعادة الوثيقة', - htmlHelp: 'يعرض هذا الإصدار المحدد كـ HTML، إذا كنت ترغب في رؤية الفرق بين إصدارين في نفس الوقت، استخدم عرض الفرق\n ', - rollbackTo: 'استعادة إلى', - selectVersion: 'اختر الإصدار', - view: 'عرض', - pagination: 'عرض الإصدار %0% إلى %1% من %2% إصدارات', - versions: 'الإصدارات', - currentDraftVersion: 'الإصدار الحالي المسودة', - currentPublishedVersion: 'الإصدار الحالي المنشور', - }, - scripts: { - editscript: 'تحرير ملف السكربت', - }, - sections: { - content: 'المحتوى', - media: 'الوسائط', - member: 'الأعضاء', - packages: 'الحزم', - marketplace: 'السوق', - settings: 'الإعدادات', - translation: 'القاموس', - users: 'المستخدمون', - }, + doNothing: 'الصق مع التنسيق الكامل (غير موصى به)', + errorMessage: + 'النص الذي تحاول لصقه يحتوي على أحرف خاصة أو تنسيق. قد يكون ذلك بسبب نسخ النص من Microsoft Word. يمكن لـ Umbraco إزالة الأحرف الخاصة أو التنسيق تلقائيًا، بحيث يكون المحتوى الملصق أكثر ملاءمة للويب.\n', + removeAll: 'الصق كـ نص خام بدون أي تنسيق على الإطلاق', + removeSpecialFormattering: 'الصق، ولكن قم بإزالة التنسيق (موصى به)', + }, + publicAccess: { + paGroups: 'حماية قائمة على المجموعة', + paGroupsHelp: 'إذا كنت ترغب في منح الوصول إلى جميع أعضاء مجموعات الأعضاء المحددة', + paGroupsNoGroups: 'تحتاج إلى إنشاء مجموعة أعضاء قبل أن تتمكن من استخدام المصادقة القائمة على المجموعة', + paErrorPage: 'صفحة الخطأ', + paErrorPageHelp: 'تستخدم عندما يكون الأشخاص مسجلين الدخول، ولكن ليس لديهم وصول', + paHowWould: 'اختر كيفية تقييد الوصول إلى الصفحة %0%', + paIsProtected: '%0% محمية الآن', + paIsRemoved: 'تمت إزالة الحماية من %0%', + paLoginPage: 'صفحة تسجيل الدخول', + paLoginPageHelp: 'اختر الصفحة التي تحتوي على نموذج تسجيل الدخول', + paRemoveProtection: 'إزالة الحماية...', + paRemoveProtectionConfirm: 'هل أنت متأكد أنك تريد إزالة الحماية من الصفحة %0%؟', + paSelectPages: 'اختر الصفحات التي تحتوي على نموذج تسجيل الدخول ورسائل الخطأ', + paSelectGroups: 'اختر المجموعات التي لديها وصول إلى الصفحة %0%', + paSelectMembers: 'اختر الأعضاء الذين لديهم وصول إلى الصفحة %0%', + paMembers: 'حماية الأعضاء المحددين', + paMembersHelp: 'إذا كنت ترغب في منح الوصول إلى أعضاء محددين', + }, + publish: { + invalidPublishBranchPermissions: 'أذونات المستخدم غير كافية لنشر جميع الوثائق التابعة', + contentPublishedFailedIsTrashed: '\n %0% لم يتم نشره لأن العنصر في سلة المهملات.\n ', + contentPublishedFailedAwaitingRelease: '\n %0% لم يتم نشره لأن العنصر مجدول للإصدار.\n ', + contentPublishedFailedExpired: '\n %0% لم يتم نشره لأن العنصر منتهي الصلاحية.\n ', + contentPublishedFailedInvalid: '\n %0% لم يتم نشره لأن بعض الخصائص لم تتجاوز قواعد التحقق.\n ', + contentPublishedFailedByEvent: '\n %0% لم يتم نشره، ألغى ملحق طرف ثالث الإجراء.\n ', + contentPublishedFailedByParent: '\n %0% لا يمكن نشره، لأن صفحة الوالد غير منشورة.\n ', + contentPublishedFailedByMissingName: '%0% لا يمكن نشره، لأنه يفتقر إلى اسم.', + contentPublishedFailedReqCultureValidationError: + "فشل التحقق من اللغة المطلوبة '%0%'. تم حفظ هذه اللغة ولكن لم يتم نشرها.\n", + inProgress: 'النشر جارٍ - يرجى الانتظار...', + inProgressCounter: '%0% من أصل %1% صفحات تم نشرها...', + nodePublish: '%0% تم نشره', + nodePublishAll: '%0% والصفحات الفرعية تم نشرها', + publishAll: 'نشر %0% وجميع الصفحات الفرعية الخاصة به', + publishHelp: + 'انقر على نشر لنشر %0% وجعل محتواه متاحًا علنًا.

\n يمكنك نشر هذه الصفحة وجميع صفحاتها الفرعية عن طريق تحديد تضمين الصفحات الفرعية غير المنشورة أدناه.\n ', + }, + colorpicker: { + noColors: 'لم تقم بتكوين أي ألوان معتمدة', + }, + contentPicker: { + allowedItemTypes: 'يمكنك فقط اختيار العناصر من النوع(s): %0%', + defineDynamicRoot: 'حدد الجذر', + defineRootNode: 'اختر جذر العقدة', + pickedTrashedItem: 'لقد اخترت عنصر محتوى محذوف حاليًا أو في سلة المهملات', + pickedTrashedItems: 'لقد اخترت عناصر محتوى محذوفة حاليًا أو في سلة المهملات', + }, + dynamicRoot: { + configurationTitle: 'استعلام الجذر الديناميكي', + pickDynamicRootOriginTitle: 'اختر الأصل', + pickDynamicRootOriginDesc: 'حدد الأصل لاستعلام الجذر الديناميكي الخاص بك', + originRootTitle: 'الجذر', + originRootDesc: 'العقدة الجذرية لجلسة التحرير هذه', + originParentTitle: 'الوالد', + originParentDesc: 'العقدة الأم للمصدر في جلسة التحرير هذه', + originCurrentTitle: 'الحالي', + originCurrentDesc: 'عقدة المحتوى التي هي المصدر لجلسة التحرير هذه', + originSiteTitle: 'الموقع', + originSiteDesc: 'ابحث عن أقرب عقدة بها اسم مضيف', + originByKeyTitle: 'عقدة محددة', + originByKeyDesc: 'اختر عقدة محددة كأصل لهذا الاستعلام', + pickDynamicRootQueryStepTitle: 'أضف خطوة إلى الاستعلام', + pickDynamicRootQueryStepDesc: 'حدد الخطوة التالية لاستعلام الجذر الديناميكي الخاص بك', + queryStepNearestAncestorOrSelfTitle: 'أقرب سلف أو نفس', + queryStepNearestAncestorOrSelfDesc: 'استعلام أقرب سلف أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepFurthestAncestorOrSelfTitle: 'أبعد سلف أو نفس', + queryStepFurthestAncestorOrSelfDesc: 'استعلام أبعد سلف أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepNearestDescendantOrSelfTitle: 'أقرب نسل أو نفس', + queryStepNearestDescendantOrSelfDesc: 'استعلام أقرب نسل أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepFurthestDescendantOrSelfTitle: 'أبعد نسل أو نفس', + queryStepFurthestDescendantOrSelfDesc: 'استعلام أبعد نسل أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepCustomTitle: 'مخصص', + queryStepCustomDesc: 'استعلام باستخدام خطوة استعلام مخصصة', + addQueryStep: 'إضافة خطوة استعلام', + queryStepTypes: 'التي تتطابق مع الأنواع: ', + noValidStartNodeTitle: 'لا توجد محتويات متطابقة', + noValidStartNodeDesc: + 'تكوين هذه الخاصية لا يتطابق مع أي محتوى. أنشئ المحتوى المفقود أو اتصل بمسؤولك لضبط إعدادات الجذر الديناميكي لهذه الخاصية.', + }, + mediaPicker: { + deletedItem: 'عنصر محذوف', + pickedTrashedItem: 'لقد اخترت عنصر وسائط محذوف حاليًا أو في سلة المهملات', + pickedTrashedItems: 'لقد اخترت عناصر وسائط محذوفة حاليًا أو في سلة المهملات', + trashed: 'محذوف', + openMedia: 'افتح في مكتبة الوسائط', + changeMedia: 'تغيير عنصر الوسائط', + editMediaEntryLabel: 'تحرير %0% على %1%', + confirmCancelMediaEntryCreationHeadline: 'تجاهل الإنشاء؟', + confirmCancelMediaEntryCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', + confirmCancelMediaEntryHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد\n تجاهلها؟\n ', + confirmRemoveAllMediaEntryMessage: 'إزالة جميع الوسائط؟', + tabClipboard: 'الحافظة', + notAllowed: 'غير مسموح', + openMediaPicker: 'افتح محدد الوسائط', + }, + propertyEditorPicker: { + title: 'اختر محرر الخصائص', + openPropertyEditorPicker: 'اختر واجهة مستخدم محرر الخصائص', + }, + relatedlinks: { + enterExternal: 'أدخل رابط خارجي', + chooseInternal: 'اختر صفحة داخلية', + caption: 'التسمية التوضيحية', + link: 'رابط', + newWindow: 'فتح في نافذة جديدة', + captionPlaceholder: 'أدخل التسمية التوضيحية للعرض', + externalLinkPlaceholder: 'أدخل الرابط', + }, + imagecropper: { + reset: 'إعادة تعيين', + updateEditCrop: 'تم', + undoEditCrop: 'تراجع عن التعديلات', + customCrop: 'مخصص', + }, + rollback: { + changes: 'التغييرات', + created: 'أنشئ', + headline: 'اختر إصدارًا للمقارنة مع الإصدار الحالي', + currentVersion: 'الإصدار الحالي', + diffHelp: + 'يظهر هذا الاختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد
النص الأحمر سيتم حذفه في الإصدار المحدد، النص الأخضر سيتم إضافته', + noDiff: 'لا توجد اختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد', + documentRolledBack: 'تمت استعادة الوثيقة', + htmlHelp: + 'يعرض هذا الإصدار المحدد كـ HTML، إذا كنت ترغب في رؤية الفرق بين إصدارين في نفس الوقت، استخدم عرض الفرق\n ', + rollbackTo: 'استعادة إلى', + selectVersion: 'اختر الإصدار', + view: 'عرض', + pagination: 'عرض الإصدار %0% إلى %1% من %2% إصدارات', + versions: 'الإصدارات', + currentDraftVersion: 'الإصدار الحالي المسودة', + currentPublishedVersion: 'الإصدار الحالي المنشور', + }, + scripts: { + editscript: 'تحرير ملف السكربت', + }, + sections: { + content: 'المحتوى', + media: 'الوسائط', + member: 'الأعضاء', + packages: 'الحزم', + marketplace: 'السوق', + settings: 'الإعدادات', + translation: 'القاموس', + users: 'المستخدمون', + }, help: { - tours: 'الجولات', - theBestUmbracoVideoTutorials: 'أفضل دروس الفيديو في Umbraco', - umbracoForum: 'زيارة our.umbraco.com', - umbracoTv: 'زيارة umbraco.tv', - umbracoLearningBase: 'شاهد دروس الفيديو المجانية لدينا', - umbracoLearningBaseDescription: 'على قاعدة تعلم Umbraco', - }, - settings: { - defaulttemplate: 'القالب الافتراضي', - importDocumentTypeHelp: 'للاستيراد نوع الوثيقة ابحث عن ملف ".udt" على جهاز الكمبيوتر الخاص بك بالنقر على زر "استيراد" (سيُطلب منك تأكيد ذلك في الشاشة التالية)', - newtabname: 'عنوان التبويب الجديد', - nodetype: 'نوع العقدة', - objecttype: 'النوع', - stylesheet: 'ورقة الأنماط', - script: 'السكريبت', - tab: 'التبويب', - tabname: 'عنوان التبويب', - tabs: 'التبويبات', - contentTypeEnabled: 'نوع المحتوى الرئيسي مفعل', - contentTypeUses: 'هذا النوع من المحتوى يستخدم', - noPropertiesDefinedOnTab: 'لا توجد خصائص محددة على هذا التبويب. انقر على رابط "إضافة خاصية جديدة" في الأعلى لإنشاء خاصية جديدة.', - createMatchingTemplate: 'إنشاء قالب مطابق', - addIcon: 'إضافة أيقونة', - }, - sort: { - sortOrder: 'ترتيب الفرز', - sortCreationDate: 'تاريخ الإنشاء', - sortDone: 'تمت عملية الفرز.', - sortHelp: 'اسحب العناصر المختلفة لأعلى أو لأسفل أدناه لتحديد كيفية ترتيبها. أو انقر على رؤوس الأعمدة لفرز جميع العناصر.', - sortPleaseWait: 'يرجى الانتظار. يتم فرز العناصر، قد يستغرق ذلك بعض الوقت.', - sortEmptyState: 'لا تحتوي هذه العقدة على عقدة فرعية لفرزها', - }, - speechBubbles: { - validationFailedHeader: 'التحقق', - validationFailedMessage: 'يجب إصلاح أخطاء التحقق قبل أن يمكن حفظ العنصر', - operationFailedHeader: 'فشل', - operationSavedHeader: 'تم الحفظ', - operationSavedHeaderReloadUser: 'تم الحفظ. لعرض التغييرات، يرجى إعادة تحميل متصفحك', - invalidUserPermissionsText: 'أذونات المستخدم غير كافية، لم نتمكن من إتمام العملية', - operationCancelledHeader: 'ملغي', - operationCancelledText: 'تم إلغاء العملية بواسطة ملحق طرف ثالث', - folderUploadNotAllowed: 'يتم تحميل هذا الملف كجزء من مجلد، ولكن إنشاء مجلد جديد غير مسموح هنا', - folderCreationNotAllowed: 'إنشاء مجلد جديد غير مسموح هنا', - contentTypeDublicatePropertyType: 'نوع الخاصية موجود بالفعل', - contentTypePropertyTypeCreated: 'تم إنشاء نوع الخاصية', - contentTypePropertyTypeCreatedText: 'الاسم: %0%
نوع البيانات: %1%', - contentTypePropertyTypeDeleted: 'تم حذف نوع الخاصية', - contentTypeSavedHeader: 'تم حفظ نوع الوثيقة', - contentTypeTabCreated: 'تم إنشاء التبويب', - contentTypeTabDeleted: 'تم حذف التبويب', - contentTypeTabDeletedText: 'تم حذف التبويب بالمعرف: %0%', - cssErrorHeader: 'لم يتم حفظ ورقة الأنماط', - cssSavedHeader: 'تم حفظ ورقة الأنماط', - cssSavedText: 'تم حفظ ورقة الأنماط بدون أي أخطاء', - dataTypeSaved: 'تم حفظ نوع البيانات', - dictionaryItemSaved: 'تم حفظ عنصر القاموس', - editContentPublishedHeader: 'تم نشر المحتوى', - editContentPublishedText: 'وهو مرئي على الموقع', - editMultiContentPublishedText: 'تم نشر %0% مستندات وهي مرئية على الموقع', - editVariantPublishedText: '%0% تم نشره وهو مرئي على الموقع', - editMultiVariantPublishedText: '%0% مستندات تم نشرها للغات %1% وهي مرئية على الموقع', - editBlueprintSavedHeader: 'تم حفظ مخطط الوثيقة', - editBlueprintSavedText: 'تم حفظ التغييرات بنجاح', - editContentSavedHeader: 'تم حفظ المحتوى', - editContentSavedText: 'تذكر النشر لجعل التغييرات مرئية', - editContentScheduledSavedText: 'تم تحديث جدول النشر', - editVariantSavedText: '%0% تم حفظه', - editContentSendToPublish: 'تم إرسالها للموافقة', - editContentSendToPublishText: 'تم إرسال التغييرات للموافقة', - editVariantSendToPublishText: '%0% تغييرات تم إرسالها للموافقة', - editMediaSaved: 'تم حفظ الوسائط', - editMediaSavedText: 'تم حفظ الوسائط بدون أي أخطاء', - editMemberSaved: 'تم حفظ العضو', - editStylesheetPropertySaved: 'تم حفظ خاصية ورقة الأنماط', - editStylesheetSaved: 'تم حفظ ورقة الأنماط', - editTemplateSaved: 'تم حفظ القالب', - editUserError: 'حدث خطأ عند حفظ المستخدم (تحقق من السجل)', - editUserSaved: 'تم حفظ المستخدم', - editUserTypeSaved: 'تم حفظ نوع المستخدم', - editUserGroupSaved: 'تم حفظ مجموعة المستخدمين', - editCulturesAndHostnamesSaved: 'تم حفظ الثقافات وأسماء المضيفين', - editCulturesAndHostnamesError: 'حدث خطأ عند حفظ الثقافات وأسماء المضيفين', - fileErrorHeader: 'لم يتم حفظ الملف', - fileErrorText: 'لم يتم حفظ الملف. يرجى التحقق من أذونات الملف', - fileSavedHeader: 'تم حفظ الملف', - fileSavedText: 'تم حفظ الملف بدون أي أخطاء', - languageSaved: 'تم حفظ اللغة', - mediaTypeSavedHeader: 'تم حفظ نوع الوسائط', - memberTypeSavedHeader: 'تم حفظ نوع العضو', - memberGroupSavedHeader: 'تم حفظ مجموعة الأعضاء', - memberGroupNameDuplicate: 'مجموعة أعضاء أخرى بنفس الاسم موجودة بالفعل', - templateErrorHeader: 'لم يتم حفظ القالب', - templateErrorText: 'يرجى التأكد من عدم وجود قالبين بنفس الاسم المستعار', - templateSavedHeader: 'تم حفظ القالب', - templateSavedText: 'تم حفظ القالب بدون أي أخطاء!', - contentUnpublished: 'تم إلغاء نشر المحتوى', - contentCultureUnpublished: 'تم إلغاء نشر التباين %0%', - contentMandatoryCultureUnpublished: "اللغة الإلزامية '%0%' تم إلغاء نشرها. جميع اللغات لهذا العنصر المحتوى أصبحت الآن غير منشورة.", - partialViewSavedHeader: 'تم حفظ العرض الجزئي', - partialViewSavedText: 'تم حفظ العرض الجزئي بدون أي أخطاء!', - partialViewErrorHeader: 'لم يتم حفظ العرض الجزئي', - partialViewErrorText: 'حدث خطأ أثناء حفظ الملف.', - permissionsSavedFor: 'تم حفظ الأذونات لـ', - deleteUserGroupsSuccess: 'تم حذف %0% مجموعات مستخدمين', - deleteUserGroupSuccess: '%0% تم حذفه', - enableUsersSuccess: 'تم تفعيل %0% مستخدمين', - disableUsersSuccess: 'تم تعطيل %0% مستخدمين', - enableUserSuccess: '%0% تم تفعيله الآن', - disableUserSuccess: '%0% تم تعطيله الآن', - setUserGroupOnUsersSuccess: 'تم تعيين مجموعات المستخدمين', - unlockUsersSuccess: 'تم فك قفل %0% مستخدمين', - unlockUserSuccess: '%0% تم فك قفله الآن', - memberExportedSuccess: 'تم تصدير العضو إلى ملف', - memberExportedError: 'حدث خطأ أثناء تصدير العضو', - deleteUserSuccess: 'تم حذف المستخدم %0%', - resendInviteHeader: 'دعوة المستخدم', - resendInviteSuccess: 'تم إعادة إرسال الدعوة إلى %0%', - contentReqCulturePublishError: "لا يمكن نشر الوثيقة لأن '%0%' المطلوب غير منشور", - contentCultureValidationError: "فشل التحقق من اللغة '%0%'", - documentTypeExportedSuccess: 'تم تصدير نوع الوثيقة إلى ملف', - documentTypeExportedError: 'حدث خطأ أثناء تصدير نوع الوثيقة', - dictionaryItemExportedSuccess: 'تم تصدير عنصر (عناصر) القاموس إلى ملف', - dictionaryItemExportedError: 'حدث خطأ أثناء تصدير عنصر (عناصر) القاموس', - dictionaryItemImported: 'تم استيراد عنصر (عناصر) القاموس التالية!', - scheduleErrReleaseDate1: 'تاريخ الإصدار لا يمكن أن يكون في الماضي', - scheduleErrReleaseDate2: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب غير منشور", - scheduleErrReleaseDate3: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب له تاريخ نشر لاحق من لغة غير إلزامية", - scheduleErrExpireDate1: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون في الماضي', - scheduleErrExpireDate2: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون قبل تاريخ الإصدار', - publishWithNoDomains: 'لم يتم تكوين النطاقات لموقع متعدد اللغات، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', - publishWithMissingDomain: 'لا يوجد مجال مكون لـ %0%، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', - preventCleanupEnableError: 'حدث خطأ أثناء تمكين تنظيف الإصدارات لـ %0%', - preventCleanupDisableError: 'حدث خطأ أثناء تعطيل تنظيف الإصدارات لـ %0%', - copySuccessMessage: 'تم نسخ معلومات النظام الخاصة بك بنجاح إلى الحافظة', - cannotCopyInformation: 'لم نتمكن من نسخ معلومات النظام الخاصة بك إلى الحافظة', - }, - stylesheet: { - addRule: 'إضافة نمط', - editRule: 'تعديل النمط', - editorRules: 'أنماط محرر النصوص الغني', - editorRulesHelp: 'حدد الأنماط التي يجب أن تكون متاحة في محرر النصوص الغني لهذه ورقة الأنماط', - editstylesheet: 'تعديل ورقة الأنماط', - editstylesheetproperty: 'تعديل خاصية ورقة الأنماط', - nameHelp: 'الاسم المعروض في قائمة اختيار الأنماط في المحرر', - preview: 'معاينة', - previewHelp: 'كيف سيبدو النص في محرر النصوص الغني.', - selector: 'المحدد', - selectorHelp: 'يستخدم بناء جملة CSS، على سبيل المثال "h1" أو ".redHeader"', - styles: 'الأنماط', - stylesHelp: 'CSS الذي يجب تطبيقه في محرر النصوص الغني، على سبيل المثال "color:red;"', - tabCode: 'الكود', - tabRules: 'محرر النصوص الغني', - }, - template: { - runtimeModeProduction: 'المحتوى غير قابل للتحرير عند استخدام وضع التشغيل Production.', - deleteByIdFailed: 'فشل في حذف القالب بالمعرف %0%', - edittemplate: 'تعديل القالب', - insertSections: 'الأقسام', - insertContentArea: 'إدراج منطقة المحتوى', - insertContentAreaPlaceHolder: 'إدراج عنصر نائبة لمنطقة المحتوى', - insert: 'إدراج', - insertDesc: 'اختر ما تريد إدراجه في قالبك', - insertDictionaryItem: 'عنصر القاموس', - insertDictionaryItemDesc: 'عنصر القاموس هو عنصر نائبة لنص قابل للترجمة، مما يسهل إنشاء تصميمات لمواقع متعددة اللغات.', - insertMacro: 'ماكرو', - insertMacroDesc: 'ماكرو هو مكون قابل للتكوين رائع للأجزاء القابلة لإعادة الاستخدام من التصميم الخاص بك، حيث تحتاج إلى خيار لتوفير معلمات، مثل المعارض والنماذج والقوائم.', - insertPageField: 'القيمة', - insertPageFieldDesc: 'يعرض قيمة حقل مسمى من الصفحة الحالية، مع خيارات لتعديل القيمة أو الرجوع إلى القيم البديلة.', - insertPartialView: 'عرض جزئي', - insertPartialViewDesc: 'العرض الجزئي هو ملف قالب منفصل يمكن عرضه داخل قالب آخر، وهو رائع لإعادة استخدام الترميز أو لفصل القوالب المعقدة إلى ملفات منفصلة.', - mastertemplate: 'القالب الرئيسي', - noMaster: 'لا يوجد رئيسي', - renderBody: 'عرض القالب الفرعي', - renderBodyDesc: 'يعرض محتويات القالب الفرعي، من خلال إدراج عنصر نائبة @RenderBody().', - defineSection: 'تحديد قسم مسمى', - defineSectionDesc: 'يحدد جزء من القالب كقسم مسمى عن طريق لفه في @section { ... }. يمكن عرض هذا في منطقة محددة من القالب الرئيسي لهذا القالب، باستخدام @RenderSection.', - renderSection: 'عرض قسم مسمى', - renderSectionDesc: 'يعرض منطقة مسمى من قالب فرعي، من خلال إدراج عنصر نائبة @RenderSection(name). هذا يعرض منطقة من قالب فرعي والتي يتم لفها في تعريف @section [name]{ ... } المقابل.', - sectionName: 'اسم القسم', - sectionMandatory: 'القسم إلزامي', - sectionMandatoryDesc: 'إذا كان إلزاميًا، يجب أن يحتوي القالب الفرعي على تعريف @section، خلاف ذلك يتم عرض خطأ.', - queryBuilder: 'باني الاستعلام', - itemsReturned: 'العناصر التي تم إرجاعها، في', - iWant: 'أريد', - allContent: 'جميع المحتويات', - contentOfType: 'محتوى من نوع "%0%"', - from: 'من', - websiteRoot: 'موقعي', - where: 'حيث', - and: 'و', - is: 'هو', - isNot: 'ليس', - before: 'قبل', - beforeIncDate: 'قبل (بما في ذلك التاريخ المحدد)', - after: 'بعد', - afterIncDate: 'بعد (بما في ذلك التاريخ المحدد)', - equals: 'يساوي', - doesNotEqual: 'لا يساوي', - contains: 'يحتوي على', - doesNotContain: 'لا يحتوي على', - greaterThan: 'أكبر من', - greaterThanEqual: 'أكبر من أو يساوي', - lessThan: 'أقل من', - lessThanEqual: 'أقل من أو يساوي', - id: 'المعرف', - name: 'الاسم', - createdDate: 'تاريخ الإنشاء', - lastUpdatedDate: 'تاريخ آخر تحديث', - orderBy: 'ترتيب حسب', - ascending: 'تصاعدي', - descending: 'تنازلي', - template: 'القالب', - }, + tours: 'الجولات', + theBestUmbracoVideoTutorials: 'أفضل دروس الفيديو في Umbraco', + umbracoForum: 'زيارة our.umbraco.com', + umbracoTv: 'زيارة umbraco.tv', + umbracoLearningBase: 'شاهد دروس الفيديو المجانية لدينا', + umbracoLearningBaseDescription: 'على قاعدة تعلم Umbraco', + }, + settings: { + defaulttemplate: 'القالب الافتراضي', + importDocumentTypeHelp: + 'للاستيراد نوع الوثيقة ابحث عن ملف ".udt" على جهاز الكمبيوتر الخاص بك بالنقر على زر "استيراد" (سيُطلب منك تأكيد ذلك في الشاشة التالية)', + newtabname: 'عنوان التبويب الجديد', + nodetype: 'نوع العقدة', + objecttype: 'النوع', + stylesheet: 'ورقة الأنماط', + script: 'السكريبت', + tab: 'التبويب', + tabname: 'عنوان التبويب', + tabs: 'التبويبات', + contentTypeEnabled: 'نوع المحتوى الرئيسي مفعل', + contentTypeUses: 'هذا النوع من المحتوى يستخدم', + noPropertiesDefinedOnTab: + 'لا توجد خصائص محددة على هذا التبويب. انقر على رابط "إضافة خاصية جديدة" في الأعلى لإنشاء خاصية جديدة.', + createMatchingTemplate: 'إنشاء قالب مطابق', + addIcon: 'إضافة أيقونة', + }, + sort: { + sortOrder: 'ترتيب الفرز', + sortCreationDate: 'تاريخ الإنشاء', + sortDone: 'تمت عملية الفرز.', + sortHelp: + 'اسحب العناصر المختلفة لأعلى أو لأسفل أدناه لتحديد كيفية ترتيبها. أو انقر على رؤوس الأعمدة لفرز جميع العناصر.', + sortPleaseWait: 'يرجى الانتظار. يتم فرز العناصر، قد يستغرق ذلك بعض الوقت.', + sortEmptyState: 'لا تحتوي هذه العقدة على عقدة فرعية لفرزها', + }, + speechBubbles: { + validationFailedHeader: 'التحقق', + validationFailedMessage: 'يجب إصلاح أخطاء التحقق قبل أن يمكن حفظ العنصر', + operationFailedHeader: 'فشل', + operationSavedHeader: 'تم الحفظ', + operationSavedHeaderReloadUser: 'تم الحفظ. لعرض التغييرات، يرجى إعادة تحميل متصفحك', + invalidUserPermissionsText: 'أذونات المستخدم غير كافية، لم نتمكن من إتمام العملية', + operationCancelledHeader: 'ملغي', + operationCancelledText: 'تم إلغاء العملية بواسطة ملحق طرف ثالث', + folderUploadNotAllowed: 'يتم تحميل هذا الملف كجزء من مجلد، ولكن إنشاء مجلد جديد غير مسموح هنا', + folderCreationNotAllowed: 'إنشاء مجلد جديد غير مسموح هنا', + contentTypeDublicatePropertyType: 'نوع الخاصية موجود بالفعل', + contentTypePropertyTypeCreated: 'تم إنشاء نوع الخاصية', + contentTypePropertyTypeCreatedText: 'الاسم: %0%
نوع البيانات: %1%', + contentTypePropertyTypeDeleted: 'تم حذف نوع الخاصية', + contentTypeSavedHeader: 'تم حفظ نوع الوثيقة', + contentTypeTabCreated: 'تم إنشاء التبويب', + contentTypeTabDeleted: 'تم حذف التبويب', + contentTypeTabDeletedText: 'تم حذف التبويب بالمعرف: %0%', + cssErrorHeader: 'لم يتم حفظ ورقة الأنماط', + cssSavedHeader: 'تم حفظ ورقة الأنماط', + cssSavedText: 'تم حفظ ورقة الأنماط بدون أي أخطاء', + dataTypeSaved: 'تم حفظ نوع البيانات', + dictionaryItemSaved: 'تم حفظ عنصر القاموس', + editContentPublishedHeader: 'تم نشر المحتوى', + editContentPublishedText: 'وهو مرئي على الموقع', + editMultiContentPublishedText: 'تم نشر %0% مستندات وهي مرئية على الموقع', + editVariantPublishedText: '%0% تم نشره وهو مرئي على الموقع', + editMultiVariantPublishedText: '%0% مستندات تم نشرها للغات %1% وهي مرئية على الموقع', + editBlueprintSavedHeader: 'تم حفظ مخطط الوثيقة', + editBlueprintSavedText: 'تم حفظ التغييرات بنجاح', + editContentSavedHeader: 'تم حفظ المحتوى', + editContentSavedText: 'تذكر النشر لجعل التغييرات مرئية', + editContentScheduledSavedText: 'تم تحديث جدول النشر', + editVariantSavedText: '%0% تم حفظه', + editContentSendToPublish: 'تم إرسالها للموافقة', + editContentSendToPublishText: 'تم إرسال التغييرات للموافقة', + editVariantSendToPublishText: '%0% تغييرات تم إرسالها للموافقة', + editMediaSaved: 'تم حفظ الوسائط', + editMediaSavedText: 'تم حفظ الوسائط بدون أي أخطاء', + editMemberSaved: 'تم حفظ العضو', + editStylesheetPropertySaved: 'تم حفظ خاصية ورقة الأنماط', + editStylesheetSaved: 'تم حفظ ورقة الأنماط', + editTemplateSaved: 'تم حفظ القالب', + editUserError: 'حدث خطأ عند حفظ المستخدم (تحقق من السجل)', + editUserSaved: 'تم حفظ المستخدم', + editUserTypeSaved: 'تم حفظ نوع المستخدم', + editUserGroupSaved: 'تم حفظ مجموعة المستخدمين', + editCulturesAndHostnamesSaved: 'تم حفظ الثقافات وأسماء المضيفين', + editCulturesAndHostnamesError: 'حدث خطأ عند حفظ الثقافات وأسماء المضيفين', + fileErrorHeader: 'لم يتم حفظ الملف', + fileErrorText: 'لم يتم حفظ الملف. يرجى التحقق من أذونات الملف', + fileSavedHeader: 'تم حفظ الملف', + fileSavedText: 'تم حفظ الملف بدون أي أخطاء', + languageSaved: 'تم حفظ اللغة', + mediaTypeSavedHeader: 'تم حفظ نوع الوسائط', + memberTypeSavedHeader: 'تم حفظ نوع العضو', + memberGroupSavedHeader: 'تم حفظ مجموعة الأعضاء', + memberGroupNameDuplicate: 'مجموعة أعضاء أخرى بنفس الاسم موجودة بالفعل', + templateErrorHeader: 'لم يتم حفظ القالب', + templateErrorText: 'يرجى التأكد من عدم وجود قالبين بنفس الاسم المستعار', + templateSavedHeader: 'تم حفظ القالب', + templateSavedText: 'تم حفظ القالب بدون أي أخطاء!', + contentUnpublished: 'تم إلغاء نشر المحتوى', + contentCultureUnpublished: 'تم إلغاء نشر التباين %0%', + contentMandatoryCultureUnpublished: + "اللغة الإلزامية '%0%' تم إلغاء نشرها. جميع اللغات لهذا العنصر المحتوى أصبحت الآن غير منشورة.", + partialViewSavedHeader: 'تم حفظ العرض الجزئي', + partialViewSavedText: 'تم حفظ العرض الجزئي بدون أي أخطاء!', + partialViewErrorHeader: 'لم يتم حفظ العرض الجزئي', + partialViewErrorText: 'حدث خطأ أثناء حفظ الملف.', + permissionsSavedFor: 'تم حفظ الأذونات لـ', + deleteUserGroupsSuccess: 'تم حذف %0% مجموعات مستخدمين', + deleteUserGroupSuccess: '%0% تم حذفه', + enableUsersSuccess: 'تم تفعيل %0% مستخدمين', + disableUsersSuccess: 'تم تعطيل %0% مستخدمين', + enableUserSuccess: '%0% تم تفعيله الآن', + disableUserSuccess: '%0% تم تعطيله الآن', + setUserGroupOnUsersSuccess: 'تم تعيين مجموعات المستخدمين', + unlockUsersSuccess: 'تم فك قفل %0% مستخدمين', + unlockUserSuccess: '%0% تم فك قفله الآن', + memberExportedSuccess: 'تم تصدير العضو إلى ملف', + memberExportedError: 'حدث خطأ أثناء تصدير العضو', + deleteUserSuccess: 'تم حذف المستخدم %0%', + resendInviteHeader: 'دعوة المستخدم', + resendInviteSuccess: 'تم إعادة إرسال الدعوة إلى %0%', + contentReqCulturePublishError: "لا يمكن نشر الوثيقة لأن '%0%' المطلوب غير منشور", + contentCultureValidationError: "فشل التحقق من اللغة '%0%'", + documentTypeExportedSuccess: 'تم تصدير نوع الوثيقة إلى ملف', + documentTypeExportedError: 'حدث خطأ أثناء تصدير نوع الوثيقة', + dictionaryItemExportedSuccess: 'تم تصدير عنصر (عناصر) القاموس إلى ملف', + dictionaryItemExportedError: 'حدث خطأ أثناء تصدير عنصر (عناصر) القاموس', + dictionaryItemImported: 'تم استيراد عنصر (عناصر) القاموس التالية!', + scheduleErrReleaseDate1: 'تاريخ الإصدار لا يمكن أن يكون في الماضي', + scheduleErrReleaseDate2: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب غير منشور", + scheduleErrReleaseDate3: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب له تاريخ نشر لاحق من لغة غير إلزامية", + scheduleErrExpireDate1: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون في الماضي', + scheduleErrExpireDate2: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون قبل تاريخ الإصدار', + publishWithNoDomains: + 'لم يتم تكوين النطاقات لموقع متعدد اللغات، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', + publishWithMissingDomain: 'لا يوجد مجال مكون لـ %0%، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', + preventCleanupEnableError: 'حدث خطأ أثناء تمكين تنظيف الإصدارات لـ %0%', + preventCleanupDisableError: 'حدث خطأ أثناء تعطيل تنظيف الإصدارات لـ %0%', + copySuccessMessage: 'تم نسخ معلومات النظام الخاصة بك بنجاح إلى الحافظة', + cannotCopyInformation: 'لم نتمكن من نسخ معلومات النظام الخاصة بك إلى الحافظة', + }, + stylesheet: { + addRule: 'إضافة نمط', + editRule: 'تعديل النمط', + editorRules: 'أنماط محرر النصوص الغني', + editorRulesHelp: 'حدد الأنماط التي يجب أن تكون متاحة في محرر النصوص الغني لهذه ورقة الأنماط', + editstylesheet: 'تعديل ورقة الأنماط', + editstylesheetproperty: 'تعديل خاصية ورقة الأنماط', + nameHelp: 'الاسم المعروض في قائمة اختيار الأنماط في المحرر', + preview: 'معاينة', + previewHelp: 'كيف سيبدو النص في محرر النصوص الغني.', + selector: 'المحدد', + selectorHelp: 'يستخدم بناء جملة CSS، على سبيل المثال "h1" أو ".redHeader"', + styles: 'الأنماط', + stylesHelp: 'CSS الذي يجب تطبيقه في محرر النصوص الغني، على سبيل المثال "color:red;"', + tabCode: 'الكود', + tabRules: 'محرر النصوص الغني', + }, + template: { + runtimeModeProduction: 'المحتوى غير قابل للتحرير عند استخدام وضع التشغيل Production.', + deleteByIdFailed: 'فشل في حذف القالب بالمعرف %0%', + edittemplate: 'تعديل القالب', + insertSections: 'الأقسام', + insertContentArea: 'إدراج منطقة المحتوى', + insertContentAreaPlaceHolder: 'إدراج عنصر نائبة لمنطقة المحتوى', + insert: 'إدراج', + insertDesc: 'اختر ما تريد إدراجه في قالبك', + insertDictionaryItem: 'عنصر القاموس', + insertDictionaryItemDesc: + 'عنصر القاموس هو عنصر نائبة لنص قابل للترجمة، مما يسهل إنشاء تصميمات لمواقع متعددة اللغات.', + insertMacro: 'ماكرو', + insertMacroDesc: + 'ماكرو هو مكون قابل للتكوين رائع للأجزاء القابلة لإعادة الاستخدام من التصميم الخاص بك، حيث تحتاج إلى خيار لتوفير معلمات، مثل المعارض والنماذج والقوائم.', + insertPageField: 'القيمة', + insertPageFieldDesc: 'يعرض قيمة حقل مسمى من الصفحة الحالية، مع خيارات لتعديل القيمة أو الرجوع إلى القيم البديلة.', + insertPartialView: 'عرض جزئي', + insertPartialViewDesc: + 'العرض الجزئي هو ملف قالب منفصل يمكن عرضه داخل قالب آخر، وهو رائع لإعادة استخدام الترميز أو لفصل القوالب المعقدة إلى ملفات منفصلة.', + mastertemplate: 'القالب الرئيسي', + noMaster: 'لا يوجد رئيسي', + renderBody: 'عرض القالب الفرعي', + renderBodyDesc: 'يعرض محتويات القالب الفرعي، من خلال إدراج عنصر نائبة @RenderBody().', + defineSection: 'تحديد قسم مسمى', + defineSectionDesc: + 'يحدد جزء من القالب كقسم مسمى عن طريق لفه في @section { ... }. يمكن عرض هذا في منطقة محددة من القالب الرئيسي لهذا القالب، باستخدام @RenderSection.', + renderSection: 'عرض قسم مسمى', + renderSectionDesc: + 'يعرض منطقة مسمى من قالب فرعي، من خلال إدراج عنصر نائبة @RenderSection(name). هذا يعرض منطقة من قالب فرعي والتي يتم لفها في تعريف @section [name]{ ... } المقابل.', + sectionName: 'اسم القسم', + sectionMandatory: 'القسم إلزامي', + sectionMandatoryDesc: + 'إذا كان إلزاميًا، يجب أن يحتوي القالب الفرعي على تعريف @section، خلاف ذلك يتم عرض خطأ.', + queryBuilder: 'باني الاستعلام', + itemsReturned: 'العناصر التي تم إرجاعها، في', + iWant: 'أريد', + allContent: 'جميع المحتويات', + contentOfType: 'محتوى من نوع "%0%"', + from: 'من', + websiteRoot: 'موقعي', + where: 'حيث', + and: 'و', + is: 'هو', + isNot: 'ليس', + before: 'قبل', + beforeIncDate: 'قبل (بما في ذلك التاريخ المحدد)', + after: 'بعد', + afterIncDate: 'بعد (بما في ذلك التاريخ المحدد)', + equals: 'يساوي', + doesNotEqual: 'لا يساوي', + contains: 'يحتوي على', + doesNotContain: 'لا يحتوي على', + greaterThan: 'أكبر من', + greaterThanEqual: 'أكبر من أو يساوي', + lessThan: 'أقل من', + lessThanEqual: 'أقل من أو يساوي', + id: 'المعرف', + name: 'الاسم', + createdDate: 'تاريخ الإنشاء', + lastUpdatedDate: 'تاريخ آخر تحديث', + orderBy: 'ترتيب حسب', + ascending: 'تصاعدي', + descending: 'تنازلي', + template: 'القالب', + }, grid: { - media: 'صورة', - macro: 'ماكرو', - insertControl: 'اختر نوع المحتوى', - chooseLayout: 'اختر تخطيطاً', - addRows: 'أضف صفاً', - addElement: 'أضف محتوى', - dropElement: 'إسقاط المحتوى', - settingsApplied: 'تم تطبيق الإعدادات', - contentNotAllowed: 'هذا المحتوى غير مسموح به هنا', - contentAllowed: 'هذا المحتوى مسموح به هنا', - clickToEmbed: 'انقر للتضمين', - clickToInsertImage: 'انقر لإدراج صورة', - clickToInsertMacro: 'انقر لإدراج ماكرو', - placeholderWriteHere: 'اكتب هنا...', - gridLayouts: 'تخطيطات الشبكة', - gridLayoutsDetail: 'التخطيطات هي منطقة العمل العامة لمحرر الشبكة، وعادةً ما تحتاج فقط إلى واحد أو اثنين من التخطيطات المختلفة', - addGridLayout: 'إضافة تخطيط شبكة', - editGridLayout: 'تعديل تخطيط الشبكة', - addGridLayoutDetail: 'ضبط التخطيط من خلال تعيين عرض الأعمدة وإضافة أقسام إضافية', - rowConfigurations: 'تكوينات الصفوف', - rowConfigurationsDetail: 'الصفوف هي خلايا محددة مسبقاً مرتبة أفقياً', - addRowConfiguration: 'إضافة تكوين صف', - editRowConfiguration: 'تعديل تكوين الصف', - addRowConfigurationDetail: 'ضبط الصف من خلال تعيين عرض الخلايا وإضافة خلايا إضافية', - noConfiguration: 'لا يوجد تكوين إضافي متاح', - columns: 'الأعمدة', - columnsDetails: 'إجمالي عدد الأعمدة في تخطيط الشبكة', - settings: 'الإعدادات', - settingsDetails: 'تكوين الإعدادات التي يمكن للمحررين تغييرها', - styles: 'الأنماط', - stylesDetails: 'تكوين التنسيق الذي يمكن للمحررين تغييره', - allowAllEditors: 'السماح لجميع المحررين', - allowAllRowConfigurations: 'السماح بجميع تكوينات الصفوف', - maxItems: 'الحد الأقصى للعناصر', - maxItemsDescription: 'اتركه فارغًا أو اضبطه على 0 لغير المحدود', - setAsDefault: 'تعيين كافتراضي', - chooseExtra: 'اختر إضافي', - chooseDefault: 'اختر افتراضي', - areAdded: 'تمت إضافتها', - warning: 'تحذير', - warningText: '

تعديل اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.

تعديل التسمية فقط لن يؤدي إلى فقدان البيانات.

', - youAreDeleting: 'أنت تقوم بحذف تكوين الصف', - deletingARow: '\n حذف اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا\n التكوين.\n ', - deleteLayout: 'أنت تقوم بحذف التخطيط', - deletingALayout: 'تعديل التخطيط سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.\n ', - }, - contentTypeEditor: { - compositions: 'التركيبات', - group: 'مجموعة', - groupReorderSameAliasError: 'لا يمكنك نقل المجموعة %0% إلى هذا التبويب لأن المجموعة ستأخذ نفس الاسم المستعار كالتبويب: "%1%". قم بإعادة تسمية المجموعة للمتابعة.\n ', - noGroups: 'لم تقم بإضافة أي مجموعات', - addGroup: 'إضافة مجموعة', - inheritedFrom: 'موروث من', - addProperty: 'إضافة خاصية', - editProperty: 'تعديل الخاصية', - requiredLabel: 'التسمية المطلوبة', - enableListViewHeading: 'تمكين عرض القائمة', - enableListViewDescription: 'تكوين العنصر لعرض قائمة قابلة للفرز والبحث من أبنائه.', - allowedTemplatesHeading: 'القوالب المسموح بها', - allowedTemplatesDescription: 'اختر القوالب التي يُسمح للمحررين باستخدامها على محتوى من هذا النوع', - allowAtRootHeading: 'السماح في الجذر', - allowAtRootDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع في جذر شجرة المحتوى.\n ', - childNodesHeading: 'أنواع العقد الفرعية المسموح بها', - childNodesDescription: 'السماح بإنشاء محتوى من الأنواع المحددة أسفل محتوى من هذا النوع.', - chooseChildNode: 'اختر العقدة الفرعية', - compositionsDescription: 'ارث التبويبات والخصائص من نوع مستند موجود. سيتم إضافة التبويبات الجديدة إلى نوع الوثيقة الحالي أو دمجها إذا كان هناك تبويب بنفس الاسم.', - compositionInUse: 'هذا النوع من المحتوى قيد الاستخدام في تركيب، وبالتالي لا يمكن تركيبه بنفسه.\n ', - noAvailableCompositions: 'لا توجد أنواع محتوى متاحة لاستخدامها كتركيب.', - compositionRemoveWarning: 'إزالة التركيب ستؤدي إلى حذف جميع بيانات الخصائص المرتبطة. بمجرد حفظ نوع الوثيقة لا يوجد طريق للعودة.', - availableEditors: 'إنشاء جديد', - reuse: 'استخدام موجود', - editorSettings: 'إعدادات المحرر', - searchResultSettings: 'الإعدادات المتاحة', - searchResultEditors: 'إنشاء تكوين جديد', - configuration: 'التكوين', - yesDelete: 'نعم، احذف', - movedUnderneath: 'تم نقله تحت', - copiedUnderneath: 'تم نسخه تحت', - folderToMove: 'اختر المجلد للتحريك', - folderToCopy: 'اختر المجلد للنسخ', - structureBelow: 'إلى هيكل الشجرة أدناه', - allDocumentTypes: 'جميع أنواع الوثائق', - allDocuments: 'جميع الوثائق', - allMediaItems: 'جميع العناصر الإعلامية', - usingThisDocument: 'استخدام هذا النوع من الوثائق سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', - usingThisMedia: 'استخدام هذا النوع من الوسائط سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', - usingThisMember: 'استخدام هذا النوع من الأعضاء سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا\n ', - andAllDocuments: 'وجميع الوثائق التي تستخدم هذا النوع', - andAllMediaItems: 'وجميع العناصر الإعلامية التي تستخدم هذا النوع', - andAllMembers: 'وجميع الأعضاء الذين يستخدمون هذا النوع', - memberCanEdit: 'يمكن للعضو التعديل', - memberCanEditDescription: 'السماح بتعديل قيمة هذه الخاصية من قبل العضو في صفحة ملفه الشخصي\n ', - isSensitiveData: 'بيانات حساسة', - isSensitiveDataDescription: 'إخفاء قيمة هذه الخاصية عن محرري المحتوى الذين لا يملكون حق الوصول لعرض المعلومات الحساسة\n ', - showOnMemberProfile: 'عرض على ملف العضو', - showOnMemberProfileDescription: 'السماح بعرض قيمة هذه الخاصية في صفحة ملف العضو\n ', - tabHasNoSortOrder: 'التبويب ليس له ترتيب فرز', - compositionUsageHeading: 'أين يتم استخدام هذا التركيب؟', - compositionUsageSpecification: 'يتم استخدام هذا التركيب حاليًا في تركيب أنواع المحتوى التالية:\n ', - variantsHeading: 'السماح بالاختلافات', - cultureVariantHeading: 'السماح بالاختلاف حسب الثقافة', - segmentVariantHeading: 'السماح بالتجزئة', - cultureVariantLabel: 'الاختلاف حسب الثقافة', - segmentVariantLabel: 'الاختلاف حسب القطاعات', - variantsDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع بلغات مختلفة.', - cultureVariantDescription: 'السماح للمحررين بإنشاء محتوى بلغات مختلفة.', - segmentVariantDescription: 'السماح للمحررين بإنشاء قطاعات من هذا المحتوى.', - allowVaryByCulture: 'السماح بالاختلاف حسب الثقافة', - allowVaryBySegment: 'السماح بالتجزئة', - elementType: 'نوع العنصر', - elementHeading: 'هو نوع عنصر', - elementDescription: 'نوع العنصر مخصص للاستخدام ضمن أنواع مستندات أخرى، وليس في شجرة المحتوى.\n ', - elementCannotToggle: 'لا يمكن تغيير نوع مستند إلى نوع عنصر بمجرد أن يتم استخدامه لإنشاء عنصر أو أكثر من محتوى.\n ', - elementDoesNotSupport: 'هذا غير قابل للتطبيق لنوع العنصر', - propertyHasChanges: 'لقد أجريت تغييرات على هذه الخاصية. هل أنت متأكد أنك تريد التخلص منها؟', - displaySettingsHeadline: 'المظهر', - displaySettingsLabelOnTop: 'التسمية في الأعلى (عرض كامل)', - confirmDeleteTabMessage: 'هل أنت متأكد أنك تريد حذف التبويب %0%؟', - confirmDeleteGroupMessage: 'هل أنت متأكد أنك تريد حذف المجموعة %0%؟', - confirmDeletePropertyMessage: 'هل أنت متأكد أنك تريد حذف الخاصية %0%؟', - confirmDeleteTabNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذا التبويب.', - confirmDeleteGroupNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذه المجموعة.', - addTab: 'إضافة تبويب', - convertToTab: 'تحويل إلى تبويب', - tabDirectPropertiesDropZone: 'اسحب الخصائص هنا لوضعها مباشرة على التبويب', - removeChildNode: 'أنت تقوم بإزالة العقدة الفرعية', - removeChildNodeWarning: 'إزالة عقدة فرعية ستحد من خيارات المحررين لإنشاء أنواع محتوى مختلفة أسفل عقدة.', - usingEditor: 'استخدام هذا المحرر سيتم تحديثه بالإعدادات الجديدة.', - historyCleanupHeading: 'تنظيف السجل', - historyCleanupDescription: 'السماح بتجاوز الإعدادات العالمية لتنظيف السجل.', - historyCleanupKeepAllVersionsNewerThanDays: 'احتفظ بجميع الإصدارات الأحدث من الأيام', - historyCleanupKeepLatestVersionPerDayForDays: 'احتفظ بأحدث إصدار لكل يوم لعدد من الأيام', - historyCleanupPreventCleanup: 'منع التنظيف', - historyCleanupEnableCleanup: 'تمكين التنظيف', - historyCleanupGloballyDisabled: 'ملاحظة! تنظيف إصدارات المحتوى التاريخية معطل عالميًا. لن تكون هذه الإعدادات فعالة حتى يتم تمكينها.', - changeDataTypeHelpText: 'تغيير نوع البيانات مع القيم المخزنة معطل. للسماح بذلك، يمكنك تغيير إعداد Umbraco:CMS:DataTypes:CanBeChanged في appsettings.json.', - collections: 'المجموعات', - collectionsDescription: 'تكوين العنصر لعرض قائمة بأبنائه.', - structure: 'الهيكل', - presentation: 'العرض', - }, - languages: { - addLanguage: 'إضافة لغة', - culture: 'رمز ISO', - mandatoryLanguage: 'اللغة الإلزامية', - mandatoryLanguageHelp: 'يجب ملء الخصائص في هذه اللغة قبل أن يتم نشر العقدة.\n ', - defaultLanguage: 'اللغة الافتراضية', - defaultLanguageHelp: 'يمكن لموقع Umbraco أن يحتوي فقط على لغة افتراضية واحدة.', - changingDefaultLanguageWarning: 'تغيير اللغة الافتراضية قد يؤدي إلى فقدان المحتوى الافتراضي.', - fallsbackToLabel: 'يعود إلى', - noFallbackLanguageOption: 'لا توجد لغة بديلة', - fallbackLanguageDescription: 'للسماح للمحتوى متعدد اللغات بالرجوع إلى لغة أخرى إذا لم يكن موجوداً باللغة المطلوبة، اخترها هنا.\n ', - fallbackLanguage: 'لغة بديلة', - none: 'لا شيء', - invariantPropertyUnlockHelp: '%0% مشتركة عبر اللغات والأقسام.', - invariantCulturePropertyUnlockHelp: '%0% مشتركة عبر جميع اللغات.', - invariantSegmentPropertyUnlockHelp: '%0% مشتركة عبر جميع الأقسام.', - invariantLanguageProperty: 'مشتركة: اللغات', - invariantSegmentProperty: 'مشتركة: الأقسام', - }, + media: 'صورة', + macro: 'ماكرو', + insertControl: 'اختر نوع المحتوى', + chooseLayout: 'اختر تخطيطاً', + addRows: 'أضف صفاً', + addElement: 'أضف محتوى', + dropElement: 'إسقاط المحتوى', + settingsApplied: 'تم تطبيق الإعدادات', + contentNotAllowed: 'هذا المحتوى غير مسموح به هنا', + contentAllowed: 'هذا المحتوى مسموح به هنا', + clickToEmbed: 'انقر للتضمين', + clickToInsertImage: 'انقر لإدراج صورة', + clickToInsertMacro: 'انقر لإدراج ماكرو', + placeholderWriteHere: 'اكتب هنا...', + gridLayouts: 'تخطيطات الشبكة', + gridLayoutsDetail: + 'التخطيطات هي منطقة العمل العامة لمحرر الشبكة، وعادةً ما تحتاج فقط إلى واحد أو اثنين من التخطيطات المختلفة', + addGridLayout: 'إضافة تخطيط شبكة', + editGridLayout: 'تعديل تخطيط الشبكة', + addGridLayoutDetail: 'ضبط التخطيط من خلال تعيين عرض الأعمدة وإضافة أقسام إضافية', + rowConfigurations: 'تكوينات الصفوف', + rowConfigurationsDetail: 'الصفوف هي خلايا محددة مسبقاً مرتبة أفقياً', + addRowConfiguration: 'إضافة تكوين صف', + editRowConfiguration: 'تعديل تكوين الصف', + addRowConfigurationDetail: 'ضبط الصف من خلال تعيين عرض الخلايا وإضافة خلايا إضافية', + noConfiguration: 'لا يوجد تكوين إضافي متاح', + columns: 'الأعمدة', + columnsDetails: 'إجمالي عدد الأعمدة في تخطيط الشبكة', + settings: 'الإعدادات', + settingsDetails: 'تكوين الإعدادات التي يمكن للمحررين تغييرها', + styles: 'الأنماط', + stylesDetails: 'تكوين التنسيق الذي يمكن للمحررين تغييره', + allowAllEditors: 'السماح لجميع المحررين', + allowAllRowConfigurations: 'السماح بجميع تكوينات الصفوف', + maxItems: 'الحد الأقصى للعناصر', + maxItemsDescription: 'اتركه فارغًا أو اضبطه على 0 لغير المحدود', + setAsDefault: 'تعيين كافتراضي', + chooseExtra: 'اختر إضافي', + chooseDefault: 'اختر افتراضي', + areAdded: 'تمت إضافتها', + warning: 'تحذير', + warningText: + '

تعديل اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.

تعديل التسمية فقط لن يؤدي إلى فقدان البيانات.

', + youAreDeleting: 'أنت تقوم بحذف تكوين الصف', + deletingARow: + '\n حذف اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا\n التكوين.\n ', + deleteLayout: 'أنت تقوم بحذف التخطيط', + deletingALayout: 'تعديل التخطيط سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.\n ', + }, + contentTypeEditor: { + compositions: 'التركيبات', + group: 'مجموعة', + groupReorderSameAliasError: + 'لا يمكنك نقل المجموعة %0% إلى هذا التبويب لأن المجموعة ستأخذ نفس الاسم المستعار كالتبويب: "%1%". قم بإعادة تسمية المجموعة للمتابعة.\n ', + noGroups: 'لم تقم بإضافة أي مجموعات', + addGroup: 'إضافة مجموعة', + inheritedFrom: 'موروث من', + addProperty: 'إضافة خاصية', + editProperty: 'تعديل الخاصية', + requiredLabel: 'التسمية المطلوبة', + enableListViewHeading: 'تمكين عرض القائمة', + enableListViewDescription: 'تكوين العنصر لعرض قائمة قابلة للفرز والبحث من أبنائه.', + allowedTemplatesHeading: 'القوالب المسموح بها', + allowedTemplatesDescription: 'اختر القوالب التي يُسمح للمحررين باستخدامها على محتوى من هذا النوع', + allowAtRootHeading: 'السماح في الجذر', + allowAtRootDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع في جذر شجرة المحتوى.\n ', + childNodesHeading: 'أنواع العقد الفرعية المسموح بها', + childNodesDescription: 'السماح بإنشاء محتوى من الأنواع المحددة أسفل محتوى من هذا النوع.', + chooseChildNode: 'اختر العقدة الفرعية', + compositionsDescription: + 'ارث التبويبات والخصائص من نوع مستند موجود. سيتم إضافة التبويبات الجديدة إلى نوع الوثيقة الحالي أو دمجها إذا كان هناك تبويب بنفس الاسم.', + compositionInUse: 'هذا النوع من المحتوى قيد الاستخدام في تركيب، وبالتالي لا يمكن تركيبه بنفسه.\n ', + noAvailableCompositions: 'لا توجد أنواع محتوى متاحة لاستخدامها كتركيب.', + compositionRemoveWarning: + 'إزالة التركيب ستؤدي إلى حذف جميع بيانات الخصائص المرتبطة. بمجرد حفظ نوع الوثيقة لا يوجد طريق للعودة.', + availableEditors: 'إنشاء جديد', + reuse: 'استخدام موجود', + editorSettings: 'إعدادات المحرر', + searchResultSettings: 'الإعدادات المتاحة', + searchResultEditors: 'إنشاء تكوين جديد', + configuration: 'التكوين', + yesDelete: 'نعم، احذف', + movedUnderneath: 'تم نقله تحت', + copiedUnderneath: 'تم نسخه تحت', + folderToMove: 'اختر المجلد للتحريك', + folderToCopy: 'اختر المجلد للنسخ', + structureBelow: 'إلى هيكل الشجرة أدناه', + allDocumentTypes: 'جميع أنواع الوثائق', + allDocuments: 'جميع الوثائق', + allMediaItems: 'جميع العناصر الإعلامية', + usingThisDocument: 'استخدام هذا النوع من الوثائق سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', + usingThisMedia: 'استخدام هذا النوع من الوسائط سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', + usingThisMember: 'استخدام هذا النوع من الأعضاء سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا\n ', + andAllDocuments: 'وجميع الوثائق التي تستخدم هذا النوع', + andAllMediaItems: 'وجميع العناصر الإعلامية التي تستخدم هذا النوع', + andAllMembers: 'وجميع الأعضاء الذين يستخدمون هذا النوع', + memberCanEdit: 'يمكن للعضو التعديل', + memberCanEditDescription: 'السماح بتعديل قيمة هذه الخاصية من قبل العضو في صفحة ملفه الشخصي\n ', + isSensitiveData: 'بيانات حساسة', + isSensitiveDataDescription: + 'إخفاء قيمة هذه الخاصية عن محرري المحتوى الذين لا يملكون حق الوصول لعرض المعلومات الحساسة\n ', + showOnMemberProfile: 'عرض على ملف العضو', + showOnMemberProfileDescription: 'السماح بعرض قيمة هذه الخاصية في صفحة ملف العضو\n ', + tabHasNoSortOrder: 'التبويب ليس له ترتيب فرز', + compositionUsageHeading: 'أين يتم استخدام هذا التركيب؟', + compositionUsageSpecification: 'يتم استخدام هذا التركيب حاليًا في تركيب أنواع المحتوى التالية:\n ', + variantsHeading: 'السماح بالاختلافات', + cultureVariantHeading: 'السماح بالاختلاف حسب الثقافة', + segmentVariantHeading: 'السماح بالتجزئة', + cultureVariantLabel: 'الاختلاف حسب الثقافة', + segmentVariantLabel: 'الاختلاف حسب القطاعات', + variantsDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع بلغات مختلفة.', + cultureVariantDescription: 'السماح للمحررين بإنشاء محتوى بلغات مختلفة.', + segmentVariantDescription: 'السماح للمحررين بإنشاء قطاعات من هذا المحتوى.', + allowVaryByCulture: 'السماح بالاختلاف حسب الثقافة', + allowVaryBySegment: 'السماح بالتجزئة', + elementType: 'نوع العنصر', + elementHeading: 'هو نوع عنصر', + elementDescription: 'نوع العنصر مخصص للاستخدام ضمن أنواع مستندات أخرى، وليس في شجرة المحتوى.\n ', + elementCannotToggle: + 'لا يمكن تغيير نوع مستند إلى نوع عنصر بمجرد أن يتم استخدامه لإنشاء عنصر أو أكثر من محتوى.\n ', + elementDoesNotSupport: 'هذا غير قابل للتطبيق لنوع العنصر', + propertyHasChanges: 'لقد أجريت تغييرات على هذه الخاصية. هل أنت متأكد أنك تريد التخلص منها؟', + displaySettingsHeadline: 'المظهر', + displaySettingsLabelOnTop: 'التسمية في الأعلى (عرض كامل)', + confirmDeleteTabMessage: 'هل أنت متأكد أنك تريد حذف التبويب %0%؟', + confirmDeleteGroupMessage: 'هل أنت متأكد أنك تريد حذف المجموعة %0%؟', + confirmDeletePropertyMessage: 'هل أنت متأكد أنك تريد حذف الخاصية %0%؟', + confirmDeleteTabNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذا التبويب.', + confirmDeleteGroupNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذه المجموعة.', + addTab: 'إضافة تبويب', + convertToTab: 'تحويل إلى تبويب', + tabDirectPropertiesDropZone: 'اسحب الخصائص هنا لوضعها مباشرة على التبويب', + removeChildNode: 'أنت تقوم بإزالة العقدة الفرعية', + removeChildNodeWarning: 'إزالة عقدة فرعية ستحد من خيارات المحررين لإنشاء أنواع محتوى مختلفة أسفل عقدة.', + usingEditor: 'استخدام هذا المحرر سيتم تحديثه بالإعدادات الجديدة.', + historyCleanupHeading: 'تنظيف السجل', + historyCleanupDescription: 'السماح بتجاوز الإعدادات العالمية لتنظيف السجل.', + historyCleanupKeepAllVersionsNewerThanDays: 'احتفظ بجميع الإصدارات الأحدث من الأيام', + historyCleanupKeepLatestVersionPerDayForDays: 'احتفظ بأحدث إصدار لكل يوم لعدد من الأيام', + historyCleanupPreventCleanup: 'منع التنظيف', + historyCleanupEnableCleanup: 'تمكين التنظيف', + historyCleanupGloballyDisabled: + 'ملاحظة! تنظيف إصدارات المحتوى التاريخية معطل عالميًا. لن تكون هذه الإعدادات فعالة حتى يتم تمكينها.', + changeDataTypeHelpText: + 'تغيير نوع البيانات مع القيم المخزنة معطل. للسماح بذلك، يمكنك تغيير إعداد Umbraco:CMS:DataTypes:CanBeChanged في appsettings.json.', + collections: 'المجموعات', + collectionsDescription: 'تكوين العنصر لعرض قائمة بأبنائه.', + structure: 'الهيكل', + presentation: 'العرض', + }, + languages: { + addLanguage: 'إضافة لغة', + culture: 'رمز ISO', + mandatoryLanguage: 'اللغة الإلزامية', + mandatoryLanguageHelp: 'يجب ملء الخصائص في هذه اللغة قبل أن يتم نشر العقدة.\n ', + defaultLanguage: 'اللغة الافتراضية', + defaultLanguageHelp: 'يمكن لموقع Umbraco أن يحتوي فقط على لغة افتراضية واحدة.', + changingDefaultLanguageWarning: 'تغيير اللغة الافتراضية قد يؤدي إلى فقدان المحتوى الافتراضي.', + fallsbackToLabel: 'يعود إلى', + noFallbackLanguageOption: 'لا توجد لغة بديلة', + fallbackLanguageDescription: + 'للسماح للمحتوى متعدد اللغات بالرجوع إلى لغة أخرى إذا لم يكن موجوداً باللغة المطلوبة، اخترها هنا.\n ', + fallbackLanguage: 'لغة بديلة', + none: 'لا شيء', + invariantPropertyUnlockHelp: '%0% مشتركة عبر اللغات والأقسام.', + invariantCulturePropertyUnlockHelp: '%0% مشتركة عبر جميع اللغات.', + invariantSegmentPropertyUnlockHelp: '%0% مشتركة عبر جميع الأقسام.', + invariantLanguageProperty: 'مشتركة: اللغات', + invariantSegmentProperty: 'مشتركة: الأقسام', + }, macro: { addParameter: 'إضافة معلمة', editParameter: 'تعديل المعلمة', @@ -1602,7 +1674,7 @@ export default { }, modelsBuilder: { buildingModels: 'بناء النماذج', - waitingMessage: "قد يستغرق هذا بعض الوقت، لا داعي للقلق", + waitingMessage: 'قد يستغرق هذا بعض الوقت، لا داعي للقلق', modelsGenerated: 'تم إنشاء النماذج', modelsGeneratedError: 'لم يتم إنشاء النماذج', modelsExceptionInUlog: 'فشل إنشاء النماذج، راجع الاستثناء في سجل U', @@ -1644,15 +1716,14 @@ export default { DownloadXmlDTD: 'تنزيل XML DTD', fields: 'الحقول', includeSubpages: 'تضمين الصفحات الفرعية', - noTranslators: - 'لم يتم العثور على مستخدمين مترجمين. يرجى إنشاء مستخدم مترجم قبل البدء في إرسال المحتوى للترجمة', + noTranslators: 'لم يتم العثور على مستخدمين مترجمين. يرجى إنشاء مستخدم مترجم قبل البدء في إرسال المحتوى للترجمة', pageHasBeenSendToTranslation: "تم إرسال الصفحة '%0%' للترجمة", sendToTranslate: "إرسال الصفحة '%0%' للترجمة", totalWords: 'إجمالي الكلمات', translateTo: 'ترجم إلى', translationDone: 'الترجمة مكتملة.', translationDoneHelp: - "يمكنك معاينة الصفحات التي قمت بترجمتها للتو بالنقر أدناه. إذا تم العثور على الصفحة الأصلية، ستتلقى مقارنة بين الصفحتين.", + 'يمكنك معاينة الصفحات التي قمت بترجمتها للتو بالنقر أدناه. إذا تم العثور على الصفحة الأصلية، ستتلقى مقارنة بين الصفحتين.', translationFailed: 'فشلت الترجمة، قد يكون ملف XML تالفاً', translationOptions: 'خيارات الترجمة', translator: 'المترجم', @@ -1705,7 +1776,7 @@ export default { updateNoServer: 'لا يوجد اتصال بالخادم', updateNoServerError: 'خطأ في التحقق من التحديث. يرجى مراجعة تتبع الأخطاء لمزيد من المعلومات', }, - user: { + user: { access: 'الوصول', accessHelp: 'استناداً إلى المجموعات المعينة وعقد البداية، يتمتع المستخدم بالوصول إلى العقد التالية', assignAccess: 'تعيين الوصول', @@ -1724,8 +1795,8 @@ export default { newPassword: 'كلمة مرور جديدة', newPasswordFormatLengthTip: 'الحد الأدنى هو %0% حرفاً!', newPasswordFormatNonAlphaTip: 'يجب أن تحتوي على %0% حرفاً خاصاً على الأقل.', - noLockouts: "لم يتم قفله", - noPasswordChange: "لم يتم تغيير كلمة المرور", + noLockouts: 'لم يتم قفله', + noPasswordChange: 'لم يتم تغيير كلمة المرور', confirmNewPassword: 'تأكيد كلمة المرور الجديدة', changePasswordDescription: "يمكنك تغيير كلمة مرورك للوصول إلى واجهة Umbraco من خلال ملء النموذج أدناه والنقر على زر 'تغيير كلمة المرور'", @@ -1772,9 +1843,8 @@ export default { passwordIsBlank: 'لا يمكن أن تكون كلمة المرور الجديدة فارغة!', passwordCurrent: 'كلمة المرور الحالية', passwordInvalid: 'كلمة المرور الحالية غير صحيحة', - passwordIsDifferent: - 'كان هناك اختلاف بين كلمة المرور الجديدة وكلمة المرور المؤكدة. يرجى المحاولة مرة أخرى!', - passwordMismatch: "كلمة المرور المؤكدة لا تطابق كلمة المرور الجديدة!", + passwordIsDifferent: 'كان هناك اختلاف بين كلمة المرور الجديدة وكلمة المرور المؤكدة. يرجى المحاولة مرة أخرى!', + passwordMismatch: 'كلمة المرور المؤكدة لا تطابق كلمة المرور الجديدة!', passwordRequiresDigit: "يجب أن تحتوي كلمة المرور على رقم واحد على الأقل ('0'-'9')", passwordRequiresLower: "يجب أن تحتوي كلمة المرور على حرف صغير واحد على الأقل ('a'-'z')", passwordRequiresNonAlphanumeric: 'يجب أن تحتوي كلمة المرور على حرف غير أبجدي رقمي واحد على الأقل', @@ -1809,8 +1879,7 @@ export default { startnodeshelp: 'تقييد شجرة المحتوى إلى عقد بداية محددة', updateDate: 'تاريخ آخر تحديث للمستخدم', userCreated: 'تم إنشاؤه', - userCreatedSuccessHelp: - 'تم إنشاء المستخدم الجديد بنجاح. لتسجيل الدخول إلى Umbraco استخدم كلمة المرور أدناه.', + userCreatedSuccessHelp: 'تم إنشاء المستخدم الجديد بنجاح. لتسجيل الدخول إلى Umbraco استخدم كلمة المرور أدناه.', userHasPassword: 'تم تعيين كلمة مرور للمستخدم بالفعل', userHasGroup: "المستخدم موجود بالفعل في المجموعة '%0%'", userLockoutNotEnabled: 'القفل غير مفعل لهذا المستخدم', @@ -1821,14 +1890,12 @@ export default { usergroup: 'مجموعة المستخدمين', usergroups: 'مجموعات المستخدمين', userInvited: 'تمت دعوته', - userInvitedSuccessHelp: - 'تم إرسال دعوة إلى المستخدم الجديد مع تفاصيل حول كيفية تسجيل الدخول إلى Umbraco.', + userInvitedSuccessHelp: 'تم إرسال دعوة إلى المستخدم الجديد مع تفاصيل حول كيفية تسجيل الدخول إلى Umbraco.', userinviteWelcomeMessage: 'مرحباً بك في Umbraco! في دقيقة واحدة فقط ستكون جاهزاً، نحن فقط بحاجة منك لتعيين كلمة مرور وإضافة صورة لملفك الشخصي.', userinviteExpiredMessage: 'مرحباً بك في Umbraco! للأسف انتهت صلاحية دعوتك. يرجى الاتصال بالمسؤول الخاص بك واطلب منهم إعادة إرسالها.', - userinviteAvatarMessage: - 'رفع صورة لنفسك سيساعد الآخرين على التعرف عليك بسهولة. انقر على الدائرة أعلاه لرفع صورتك.', + userinviteAvatarMessage: 'رفع صورة لنفسك سيساعد الآخرين على التعرف عليك بسهولة. انقر على الدائرة أعلاه لرفع صورتك.', writer: 'كاتب', configureTwoFactor: 'تكوين التحقق بخطوتين', change: 'تغيير', @@ -1915,10 +1982,10 @@ export default { macroErrorModeCheckSuccessMessage: "MacroErrors تم تعيينها إلى '%0%'.", macroErrorModeCheckErrorMessage: "MacroErrors تم تعيينها إلى '%0%' مما سيمنع بعض أو جميع الصفحات في\n موقعك من التحميل بالكامل إذا كانت هناك أي أخطاء في الماكرو. تصحيح ذلك سيجعل القيمة تُعيّن إلى '%1%'.\n ", - httpsCheckValidCertificate: "شهادة موقعك صالحة.", + httpsCheckValidCertificate: 'شهادة موقعك صالحة.', httpsCheckInvalidCertificate: "خطأ في التحقق من الشهادة: '%0%'", - httpsCheckExpiredCertificate: "شهادة SSL لموقعك قد انتهت صلاحيتها.", - httpsCheckExpiringCertificate: "شهادة SSL لموقعك تنتهي صلاحيتها في %0% يوماً.", + httpsCheckExpiredCertificate: 'شهادة SSL لموقعك قد انتهت صلاحيتها.', + httpsCheckExpiringCertificate: 'شهادة SSL لموقعك تنتهي صلاحيتها في %0% يوماً.', healthCheckInvalidUrl: "خطأ في اختبار URL %0% - '%1%'", httpsCheckIsCurrentSchemeHttps: 'أنت حالياً %0% تعرض الموقع باستخدام مخطط HTTPS.', httpsCheckConfigurationRectifyNotPossible: @@ -1953,15 +2020,12 @@ export default { 'تم العثور على الرؤوس التالية التي تكشف عن معلومات حول تكنولوجيا الموقع: %0%.', excessiveHeadersNotFound: 'لم يتم العثور على رؤوس تكشف عن معلومات حول تكنولوجيا الموقع.\n ', smtpMailSettingsNotFound: "إعدادات 'Umbraco:CMS:Global:Smtp' لم يتم العثور عليها.", - smtpMailSettingsHostNotConfigured: - "إعداد 'Umbraco:CMS:Global:Smtp:Host' لم يتم العثور عليه.\n ", - smtpMailSettingsConnectionSuccess: - 'تم تكوين إعدادات SMTP بشكل صحيح والخدمة تعمل كما هو متوقع.\n ', + smtpMailSettingsHostNotConfigured: "إعداد 'Umbraco:CMS:Global:Smtp:Host' لم يتم العثور عليه.\n ", + smtpMailSettingsConnectionSuccess: 'تم تكوين إعدادات SMTP بشكل صحيح والخدمة تعمل كما هو متوقع.\n ', smtpMailSettingsConnectionFail: "لم يتم الوصول إلى خادم SMTP المُعين بالمضيف '%0%' والمنفذ '%1%'. يرجى التحقق للتأكد من صحة إعدادات SMTP في التكوين 'Umbraco:CMS:Global:Smtp'.\n ", notificationEmailsCheckSuccessMessage: 'تم تعيين بريد الإشعارات إلى %0%.', - notificationEmailsCheckErrorMessage: - 'بريد الإشعارات ما زال مضبوطًا على القيمة الافتراضية %0%.', + notificationEmailsCheckErrorMessage: 'بريد الإشعارات ما زال مضبوطًا على القيمة الافتراضية %0%.', checkGroup: 'فحص المجموعة', helpText: '\n

مدقق الصحة يقيم مجالات مختلفة في موقعك لأفضل إعدادات الممارسات والتكوين والمشاكل المحتملة، وما إلى ذلك. يمكنك إصلاح المشكلات بسهولة عن طريق الضغط على زر.\n يمكنك إضافة فحوصات صحية خاصة بك، راجع التوثيق لمزيد من المعلومات حول فحوصات الصحة المخصصة.

\n ', @@ -1975,8 +2039,7 @@ export default { redirectUrlManagement: 'إدارة URL التحويل', panelInformation: 'توجه URLs التالية إلى هذا العنصر المحتوى:', noRedirects: 'لم يتم إجراء أي تحويلات', - noRedirectsDescription: - 'عند إعادة تسمية صفحة منشورة أو نقلها، سيتم تلقائيًا إجراء تحويل إلى الصفحة الجديدة.\n ', + noRedirectsDescription: 'عند إعادة تسمية صفحة منشورة أو نقلها، سيتم تلقائيًا إجراء تحويل إلى الصفحة الجديدة.\n ', redirectRemoved: 'تمت إزالة URL التحويل.', redirectRemoveError: 'خطأ في إزالة URL التحويل.', redirectRemoveWarning: 'سيتم إزالة التحويل', @@ -2098,8 +2161,7 @@ export default { labelUsedItems: 'العناصر التالية يتم الاستشهاد بها', labelUsedDescendants: 'العناصر اللاحقة التالية لها تبعيات', labelDependentDescendants: 'العناصر اللاحقة التالية لها تبعيات', - deleteWarning: - 'يتم الاستشهاد بهذا العنصر أو أحفاده. يمكن أن تؤدي الحذف إلى روابط مكسورة على موقعك الإلكتروني.', + deleteWarning: 'يتم الاستشهاد بهذا العنصر أو أحفاده. يمكن أن تؤدي الحذف إلى روابط مكسورة على موقعك الإلكتروني.', unpublishWarning: 'يتم الاستشهاد بهذا العنصر أو أحفاده. يمكن أن يؤدي إلغاء النشر إلى روابط مكسورة على موقعك الإلكتروني. يرجى اتخاذ الإجراءات المناسبة.', deleteDisabledWarning: 'يتم الاستشهاد بهذا العنصر أو أحفاده. لذلك، تم تعطيل الحذف.', @@ -2109,286 +2171,314 @@ export default { return `...ومزيد من ${count} عناصر`; }, }, - logViewer: { - deleteSavedSearch: 'حذف البحث المحفوظ', - logLevels: 'مستويات السجل', - selectAllLogLevelFilters: 'تحديد الكل', - deselectAllLogLevelFilters: 'إلغاء تحديد الكل', - savedSearches: 'البحث المحفوظ', - saveSearch: 'حفظ البحث', - saveSearchDescription: 'أدخل اسمًا وديًا لاستعلام البحث الخاص بك', - filterSearch: 'تصفية البحث', - totalItems: 'إجمالي العناصر', - timestamp: 'الطابع الزمني', - level: 'المستوى', - machine: 'الآلة', - message: 'الرسالة', - exception: 'الاستثناء', - properties: 'الخصائص', - searchWithGoogle: 'البحث باستخدام جوجل', - searchThisMessageWithGoogle: 'ابحث عن هذه الرسالة باستخدام جوجل', - searchWithBing: 'البحث باستخدام بينج', - searchThisMessageWithBing: 'ابحث عن هذه الرسالة باستخدام بينج', - searchOurUmbraco: 'البحث في Umbraco الخاص بنا', - searchThisMessageOnOurUmbracoForumsAndDocs: 'ابحث عن هذه الرسالة في منتديات ومراسلات Umbraco الخاصة بنا', - searchOurUmbracoWithGoogle: 'البحث في Umbraco الخاص بنا باستخدام جوجل', - searchOurUmbracoForumsUsingGoogle: 'البحث في منتديات Umbraco الخاصة بنا باستخدام جوجل', - searchUmbracoSource: 'البحث في مصدر Umbraco', - searchWithinUmbracoSourceCodeOnGithub: 'البحث ضمن كود مصدر Umbraco على Github', - searchUmbracoIssues: 'البحث في قضايا Umbraco', - searchUmbracoIssuesOnGithub: 'البحث في قضايا Umbraco على Github', - deleteThisSearch: 'حذف هذا البحث', - findLogsWithRequestId: 'البحث في السجلات باستخدام معرّف الطلب', - findLogsWithNamespace: 'البحث في السجلات باستخدام النطاق', - findLogsWithMachineName: 'البحث في السجلات باستخدام اسم الآلة', - open: 'فتح', - polling: 'استطلاع', - every2: 'كل 2 ثانية', - every5: 'كل 5 ثوانٍ', - every10: 'كل 10 ثوانٍ', - every20: 'كل 20 ثانية', - every30: 'كل 30 ثانية', - pollingEvery2: 'استطلاع كل 2 ثانية', - pollingEvery5: 'استطلاع كل 5 ثوانٍ', - pollingEvery10: 'استطلاع كل 10 ثوانٍ', - pollingEvery20: 'استطلاع كل 20 ثانية', - pollingEvery30: 'استطلاع كل 30 ثانية' - }, - clipboard: { - labelForCopyAllEntries: 'نسخ %0%', - labelForArrayOfItemsFrom: '%0% من %1%', - labelForArrayOfItems: 'مجموعة من %0%', - labelForRemoveAllEntries: 'إزالة جميع العناصر', - labelForClearClipboard: 'مسح الحافظة', - labelForCopyToClipboard: 'نسخ إلى الحافظة' - }, - propertyActions: { - tooltipForPropertyActionsMenu: 'فتح إجراءات الخصائص', - tooltipForPropertyActionsMenuClose: 'إغلاق إجراءات الخصائص' - }, - nuCache: { - refreshStatus: 'تحديث الحالة', - memoryCache: 'ذاكرة التخزين المؤقت', - memoryCacheDescription: 'هذا الزر يتيح لك إعادة تحميل ذاكرة التخزين المؤقت في الذاكرة، من خلال إعادة تحميلها بالكامل من قاعدة البيانات (ولكنه لا يعيد بناء تلك الذاكرة المؤقتة في قاعدة البيانات). هذا سريع نسبيًا. استخدمه عندما تعتقد أن ذاكرة التخزين المؤقت في الذاكرة لم يتم تحديثها بشكل صحيح، بعد بعض الأحداث التي تم تشغيلها—مما قد يشير إلى مشكلة طفيفة في Umbraco. (ملاحظة: يشغل إعادة التحميل على جميع الخوادم في بيئة LB).', - reload: 'إعادة تحميل', - databaseCache: 'ذاكرة التخزين المؤقت لقاعدة البيانات', - databaseCacheDescription: 'هذا الزر يتيح لك إعادة بناء ذاكرة التخزين المؤقت لقاعدة البيانات، أي محتوى جدول cmsContentNu. إعادة البناء يمكن أن تكون مكلفة. استخدمه عندما لا يكون إعادة التحميل كافيًا، وتعتقد أن ذاكرة التخزين المؤقت لقاعدة البيانات لم يتم إنشاؤها بشكل صحيح—مما قد يشير إلى مشكلة حاسمة في Umbraco.', - rebuild: 'إعادة بناء', - internals: 'الأنظمة الداخلية', - internalsDescription: 'هذا الزر يتيح لك تشغيل مجموعة لقطات NuCache (بعد تشغيل GC الكامل). ما لم تكن تعرف ما يعني ذلك، فمن المحتمل أنك لا تحتاج إلى استخدامه.', - collect: 'جمع', - publishedCacheStatus: 'حالة ذاكرة التخزين المؤقت المنشورة', - caches: 'ذاكرات التخزين المؤقت' - }, - profiling: { - performanceProfiling: 'تحليل الأداء', - performanceProfilingDescription: "

تشغيل Umbraco حاليًا في وضع التصحيح. هذا يعني أنه يمكنك استخدام أداة تحليل الأداء المدمجة لتقييم الأداء عند عرض الصفحات.

إذا كنت تريد تفعيل أداة التحليل لعرض صفحة معينة، أضف ببساطة umbDebug=true إلى سلسلة الاستعلام عند طلب الصفحة.

إذا كنت تريد أن يتم تفعيل أداة التحليل بشكل افتراضي لجميع عمليات عرض الصفحات، يمكنك استخدام التبديل أدناه. سيقوم بتعيين ملف تعريف في متصفحك، والذي يقوم بعد ذلك بتفعيل أداة التحليل تلقائيًا. بعبارة أخرى، ستكون أداة التحليل نشطة افتراضيًا فقط في متصفحك - وليس في متصفحات الآخرين.

", - activateByDefault: 'تفعيل أداة التحليل بشكل افتراضي', - reminder: 'تذكير ودي', - reminderDescription: '

يجب ألا تدع موقع الإنتاج يعمل في وضع التصحيح. يتم إيقاف وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى false في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

', - profilerEnabledDescription: "

Umbraco حاليًا لا يعمل في وضع التصحيح، لذا لا يمكنك استخدام أداة التحليل المدمجة. هذا هو الوضع الصحيح لموقع الإنتاج.

يتم تشغيل وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى true في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

" - }, - settingsDashboardVideos: { - trainingHeadline: 'ساعات من مقاطع فيديو تدريب Umbraco على بعد نقرة واحدة', - trainingDescription: '

هل تريد إتقان Umbraco؟ اقض بضع دقائق في تعلم بعض الممارسات الأفضل من خلال مشاهدة واحدة من هذه الفيديوهات حول استخدام Umbraco. وزيارة umbraco.tv لمزيد من مقاطع الفيديو حول Umbraco

' - }, - settingsDashboard: { - documentationHeader: 'التوثيق', - documentationDescription: 'اقرأ المزيد عن العمل مع العناصر في الإعدادات في توثيقنا.', - communityHeader: 'المجتمع', - communityDescription: 'اطرح سؤالاً في منتدى المجتمع أو مجتمع Discord لدينا.', - trainingHeader: 'التدريب', - trainingDescription: 'اكتشف فرص التدريب والتأهيل الرسمية', - supportHeader: 'الدعم', - supportDescription: 'قم بتوسيع فريقك مع مجموعة ماهرة ومتحمسة من خبراء Umbraco.', - videosHeader: 'مقاطع الفيديو', - videosDescription: 'شاهد مقاطع الفيديو التعليمية المجانية لدينا على قناة YouTube الخاصة بأساسيات Umbraco، لتصبح على اطلاع سريع بـ Umbraco.', - getHelp: 'احصل على المساعدة التي تحتاجها', - getCertified: 'احصل على الشهادة', - goForum: 'اذهب إلى المنتدى', - chatWithCommunity: 'الدردشة مع المجتمع', - watchVideos: 'شاهد مقاطع الفيديو' - }, - startupDashboard: { - fallbackHeadline: 'مرحبًا بك في نظام إدارة المحتوى الودود', - fallbackDescription: "شكرًا لاختيارك Umbraco - نعتقد أن هذه قد تكون بداية شيء جميل. بينما قد يبدو الأمر مربكًا في البداية، لقد بذلنا الكثير لجعل منحنى التعلم سلسًا وسريعًا قدر الإمكان." - }, - welcomeDashboard: { - ourUmbracoHeadline: 'Umbraco الخاص بنا - أكثر المجتمعات صداقة', - ourUmbracoDescription: "Umbraco الخاص بنا، الموقع الرسمي للمجتمع، هو وجهتك الشاملة لكل شيء متعلق بـ Umbraco. سواء كنت بحاجة إلى إجابة على سؤال، أو إضافات رائعة، أو دليل حول كيفية القيام بشيء ما في Umbraco، فإن أفضل وأصدق مجتمع في العالم هو مجرد نقرة بعيدًا.", - ourUmbracoButton: 'زيارة Umbraco الخاص بنا', - documentationHeadline: 'التوثيق', - documentationDescription: 'ابحث عن إجابات لجميع أسئلتك حول Umbraco', - communityHeadline: 'المجتمع', - communityDescription: 'احصل على الدعم والإلهام من خبراء Umbraco المتحمسين', - resourcesHeadline: 'الموارد', - resourcesDescription: 'دروس فيديو مجانية لبدء رحلتك مع نظام إدارة المحتوى', - trainingHeadline: 'التدريب', - trainingDescription: 'التدريب الواقعي وشهادات Umbraco الرسمية' - }, - blockEditor: { - headlineCreateBlock: 'اختيار نوع العنصر', - headlineAddSettingsElementType: 'إضافة نوع عنصر الإعدادات', - headlineAddCustomView: 'اختيار العرض', - headlineAddCustomStylesheet: 'اختيار ورقة الأنماط', - headlineAddThumbnail: 'اختيار الصورة المصغرة', - labelcreateNewElementType: 'إنشاء نوع عنصر جديد', - labelCustomStylesheet: 'ورقة أنماط مخصصة', - addCustomStylesheet: 'إضافة ورقة أنماط', - headlineEditorAppearance: 'مظهر الكتلة', - headlineDataModels: 'نماذج البيانات', - headlineCatalogueAppearance: 'مظهر الكتالوج', - labelBackgroundColor: 'لون الخلفية', - labelIconColor: 'لون الأيقونة', - labelContentElementType: 'نموذج المحتوى', - labelLabelTemplate: 'التسمية', - labelCustomView: 'عرض مخصص', - labelCustomViewInfoTitle: 'عرض وصف العرض المخصص', - labelCustomViewDescription: 'تجاوز كيفية ظهور هذه الكتلة في واجهة المستخدم الخلفية. اختر ملف .html يحتوي على تقديمك.', - labelSettingsElementType: 'نموذج الإعدادات', - labelEditorSize: 'حجم محرر التراكب', - addCustomView: 'إضافة عرض مخصص', - addSettingsElementType: 'إضافة إعدادات', - confirmDeleteBlockMessage: 'هل أنت متأكد أنك تريد حذف المحتوى %0%؟', - confirmDeleteBlockTypeMessage: 'هل أنت متأكد أنك تريد حذف تكوين الكتلة %0%؟', - confirmDeleteBlockTypeNotice: 'سيظل محتوى هذه الكتلة موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', - confirmDeleteBlockGroupMessage: 'هل أنت متأكد أنك تريد حذف المجموعة %0% وجميع تكوينات الكتلة الخاصة بها؟', - confirmDeleteBlockGroupNotice: 'سيظل محتوى هذه الكتل موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', - blockConfigurationOverlayTitle: "تكوين '%0%'", - elementTypeDoesNotExist: 'لا يمكن تحريره لأن نوع العنصر غير موجود.', - thumbnail: 'صورة مصغرة', - addThumbnail: 'إضافة صورة مصغرة', - tabCreateEmpty: 'إنشاء فارغ', - tabClipboard: 'الحافظة', - tabBlockSettings: 'الإعدادات', - headlineAdvanced: 'متقدم', - headlineCustomView: 'عرض مخصص', - forceHideContentEditor: 'إخفاء محرر المحتوى', - forceHideContentEditorHelp: 'إخفاء زر تحرير المحتوى ومحرر المحتوى من تراكب محرر الكتل', - gridInlineEditing: 'تحرير مباشر', - gridInlineEditingHelp: 'يتيح التحرير المباشر لأول خاصية. يمكن تحرير الخصائص الإضافية في التراكب.', - blockHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد تجاهلها؟', - confirmCancelBlockCreationHeadline: 'تجاهل الإنشاء؟', - confirmCancelBlockCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', - elementTypeDoesNotExistHeadline: 'خطأ!', - elementTypeDoesNotExistDescription: 'نوع العنصر لهذه الكتلة لم يعد موجودًا', - addBlock: 'إضافة محتوى', - addThis: 'إضافة %0%', - propertyEditorNotSupported: "الخاصية '%0%' تستخدم المحرر '%1%' والذي لا يدعمه الكتل.", - focusParentBlock: 'تعيين التركيز على الكتلة الحاوية', - areaIdentification: 'التحديد', - areaValidation: 'التحقق', - areaValidationEntriesShort: '%0% يجب أن تكون موجودة على الأقل %2% مرة(s).', - areaValidationEntriesExceed: '%0% يجب أن تكون موجودة بحد أقصى %3% مرة(s).', - areaNumberOfBlocks: 'عدد الكتل', - areaDisallowAllBlocks: 'السماح بأنواع كتل محددة فقط', - areaAllowedBlocks: 'أنواع الكتل المسموح بها', - areaAllowedBlocksHelp: 'حدد أنواع الكتل المسموح بها في هذه المنطقة، واختياريًا عدد كل نوع من الأنواع التي يجب أن تكون موجودة.', - confirmDeleteBlockAreaMessage: 'هل أنت متأكد أنك تريد حذف هذه المنطقة؟', - confirmDeleteBlockAreaNotice: 'أي كتل تم إنشاؤها حاليًا داخل هذه المنطقة سيتم حذفها.', - layoutOptions: 'خيارات التخطيط', - structuralOptions: 'هيكلية', - sizeOptions: 'خيارات الحجم', - sizeOptionsHelp: 'حدد خيارًا أو أكثر من خيارات الحجم، هذا يمكن أن يتيح تغيير حجم الكتلة', - allowedBlockColumns: 'امتدادات الأعمدة المتاحة', - allowedBlockColumnsHelp: 'حدد عدد الأعمدة المختلفة التي يُسمح لهذه الكتلة بالامتداد عبرها. هذا لا يمنع الكتل من وضعها في مناطق ذات امتداد أعمدة أصغر.', - allowedBlockRows: 'امتدادات الصفوف المتاحة', - allowedBlockRowsHelp: 'حدد نطاق الصفوف التخطيطية التي يُسمح لهذه الكتلة بالامتداد عبرها.', - allowBlockInRoot: 'السماح في الجذر', - allowBlockInRootHelp: 'اجعل هذه الكتلة متاحة في جذر التخطيط.', - allowBlockInAreas: 'السماح في المناطق', - allowBlockInAreasHelp: 'اجعل هذه الكتلة متاحة افتراضيًا ضمن مناطق كتل أخرى (ما لم يتم تعيين أذونات صريحة لهذه المناطق).', - areaAllowedBlocksEmpty: 'افتراضيًا، جميع أنواع الكتل مسموح بها في منطقة، استخدم هذا الخيار للسماح بأنواع محددة فقط.', - areas: 'المناطق', - areasLayoutColumns: 'أعمدة الشبكة للمناطق', - areasLayoutColumnsHelp: 'حدد عدد الأعمدة المتاحة للمناطق. إذا لم يتم تحديدها، سيتم استخدام عدد الأعمدة المحدد للتخطيط الكامل.', - areasConfigurations: 'المناطق', - areasConfigurationsHelp: 'لتمكين تداخل الكتل داخل هذه الكتلة، حدد منطقة واحدة أو أكثر. تتبع المناطق التخطيط المحدد من خلال تكوين عمود الشبكة الخاص بها. يمكن تعديل "امتداد العمود" و "امتداد الصف" لكل منطقة باستخدام مربع مقبض التدرج في الزاوية السفلى اليمنى من المنطقة المحددة.', - invalidDropPosition: '%0% غير مسموح به في هذا الموضع.', - defaultLayoutStylesheet: 'ورقة أنماط التخطيط الافتراضية', - confirmPasteDisallowedNestedBlockHeadline: 'تم رفض المحتوى غير المسموح به', - confirmPasteDisallowedNestedBlockMessage: 'احتوى المحتوى الذي تم إدراجه على محتوى غير مسموح به، والذي لم يتم إنشاؤه. هل ترغب في الاحتفاظ ببقية هذا المحتوى على أي حال؟', - areaAliasHelp: 'عند استخدام GetBlockGridHTML() لعرض شبكة الكتل، سيتم عرض الاسم المستعار في الشيفرة المصدرية كخاصية \'data-area-alias\'. استخدم خاصية الاسم المستعار لاستهداف العنصر للمنطقة. مثال. .umb-block-grid__area[data-area-alias="MyAreaAlias"] { ... }', - scaleHandlerButtonTitle: 'اسحب للتغيير الحجم', - areaCreateLabelTitle: 'تسمية زر الإنشاء', - areaCreateLabelHelp: 'تجاوز نص التسمية لإضافة كتلة جديدة إلى هذه المنطقة، مثال: "إضافة عنصر واجهة المستخدم"', - showSizeOptions: 'عرض خيارات تغيير الحجم', - addBlockType: 'إضافة كتلة', - addBlockGroup: 'إضافة مجموعة', - pickSpecificAllowance: 'اختر مجموعة أو كتلة', - allowanceMinimum: 'تحديد الحد الأدنى المطلوب', - allowanceMaximum: 'تحديد الحد الأقصى المطلوب', - block: 'كتلة', - tabBlock: 'كتلة', - tabBlockTypeSettings: 'الإعدادات', - tabAreas: 'المناطق', - tabAdvanced: 'متقدم', - headlineAllowance: 'الأذونات', - getSampleHeadline: 'تثبيت التكوين التجريبي', - getSampleDescription: "سيضيف هذا كتل أساسية ويساعدك على البدء باستخدام محرر شبكة الكتل. ستحصل على كتل للعناوين والنصوص الغنية والصور، بالإضافة إلى تخطيط بعمودين.", - getSampleButton: 'تثبيت', - actionEnterSortMode: 'وضع الترتيب', - actionExitSortMode: 'إنهاء وضع الترتيب', - areaAliasIsNotUnique: 'يجب أن يكون اسم المنطقة هذا فريد مقارنةً بالمناطق الأخرى لهذه الكتلة.', - configureArea: 'تكوين المنطقة', - deleteArea: 'حذف المنطقة', - addColumnSpanOption: 'إضافة خيار امتداد %0% عمود' - }, - contentTemplatesDashboard: { - whatHeadline: 'ما هي المخططات الوثائقية؟', - whatDescription: 'المخططات الوثائقية هي محتوى مُعرّف مسبقًا يمكن تحديده عند إنشاء عقدة محتوى جديدة.', - createHeadline: 'كيف يمكنني إنشاء مخطط وثائقي؟', - createDescription: '

هناك طريقتان لإنشاء مخطط وثائقي:

  • انقر بزر الماوس الأيمن على عقدة المحتوى واختر "إنشاء مخطط وثائقي" لإنشاء مخطط وثائقي جديد.
  • انقر بزر الماوس الأيمن على شجرة المخططات الوثائقية في قسم الإعدادات واختر نوع الوثيقة الذي تريد إنشاء مخطط وثائقي له.

بمجرد إعطائها اسمًا، يمكن للمحررين البدء في استخدام المخطط الوثائقي كأساس لصفحتهم الجديدة.

', - manageHeadline: 'كيف يمكنني إدارة المخططات الوثائقية؟', - manageDescription: 'يمكنك تعديل وحذف المخططات الوثائقية من "شجرة المخططات الوثائقية" في قسم الإعدادات. قم بتوسيع نوع الوثيقة الذي يعتمد عليه المخطط الوثائقي وانقر عليه لتعديله أو حذفه.' - }, - preview: { - endLabel: 'نهاية', - endTitle: 'إنهاء وضع المعاينة', - openWebsiteLabel: 'معاينة الموقع', - openWebsiteTitle: 'فتح الموقع في وضع المعاينة', - returnToPreviewHeadline: 'معاينة الموقع؟', - returnToPreviewDescription: 'لقد انتهيت من وضع المعاينة، هل ترغب في تمكينه مرة أخرى لعرض أحدث إصدار محفوظ من موقعك؟', - returnToPreviewAcceptButton: 'معاينة أحدث إصدار', - returnToPreviewDeclineButton: 'عرض الإصدار المنشور', - viewPublishedContentHeadline: 'عرض الإصدار المنشور؟', - viewPublishedContentDescription: 'أنت في وضع المعاينة، هل تريد الخروج لعرض الإصدار المنشور لموقعك؟', - viewPublishedContentAcceptButton: 'عرض الإصدار المنشور', - viewPublishedContentDeclineButton: 'البقاء في وضع المعاينة' - }, - permissions: { - FolderCreation: 'إنشاء مجلد', - FileWritingForPackages: 'كتابة الملفات للحزم', - FileWriting: 'كتابة الملفات', - MediaFolderCreation: 'إنشاء مجلد الوسائط' - }, - treeSearch: { - searchResult: 'عنصر تم إرجاعه', - searchResults: 'عناصر تم إرجاعها' - }, - analytics: { - consentForAnalytics: 'الموافقة على بيانات التتبع', - analyticsLevelSavedSuccess: 'تم حفظ مستوى التتبع!', - analyticsDescription: '\n لتحسين Umbraco وإضافة ميزات جديدة بناءً على معلومات ذات صلة قدر الإمكان،\n
نود جمع معلومات النظام والاستخدام من تثبيتك.\n
سيتم مشاركة البيانات المجمعة بانتظام بالإضافة إلى الدروس المستفادة من هذه المقاييس.\n
نأمل أن تساعدنا في جمع بعض البيانات القيمة.\n
\n
نحن لن نقوم بجمع أي بيانات شخصية مثل المحتوى أو الكود أو معلومات المستخدم، وستكون جميع البيانات مجهولة الهوية تمامًا.\n ', - minimalLevelDescription: 'سوف نرسل فقط معرف موقع مجهول الهوية لإعلامنا بوجود الموقع.', - basicLevelDescription: 'سوف نرسل معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة', - detailedLevelDescription: '\n سوف نرسل:\n
    \n
  • معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة.
  • \n
  • عدد: العقد الجذرية، العقد المحتوى، الوسائط، أنواع الوثائق، القوالب، اللغات، النطاقات، مجموعات المستخدمين، المستخدمين، الأعضاء، مقدمي تسجيل الدخول الخارجيين إلى المكتب الخلفي، ومحرري الخصائص قيد الاستخدام.
  • \n
  • معلومات النظام: خادم الويب، نظام تشغيل الخادم، إطار عمل الخادم، لغة نظام تشغيل الخادم، ومزود قاعدة البيانات.
  • \n
  • إعدادات التكوين: وضع Modelsbuilder، إذا كان هناك مسار Umbraco مخصص، بيئة ASP، ما إذا كان API التوصيل مفعلًا، ويتيح الوصول العام، وإذا كنت في وضع التصحيح.
  • \n
\n قد نغير ما نرسله على المستوى التفصيلي في المستقبل. إذا كان الأمر كذلك، فسيتم سردها أعلاه.\n
من خلال اختيار "تفصيلي" توافق على جمع المعلومات المجهولة الهوية الحالية والمستقبلية.
\n ' - }, - routing: { - routeNotFoundTitle: 'لم يتم العثور على الصفحة', - routeNotFoundDescription: 'لم يتم العثور على المسار المطلوب. يرجى التحقق من عنوان URL والمحاولة مرة أخرى.' - }, - codeEditor: { - label: 'محرر الأكواد', - languageConfigLabel: 'اللغة', - languageConfigDescription: 'اختر اللغة لتظليل بناء الجملة وIntelliSense.', - heightConfigLabel: 'الارتفاع', - heightConfigDescription: 'حدد ارتفاع محرر الأكواد بالبكسل.', - lineNumbersConfigLabel: 'أرقام الأسطر', - lineNumbersConfigDescription: 'عرض أرقام الأسطر في محرر الأكواد.', - minimapConfigLabel: 'خريطة مصغرة', - minimapConfigDescription: 'عرض خريطة مصغرة في محرر الأكواد.', - wordWrapConfigLabel: 'تغليف الكلمات', - wordWrapConfigDescription: 'تفعيل تغليف الكلمات في محرر الأكواد.' - } + logViewer: { + deleteSavedSearch: 'حذف البحث المحفوظ', + logLevels: 'مستويات السجل', + selectAllLogLevelFilters: 'تحديد الكل', + deselectAllLogLevelFilters: 'إلغاء تحديد الكل', + savedSearches: 'البحث المحفوظ', + saveSearch: 'حفظ البحث', + saveSearchDescription: 'أدخل اسمًا وديًا لاستعلام البحث الخاص بك', + filterSearch: 'تصفية البحث', + totalItems: 'إجمالي العناصر', + timestamp: 'الطابع الزمني', + level: 'المستوى', + machine: 'الآلة', + message: 'الرسالة', + exception: 'الاستثناء', + properties: 'الخصائص', + searchWithGoogle: 'البحث باستخدام جوجل', + searchThisMessageWithGoogle: 'ابحث عن هذه الرسالة باستخدام جوجل', + searchWithBing: 'البحث باستخدام بينج', + searchThisMessageWithBing: 'ابحث عن هذه الرسالة باستخدام بينج', + searchOurUmbraco: 'البحث في Umbraco الخاص بنا', + searchThisMessageOnOurUmbracoForumsAndDocs: 'ابحث عن هذه الرسالة في منتديات ومراسلات Umbraco الخاصة بنا', + searchOurUmbracoWithGoogle: 'البحث في Umbraco الخاص بنا باستخدام جوجل', + searchOurUmbracoForumsUsingGoogle: 'البحث في منتديات Umbraco الخاصة بنا باستخدام جوجل', + searchUmbracoSource: 'البحث في مصدر Umbraco', + searchWithinUmbracoSourceCodeOnGithub: 'البحث ضمن كود مصدر Umbraco على Github', + searchUmbracoIssues: 'البحث في قضايا Umbraco', + searchUmbracoIssuesOnGithub: 'البحث في قضايا Umbraco على Github', + deleteThisSearch: 'حذف هذا البحث', + findLogsWithRequestId: 'البحث في السجلات باستخدام معرّف الطلب', + findLogsWithNamespace: 'البحث في السجلات باستخدام النطاق', + findLogsWithMachineName: 'البحث في السجلات باستخدام اسم الآلة', + open: 'فتح', + polling: 'استطلاع', + every2: 'كل 2 ثانية', + every5: 'كل 5 ثوانٍ', + every10: 'كل 10 ثوانٍ', + every20: 'كل 20 ثانية', + every30: 'كل 30 ثانية', + pollingEvery2: 'استطلاع كل 2 ثانية', + pollingEvery5: 'استطلاع كل 5 ثوانٍ', + pollingEvery10: 'استطلاع كل 10 ثوانٍ', + pollingEvery20: 'استطلاع كل 20 ثانية', + pollingEvery30: 'استطلاع كل 30 ثانية', + }, + clipboard: { + labelForCopyAllEntries: 'نسخ %0%', + labelForArrayOfItemsFrom: '%0% من %1%', + labelForArrayOfItems: 'مجموعة من %0%', + labelForRemoveAllEntries: 'إزالة جميع العناصر', + labelForClearClipboard: 'مسح الحافظة', + labelForCopyToClipboard: 'نسخ إلى الحافظة', + }, + propertyActions: { + tooltipForPropertyActionsMenu: 'فتح إجراءات الخصائص', + tooltipForPropertyActionsMenuClose: 'إغلاق إجراءات الخصائص', + }, + nuCache: { + refreshStatus: 'تحديث الحالة', + memoryCache: 'ذاكرة التخزين المؤقت', + memoryCacheDescription: + 'هذا الزر يتيح لك إعادة تحميل ذاكرة التخزين المؤقت في الذاكرة، من خلال إعادة تحميلها بالكامل من قاعدة البيانات (ولكنه لا يعيد بناء تلك الذاكرة المؤقتة في قاعدة البيانات). هذا سريع نسبيًا. استخدمه عندما تعتقد أن ذاكرة التخزين المؤقت في الذاكرة لم يتم تحديثها بشكل صحيح، بعد بعض الأحداث التي تم تشغيلها—مما قد يشير إلى مشكلة طفيفة في Umbraco. (ملاحظة: يشغل إعادة التحميل على جميع الخوادم في بيئة LB).', + reload: 'إعادة تحميل', + databaseCache: 'ذاكرة التخزين المؤقت لقاعدة البيانات', + databaseCacheDescription: + 'هذا الزر يتيح لك إعادة بناء ذاكرة التخزين المؤقت لقاعدة البيانات، أي محتوى جدول cmsContentNu. إعادة البناء يمكن أن تكون مكلفة. استخدمه عندما لا يكون إعادة التحميل كافيًا، وتعتقد أن ذاكرة التخزين المؤقت لقاعدة البيانات لم يتم إنشاؤها بشكل صحيح—مما قد يشير إلى مشكلة حاسمة في Umbraco.', + rebuild: 'إعادة بناء', + internals: 'الأنظمة الداخلية', + internalsDescription: + 'هذا الزر يتيح لك تشغيل مجموعة لقطات NuCache (بعد تشغيل GC الكامل). ما لم تكن تعرف ما يعني ذلك، فمن المحتمل أنك لا تحتاج إلى استخدامه.', + collect: 'جمع', + publishedCacheStatus: 'حالة ذاكرة التخزين المؤقت المنشورة', + caches: 'ذاكرات التخزين المؤقت', + }, + profiling: { + performanceProfiling: 'تحليل الأداء', + performanceProfilingDescription: + '

تشغيل Umbraco حاليًا في وضع التصحيح. هذا يعني أنه يمكنك استخدام أداة تحليل الأداء المدمجة لتقييم الأداء عند عرض الصفحات.

إذا كنت تريد تفعيل أداة التحليل لعرض صفحة معينة، أضف ببساطة umbDebug=true إلى سلسلة الاستعلام عند طلب الصفحة.

إذا كنت تريد أن يتم تفعيل أداة التحليل بشكل افتراضي لجميع عمليات عرض الصفحات، يمكنك استخدام التبديل أدناه. سيقوم بتعيين ملف تعريف في متصفحك، والذي يقوم بعد ذلك بتفعيل أداة التحليل تلقائيًا. بعبارة أخرى، ستكون أداة التحليل نشطة افتراضيًا فقط في متصفحك - وليس في متصفحات الآخرين.

', + activateByDefault: 'تفعيل أداة التحليل بشكل افتراضي', + reminder: 'تذكير ودي', + reminderDescription: + '

يجب ألا تدع موقع الإنتاج يعمل في وضع التصحيح. يتم إيقاف وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى false في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

', + profilerEnabledDescription: + '

Umbraco حاليًا لا يعمل في وضع التصحيح، لذا لا يمكنك استخدام أداة التحليل المدمجة. هذا هو الوضع الصحيح لموقع الإنتاج.

يتم تشغيل وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى true في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

', + }, + settingsDashboardVideos: { + trainingHeadline: 'ساعات من مقاطع فيديو تدريب Umbraco على بعد نقرة واحدة', + trainingDescription: + '

هل تريد إتقان Umbraco؟ اقض بضع دقائق في تعلم بعض الممارسات الأفضل من خلال مشاهدة واحدة من هذه الفيديوهات حول استخدام Umbraco. وزيارة umbraco.tv لمزيد من مقاطع الفيديو حول Umbraco

', + }, + settingsDashboard: { + documentationHeader: 'التوثيق', + documentationDescription: 'اقرأ المزيد عن العمل مع العناصر في الإعدادات في توثيقنا.', + communityHeader: 'المجتمع', + communityDescription: 'اطرح سؤالاً في منتدى المجتمع أو مجتمع Discord لدينا.', + trainingHeader: 'التدريب', + trainingDescription: 'اكتشف فرص التدريب والتأهيل الرسمية', + supportHeader: 'الدعم', + supportDescription: 'قم بتوسيع فريقك مع مجموعة ماهرة ومتحمسة من خبراء Umbraco.', + videosHeader: 'مقاطع الفيديو', + videosDescription: + 'شاهد مقاطع الفيديو التعليمية المجانية لدينا على قناة YouTube الخاصة بأساسيات Umbraco، لتصبح على اطلاع سريع بـ Umbraco.', + getHelp: 'احصل على المساعدة التي تحتاجها', + getCertified: 'احصل على الشهادة', + goForum: 'اذهب إلى المنتدى', + chatWithCommunity: 'الدردشة مع المجتمع', + watchVideos: 'شاهد مقاطع الفيديو', + }, + startupDashboard: { + fallbackHeadline: 'مرحبًا بك في نظام إدارة المحتوى الودود', + fallbackDescription: + 'شكرًا لاختيارك Umbraco - نعتقد أن هذه قد تكون بداية شيء جميل. بينما قد يبدو الأمر مربكًا في البداية، لقد بذلنا الكثير لجعل منحنى التعلم سلسًا وسريعًا قدر الإمكان.', + }, + welcomeDashboard: { + ourUmbracoHeadline: 'Umbraco الخاص بنا - أكثر المجتمعات صداقة', + ourUmbracoDescription: + 'Umbraco الخاص بنا، الموقع الرسمي للمجتمع، هو وجهتك الشاملة لكل شيء متعلق بـ Umbraco. سواء كنت بحاجة إلى إجابة على سؤال، أو إضافات رائعة، أو دليل حول كيفية القيام بشيء ما في Umbraco، فإن أفضل وأصدق مجتمع في العالم هو مجرد نقرة بعيدًا.', + ourUmbracoButton: 'زيارة Umbraco الخاص بنا', + documentationHeadline: 'التوثيق', + documentationDescription: 'ابحث عن إجابات لجميع أسئلتك حول Umbraco', + communityHeadline: 'المجتمع', + communityDescription: 'احصل على الدعم والإلهام من خبراء Umbraco المتحمسين', + resourcesHeadline: 'الموارد', + resourcesDescription: 'دروس فيديو مجانية لبدء رحلتك مع نظام إدارة المحتوى', + trainingHeadline: 'التدريب', + trainingDescription: 'التدريب الواقعي وشهادات Umbraco الرسمية', + }, + blockEditor: { + headlineCreateBlock: 'اختيار نوع العنصر', + headlineAddSettingsElementType: 'إضافة نوع عنصر الإعدادات', + headlineAddCustomView: 'اختيار العرض', + headlineAddCustomStylesheet: 'اختيار ورقة الأنماط', + headlineAddThumbnail: 'اختيار الصورة المصغرة', + labelcreateNewElementType: 'إنشاء نوع عنصر جديد', + labelCustomStylesheet: 'ورقة أنماط مخصصة', + addCustomStylesheet: 'إضافة ورقة أنماط', + headlineEditorAppearance: 'مظهر الكتلة', + headlineDataModels: 'نماذج البيانات', + headlineCatalogueAppearance: 'مظهر الكتالوج', + labelBackgroundColor: 'لون الخلفية', + labelIconColor: 'لون الأيقونة', + labelContentElementType: 'نموذج المحتوى', + labelLabelTemplate: 'التسمية', + labelCustomView: 'عرض مخصص', + labelCustomViewInfoTitle: 'عرض وصف العرض المخصص', + labelCustomViewDescription: + 'تجاوز كيفية ظهور هذه الكتلة في واجهة المستخدم الخلفية. اختر ملف .html يحتوي على تقديمك.', + labelSettingsElementType: 'نموذج الإعدادات', + labelEditorSize: 'حجم محرر التراكب', + addCustomView: 'إضافة عرض مخصص', + addSettingsElementType: 'إضافة إعدادات', + confirmDeleteBlockMessage: 'هل أنت متأكد أنك تريد حذف المحتوى %0%؟', + confirmDeleteBlockTypeMessage: 'هل أنت متأكد أنك تريد حذف تكوين الكتلة %0%؟', + confirmDeleteBlockTypeNotice: + 'سيظل محتوى هذه الكتلة موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', + confirmDeleteBlockGroupMessage: + 'هل أنت متأكد أنك تريد حذف المجموعة %0% وجميع تكوينات الكتلة الخاصة بها؟', + confirmDeleteBlockGroupNotice: + 'سيظل محتوى هذه الكتل موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', + blockConfigurationOverlayTitle: "تكوين '%0%'", + elementTypeDoesNotExist: 'لا يمكن تحريره لأن نوع العنصر غير موجود.', + thumbnail: 'صورة مصغرة', + addThumbnail: 'إضافة صورة مصغرة', + tabCreateEmpty: 'إنشاء فارغ', + tabClipboard: 'الحافظة', + tabBlockSettings: 'الإعدادات', + headlineAdvanced: 'متقدم', + headlineCustomView: 'عرض مخصص', + forceHideContentEditor: 'إخفاء محرر المحتوى', + forceHideContentEditorHelp: 'إخفاء زر تحرير المحتوى ومحرر المحتوى من تراكب محرر الكتل', + gridInlineEditing: 'تحرير مباشر', + gridInlineEditingHelp: 'يتيح التحرير المباشر لأول خاصية. يمكن تحرير الخصائص الإضافية في التراكب.', + blockHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد تجاهلها؟', + confirmCancelBlockCreationHeadline: 'تجاهل الإنشاء؟', + confirmCancelBlockCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', + elementTypeDoesNotExistHeadline: 'خطأ!', + elementTypeDoesNotExistDescription: 'نوع العنصر لهذه الكتلة لم يعد موجودًا', + addBlock: 'إضافة محتوى', + addThis: 'إضافة %0%', + propertyEditorNotSupported: "الخاصية '%0%' تستخدم المحرر '%1%' والذي لا يدعمه الكتل.", + focusParentBlock: 'تعيين التركيز على الكتلة الحاوية', + areaIdentification: 'التحديد', + areaValidation: 'التحقق', + areaValidationEntriesShort: '%0% يجب أن تكون موجودة على الأقل %2% مرة(s).', + areaValidationEntriesExceed: '%0% يجب أن تكون موجودة بحد أقصى %3% مرة(s).', + areaNumberOfBlocks: 'عدد الكتل', + areaDisallowAllBlocks: 'السماح بأنواع كتل محددة فقط', + areaAllowedBlocks: 'أنواع الكتل المسموح بها', + areaAllowedBlocksHelp: + 'حدد أنواع الكتل المسموح بها في هذه المنطقة، واختياريًا عدد كل نوع من الأنواع التي يجب أن تكون موجودة.', + confirmDeleteBlockAreaMessage: 'هل أنت متأكد أنك تريد حذف هذه المنطقة؟', + confirmDeleteBlockAreaNotice: 'أي كتل تم إنشاؤها حاليًا داخل هذه المنطقة سيتم حذفها.', + layoutOptions: 'خيارات التخطيط', + structuralOptions: 'هيكلية', + sizeOptions: 'خيارات الحجم', + sizeOptionsHelp: 'حدد خيارًا أو أكثر من خيارات الحجم، هذا يمكن أن يتيح تغيير حجم الكتلة', + allowedBlockColumns: 'امتدادات الأعمدة المتاحة', + allowedBlockColumnsHelp: + 'حدد عدد الأعمدة المختلفة التي يُسمح لهذه الكتلة بالامتداد عبرها. هذا لا يمنع الكتل من وضعها في مناطق ذات امتداد أعمدة أصغر.', + allowedBlockRows: 'امتدادات الصفوف المتاحة', + allowedBlockRowsHelp: 'حدد نطاق الصفوف التخطيطية التي يُسمح لهذه الكتلة بالامتداد عبرها.', + allowBlockInRoot: 'السماح في الجذر', + allowBlockInRootHelp: 'اجعل هذه الكتلة متاحة في جذر التخطيط.', + allowBlockInAreas: 'السماح في المناطق', + allowBlockInAreasHelp: + 'اجعل هذه الكتلة متاحة افتراضيًا ضمن مناطق كتل أخرى (ما لم يتم تعيين أذونات صريحة لهذه المناطق).', + areaAllowedBlocksEmpty: + 'افتراضيًا، جميع أنواع الكتل مسموح بها في منطقة، استخدم هذا الخيار للسماح بأنواع محددة فقط.', + areas: 'المناطق', + areasLayoutColumns: 'أعمدة الشبكة للمناطق', + areasLayoutColumnsHelp: + 'حدد عدد الأعمدة المتاحة للمناطق. إذا لم يتم تحديدها، سيتم استخدام عدد الأعمدة المحدد للتخطيط الكامل.', + areasConfigurations: 'المناطق', + areasConfigurationsHelp: + 'لتمكين تداخل الكتل داخل هذه الكتلة، حدد منطقة واحدة أو أكثر. تتبع المناطق التخطيط المحدد من خلال تكوين عمود الشبكة الخاص بها. يمكن تعديل "امتداد العمود" و "امتداد الصف" لكل منطقة باستخدام مربع مقبض التدرج في الزاوية السفلى اليمنى من المنطقة المحددة.', + invalidDropPosition: '%0% غير مسموح به في هذا الموضع.', + defaultLayoutStylesheet: 'ورقة أنماط التخطيط الافتراضية', + confirmPasteDisallowedNestedBlockHeadline: 'تم رفض المحتوى غير المسموح به', + confirmPasteDisallowedNestedBlockMessage: + 'احتوى المحتوى الذي تم إدراجه على محتوى غير مسموح به، والذي لم يتم إنشاؤه. هل ترغب في الاحتفاظ ببقية هذا المحتوى على أي حال؟', + areaAliasHelp: + 'عند استخدام GetBlockGridHTML() لعرض شبكة الكتل، سيتم عرض الاسم المستعار في الشيفرة المصدرية كخاصية \'data-area-alias\'. استخدم خاصية الاسم المستعار لاستهداف العنصر للمنطقة. مثال. .umb-block-grid__area[data-area-alias="MyAreaAlias"] { ... }', + scaleHandlerButtonTitle: 'اسحب للتغيير الحجم', + areaCreateLabelTitle: 'تسمية زر الإنشاء', + areaCreateLabelHelp: 'تجاوز نص التسمية لإضافة كتلة جديدة إلى هذه المنطقة، مثال: "إضافة عنصر واجهة المستخدم"', + showSizeOptions: 'عرض خيارات تغيير الحجم', + addBlockType: 'إضافة كتلة', + addBlockGroup: 'إضافة مجموعة', + pickSpecificAllowance: 'اختر مجموعة أو كتلة', + allowanceMinimum: 'تحديد الحد الأدنى المطلوب', + allowanceMaximum: 'تحديد الحد الأقصى المطلوب', + block: 'كتلة', + tabBlock: 'كتلة', + tabBlockTypeSettings: 'الإعدادات', + tabAreas: 'المناطق', + tabAdvanced: 'متقدم', + headlineAllowance: 'الأذونات', + getSampleHeadline: 'تثبيت التكوين التجريبي', + getSampleDescription: + 'سيضيف هذا كتل أساسية ويساعدك على البدء باستخدام محرر شبكة الكتل. ستحصل على كتل للعناوين والنصوص الغنية والصور، بالإضافة إلى تخطيط بعمودين.', + getSampleButton: 'تثبيت', + actionEnterSortMode: 'وضع الترتيب', + actionExitSortMode: 'إنهاء وضع الترتيب', + areaAliasIsNotUnique: 'يجب أن يكون اسم المنطقة هذا فريد مقارنةً بالمناطق الأخرى لهذه الكتلة.', + configureArea: 'تكوين المنطقة', + deleteArea: 'حذف المنطقة', + addColumnSpanOption: 'إضافة خيار امتداد %0% عمود', + }, + contentTemplatesDashboard: { + whatHeadline: 'ما هي المخططات الوثائقية؟', + whatDescription: 'المخططات الوثائقية هي محتوى مُعرّف مسبقًا يمكن تحديده عند إنشاء عقدة محتوى جديدة.', + createHeadline: 'كيف يمكنني إنشاء مخطط وثائقي؟', + createDescription: + '

هناك طريقتان لإنشاء مخطط وثائقي:

  • انقر بزر الماوس الأيمن على عقدة المحتوى واختر "إنشاء مخطط وثائقي" لإنشاء مخطط وثائقي جديد.
  • انقر بزر الماوس الأيمن على شجرة المخططات الوثائقية في قسم الإعدادات واختر نوع الوثيقة الذي تريد إنشاء مخطط وثائقي له.

بمجرد إعطائها اسمًا، يمكن للمحررين البدء في استخدام المخطط الوثائقي كأساس لصفحتهم الجديدة.

', + manageHeadline: 'كيف يمكنني إدارة المخططات الوثائقية؟', + manageDescription: + 'يمكنك تعديل وحذف المخططات الوثائقية من "شجرة المخططات الوثائقية" في قسم الإعدادات. قم بتوسيع نوع الوثيقة الذي يعتمد عليه المخطط الوثائقي وانقر عليه لتعديله أو حذفه.', + }, + preview: { + endLabel: 'نهاية', + endTitle: 'إنهاء وضع المعاينة', + openWebsiteLabel: 'معاينة الموقع', + openWebsiteTitle: 'فتح الموقع في وضع المعاينة', + returnToPreviewHeadline: 'معاينة الموقع؟', + returnToPreviewDescription: + 'لقد انتهيت من وضع المعاينة، هل ترغب في تمكينه مرة أخرى لعرض أحدث إصدار محفوظ من موقعك؟', + returnToPreviewAcceptButton: 'معاينة أحدث إصدار', + returnToPreviewDeclineButton: 'عرض الإصدار المنشور', + viewPublishedContentHeadline: 'عرض الإصدار المنشور؟', + viewPublishedContentDescription: 'أنت في وضع المعاينة، هل تريد الخروج لعرض الإصدار المنشور لموقعك؟', + viewPublishedContentAcceptButton: 'عرض الإصدار المنشور', + viewPublishedContentDeclineButton: 'البقاء في وضع المعاينة', + }, + permissions: { + FolderCreation: 'إنشاء مجلد', + FileWritingForPackages: 'كتابة الملفات للحزم', + FileWriting: 'كتابة الملفات', + MediaFolderCreation: 'إنشاء مجلد الوسائط', + }, + treeSearch: { + searchResult: 'عنصر تم إرجاعه', + searchResults: 'عناصر تم إرجاعها', + }, + analytics: { + consentForAnalytics: 'الموافقة على بيانات التتبع', + analyticsLevelSavedSuccess: 'تم حفظ مستوى التتبع!', + analyticsDescription: + '\n لتحسين Umbraco وإضافة ميزات جديدة بناءً على معلومات ذات صلة قدر الإمكان،\n
نود جمع معلومات النظام والاستخدام من تثبيتك.\n
سيتم مشاركة البيانات المجمعة بانتظام بالإضافة إلى الدروس المستفادة من هذه المقاييس.\n
نأمل أن تساعدنا في جمع بعض البيانات القيمة.\n
\n
نحن لن نقوم بجمع أي بيانات شخصية مثل المحتوى أو الكود أو معلومات المستخدم، وستكون جميع البيانات مجهولة الهوية تمامًا.\n ', + minimalLevelDescription: 'سوف نرسل فقط معرف موقع مجهول الهوية لإعلامنا بوجود الموقع.', + basicLevelDescription: 'سوف نرسل معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة', + detailedLevelDescription: + '\n سوف نرسل:\n
    \n
  • معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة.
  • \n
  • عدد: العقد الجذرية، العقد المحتوى، الوسائط، أنواع الوثائق، القوالب، اللغات، النطاقات، مجموعات المستخدمين، المستخدمين، الأعضاء، مقدمي تسجيل الدخول الخارجيين إلى المكتب الخلفي، ومحرري الخصائص قيد الاستخدام.
  • \n
  • معلومات النظام: خادم الويب، نظام تشغيل الخادم، إطار عمل الخادم، لغة نظام تشغيل الخادم، ومزود قاعدة البيانات.
  • \n
  • إعدادات التكوين: وضع Modelsbuilder، إذا كان هناك مسار Umbraco مخصص، بيئة ASP، ما إذا كان API التوصيل مفعلًا، ويتيح الوصول العام، وإذا كنت في وضع التصحيح.
  • \n
\n قد نغير ما نرسله على المستوى التفصيلي في المستقبل. إذا كان الأمر كذلك، فسيتم سردها أعلاه.\n
من خلال اختيار "تفصيلي" توافق على جمع المعلومات المجهولة الهوية الحالية والمستقبلية.
\n ', + }, + routing: { + routeNotFoundTitle: 'لم يتم العثور على الصفحة', + routeNotFoundDescription: 'لم يتم العثور على المسار المطلوب. يرجى التحقق من عنوان URL والمحاولة مرة أخرى.', + }, + codeEditor: { + label: 'محرر الأكواد', + languageConfigLabel: 'اللغة', + languageConfigDescription: 'اختر اللغة لتظليل بناء الجملة وIntelliSense.', + heightConfigLabel: 'الارتفاع', + heightConfigDescription: 'حدد ارتفاع محرر الأكواد بالبكسل.', + lineNumbersConfigLabel: 'أرقام الأسطر', + lineNumbersConfigDescription: 'عرض أرقام الأسطر في محرر الأكواد.', + minimapConfigLabel: 'خريطة مصغرة', + minimapConfigDescription: 'عرض خريطة مصغرة في محرر الأكواد.', + wordWrapConfigLabel: 'تغليف الكلمات', + wordWrapConfigDescription: 'تفعيل تغليف الكلمات في محرر الأكواد.', + }, } as UmbLocalizationDictionary; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts index 7cf6c376e0..25bfe74cd0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts @@ -39,7 +39,6 @@ export abstract class UmbElementPropertyDatasetContext< abstract culture: Observable; abstract segment: Observable; - // eslint-disable-next-line no-unused-private-class-members #propertyVariantIdPromise?: Promise; #propertyVariantIdPromiseResolver?: () => void; #propertyVariantIdMap = new UmbBasicState([]); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts index cec662b335..576c677f65 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts @@ -260,5 +260,5 @@ export const manifests: Array = [ culture: 'zh-tw', }, js: () => import('../../../assets/lang/zh-tw.js'), - } + }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts index 8ac5aaaf70..cbf60d85a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts @@ -1,10 +1,10 @@ +import type { ManifestMenu } from '../menu.extension.js'; import type { ManifestSectionSidebarAppBaseMenu, ManifestSectionSidebarAppMenuKind } from './types.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { ManifestMenu } from '../menu.extension.js'; // TODO: Move to separate file: const manifest: UmbExtensionManifestKind = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts index 55c96788cc..542b32b8a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar-context-menu/section-sidebar-context-menu.element.ts @@ -154,7 +154,7 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement { display: flex; align-items: center; } - #action-modal umb-entity-action-list{ + #action-modal umb-entity-action-list { --uui-menu-item-flat-structure: 0; } `, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts index d35f34033f..67b72045bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/utils/object-to-property-value-array.function.ts @@ -1,4 +1,4 @@ -import type { UmbPropertyValueData } from '../../property/types'; +import type { UmbPropertyValueData } from '../../property/types.js'; /** * @function UmbObjectToPropertyValueArray diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts index 5ada737930..a63effc1e6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts @@ -114,17 +114,17 @@ export class UmbPropertyEditorUITinyMceToolbarConfigurationElement override render() { return html`
    - ${repeat( - this._toolbarConfig, - (v) => v.alias, + ${repeat( + this._toolbarConfig, + (v) => v.alias, (v) => html`
  • - - + + ${v.label} - +
  • `, - )} + )}
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index c61e4882c5..812790a01f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -131,8 +131,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { return html``; } From d6c6eddb3cb472e8a8b988d0fecd95f00e7a3af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 13:23:14 +0200 Subject: [PATCH 027/246] parse config to block list elements --- .../block-list-entry.element.ts | 2 ++ .../ref-list-block/ref-list-block.element.ts | 23 ++++--------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 19aa589759..342e96082e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -267,6 +267,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper .label=${this._label} .icon=${this._icon} .unpublished=${!this._exposed} + .config=${this._blockViewProps.config} .content=${this._blockViewProps.content} .settings=${this._blockViewProps.settings}>`; } @@ -276,6 +277,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper .label=${this._label} .icon=${this._icon} .unpublished=${!this._exposed} + .config=${this._blockViewProps.config} .content=${this._blockViewProps.content} .settings=${this._blockViewProps.settings}>`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts index 556d67460f..c748abf59c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts @@ -1,9 +1,9 @@ import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_BLOCK_ENTRY_CONTEXT } from '@umbraco-cms/backoffice/block'; import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; import '@umbraco-cms/backoffice/ufm'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; /** * @element umb-ref-list-block @@ -23,27 +23,12 @@ export class UmbRefListBlockElement extends UmbLitElement { @property({ attribute: false }) content?: UmbBlockDataType; - @property() - _workspaceEditPath?: string; - - constructor() { - super(); - - // UMB_BLOCK_LIST_ENTRY_CONTEXT - this.consumeContext(UMB_BLOCK_ENTRY_CONTEXT, async (context) => { - this.observe( - context.workspaceEditContentPath, - (workspaceEditPath) => { - this._workspaceEditPath = workspaceEditPath; - }, - 'observeWorkspaceEditPath', - ); - }); - } + @property({ attribute: false }) + config?: UmbBlockEditorCustomViewConfiguration; override render() { return html` - + href=${(this.config?.showContentEdit ? this.config?.editContentPath : undefined) ?? ''}> From 49c9528ae9415b88032be26fb1ed1186a7fc8873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 14:07:39 +0200 Subject: [PATCH 028/246] fix rendering --- .../components/ref-list-block/ref-list-block.element.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts index c748abf59c..2e9695f545 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts @@ -5,9 +5,6 @@ import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; import '@umbraco-cms/backoffice/ufm'; import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; -/** - * @element umb-ref-list-block - */ @customElement('umb-ref-list-block') export class UmbRefListBlockElement extends UmbLitElement { // @@ -28,7 +25,7 @@ export class UmbRefListBlockElement extends UmbLitElement { override render() { return html` - href=${(this.config?.showContentEdit ? this.config?.editContentPath : undefined) ?? ''}> + From 1f56d3c2630bb696c4088ec66e53b25b878766bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 16:22:59 +0200 Subject: [PATCH 029/246] small refactor --- .../schedule-modal/document-schedule-modal.element.ts | 6 +++++- .../shared/document-variant-language-picker.element.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts index 724806b140..0d08bd0068 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts @@ -21,6 +21,9 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< @state() _selection: UmbDocumentScheduleModalValue['selection'] = []; + @state() + _isAllSelected?: boolean; + constructor() { super(); this.observe( @@ -29,6 +32,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< this._selection = selection.map((unique) => { return { unique, schedule: {} }; }); + this._isAllSelected = this.#isAllSelected(); }, '_selection', ); @@ -132,7 +136,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< + .checked=${this._isAllSelected}> ${repeat( this._options, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index a372fd445d..01ad48725b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -28,6 +28,7 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { this.selectionManager.selection, (selection) => { this._selection = selection; + this._isAllSelected = this.#isAllSelected(); }, '_selectionManager', ); @@ -39,6 +40,9 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { @state() _selection: Array = []; + @state() + _isAllSelected?: boolean; + /** * A filter function that determines if an item is pickableFilter or not. * @memberof UmbDocumentVariantLanguagePickerElement @@ -96,7 +100,7 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { + .checked=${this._isAllSelected}> ${repeat( this.variantLanguageOptions, (option) => option.unique, From b166b04ed07060aad2f0774bfc691f5245ba4fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 20:17:20 +0200 Subject: [PATCH 030/246] remove temp files --- .../element-data-properties.manager.tempts | 160 ------------------ 1 file changed, 160 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts b/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts deleted file mode 100644 index ed8f8e9b87..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/manager/element-data-properties.manager.tempts +++ /dev/null @@ -1,160 +0,0 @@ -import type { UmbElementPropertyDataOwner } from '../property-dataset-context/element-property-data-owner.interface.js'; -import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { - UmbBasicState, - classEqualMemoization, - createObservablePart, - mergeObservables, -} from '@umbraco-cms/backoffice/observable-api'; -import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; - -type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>; - -export class UmbElementDataPropertyManager< - ContentModel extends { values: Array }, - ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel, -> extends UmbControllerBase { - #dataOwner: UmbElementPropertyDataOwner; - #variantId: UmbVariantId; - - // eslint-disable-next-line no-unused-private-class-members - #propertyVariantIdPromise?: Promise; - #propertyVariantIdPromiseResolver?: () => void; - #propertyVariantIdMap = new UmbBasicState([]); - private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable(); - - constructor( - host: UmbControllerHost, - dataOwner: UmbElementPropertyDataOwner, - variantId?: UmbVariantId, - ) { - // The controller alias, is a very generic name cause we want only one of these for this controller host. - super(host); - this.#dataOwner = dataOwner; - this.#variantId = variantId ?? UmbVariantId.CreateInvariant(); - - this.observe(this.#dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { - this.#propertyVariantIdPromise ??= new Promise((resolve) => { - this.#propertyVariantIdPromiseResolver = resolve as any; - }); - const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); - this.#propertyVariantIdMap.setValue(map); - // Resolve promise, to let the once waiting on this know. - if (this.#propertyVariantIdPromiseResolver) { - this.#propertyVariantIdPromise = undefined; - this.#propertyVariantIdPromiseResolver(); - this.#propertyVariantIdPromiseResolver = undefined; - } - }); - } - - #createPropertyVariantId(property: UmbPropertyTypeModel) { - return UmbVariantId.Create({ - culture: property.variesByCulture ? this.#variantId.culture : null, - segment: property.variesBySegment ? this.#variantId.segment : null, - }); - } - - #propertiesObservable?: Observable>; - // Should it be possible to get the properties as a list of property aliases? - get properties(): Observable> { - if (!this.#propertiesObservable) { - this.#propertiesObservable = mergeObservables( - [this._propertyVariantIdMap, this.#dataOwner.values], - this.#mergeVariantIdsAndValues, - ); - } - - return this.#propertiesObservable; - } - - #mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, Array | undefined]) { - const r: Array = []; - if (values) { - for (const prop of props) { - const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v)); - if (f) { - r.push(f); - } - } - } - return r; - } - - async getProperties(): Promise> { - await this.#propertyVariantIdPromise; - return this.#mergeVariantIdsAndValues([this.#propertyVariantIdMap.getValue(), this.#dataOwner.getValues()]); - } - - /** - * @function propertyVariantId - * @param {string} propertyAlias - The property alias to observe the variantId of. - * @returns {Promise | undefined>} - The observable for this properties variantId. - * @description Get an Observable for the variant id of this property. - */ - async propertyVariantId(propertyAlias: string) { - return createObservablePart( - this._propertyVariantIdMap, - (x) => x.find((v) => v.alias === propertyAlias)?.variantId, - classEqualMemoization, - ); - } - - /** - * @function propertyValueByAlias - * @param {string} propertyAlias The alias of the property - * @returns {Promise | undefined>} - An observable of the property value - * @description Get an Observable for the value of this property. - */ - async propertyValueByAlias( - propertyAlias: string, - ): Promise | undefined> { - await this.#dataOwner.isLoaded(); - await this.#propertyVariantIdPromise; - const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); - if (propVariantId) { - return this.#dataOwner.propertyValueByAlias(propertyAlias, propVariantId.variantId); - } - return; - } - - async propertyValueByAliasAndVariantId( - propertyAlias: string, - propertyVariantId: UmbVariantId, - ): Promise | undefined> { - return this.#dataOwner.propertyValueByAlias(propertyAlias, propertyVariantId); - } - - /** - * @function setPropertyValueByVariant - * @param {string} propertyAlias - The alias of the property - * @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self. - * @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for. - * @returns {Promise} - A promise that resolves once the value has been set. - * @description Get the value of this property. - */ - setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise { - return this.#dataOwner.setPropertyValue(propertyAlias, value, propertyVariantId); - } - - /** - * @function setPropertyValue - * @param {string} propertyAlias - The alias for the value to be set - * @param {PromiseLike} value - value can be a promise resolving into the actual value or the raw value it self. - * @returns {Promise} - * @description Set the value of this property. - */ - async setPropertyValue(propertyAlias: string, value: PromiseLike) { - this.#dataOwner.initiatePropertyValueChange(); - await this.#propertyVariantIdPromise; - const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); - if (propVariantId) { - return this.#dataOwner.setPropertyValue(propertyAlias, await value, propVariantId.variantId); - } - this.#dataOwner.finishPropertyValueChange(); - } -} From 5a2b4f663429334c2c3c282bcfeb3c3e575967aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 21:10:50 +0200 Subject: [PATCH 031/246] adapt createThisFor and fix grid inline property --- .../src/assets/lang/da-dk.ts | 3 +- .../src/assets/lang/en-us.ts | 3 +- .../src/assets/lang/en.ts | 3 +- .../block-grid-block-inline.element.ts | 145 ++++++++++++++++-- .../content-type-structure-manager.class.ts | 2 + .../element-property-dataset.context.ts | 9 +- 6 files changed, 145 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index b95bdce162..5e521a3d5b 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -2362,7 +2362,8 @@ export default { allowBlockInAreas: 'Allow in areas', allowBlockInAreasHelp: 'Make this block available by default within the areas of other Blocks (unless explicit permissions are set for these areas).', - createThisFor: 'Opret %0% for %1%', + createThisFor: (name: string, variantName: string) => + variantName ? `Opret ${name} for ${variantName}` : `Create ${name}`, insertBlock: 'Indsæt Block', labelInlineMode: 'Indsæt på linje med tekst', }, diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index ccc472ee6b..4dfd1fd4f6 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -2515,7 +2515,8 @@ export default { configureArea: 'Configure area', deleteArea: 'Delete area', addColumnSpanOption: 'Add spanning %0% columns option', - createThisFor: 'Create %0% for %1%', + createThisFor: (name: string, variantName: string) => + variantName ? `Create ${name} for ${variantName}` : `Create ${name}`, insertBlock: 'Insert Block', labelInlineMode: 'Display inline with text', }, 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 968a0fe484..f187c4216f 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2573,7 +2573,8 @@ export default { configureArea: 'Configure area', deleteArea: 'Delete area', addColumnSpanOption: 'Add spanning %0% columns option', - createThisFor: 'Create %0% for %1%', + createThisFor: (name: string, variantName: string) => + variantName ? `Create ${name} for ${variantName}` : `Create ${name}`, insertBlock: 'Insert Block', labelInlineMode: 'Display inline with text', }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 38dfb7f95e..33dde6ab6c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -17,6 +17,7 @@ import { type UmbApiConstructorArgumentsMethodType, } from '@umbraco-cms/backoffice/extension-api'; import { UmbLanguageItemRepository } from '@umbraco-cms/backoffice/language'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; const apiArgsCreator: UmbApiConstructorArgumentsMethodType = (manifest: unknown) => { return [{ manifest }]; @@ -50,9 +51,6 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { @state() private _exposed?: boolean; - @state() - _isOpen = false; - @state() _inlineProperty?: UmbPropertyTypeModel; @@ -150,18 +148,34 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { }; override render() { - return html` - - - ${this.#renderInside()} - `; + return html` +
+ +
${this.#renderInside()}
+
+ `; + } + + #renderBlockInfo() { + return html` + + + + +
+ +
+
+ `; } #renderInside() { if (this._exposed === false) { - return html` { + this.#propertyVariantIdPromiseResolver = resolve as any; + }); + this.observe( this._dataOwner.readOnlyState.states, (states) => { @@ -76,16 +80,13 @@ export abstract class UmbElementPropertyDatasetContext< // TODO: Refactor this into a separate manager/controller of some sort? [NL] this.observe(this._dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { - this.#propertyVariantIdPromise ??= new Promise((resolve) => { - this.#propertyVariantIdPromiseResolver = resolve as any; - }); const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); this.#propertyVariantIdMap.setValue(map); // Resolve promise, to let the once waiting on this know. if (this.#propertyVariantIdPromiseResolver) { - this.#propertyVariantIdPromise = undefined; this.#propertyVariantIdPromiseResolver(); this.#propertyVariantIdPromiseResolver = undefined; + this.#propertyVariantIdPromise = undefined; } }); } From 6e368faa27ce8e355b9ccc3a1b05b932190d3d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 21:11:16 +0200 Subject: [PATCH 032/246] remove console.log --- .../structure/content-type-structure-manager.class.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index d76e9fa180..09523c31b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -109,8 +109,6 @@ export class UmbContentTypeStructureManager< this.#ownerContentTypeUnique = unique; - console.log('loadType', unique); - const promise = this.#loadType(unique); this.#init = promise; await this.#init; From d38da0eb8097b4c302efa82d7d540b723314da1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 21:26:01 +0200 Subject: [PATCH 033/246] runtime clean up --- .../element-property-dataset.context.ts | 5 +++++ .../documents/workspace/document-workspace.context.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts index e7c8efed58..033f2271d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts @@ -205,4 +205,9 @@ export abstract class UmbElementPropertyDatasetContext< } this._dataOwner.finishPropertyValueChange(); } + + override destroy() { + super.destroy(); + this.#propertyVariantIdMap.destroy(); + } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 4813b6a90e..3b44787443 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -291,6 +291,7 @@ export class UmbDocumentWorkspaceContext override resetState() { super.resetState(); this.#data.clear(); + this.removeUmbControllerByAlias(UmbWorkspaceIsNewRedirectControllerAlias); } async loadLanguages() { From 4feb7e77dec84c6c65b17821aa6a89d4c9e65d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 22:11:04 +0200 Subject: [PATCH 034/246] clean up code --- .../controller/base-extensions-initializer.controller.ts | 1 + .../block-grid-entry/block-grid-entry.element.ts | 8 +++++--- .../content-property-dataset.context.ts | 2 +- .../extensions/property-editor-ui-element.interface.ts | 1 + .../packages/core/property/property/property.element.ts | 1 + 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts index f4e1b9d4fc..48d5fd8f49 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts @@ -201,6 +201,7 @@ export abstract class UmbBaseExtensionsInitializer< if (!this.#extensionRegistry) return; const oldPermittedExtsLength = this.#exposedPermittedExts?.length ?? 0; + this._extensions.forEach((extension) => extension.destroy()); (this._extensions as unknown) = undefined; (this.#permittedExts as unknown) = undefined; this.#exposedPermittedExts = undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 5bd07e2aba..8ca0d13b97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -1,5 +1,5 @@ import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; @@ -400,7 +400,8 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper .unpublished=${!this._exposed} .config=${this._blockViewProps.config} .content=${this._blockViewProps.content} - .settings=${this._blockViewProps.settings}>`; + .settings=${this._blockViewProps.settings} + ${umbDestroyOnDisconnect()}>`; } #renderRefBlock() { @@ -411,7 +412,8 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper .unpublished=${!this._exposed} .config=${this._blockViewProps.config} .content=${this._blockViewProps.content} - .settings=${this._blockViewProps.settings}>`; + .settings=${this._blockViewProps.settings} + ${umbDestroyOnDisconnect()}>`; } #renderBlock() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts index 09a35613ba..3fff502923 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/content-property-dataset.context.ts @@ -51,7 +51,7 @@ export class UmbContentPropertyDatasetContext< if (!variantInfo) return; this.#currentVariant.setValue(variantInfo); }, - '_observeActiveVariant', + null, ); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts index 39f40cde5b..41c3e26888 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts @@ -5,4 +5,5 @@ export interface UmbPropertyEditorUiElement extends HTMLElement { config?: UmbPropertyEditorConfigCollection; mandatory?: boolean; mandatoryMessage?: string; + destroy?: () => void; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts index f54e2dc1e1..0ae7759ad2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts @@ -285,6 +285,7 @@ export class UmbPropertyElement extends UmbLitElement { this.#controlValidator?.destroy(); oldElement?.removeEventListener('change', this._onPropertyEditorChange as any as EventListener); oldElement?.removeEventListener('property-value-change', this._onPropertyEditorChange as any as EventListener); + oldElement?.destroy?.(); this._element = el as ManifestPropertyEditorUi['ELEMENT_TYPE']; From a67ad61e80d139d115bce9be09f4c9277d8bb847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 22:37:51 +0200 Subject: [PATCH 035/246] controller aliases --- .../element-property-dataset.context.ts | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts index 033f2271d6..219f2134ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts @@ -75,20 +75,24 @@ export abstract class UmbElementPropertyDatasetContext< const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId)); this.#readOnly.setValue(isReadOnly); }, - 'umbObserveReadOnlyStates', + null, ); // TODO: Refactor this into a separate manager/controller of some sort? [NL] - this.observe(this._dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { - const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); - this.#propertyVariantIdMap.setValue(map); - // Resolve promise, to let the once waiting on this know. - if (this.#propertyVariantIdPromiseResolver) { - this.#propertyVariantIdPromiseResolver(); - this.#propertyVariantIdPromiseResolver = undefined; - this.#propertyVariantIdPromise = undefined; - } - }); + this.observe( + this._dataOwner.structure.contentTypeProperties, + (props: UmbPropertyTypeModel[]) => { + const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); + this.#propertyVariantIdMap.setValue(map); + // Resolve promise, to let the once waiting on this know. + if (this.#propertyVariantIdPromiseResolver) { + this.#propertyVariantIdPromiseResolver(); + this.#propertyVariantIdPromiseResolver = undefined; + this.#propertyVariantIdPromise = undefined; + } + }, + null, + ); } #createPropertyVariantId(property: UmbPropertyTypeModel) { From df910a808e438a84078043b206ddc05af0428a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 22:58:32 +0200 Subject: [PATCH 036/246] A11Y label for text box property editor input --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + .../structure/content-type-structure-manager.class.ts | 4 ++++ .../extensions/property-editor-ui-element.interface.ts | 1 + .../src/packages/core/property/property/property.element.ts | 6 +++++- 6 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 5e521a3d5b..d7d5b6d9be 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -783,6 +783,7 @@ export default { email: 'E-mail', error: 'Fejl', field: 'Felt', + fieldFor: 'Felt for %0%', findDocument: 'Find', first: 'Første', focalPoint: 'Fokuspunkt', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 4dfd1fd4f6..9067b709d0 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -803,6 +803,7 @@ export default { email: 'Email', error: 'Error', field: 'Field', + fieldFor: 'Field for %0%', findDocument: 'Find', first: 'First', focalPoint: 'Focal point', 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 f187c4216f..7d698cee40 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -805,6 +805,7 @@ export default { email: 'Email', error: 'Error', field: 'Field', + fieldFor: 'Field for %0%', findDocument: 'Find', first: 'First', focalPoint: 'Focal point', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 09523c31b2..3cc892976a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -105,6 +105,9 @@ export class UmbContentTypeStructureManager< * @returns {Promise} - Promise resolved */ public async loadType(unique?: string) { + if (!unique) return; + if (this.#ownerContentTypeUnique === unique) return; + console.log('loadType', unique); this._reset(); this.#ownerContentTypeUnique = unique; @@ -724,6 +727,7 @@ export class UmbContentTypeStructureManager< } private _reset() { + this.#contentTypes.setValue([]); this.#contentTypeObservers.forEach((observer) => observer.destroy()); this.#contentTypeObservers = []; this.#contentTypes.setValue([]); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts index 41c3e26888..483b90bcf8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts @@ -1,6 +1,7 @@ import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; export interface UmbPropertyEditorUiElement extends HTMLElement { + alias?: string; value?: unknown; config?: UmbPropertyEditorConfigCollection; mandatory?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts index 0ae7759ad2..a6a4d719f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts @@ -182,6 +182,9 @@ export class UmbPropertyElement extends UmbLitElement { this.#propertyContext.alias, (alias) => { this._alias = alias; + if (this._element) { + this._element.alias = alias; + } }, null, ); @@ -294,8 +297,9 @@ export class UmbPropertyElement extends UmbLitElement { if (this._element) { this._element.addEventListener('change', this._onPropertyEditorChange as any as EventListener); this._element.addEventListener('property-value-change', this._onPropertyEditorChange as any as EventListener); - // No need to observe mandatory, as we already do so and set it on the _element if present: [NL] + // No need to observe mandatory or alias, as we already do so and set it on the _element if present: [NL] this._element.mandatory = this._mandatory; + this._element.alias = this._alias; // No need for a controller alias, as the clean is handled via the observer prop: this.#valueObserver = this.observe( From 578609c0503f6625563e883d07638fad0e8bd5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 23:30:56 +0200 Subject: [PATCH 037/246] revert --- .../structure/content-type-structure-manager.class.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 3cc892976a..eb0826f824 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -105,9 +105,8 @@ export class UmbContentTypeStructureManager< * @returns {Promise} - Promise resolved */ public async loadType(unique?: string) { - if (!unique) return; - if (this.#ownerContentTypeUnique === unique) return; - console.log('loadType', unique); + //if (!unique) return; + //if (this.#ownerContentTypeUnique === unique) return; this._reset(); this.#ownerContentTypeUnique = unique; From 8a74976d9bfc088d487c77d5f9da222007311b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 23:31:05 +0200 Subject: [PATCH 038/246] more destroy --- .../core/workspace/entity/entity-workspace-data-manager.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts index 552dd59903..2233e9958e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity/entity-workspace-data-manager.ts @@ -135,6 +135,9 @@ export class UmbEntityWorkspaceDataManager override destroy() { this._persisted.destroy(); this._current.destroy(); + + (this._persisted as any) = undefined; + (this._current as any) = undefined; super.destroy(); } } From 020ad62581cc0d49f630e81efb771549f2a6ee3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 11 Oct 2024 23:52:57 +0200 Subject: [PATCH 039/246] destroy and clean up and more --- .../block/block/workspace/block-element-manager.ts | 1 - .../entity-detail/entity-detail-workspace-base.ts | 3 +-- .../workspace/entity/entity-workspace-data-manager.ts | 4 ++-- .../workspace/document-blueprint-workspace.context.ts | 1 - .../documents/workspace/document-workspace.context.ts | 1 - .../media/media/workspace/media-workspace.context.ts | 1 - .../member/workspace/member/member-workspace.context.ts | 1 - .../text-box/property-editor-ui-text-box.element.ts | 8 ++++++++ 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index 352701d1c0..65af1b54db 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -229,7 +229,6 @@ export class UmbBlockElementManager } override destroy() { - this._persisted.destroy(); - this._current.destroy(); + this._persisted?.destroy(); + this._current?.destroy(); (this._persisted as any) = undefined; (this._current as any) = undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts index c318a9c505..c3b5b3264f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts @@ -470,7 +470,6 @@ export class UmbDocumentBlueprintWorkspaceContext } public override destroy(): void { - this.#data.destroy(); this.structure.destroy(); this.#languageRepository.destroy(); super.destroy(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 3b44787443..8bdec9bd0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -876,7 +876,6 @@ export class UmbDocumentWorkspaceContext } public override destroy(): void { - this.#data.destroy(); this.structure.destroy(); this.#languageRepository.destroy(); super.destroy(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts index c26549700e..e22db20690 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts @@ -466,7 +466,6 @@ export class UmbMediaWorkspaceContext } public override destroy(): void { - this.#data.destroy(); this.structure.destroy(); this.#languageRepository.destroy(); super.destroy(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts index 06a24a07ec..0c54e85606 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts @@ -454,7 +454,6 @@ export class UmbMemberWorkspaceContext } public override destroy(): void { - this.#data.destroy(); super.destroy(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts index 06c2a50778..e0fb795227 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts @@ -34,6 +34,13 @@ export class UmbPropertyEditorUITextBoxElement @property({ type: String }) mandatoryMessage = UMB_VALIDATION_EMPTY_LOCALIZATION_KEY; + /** + * The alias of this field. + * @type {string} + */ + @property({ type: String }) + alias?: string; + #defaultType: UuiInputTypeType = 'text'; @state() @@ -72,6 +79,7 @@ export class UmbPropertyEditorUITextBoxElement override render() { return html` Date: Fri, 11 Oct 2024 23:59:29 +0200 Subject: [PATCH 040/246] remove return and clean up --- .../element-property-dataset.context.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts index 219f2134ba..ac92247246 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/property-dataset-context/element-property-dataset.context.ts @@ -82,6 +82,7 @@ export abstract class UmbElementPropertyDatasetContext< this.observe( this._dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => { + console.log('props', props); const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); this.#propertyVariantIdMap.setValue(map); // Resolve promise, to let the once waiting on this know. @@ -166,11 +167,14 @@ export abstract class UmbElementPropertyDatasetContext< ): Promise | undefined> { await this._dataOwner.isLoaded(); await this.#propertyVariantIdPromise; - const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); - if (propVariantId) { - return this._dataOwner.propertyValueByAlias(propertyAlias, propVariantId.variantId); - } - return; + return mergeObservables( + [await this.propertyVariantId(propertyAlias), this._dataOwner.values], + ([variantId, values]) => { + return variantId + ? (values?.find((x) => x?.alias === propertyAlias && variantId.compare(x))?.value as ReturnType) + : undefined; + }, + ); } // TODO: Refactor: Not used currently, but should investigate if we can implement this, to spare some energy. @@ -203,9 +207,9 @@ export abstract class UmbElementPropertyDatasetContext< async setPropertyValue(propertyAlias: string, value: PromiseLike) { this._dataOwner.initiatePropertyValueChange(); await this.#propertyVariantIdPromise; - const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias); + const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias)?.variantId; if (propVariantId) { - return this._dataOwner.setPropertyValue(propertyAlias, await value, propVariantId.variantId); + await this._dataOwner.setPropertyValue(propertyAlias, await value, propVariantId); } this._dataOwner.finishPropertyValueChange(); } @@ -213,5 +217,6 @@ export abstract class UmbElementPropertyDatasetContext< override destroy() { super.destroy(); this.#propertyVariantIdMap.destroy(); + (this.#propertyVariantIdMap as unknown) = undefined; } } From 1d2e6bce8b57cacc3a8f1096ee2a514bb012f6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Sat, 12 Oct 2024 00:16:17 +0200 Subject: [PATCH 041/246] remove unused import --- .../packages/block/block/workspace/block-workspace.context.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index e16dc3d786..df8349a9c3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -26,7 +26,6 @@ import { UMB_BLOCK_ENTRY_CONTEXT, } from '@umbraco-cms/backoffice/block'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; export type UmbBlockWorkspaceElementManagerNames = 'content' | 'settings'; export class UmbBlockWorkspaceContext From 8e39004c59dd7039d3bfbacb555944746d771a80 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 14 Oct 2024 07:44:19 +0100 Subject: [PATCH 042/246] Chore: Lee's code sweep (during Hacktoberfest '24) (#2450) * Removed my outdated TODO comments * Manifest Picker code tidy-up * Attribute tidy-up Things I'd picked up during development * Corrects Storybook control type for `umb-localize` key * Ran `npm run lint:fix` --- .../manifest-picker-dashboard.ts | 6 +- .../src/apps/preview/preview.context.ts | 1 - .../src/assets/lang/ar.ts | 3160 +++++++++-------- .../src/packages/core/collection/types.ts | 2 - .../packages/core/localization/manifests.ts | 2 +- .../stories/localize.element.stories.ts | 2 +- .../section-sidebar-menu.element.ts | 2 +- .../section-sidebar-context-menu.element.ts | 2 +- .../document-type-workspace-editor.element.ts | 2 +- ...t-type-workspace-view-templates.element.ts | 9 +- .../media-type-workspace-editor.element.ts | 2 +- .../image-cropper-focus-setter.element.ts | 1 - .../member-type-workspace-editor.element.ts | 2 +- .../input-content-picker-source.element.ts | 2 +- .../input-template/input-template.element.ts | 16 +- ...-tiny-mce-toolbar-configuration.element.ts | 14 +- .../grid/user-grid-collection-view.element.ts | 3 +- 17 files changed, 1657 insertions(+), 1571 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/examples/manifest-picker/manifest-picker-dashboard.ts b/src/Umbraco.Web.UI.Client/examples/manifest-picker/manifest-picker-dashboard.ts index 988ad6197a..43be6cfdd4 100644 --- a/src/Umbraco.Web.UI.Client/examples/manifest-picker/manifest-picker-dashboard.ts +++ b/src/Umbraco.Web.UI.Client/examples/manifest-picker/manifest-picker-dashboard.ts @@ -1,11 +1,13 @@ import { css, html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbInputManifestElement } from '@umbraco-cms/backoffice/components'; +import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; +import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; +// eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name @customElement('example-manifest-picker-dashboard') +// eslint-disable-next-line local-rules/enforce-element-suffix-on-element-class-name, local-rules/umb-class-prefix export class ExampleManifestPickerDashboard extends UmbLitElement { #options: Array `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts index 5ada737930..a63effc1e6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts @@ -114,17 +114,17 @@ export class UmbPropertyEditorUITinyMceToolbarConfigurationElement override render() { return html`
    - ${repeat( - this._toolbarConfig, - (v) => v.alias, + ${repeat( + this._toolbarConfig, + (v) => v.alias, (v) => html`
  • - - + + ${v.label} - +
  • `, - )} + )}
`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index c61e4882c5..812790a01f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -131,8 +131,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { return html``; } From 3015c3813fde2fe4fa0a227ead7d08180c7aac2f Mon Sep 17 00:00:00 2001 From: Allen Smith Date: Sun, 13 Oct 2024 12:38:51 -0400 Subject: [PATCH 043/246] Update instruction text for Collection elements. --- .../property-editors/collection/manifests.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts index aea55c6149..ae597d3610 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/manifests.ts @@ -26,7 +26,7 @@ const propertyEditorUiManifest: ManifestPropertyEditorUi = { { alias: 'orderBy', label: 'Order By', - description: 'The default sort order for the list.', + description: 'The default sort order for the Collection.', propertyEditorUiAlias: 'Umb.PropertyEditorUi.Collection.OrderBy', }, { @@ -44,25 +44,25 @@ const propertyEditorUiManifest: ManifestPropertyEditorUi = { { alias: 'bulkActionPermissions', label: 'Bulk Action Permissions', - description: 'The bulk actions that are allowed from the list view.', + description: 'The bulk actions that are allowed on items in the Collection view.', propertyEditorUiAlias: 'Umb.PropertyEditorUi.Collection.BulkActionPermissions', }, { alias: 'icon', - label: 'Content app icon', - description: 'The icon of the listview content app.', + label: 'Workspace View icon', + description: 'The icon for the Collection\'s Workspace View.', propertyEditorUiAlias: 'Umb.PropertyEditorUi.IconPicker', }, { alias: 'tabName', - label: 'Content app name', - description: 'The name of the listview content app (default if empty: Child Items).', + label: 'Workspace View name', + description: 'The name of the Collection\'s Workspace View (default if empty: Child Items).', propertyEditorUiAlias: 'Umb.PropertyEditorUi.TextBox', }, { alias: 'showContentFirst', - label: 'Show Content App First', - description: 'Enable this to show the content app by default instead of the list view app.', + label: 'Show Content Workspace View First', + description: 'Enable this to show the Content Workspace View by default instead of the Collection\'s.', propertyEditorUiAlias: 'Umb.PropertyEditorUi.Toggle', }, ], From bc2d2916fd8feaf73d5ae45e605b212fc031261b Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 14 Oct 2024 09:40:41 +0200 Subject: [PATCH 044/246] build(deps): update @umbraco-ui/uui to 1.11.0 --- src/Umbraco.Web.UI.Client/package-lock.json | 952 ++++++++++---------- src/Umbraco.Web.UI.Client/package.json | 4 +- 2 files changed, 478 insertions(+), 478 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 9ce0248a19..4ea81365db 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -30,8 +30,8 @@ "@types/diff": "^5.2.1", "@types/dompurify": "^3.0.5", "@types/uuid": "^10.0.0", - "@umbraco-ui/uui": "^v1.10.1", - "@umbraco-ui/uui-css": "^v1.10.0", + "@umbraco-ui/uui": "^1.11.0", + "@umbraco-ui/uui-css": "^1.11.0", "base64-js": "^1.5.1", "diff": "^5.2.0", "dompurify": "^3.1.6", @@ -4091,814 +4091,814 @@ "link": true }, "node_modules/@umbraco-ui/uui": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui/-/uui-1.10.1.tgz", - "integrity": "sha512-1PNb/0W8+Q9aLx34px3L7zdCdmFkWSHbdxH6t98nQdftjps/LdCNFd4psT+Uow6VrNcMTsk2QwvRrS2QKyk/fQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui/-/uui-1.11.0.tgz", + "integrity": "sha512-1mX7adcpAZRswPA1p64kqE83Rg5cbZsYM/b/OyUcObaL2cIuBCVvjjuUjgkL2el993GptIzl05XVocdj1dDCeQ==", "dependencies": { - "@umbraco-ui/uui-action-bar": "1.10.0", - "@umbraco-ui/uui-avatar": "1.10.0", - "@umbraco-ui/uui-avatar-group": "1.10.0", - "@umbraco-ui/uui-badge": "1.10.0", - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-boolean-input": "1.10.0", - "@umbraco-ui/uui-box": "1.10.0", - "@umbraco-ui/uui-breadcrumbs": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-button-group": "1.10.0", - "@umbraco-ui/uui-button-inline-create": "1.10.0", - "@umbraco-ui/uui-card": "1.10.0", - "@umbraco-ui/uui-card-block-type": "1.10.0", - "@umbraco-ui/uui-card-content-node": "1.10.0", - "@umbraco-ui/uui-card-media": "1.10.0", - "@umbraco-ui/uui-card-user": "1.10.0", - "@umbraco-ui/uui-caret": "1.10.0", - "@umbraco-ui/uui-checkbox": "1.10.0", - "@umbraco-ui/uui-color-area": "1.10.0", - "@umbraco-ui/uui-color-picker": "1.10.0", - "@umbraco-ui/uui-color-slider": "1.10.0", - "@umbraco-ui/uui-color-swatch": "1.10.0", - "@umbraco-ui/uui-color-swatches": "1.10.0", - "@umbraco-ui/uui-combobox": "1.10.0", - "@umbraco-ui/uui-combobox-list": "1.10.0", - "@umbraco-ui/uui-css": "1.10.0", - "@umbraco-ui/uui-dialog": "1.10.0", - "@umbraco-ui/uui-dialog-layout": "1.10.0", - "@umbraco-ui/uui-file-dropzone": "1.10.1", - "@umbraco-ui/uui-file-preview": "1.10.0", - "@umbraco-ui/uui-form": "1.10.0", - "@umbraco-ui/uui-form-layout-item": "1.10.0", - "@umbraco-ui/uui-form-validation-message": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0", - "@umbraco-ui/uui-icon-registry": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0", - "@umbraco-ui/uui-input": "1.10.0", - "@umbraco-ui/uui-input-file": "1.10.1", - "@umbraco-ui/uui-input-lock": "1.10.0", - "@umbraco-ui/uui-input-password": "1.10.0", - "@umbraco-ui/uui-keyboard-shortcut": "1.10.0", - "@umbraco-ui/uui-label": "1.10.0", - "@umbraco-ui/uui-loader": "1.10.0", - "@umbraco-ui/uui-loader-bar": "1.10.0", - "@umbraco-ui/uui-loader-circle": "1.10.0", - "@umbraco-ui/uui-menu-item": "1.10.0", - "@umbraco-ui/uui-modal": "1.10.0", - "@umbraco-ui/uui-pagination": "1.10.0", - "@umbraco-ui/uui-popover": "1.10.0", - "@umbraco-ui/uui-popover-container": "1.10.0", - "@umbraco-ui/uui-progress-bar": "1.10.0", - "@umbraco-ui/uui-radio": "1.10.0", - "@umbraco-ui/uui-range-slider": "1.10.0", - "@umbraco-ui/uui-ref": "1.10.0", - "@umbraco-ui/uui-ref-list": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0", - "@umbraco-ui/uui-ref-node-data-type": "1.10.0", - "@umbraco-ui/uui-ref-node-document-type": "1.10.0", - "@umbraco-ui/uui-ref-node-form": "1.10.0", - "@umbraco-ui/uui-ref-node-member": "1.10.0", - "@umbraco-ui/uui-ref-node-package": "1.10.0", - "@umbraco-ui/uui-ref-node-user": "1.10.0", - "@umbraco-ui/uui-scroll-container": "1.10.0", - "@umbraco-ui/uui-select": "1.10.0", - "@umbraco-ui/uui-slider": "1.10.1", - "@umbraco-ui/uui-symbol-expand": "1.10.0", - "@umbraco-ui/uui-symbol-file": "1.10.0", - "@umbraco-ui/uui-symbol-file-dropzone": "1.10.0", - "@umbraco-ui/uui-symbol-file-thumbnail": "1.10.0", - "@umbraco-ui/uui-symbol-folder": "1.10.0", - "@umbraco-ui/uui-symbol-lock": "1.10.0", - "@umbraco-ui/uui-symbol-more": "1.10.0", - "@umbraco-ui/uui-symbol-sort": "1.10.0", - "@umbraco-ui/uui-table": "1.10.0", - "@umbraco-ui/uui-tabs": "1.10.0", - "@umbraco-ui/uui-tag": "1.10.0", - "@umbraco-ui/uui-textarea": "1.10.0", - "@umbraco-ui/uui-toast-notification": "1.10.0", - "@umbraco-ui/uui-toast-notification-container": "1.10.0", - "@umbraco-ui/uui-toast-notification-layout": "1.10.0", - "@umbraco-ui/uui-toggle": "1.10.0", - "@umbraco-ui/uui-visually-hidden": "1.10.0" + "@umbraco-ui/uui-action-bar": "1.11.0", + "@umbraco-ui/uui-avatar": "1.11.0", + "@umbraco-ui/uui-avatar-group": "1.11.0", + "@umbraco-ui/uui-badge": "1.11.0", + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-boolean-input": "1.11.0", + "@umbraco-ui/uui-box": "1.11.0", + "@umbraco-ui/uui-breadcrumbs": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-button-group": "1.11.0", + "@umbraco-ui/uui-button-inline-create": "1.11.0", + "@umbraco-ui/uui-card": "1.11.0", + "@umbraco-ui/uui-card-block-type": "1.11.0", + "@umbraco-ui/uui-card-content-node": "1.11.0", + "@umbraco-ui/uui-card-media": "1.11.0", + "@umbraco-ui/uui-card-user": "1.11.0", + "@umbraco-ui/uui-caret": "1.11.0", + "@umbraco-ui/uui-checkbox": "1.11.0", + "@umbraco-ui/uui-color-area": "1.11.0", + "@umbraco-ui/uui-color-picker": "1.11.0", + "@umbraco-ui/uui-color-slider": "1.11.0", + "@umbraco-ui/uui-color-swatch": "1.11.0", + "@umbraco-ui/uui-color-swatches": "1.11.0", + "@umbraco-ui/uui-combobox": "1.11.0", + "@umbraco-ui/uui-combobox-list": "1.11.0", + "@umbraco-ui/uui-css": "1.11.0", + "@umbraco-ui/uui-dialog": "1.11.0", + "@umbraco-ui/uui-dialog-layout": "1.11.0", + "@umbraco-ui/uui-file-dropzone": "1.11.0", + "@umbraco-ui/uui-file-preview": "1.11.0", + "@umbraco-ui/uui-form": "1.11.0", + "@umbraco-ui/uui-form-layout-item": "1.11.0", + "@umbraco-ui/uui-form-validation-message": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0", + "@umbraco-ui/uui-icon-registry": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0", + "@umbraco-ui/uui-input": "1.11.0", + "@umbraco-ui/uui-input-file": "1.11.0", + "@umbraco-ui/uui-input-lock": "1.11.0", + "@umbraco-ui/uui-input-password": "1.11.0", + "@umbraco-ui/uui-keyboard-shortcut": "1.11.0", + "@umbraco-ui/uui-label": "1.11.0", + "@umbraco-ui/uui-loader": "1.11.0", + "@umbraco-ui/uui-loader-bar": "1.11.0", + "@umbraco-ui/uui-loader-circle": "1.11.0", + "@umbraco-ui/uui-menu-item": "1.11.0", + "@umbraco-ui/uui-modal": "1.11.0", + "@umbraco-ui/uui-pagination": "1.11.0", + "@umbraco-ui/uui-popover": "1.11.0", + "@umbraco-ui/uui-popover-container": "1.11.0", + "@umbraco-ui/uui-progress-bar": "1.11.0", + "@umbraco-ui/uui-radio": "1.11.0", + "@umbraco-ui/uui-range-slider": "1.11.0", + "@umbraco-ui/uui-ref": "1.11.0", + "@umbraco-ui/uui-ref-list": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0", + "@umbraco-ui/uui-ref-node-data-type": "1.11.0", + "@umbraco-ui/uui-ref-node-document-type": "1.11.0", + "@umbraco-ui/uui-ref-node-form": "1.11.0", + "@umbraco-ui/uui-ref-node-member": "1.11.0", + "@umbraco-ui/uui-ref-node-package": "1.11.0", + "@umbraco-ui/uui-ref-node-user": "1.11.0", + "@umbraco-ui/uui-scroll-container": "1.11.0", + "@umbraco-ui/uui-select": "1.11.0", + "@umbraco-ui/uui-slider": "1.11.0", + "@umbraco-ui/uui-symbol-expand": "1.11.0", + "@umbraco-ui/uui-symbol-file": "1.11.0", + "@umbraco-ui/uui-symbol-file-dropzone": "1.11.0", + "@umbraco-ui/uui-symbol-file-thumbnail": "1.11.0", + "@umbraco-ui/uui-symbol-folder": "1.11.0", + "@umbraco-ui/uui-symbol-lock": "1.11.0", + "@umbraco-ui/uui-symbol-more": "1.11.0", + "@umbraco-ui/uui-symbol-sort": "1.11.0", + "@umbraco-ui/uui-table": "1.11.0", + "@umbraco-ui/uui-tabs": "1.11.0", + "@umbraco-ui/uui-tag": "1.11.0", + "@umbraco-ui/uui-textarea": "1.11.0", + "@umbraco-ui/uui-toast-notification": "1.11.0", + "@umbraco-ui/uui-toast-notification-container": "1.11.0", + "@umbraco-ui/uui-toast-notification-layout": "1.11.0", + "@umbraco-ui/uui-toggle": "1.11.0", + "@umbraco-ui/uui-visually-hidden": "1.11.0" } }, "node_modules/@umbraco-ui/uui-action-bar": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-action-bar/-/uui-action-bar-1.10.0.tgz", - "integrity": "sha512-f4nQx/s4XRtnQA3p/Q+qOhMi5zdK2ZUz7rh0qAT9Qi+Y24uLwnMabLWlnMRqyDe5z5/DTMoYDKaKhRWTjVFjzw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-action-bar/-/uui-action-bar-1.11.0.tgz", + "integrity": "sha512-lhWw7CiLL2FIXVOWgmAt8yeb625HYWXceMQMEwhlic4bp/jpVmrbYGuKl4SyubR4ws6ein4Uzzy1EWfT5K+kFQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button-group": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button-group": "1.11.0" } }, "node_modules/@umbraco-ui/uui-avatar": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar/-/uui-avatar-1.10.0.tgz", - "integrity": "sha512-JwCoFF/lLkLwRWYRYDoi8w7qHp3bFZQvCu9unQ8QQg/XZVULbiDGwZnSJoMPRdNo6fpN/hx8gDszYDn1tMkCaw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar/-/uui-avatar-1.11.0.tgz", + "integrity": "sha512-ixM8Kx9rE15iWYJgk28mEGeNvVDag/I8mZH/lceuq5Mm0EhUbG6gJGPkUSkDSNTnDRijkjwlF4oeCO+8nA+DRw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-avatar-group": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar-group/-/uui-avatar-group-1.10.0.tgz", - "integrity": "sha512-JMx0cBIsKfhSSf/I0rBNw3jxjKOMw3UJEDL0YTOEBUhtsVIXf7LSQlJ8977vzJuO7a3PjlhWx8F7lhukRzL3aw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-avatar-group/-/uui-avatar-group-1.11.0.tgz", + "integrity": "sha512-/edFijQFzOsNMBbhg8eu0imhDnLE4MSoC30o4dQ4bI3XCtGLfJh1BiOgA+TLUU1vH7D0NIvidzH49+OOIUrvMg==", "dependencies": { - "@umbraco-ui/uui-avatar": "1.10.0", - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-avatar": "1.11.0", + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-badge": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-badge/-/uui-badge-1.10.0.tgz", - "integrity": "sha512-x+UsAQknE3kT7yxAhzS38ILqvDzKdEmYxlYES4dqR5Cj/Vc4iMZTY4pRd1UJEBsC5G/tLlquDGbXG9IZCgCk/w==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-badge/-/uui-badge-1.11.0.tgz", + "integrity": "sha512-7VMZzUZ+CYaFhsCe8XS8VgadBhXZtJh0ilZ695YG9Q9IAbAVyeART59VwRzO/1kS0hfCj10DPEKp8IPMbePWEA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-base": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-base/-/uui-base-1.10.0.tgz", - "integrity": "sha512-0t6BpQmXPgSdjDhb3rQEYcJJtkE50w5rZppsOFXyossaBxfijfTK9JRVc95JRzpLn/a5iQyhuxdUx9r85t71HA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-base/-/uui-base-1.11.0.tgz", + "integrity": "sha512-w7HQDNtEt0qnu+psrwxvrdNxUT08qZ1fYygqH9yeKFyE5GMDvYlL1TWU696Lo72LTbTdSMm/ka9b2QBJv1ZJxA==", "peerDependencies": { "lit": ">=2.8.0" } }, "node_modules/@umbraco-ui/uui-boolean-input": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-boolean-input/-/uui-boolean-input-1.10.0.tgz", - "integrity": "sha512-Xe+B1E+RJCHmSK3aE/ZHVjZwJkijNOh4Un+x42oZX2XQqTz57aafBVY5HSrY7/N8n0xvSY1HCc6sG9wJyXXfMQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-boolean-input/-/uui-boolean-input-1.11.0.tgz", + "integrity": "sha512-3r/lMYSrFzrw6EclCRjJADtf+1yAYPcz5QRQ4yD7WxLD/Kb338HRgQ50pMG5Jwq28cdDha4n7aNx7mGInrHD3g==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-box": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-box/-/uui-box-1.10.0.tgz", - "integrity": "sha512-BF/AUdGTjRxf4OqdVapMkKNkRLbnHTvuYMEhXDxhHT19prB8ZQQLzjDiX1WW9+q8owq3LPVMxoRjT/+AATpsEA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-box/-/uui-box-1.11.0.tgz", + "integrity": "sha512-gYiERouKMpFy/n/6LDh9ckzWpUa2vBmCsWS41Gskct3WZNSVdApZ3g2yvE9ZoJoJB2Q26JfbKShuw0BaJkEFxg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-css": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-css": "1.11.0" } }, "node_modules/@umbraco-ui/uui-breadcrumbs": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-breadcrumbs/-/uui-breadcrumbs-1.10.0.tgz", - "integrity": "sha512-yXzTPi/CTb48QQjgFhFUgO5yM2fe/f7gOiPcXKUelLFbCnWV+HpvO+5QdE9fklJd9rTLb7OuxBVsTU96j90fPA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-breadcrumbs/-/uui-breadcrumbs-1.11.0.tgz", + "integrity": "sha512-wRTtuZAKb0z2Mi3P3wb1CcIO1ExnnFD8vCsHxiTEAjb2e2VzEaEwnnugHnr8chxlOKiTPyX8NtsBXDLTnL/TRA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-button": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button/-/uui-button-1.10.0.tgz", - "integrity": "sha512-zCTVTPMkBG6zQpSzHALOjSlsQu4e1SZCciZoC2bD6aZ6nQbx1C9z8mgIGsNt8lGQqzU5GnF1nVGwIfFn6MEq7Q==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button/-/uui-button-1.11.0.tgz", + "integrity": "sha512-/9B8Rsar9OE9NP84fXBzu5HkEIvXuEtmoaa37QQq9STgLyqrqRMxj6Mt47k69tQgh79HDNu+nwc8A5Gv+h+HHA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0" } }, "node_modules/@umbraco-ui/uui-button-group": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-group/-/uui-button-group-1.10.0.tgz", - "integrity": "sha512-8Fmrs920fExYhvAvm7LtKfwNqwE4bAjqTeNYUoisthbKcme2//po1w4II6RLYGLfq39A6mcEpn9IptjIsPF67g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-group/-/uui-button-group-1.11.0.tgz", + "integrity": "sha512-TW2OioMnjyTCjJA6lJhoX80SyeEb/R2BK6Py82/ZCifnVQ2QFWZ6PtIcnqGT+b0x95xTvzc19f+z4N841wYc8g==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-button-inline-create": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-inline-create/-/uui-button-inline-create-1.10.0.tgz", - "integrity": "sha512-MBQLGhBZJzhUxzrFvbAtBZkK5zlZkS1nR1vBTQEqunORjbooo6JEeTBrlPRk7HDPJpWWsqB6uIe0m2UQ8rBAPA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-button-inline-create/-/uui-button-inline-create-1.11.0.tgz", + "integrity": "sha512-hoKR3sj5V4kzJ9qR0xe5q6giz41QmcPVQRP+qd90BjpxefezgnN2fud+RC59ZbhssAmep031b1pONRZyFr+6ow==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-card": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card/-/uui-card-1.10.0.tgz", - "integrity": "sha512-ozWuLFJanivYDybnJgvPomPPwhCxPHg2NatpNGxLnDnn0VCJVwQQ4vvejrjdHTGknjITmFaGweZbJG3a4q+G1g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card/-/uui-card-1.11.0.tgz", + "integrity": "sha512-MIesvjoBVgSNo+2ManDIpLtWXwsO3emhsloQH+nMoyU/ryy/HZMe/p4HRx/leZmM17HG3KXm2j8GpLHie8bU+w==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-card-block-type": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-block-type/-/uui-card-block-type-1.10.0.tgz", - "integrity": "sha512-9BMH9Z5jS75++onPuGIODcsHFS+bCuEKjgTOqmCDZfU7BIMLMJH/+OW2Uzwqoh+4If41Yumm2TiOSwxo6KOOdw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-block-type/-/uui-card-block-type-1.11.0.tgz", + "integrity": "sha512-kZeFGwSwjdD+M9HwzJ+1bScFCnS3AV36RzXDc6YklVPh63PKlt+wDmiIDd2I4+jHp8NC1buzUz/2dkmZVYOYrg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-card": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-card": "1.11.0" } }, "node_modules/@umbraco-ui/uui-card-content-node": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-content-node/-/uui-card-content-node-1.10.0.tgz", - "integrity": "sha512-iJQucR2IDC6OQFuCsqHjUlt6ze/X6n0ZQm/nDnSZofVTRRFOJb95T0CA6Ytm4Atuz3K0kkLr4AcKsb10/6Zayw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-content-node/-/uui-card-content-node-1.11.0.tgz", + "integrity": "sha512-iEzCVOpucAoCQnDYaGaq2k38zXUax+09gUypt907h0YPc6vRoTou5N5masvxZYyRYJrtWxv5kFs+MtLynREjGA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-card": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-card": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0" } }, "node_modules/@umbraco-ui/uui-card-media": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-media/-/uui-card-media-1.10.0.tgz", - "integrity": "sha512-zWL+/cnQRVFpvWPUOhHjirW9WxBRpC5tFfdE1SunvKBNkKhygGsPTq+b/Te9dI024ZLyaazej57NkpylGeNSOA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-media/-/uui-card-media-1.11.0.tgz", + "integrity": "sha512-uOdN0iu5OKsOtxhTSE8epuUMo2iXq6FEVqBPQBHAmAFELDFyNf2UBwnBxnrTuU6RJ0jbGuLTqQQM7Gv8vD6Kjg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-card": "1.10.0", - "@umbraco-ui/uui-symbol-file": "1.10.0", - "@umbraco-ui/uui-symbol-folder": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-card": "1.11.0", + "@umbraco-ui/uui-symbol-file": "1.11.0", + "@umbraco-ui/uui-symbol-folder": "1.11.0" } }, "node_modules/@umbraco-ui/uui-card-user": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-user/-/uui-card-user-1.10.0.tgz", - "integrity": "sha512-e6LRpSfgKzbKo2pSKL5Ku9jaB5P6lowiV0/0l/uGHkvXfFfuCUVoMPjQncuCcaMcGW7Q2g5lkXNgOOXtiuyw0A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-card-user/-/uui-card-user-1.11.0.tgz", + "integrity": "sha512-/6No4e+eLqCmivNeCHlLfmChKb6F8asv9pgZdi6mUr44TOc44OGvvuF1vONslf9f4B2eKbRTFmFwGVIfWpjOAw==", "dependencies": { - "@umbraco-ui/uui-avatar": "1.10.0", - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-card": "1.10.0" + "@umbraco-ui/uui-avatar": "1.11.0", + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-card": "1.11.0" } }, "node_modules/@umbraco-ui/uui-caret": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-caret/-/uui-caret-1.10.0.tgz", - "integrity": "sha512-XCsvDV5CKZ5wy1zdjEQ849411B/fCkENRmqCiqnHa1+JFAVgbb1AA1+gjb+lz4EWpE1CfiL556mYjt1ZznwFZA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-caret/-/uui-caret-1.11.0.tgz", + "integrity": "sha512-Lq+zBOMeobRvFPhEps03efcy+NFOm27w5jqwJ/4ad2TbEMLTBLdSose/3ZqPV4nvTPMlWButRIFo3Nrp+4jL/Q==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-checkbox": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-checkbox/-/uui-checkbox-1.10.0.tgz", - "integrity": "sha512-1NPLxyGGJcWuU0tXzw/FpQrwjEfBzrO4yTkss+kRbryi9yrxJgxfOsug+JIHSEfiFjQoSDU/mvoirPxa5xhGIg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-checkbox/-/uui-checkbox-1.11.0.tgz", + "integrity": "sha512-bOfJXJ5LMiGCMD37A3mzYjiGTIvzjREN2AhtqGLbwcrAgj662WVhw0aQobo2+iIwaMUIAvl3kNS8930XDeUe/A==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-boolean-input": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-boolean-input": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0" } }, "node_modules/@umbraco-ui/uui-color-area": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-area/-/uui-color-area-1.10.0.tgz", - "integrity": "sha512-zmJseESe9KmFmJrrI+/l1a2RLOZWuRNp8MTjhuaf7p9HBopOeYyhC4vXgf/6VPa+y5uZyitRM6d/yUQmL7CxsA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-area/-/uui-color-area-1.11.0.tgz", + "integrity": "sha512-R1fWHHk7BPilveIF7vPWECAHz/FPKIdvqllYu9f/oJ3RWm7DJtfcNI+Eb7hwkPR/Uj8ug7SkcL4ZvXOG30Ux4A==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", + "@umbraco-ui/uui-base": "1.11.0", "colord": "^2.9.3" } }, "node_modules/@umbraco-ui/uui-color-picker": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-picker/-/uui-color-picker-1.10.0.tgz", - "integrity": "sha512-MYDaO+pBUTH7lpdjH5RQivqEc4JqFcpTD0qEqyk7iyU5vHJ7HcYLng5fiNuEhavVGhN6f0Ee10bAq7cWx3ZKyA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-picker/-/uui-color-picker-1.11.0.tgz", + "integrity": "sha512-EHU2DXmET3ehRQMwkVtS+nyrfIm8c9cu01GDQR6GFzRNl3G7nUKKdK0LyRQUEm7bSXbWpwctGz6qzB9/MCuxBg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-popover-container": "1.10.0", + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-popover-container": "1.11.0", "colord": "^2.9.3" } }, "node_modules/@umbraco-ui/uui-color-slider": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-slider/-/uui-color-slider-1.10.0.tgz", - "integrity": "sha512-Y6u5G7YVHMVC28rmggFYGSdB3A3MO6wZ2GL1YJjzzO8smRRAjtYkOkkbHYSKgn4Mao9K2BHn4DuZVizhWQe8Aw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-slider/-/uui-color-slider-1.11.0.tgz", + "integrity": "sha512-E2mW4hvARy4C7ETZ4PUCgeUPgSvw4HEPX1CpOWl32vM85R4F/K/RdS6OsSP3GHO/8oBYPjlLfX8betMrf4+3+Q==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-color-swatch": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatch/-/uui-color-swatch-1.10.0.tgz", - "integrity": "sha512-BazYXqGeScvYsHuOZlnT0Yi8xRH1XfQYaHJEpzvSR4tfdUPqM4fGbLdnFNgDrCPaZziIbkuGltpz/lK/JeN9ew==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatch/-/uui-color-swatch-1.11.0.tgz", + "integrity": "sha512-BeCyW9FyVmjE2W8u3k5bPwkRUIVbudK2q9VTKmIcnkwsZz8wv6dDpFoFb92So8YSzMhdiVIRQ14fnphHwMHfWQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0", + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0", "colord": "^2.9.3" } }, "node_modules/@umbraco-ui/uui-color-swatches": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatches/-/uui-color-swatches-1.10.0.tgz", - "integrity": "sha512-q5vcDckApfL730m59ihiAOwvojMg5t/EHAAqzyKrPO2rqUXB1+SYukWAc7pu12V0Yvqvl6in4zqcyNK8uPdT6g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-color-swatches/-/uui-color-swatches-1.11.0.tgz", + "integrity": "sha512-t+BKLHKlnFdSB/AB0vihqMl7EuIUI1M+m7q07E/or+BX7juV2H+sVAwWdYiOlCjpC5wqi1RAKh41tPWyslc/vQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-color-swatch": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-color-swatch": "1.11.0" } }, "node_modules/@umbraco-ui/uui-combobox": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox/-/uui-combobox-1.10.0.tgz", - "integrity": "sha512-Z86/u0PAIUepTL0J7+H1kiJzXFEoHJcaFJQpExFMp6AbCEP11m1Fz17oHipz7uCWQ0DlImrSQcBq+7ed/Y1OLQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox/-/uui-combobox-1.11.0.tgz", + "integrity": "sha512-Z+cfhxoK6/tGdErNc1rvrT9NDjuZPJ/SHAJlm83ziPvbWxTGVgjf75nqNZ3z6VW9EVWWJ0Fstz2VTzo4K0mcRA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-combobox-list": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0", - "@umbraco-ui/uui-popover-container": "1.10.0", - "@umbraco-ui/uui-scroll-container": "1.10.0", - "@umbraco-ui/uui-symbol-expand": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-combobox-list": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0", + "@umbraco-ui/uui-popover-container": "1.11.0", + "@umbraco-ui/uui-scroll-container": "1.11.0", + "@umbraco-ui/uui-symbol-expand": "1.11.0" } }, "node_modules/@umbraco-ui/uui-combobox-list": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox-list/-/uui-combobox-list-1.10.0.tgz", - "integrity": "sha512-5TBt/C6eDyd8TDYVS7oXE0hjDvTqbskjMNBsUTzZwWWGr1G8LtRliEVEc48akSrWSFmNf799OPQhNLWQnJ1UEA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-combobox-list/-/uui-combobox-list-1.11.0.tgz", + "integrity": "sha512-XV59sGG4NYZq6llWC3OqxxpR44Cavwfn+/7ee8kTBPmjWhzvS5XijDCGQxhrLcIK74L6OnqrfLcUgItPQUA3Dg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-css": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-css/-/uui-css-1.10.0.tgz", - "integrity": "sha512-bsUBvFGzPzAMegNpznYIzW1CBgxmN2pXfbsgQLpaDJIE8GIW3Y+AW4RNSZV4Tf0uDWIxVlbvI/NruRGLuoCKhA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-css/-/uui-css-1.11.0.tgz", + "integrity": "sha512-DpYKHmA4/te9gYUTLfLNgp0sotkq9TJQ9XkBzXJerwye+IzZdKhIsCWf/m5S6jf065MPjncEtwBgxDdvvB8DrQ==", "peerDependencies": { "lit": ">=2.8.0" } }, "node_modules/@umbraco-ui/uui-dialog": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog/-/uui-dialog-1.10.0.tgz", - "integrity": "sha512-Pkm+YShZbZWHtZ7j27uvabTt33MiAeLL8b/HkTppSCbcVqZ0F/TvUxNBVy0N0mlgvU8c0Zei8b4TPSDfeNnxEQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog/-/uui-dialog-1.11.0.tgz", + "integrity": "sha512-aEpitRE2an8YGm/s0QDfGW/0ccWlnqgA9DhrosZ7kxTElj7BVMQOGVh/nQKBjf+finOGThjvTCM33eksmgPaOw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-css": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-css": "1.11.0" } }, "node_modules/@umbraco-ui/uui-dialog-layout": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog-layout/-/uui-dialog-layout-1.10.0.tgz", - "integrity": "sha512-Jdk7FFoyhKqwK8n3+T13CuJUsJ0X/gG0e9XKUC9DdcnJsw5WYx4BhyqPyQpw+7uTZ9GMBSMZ4PMzN30KbMNcvg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-dialog-layout/-/uui-dialog-layout-1.11.0.tgz", + "integrity": "sha512-z7ZTDonZ/mEJ6u/WH7De/NzT4IZ+zgqR0mJn4ypsf8T0ixB/r7aDHZG9cTP9hG4gnUag8VNbdashMCroDLSYNA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-file-dropzone": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-dropzone/-/uui-file-dropzone-1.10.1.tgz", - "integrity": "sha512-+Crxkuo6DcoAefHqx5QDsArQBfPlwMqkDfdP2eDSS7MueVmwVAnKRS3oFuO/MwD2Qy8jlcuM0i2bLz+DuZ97FA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-dropzone/-/uui-file-dropzone-1.11.0.tgz", + "integrity": "sha512-oV/SKvKuSze7eTbALCU0sCGmzMe8JgVQrrOPwWpepO/x2VHlWTNQbBQpsFmTOksR89Qx8NlK3Umo84i1RkeF1w==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-symbol-file-dropzone": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-symbol-file-dropzone": "1.11.0" } }, "node_modules/@umbraco-ui/uui-file-preview": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-preview/-/uui-file-preview-1.10.0.tgz", - "integrity": "sha512-1r7BSSF7JHPC3t9YIRCKfchK7jK+43Y9WTHi8lyi2ZpNt3Kju42OQIB9eyFm1+MdJsZi2VkEcBCWTo1wveUasw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-file-preview/-/uui-file-preview-1.11.0.tgz", + "integrity": "sha512-ZgJb3rdlKHo3iu9XZwy+elzhcBfZXb1LzoRIsLuanVHYeq/pbSXFtw8cJYJ3a65dnA6ryvGbY2m5TrWw39slMg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-symbol-file": "1.10.0", - "@umbraco-ui/uui-symbol-file-thumbnail": "1.10.0", - "@umbraco-ui/uui-symbol-folder": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-symbol-file": "1.11.0", + "@umbraco-ui/uui-symbol-file-thumbnail": "1.11.0", + "@umbraco-ui/uui-symbol-folder": "1.11.0" } }, "node_modules/@umbraco-ui/uui-form": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form/-/uui-form-1.10.0.tgz", - "integrity": "sha512-ByJQV+Lr0iNwth4GXxckoeXtnpRQ1Gnqfo2/Bu53EdEpnpfomrzB6su4AIdaswtHPD+RoM6JVGNtlfzPGtcVvQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form/-/uui-form-1.11.0.tgz", + "integrity": "sha512-+RqU/N8FUfbvmNPYCOyjS5e4H86dsT7h4A/2+NT2HmuyFObeXhCFMyp/60Kpfb6X7wJtnw1qa8go3zb8Gv5cpw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-form-layout-item": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-layout-item/-/uui-form-layout-item-1.10.0.tgz", - "integrity": "sha512-VdbEhx84mgrWm8puo6RagY9LsaR+kfGp8yPzuzuFXKvWNtKNucT+OmB8OoU6cWJfNahQ89evYeSicIJKakHivw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-layout-item/-/uui-form-layout-item-1.11.0.tgz", + "integrity": "sha512-o8V+S7mNoTV5mceCaTtY6+dFhzpJAxcR/e+1kN7yq6SfiabVjfW6EBqQYAnVc/hT9WfS3AUgO/8YFdr1CKOTqA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-form-validation-message": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-form-validation-message": "1.11.0" } }, "node_modules/@umbraco-ui/uui-form-validation-message": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-validation-message/-/uui-form-validation-message-1.10.0.tgz", - "integrity": "sha512-TlSvmNAxWmkg5ncKyBrTtMSDvUnGCyn1BxvNfaz8pp4KqGu/sd1a0hBp/80dCa025XH7BJ3d87Kyp9UXLRQi0A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-form-validation-message/-/uui-form-validation-message-1.11.0.tgz", + "integrity": "sha512-VxkPNQNPbMNMX/cPzrkekdGC7QUlyb9aH4feGe1RzD33hRc9FQufoTxS4gjSeX6yemjYu/78nqroBAMzIEmvUg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-icon": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon/-/uui-icon-1.10.0.tgz", - "integrity": "sha512-nsZyJfcF9MpRXahZ2DS/kzPfJzY3Xql5I/xjjFaS8JEIkT81HzOy1D9bo8AoDrL7VzyaspCbDgLM6R1yhNhlMg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon/-/uui-icon-1.11.0.tgz", + "integrity": "sha512-aH7tKlqfkMRU4+T8neSedU+YpHuFEhDe2ckHuqILw3iK1/j56Y0lUeoabkh1y/SWRZwydkkOjIhwDFIv48Ceag==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-icon-registry": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry/-/uui-icon-registry-1.10.0.tgz", - "integrity": "sha512-v/ajwASl4jVSiuGgn4uYetV5NxNghtdZXD7DV0+Lu2u9sV8wIOvk89pWAFsAwDT593/p9/H3p5CoRIzyCmCDIA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry/-/uui-icon-registry-1.11.0.tgz", + "integrity": "sha512-NbNDV35f1rSgKK2xFV/CPAdLPLhAFThilCPGraMY260WNIFwpcbP8n+PQ1dzNSec6xhIEMV4AC4Y5SvK/z54LA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0" } }, "node_modules/@umbraco-ui/uui-icon-registry-essential": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry-essential/-/uui-icon-registry-essential-1.10.0.tgz", - "integrity": "sha512-0MdN0A4Mz8O1bT22JlHPesvbqMVM+RomtcsHh+DhN3l0RxfamlrSZLEWMavRODq/ign0vfhQ0Zo4iS3fjqzaeg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-icon-registry-essential/-/uui-icon-registry-essential-1.11.0.tgz", + "integrity": "sha512-WU5LRcjDFeGlr/Dq540IHLC1mMLgEkMJXjCNOb2d/7jLP3FHDs0T4qJGgzILYfeX7fDjQCnxkWVfaDmGGikSWA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-icon-registry": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-icon-registry": "1.11.0" } }, "node_modules/@umbraco-ui/uui-input": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input/-/uui-input-1.10.0.tgz", - "integrity": "sha512-dnK43VZo7RMOquO8Ih+wurqwlHMmGQ0vdYfc8/DIy3RAeT6+G5ZYJyWmZ3u5jJJ7lBauLJfPVOJAH7BdNPIhmA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input/-/uui-input-1.11.0.tgz", + "integrity": "sha512-DWe25cOCtYvRgqShL/UL4OnTRSbIZgTLp1JSdzLzSFxNm3PO2mAhYZuOMdGCjDkjv0G2lszmaqd7Ix8Xw+51ZA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-input-file": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-file/-/uui-input-file-1.10.1.tgz", - "integrity": "sha512-GbBpemwHGy9hATySF00XrlHrci9PEjbrlxx+vyWPUvayMG1focc0Snpf9Gui9g629LY1g320aPPQ8IHtjFWJ+A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-file/-/uui-input-file-1.11.0.tgz", + "integrity": "sha512-u19lW5F7aiMN/D3wHhqJgqdreKaHJDoZ76A37nys2kItNWHvpoFbRrHkAaaN9RQVrl0rwmx3R6Sbs+IWFuTCJA==", "dependencies": { - "@umbraco-ui/uui-action-bar": "1.10.0", - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-file-dropzone": "1.10.1", - "@umbraco-ui/uui-icon": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0" + "@umbraco-ui/uui-action-bar": "1.11.0", + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-file-dropzone": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0" } }, "node_modules/@umbraco-ui/uui-input-lock": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-lock/-/uui-input-lock-1.10.0.tgz", - "integrity": "sha512-nIY/lT/sN6R0jSTk27h42CqQcFHEI3JZgzlQz9sb0Z8HZ+uybuh5MWLuElWdDh+3V2On+fKKZUuXVcHERsWfww==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-lock/-/uui-input-lock-1.11.0.tgz", + "integrity": "sha512-VCpLcFZ+OOeCubczsQsxrhqj3iPdq7o81YMxckd+BLiqU0O5nDxioSuZf5WeU7zttkTE64a0NYu0fKaRC7hLOA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0", - "@umbraco-ui/uui-input": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0", + "@umbraco-ui/uui-input": "1.11.0" } }, "node_modules/@umbraco-ui/uui-input-password": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-password/-/uui-input-password-1.10.0.tgz", - "integrity": "sha512-uffOb2+O/wTk2RgYZmdFZTJwCwhPm56l9/YGkZ+p9O4QBhTIrwEndfdQjGLCo+qj0/skuG0sMzKyWZTbJTRb+Q==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-input-password/-/uui-input-password-1.11.0.tgz", + "integrity": "sha512-doilXxlrc8v6BUtXUhlrno2aQSzlApUw1B9nnG2TuFOxoJ3iynJV6p6CcwPNlNPEYzPeiHFOaizPeDaZWZYmRg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0", - "@umbraco-ui/uui-input": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0", + "@umbraco-ui/uui-input": "1.11.0" } }, "node_modules/@umbraco-ui/uui-keyboard-shortcut": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-keyboard-shortcut/-/uui-keyboard-shortcut-1.10.0.tgz", - "integrity": "sha512-hr3puURGR8DgHOAOa9vzXKFx+WAxfBbQtcg+xw4PHgCDEDV9wLbvnqBOVdP5DrIp3atLCHW355i8T/Fv8ffPqA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-keyboard-shortcut/-/uui-keyboard-shortcut-1.11.0.tgz", + "integrity": "sha512-wRhfCnjjmZzs2gVoF1gZXNvIooPH8Qytr7UE6ijr6rDWbkDsltjhHocsPpcBAu1LUhqmqmlXDPHOOnc4sraL4A==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-label": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-label/-/uui-label-1.10.0.tgz", - "integrity": "sha512-VD8daFTnNgnTgDG8sFmq6JaMMWLDYsTyR5Jl6twrC09GgD2YOn1lFw7mOYpNpKwJv1i5yngXbaT6QCQ+uU1NFg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-label/-/uui-label-1.11.0.tgz", + "integrity": "sha512-xeVOm9gGyPERnmwjmBNiqsfHFU4ROn6wGIEg6bV/CRdz0sjOKBHMYjdH+hg00kRQjj8oYt52HK4dVos8lDDYZg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-loader": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader/-/uui-loader-1.10.0.tgz", - "integrity": "sha512-VDxYhwkojD52zI2PfFAoPI5m83KeU7AILFqDqjySIr5uqjrHv3DlE6BjbfqQHivIvgRKSNlSukukROJZ+bsPiQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader/-/uui-loader-1.11.0.tgz", + "integrity": "sha512-BoNCOFV+CXwMH/WEwVo5ADj6QXg1tIRPtzVtN3gZGTcDizbqp20171JtkeW3IvOpE6s9Gypn22bv1sUI+ZZOFA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-loader-bar": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-bar/-/uui-loader-bar-1.10.0.tgz", - "integrity": "sha512-66BVb/Y2mkb7jHMeQhHGuAuxZ54n2IOeGZ8yVYIs44+U8tXb792Mq6Tr1zgEIzvvmWdfajAjnglhR9hfmijdoQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-bar/-/uui-loader-bar-1.11.0.tgz", + "integrity": "sha512-WSIGG4Xlb/SuhnMmL0yd5ZaFUUdHR1UnZ6vv9ja5ORug88AnvPTNMY/53u2ilSh6NT0GCPXWFAbVgIZDn5KaFA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-loader-circle": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-circle/-/uui-loader-circle-1.10.0.tgz", - "integrity": "sha512-Beg5+Kt3QpPnC31gYMHI2IkVlk8+EU7fzyXSBq+PIaRhhWF8WO0pjsnsXrY0SxrBfSO4qqcGPaB7VDjD/Q4u6g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-loader-circle/-/uui-loader-circle-1.11.0.tgz", + "integrity": "sha512-78xMkQVPUxSwEbvUIdg7L6lamliVKS+NVh+ZRGB+U3HG5t+kwXlcjgaQ4ebdkB7LgLvqrT41GEbXPsmk8hVKKQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-menu-item": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-menu-item/-/uui-menu-item-1.10.0.tgz", - "integrity": "sha512-DJHBKkp8gWP4x/r0k8NiI8QFQmJscD8iaSKMbRkIBm8cb/Lk7hF/szlo67j1rfoV7iRrGvYhL17p+JaoJ9FyqQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-menu-item/-/uui-menu-item-1.11.0.tgz", + "integrity": "sha512-SMbTptyJdLCh03pSa1MflC0im6c7jaRdjb3p6exQ7cz++TdoLveJyOKAWaJ2TvaAShoaLOdlVHRD88sXcuj2Eg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-loader-bar": "1.10.0", - "@umbraco-ui/uui-symbol-expand": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-loader-bar": "1.11.0", + "@umbraco-ui/uui-symbol-expand": "1.11.0" } }, "node_modules/@umbraco-ui/uui-modal": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-modal/-/uui-modal-1.10.0.tgz", - "integrity": "sha512-Z13sfDV47aDlr7cpsD3YTFpbr1vhFJ/icpSBTKm6oJs4koiG+ZuiVjt//qLqS3eBL8UXgz6rVL5Q+DcWmJOn3Q==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-modal/-/uui-modal-1.11.0.tgz", + "integrity": "sha512-rNq8lhzKj4bk4EMgAIlnHcaQX0W7kQhHWBeJahvLL6jNMmiMGtN/ZtE0efG5tx1r4dixTPbiXXGAl8qMqgTIig==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-pagination": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-pagination/-/uui-pagination-1.10.0.tgz", - "integrity": "sha512-PP0Dsa++77fxv7SqZmRRs8EzKNBQCubPV2t6AEN33fGXjYW83STMJN0BLwZ4za46KbInImAorIbkWA3kEetZQQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-pagination/-/uui-pagination-1.11.0.tgz", + "integrity": "sha512-aQf9MH4BlBbR9r+u4jbknuivhXPrwn65YjLkO3gDDfVfeSSu+ZsrNxReUVnVehF+bP55htcxgwC/lKDJldHVEQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-button-group": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-button-group": "1.11.0" } }, "node_modules/@umbraco-ui/uui-popover": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover/-/uui-popover-1.10.0.tgz", - "integrity": "sha512-gPEVFVeFqa76bGwzkxc8Gjt5EbLKd2WgUeFGIBrP8+ZscbDyP/eG6bXjfUSBweXedPFxmlN/Ng3Dtz+KU2QIGQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover/-/uui-popover-1.11.0.tgz", + "integrity": "sha512-ZHjkuJ1z8P/zLFeBf8LB8+c/JXm6YK5SORVnZfIlF8MZSDLanFlST62uOT7dcop96yihI/zIr7O5vO8OEw44bw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-popover-container": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover-container/-/uui-popover-container-1.10.0.tgz", - "integrity": "sha512-YguOGWH7XfD7tsopKoh5S6UgymufLna/1xxsBt88/FdF/m1xzHHmrgqWy/GnNycXgGgSulJ3fYe1OG2JhIOHRQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-popover-container/-/uui-popover-container-1.11.0.tgz", + "integrity": "sha512-i90xXibf8BfP4Yd5Bp4wOfjnFEWQ2Qmn9vnDOWcxmsM9q7NQFx7m4287jJCMtfz2DUbj0VIFJlA2rffWnnSJzw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-progress-bar": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-progress-bar/-/uui-progress-bar-1.10.0.tgz", - "integrity": "sha512-ymOWS5R8l3xU3NOPCXAb2gsRvHVjgu6zCGyUreDj0Lz1glagkPKM2evttui9ixoVV8CR7SxAj3hK6t+PXp2ubA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-progress-bar/-/uui-progress-bar-1.11.0.tgz", + "integrity": "sha512-ZTRlebLZV19wvNS5TtX+Ku/1cXgAXBR9anYydx/+e2sXQeotwsak74vHqVgNYTzFqD+8EuRlwYJOI4kMer8COw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-radio": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-radio/-/uui-radio-1.10.0.tgz", - "integrity": "sha512-ZvC7wgVB4Odn7n8oYsyXOLeIGhx6Ej/Np67Eqg3l+YSxee+SZzBKIHnqSo6BrgaNDSuSS+gWXS8vREGss1UVjg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-radio/-/uui-radio-1.11.0.tgz", + "integrity": "sha512-s2KhChBWMlpUThSAm7HGPcbCFXJ7vQTTgSw1e+VED/p/xwKhMrcMiwGX1s4fRTXt4tnCm8AcbMSkhfrW4DW8IA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-range-slider": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-range-slider/-/uui-range-slider-1.10.0.tgz", - "integrity": "sha512-suYF7UnErKmWyjnPdua6GwmzUe+FovKMyePKISk17gicoiCfked1ygQi0w7YFPJeo7hScx1MA9sUpvh6TVDrkw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-range-slider/-/uui-range-slider-1.11.0.tgz", + "integrity": "sha512-ReU+Xh8VEH9L+ap4Zwo4+TFWDodoiU5iNkkM0NwbHMz/PLiBE0tVKD5wgppkJKnTRxDxS3MG98C+3DOvXqO2ZQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref/-/uui-ref-1.10.0.tgz", - "integrity": "sha512-dDbpHYQeMQGF/3pudcj0B6y3ATN8/IQqF9fWlbz/L4H9oAxmiiFgujwXpzLqLx2j9IQvw+pbOx2fi7rVpKsMfw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref/-/uui-ref-1.11.0.tgz", + "integrity": "sha512-gAtI3/FgcUmmUPSNY9HMGnlMSby9PrcZ1hJRFmv+b86Ducc+4ljmsro97noTexYG1zttDPMkvYGFqOeE5bAeDQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-list": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-list/-/uui-ref-list-1.10.0.tgz", - "integrity": "sha512-XvDCMM4WTEADKqV/QIqy9gzFe1M6w6XQjX5dVE64Luc2lEjvzKf+/LKcJaoULJsd72roh31MbXNvCO6AdGTqdA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-list/-/uui-ref-list-1.11.0.tgz", + "integrity": "sha512-c0DLRyNs/sRKPqmnjY6QAfuPa8+etQpXK683gJEn5R4zwcJGGPFzRf6BD9nIcecAAnbL+MFd6cgCBZWlDq/BJA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node/-/uui-ref-node-1.10.0.tgz", - "integrity": "sha512-gRu81TImEcJdJ1PKs7glmFXWwP4NkkuvEg0EDXEZoS1ORK7Ms/rLgjecnjruTU2oqxlEiTeSpy3fvw8Ybc+Wyg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node/-/uui-ref-node-1.11.0.tgz", + "integrity": "sha512-/+kpfFBb1su5/7egIAHQfeCm3+VQuMrwt07evovAeAM6YAdZsEcv8l2B0V09uKIcJJn/eJOfVVWlqWqi+qQazg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0", - "@umbraco-ui/uui-ref": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0", + "@umbraco-ui/uui-ref": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node-data-type": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-data-type/-/uui-ref-node-data-type-1.10.0.tgz", - "integrity": "sha512-4PxcAdF8wgKfBepHL5xmUKB6i1i5lbHKJUOPmo67N/Vj/xPeBfc899mfv9zFxHV2i5q7FGrxexDEkjtvp2QkYg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-data-type/-/uui-ref-node-data-type-1.11.0.tgz", + "integrity": "sha512-MED2t6TvjNgzLhV2aaWf/WJ6qA5fhWgFC11hCfEDdjqzhot7TrL4yI/YRDaEJXcYjb5rivod+c346ejSL9+Eog==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node-document-type": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-document-type/-/uui-ref-node-document-type-1.10.0.tgz", - "integrity": "sha512-sKqOGeqbLoJfOrstQebwNv/Mu+Zn5MJOUEyhKgYU04Xh5alpQuEm8G1fmrWYlR3RVeN0APGhl8zC0GJToThw4g==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-document-type/-/uui-ref-node-document-type-1.11.0.tgz", + "integrity": "sha512-S2kzH14m508FBkYalKsWEPLT2xShqryxuSs6caiYAi3cXm5MJq04phvRxl9Yo7h74PESojmZWHjRquPfCLEHog==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node-form": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-form/-/uui-ref-node-form-1.10.0.tgz", - "integrity": "sha512-c7fJdsNswUnbCl92zWSU6cxKoimPKqNstoHGcDXfy0GTW0pPQqdL/Ux2ymuY84U1HfJxMsc+hC21KVmG/N0oxw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-form/-/uui-ref-node-form-1.11.0.tgz", + "integrity": "sha512-S1RobwV2O69eyw5sDRrJJDcFNF49hfZ/UcsluK9snPBe080Hzcqjl8bp+6AnH5NyicVwwDW43s6KImXhlIhtVw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node-member": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-member/-/uui-ref-node-member-1.10.0.tgz", - "integrity": "sha512-ZrSb8b6/hizqqlKtcaCxg0A/L8hBblxiXpMuxx+vD0ihYLJt6fYBFo6NI2KGqAztTd/5/Bih+7Ayy33gh7+0Eg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-member/-/uui-ref-node-member-1.11.0.tgz", + "integrity": "sha512-rFqPLY2xnFNFaGgPvneYHapLbnmNhUBaGYnSBe8GJkywz1YFBfdJKj7OftKiqMVWidNz32fejGEUouj9zztxyw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node-package": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-package/-/uui-ref-node-package-1.10.0.tgz", - "integrity": "sha512-yaHAx0NOWIBDs+eHqvKMIgqHvTIRvPEj0O9c8smTDPaXNiIpTdzikRoqbFfp9QoPipK2Yzgtdzx6FxwnkOldJw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-package/-/uui-ref-node-package-1.11.0.tgz", + "integrity": "sha512-ykakG0czZnDdCMy5bRawizwYTu4J267vM1bJrfUa22+hSMKGMy/o4oKS+aKQ2Rh5eUlfBq80iylLDhn4rdmJ6A==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0" } }, "node_modules/@umbraco-ui/uui-ref-node-user": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-user/-/uui-ref-node-user-1.10.0.tgz", - "integrity": "sha512-+gFVF/gY3VU6NqwI1Ns54Ly7LNEIlTh891MTLxum/3WidyhCQfHEjlFpjEtyBYafWY2/dS54/9ST7wg8+wLFlQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-ref-node-user/-/uui-ref-node-user-1.11.0.tgz", + "integrity": "sha512-mrvjf+0usJmJRtTwg90bvLZvftBLG6IQPUxPqWEN7cYbwnDnT0GDn/5qA8Yx9+eND+xMU/I3Dvke9XOyLXfT9Q==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-ref-node": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-ref-node": "1.11.0" } }, "node_modules/@umbraco-ui/uui-scroll-container": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-scroll-container/-/uui-scroll-container-1.10.0.tgz", - "integrity": "sha512-BX/ECh7lsJPbNzQD6N43bMyNTk4EROG6L9LbQja/YUYB6/9CH/uaOpve31vFyykjQTi84QFf/C4zWcuLAfQHPg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-scroll-container/-/uui-scroll-container-1.11.0.tgz", + "integrity": "sha512-e+8Fnc2rFtRdv52DpZW0UC9CnxzhXmIqRldYjTpbaL6Xjg9qNSdeW5AvJNk+fgufL6LJOO6NUXs6ixTp8eiOIA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-select": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-select/-/uui-select-1.10.0.tgz", - "integrity": "sha512-J2Oif7zwWaGvmV+04B6oAi37+AWsId9sfBy9LHswuovoe4wOf2mwIiSXRfJZ7hODfoS9g8y9Y/usX09CZhPZVA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-select/-/uui-select-1.11.0.tgz", + "integrity": "sha512-slTOIvJZMMtCnVEhBVjAs1MPQBb1BAAa6R+DOoslC4aqA1yEgXWQmFu0xVZqiN0NTz3kqEF5zfexumVJ5f79LQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-slider": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-slider/-/uui-slider-1.10.1.tgz", - "integrity": "sha512-rqytuqHE9zvDQ+YObH2HZh/H1tMTnud62V/2femk8nEMAxFMGLXLo89f8EYz3SaWPrzak/aD8NhKoSgFfH4Tcw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-slider/-/uui-slider-1.11.0.tgz", + "integrity": "sha512-sxWZCvznmTkpJ+VyoIjMRsVQuYC2SMnTWFd+7xrg3pk5SRySNxhZhyQUyf5jI1hAzrW9ATySDZlaRYCOMsC7uA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-expand": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-expand/-/uui-symbol-expand-1.10.0.tgz", - "integrity": "sha512-hmZrRLaGGaNM65vuUI6bfAIHMfN59Ba3bpiHcEXUvtS1lMsyydGgfZlVuzW7ZlUUEdRj3FRhdwyATuTVUDkhCg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-expand/-/uui-symbol-expand-1.11.0.tgz", + "integrity": "sha512-bFGp9Dhp8heBfNnu3ozw9DOIfwjkVcKNfHLSts6wg+J3vLW4x0y9jLfxSyvArQQUcUHKsgOzEHoNw6igYDpDJw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-file": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file/-/uui-symbol-file-1.10.0.tgz", - "integrity": "sha512-DitXeZrr2X5bRNqP8Etxdg/0oN0PKwxOVdOndAUxvW/5nSQMEPu6YBR4VBPwvTBrO/O3aXW7fe99yMnQ0mILKg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file/-/uui-symbol-file-1.11.0.tgz", + "integrity": "sha512-AK411VsceFqOAGtvlK2VcyTqwPbYVdqJkXbTbsSxYVhIB2jMVISppwlefqerx4zbPASBp4aeIN54PZWN+Y3dfw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-file-dropzone": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-dropzone/-/uui-symbol-file-dropzone-1.10.0.tgz", - "integrity": "sha512-jTF+20vxDQzhpcuqEFbub+5EkCgEZb7OVYBhgxCUW9SftoB5EWaGYR+9lpz5FNjqBQJi5FTR08oji8gFEbmiEA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-dropzone/-/uui-symbol-file-dropzone-1.11.0.tgz", + "integrity": "sha512-Tma0hziyVM3ZXUduL97i8s3zs5JjbZi9lbydPx7foL/vAhEdP7fov8OXF1kMBhYIEieT11td/9ARxKlDOaLojQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-file-thumbnail": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-thumbnail/-/uui-symbol-file-thumbnail-1.10.0.tgz", - "integrity": "sha512-ZbXqXD8MyrHPMTgqwSy81mjaSgb8ZYgkZ6a7M2WNWqL5cpzQ7URUUuT/3U+VDreMexyl9Yy60soWbr2zrjBuqQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-file-thumbnail/-/uui-symbol-file-thumbnail-1.11.0.tgz", + "integrity": "sha512-22JNF2zs9iumu5JTsn6WmvyMqOwjrZ5/tfeL8+4ZnrxWM5CmJ7neKTm5BHoJyj0oM1wML2NWAc4McbWNOXktrg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-folder": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-folder/-/uui-symbol-folder-1.10.0.tgz", - "integrity": "sha512-7gCGuIl8WPwZKVjR5+Tcb5CjAFL7i9kdbpKdDXGpComyZUpfIzy+2Eeb6H0N1P7M6c9gWJkvl06hghI7XJpz+A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-folder/-/uui-symbol-folder-1.11.0.tgz", + "integrity": "sha512-NcQQupEQASwp8pyxVFG6v7rCvNAbgtE2R9IDlLl5yC/k3449TZ/NiEgMaSlmNhexBEc4SCoTMD9IuaEBo4vmZg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-lock": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-lock/-/uui-symbol-lock-1.10.0.tgz", - "integrity": "sha512-8kziG7cQxd0Xjo3XdBBorZ7AwFw0joI7xJCTsFbymIvwRYp5hiJbrj2Kmf4kxs2rCcXPaWjI9D9nr/41EJqO2A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-lock/-/uui-symbol-lock-1.11.0.tgz", + "integrity": "sha512-1PsxVXj5zT3vXOcb+LP6/bgfGOt0aUmIoAGtV6mO/QHb1XPmOB07xrRzkk7CX+VixOCIdkTGYNU/CFjPJwLsow==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-more": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-more/-/uui-symbol-more-1.10.0.tgz", - "integrity": "sha512-Hp2/BP8JDatgI/WVxfriZ/5IhlzvxFOyBzKNi/EIGPQYvMRofdp0GAI1UhT5MmWe6J5R/q9v106CWaDSNUP9pw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-more/-/uui-symbol-more-1.11.0.tgz", + "integrity": "sha512-72OwXzXAm9XXLB/+qGhtl7IRzrq/2uDdMFG93EMJs0NM3MU0EM0Ild7MuIAPecGiCGjBYn/iyZmWhYMDhS/KOA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-symbol-sort": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-sort/-/uui-symbol-sort-1.10.0.tgz", - "integrity": "sha512-J6EyHkY0hT7ZcZrh3JhCXlKnHE6xC9CXzIZ3EJ0lIPZOBLOql2okut0g/ZdP5s4JM7zGOEUEwEFwO+duxxacYA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-symbol-sort/-/uui-symbol-sort-1.11.0.tgz", + "integrity": "sha512-Y+PQc77PvmVOGAaPGRTYrtLI3MCV/BqE9hl0f+yGZYK/C97r3ogGQxMguU5zThf49EOEL3VmB/WWS/HEFblsjA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-table": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-table/-/uui-table-1.10.0.tgz", - "integrity": "sha512-AoqRaRAfI/WokEuDtE1utl5HVh05l/4+gpUWUj1vzyTNoVeBH3pMxg93ZDlus5pntNavP4foYl4GyTlPSVXcXg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-table/-/uui-table-1.11.0.tgz", + "integrity": "sha512-AXKMARK9WtyuU9T72LGprhBQXpYKw4rWGoGQwUjRk4lwdQD8WKeY3kfIIcaeabBiK5FPnZaEoCpxIkmPt77n2w==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-tabs": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tabs/-/uui-tabs-1.10.0.tgz", - "integrity": "sha512-97kkyWEyTvbNVFvcsD4Q9Av2SSwlRN+bdTZe+v1s4gROLJTef9UXs53N68WcjjPZvjBuVL0MpcxZ6kYTs9oxOg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tabs/-/uui-tabs-1.11.0.tgz", + "integrity": "sha512-IyB1qao2G3T5UNBj3Kw9EL7ikjAp8COvHVH8eTD+fjx1PbrNJmDl6utTV6tpysxLkT7UQ3o6QtjxstDtlUSqsg==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-popover-container": "1.10.0", - "@umbraco-ui/uui-symbol-more": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-popover-container": "1.11.0", + "@umbraco-ui/uui-symbol-more": "1.11.0" } }, "node_modules/@umbraco-ui/uui-tag": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tag/-/uui-tag-1.10.0.tgz", - "integrity": "sha512-CtR6XcvM9DXBhZrVmngeT2aMsx5D38DnJCDLZlxcNyqbfL7U6FH8QGTWO9Htepln/hPr48VyTMV0yHs/mKfpHQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-tag/-/uui-tag-1.11.0.tgz", + "integrity": "sha512-TGMkL7J+PPOq0dZiXnj5Y7f6+c/IJl71I2cme75cE/SkzoI01hr1KvEEThHT83yn64PPqews8ZCh1fKwmI1tmw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-textarea": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-textarea/-/uui-textarea-1.10.0.tgz", - "integrity": "sha512-hZKAhzDYqGVGqR2aZ+TsE/YygfKXOUs8i0OGeecUEuiEsL18+Js5Y2qyeb8pq5GUE2Mu6nJx2FkH8KThRCoLug==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-textarea/-/uui-textarea-1.11.0.tgz", + "integrity": "sha512-g4ciGte7YgHJkzhkLPn4xiGfjHXFbUWa86S4bg3WricucdF20EReLRc6I2jW7mo8lL+h+y8wLcIIQ8CquscLsQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@umbraco-ui/uui-toast-notification": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification/-/uui-toast-notification-1.10.0.tgz", - "integrity": "sha512-dVPSRVPDblNDeqKMEVZx2PePyn/qfKtq6pu5k6gqh5aQhYZt2GyyV/oHELgf+VYNzzfgdN65w2cd78i3Ug5fVw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification/-/uui-toast-notification-1.11.0.tgz", + "integrity": "sha512-5Mhhwn5z/IdlO3iuMMM8HYlDXg9GM23NxCykDcNGpGxMW0TeMFNLNxsBqm+5fOsNYjL2vhv3utPZyeE57ulyQA==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-button": "1.10.0", - "@umbraco-ui/uui-css": "1.10.0", - "@umbraco-ui/uui-icon": "1.10.0", - "@umbraco-ui/uui-icon-registry-essential": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-button": "1.11.0", + "@umbraco-ui/uui-css": "1.11.0", + "@umbraco-ui/uui-icon": "1.11.0", + "@umbraco-ui/uui-icon-registry-essential": "1.11.0" } }, "node_modules/@umbraco-ui/uui-toast-notification-container": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-container/-/uui-toast-notification-container-1.10.0.tgz", - "integrity": "sha512-s+Uxe+IDLvzg+cj1+icFzVYU+8UB/XgFZetLOI7PLe5edbvFVwld0UmminQ9n1KYbyxGOnxvvhCgBfrgpiFkLw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-container/-/uui-toast-notification-container-1.11.0.tgz", + "integrity": "sha512-Y0LunmaTU/06i6mZF/RmopCDvsZMbgYlayJ3K7w6qkqXeJCnLg9cWHQSmOvIz9DJPO84NOcoYCwsLo4DRYa8WQ==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-toast-notification": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-toast-notification": "1.11.0" } }, "node_modules/@umbraco-ui/uui-toast-notification-layout": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-layout/-/uui-toast-notification-layout-1.10.0.tgz", - "integrity": "sha512-TY6DUEDqXXvNpe7O/j1fanBeWxyeV6Mc9jpXY2ERXrDCaPKL1uEUl2ouIrOCBw5OQMJsoZBU8ZtZmkGRRjlu4w==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toast-notification-layout/-/uui-toast-notification-layout-1.11.0.tgz", + "integrity": "sha512-lYuYhtgnO4ELs+qxc2bt6JPBdm+RYhcujMTpx8sSgCYPkHiwxnZt9WEfQQJe4wcwNyuGyMTcwn2d6BKMYgqP9g==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-css": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-css": "1.11.0" } }, "node_modules/@umbraco-ui/uui-toggle": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toggle/-/uui-toggle-1.10.0.tgz", - "integrity": "sha512-uSBf7j1f66rKHnfYXzJdkEDAx0WLukMpQ8zD7ZhvsZ6fEfNP31JbWDaWM7quHshXhk05/wVOgU7fa+6D7sCleA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-toggle/-/uui-toggle-1.11.0.tgz", + "integrity": "sha512-ZWafhMLnR/Z55U4Nw2mUYiPOWrIcSYS4Oay388ZuEKZmfQ0iwGYGSBo4awn3OeY/mVoY88QY6R2siRq9jABKig==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0", - "@umbraco-ui/uui-boolean-input": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0", + "@umbraco-ui/uui-boolean-input": "1.11.0" } }, "node_modules/@umbraco-ui/uui-visually-hidden": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-visually-hidden/-/uui-visually-hidden-1.10.0.tgz", - "integrity": "sha512-Jp+tg8v2Ujth+HSP8W/JZth6QaeqWO2qbLhCCifEwvU4M7/ehmavcm+JnFx8zICkHrSsyL+p7yH4iXJ3H4eGOQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@umbraco-ui/uui-visually-hidden/-/uui-visually-hidden-1.11.0.tgz", + "integrity": "sha512-IxZwVLvX311+iupaupA36C6Ea3Aox/KAh/C5hE81qN+fNI/A8CZxr4OHHEvnQj4VcL0gTG0qt4PbxSR4hRfxmw==", "dependencies": { - "@umbraco-ui/uui-base": "1.10.0" + "@umbraco-ui/uui-base": "1.11.0" } }, "node_modules/@ungap/structured-clone": { diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 53cd7afbf8..e8c3c25519 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -215,8 +215,8 @@ "@types/diff": "^5.2.1", "@types/dompurify": "^3.0.5", "@types/uuid": "^10.0.0", - "@umbraco-ui/uui": "^v1.10.1", - "@umbraco-ui/uui-css": "^v1.10.0", + "@umbraco-ui/uui": "^1.11.0", + "@umbraco-ui/uui-css": "^1.11.0", "base64-js": "^1.5.1", "diff": "^5.2.0", "dompurify": "^3.1.6", From db7a683dc9b34e955c5291d22798a414d4baf09d Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 14 Oct 2024 08:56:33 +0100 Subject: [PATCH 045/246] Chore: Update's VS Code new `UmbLitElement` code snippet (#2449) * Reworked VSCode code snippet for creating new `UmbLitElement` classes * Removed ctor Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Marks `styles` as `readonly` Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Removes `elementName` constant --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> --- .../.vscode/lit.code-snippets | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/.vscode/lit.code-snippets b/src/Umbraco.Web.UI.Client/.vscode/lit.code-snippets index b8907220b6..4920d8011b 100644 --- a/src/Umbraco.Web.UI.Client/.vscode/lit.code-snippets +++ b/src/Umbraco.Web.UI.Client/.vscode/lit.code-snippets @@ -1,30 +1,30 @@ { - "Create Lit Component": { - "prefix": "lit new", + "UmbNewLitElement": { + "prefix": "new umb element", "scope": "typescript", "body": [ - "import { UmbTextStyles } from '@umbraco-ui/backoffice/style';", - "import { css, html } from 'lit';", - "import { customElement } from 'lit/decorators.js';", + "import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit';", "import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';", + "import { UmbTextStyles } from '@umbraco-cms/backoffice/style';", "", "@customElement('umb-${TM_FILENAME_BASE/(.*)\\..+$/$1/}')", - "export class Umb${TM_FILENAME_BASE/(.*)\\..+$/${1:/pascalcase}/}Element extends UmbLitElement {", - "\trender() {", - "\t\treturn html`${0:umb-${TM_FILENAME_BASE/(.*)\\..+$/$1/}}`;", + "export class Umb${TM_FILENAME_BASE/(.*)$/${1:/pascalcase}/}Element extends UmbLitElement {", + "\toverride render() {", + "\t\treturn html`$0`;", "\t}", "", - "\tstatic styles = [UmbTextStyles, css``];", + "\tstatic override readonly styles = [UmbTextStyles, css``];", "}", "", - "export default Umb${TM_FILENAME_BASE/(.*)\\..+$/${1:/pascalcase}/}Element", + "export { Umb${TM_FILENAME_BASE/(.*)$/${1:/pascalcase}/}Element as element };", "", "declare global {", "\tinterface HTMLElementTagNameMap {", - "\t\t'umb-${TM_FILENAME_BASE/(.*)\\..+$/$1/}': Umb${TM_FILENAME_BASE/(.*)\\..+$/${1:/pascalcase}/}Element;", + "\t\t'umb-${TM_FILENAME_BASE/(.*)\\..+$/$1/}': Umb${TM_FILENAME_BASE/(.*)$/${1:/pascalcase}/}Element;", "\t}", - "}" + "}", + "", ], - "description": "Create a new Lit Component" - } + "description": "Create a new Umbraco Lit element", + }, } From d4a245307563562af6cb657b127ad9a9972b2269 Mon Sep 17 00:00:00 2001 From: Richard Thompson Date: Mon, 14 Oct 2024 09:12:55 +0100 Subject: [PATCH 046/246] Adds read-only mode to Color Picker Property Editor (#2451) * Adds read-only mode to Color Picker Property Editor Implemented the read-only mode of the Color Picker Property Editor UI to close https://github.com/umbraco/Umbraco-CMS/issues/17045. * feat: forward the `readonly` attribute to the swatch* elements * chore: rearrange properties in the element --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> --- .../input-color/input-color.element.ts | 20 +++++++++++++++++-- .../color-picker/manifests.ts | 1 + ...property-editor-ui-color-picker.element.ts | 12 ++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts index e2805d571f..a25a6e09d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts @@ -15,6 +15,14 @@ export class UmbInputColorElement extends UUIFormControlMixin(UmbLitElement, '') return undefined; } + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + @property({ type: Boolean }) showLabels = false; @@ -28,7 +36,11 @@ export class UmbInputColorElement extends UUIFormControlMixin(UmbLitElement, '') override render() { return html` - + ${this.#renderColors()} `; @@ -39,7 +51,11 @@ export class UmbInputColorElement extends UUIFormControlMixin(UmbLitElement, '') return map( this.swatches, (swatch) => html` - + `, ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/manifests.ts index 661024c3b4..4fd2a6f70f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/manifests.ts @@ -11,6 +11,7 @@ export const manifests: Array = [ propertyEditorSchemaAlias: 'Umbraco.ColorPicker', icon: 'icon-colorpicker', group: 'pickers', + supportsReadOnly: true, }, }, schemaManifest, diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.element.ts index 9aa22a08be..cbb8ad632d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.element.ts @@ -25,6 +25,15 @@ export class UmbPropertyEditorUIColorPickerElement extends UmbLitElement impleme } #value?: UmbSwatchDetails | undefined; + /** + * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @attr + * @default false + */ + @property({ type: Boolean, reflect: true }) + readonly = false; + @state() private _showLabels = this.#defaultShowLabels; @@ -59,7 +68,8 @@ export class UmbPropertyEditorUIColorPickerElement extends UmbLitElement impleme value=${this.value?.value ?? ''} .swatches=${this._swatches} ?showLabels=${this._showLabels} - @change=${this.#onChange}>`; + @change=${this.#onChange} + ?readonly=${this.readonly}>`; } } From 4726335a7ddd4b99c2742627daf929b266b46f71 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:55:35 +0200 Subject: [PATCH 047/246] fix: only set the ?readonly attribute on the swatches element since it handles setting it on the colors afterwards --- .../core/components/input-color/input-color.element.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts index a25a6e09d7..47f48626e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.element.ts @@ -51,11 +51,7 @@ export class UmbInputColorElement extends UUIFormControlMixin(UmbLitElement, '') return map( this.swatches, (swatch) => html` - + `, ); } From 62050e9cb6ae33f350669f48be19ca5a16b032ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kottal?= Date: Mon, 14 Oct 2024 11:47:31 +0200 Subject: [PATCH 048/246] fixes icon alignment in links in redirect dashboard --- .../dashboard-redirect-management.element.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.element.ts index 6dc438db9e..e07c2596d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.element.ts @@ -212,15 +212,19 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement { return html` ${data.culture || '*'} - ${data.originalUrl} - + + ${data.originalUrl} + + - ${data.destinationUrl} - + + ${data.destinationUrl} + + @@ -290,6 +294,12 @@ export class UmbDashboardRedirectManagementElement extends UmbLitElement { justify-content: center; margin-top: var(--uui-size-space-5); } + + uui-table-cell a:has(span, uui-icon) { + display: inline-flex; + align-items: center; + gap: var(--uui-size-2); + } `, ]; } From e2b8a788f615208f56d41ea43cd369bdb0655598 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 14 Oct 2024 13:04:40 +0100 Subject: [PATCH 049/246] Fixes #17254 Making 'Umb.Section.Content' as a const UMB_CONTENT_SECTION_ALIAS that can be imported --- .../src/mocks/data/user-group/user-group.data.ts | 7 ++++--- .../src/packages/core/content/constants.ts | 1 + .../src/packages/core/content/index.ts | 1 + .../documents/document-redirect-management/manifests.ts | 4 +++- .../src/packages/documents/section/constants.ts | 1 - .../src/packages/documents/section/manifests.ts | 2 +- .../src/packages/language/app-language-select/manifests.ts | 3 ++- .../src/packages/umbraco-news/manifests.ts | 3 ++- 8 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/section/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/user-group/user-group.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/user-group/user-group.data.ts index 07cfdc57f7..a6ec2a5e7c 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/user-group/user-group.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/user-group/user-group.data.ts @@ -1,4 +1,5 @@ import type { UserGroupItemResponseModel, UserGroupResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import { UMB_CONTENT_SECTION_ALIAS } from '@umbraco-cms/backoffice/content'; export type UmbMockUserGroupModel = UserGroupResponseModel & UserGroupItemResponseModel; @@ -34,7 +35,7 @@ export const data: Array = [ }, ], sections: [ - 'Umb.Section.Content', + UMB_CONTENT_SECTION_ALIAS, 'Umb.Section.Media', 'Umb.Section.Settings', 'Umb.Section.Members', @@ -71,7 +72,7 @@ export const data: Array = [ 'Umb.Document.Rollback', ], permissions: [], - sections: ['Umb.Section.Content', 'Umb.Section.Media'], + sections: [UMB_CONTENT_SECTION_ALIAS, 'Umb.Section.Media'], languages: [], hasAccessToAllLanguages: true, documentRootAccess: true, @@ -124,7 +125,7 @@ export const data: Array = [ 'Umb.Document.Notifications', ], permissions: [], - sections: ['Umb.Section.Content'], + sections: [UMB_CONTENT_SECTION_ALIAS], languages: [], hasAccessToAllLanguages: true, documentRootAccess: true, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/constants.ts new file mode 100644 index 0000000000..cecd2baf55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/constants.ts @@ -0,0 +1 @@ +export const UMB_CONTENT_SECTION_ALIAS = 'Umb.Section.Content'; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts index b955ee1cfe..0a951a2634 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/index.ts @@ -5,4 +5,5 @@ export * from './controller/merge-content-variant-data.controller.js'; export * from './property-dataset-context/content-property-dataset.context.js'; export * from './workspace/index.js'; export * from './collection/index.js'; +export * from './constants.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/manifests.ts index b2d382a017..57d82f47f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/manifests.ts @@ -1,3 +1,5 @@ +import { UMB_CONTENT_SECTION_ALIAS } from '@umbraco-cms/backoffice/content'; + export const manifests: Array = [ { type: 'dashboard', @@ -12,7 +14,7 @@ export const manifests: Array = [ conditions: [ { alias: 'Umb.Condition.SectionAlias', - match: 'Umb.Section.Content', + match: UMB_CONTENT_SECTION_ALIAS, }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/section/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/section/constants.ts deleted file mode 100644 index 05a27ced5d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/section/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const UMB_CONTENT_SECTION_ALIAS = 'Umb.Section.Content'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/section/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/section/manifests.ts index b85ba02924..026dea27f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/section/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/section/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_CONTENT_SECTION_ALIAS } from './constants.js'; +import { UMB_CONTENT_SECTION_ALIAS } from '@umbraco-cms/backoffice/content'; import { UMB_DOCUMENT_ROOT_ENTITY_TYPE, UMB_CONTENT_MENU_ALIAS } from '@umbraco-cms/backoffice/document'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts index 7dad1225b7..5bb2dc5fd6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_CONTENT_SECTION_ALIAS } from '@umbraco-cms/backoffice/content'; export const manifests: Array = [ { type: 'sectionSidebarApp', @@ -8,7 +9,7 @@ export const manifests: Array = [ conditions: [ { alias: 'Umb.Condition.SectionAlias', - match: 'Umb.Section.Content', + match: UMB_CONTENT_SECTION_ALIAS, }, { alias: 'Umb.Condition.MultipleAppLanguages', diff --git a/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/manifests.ts index b181f8336d..202efc257c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/manifests.ts @@ -1,4 +1,5 @@ import type { ManifestDashboard } from '@umbraco-cms/backoffice/dashboard'; +import { UMB_CONTENT_SECTION_ALIAS } from '@umbraco-cms/backoffice/content'; export const dashboard: ManifestDashboard = { type: 'dashboard', @@ -12,7 +13,7 @@ export const dashboard: ManifestDashboard = { conditions: [ { alias: 'Umb.Condition.SectionAlias', - match: 'Umb.Section.Content', + match: UMB_CONTENT_SECTION_ALIAS, }, ], }; From 7719d4b5785864a3fd2ea0428ed1cfac51e46a49 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 09:35:49 +0100 Subject: [PATCH 050/246] Reordered Tiptap extension manifests Removed the weighing and put into order of perceived usefulness. --- .../packages/tiptap/extensions/manifests.ts | 561 +++++++++--------- .../src/packages/tiptap/plugins/manifests.ts | 1 - 2 files changed, 268 insertions(+), 294 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts index ed8f9f7f56..4d7f9b1cee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts @@ -132,298 +132,6 @@ const coreExtensions: Array = [ ]; const toolbarExtensions: Array = [ - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Blockquote', - name: 'Blockquote Tiptap Extension', - api: () => import('./toolbar/blockquote.extension.js'), - weight: 995, - meta: { - alias: 'blockquote', - icon: 'icon-blockquote', - label: 'Blockquote', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Bold', - name: 'Bold Tiptap Extension', - api: () => import('./toolbar/bold.extension.js'), - weight: 999, - meta: { - alias: 'bold', - icon: 'icon-bold', - label: 'Bold', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.CodeBlock', - name: 'Code Block Tiptap Extension', - api: () => import('./toolbar/code-block.extension.js'), - weight: 994, - meta: { - alias: 'codeBlock', - icon: 'icon-code', - label: 'Code Block', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.BulletList', - name: 'Bullet List Tiptap Extension', - api: () => import('./toolbar/bullet-list.extension.js'), - weight: 993, - meta: { - alias: 'bulletList', - icon: 'icon-bulleted-list', - label: 'Bullet List', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.OrderedList', - name: 'Ordered List Tiptap Extension', - api: () => import('./toolbar/ordered-list.extension.js'), - weight: 992, - meta: { - alias: 'orderedList', - icon: 'icon-ordered-list', - label: 'Ordered List', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Redo', - name: 'Redo Tiptap Extension', - api: () => import('./toolbar/redo.extension.js'), - element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), - weight: 994, - meta: { - alias: 'redo', - icon: 'icon-redo', - label: 'Redo', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Strike', - name: 'Strike Tiptap Extension', - api: () => import('./toolbar/strike.extension.js'), - weight: 996, - meta: { - alias: 'strike', - icon: 'icon-strikethrough', - label: 'Strike', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Subscript', - name: 'Subscript Tiptap Extension', - api: () => import('./toolbar/subscript.extension.js'), - weight: 1010, - meta: { - alias: 'subscript', - icon: 'icon-subscript', - label: 'Subscript', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Superscript', - name: 'Superscript Tiptap Extension', - api: () => import('./toolbar/superscript.extension.js'), - weight: 1011, - meta: { - alias: 'superscript', - icon: 'icon-superscript', - label: 'Superscript', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Table', - name: 'Table Tiptap Extension', - api: () => import('./toolbar/table.extension.js'), - weight: 909, - meta: { - alias: 'table', - icon: 'icon-table', - label: 'Table', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Heading1', - name: 'Heading 1 Tiptap Extension', - api: () => import('./toolbar/heading1.extension.js'), - weight: 949, - meta: { - alias: 'heading1', - icon: 'icon-heading-1', - label: 'Heading 1', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Heading2', - name: 'Heading 2 Tiptap Extension', - api: () => import('./toolbar/heading2.extension.js'), - weight: 948, - meta: { - alias: 'heading2', - icon: 'icon-heading-2', - label: 'Heading 2', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Heading3', - name: 'Heading 3 Tiptap Extension', - api: () => import('./toolbar/heading3.extension.js'), - weight: 947, - meta: { - alias: 'heading3', - icon: 'icon-heading-3', - label: 'Heading 3', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.HorizontalRule', - name: 'Horizontal Rule Tiptap Extension', - api: () => import('./toolbar/horizontal-rule.extension.js'), - weight: 991, - meta: { - alias: 'horizontalRule', - icon: 'icon-horizontal-rule', - label: 'Horizontal Rule', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Italic', - name: 'Italic Tiptap Extension', - api: () => import('./toolbar/italic.extension.js'), - weight: 998, - meta: { - alias: 'italic', - icon: 'icon-italic', - label: 'Italic', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.TextAlignCenter', - name: 'Text Align Center Tiptap Extension', - api: () => import('./toolbar/text-align-center.extension.js'), - weight: 918, - meta: { - alias: 'text-align-center', - icon: 'icon-text-align-center', - label: 'Text Align Center', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.TextAlignJustify', - name: 'Text Align Justify Tiptap Extension', - api: () => import('./toolbar/text-align-justify.extension.js'), - weight: 916, - meta: { - alias: 'text-align-justify', - icon: 'icon-text-align-justify', - label: 'Text Align Justify', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.TextAlignLeft', - name: 'Text Align Left Tiptap Extension', - api: () => import('./toolbar/text-align-left.extension.js'), - weight: 919, - meta: { - alias: 'text-align-left', - icon: 'icon-text-align-left', - label: 'Text Align Left', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.TextAlignRight', - name: 'Text Align Right Tiptap Extension', - api: () => import('./toolbar/text-align-right.extension.js'), - weight: 917, - meta: { - alias: 'text-align-right', - icon: 'icon-text-align-right', - label: 'Text Align Right', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Underline', - name: 'Underline Tiptap Extension', - api: () => import('./toolbar/underline.extension.js'), - weight: 997, - meta: { - alias: 'underline', - icon: 'icon-underline', - label: 'Underline', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Undo', - name: 'Undo Tiptap Extension', - api: () => import('./toolbar/undo.extension.js'), - element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), - weight: 994, - meta: { - alias: 'undo', - icon: 'icon-undo', - label: 'Undo', - }, - }, - { - type: 'tiptapToolbarExtension', - kind: 'button', - alias: 'Umb.Tiptap.Toolbar.Unlink', - name: 'Unlink Tiptap Extension', - api: () => import('./toolbar/unlink.extension.js'), - element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), - weight: 101, - meta: { - alias: 'unlink', - icon: 'icon-unlink', - label: 'Unlink', - }, - }, -]; - -const umbToolbarExtensions: Array = [ { type: 'tiptapToolbarExtension', kind: 'button', @@ -436,6 +144,174 @@ const umbToolbarExtensions: Array = [ label: '#general_viewSourceCode', }, }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Bold', + name: 'Bold Tiptap Extension', + api: () => import('./toolbar/bold.extension.js'), + meta: { + alias: 'bold', + icon: 'icon-bold', + label: 'Bold', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Italic', + name: 'Italic Tiptap Extension', + api: () => import('./toolbar/italic.extension.js'), + meta: { + alias: 'italic', + icon: 'icon-italic', + label: 'Italic', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Underline', + name: 'Underline Tiptap Extension', + api: () => import('./toolbar/underline.extension.js'), + meta: { + alias: 'underline', + icon: 'icon-underline', + label: 'Underline', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Strike', + name: 'Strike Tiptap Extension', + api: () => import('./toolbar/strike.extension.js'), + meta: { + alias: 'strike', + icon: 'icon-strikethrough', + label: 'Strike', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.TextAlignLeft', + name: 'Text Align Left Tiptap Extension', + api: () => import('./toolbar/text-align-left.extension.js'), + meta: { + alias: 'text-align-left', + icon: 'icon-text-align-left', + label: 'Text Align Left', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.TextAlignCenter', + name: 'Text Align Center Tiptap Extension', + api: () => import('./toolbar/text-align-center.extension.js'), + meta: { + alias: 'text-align-center', + icon: 'icon-text-align-center', + label: 'Text Align Center', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.TextAlignRight', + name: 'Text Align Right Tiptap Extension', + api: () => import('./toolbar/text-align-right.extension.js'), + meta: { + alias: 'text-align-right', + icon: 'icon-text-align-right', + label: 'Text Align Right', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.TextAlignJustify', + name: 'Text Align Justify Tiptap Extension', + api: () => import('./toolbar/text-align-justify.extension.js'), + meta: { + alias: 'text-align-justify', + icon: 'icon-text-align-justify', + label: 'Text Align Justify', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Heading1', + name: 'Heading 1 Tiptap Extension', + api: () => import('./toolbar/heading1.extension.js'), + meta: { + alias: 'heading1', + icon: 'icon-heading-1', + label: 'Heading 1', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Heading2', + name: 'Heading 2 Tiptap Extension', + api: () => import('./toolbar/heading2.extension.js'), + meta: { + alias: 'heading2', + icon: 'icon-heading-2', + label: 'Heading 2', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Heading3', + name: 'Heading 3 Tiptap Extension', + api: () => import('./toolbar/heading3.extension.js'), + meta: { + alias: 'heading3', + icon: 'icon-heading-3', + label: 'Heading 3', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.BulletList', + name: 'Bullet List Tiptap Extension', + api: () => import('./toolbar/bullet-list.extension.js'), + meta: { + alias: 'bulletList', + icon: 'icon-bulleted-list', + label: 'Bullet List', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.OrderedList', + name: 'Ordered List Tiptap Extension', + api: () => import('./toolbar/ordered-list.extension.js'), + meta: { + alias: 'orderedList', + icon: 'icon-ordered-list', + label: 'Ordered List', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Blockquote', + name: 'Blockquote Tiptap Extension', + api: () => import('./toolbar/blockquote.extension.js'), + meta: { + alias: 'blockquote', + icon: 'icon-blockquote', + label: 'Blockquote', + }, + }, { type: 'tiptapToolbarExtension', kind: 'button', @@ -448,6 +324,93 @@ const umbToolbarExtensions: Array = [ label: '#defaultdialogs_urlLinkPicker', }, }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Unlink', + name: 'Unlink Tiptap Extension', + api: () => import('./toolbar/unlink.extension.js'), + element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), + meta: { + alias: 'unlink', + icon: 'icon-unlink', + label: 'Unlink', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.CodeBlock', + name: 'Code Block Tiptap Extension', + api: () => import('./toolbar/code-block.extension.js'), + meta: { + alias: 'codeBlock', + icon: 'icon-code', + label: 'Code Block', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Subscript', + name: 'Subscript Tiptap Extension', + api: () => import('./toolbar/subscript.extension.js'), + meta: { + alias: 'subscript', + icon: 'icon-subscript', + label: 'Subscript', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Superscript', + name: 'Superscript Tiptap Extension', + api: () => import('./toolbar/superscript.extension.js'), + meta: { + alias: 'superscript', + icon: 'icon-superscript', + label: 'Superscript', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.HorizontalRule', + name: 'Horizontal Rule Tiptap Extension', + api: () => import('./toolbar/horizontal-rule.extension.js'), + meta: { + alias: 'horizontalRule', + icon: 'icon-horizontal-rule', + label: 'Horizontal Rule', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Undo', + name: 'Undo Tiptap Extension', + api: () => import('./toolbar/undo.extension.js'), + element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), + meta: { + alias: 'undo', + icon: 'icon-undo', + label: 'Undo', + }, + }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Redo', + name: 'Redo Tiptap Extension', + api: () => import('./toolbar/redo.extension.js'), + element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), + meta: { + alias: 'redo', + icon: 'icon-redo', + label: 'Redo', + }, + }, { type: 'tiptapToolbarExtension', kind: 'button', @@ -472,8 +435,20 @@ const umbToolbarExtensions: Array = [ label: '#general_embed', }, }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.Table', + name: 'Table Tiptap Extension', + api: () => import('./toolbar/table.extension.js'), + meta: { + alias: 'table', + icon: 'icon-table', + label: 'Table', + }, + }, ]; -const extensions = [...coreExtensions, ...toolbarExtensions, ...umbToolbarExtensions]; +const extensions = [...coreExtensions, ...toolbarExtensions]; export const manifests = [...kinds, ...extensions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts index aafd570b89..ed1effb3cb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts @@ -19,7 +19,6 @@ export const manifests: Array import('./block-picker-toolbar.extension.js'), - weight: 90, meta: { alias: 'umbblockpicker', icon: 'icon-plugin', From 7b548768c62eadcfa37405483ff261b9e267298b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 09:36:08 +0100 Subject: [PATCH 051/246] Reworked Tiptap Extensions configuration Refactored UI to be a grouped checkbox lists, improves on intend and accessibility. --- ...tiptap-extensions-configuration.element.ts | 185 +++++++----------- .../property-editors/tiptap/manifests.ts | 4 +- 2 files changed, 70 insertions(+), 119 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts index d020ec400d..572e827e2e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts @@ -1,31 +1,27 @@ -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; -import { customElement, css, html, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { customElement, css, html, property, state, repeat, when, nothing } from '@umbraco-cms/backoffice/external/lit'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { - UmbPropertyValueChangeEvent, - type UmbPropertyEditorConfigCollection, - type UmbPropertyEditorUiElement, +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; +import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; +import type { + UmbPropertyEditorConfigCollection, + UmbPropertyEditorUiElement, } from '@umbraco-cms/backoffice/property-editor'; -type UmbTiptapExtensionConfig = { +type UmbTiptapExtension = { alias: string; label: string; icon?: string; - group: string; + group?: string; }; -type UmbTiptapExtensionGroupItem = { - alias: string; - label: string; - icon?: string; +type UmbTiptapExtensionGroupItem = UmbTiptapExtension & { selected: boolean; }; type UmbTiptapExtensionGroup = { group: string; - extensions: UmbTiptapExtensionGroupItem[]; + extensions: Array; }; const elementName = 'umb-property-editor-ui-tiptap-extensions-configuration'; @@ -42,61 +38,41 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement config?: UmbPropertyEditorConfigCollection; @state() - private _extensionCategories: UmbTiptapExtensionGroup[] = []; + private _extensions: Array = []; @state() - private _extensionConfigs: UmbTiptapExtensionConfig[] = []; + private _groups: Array = []; protected override async firstUpdated(_changedProperties: PropertyValueMap) { super.firstUpdated(_changedProperties); this.observe(umbExtensionsRegistry.byType('tiptapExtension'), (extensions) => { - this._extensionConfigs = extensions + this._extensions = extensions .sort((a, b) => a.alias.localeCompare(b.alias)) - .map((ext) => { - return { - alias: ext.alias, - label: ext.meta.label, - icon: ext.meta.icon, - group: ext.meta.group, - }; - }); + .map((ext) => ({ alias: ext.alias, label: ext.meta.label, icon: ext.meta.icon, group: ext.meta.group })); if (!this.value) { // The default value is all extensions enabled - this.value = this._extensionConfigs.map((ext) => ext.alias); + this.value = this._extensions.map((ext) => ext.alias); this.dispatchEvent(new UmbPropertyValueChangeEvent()); } - this.#setupExtensionCategories(); - }); - } - - #setupExtensionCategories() { - const useDefault = !this.value; // The default value is all extensions enabled - const withSelectedProperty = this._extensionConfigs.map((extensionConfig) => { - return { - ...extensionConfig, - selected: useDefault ? true : this.value!.includes(extensionConfig.alias), - }; - }); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - const grouped = Object.groupBy( - withSelectedProperty, - (item: UmbTiptapExtensionConfig) => item.group || 'Uncategorized', - ); - - this._extensionCategories = Object.keys(grouped) - .sort((a, b) => a.localeCompare(b)) - .map((key) => ({ - group: key, - extensions: grouped[key], + const items: Array = this._extensions.map((extension) => ({ + ...extension, + selected: this.value!.includes(extension.alias), })); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + const grouped = Object.groupBy(items, (item: UmbTiptapExtensionGroupItem) => item.group || 'Uncategorized'); + + this._groups = Object.keys(grouped) + .sort((a, b) => a.localeCompare(b)) + .map((key) => ({ group: key, extensions: grouped[key] })); + }); } - #onExtensionClick(item: UmbTiptapExtensionGroupItem) { + #onClick(item: UmbTiptapExtensionGroupItem) { item.selected = !item.selected; if (!this.value) { @@ -109,93 +85,68 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement this.value = this.value.filter((alias) => alias !== item.alias); } - this.requestUpdate('_extensionCategories'); this.dispatchEvent(new UmbPropertyValueChangeEvent()); } override render() { + if (!this._groups.length) return nothing; return html` -
- ${repeat( - this._extensionCategories, - (group) => html` -
-

${this.localize.string(group.group)}

+ ${repeat( + this._groups, + (group) => html` +
+ ${this.localize.string(group.group)} +
    ${repeat( group.extensions, (item) => html` -
    - + this.#onExtensionClick(item)}> - - - this.#onExtensionClick(item)}> -
    + value=${item.alias} + ?checked=${item.selected} + @change=${() => this.#onClick(item)}> +
    + ${when(item.icon, () => html``)} + ${this.localize.string(item.label)} +
    + + `, )} -
- `, - )} -
+ +
+ `, + )} `; } static override readonly styles = [ - UmbTextStyles, css` - uui-icon { - width: unset; - height: unset; - display: flex; - vertical-align: unset; - } - - uui-button.selected { - --uui-button-border-color: var(--uui-color-selected); - --uui-button-border-width: 2px; - } - - .extensions { + :host { display: flex; flex-wrap: wrap; - gap: 16px; - margin-top: 16px; - } - - .extension-item { - display: grid; - grid-template-columns: 36px 1fr; - grid-template-rows: 1fr; - align-items: center; - gap: 9px; + gap: 1rem; } .group { flex: 1; - display: flex; - flex-direction: column; - gap: 6px; - padding: 12px; - background-color: var(--uui-color-surface-alt); - border: 1px solid var(--uui-color-border); - border-radius: 6px; - } - .group-name { - grid-column: 1 / -1; - display: flex; - font-weight: bold; - margin: 0; + ul { + list-style: none; + padding: 0; + margin: 1rem 0 0; + + .inner { + display: flex; + flex-direction: row; + gap: 0.5rem; + + umb-icon { + font-size: 1.2rem; + } + } + } } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts index a2791c4935..768105faa1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts @@ -22,8 +22,8 @@ export const manifests: Array = [ }, { alias: 'extensions', - label: 'Extensions', - description: 'Extensions to enable', + label: 'Capabilities', + description: 'Enable extensions enhance the capabilities of the Tiptap editor.', propertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap.ExtensionsConfiguration', weight: 10, }, From 36b7a68f7cf4b04745dc25343f0ece34cf171926 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 09:36:27 +0100 Subject: [PATCH 052/246] Adds "Rich Text Essentials" as a hard-coded core option This is to indicate that the basic formatting, e.g. bold, italic, etc are enabled by default. --- ...or-ui-tiptap-extensions-configuration.element.ts | 13 +++++++++++++ .../tiptap/property-editors/tiptap/manifests.ts | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts index 572e827e2e..2a313a31af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts @@ -97,6 +97,19 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement
${this.localize.string(group.group)}
    + ${when( + group.group === '#tiptap_extGroup_formatting', + () => html` +
  • + +
    + + Rich Text Essentials +
    +
    +
  • + `, + )} ${repeat( group.extensions, (item) => html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts index 768105faa1..5aaf02032b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts @@ -18,7 +18,7 @@ export const manifests: Array = [ label: 'Toolbar', description: 'Pick the toolbar items that should be available when editing', propertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap.ToolbarConfiguration', - weight: 5, + weight: 15, }, { alias: 'extensions', From 171b899828982dbb6258e163ab973285bcf1c79c Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 09:48:17 +0100 Subject: [PATCH 053/246] Relocated `UmbTiptapToolbarValue` --- .../tiptap/components/input-tiptap/input-tiptap.element.ts | 3 ++- .../tiptap/components/input-tiptap/tiptap-toolbar.element.ts | 2 +- .../src/packages/tiptap/components/types.ts | 1 + .../src/packages/tiptap/extensions/types.ts | 2 -- .../property-editor-ui-tiptap-toolbar-configuration.element.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/components/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index 4197a5075a..e0f083f65a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -1,4 +1,5 @@ -import type { UmbTiptapExtensionApi, UmbTiptapToolbarValue } from '../../extensions/types.js'; +import type { UmbTiptapExtensionApi } from '../../extensions/types.js'; +import type { UmbTiptapToolbarValue } from '../types.js'; import { css, customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit'; import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts index 678ec6369a..a799d05907 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts @@ -1,4 +1,4 @@ -import type { UmbTiptapToolbarValue } from '../../extensions/types.js'; +import type { UmbTiptapToolbarValue } from '../types.js'; import { css, customElement, html, map, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbExtensionsElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/types.ts new file mode 100644 index 0000000000..5167150c48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/types.ts @@ -0,0 +1 @@ +export type UmbTiptapToolbarValue = Array>>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts index 927d22cf63..ec2bcc1f8c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts @@ -98,5 +98,3 @@ export abstract class UmbTiptapToolbarElementApiBase extends UmbControllerBase i return editor && this.manifest?.meta.alias ? editor?.isActive(this.manifest.meta.alias) : false; } } - -export type UmbTiptapToolbarValue = Array>>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts index 7078d2318a..74203c67a0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts @@ -1,6 +1,6 @@ -import type { UmbTiptapToolbarValue } from '../../../extensions/types.js'; import { customElement, css, html, property, state, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbTiptapToolbarValue } from '../../../components/types.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; From 7f84bc31a85402f7e7fb4851d9a42811bd9ea26f Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 09:49:04 +0100 Subject: [PATCH 054/246] Updated `tiptapToolbarExtension` manifest with `forExtensions` data --- .../src/packages/tiptap/extensions/manifests.ts | 12 ++++++++++++ .../tiptap/extensions/tiptap-toolbar-extension.ts | 1 + .../src/packages/tiptap/plugins/manifests.ts | 1 + 3 files changed, 14 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts index 4d7f9b1cee..8f27df5139 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts @@ -174,6 +174,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.Underline', name: 'Underline Tiptap Extension', api: () => import('./toolbar/underline.extension.js'), + forExtensions: ['Umb.Tiptap.Underline'], meta: { alias: 'underline', icon: 'icon-underline', @@ -198,6 +199,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.TextAlignLeft', name: 'Text Align Left Tiptap Extension', api: () => import('./toolbar/text-align-left.extension.js'), + forExtensions: ['Umb.Tiptap.TextAlign'], meta: { alias: 'text-align-left', icon: 'icon-text-align-left', @@ -210,6 +212,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.TextAlignCenter', name: 'Text Align Center Tiptap Extension', api: () => import('./toolbar/text-align-center.extension.js'), + forExtensions: ['Umb.Tiptap.TextAlign'], meta: { alias: 'text-align-center', icon: 'icon-text-align-center', @@ -222,6 +225,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.TextAlignRight', name: 'Text Align Right Tiptap Extension', api: () => import('./toolbar/text-align-right.extension.js'), + forExtensions: ['Umb.Tiptap.TextAlign'], meta: { alias: 'text-align-right', icon: 'icon-text-align-right', @@ -234,6 +238,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.TextAlignJustify', name: 'Text Align Justify Tiptap Extension', api: () => import('./toolbar/text-align-justify.extension.js'), + forExtensions: ['Umb.Tiptap.TextAlign'], meta: { alias: 'text-align-justify', icon: 'icon-text-align-justify', @@ -318,6 +323,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.Link', name: 'Link Tiptap Extension', api: () => import('./toolbar/link.extension.js'), + forExtensions: ['Umb.Tiptap.Link'], meta: { alias: 'umbLink', icon: 'icon-link', @@ -331,6 +337,7 @@ const toolbarExtensions: Array = [ name: 'Unlink Tiptap Extension', api: () => import('./toolbar/unlink.extension.js'), element: () => import('../components/toolbar/tiptap-toolbar-button-disabled.element.js'), + forExtensions: ['Umb.Tiptap.Link'], meta: { alias: 'unlink', icon: 'icon-unlink', @@ -355,6 +362,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.Subscript', name: 'Subscript Tiptap Extension', api: () => import('./toolbar/subscript.extension.js'), + forExtensions: ['Umb.Tiptap.Subscript'], meta: { alias: 'subscript', icon: 'icon-subscript', @@ -367,6 +375,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.Superscript', name: 'Superscript Tiptap Extension', api: () => import('./toolbar/superscript.extension.js'), + forExtensions: ['Umb.Tiptap.Superscript'], meta: { alias: 'superscript', icon: 'icon-superscript', @@ -417,6 +426,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.MediaPicker', name: 'Media Picker Tiptap Extension', api: () => import('./toolbar/media-picker.extension.js'), + forExtensions: ['Umb.Tiptap.Figure', 'Umb.Tiptap.Image'], meta: { alias: 'umbMedia', icon: 'icon-picture', @@ -429,6 +439,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.EmbeddedMedia', name: 'Embedded Media Tiptap Extension', api: () => import('./toolbar/embedded-media.extension.js'), + forExtensions: ['Umb.Tiptap.Embed'], meta: { alias: 'umbEmbeddedMedia', icon: 'icon-embed', @@ -441,6 +452,7 @@ const toolbarExtensions: Array = [ alias: 'Umb.Tiptap.Toolbar.Table', name: 'Table Tiptap Extension', api: () => import('./toolbar/table.extension.js'), + forExtensions: ['Umb.Tiptap.Table'], meta: { alias: 'table', icon: 'icon-table', diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts index a97d658328..3c178b4e85 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts @@ -6,6 +6,7 @@ export interface ManifestTiptapToolbarExtension< MetaType extends MetaTiptapToolbarExtension = MetaTiptapToolbarExtension, > extends ManifestElementAndApi { type: 'tiptapToolbarExtension'; + forExtensions?: Array; meta: MetaType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts index ed1effb3cb..7701a5f10a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/plugins/manifests.ts @@ -19,6 +19,7 @@ export const manifests: Array import('./block-picker-toolbar.extension.js'), + forExtensions: ['Umb.Tiptap.Block'], meta: { alias: 'umbblockpicker', icon: 'icon-plugin', From 0b7c50730e41c3e97766e514ef2bf1d8520e22f9 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 09:49:29 +0100 Subject: [PATCH 055/246] Updated Tiptap data-type config labels/descriptions --- .../property-editors/tiptap/manifests.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts index 5aaf02032b..b0526ffd57 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/manifests.ts @@ -13,20 +13,24 @@ export const manifests: Array = [ group: 'richContent', settings: { properties: [ - { - alias: 'toolbar', - label: 'Toolbar', - description: 'Pick the toolbar items that should be available when editing', - propertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap.ToolbarConfiguration', - weight: 15, - }, { alias: 'extensions', label: 'Capabilities', - description: 'Enable extensions enhance the capabilities of the Tiptap editor.', + description: `Enable extensions enhance the capabilities of the Tiptap editor. + +_Once enabled, the extensions will be available in the toolbar._`, propertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap.ExtensionsConfiguration', weight: 10, }, + { + alias: 'toolbar', + label: 'Toolbar', + description: `Configure the toolbar for the intended editing experience. + +_Drag and drop the available items onto the toolbar designer._`, + propertyEditorUiAlias: 'Umb.PropertyEditorUi.Tiptap.ToolbarConfiguration', + weight: 15, + }, { alias: 'dimensions', label: 'Dimensions', From bd5b898fcec60c91f328e8248fbe501ed2b72526 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 13:11:18 +0100 Subject: [PATCH 056/246] Tiptap toolbar designer reworking Observes the enabled extensions, updates available items accordingly. Adds a context API and label localizations. --- .../src/assets/lang/en.ts | 9 + ...ui-tiptap-toolbar-configuration.element.ts | 606 +++++++++++------- .../tiptap-toolbar-configuration.context.ts | 247 +++++++ .../tiptap/property-editors/tiptap/types.ts | 10 + 4 files changed, 627 insertions(+), 245 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/types.ts 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 18827472af..363c255c74 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2648,5 +2648,14 @@ export default { extGroup_interactive: 'Interactive elements', extGroup_media: 'Embeds and media', extGroup_structure: 'Content structure', + toobar_availableItems: 'Available toolbar items', + toobar_availableItemsEmpty: 'There are no toolbar extensions to show', + toolbar_designer: 'Toolbar designer', + toolbar_addRow: 'Add row configuration', + toolbar_addGroup: 'Add group', + toolbar_addItems: 'Add items', + toolbar_removeRow: 'Remove row', + toolbar_removeGroup: 'Remove group', + toolbar_removeItem: 'Remove item', }, } as UmbLocalizationDictionary; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts index 74203c67a0..4fd205cead 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts @@ -1,16 +1,16 @@ -import { customElement, css, html, property, state, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbTiptapToolbarConfigurationContext } from '../contexts/tiptap-toolbar-configuration.context.js'; +import type { + UmbTiptapToolbarExtension, + UmbTiptapToolbarGroupViewModel, + UmbTiptapToolbarRowViewModel, +} from '../types.js'; import type { UmbTiptapToolbarValue } from '../../../components/types.js'; +import { customElement, css, html, property, repeat, state, when, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { debounce } from '@umbraco-cms/backoffice/utils'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UmbPropertyValueChangeEvent, type UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; -import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; -type UmbTiptapToolbarExtension = { - alias: string; - label: string; - icon: string; -}; const elementName = 'umb-property-editor-ui-tiptap-toolbar-configuration'; @customElement(elementName) @@ -18,56 +18,59 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement extends UmbLitElement implements UmbPropertyEditorUiElement { - readonly #inUse: Set = new Set(); + #context = new UmbTiptapToolbarConfigurationContext(this); - #currentDragItem?: { - alias: string; - fromPos?: [number, number, number]; - }; + #currentDragItem?: { alias: string; fromPos?: [number, number, number] }; - #lookup?: Map; + #debouncedFilter = debounce((query: string) => { + this._availableExtensions = this.#context.filterExtensions(query); + }, 250); @state() - private _extensions: Array = []; + private _availableExtensions: Array = []; + + @state() + private _toolbar: Array = []; @property({ attribute: false }) set value(value: UmbTiptapToolbarValue | undefined) { - if (!this.#isValidTiptapToolbarValue(value)) { - this.#value = [[[]]]; - return; - } - - if (value.length > 0) { - this.#value = value.map((rows) => rows.map((groups) => [...groups])); - value.forEach((row) => row.forEach((group) => group.forEach((alias) => this.#inUse.add(alias)))); - } + if (!value) value = [[[]]]; + if (value === this.#value) return; + this.#context.setToolbar(value); } - get value(): UmbTiptapToolbarValue { - return this.#value; + get value(): UmbTiptapToolbarValue | undefined { + return this.#value?.map((rows) => rows.map((groups) => [...groups])); } - #value: UmbTiptapToolbarValue = [[[]]]; + #value?: UmbTiptapToolbarValue; - protected override async firstUpdated(_changedProperties: PropertyValueMap) { - super.firstUpdated(_changedProperties); + constructor() { + super(); - this.observe(umbExtensionsRegistry.byType('tiptapToolbarExtension'), (extensions) => { - this._extensions = extensions.map((ext) => ({ alias: ext.alias, label: ext.meta.label, icon: ext.meta.icon })); - this.#lookup = new Map(this._extensions.map((ext) => [ext.alias, ext])); + this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { + this.observe(this.#context.extensions, (extensions) => { + this._availableExtensions = extensions; + }); + + this.observe(this.#context.reload, (reload) => { + if (reload) { + this.requestUpdate(); + } + }); + + this.observe(this.#context.toolbar, (toolbar) => { + if (!toolbar.length) return; + this._toolbar = toolbar; + this.#value = toolbar.map((rows) => rows.data.map((groups) => [...groups.data])); + propertyContext.setValue(this.#value); + }); }); } - #isValidTiptapToolbarValue(value: unknown): value is UmbTiptapToolbarValue { - if (!Array.isArray(value)) return false; - for (const row of value) { - if (!Array.isArray(row)) return false; - for (const group of row) { - if (!Array.isArray(group)) return false; - for (const alias of group) { - if (typeof alias !== 'string') return false; - } - } - } - return true; + #onClick(item: UmbTiptapToolbarExtension) { + const lastRow = (this.#value?.length ?? 1) - 1; + const lastGroup = (this.#value?.[lastRow].length ?? 1) - 1; + const lastItem = this.#value?.[lastRow][lastGroup].length ?? 0; + this.#context.insertToolbarItem(item.alias, [lastRow, lastGroup, lastItem]); } #onDragStart(event: DragEvent, alias: string, fromPos?: [number, number, number]) { @@ -86,7 +89,7 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement const { fromPos } = this.#currentDragItem ?? {}; if (!fromPos) return; - this.#removeItem(fromPos); + this.#context.removeToolbarItem(fromPos); } } @@ -96,240 +99,353 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement // Remove item if no destination position is provided if (fromPos && !toPos) { - this.#removeItem(fromPos); + this.#context.removeToolbarItem(fromPos); return; } + // Move item if both source and destination positions are available if (fromPos && toPos) { - this.#moveItem(fromPos, toPos); + this.#context.moveToolbarItem(fromPos, toPos); return; } + // Insert item if an alias and a destination position are provided if (alias && toPos) { - this.#insertItem(alias, toPos); + this.#context.insertToolbarItem(alias, toPos); } } - #moveItem(from: [number, number, number], to: [number, number, number]) { - const [rowIndex, groupIndex, itemIndex] = from; - - // Get the item to move from the 'from' position - const itemToMove = this.#value[rowIndex][groupIndex][itemIndex]; - - // Remove the item from the original position - this.#value[rowIndex][groupIndex].splice(itemIndex, 1); - - this.#insertItem(itemToMove, to); - } - - #insertItem(alias: string, toPos: [number, number, number]) { - const [rowIndex, groupIndex, itemIndex] = toPos; - - // Insert the item into the new position - const inserted = this.#value[rowIndex][groupIndex].splice(itemIndex, 0, alias); - inserted.forEach((alias) => this.#inUse.add(alias)); - - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - } - - #removeItem(from: [number, number, number]) { - const [rowIndex, groupIndex, itemIndex] = from; - - const removed = this.#value[rowIndex][groupIndex].splice(itemIndex, 1); - removed.forEach((alias) => this.#inUse.delete(alias)); - - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - } - - #addGroup(rowIndex: number, groupIndex: number) { - this.#value[rowIndex].splice(groupIndex, 0, []); - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - } - - #removeGroup(rowIndex: number, groupIndex: number) { - if (this.#value[rowIndex].length > groupIndex) { - const removed = this.#value[rowIndex].splice(groupIndex, 1); - removed.forEach((group) => group.forEach((alias) => this.#inUse.delete(alias))); - } - - // Prevent leaving an empty group - if (this.#value[rowIndex].length === 0) { - this.#value[rowIndex][groupIndex] = []; - } - - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - } - - #addRow(rowIndex: number) { - this.#value.splice(rowIndex, 0, [[]]); - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - } - - #removeRow(rowIndex: number) { - if (this.#value.length > rowIndex) { - const removed = this.#value.splice(rowIndex, 1); - removed.forEach((row) => row.forEach((group) => group.forEach((alias) => this.#inUse.delete(alias)))); - } - - // Prevent leaving an empty row - if (this.#value.length === 0) { - this.#value[rowIndex] = [[]]; - } - - this.dispatchEvent(new UmbPropertyValueChangeEvent()); + #onFilterInput(event: InputEvent & { target: HTMLInputElement }) { + const query = (event.target.value ?? '').toLocaleLowerCase(); + this.#debouncedFilter(query); } override render() { - return html` - ${repeat(this.#value, (row, rowIndex) => this.#renderRow(row, rowIndex))} - this.#addRow(this.#value.length)}> - - Add row - - ${this.#renderExtensions()} - `; + return html`${this.#renderAvailableItems()} ${this.#renderDesigner()}`; } - #renderRow(row: string[][], rowIndex: number) { + #renderAvailableItems() { return html` -
    - ${repeat(row, (group, groupIndex) => this.#renderGroup(group, rowIndex, groupIndex))} - this.#addGroup(rowIndex, row.length)}> - - Add group - - this.#removeRow(rowIndex)}> - - -
    - `; - } - - #renderGroup(group: string[], rowIndex: number, groupIndex: number) { - return html` -
    this.#onDrop(e, [rowIndex, groupIndex, group.length])}> - ${group.map((alias, itemIndex) => this.#renderItem(alias, rowIndex, groupIndex, itemIndex))} - this.#removeGroup(rowIndex, groupIndex)}> - - -
    - `; - } - - #renderItem(alias: string, rowIndex: number, groupIndex: number, itemIndex: number) { - const extension = this.#lookup?.get(alias); - if (!extension) return nothing; - return html` -
    this.#onDragStart(e, alias, [rowIndex, groupIndex, itemIndex])}> - -
    - `; - } - - #renderExtensions() { - return html` -
    - ${repeat( - this._extensions.filter((ext) => !this.#inUse.has(ext.alias)), - (extension) => html` -
    this.#onDragStart(e, extension.alias)} - @dragend=${this.#onDragEnd}> - + +
    + +
    +
    +
    +
    +
    + ${when( + this._availableExtensions.length === 0, + () => + html`There are no toolbar extensions to show`, + () => repeat(this._availableExtensions, (item) => this.#renderAvailableItem(item)), + )} +
    +
    + `; + } + + #renderAvailableItem(item: UmbTiptapToolbarExtension) { + const forbidden = !this.#context.isExtensionEnabled(item.alias); + const inUse = this.#context.isExtensionInUse(item.alias); + return html` + this.#onClick(item)} + @dragstart=${(e: DragEvent) => this.#onDragStart(e, item.alias)} + @dragend=${this.#onDragEnd}> +
    + ${when(item.icon, () => html``)} + ${this.localize.string(item.label)} +
    +
    + `; + } + + #renderDesigner() { + return html` + +
    + ${repeat( + this._toolbar, + (row) => row.unique, + (row, idx) => this.#renderRow(row, idx), + )} +
    + this.#context.insertToolbarRow(this._toolbar.length)}> +
    + `; + } + + #renderRow(row?: UmbTiptapToolbarRowViewModel, rowIndex = 0) { + if (!row) return nothing; + const hideActionBar = this._toolbar.length === 1; + return html` + this.#context?.insertToolbarRow(rowIndex)}> +
    +
    + this.#context?.insertToolbarGroup(rowIndex, 0)}> + ${repeat( + row.data, + (group) => group.unique, + (group, idx) => this.#renderGroup(group, rowIndex, idx), + )} +
    + ${when( + !hideActionBar, + () => html` + + this.#context?.removeToolbarRow(rowIndex)}> + + + `, )}
    `; } + #renderGroup(group?: UmbTiptapToolbarGroupViewModel, rowIndex = 0, groupIndex = 0) { + if (!group) return nothing; + const hideActionBar = this._toolbar[rowIndex].data.length === 1 && group.data.length === 0; + return html` +
    this.#onDrop(e, [rowIndex, groupIndex, group.data.length - 1])}> +
    + ${when( + group?.data.length === 0, + () => html`Add items`, + () => html`${group!.data.map((alias, idx) => this.#renderItem(alias, rowIndex, groupIndex, idx))}`, + )} +
    + ${when( + !hideActionBar, + () => html` + + this.#context?.removeToolbarGroup(rowIndex, groupIndex)}> + + + + `, + )} +
    + this.#context?.insertToolbarGroup(rowIndex, groupIndex + 1)}> + `; + } + + #renderItem(alias: string, rowIndex = 0, groupIndex = 0, itemIndex = 0) { + const item = this.#context?.getExtensionByAlias(alias); + if (!item) return nothing; + const forbidden = !this.#context?.isExtensionEnabled(item.alias); + return html` + this.#context.removeToolbarItem([rowIndex, groupIndex, itemIndex])} + @dragend=${this.#onDragEnd} + @dragstart=${(e: DragEvent) => this.#onDragStart(e, alias, [rowIndex, groupIndex, itemIndex])}> +
    + ${when( + item.icon, + () => html``, + () => html`${this.localize.string(item.label)}`, + )} +
    +
    + `; + } + static override readonly styles = [ - UmbTextStyles, css` :host { display: flex; flex-direction: column; - gap: 6px; + gap: var(--uui-size-1); } - .extensions { + + uui-box.minimal { + --uui-box-header-padding: 0; + --uui-box-default-padding: var(--uui-size-2) 0; + --uui-box-box-shadow: none; + + [slot='header-actions'] { + margin-bottom: var(--uui-size-2); + + uui-icon { + color: var(--uui-color-border); + } + } + } + + .available-items { display: flex; flex-wrap: wrap; - gap: 3px; - border-radius: var(--uui-border-radius); + gap: var(--uui-size-3); background-color: var(--uui-color-surface-alt); - padding: 6px; - min-height: 30px; - min-width: 30px; - } - .row { - position: relative; - display: flex; - gap: 12px; - } - .group { - position: relative; - display: flex; - gap: 3px; border-radius: var(--uui-border-radius); - background-color: var(--uui-color-surface-alt); - padding: 6px; - min-height: 32px; - min-width: 32px; + padding: var(--uui-size-3); + + uui-button { + --uui-button-font-weight: normal; + + &[draggable='true'], + &[draggable='true'] > .inner { + cursor: move; + } + + &[disabled], + &[disabled] > .inner { + cursor: not-allowed; + } + + &.forbidden { + --color: var(--uui-color-danger); + --color-standalone: var(--uui-color-danger-standalone); + --color-emphasis: var(--uui-color-danger-emphasis); + --color-contrast: var(--uui-color-danger); + --uui-button-contrast-disabled: var(--uui-color-danger); + --uui-button-border-color-disabled: var(--uui-color-danger); + opacity: 0.5; + } + + div { + display: flex; + gap: var(--uui-size-1); + } + } } - .item { - padding: var(--uui-size-space-2); - border: 1px solid var(--uui-color-border); - border-radius: var(--uui-border-radius); - background-color: var(--uui-color-surface); + + #rows { + display: flex; + flex-direction: column; + gap: var(--uui-size-1); + + .row { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: var(--uui-size-3); + border: 1px solid var(--uui-color-border); + border-radius: var(--uui-border-radius); + padding: var(--uui-size-3) var(--uui-size-2); + + &:hover { + border-color: var(--uui-button-contrast-hover); + } + + .groups { + flex: 1; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: flex-start; + gap: var(--uui-size-1); + + uui-button-inline-create { + height: 40px; + } + + .group { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: var(--uui-size-3); + + border: 1px dashed var(--uui-color-border-standalone); + border-radius: var(--uui-border-radius); + padding: var(--uui-size-3); + + &:hover { + border-color: var(--uui-button-contrast-hover); + } + + .items { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: var(--uui-size-1); + + uui-button { + --uui-button-font-weight: normal; + + &[draggable='true'], + &[draggable='true'] > .inner { + cursor: move; + } + + &[disabled], + &[disabled] > .inner { + cursor: not-allowed; + } + + &.forbidden { + --color: var(--uui-color-danger); + --color-standalone: var(--uui-color-danger-standalone); + --color-emphasis: var(--uui-color-danger-emphasis); + --color-contrast: var(--uui-color-danger); + --uui-button-contrast-disabled: var(--uui-color-danger); + --uui-button-border-color-disabled: var(--uui-color-danger); + opacity: 0.5; + } + + div { + display: flex; + gap: var(--uui-size-1); + } + } + } + } + } + } + } + + #btnAddRow { + display: block; + margin-top: var(--uui-size-1); + } + + .handle { cursor: move; - display: flex; - box-sizing: border-box; - width: 32px; - height: 32px; - justify-content: center; - } - - .remove-row-button, - .remove-group-button { - display: none; - } - .remove-group-button { - position: absolute; - top: -26px; - left: 50%; - transform: translateX(-50%); - z-index: 1; - } - - .row:hover .remove-row-button:not(.hidden), - .group:hover .remove-group-button:not(.hidden) { - display: flex; - } - umb-icon { - /* Prevents titles from bugging out */ - pointer-events: none; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts new file mode 100644 index 0000000000..a6d73979c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts @@ -0,0 +1,247 @@ +import type { UmbTiptapToolbarValue } from '../../../components/types.js'; +import type { + UmbTiptapToolbarExtension, + UmbTiptapToolbarGroupViewModel, + UmbTiptapToolbarRowViewModel, +} from '../types.js'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbArrayState, UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UmbId } from '@umbraco-cms/backoffice/id'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbTiptapToolbarConfigurationContext extends UmbContextBase { + #extensions = new UmbArrayState([], (x) => x.alias); + public readonly extensions = this.#extensions.asObservable(); + + #reload = new UmbBooleanState(false); + public readonly reload = this.#reload.asObservable(); + + #extensionsEnabled = new Set(); + + #extensionsInUse = new Set(); + + #lookup?: Map; + + #toolbar = new UmbArrayState([], (x) => x.unique); + public readonly toolbar = this.#toolbar.asObservable(); + + constructor(host: UmbControllerHost) { + super(host, UMB_TIPTAP_TOOLBAR_CONFIGURATION_CONTEXT); + + this.observe(umbExtensionsRegistry.byType('tiptapToolbarExtension'), (extensions) => { + const _extensions = extensions.map((ext) => ({ + alias: ext.alias, + label: ext.meta.label, + icon: ext.meta.icon, + dependencies: ext.forExtensions, + })); + + this.#extensions.setValue(_extensions); + + this.#lookup = new Map(_extensions.map((ext) => [ext.alias, ext])); + }); + + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (dataset) => { + this.observe( + await dataset.propertyValueByAlias>('extensions'), + (extensions) => { + if (extensions) { + this.#extensionsEnabled.clear(); + this.#reload.setValue(false); + + this.#extensions + .getValue() + .filter((x) => !x.dependencies || x.dependencies.every((z) => extensions.includes(z))) + .map((x) => x.alias) + .forEach((alias) => this.#extensionsEnabled.add(alias)); + + this.#reload.setValue(true); + } + }, + '_observeExtensions', + ); + }); + } + + public filterExtensions(query: string): Array { + return this.#extensions + .getValue() + .filter((ext) => ext.alias?.toLowerCase().includes(query) || ext.label?.toLowerCase().includes(query)); + } + + public getExtensionByAlias(alias: string): UmbTiptapToolbarExtension | undefined { + return this.#lookup?.get(alias); + } + + public isExtensionEnabled(alias: string): boolean { + return this.#extensionsEnabled.has(alias); + } + + public isExtensionInUse(alias: string): boolean { + return this.#extensionsInUse.has(alias); + } + + public isValidToolbarValue(value: unknown): value is UmbTiptapToolbarValue { + if (!Array.isArray(value)) return false; + for (const row of value) { + if (!Array.isArray(row)) return false; + for (const group of row) { + if (!Array.isArray(group)) return false; + for (const alias of group) { + if (typeof alias !== 'string') return false; + } + } + } + return true; + } + + public insertToolbarItem(alias: string, to: [number, number, number]) { + const toolbar = [...this.#toolbar.getValue()]; + + const [rowIndex, groupIndex, itemIndex] = to; + + const row = toolbar[rowIndex]; + const rowData = [...row.data]; + const group = rowData[groupIndex]; + const items = [...group.data]; + + items.splice(itemIndex, 0, alias); + this.#extensionsInUse.add(alias); + + rowData[groupIndex] = { unique: group.unique, data: items }; + toolbar[rowIndex] = { unique: row.unique, data: rowData }; + + this.#toolbar.setValue(toolbar); + } + + public insertToolbarGroup(rowIndex: number, groupIndex: number) { + const toolbar = [...this.#toolbar.getValue()]; + const row = toolbar[rowIndex]; + const groups = [...row.data]; + groups.splice(groupIndex, 0, { unique: UmbId.new(), data: [] }); + toolbar[rowIndex] = { unique: row.unique, data: groups }; + this.#toolbar.setValue(toolbar); + } + + public insertToolbarRow(rowIndex: number) { + const toolbar = [...this.#toolbar.getValue()]; + toolbar.splice(rowIndex, 0, { unique: UmbId.new(), data: [{ unique: UmbId.new(), data: [] }] }); + this.#toolbar.setValue(toolbar); + } + + public moveToolbarItem(from: [number, number, number], to: [number, number, number]) { + const [fromRowIndex, fromGroupIndex, fromItemIndex] = from; + const [toRowIndex, toGroupIndex, toItemIndex] = to; + + const toolbar = [...this.#toolbar.getValue()]; + + const fromRow = toolbar[fromRowIndex]; + const fromRowData = [...fromRow.data]; + const fromGroup = fromRowData[fromGroupIndex]; + const fromItems = [...fromGroup.data]; + + const toBeMoved = fromItems.splice(fromItemIndex, 1); + + fromRowData[fromGroupIndex] = { unique: fromGroup.unique, data: fromItems }; + toolbar[fromRowIndex] = { unique: fromRow.unique, data: fromRowData }; + + const toRow = toolbar[toRowIndex]; + const toRowData = [...toRow.data]; + const toGroup = toRowData[toGroupIndex]; + const toItems = [...toGroup.data]; + + toItems.splice(toItemIndex, 0, toBeMoved[0]); + + toRowData[toGroupIndex] = { unique: toGroup.unique, data: toItems }; + toolbar[toRowIndex] = { unique: toRow.unique, data: toRowData }; + + this.#toolbar.setValue(toolbar); + } + + public removeToolbarItem(from: [number, number, number]) { + const [rowIndex, groupIndex, itemIndex] = from; + + const toolbar = [...this.#toolbar.getValue()]; + const row = toolbar[rowIndex]; + const rowData = [...row.data]; + const group = rowData[groupIndex]; + const items = [...group.data]; + + const removed = items.splice(itemIndex, 1); + removed.forEach((alias) => this.#extensionsInUse.delete(alias)); + + rowData[groupIndex] = { unique: group.unique, data: items }; + toolbar[rowIndex] = { unique: row.unique, data: rowData }; + + this.#toolbar.setValue(toolbar); + } + + public removeToolbarGroup(rowIndex: number, groupIndex: number) { + const toolbar = [...this.#toolbar.getValue()]; + + if (toolbar[rowIndex].data.length > groupIndex) { + const row = toolbar[rowIndex]; + const groups = [...row.data]; + const removed = groups.splice(groupIndex, 1); + removed.forEach((group) => group.data.forEach((alias) => this.#extensionsInUse.delete(alias))); + toolbar[rowIndex] = { unique: row.unique, data: groups }; + } + + // Prevent leaving an empty group + if (toolbar[rowIndex].data.length === 0) { + toolbar[rowIndex].data[0] = { unique: UmbId.new(), data: [] }; + } + + this.#toolbar.setValue(toolbar); + } + + public removeToolbarRow(rowIndex: number) { + const toolbar = [...this.#toolbar.getValue()]; + + if (toolbar.length > rowIndex) { + const removed = toolbar.splice(rowIndex, 1); + removed.forEach((row) => + row.data.forEach((group) => group.data.forEach((alias) => this.#extensionsInUse.delete(alias))), + ); + } + + // Prevent leaving an empty row + if (toolbar.length === 0) { + toolbar[0] = { unique: UmbId.new(), data: [{ unique: UmbId.new(), data: [] }] }; + } + + this.#toolbar.setValue(toolbar); + } + + public setToolbar(value?: UmbTiptapToolbarValue | null) { + if (!this.isValidToolbarValue(value)) { + value = [[[]]]; + } + + this.#extensionsInUse.clear(); + value.forEach((row) => row.forEach((group) => group.forEach((alias) => this.#extensionsInUse.add(alias)))); + + const toolbar = value.map((row) => ({ + unique: UmbId.new(), + data: row.map((group) => ({ unique: UmbId.new(), data: group })), + })); + + this.#toolbar.setValue(toolbar); + } + + public updateToolbarRow(rowIndex: number, groups: Array) { + const toolbar = [...this.#toolbar.getValue()]; + + const row = toolbar[rowIndex]; + toolbar[rowIndex] = { unique: row.unique, data: groups }; + + this.#toolbar.setValue(toolbar); + } +} + +export const UMB_TIPTAP_TOOLBAR_CONFIGURATION_CONTEXT = new UmbContextToken( + 'UmbTiptapToolbarConfigurationContext', +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/types.ts new file mode 100644 index 0000000000..305cd36967 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/types.ts @@ -0,0 +1,10 @@ +export type UmbTiptapToolbarExtension = { + alias: string; + label: string; + icon: string; + dependencies?: Array; +}; + +export type UmbTiptapToolbarSortableViewModel = { unique: string; data: T }; +export type UmbTiptapToolbarRowViewModel = UmbTiptapToolbarSortableViewModel>; +export type UmbTiptapToolbarGroupViewModel = UmbTiptapToolbarSortableViewModel>; From 22f8aac99f33b0de55ddc15ce971ce9c742b4df7 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 14 Oct 2024 13:16:25 +0100 Subject: [PATCH 057/246] Tiptap extensions field observes the Block configuration, updates UI accordingly, to enable/disable the Block extension. --- .../src/assets/lang/en.ts | 1 + ...tiptap-extensions-configuration.element.ts | 133 +++++++++++++----- 2 files changed, 96 insertions(+), 38 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 363c255c74..e5b2ca73c7 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2648,6 +2648,7 @@ export default { extGroup_interactive: 'Interactive elements', extGroup_media: 'Embeds and media', extGroup_structure: 'Content structure', + extGroup_unknown: 'Uncategorized', toobar_availableItems: 'Available toolbar items', toobar_availableItemsEmpty: 'There are no toolbar extensions to show', toolbar_designer: 'Toolbar designer', diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts index 2a313a31af..3762eae369 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts @@ -1,4 +1,14 @@ -import { customElement, css, html, property, state, repeat, when, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { + customElement, + css, + html, + ifDefined, + nothing, + property, + state, + repeat, + when, +} from '@umbraco-cms/backoffice/external/lit'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; @@ -7,12 +17,14 @@ import type { UmbPropertyEditorConfigCollection, UmbPropertyEditorUiElement, } from '@umbraco-cms/backoffice/property-editor'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; type UmbTiptapExtension = { alias: string; label: string; icon?: string; group?: string; + description?: string; }; type UmbTiptapExtensionGroupItem = UmbTiptapExtension & { @@ -24,6 +36,9 @@ type UmbTiptapExtensionGroup = { extensions: Array; }; +const TIPTAP_CORE_EXTENSION_ALIAS = 'Umb.Tiptap.RichTextEssentials'; +const TIPTAP_BLOCK_EXTENSION_ALIAS = 'Umb.Tiptap.Block'; + const elementName = 'umb-property-editor-ui-tiptap-extensions-configuration'; @customElement(elementName) @@ -31,8 +46,10 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement extends UmbLitElement implements UmbPropertyEditorUiElement { + #disabledExtensions = new Set([TIPTAP_CORE_EXTENSION_ALIAS]); + @property({ attribute: false }) - value?: Array = []; + value?: Array = [TIPTAP_CORE_EXTENSION_ALIAS]; @property({ attribute: false }) config?: UmbPropertyEditorConfigCollection; @@ -43,6 +60,41 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement @state() private _groups: Array = []; + constructor() { + super(); + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (dataset) => { + this.observe( + await dataset.propertyValueByAlias>('blocks'), + (blocks) => { + const tmpValue = this.value ? [...this.value] : []; + + // When blocks are configured, the block extension can be enabled; + // otherwise, the block extension must be disabled. + if (blocks?.length) { + // Check if the block extension is already enabled, if not, add it. + if (!tmpValue.includes(TIPTAP_BLOCK_EXTENSION_ALIAS)) { + tmpValue.push(TIPTAP_BLOCK_EXTENSION_ALIAS); + } + this.#disabledExtensions.delete(TIPTAP_BLOCK_EXTENSION_ALIAS); + } else { + // Check if the block extension is enabled, if so, remove it. + const idx = tmpValue.indexOf(TIPTAP_BLOCK_EXTENSION_ALIAS) ?? -1; + if (idx >= 0) { + tmpValue.splice(idx, 1); + } + this.#disabledExtensions.add(TIPTAP_BLOCK_EXTENSION_ALIAS); + } + + if (!this.value || !this.#isArrayEqualTo(tmpValue, this.value)) { + this.#setValue(tmpValue); + this.#syncViewModel(); + } + }, + '_observeBlocks', + ); + }); + } + protected override async firstUpdated(_changedProperties: PropertyValueMap) { super.firstUpdated(_changedProperties); @@ -51,43 +103,60 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement .sort((a, b) => a.alias.localeCompare(b.alias)) .map((ext) => ({ alias: ext.alias, label: ext.meta.label, icon: ext.meta.icon, group: ext.meta.group })); + // Hardcoded core extension + this._extensions.unshift({ + alias: TIPTAP_CORE_EXTENSION_ALIAS, + label: 'Rich Text Essentials', + icon: 'icon-browser-window', + group: '#tiptap_extGroup_formatting', + description: 'This is a core extension, it must be enabled', + }); + if (!this.value) { // The default value is all extensions enabled - this.value = this._extensions.map((ext) => ext.alias); - this.dispatchEvent(new UmbPropertyValueChangeEvent()); + this.#setValue(this._extensions.map((ext) => ext.alias)); } - const items: Array = this._extensions.map((extension) => ({ - ...extension, - selected: this.value!.includes(extension.alias), - })); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - const grouped = Object.groupBy(items, (item: UmbTiptapExtensionGroupItem) => item.group || 'Uncategorized'); - - this._groups = Object.keys(grouped) - .sort((a, b) => a.localeCompare(b)) - .map((key) => ({ group: key, extensions: grouped[key] })); + this.#syncViewModel(); }); } + #isArrayEqualTo(a: Array, b: Array) { + return a.length === b.length && a.every((item) => b.includes(item)) && b.every((item) => a.includes(item)); + } + #onClick(item: UmbTiptapExtensionGroupItem) { item.selected = !item.selected; - if (!this.value) { - this.value = []; - } + const tmpValue = item.selected + ? [...(this.value ?? []), item.alias] + : (this.value ?? []).filter((alias) => alias !== item.alias); - if (item.selected) { - this.value = [...this.value, item.alias]; - } else { - this.value = this.value.filter((alias) => alias !== item.alias); - } + this.#setValue(tmpValue); + } + #setValue(value: Array) { + this.value = value; this.dispatchEvent(new UmbPropertyValueChangeEvent()); } + #syncViewModel() { + const items: Array = this._extensions.map((extension) => ({ + ...extension, + selected: this.value!.includes(extension.alias) || extension.alias === TIPTAP_CORE_EXTENSION_ALIAS, + })); + + const uncategorizedLabel = this.localize.term('tiptap_extGroup_unknown'); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + const grouped = Object.groupBy(items, (item: UmbTiptapExtensionGroupItem) => item.group || uncategorizedLabel); + + this._groups = Object.keys(grouped) + .sort((a, b) => a.localeCompare(b)) + .map((key) => ({ group: key, extensions: grouped[key] })); + } + override render() { if (!this._groups.length) return nothing; return html` @@ -97,27 +166,15 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement
    ${this.localize.string(group.group)}
      - ${when( - group.group === '#tiptap_extGroup_formatting', - () => html` -
    • - -
      - - Rich Text Essentials -
      -
      -
    • - `, - )} ${repeat( group.extensions, (item) => html` -
    • +
    • this.#onClick(item)}>
      ${when(item.icon, () => html``)} From b92f0052fa6b87b9578d839af36dfe3e6d9cf61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kottal?= Date: Mon, 14 Oct 2024 17:45:38 +0200 Subject: [PATCH 058/246] Adds gap between grouped buttons in settings welcome dashboard (#2457) * Adds gap between grouped buttons to prevent them from sticking together on small screens * Gremlins :) --- .../settings-welcome-dashboard.element.ts | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.element.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.element.ts index dd8d091c2d..93b7206850 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.element.ts @@ -29,18 +29,21 @@ export class UmbSettingsWelcomeDashboardElement extends UmbLitElement { Ask a question in the community forum or our Discord community

      - - + +
      + + +
      @@ -115,6 +118,12 @@ export class UmbSettingsWelcomeDashboardElement extends UmbLitElement { grid-template-columns: repeat(1, 1fr); } } + + .button-group { + display: flex; + flex-wrap: wrap; + gap: var(--uui-size-space-2); + } `, ]; } From e3d0acc8a2735958564c6128dd192681b7338dab Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 15 Oct 2024 08:17:11 +0100 Subject: [PATCH 059/246] Adds CONST for 'Umb.Condition.WorkspaceAlias' (#2454) * Add a const for 'Umb.Condition.WorkspaceAlias' * Update usages 'Umb.Condition.WorkspaceAlias' of to the new CONST * Somehow accidently deleted .nvmrc * Change from 'src/packages/core/workspace/conditions/const.js' to '@umbraco-cms/backoffice/workspace' as the import * Another fix from the build errors from GitHub - didnt come up locally which was weird * Update src/packages/core/workspace/conditions/workspace-alias.condition.ts Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Renames the consts as agreed in the PR and adds the deprecated notice --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> --- .../workspace-context-counter/index.ts | 8 +++-- .../registry/extension.registry.test.ts | 15 ++++---- .../workspace/manifests.ts | 3 +- .../workspace/views/manifests.ts | 3 +- .../block-grid/workspace/views/manifests.ts | 7 ++-- .../block-list/workspace/views/manifests.ts | 3 +- .../block-rte/workspace/views/manifests.ts | 3 +- .../block/block-type/workspace/manifests.ts | 3 +- .../block/block/workspace/manifests.ts | 9 ++--- .../core/property-type/workspace/manifests.ts | 6 ++-- .../core/workspace/conditions/const.ts | 29 +++++++++++++-- .../core/workspace/conditions/types.ts | 35 ++++++++++--------- .../conditions/workspace-alias.condition.ts | 5 +-- .../workspace-entity-is-new.condition.ts | 4 +-- .../workspace-has-collection.condition.ts | 4 +-- .../src/packages/core/workspace/index.ts | 1 + .../src/packages/data-type/menu/manifests.ts | 6 ++-- .../tree/folder/workspace/manifests.ts | 3 +- .../packages/data-type/workspace/manifests.ts | 7 ++-- .../dictionary/menu-item/manifests.ts | 5 +-- .../dictionary/workspace/manifests.ts | 5 +-- .../tree/folder/workspace/manifests.ts | 3 +- .../workspace/manifests.ts | 5 +-- .../document-types/menu/manifests.ts | 5 +-- .../tree/folder/workspace/manifests.ts | 3 +- .../document-types/workspace/manifests.ts | 11 +++--- .../documents/documents/menu/manifests.ts | 5 +-- .../rollback/entity-action/manifests.ts | 3 +- .../documents/workspace/manifests.ts | 13 +++---- .../extension-insights/workspace/manifests.ts | 3 +- .../src/packages/language/manifests.ts | 3 +- .../src/packages/language/menu/manifests.ts | 6 ++-- .../workspace/language-root/manifests.ts | 3 +- .../language/workspace/language/manifests.ts | 5 +-- .../log-viewer/workspace/manifests.ts | 6 ++-- .../media/media-types/menu/manifests.ts | 5 +-- .../tree/folder/workspace/manifests.ts | 3 +- .../media/media-types/workspace/manifests.ts | 7 ++-- .../packages/media/media/menu/manifests.ts | 5 +-- .../media/media/workspace/manifests.ts | 9 ++--- .../workspace/member-group-root/manifests.ts | 3 +- .../workspace/member-group/manifests.ts | 5 +-- .../members/member-type/menu/manifests.ts | 5 +-- .../member-type/workspace/manifests.ts | 5 +-- .../member/workspace/member-root/manifests.ts | 3 +- .../member/workspace/member/manifests.ts | 7 ++-- .../workspace/relation-type/manifests.ts | 4 ++- .../packages/relations/workspace/manifests.ts | 3 +- .../partial-views/menu/manifests.ts | 5 +-- .../partial-views/workspace/manifests.ts | 3 +- .../templating/scripts/menu/manifests.ts | 5 +-- .../templating/scripts/workspace/manifests.ts | 3 +- .../templating/stylesheets/menu/manifests.ts | 5 +-- .../stylesheets/workspace/manifests.ts | 7 ++-- .../templating/templates/menu/manifests.ts | 5 +-- .../templates/workspace/manifests.ts | 3 +- .../workspace/user-group-root/manifests.ts | 3 +- .../workspace/user-group/manifests.ts | 3 +- .../user/workspace/user-root/manifests.ts | 3 +- .../user/user/workspace/user/manifests.ts | 3 +- .../workspace/webhook-root/manifests.ts | 3 +- .../webhook/workspace/webhook/manifests.ts | 5 +-- 62 files changed, 223 insertions(+), 135 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts index 2bd252893b..edc248b4a9 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts @@ -1,3 +1,5 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; + export const manifests: Array = [ { type: 'workspaceContext', @@ -6,7 +8,7 @@ export const manifests: Array = [ api: () => import('./counter-workspace-context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }, ], @@ -25,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }, ], @@ -43,7 +45,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts index caed039f60..5a9cfce9b5 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts @@ -8,6 +8,7 @@ import type { } from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; interface TestManifestWithMeta extends ManifestBase { meta: unknown; @@ -535,7 +536,7 @@ describe('Add Conditions', () => { // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }; @@ -543,7 +544,7 @@ describe('Add Conditions', () => { const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); - expect(updatedWorkspaceExt.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(updatedWorkspaceExt.conditions?.[0]?.alias).to.equal(UMB_WORKSPACE_CONDITION_ALIAS); }); it('allows an extension to update with multiple conditions', async () => { @@ -555,7 +556,7 @@ describe('Add Conditions', () => { alias: 'Umb.Test.Condition.Valid', }, { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', } as WorkspaceAliasConditionConfig, ]; @@ -566,7 +567,7 @@ describe('Add Conditions', () => { expect(extUpdated.conditions?.length).to.equal(3); expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[2]?.alias).to.equal(UMB_WORKSPACE_CONDITION_ALIAS); }); it('allows conditions to be prepended when an extension is loaded later on', async () => { @@ -575,7 +576,7 @@ describe('Add Conditions', () => { alias: 'Umb.Test.Condition.Invalid', }, { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', } as WorkspaceAliasConditionConfig, ]; @@ -606,7 +607,7 @@ describe('Add Conditions', () => { expect(extUpdated.conditions?.length).to.equal(3); expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[2]?.alias).to.equal(UMB_WORKSPACE_CONDITION_ALIAS); }); /** @@ -622,7 +623,7 @@ describe('Add Conditions', () => { alias: 'Umb.Test.Condition.Invalid', }, { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', } as WorkspaceAliasConditionConfig, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/manifests.ts index e8d2b915e8..10eb00ca0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/manifests.ts @@ -1,6 +1,7 @@ import { manifests as workspaceViewManifests } from './views/manifests.js'; import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_ALIAS } from './index.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const manifests: Array = [ ...workspaceViewManifests, @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/manifests.ts index e30f10ceda..ba7238c442 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_ALIAS } from '../index.js'; import type { ManifestWorkspaceView } from '@umbraco-cms/backoffice/workspace'; @@ -15,7 +16,7 @@ export const workspaceViews: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/manifests.ts index a81da4e20d..8722b9f764 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_BLOCK_GRID_TYPE_WORKSPACE_ALIAS } from '../index.js'; export const manifests: Array = [ @@ -14,7 +15,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_GRID_TYPE_WORKSPACE_ALIAS, }, ], @@ -32,7 +33,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_GRID_TYPE_WORKSPACE_ALIAS, }, ], @@ -50,7 +51,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_GRID_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/views/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/views/manifests.ts index 2668e8db6a..04d75d39ab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/views/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/views/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_BLOCK_LIST_TYPE_WORKSPACE_ALIAS } from '../index.js'; export const manifests: Array = [ @@ -14,7 +15,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_LIST_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/views/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/views/manifests.ts index a6f11440a5..5b8abf2041 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/views/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/views/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_BLOCK_RTE_TYPE_WORKSPACE_ALIAS } from '../index.js'; export const manifests: Array = [ @@ -14,7 +15,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_RTE_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/manifests.ts index eadd29a17c..3fcdb6fb10 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_BLOCK_GRID_TYPE_WORKSPACE_ALIAS } from '../../block-grid/workspace/index.js'; import { UMB_BLOCK_LIST_TYPE_WORKSPACE_ALIAS } from '../../block-list/workspace/index.js'; import { UMB_BLOCK_RTE_TYPE_WORKSPACE_ALIAS } from '../../block-rte/workspace/index.js'; @@ -17,7 +18,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, oneOf: [ UMB_BLOCK_GRID_TYPE_WORKSPACE_ALIAS, UMB_BLOCK_LIST_TYPE_WORKSPACE_ALIAS, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts index e5a5645042..1b67a6e46e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_BLOCK_WORKSPACE_ALIAS } from './index.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -15,7 +16,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_WORKSPACE_ALIAS, }, { @@ -37,7 +38,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_WORKSPACE_ALIAS, }, { @@ -69,7 +70,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_WORKSPACE_ALIAS, }, ], @@ -94,7 +95,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_BLOCK_WORKSPACE_ALIAS, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts index 14d045bb48..23bb2d577c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts @@ -1,5 +1,5 @@ import { UMB_PROPERTY_TYPE_ENTITY_TYPE, UMB_PROPERTY_TYPE_WORKSPACE_ALIAS } from './constants.js'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS, UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; export const manifests: Array = [ { @@ -25,7 +25,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_PROPERTY_TYPE_WORKSPACE_ALIAS, }, ], @@ -43,7 +43,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, oneOf: [UMB_PROPERTY_TYPE_WORKSPACE_ALIAS], }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/const.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/const.ts index 4f333d6e35..00c36c7222 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/const.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/const.ts @@ -1,2 +1,27 @@ -export const UMB_WORKSPACE_HAS_COLLECTION_CONDITION = 'Umb.Condition.WorkspaceHasCollection'; -export const UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION = 'Umb.Condition.WorkspaceEntityIsNew'; +/** + * Workspace has collection condition alias + */ +export const UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS = 'Umb.Condition.WorkspaceHasCollection'; + +/** + * [Deperecated] Workspace has collection condition alias + * @deprecated Use {UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS} instead. This will be removed in Umbraco 16. + */ +export const UMB_WORKSPACE_HAS_COLLECTION_CONDITION = UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS; + +/** + * Workspace entity is new condition alias + */ +export const UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS = 'Umb.Condition.WorkspaceEntityIsNew'; + +/** + * [Deperecated] Workspace entity is new condition alias + * @deprecated Use {UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS} instead. This will be removed in Umbraco 16. + */ +export const UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION = UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS; + +/** + * Workspace alias condition alias + */ +export const UMB_WORKSPACE_CONDITION_ALIAS = 'Umb.Condition.WorkspaceAlias'; + diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/types.ts index 68f753151a..e13151df82 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/types.ts @@ -1,20 +1,21 @@ -import type { UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION, UMB_WORKSPACE_HAS_COLLECTION_CONDITION } from './const.js'; +import type { UMB_WORKSPACE_CONDITION_ALIAS, UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS, UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS } from './const.js'; import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; -export type WorkspaceAliasConditionConfig = UmbConditionConfigBase<'Umb.Condition.WorkspaceAlias'> & { - /** - * Define the workspace that this extension should be available in - * @example - * "Umb.Workspace.Document" - */ - match?: string; - /** - * Define one or more workspaces that this extension should be available in - * @example - * ["Umb.Workspace.Document", "Umb.Workspace.Media"] - */ - oneOf?: Array; -}; +export interface WorkspaceAliasConditionConfig + extends UmbConditionConfigBase { + /** + * Define the workspace that this extension should be available in + * @example + * "Umb.Workspace.Document" + */ + match?: string; + /** + * Define one or more workspaces that this extension should be available in + * @example + * ["Umb.Workspace.Document", "Umb.Workspace.Media"] + */ + oneOf?: Array; + } export type WorkspaceContentTypeAliasConditionConfig = UmbConditionConfigBase<'Umb.Condition.WorkspaceContentTypeAlias'> & { @@ -42,11 +43,11 @@ export type WorkspaceEntityTypeConditionConfig = UmbConditionConfigBase<'Umb.Con }; export type WorkspaceHasCollectionConditionConfig = UmbConditionConfigBase< - typeof UMB_WORKSPACE_HAS_COLLECTION_CONDITION + typeof UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS >; export interface WorkspaceEntityIsNewConditionConfig - extends UmbConditionConfigBase { + extends UmbConditionConfigBase { match: boolean; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts index d327ca6a12..7e6c421ebf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts @@ -4,6 +4,7 @@ import type { WorkspaceAliasConditionConfig } from './types.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from './const.js'; export class UmbWorkspaceAliasCondition extends UmbConditionBase @@ -25,7 +26,7 @@ export class UmbWorkspaceAliasCondition }); } else { throw new Error( - 'Condition `Umb.Condition.WorkspaceAlias` could not be initialized properly. Either "match" or "oneOf" must be defined', + `Condition [UMB_WORKSPACE_CONDITION_ALIAS] (${UMB_WORKSPACE_CONDITION_ALIAS}) could not be initialized properly. Either "match" or "oneOf" must be defined.`, ); } } @@ -34,6 +35,6 @@ export class UmbWorkspaceAliasCondition export const manifest: UmbExtensionManifest = { type: 'condition', name: 'Workspace Alias Condition', - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, api: UmbWorkspaceAliasCondition, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts index c608988944..c3522278c9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts @@ -1,6 +1,6 @@ import { UMB_SUBMITTABLE_WORKSPACE_CONTEXT } from '../index.js'; import type { WorkspaceEntityIsNewConditionConfig } from './types.js'; -import { UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION } from './const.js'; +import { UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS } from './const.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -32,6 +32,6 @@ export class UmbWorkspaceEntityIsNewCondition export const manifest: UmbExtensionManifest = { type: 'condition', name: 'Workspace Entity Is New Condition', - alias: UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION, + alias: UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS, api: UmbWorkspaceEntityIsNewCondition, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts index ea06b69196..9709d9c758 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts @@ -1,6 +1,6 @@ import { UMB_CONTENT_COLLECTION_WORKSPACE_CONTEXT } from '../../content/collection/content-collection-workspace.context-token.js'; import type { WorkspaceHasCollectionConditionConfig } from './types.js'; -import { UMB_WORKSPACE_HAS_COLLECTION_CONDITION } from './const.js'; +import { UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS } from './const.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -29,6 +29,6 @@ export class UmbWorkspaceHasCollectionCondition export const manifest: UmbExtensionManifest = { type: 'condition', name: 'Workspace Has Collection Condition', - alias: UMB_WORKSPACE_HAS_COLLECTION_CONDITION, + alias: UMB_WORKSPACE_HAS_COLLECTION_CONDITION_ALIAS, api: UmbWorkspaceHasCollectionCondition, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts index a568fc8775..1bf6c4d77c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts @@ -1,4 +1,5 @@ export * from './components/index.js'; +export * from './conditions/const.js'; export * from './contexts/index.js'; export * from './controllers/index.js'; export * from './data-manager/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/menu/manifests.ts index 7fc04fe562..bcd1dda1ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/menu/manifests.ts @@ -1,3 +1,5 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; + export const manifests: Array = [ { type: 'menuItem', @@ -19,7 +21,7 @@ export const manifests: Array = [ api: () => import('./data-type-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.DataType', }, ], @@ -31,7 +33,7 @@ export const manifests: Array = [ name: 'Data Type Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.DataType', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/folder/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/folder/workspace/manifests.ts index e1b8108bc0..78447f41ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/folder/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/folder/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DATA_TYPE_FOLDER_ENTITY_TYPE } from '../../../entity.js'; import { UMB_DATA_TYPE_FOLDER_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DATA_TYPE_FOLDER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts index 06c4007e1e..c83c6cb153 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DATA_TYPE_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -25,7 +26,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DATA_TYPE_WORKSPACE_ALIAS, }, ], @@ -43,7 +44,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DATA_TYPE_WORKSPACE_ALIAS, }, ], @@ -61,7 +62,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DATA_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/menu-item/manifests.ts index 447eb8727b..f3a87bd76a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/menu-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/menu-item/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DICTIONARY_ENTITY_TYPE } from '../entity.js'; import { UMB_DICTIONARY_TREE_ALIAS } from '../tree/index.js'; import { UMB_TRANSLATION_MENU_ALIAS } from '@umbraco-cms/backoffice/translation'; @@ -25,7 +26,7 @@ export const manifests: Array = [ api: () => import('./dictionary-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Dictionary', }, ], @@ -37,7 +38,7 @@ export const manifests: Array = [ name: 'Data Type Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Dictionary', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/manifests.ts index a2618139f2..a78e4a8ef3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DICTIONARY_ENTITY_TYPE } from '../entity.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DICTIONARY_WORKSPACE_ALIAS, }, ], @@ -46,7 +47,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DICTIONARY_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/workspace/manifests.ts index af23fb61dd..52f6f4e34f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/tree/folder/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_BLUEPRINT_FOLDER_ENTITY_TYPE } from '../../../entity.js'; import { UMB_DOCUMENT_BLUEPRINT_FOLDER_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_BLUEPRINT_FOLDER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts index f7f68a32bf..ba2884d0e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_BLUEPRINT_ENTITY_TYPE } from '../entity.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_BLUEPRINT_WORKSPACE_ALIAS, }, ], @@ -47,7 +48,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_BLUEPRINT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/menu/manifests.ts index 2e98f9edd5..73d7506420 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_TYPE_TREE_ALIAS } from '../tree/index.js'; export const manifests: Array = [ @@ -20,7 +21,7 @@ export const manifests: Array = [ api: () => import('./document-type-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.DocumentType', }, ], @@ -32,7 +33,7 @@ export const manifests: Array = [ name: 'Document Type Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.DocumentType', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/workspace/manifests.ts index 52c211ec2f..d0a5f120c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/folder/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE } from '../../../entity.js'; import { UMB_DOCUMENT_TYPE_FOLDER_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_TYPE_FOLDER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/manifests.ts index f4230143a2..028faf033a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_TYPE_COMPOSITION_REPOSITORY_ALIAS } from '../repository/composition/index.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_TYPE_WORKSPACE_ALIAS, }, ], @@ -45,7 +46,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_TYPE_WORKSPACE_ALIAS, }, ], @@ -63,7 +64,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_TYPE_WORKSPACE_ALIAS, }, ], @@ -81,7 +82,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_TYPE_WORKSPACE_ALIAS, }, ], @@ -99,7 +100,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts index 1d1145d447..a842fa686c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_TREE_ALIAS } from '../tree/index.js'; export const UMB_CONTENT_MENU_ALIAS = 'Umb.Menu.Content'; @@ -28,7 +29,7 @@ export const manifests: Array = [ api: () => import('./document-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }, ], @@ -40,7 +41,7 @@ export const manifests: Array = [ name: 'Document Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/entity-action/manifests.ts index 88dcf25c5c..2bed9b0321 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/entity-action/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; import { UMB_USER_PERMISSION_DOCUMENT_ROLLBACK } from '../../user-permissions/index.js'; import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '../../workspace/index.js'; @@ -27,7 +28,7 @@ export const manifests: Array = [ /* Currently the rollback is tightly coupled to the workspace contexts so we only allow it to show up In the document workspace. */ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts index 0301ab190c..a79c270056 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts @@ -7,6 +7,7 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; import { UMB_DOCUMENT_WORKSPACE_ALIAS } from './constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; import { UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION } from '@umbraco-cms/backoffice/content'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const manifests: Array = [ { @@ -31,7 +32,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, { @@ -52,7 +53,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, { @@ -73,7 +74,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, ], @@ -92,7 +93,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, { @@ -114,7 +115,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, { @@ -134,7 +135,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/extension-insights/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/extension-insights/workspace/manifests.ts index 1fafb06a69..6cd95677fb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/extension-insights/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/extension-insights/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_EXTENSION_COLLECTION_ALIAS } from '../collection/manifests.js'; import { UMB_EXTENSION_ROOT_ENTITY_TYPE } from '../entity.js'; import { UMB_EXTENSION_ROOT_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_EXTENSION_ROOT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/manifests.ts index 4767edb2f9..c15d3fa682 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/manifests.ts @@ -7,6 +7,7 @@ import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as globalContextManifests } from './global-contexts/manifests.js'; import { manifest as conditionsManifest } from './conditions/multiple-app-languages.condition.js'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const manifests: Array = [ ...repositoryManifests, @@ -25,7 +26,7 @@ export const manifests: Array = [ api: () => import('./permissions/language-access.workspace-context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Document', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/menu/manifests.ts index a5349c78d8..957ef86f02 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/menu/manifests.ts @@ -1,3 +1,5 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; + export const manifests: Array = [ { type: 'menuItem', @@ -18,7 +20,7 @@ export const manifests: Array = [ api: () => import('./language-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Language', }, ], @@ -30,7 +32,7 @@ export const manifests: Array = [ name: 'Language Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Language', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/manifests.ts index 08d9f3509f..e0fef2efe7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_LANGUAGE_COLLECTION_ALIAS } from '../../collection/index.js'; import { UMB_LANGUAGE_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_LANGUAGE_ROOT_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias:UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_LANGUAGE_ROOT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts index c65b6e0a19..b0e3508017 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_LANGUAGE_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -25,7 +26,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_LANGUAGE_WORKSPACE_ALIAS, }, ], @@ -43,7 +44,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_LANGUAGE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/manifests.ts index 57a6885292..1ca41da4d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/manifests.ts @@ -1,3 +1,5 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; + const UMB_LOG_VIEWER_WORKSPACE_ALIAS = 'Umb.Workspace.LogViewer'; export const manifests: Array = [ @@ -24,7 +26,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_LOG_VIEWER_WORKSPACE_ALIAS, }, ], @@ -42,7 +44,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_LOG_VIEWER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu/manifests.ts index db67666029..7295ae54db 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEDIA_TYPE_TREE_ALIAS } from '../tree/index.js'; export const manifests: Array = [ @@ -20,7 +21,7 @@ export const manifests: Array = [ api: () => import('./media-type-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.MediaType', }, ], @@ -32,7 +33,7 @@ export const manifests: Array = [ name: 'Media Type Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.MediaType', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/folder/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/folder/workspace/manifests.ts index afc7e22354..00f6310476 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/folder/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/folder/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE } from '../../../entity.js'; import { UMB_MEDIA_TYPE_FOLDER_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_TYPE_FOLDER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts index 55c5dd0374..5fd768d67b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEDIA_TYPE_COMPOSITION_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_MEDIA_TYPE_WORKSPACE_ALIAS } from './constants.js'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_TYPE_WORKSPACE_ALIAS, }, ], @@ -45,7 +46,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_TYPE_WORKSPACE_ALIAS, }, ], @@ -63,7 +64,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts index c1114d7815..1681aedd98 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEDIA_TREE_ALIAS } from '../tree/index.js'; import { UMB_MEDIA_MENU_ALIAS } from './constants.js'; @@ -27,7 +28,7 @@ export const manifests: Array = [ api: () => import('./media-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Media', }, ], @@ -39,7 +40,7 @@ export const manifests: Array = [ name: 'Media Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Media', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts index 37161fba4b..a48480ee07 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts @@ -1,6 +1,7 @@ import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; import { UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION } from '@umbraco-cms/backoffice/content'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_MEDIA_WORKSPACE_ALIAS = 'Umb.Workspace.Media'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_WORKSPACE_ALIAS, }, { @@ -48,7 +49,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_WORKSPACE_ALIAS, }, { @@ -69,7 +70,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_WORKSPACE_ALIAS, }, ], @@ -87,7 +88,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEDIA_WORKSPACE_ALIAS, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-root/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-root/manifests.ts index 25634ebe02..a066e19b59 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-root/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group-root/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEMBER_GROUP_COLLECTION_ALIAS } from '../../collection/manifests.js'; import { UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_MEMBER_GROUP_ROOT_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_GROUP_ROOT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/manifests.ts index 3f82c51f36..ebfd58fccb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/manifests.ts @@ -5,6 +5,7 @@ import type { ManifestWorkspaceView, } from '@umbraco-cms/backoffice/workspace'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_MEMBER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.MemberGroup'; @@ -33,7 +34,7 @@ const workspaceActions: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, }, ], @@ -54,7 +55,7 @@ export const workspaceViews: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_GROUP_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/menu/manifests.ts index 69aea21501..39f0b5b1e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEMBER_TYPE_TREE_ALIAS } from '../tree/index.js'; export const manifests: Array = [ @@ -20,7 +21,7 @@ export const manifests: Array = [ api: () => import('./member-type-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.MemberType', }, ], @@ -32,7 +33,7 @@ export const manifests: Array = [ name: 'Member Type Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.MemberType', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts index c0d1aea14d..1d9925c118 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS } from '../repository/index.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_TYPE_WORKSPACE_ALIAS, }, ], @@ -45,7 +46,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member-root/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member-root/manifests.ts index afe1a7fa56..bfc4101ec5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member-root/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member-root/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_MEMBER_COLLECTION_ALIAS } from '../../collection/manifests.js'; import { UMB_MEMBER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_MEMBER_ROOT_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_ROOT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/manifests.ts index dc4946fb60..cb8be75248 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/manifests.ts @@ -6,6 +6,7 @@ import type { } from '@umbraco-cms/backoffice/workspace'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import { UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION } from '@umbraco-cms/backoffice/content'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_MEMBER_WORKSPACE_ALIAS = 'Umb.Workspace.Member'; @@ -34,7 +35,7 @@ const workspaceActions: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_WORKSPACE_ALIAS, }, ], @@ -55,7 +56,7 @@ export const workspaceViews: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_WORKSPACE_ALIAS, }, { @@ -76,7 +77,7 @@ export const workspaceViews: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_MEMBER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/manifests.ts index 33ac0d2a59..bbf2a517eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/manifests.ts @@ -1,3 +1,5 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; + export const UMB_RELATION_TYPE_WORKSPACE_ALIAS = 'Umb.Workspace.RelationType'; export const manifests: Array = [ @@ -24,7 +26,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_RELATION_TYPE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/workspace/manifests.ts index 54a076ba06..a3880d3329 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/workspace/manifests.ts @@ -1,4 +1,5 @@ import { UMB_RELATION_TYPE_COLLECTION_ALIAS } from '@umbraco-cms/backoffice/relation-type'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const manifests: Array = [ { @@ -24,7 +25,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.RelationsRoot', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/menu/manifests.ts index 9014ce1386..de2147b6f0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_PARTIAL_VIEW_TREE_ALIAS } from '../tree/index.js'; export const manifests: Array = [ @@ -20,7 +21,7 @@ export const manifests: Array = [ api: () => import('./partial-view-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.PartialView', }, ], @@ -32,7 +33,7 @@ export const manifests: Array = [ name: 'Partial View Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.PartialView', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts index ae6628e08c..7e21cc0506 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts @@ -1,4 +1,5 @@ import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_PARTIAL_VIEW_WORKSPACE_ALIAS = 'Umb.Workspace.PartialView'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_PARTIAL_VIEW_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/menu/manifests.ts index 8b5c8890a8..9dd63daaa8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_SCRIPT_TREE_ALIAS } from '../tree/index.js'; export const UMB_SCRIPT_MENU_ITEM_ALIAS = 'Umb.MenuItem.Script'; @@ -21,7 +22,7 @@ export const manifests: Array = [ api: () => import('./script-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Script', }, ], @@ -33,7 +34,7 @@ export const manifests: Array = [ name: 'Script Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Script', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/manifests.ts index 1af7a9adc7..13664d8a9c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_SCRIPT_ENTITY_TYPE } from '../entity.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -28,7 +29,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_SCRIPT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/menu/manifests.ts index 80e7c335e3..1a74c5f0f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_STYLESHEET_TREE_ALIAS } from '../tree/index.js'; export const manifests: Array = [ @@ -20,7 +21,7 @@ export const manifests: Array = [ api: () => import('./stylesheet-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Stylesheet', }, ], @@ -32,7 +33,7 @@ export const manifests: Array = [ name: 'Stylesheet Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Stylesheet', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index e7e74233ea..98911276c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -1,4 +1,5 @@ import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_STYLESHEET_WORKSPACE_ALIAS = 'Umb.Workspace.Stylesheet'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_STYLESHEET_WORKSPACE_ALIAS, }, ], @@ -44,7 +45,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_STYLESHEET_WORKSPACE_ALIAS, }, ], @@ -62,7 +63,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_STYLESHEET_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/menu/manifests.ts index 17f3a60f38..ab40f89560 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_TEMPLATE_TREE_ALIAS } from '../tree/index.js'; export const manifests: Array = [ @@ -21,7 +22,7 @@ export const manifests: Array = [ api: () => import('./template-menu-structure.context.js'), conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Template', }, ], @@ -33,7 +34,7 @@ export const manifests: Array = [ name: 'Template Breadcrumb Workspace Footer App', conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: 'Umb.Workspace.Template', }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/manifests.ts index 3fb187abfa..fc2b33e8ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/manifests.ts @@ -1,4 +1,5 @@ import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_TEMPLATE_WORKSPACE_ALIAS = 'Umb.Workspace.Template'; @@ -27,7 +28,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_TEMPLATE_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-root/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-root/manifests.ts index 3a269c71ff..0d528f9fc7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-root/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-root/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../../collection/index.js'; import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_USER_GROUP_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/manifests.ts index 6eacae864d..3a2e096501 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/manifests.ts @@ -1,4 +1,5 @@ import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.UserGroup'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_USER_GROUP_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-root/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-root/manifests.ts index 90662322da..44217e9ba9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-root/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-root/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_USER_COLLECTION_ALIAS } from '../../collection/constants.js'; import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_USER_ROOT_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_USER_ROOT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/manifests.ts index 3e96474084..1149050381 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_USER_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/manifests.ts index 1bd1cbc0e0..c837a613e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_WEBHOOK_COLLECTION_ALIAS } from '../../collection/manifests.js'; import { UMB_WEBHOOK_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_WEBHOOK_ROOT_WORKSPACE_ALIAS } from './constants.js'; @@ -26,7 +27,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_WEBHOOK_ROOT_WORKSPACE_ALIAS, }, ], diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/manifests.ts index 4bc1e0757d..ae338f664e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_WEBHOOK_ENTITY_TYPE, UMB_WEBHOOK_WORKSPACE_ALIAS } from '../../entity.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -25,7 +26,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_WEBHOOK_WORKSPACE_ALIAS, }, ], @@ -43,7 +44,7 @@ export const manifests: Array = [ }, conditions: [ { - alias: 'Umb.Condition.WorkspaceAlias', + alias: UMB_WORKSPACE_CONDITION_ALIAS, match: UMB_WEBHOOK_WORKSPACE_ALIAS, }, ], From 928a3352bf797927d11e3afb41d73bc702f18232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 10:33:03 +0200 Subject: [PATCH 060/246] property editor ui name, using label value --- .../libs/localization-api/localization.controller.ts | 5 +++-- .../extensions/property-editor-ui-element.interface.ts | 2 +- .../core/property/property/property.element.ts | 10 +++++----- .../text-box/property-editor-ui-text-box.element.ts | 6 +++--- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts index 587f7b14d8..d855db82a1 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts @@ -109,8 +109,9 @@ export class UmbLocalizationController(key: K, ...args: FunctionParams): string { if (!this.#usedKeys.includes(key)) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts index 483b90bcf8..58163db2d9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/extensions/property-editor-ui-element.interface.ts @@ -1,7 +1,7 @@ import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; export interface UmbPropertyEditorUiElement extends HTMLElement { - alias?: string; + name?: string; value?: unknown; config?: UmbPropertyEditorConfigCollection; mandatory?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts index a6a4d719f8..1ec36a2abe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts @@ -182,9 +182,6 @@ export class UmbPropertyElement extends UmbLitElement { this.#propertyContext.alias, (alias) => { this._alias = alias; - if (this._element) { - this._element.alias = alias; - } }, null, ); @@ -193,6 +190,9 @@ export class UmbPropertyElement extends UmbLitElement { this.#propertyContext.label, (label) => { this._label = label; + if (this._element) { + this._element.name = label; + } }, null, ); @@ -297,9 +297,9 @@ export class UmbPropertyElement extends UmbLitElement { if (this._element) { this._element.addEventListener('change', this._onPropertyEditorChange as any as EventListener); this._element.addEventListener('property-value-change', this._onPropertyEditorChange as any as EventListener); - // No need to observe mandatory or alias, as we already do so and set it on the _element if present: [NL] + // No need to observe mandatory or label, as we already do so and set it on the _element if present: [NL] this._element.mandatory = this._mandatory; - this._element.alias = this._alias; + this._element.name = this._label; // No need for a controller alias, as the clean is handled via the observer prop: this.#valueObserver = this.observe( diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts index e0fb795227..7913e1a50c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.element.ts @@ -35,11 +35,11 @@ export class UmbPropertyEditorUITextBoxElement mandatoryMessage = UMB_VALIDATION_EMPTY_LOCALIZATION_KEY; /** - * The alias of this field. + * The name of this field. * @type {string} */ @property({ type: String }) - alias?: string; + name?: string; #defaultType: UuiInputTypeType = 'text'; @@ -79,7 +79,7 @@ export class UmbPropertyEditorUITextBoxElement override render() { return html` Date: Wed, 16 Oct 2024 10:53:41 +0200 Subject: [PATCH 061/246] fix live editing mode --- .../block/context/block-manager.context.ts | 2 +- .../workspace/block-workspace.context.ts | 21 +++++++++++-------- .../element-property-dataset.context.ts | 1 - 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index c650cee4c0..59109b8945 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -78,7 +78,7 @@ export abstract class UmbBlockManagerContext< setEditorConfiguration(configs: UmbPropertyEditorConfigCollection) { this._editorConfiguration.setValue(configs); if (this._liveEditingMode.getValue() === undefined) { - this._liveEditingMode.setValue(configs.getValueByAlias('liveEditingMode')); + this._liveEditingMode.setValue(configs.getValueByAlias('useLiveEditing')); } } getEditorConfiguration(): UmbPropertyEditorConfigCollection | undefined { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index df8349a9c3..4ea9f4370d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -45,6 +45,7 @@ export class UmbBlockWorkspaceContext; #liveEditingMode?: boolean; #initialLayout?: LayoutDataType; @@ -87,13 +88,13 @@ export class UmbBlockWorkspaceContext { this.#blockManager = manager; - this.observe( + this.#liveEditingModePromise = this.observe( manager.liveEditingMode, (liveEditingMode) => { this.#liveEditingMode = liveEditingMode; }, 'observeLiveEditingMode', - ); + ).asPromise(); this.observe( observeMultiple([ @@ -212,6 +213,7 @@ export class UmbBlockWorkspaceContext { - console.log('props', props); const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) })); this.#propertyVariantIdMap.setValue(map); // Resolve promise, to let the once waiting on this know. From f001e168c975d9064a3fac760dc971d617f21ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 10:55:08 +0200 Subject: [PATCH 062/246] correct config field alias to 'useLiveEditing' --- .../src/packages/block/block/context/block-manager.context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index e7aae5b4e3..abf7083a70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -75,7 +75,7 @@ export abstract class UmbBlockManagerContext< setEditorConfiguration(configs: UmbPropertyEditorConfigCollection) { this._editorConfiguration.setValue(configs); if (this._liveEditingMode.getValue() === undefined) { - this._liveEditingMode.setValue(configs.getValueByAlias('liveEditingMode')); + this._liveEditingMode.setValue(configs.getValueByAlias('useLiveEditing')); } } getEditorConfiguration(): UmbPropertyEditorConfigCollection | undefined { From f99b542ece1bc741683ce6b5e89efb91d89625b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 11:40:04 +0200 Subject: [PATCH 063/246] expose button for no content editor block --- .../block-grid-block-inline.element.ts | 13 +------- .../block-grid-block.element.ts | 30 ++++++++++++++++++- .../block/context/block-entry.context.ts | 4 +-- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 33dde6ab6c..82e3f4333f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -48,9 +48,6 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { @property({ attribute: false }) content?: UmbBlockDataType; - @state() - private _exposed?: boolean; - @state() _inlineProperty?: UmbPropertyTypeModel; @@ -95,14 +92,6 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { 'observeProperties', ); - this.observe( - this.#workspaceContext.exposed, - (exposed) => { - this._exposed = exposed; - }, - 'observeExposed', - ); - this.observe( context.content.structure.ownerContentTypeName, (name) => { @@ -174,7 +163,7 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { } #renderInside() { - if (this._exposed === false) { + if (this.unpublished === true) { return html` { + this.#context = context; + this.observe(context.contentElementTypeName, (name) => { + this._ownerContentTypeName = name; + }); + }); + } + + #expose = () => { + this.#context?.expose(); + }; + override render() { return html` + ${this.config?.showContentEdit === false && this.unpublished + ? html` + + + ` + : nothing} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts index 90897490a7..1e5e0cd222 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts @@ -46,10 +46,10 @@ export abstract class UmbBlockEntryContext< #contentKey?: string; #variantId = new UmbClassState(undefined); - protected _variantId = this.#variantId.asObservable(); + protected readonly _variantId = this.#variantId.asObservable(); #hasExpose = new UmbBooleanState(undefined); - hasExpose = this.#hasExpose.asObservable(); + readonly hasExpose = this.#hasExpose.asObservable(); public readonly readOnlyState = new UmbReadOnlyVariantStateManager(this); From f66990551cb6a9989a649ffdaae6a1ea0d5da35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 11:50:56 +0200 Subject: [PATCH 064/246] general expose button for grid --- .../block-grid-block.element.ts | 27 ----------- .../block-grid-entry.element.ts | 45 ++++++++++++++----- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 85750a34c8..53d7cf2bf3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -14,8 +14,6 @@ import '../ref-grid-block/index.js'; @customElement('umb-block-grid-block') export class UmbBlockGridBlockElement extends UmbLitElement { // - #context?: typeof UMB_BLOCK_GRID_ENTRY_CONTEXT.TYPE; - @property({ attribute: false }) label?: string; @@ -31,35 +29,10 @@ export class UmbBlockGridBlockElement extends UmbLitElement { @property({ attribute: false }) content?: UmbBlockDataType; - @state() - _ownerContentTypeName?: string; - - constructor() { - super(); - this.consumeContext(UMB_BLOCK_GRID_ENTRY_CONTEXT, (context) => { - this.#context = context; - this.observe(context.contentElementTypeName, (name) => { - this._ownerContentTypeName = name; - }); - }); - } - - #expose = () => { - this.#context?.expose(); - }; - override render() { return html` - ${this.config?.showContentEdit === false && this.unpublished - ? html` - - - ` - : nothing} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 8ca0d13b97..211b8450d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -61,6 +61,9 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper @state() _contentTypeAlias?: string; + @state() + _contentTypeName?: string; + @state() _columnSpan?: number; @@ -325,6 +328,15 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper }, 'contentElementTypeAlias', ); + this.observe( + this.#context.contentElementTypeName, + (contentElementTypeName) => { + if (contentElementTypeName) { + this._contentTypeName = contentElementTypeName; + } + }, + 'contentElementTypeName', + ); this.#callUpdateInlineCreateButtons(); } @@ -336,6 +348,10 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper } } + #expose = () => { + this.#context.expose(); + }; + #callUpdateInlineCreateButtons() { clearTimeout(this.#renderTimeout); this.#renderTimeout = setTimeout(this.#updateInlineCreateButtons, 100) as unknown as number; @@ -481,20 +497,25 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper } #renderEditAction() { - return html` - ${this._showContentEdit && this._workspaceEditContentPath + return this._showContentEdit && this._workspaceEditContentPath + ? html` + + ${this._contentInvalid + ? html`!` + : nothing} + ` + : this._showContentEdit === false && this._exposed === false ? html` - - ${this._contentInvalid - ? html`!` - : nothing} - ` - : nothing} - `; + >` + : nothing; } #renderEditSettingsAction() { From dbca6ef78dc246537420b542ac4f91cd16493090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 11:54:36 +0200 Subject: [PATCH 065/246] block list entry expose ability --- .../block-list-entry.element.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 342e96082e..028fe33082 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -53,6 +53,9 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper @state() _contentTypeAlias?: string; + @state() + _contentTypeName?: string; + @state() _showContentEdit = false; @state() @@ -247,8 +250,21 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper }, 'contentElementTypeAlias', ); + this.observe( + this.#context.contentElementTypeName, + (contentElementTypeName) => { + if (contentElementTypeName) { + this._contentTypeName = contentElementTypeName; + } + }, + 'contentElementTypeName', + ); } + #expose = () => { + this.#context.expose(); + }; + #extensionSlotFilterMethod = (manifest: ManifestBlockEditorCustomView) => { if ( manifest.forContentTypeAlias && @@ -302,7 +318,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper } #renderEditContentAction() { - return html` ${this._showContentEdit && this._workspaceEditContentPath + return this._showContentEdit && this._workspaceEditContentPath ? html`!` : nothing} ` - : nothing}`; + : this._showContentEdit === false && this._exposed === false + ? html`` + : nothing; } #renderEditSettingsAction() { From 0bb54c6af6d789c33427c47ffee549f7f17ed807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 11:58:16 +0200 Subject: [PATCH 066/246] clean up --- .../components/block-grid-block/block-grid-block.element.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 53d7cf2bf3..3cf7b091f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -1,6 +1,5 @@ -import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { css, customElement, html, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; From 5493c0a2a13afdbe924daf1ccf00a93ceaa91f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 12:03:35 +0200 Subject: [PATCH 067/246] implement expose button for rte block --- .../block-rte-entry.element.ts | 147 +++++++++++++----- 1 file changed, 111 insertions(+), 36 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index f835c064c1..96b7c0de0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -1,7 +1,7 @@ import { UMB_BLOCK_RTE, type UmbBlockRteLayoutModel } from '../../types.js'; import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { html, css, property, state, customElement, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { @@ -11,6 +11,8 @@ import type { import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import '../ref-rte-block/index.js'; +import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; +import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; /** * @class UmbBlockRteEntryElement @@ -26,6 +28,16 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert if (!value) return; this._contentKey = value; this.#context.setContentKey(value); + + new UmbObserveValidationStateController( + this, + `$.contentData[${UmbDataPathBlockElementDataQuery({ key: value })}]`, + (hasMessages) => { + this._contentInvalid = hasMessages; + this._blockViewProps.contentInvalid = hasMessages; + }, + 'observeMessagesForContent', + ); } private _contentKey?: string | undefined; @@ -55,12 +67,23 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert @state() _contentElementTypeAlias?: string; + @state() + _contentTypeName?: string; + @state() _blockViewProps: UmbBlockEditorCustomViewProperties = { contentKey: undefined!, config: { showContentEdit: false, showSettingsEdit: false }, }; // Set to undefined cause it will be set before we render. + // 'content-invalid' attribute is used for styling purpose. + @property({ type: Boolean, attribute: 'content-invalid', reflect: true }) + _contentInvalid?: boolean; + + // 'settings-invalid' attribute is used for styling purpose. + @property({ type: Boolean, attribute: 'settings-invalid', reflect: true }) + _settingsInvalid?: boolean; + #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; this.requestUpdate('_blockViewProps'); @@ -72,17 +95,36 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert // We do not have index for RTE Blocks at the moment. this.#context.setIndex(0); - this.observe(this.#context.showContentEdit, (showContentEdit) => { - this._showContentEdit = showContentEdit; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showContentEdit } }); - }); - this.observe(this.#context.settingsElementTypeKey, (key) => { - this._hasSettings = !!key; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showSettingsEdit: !!key } }); - }); - this.observe(this.#context.contentElementTypeAlias, (alias) => { - this._contentElementTypeAlias = alias; - }); + this.observe( + this.#context.showContentEdit, + (showContentEdit) => { + this._showContentEdit = showContentEdit; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showContentEdit } }); + }, + null, + ); + this.observe( + this.#context.settingsElementTypeKey, + (key) => { + this._hasSettings = !!key; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showSettingsEdit: !!key } }); + }, + null, + ); + this.observe( + this.#context.contentElementTypeAlias, + (alias) => { + this._contentElementTypeAlias = alias; + }, + null, + ); + this.observe( + this.#context.contentElementTypeName, + (contentElementTypeName) => { + this._contentTypeName = contentElementTypeName; + }, + null, + ); this.observe( this.#context.blockType, (blockType) => { @@ -126,8 +168,6 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert this.#observeData(); - // TODO: Implement validation for RTE Blocks: [NL] - /* this.observe( this.#context.settingsKey, (settingsKey) => { @@ -147,7 +187,7 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert }, null, ); - */ + this.observe( this.#context.workspaceEditContentPath, (path) => { @@ -188,15 +228,6 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert this.setAttribute('contenteditable', 'false'); } - #renderRefBlock() { - return html``; - } - readonly #filterBlockCustomViews = (manifest: ManifestBlockEditorCustomView) => { const elementTypeAlias = this._contentElementTypeAlias ?? ''; const isForBlockEditor = @@ -206,6 +237,10 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert return isForBlockEditor && isForContentTypeAlias; }; + #expose = () => { + this.#context.expose(); + }; + #renderBlock() { return html`
      @@ -217,22 +252,62 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert single> ${this.#renderRefBlock()} - - ${this._showContentEdit && this._workspaceEditContentPath - ? html` - - ` - : ''} - ${this._hasSettings && this._workspaceEditSettingsPath - ? html` - - ` - : ''} - + ${this.#renderEditAction()} ${this.#renderEditSettingsAction()} + ${!this._showContentEdit && this._contentInvalid + ? html`!` + : nothing}
      `; } + #renderRefBlock() { + return html``; + } + + #renderEditAction() { + return this._showContentEdit && this._workspaceEditContentPath + ? html` + + ${this._contentInvalid + ? html`!` + : nothing} + ` + : this._showContentEdit === false && this._exposed === false + ? html`` + : nothing; + } + + #renderEditSettingsAction() { + return html` + ${this._hasSettings && this._workspaceEditSettingsPath + ? html` + + ${this._settingsInvalid + ? html`!` + : nothing} + ` + : nothing} + `; + } + override render() { return this.#renderBlock(); } From c79001a7b6a2cea3b1d8e50132fa77f0bd3d6d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 12:03:41 +0200 Subject: [PATCH 068/246] remove if --- .../components/block-grid-entry/block-grid-entry.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 211b8450d7..4e39f774d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -331,9 +331,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper this.observe( this.#context.contentElementTypeName, (contentElementTypeName) => { - if (contentElementTypeName) { - this._contentTypeName = contentElementTypeName; - } + this._contentTypeName = contentElementTypeName; }, 'contentElementTypeName', ); From 704d2bea78e98d8346845712f24729699fd353a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 12:04:05 +0200 Subject: [PATCH 069/246] clean up --- .../components/block-list-entry/block-list-entry.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 028fe33082..6a4024077a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -253,9 +253,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper this.observe( this.#context.contentElementTypeName, (contentElementTypeName) => { - if (contentElementTypeName) { - this._contentTypeName = contentElementTypeName; - } + this._contentTypeName = contentElementTypeName; }, 'contentElementTypeName', ); From 288ba4e0a6976007973fb80904dbbf53076b80be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 13:13:35 +0200 Subject: [PATCH 070/246] destroy block list elements --- .../block-list-entry/block-list-entry.element.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 6a4024077a..336c7e0710 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -1,6 +1,6 @@ import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js'; import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; import '../ref-list-block/index.js'; @@ -283,7 +283,8 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper .unpublished=${!this._exposed} .config=${this._blockViewProps.config} .content=${this._blockViewProps.content} - .settings=${this._blockViewProps.settings}>`; + .settings=${this._blockViewProps.settings} + ${umbDestroyOnDisconnect()}>`; } #renderInlineBlock() { @@ -293,7 +294,8 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper .unpublished=${!this._exposed} .config=${this._blockViewProps.config} .content=${this._blockViewProps.content} - .settings=${this._blockViewProps.settings}>`; + .settings=${this._blockViewProps.settings} + ${umbDestroyOnDisconnect()}>`; } #renderBlock() { From b76e95dd62662da3df83f38b8500b6c67346f946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 13:19:42 +0200 Subject: [PATCH 071/246] liveEditing value can be undefined, therefor custom promise --- .../block/block/workspace/block-workspace.context.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index 4ea9f4370d..e96c79a0d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -45,7 +45,10 @@ export class UmbBlockWorkspaceContext; + #liveEditingModePromiseResolve?: (value: unknown) => void; + #liveEditingModePromise = new Promise((resolve) => { + this.#liveEditingModePromiseResolve = resolve; + }); #liveEditingMode?: boolean; #initialLayout?: LayoutDataType; @@ -88,13 +91,14 @@ export class UmbBlockWorkspaceContext { this.#blockManager = manager; - this.#liveEditingModePromise = this.observe( + this.observe( manager.liveEditingMode, (liveEditingMode) => { - this.#liveEditingMode = liveEditingMode; + this.#liveEditingMode = liveEditingMode ?? false; + this.#liveEditingModePromiseResolve?.(); }, 'observeLiveEditingMode', - ).asPromise(); + ); this.observe( observeMultiple([ From d95cfbc3319bd5794fac8238d142072b2e981fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 13:20:49 +0200 Subject: [PATCH 072/246] remove await for live editing config --- .../block/block/workspace/block-workspace.context.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index e96c79a0d3..eeb1825e0f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -45,10 +45,6 @@ export class UmbBlockWorkspaceContext void; - #liveEditingModePromise = new Promise((resolve) => { - this.#liveEditingModePromiseResolve = resolve; - }); #liveEditingMode?: boolean; #initialLayout?: LayoutDataType; @@ -95,7 +91,6 @@ export class UmbBlockWorkspaceContext { this.#liveEditingMode = liveEditingMode ?? false; - this.#liveEditingModePromiseResolve?.(); }, 'observeLiveEditingMode', ); @@ -217,7 +212,6 @@ export class UmbBlockWorkspaceContext Date: Wed, 16 Oct 2024 12:37:11 +0100 Subject: [PATCH 073/246] Bugfix: TinyMCE anchor links without base URL (#2462) * Fixes TinyMCE anchor links without a base URL it was previously prefixing the `href` with the current backoffice page URL. * Code tidy-up + remove unused code --- .../tiny-mce-multi-url-picker.plugin.ts | 105 +++++++----------- .../plugins/tiny-mce-code-editor.plugin.ts | 10 +- 2 files changed, 48 insertions(+), 67 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/tiny-mce-plugin/tiny-mce-multi-url-picker.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/tiny-mce-plugin/tiny-mce-multi-url-picker.plugin.ts index 00046cc23c..6bdc8e54ff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/tiny-mce-plugin/tiny-mce-multi-url-picker.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/tiny-mce-plugin/tiny-mce-multi-url-picker.plugin.ts @@ -1,17 +1,19 @@ -import type { UmbLinkPickerModalValue } from '../link-picker-modal/link-picker-modal.token.js'; import { UMB_LINK_PICKER_MODAL } from '../link-picker-modal/link-picker-modal.token.js'; -import type { UmbLinkPickerLink } from '../link-picker-modal/types.js'; -import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbLinkPickerLink, UmbLinkPickerLinkType } from '../link-picker-modal/types.js'; +import type { UmbLinkPickerModalValue } from '../link-picker-modal/link-picker-modal.token.js'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; +import { UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { TinyMcePluginArguments } from '@umbraco-cms/backoffice/tiny-mce'; type AnchorElementAttributes = { - href?: string | null; - title?: string | null; - target?: string | null; 'data-anchor'?: string | null; - rel?: string | null; + href?: string | null; + target?: string | null; text?: string; + title?: string | null; + type?: UmbLinkPickerLinkType; + rel?: string | null; }; export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase { @@ -21,17 +23,9 @@ export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase constructor(args: TinyMcePluginArguments) { super(args); + const localize = new UmbLocalizationController(args.host); - // const editorEventSetupCallback = (buttonApi: { setEnabled: (state: boolean) => void }) => { - // const editorEventCallback = (eventApi: { element: Element}) => { - // buttonApi.setEnabled(eventApi.element.nodeName.toLowerCase() === 'a' && eventApi.element.hasAttribute('href')); - // }; - - // editor.on('NodeChange', editorEventCallback); - // return () => editor.off('NodeChange', editorEventCallback); - // }; - this.editor.ui.registry.addToggleButton('link', { icon: 'link', tooltip: localize.term('general_addEditLink'), @@ -57,39 +51,27 @@ export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase const selectedElm = this.editor.selection.getNode(); this.#anchorElement = this.editor.dom.getParent(selectedElm, 'a[href]') as HTMLAnchorElement; - const data: AnchorElementAttributes = { - text: this.#anchorElement - ? this.#anchorElement.innerText || (this.#anchorElement.textContent ?? '') - : this.editor.selection.getContent({ format: 'text' }), - href: this.#anchorElement?.getAttribute('href') ?? '', - target: this.#anchorElement?.target ?? '', - rel: this.#anchorElement?.rel ?? '', - }; - - if (selectedElm.nodeName === 'IMG') { - data.text = ' '; - } - if (!this.#anchorElement) { - this.#openLinkPicker({ name: this.editor.selection.getContent() }); + this.#openLinkPicker({ name: this.editor.selection.getContent({ format: 'text' }) }); return; } - //if we already have a link selected, we want to pass that data over to the dialog + let url = this.#anchorElement.getAttribute('href') ?? this.#anchorElement.href ?? ''; + + const queryString = this.#anchorElement.getAttribute('data-anchor') ?? ''; + if (queryString && url.endsWith(queryString)) { + url = url.substring(0, url.indexOf(queryString)); + } + const currentTarget: UmbLinkPickerLink = { name: this.#anchorElement.title || this.#anchorElement.textContent, target: this.#anchorElement.target, - queryString: `${this.#anchorElement.search}${this.#anchorElement.hash}`, + queryString: queryString, + type: (this.#anchorElement.type as UmbLinkPickerLinkType) ?? 'external', + unique: url.includes('localLink:') ? url.substring(url.indexOf(':') + 1, url.indexOf('}')) : null, + url: url, }; - if (this.#anchorElement.href.includes('localLink:')) { - const href = this.#anchorElement.getAttribute('href')!; - currentTarget.unique = href.substring(href.indexOf(':') + 1, href.indexOf('}')); - } else if (this.#anchorElement.host.length) { - currentTarget.url = this.#anchorElement.protocol ? this.#anchorElement.protocol + '//' : undefined; - currentTarget.url += this.#anchorElement.host + this.#anchorElement.pathname; - } - this.#openLinkPicker(currentTarget); } @@ -112,35 +94,32 @@ export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase // TODO: This is a workaround for the issue where the link picker modal is returning a frozen object, and we need to extract the link into smaller parts to avoid the frozen object issue. this.#linkPickerData = { link: { ...linkPickerData.link } }; + this.#updateLink(); } - //Create a json obj used to create the attributes for the tag - // TODO => where has rel gone? #createElemAttributes() { - // Attribute 'name' because of linkPickerData. It should be 'title' . - const { name, ...linkPickerData } = this.#linkPickerData!.link; - const a: AnchorElementAttributes = Object.assign({}, linkPickerData); + const link = this.#linkPickerData!.link; - // always need to map back to href for tinymce to render correctly - // do this first as checking querystring below may modify the href property - if (this.#linkPickerData?.link.url) { - a.href = this.#linkPickerData.link.url; + const anchor: AnchorElementAttributes = { + href: link.url ?? '', + title: link.name ?? link.url ?? '', + target: link.target, + type: link.type ?? 'external', + rel: link.target === '_blank' ? 'noopener' : null, + }; + + if (link.queryString) { + anchor['data-anchor'] = link.queryString; + + if (link.queryString.startsWith('?')) { + anchor.href += !anchor.href ? '/' + link.queryString : link.queryString; + } else if (link.queryString.startsWith('#')) { + anchor.href += link.queryString; + } } - if (this.#linkPickerData?.link.name) { - a.title = name; - } - - if ( - this.#linkPickerData?.link.queryString?.startsWith('#') || - this.#linkPickerData?.link.queryString?.startsWith('?') - ) { - a['data-anchor'] = this.#linkPickerData?.link.queryString; - a.href += this.#linkPickerData?.link.queryString; - } - - return a; + return anchor; } #insertLink() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts index 54c16a3818..f524840f51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/plugins/tiny-mce-code-editor.plugin.ts @@ -25,13 +25,15 @@ export default class UmbTinyMceCodeEditorPlugin extends UmbTinyMcePluginBase { }, }); - if (!modal) return; + const value = await modal.onSubmit().catch(() => undefined); + if (!value) { + return; + } - const { content } = await modal.onSubmit(); - if (!content) { + if (!value.content) { this.editor.resetContent(); } else { - this.editor.setContent(content.toString()); + this.editor.setContent(value.content.toString()); } this.editor.dispatch('Change'); From c53cb49496c4e7bdae3112ce892cca9cfccb70b7 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 16 Oct 2024 14:13:57 +0200 Subject: [PATCH 074/246] Adjust Image Cropper handle (focal point) (#1021) * Adjust Image Cropper focal point to be consistent with Color Area handle * Make focus point focusable via keyboard * Update import of utils from uui * Make focal point accessible via keyboard * Move logic to function * Reset coords * Remove reset coords * Reset coords if focal point is updated to center * Format document * Set focal point property instead * Formatting * Fix warnings * Width and height * Remove added outline so we can see when focal point has focus via keyboard * Reset coords * Cleanup * Update import * Cleanup * Use UmbChangeEvent * Adjust elements * Import drag for uui * Cleanup styling * Cleanup * Remove unnecessary events * Container is HTMLElement * Check focal point updated * Fix conflicts after merge * Null check * Update correct element types * Revert to custom event * Cleanup console * Don't hide overflow, so focal point is not cut off on edges on image * Add margin top at actions so focal point doesn't overlap buttons * Top margin at actions * Crosshair cursor when focal point is not hidden * Cancel update focal point * Add move cursor to viewport image * Use crop label * Add missing label * Disable draggable of image as in old backoffice * Fix previous merge conflicts * Update src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Update src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Update src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Update src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> * Remove disconnectedCallback * Ignore in the debug element * Add custom event for focal point change * Import type * Replace with UmbImageCropChangeEvent * Use UmbFocalPointModel * Move set focal pont style to setter * Update custom event name * Localize focal point label * Fix import of UmbFocalPointModel type * Localize buttons * Update labels * Combine imports --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> --- .../input-image-cropper/crop-change.event.ts | 8 + .../focalpoint-change.event.ts | 13 + .../image-cropper-field.element.ts | 13 +- .../image-cropper-focus-setter.element.ts | 236 ++++++++++++------ .../image-cropper.element.ts | 27 +- .../components/input-image-cropper/index.ts | 2 + 6 files changed, 209 insertions(+), 90 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/crop-change.event.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/focalpoint-change.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/crop-change.event.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/crop-change.event.ts new file mode 100644 index 0000000000..0c9b076fba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/crop-change.event.ts @@ -0,0 +1,8 @@ +export class UmbImageCropChangeEvent extends Event { + public static readonly TYPE = 'imagecrop-change'; + + public constructor(args?: EventInit) { + // mimics the native change event + super(UmbImageCropChangeEvent.TYPE, { bubbles: false, composed: false, cancelable: false, ...args }); + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/focalpoint-change.event.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/focalpoint-change.event.ts new file mode 100644 index 0000000000..ba38c5e87f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/focalpoint-change.event.ts @@ -0,0 +1,13 @@ +import type { UmbFocalPointModel } from '../../types.js'; + +export class UmbFocalPointChangeEvent extends Event { + public static readonly TYPE = 'focalpoint-change'; + + public focalPoint: UmbFocalPointModel; + + public constructor(focalPoint: UmbFocalPointModel, args?: EventInit) { + // mimics the native change event + super(UmbFocalPointChangeEvent.TYPE, { bubbles: false, composed: false, cancelable: false, ...args }); + this.focalPoint = focalPoint; + } +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts index c330b50c43..3ca9812849 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts @@ -7,6 +7,8 @@ import type { UmbImageCropperCrops, UmbImageCropperFocalPoint, UmbImageCropperPropertyEditorValue, + UmbFocalPointChangeEvent, + UmbImageCropChangeEvent, } from './index.js'; import { css, customElement, html, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @@ -87,7 +89,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement { this.currentCrop = { ...this.crops[index] }; } - #onCropChange = (event: CustomEvent) => { + #onCropChange = (event: UmbImageCropChangeEvent) => { const target = event.target as UmbImageCropperElement; const value = target.value; @@ -102,8 +104,8 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement { this.#updateValue(); }; - #onFocalPointChange = (event: CustomEvent) => { - this.focalPoint = event.detail; + #onFocalPointChange = (event: UmbFocalPointChangeEvent) => { + this.focalPoint = { top: event.focalPoint.top, left: event.focalPoint.left }; this.#updateValue(); }; @@ -137,7 +139,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement { .src=${this.source} .value=${this.currentCrop} ?hideFocalPoint=${this.hideFocalPoint} - @change=${this.#onCropChange}> + @imagecrop-change=${this.#onCropChange}> `; } @@ -147,7 +149,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement { .focalPoint=${this.focalPoint} .src=${this.source} ?hideFocalPoint=${this.hideFocalPoint} - @change=${this.#onFocalPointChange}> + @focalpoint-change=${this.#onFocalPointChange}>
      ${this.renderActions()}
      `; @@ -200,6 +202,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement { #actions { display: flex; justify-content: space-between; + margin-top: 0.5rem; } umb-image-cropper-focus-setter { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts index 2760dbfae0..0963940875 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-focus-setter.element.ts @@ -1,45 +1,51 @@ -import type { UmbImageCropperFocalPoint } from './index.js'; +import { type UmbImageCropperFocalPoint, UmbFocalPointChangeEvent } from './index.js'; +import type { UmbFocalPointModel } from '../../types.js'; +import { drag } from '@umbraco-cms/backoffice/external/uui'; import { clamp } from '@umbraco-cms/backoffice/utils'; -import { css, customElement, html, nothing, property, query, LitElement } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, classMap, ifDefined, html, nothing, state, property, query } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; @customElement('umb-image-cropper-focus-setter') -export class UmbImageCropperFocusSetterElement extends LitElement { +export class UmbImageCropperFocusSetterElement extends UmbLitElement { @query('#image') imageElement!: HTMLImageElement; @query('#wrapper') - wrapperElement?: HTMLImageElement; + wrapperElement?: HTMLElement; @query('#focal-point') - focalPointElement!: HTMLImageElement; + focalPointElement!: HTMLElement; + + @state() + private _isDraggingGridHandle = false; + + @state() + private coords = { x: 0, y: 0 }; @property({ attribute: false }) - focalPoint: UmbImageCropperFocalPoint = { left: 0.5, top: 0.5 }; + set focalPoint(value) { + this.#focalPoint = value; + this.#setFocalPointStyle(this.#focalPoint.left, this.#focalPoint.top); + this.#onFocalPointUpdated(); + } + get focalPoint() { + return this.#focalPoint; + } + + #focalPoint: UmbImageCropperFocalPoint = { left: 0.5, top: 0.5 }; @property({ type: Boolean }) hideFocalPoint = false; + + @property({ type: Boolean, reflect: true }) + disabled = false; @property({ type: String }) src?: string; - #DOT_RADIUS = 6 as const; - - override disconnectedCallback() { - super.disconnectedCallback(); - this.#removeEventListeners(); - } - - protected override updated(_changedProperties: PropertyValueMap | Map): void { - super.updated(_changedProperties); - - if (this.hideFocalPoint) return; - - if (_changedProperties.has('focalPoint') && this.focalPointElement) { - this.focalPointElement.style.left = `calc(${this.focalPoint.left * 100}% - ${this.#DOT_RADIUS}px)`; - this.focalPointElement.style.top = `calc(${this.focalPoint.top * 100}% - ${this.#DOT_RADIUS}px)`; - } - } + #DOT_RADIUS = 8 as const; protected override update(changedProperties: PropertyValueMap | Map): void { super.update(changedProperties); @@ -61,8 +67,7 @@ export class UmbImageCropperFocusSetterElement extends LitElement { await this.updateComplete; // Wait for the @query to be resolved if (!this.hideFocalPoint) { - this.focalPointElement.style.left = `calc(${this.focalPoint.left * 100}% - ${this.#DOT_RADIUS}px)`; - this.focalPointElement.style.top = `calc(${this.focalPoint.top * 100}% - ${this.#DOT_RADIUS}px)`; + this.#setFocalPointStyle(this.focalPoint.left, this.focalPoint.top); } this.imageElement.onload = () => { @@ -78,73 +83,143 @@ export class UmbImageCropperFocusSetterElement extends LitElement { this.imageElement.style.height = '100%'; } + this.#resetCoords(); + this.imageElement.style.aspectRatio = `${imageAspectRatio}`; this.wrapperElement.style.aspectRatio = `${imageAspectRatio}`; }; + } - if (!this.hideFocalPoint) { - this.#addEventListeners(); + #onFocalPointUpdated() { + if (this.#isCentered(this.#focalPoint)) { + this.#resetCoords(); } } - async #addEventListeners() { - await this.updateComplete; // Wait for the @query to be resolved - this.imageElement?.addEventListener('mousedown', this.#onStartDrag); - window.addEventListener('mouseup', this.#onEndDrag); + #coordsToFactor(x: number, y: number) { + const top = (y / 100) / y * 50; + const left = (x / 100) / x * 50; + + return { top, left }; } - #removeEventListeners() { - this.imageElement?.removeEventListener('mousedown', this.#onStartDrag); - window.removeEventListener('mouseup', this.#onEndDrag); + #setFocalPoint(x: number, y: number, width: number, height: number) { + + const left = clamp((x / width), 0, 1); + const top = clamp((y / height), 0, 1); + + this.#coordsToFactor(x, y); + + const focalPoint = { left, top } as UmbFocalPointModel; + + console.log("setFocalPoint", focalPoint) + + this.dispatchEvent(new UmbFocalPointChangeEvent(focalPoint)); } - #onStartDrag = (event: MouseEvent) => { - event.preventDefault(); - window.addEventListener('mousemove', this.#onDrag); - }; - - #onEndDrag = (event: MouseEvent) => { - event.preventDefault(); - window.removeEventListener('mousemove', this.#onDrag); - }; - - #onDrag = (event: MouseEvent) => { - event.preventDefault(); - this.#onSetFocalPoint(event); - }; - - #onSetFocalPoint(event: MouseEvent) { - event.preventDefault(); - if (this.hideFocalPoint) return; - - if (!this.focalPointElement || !this.imageElement) return; - - const image = this.imageElement.getBoundingClientRect(); - - const x = clamp(event.clientX - image.left, 0, image.width); - const y = clamp(event.clientY - image.top, 0, image.height); - - const left = clamp(x / image.width, 0, 1); - const top = clamp(y / image.height, 0, 1); + #setFocalPointStyle(left: number, top: number) { + if (!this.focalPointElement) return; this.focalPointElement.style.left = `calc(${left * 100}% - ${this.#DOT_RADIUS}px)`; this.focalPointElement.style.top = `calc(${top * 100}% - ${this.#DOT_RADIUS}px)`; + } - this.dispatchEvent( - new CustomEvent('change', { - detail: { left, top }, - bubbles: false, - composed: false, - }), - ); + #isCentered(focalPoint: UmbImageCropperFocalPoint) { + if (!this.focalPoint) return; + + return focalPoint.left === 0.5 && focalPoint.top === 0.5; + } + + #resetCoords() { + if (!this.imageElement) return; + + // Init x and y coords from half of rendered image size, which is equavalient to focal point { left: 0.5, top: 0.5 }. + this.coords.x = this.imageElement?.clientWidth / 2; + this.coords.y = this.imageElement.clientHeight / 2; + } + + #handleGridDrag(event: PointerEvent) { + if (this.disabled || this.hideFocalPoint) return; + + const grid = this.wrapperElement; + const handle = this.focalPointElement; + + if (!grid) return; + + const { width, height } = grid.getBoundingClientRect(); + + handle?.focus(); + event.preventDefault(); + event.stopPropagation(); + + this._isDraggingGridHandle = true; + + drag(grid, { + onMove: (x, y) => { + // check if coordinates are not NaN (can happen when dragging outside of the grid) + if (isNaN(x) || isNaN(y)) return; + + this.coords.x = x; + this.coords.y = y; + + this.#setFocalPoint(x, y, width, height); + }, + onStop: () => (this._isDraggingGridHandle = false), + initialEvent: event, + }); + } + + #handleGridKeyDown(event: KeyboardEvent) { + if (this.disabled || this.hideFocalPoint) return; + + const increment = event.shiftKey ? 1 : 10; + + const grid = this.wrapperElement; + if (!grid) return; + + const { width, height } = grid.getBoundingClientRect(); + + if (event.key === 'ArrowLeft') { + event.preventDefault(); + this.coords.x = clamp(this.coords.x - increment, 0, width); + this.#setFocalPoint(this.coords.x, this.coords.y, width, height); + } + + if (event.key === 'ArrowRight') { + event.preventDefault(); + this.coords.x = clamp(this.coords.x + increment, 0, width); + this.#setFocalPoint(this.coords.x, this.coords.y, width, height); + } + + if (event.key === 'ArrowUp') { + event.preventDefault(); + this.coords.y = clamp(this.coords.y - increment, 0, height); + this.#setFocalPoint(this.coords.x, this.coords.y, width, height); + } + + if (event.key === 'ArrowDown') { + event.preventDefault(); + this.coords.y = clamp(this.coords.y + increment, 0, height); + this.#setFocalPoint(this.coords.x, this.coords.y, width, height); + } } override render() { if (!this.src) return nothing; return html` -
      - nothing} src=${this.src} alt="" /> -
      +
      + nothing} src=${this.src} alt="" /> + +
      `; } @@ -161,12 +236,16 @@ export class UmbImageCropperFocusSetterElement extends LitElement { } /* Wrapper is used to make the focal point position responsive to the image size */ #wrapper { - overflow: hidden; position: relative; display: flex; margin: auto; max-width: 100%; max-height: 100%; + box-sizing: border-box; + forced-color-adjust: none; + } + :host(:not([hidefocalpoint])) #wrapper { + cursor: crosshair; } #image { margin: auto; @@ -178,11 +257,18 @@ export class UmbImageCropperFocusSetterElement extends LitElement { position: absolute; width: calc(2 * var(--dot-radius)); height: calc(2 * var(--dot-radius)); - outline: 3px solid black; top: 0; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); + border: solid 2px white; border-radius: 50%; pointer-events: none; - background-color: white; + background-color: var(--uui-palette-spanish-pink-light); + transition: 150ms transform; + box-sizing: inherit; + } + .focal-point--dragging { + cursor: none; + transform: scale(1.5); } #focal-point.hidden { display: none; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper.element.ts index 1f838f82bd..6f99d7bd40 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper.element.ts @@ -1,10 +1,11 @@ -import type { UmbImageCropperCrop, UmbImageCropperFocalPoint } from './index.js'; +import { UmbImageCropChangeEvent, type UmbImageCropperCrop, type UmbImageCropperFocalPoint } from './index.js'; import { calculateExtrapolatedValue, clamp, inverseLerp, lerp } from '@umbraco-cms/backoffice/utils'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; -import { customElement, property, query, state, LitElement, css, html } from '@umbraco-cms/backoffice/external/lit'; +import { customElement, property, query, state, css, html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-image-cropper') -export class UmbImageCropperElement extends LitElement { +export class UmbImageCropperElement extends UmbLitElement { @query('#viewport') viewportElement!: HTMLElement; @query('#mask') maskElement!: HTMLElement; @query('#image') imageElement!: HTMLImageElement; @@ -261,19 +262,19 @@ export class UmbImageCropperElement extends LitElement { coordinates: { x1, x2, y1, y2 }, }; - this.dispatchEvent(new CustomEvent('change')); + this.dispatchEvent(new UmbImageCropChangeEvent()); } #onCancel() { //TODO: How should we handle canceling the crop? - this.dispatchEvent(new CustomEvent('change')); + this.dispatchEvent(new UmbImageCropChangeEvent()); } #onReset() { if (!this.value) return; delete this.value.coordinates; - this.dispatchEvent(new CustomEvent('change')); + this.dispatchEvent(new UmbImageCropChangeEvent()); } #onSliderUpdate(event: InputEvent) { @@ -330,11 +331,12 @@ export class UmbImageCropperElement extends LitElement { min="0" max="1" value="0" - step="0.001"> + step="0.001"> +
      - - - + + +
      `; } @@ -364,6 +366,7 @@ export class UmbImageCropperElement extends LitElement { display: flex; justify-content: flex-end; gap: var(--uui-size-space-1); + margin-top: 0.5rem; } #mask { @@ -379,6 +382,10 @@ export class UmbImageCropperElement extends LitElement { user-select: none; } + #viewport #image { + cursor: move; + } + #slider { width: 100%; height: 0px; /* TODO: FIX - This is needed to prevent the slider from taking up more space than needed */ diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/index.ts index 8e082a62c0..558f325be0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/index.ts @@ -1,2 +1,4 @@ export * from './input-image-cropper.element.js'; +export * from './crop-change.event.js'; +export * from './focalpoint-change.event.js'; export * from './types.js'; From 5003e1c1e7b83196a77047e92988cb7b0e852717 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:09:24 +0200 Subject: [PATCH 075/246] feat: allow images to be uploaded from the clipboard --- .../tiptap/extensions/core/media-upload.extension.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts index 1af085137c..22fe093aaa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts @@ -67,6 +67,13 @@ export default class UmbTiptapMediaUploadExtensionApi extends UmbTiptapExtension self.#uploadTemporaryFile(files, this.editor); }); + + host.addEventListener('paste', (event) => { + const files = event.clipboardData?.files; + if (!files) return; + + self.#uploadTemporaryFile(files, this.editor); + }); }, }), ]; From dcc2ced8ff6b53d7ca445f0923d6c8008f2038de Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:16:51 +0200 Subject: [PATCH 076/246] fix: catch any uncaught promises up the chain that could be thrown if there is a fatal error with the request --- .../core/temporary-file/temporary-file-manager.class.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts index e89f8979aa..9d756fdb8b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/temporary-file/temporary-file-manager.class.ts @@ -61,8 +61,9 @@ export class UmbTemporaryFileManager< for (const item of queue) { if (!item.temporaryUnique) throw new Error(`Unique is missing for item ${item}`); - const { error } = await this.#temporaryFileRepository.upload(item.temporaryUnique, item.file); - //await new Promise((resolve) => setTimeout(resolve, (Math.random() + 0.5) * 1000)); // simulate small delay so that the upload badge is properly shown + const { error } = await this.#temporaryFileRepository + .upload(item.temporaryUnique, item.file) + .catch(() => ({ error: true })); let status: TemporaryFileStatus; if (error) { From 67c0fcee35c6c5dc9c32c7b87606a121013de062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 16:26:05 +0200 Subject: [PATCH 077/246] simplify code --- .../core/validation/controllers/validation.controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts index 594b65ca45..499783244c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts @@ -225,8 +225,8 @@ export class UmbValidationController extends UmbControllerBase implements UmbVal this.#validationMode = true; const resultsStatus = await Promise.all(this.#validators.map((v) => v.validate())).then( - () => Promise.resolve(true), - () => Promise.resolve(false), + () => true, + () => false, ); if (!this.messages) { From 19de38f021d68f19dbaa6134dcdc0047219fe5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 16 Oct 2024 17:11:47 +0200 Subject: [PATCH 078/246] Bugfix: Variant Blocks create duplicates in the frontend when created in an area (#2464) * revert to previous code before tiptap * correct rte-entries context --- .../context/block-grid-manager.context.ts | 2 +- .../context/block-list-entries.context.ts | 14 +++++++++++--- .../context/block-list-manager.context.ts | 10 ++++++++-- .../context/block-rte-entries.context.ts | 18 ++++++++++++++---- .../context/block-rte-manager.context.ts | 18 +++++++++++++++--- .../block/context/block-manager.context.ts | 12 ++++++++++-- .../block/workspace/block-workspace.context.ts | 12 +++++++++--- 7 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts index 7a34386848..2f411cfd2b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts @@ -186,7 +186,7 @@ export class UmbBlockGridManagerContext< originData: UmbBlockGridWorkspaceOriginData, ) { this.setOneLayout(layoutEntry, originData); - this.insertBlockData(layoutEntry, content, settings); + this.insertBlockData(layoutEntry, content, settings, originData); return true; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts index 2e20c5836e..0ddd1eb326 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts @@ -48,7 +48,11 @@ export class UmbBlockListEntriesContext extends UmbBlockEntriesContext< }) .onSubmit(async (value, data) => { if (value?.create && data) { - const created = await this.create(value.create.contentElementTypeKey, {}); + const created = await this.create( + value.create.contentElementTypeKey, + {}, + data.originData as UmbBlockListWorkspaceOriginData, + ); if (created) { this.insert( created.layout, @@ -127,9 +131,13 @@ export class UmbBlockListEntriesContext extends UmbBlockEntriesContext< this._manager?.setLayouts(layouts); } - async create(contentElementTypeKey: string, partialLayoutEntry?: Omit) { + async create( + contentElementTypeKey: string, + partialLayoutEntry?: Omit, + originData?: UmbBlockListWorkspaceOriginData, + ) { await this._retrieveManager; - return this._manager?.create(contentElementTypeKey, partialLayoutEntry); + return this._manager?.create(contentElementTypeKey, partialLayoutEntry, originData); } // insert Block? diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts index b2b8d3d065..ccc98f903a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts @@ -21,7 +21,13 @@ export class UmbBlockListManagerContext< return this.#inlineEditingMode.getValue(); } - create(contentElementTypeKey: string, partialLayoutEntry?: Omit) { + create( + contentElementTypeKey: string, + partialLayoutEntry?: Omit, + // This property is used by some implementations, but not used in this. Do not remove. [NL] + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _originData?: UmbBlockListWorkspaceOriginData, + ) { return super._createBlockData(contentElementTypeKey, partialLayoutEntry); } @@ -33,7 +39,7 @@ export class UmbBlockListManagerContext< ) { this._layouts.appendOneAt(layoutEntry, originData.index ?? -1); - this.insertBlockData(layoutEntry, content, settings); + this.insertBlockData(layoutEntry, content, settings, originData); return true; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-entries.context.ts index 441f6c17fb..70846d23fd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-entries.context.ts @@ -53,7 +53,12 @@ export class UmbBlockRteEntriesContext extends UmbBlockEntriesContext< {} as any, ); if (created) { - this.insert(created.layout, created.content, created.settings); + this.insert( + created.layout, + created.content, + created.settings, + data.originData as UmbBlockRteWorkspaceOriginData, + ); } else { throw new Error('Failed to create block'); } @@ -122,9 +127,13 @@ export class UmbBlockRteEntriesContext extends UmbBlockEntriesContext< this._manager?.setLayouts(layouts); } - async create(contentElementTypeKey: string, partialLayoutEntry?: Omit) { + async create( + contentElementTypeKey: string, + partialLayoutEntry?: Omit, + originData?: UmbBlockRteWorkspaceOriginData, + ) { await this._retrieveManager; - return this._manager?.create(contentElementTypeKey, partialLayoutEntry); + return this._manager?.create(contentElementTypeKey, partialLayoutEntry, originData); } // insert Block? @@ -133,9 +142,10 @@ export class UmbBlockRteEntriesContext extends UmbBlockEntriesContext< layoutEntry: UmbBlockRteLayoutModel, content: UmbBlockDataModel, settings: UmbBlockDataModel | undefined, + originData: UmbBlockRteWorkspaceOriginData, ) { await this._retrieveManager; - return this._manager?.insert(layoutEntry, content, settings) ?? false; + return this._manager?.insert(layoutEntry, content, settings, originData) ?? false; } // create Block? diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-manager.context.ts index 876dfb06d8..4fefc64e27 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/context/block-rte-manager.context.ts @@ -1,3 +1,4 @@ +import type { UmbBlockRteWorkspaceOriginData } from '../workspace/block-rte-workspace.modal-token.js'; import type { UmbBlockRteLayoutModel, UmbBlockRteTypeModel } from '../types.js'; import type { UmbBlockDataModel } from '../../block/types.js'; import { UmbBlockManagerContext } from '@umbraco-cms/backoffice/block'; @@ -14,7 +15,13 @@ export class UmbBlockRteManagerContext< this._layouts.removeOne(contentKey); } - create(contentElementTypeKey: string, partialLayoutEntry?: Omit) { + create( + contentElementTypeKey: string, + partialLayoutEntry?: Omit, + // This property is used by some implementations, but not used in this, do not remove. [NL] + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _originData?: UmbBlockRteWorkspaceOriginData, + ) { const data = super._createBlockData(contentElementTypeKey, partialLayoutEntry); // Find block type. @@ -30,10 +37,15 @@ export class UmbBlockRteManagerContext< return data; } - insert(layoutEntry: BlockLayoutType, content: UmbBlockDataModel, settings: UmbBlockDataModel | undefined) { + insert( + layoutEntry: BlockLayoutType, + content: UmbBlockDataModel, + settings: UmbBlockDataModel | undefined, + originData: UmbBlockRteWorkspaceOriginData, + ) { this._layouts.appendOne(layoutEntry); - this.insertBlockData(layoutEntry, content, settings); + this.insertBlockData(layoutEntry, content, settings, originData); return true; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index abf7083a70..fcfbf774ab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -203,7 +203,9 @@ export abstract class UmbBlockManagerContext< getContentOf(contentKey: string) { return this.#contents.value.find((x) => x.key === contentKey); } - setOneLayout(layoutData: BlockLayoutType) { + // originData param is used by some implementations. [NL] should be here, do not remove it. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + setOneLayout(layoutData: BlockLayoutType, _originData?: BlockOriginDataType) { this._layouts.appendOne(layoutData); } setOneContent(contentData: UmbBlockDataModel) { @@ -316,7 +318,13 @@ export abstract class UmbBlockManagerContext< originData: BlockOriginDataType, ): boolean; - protected insertBlockData(layoutEntry: BlockLayoutType, content: UmbBlockDataModel, settings?: UmbBlockDataModel) { + protected insertBlockData( + layoutEntry: BlockLayoutType, + content: UmbBlockDataModel, + settings: UmbBlockDataModel | undefined, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _originData: BlockOriginDataType, + ) { // Create content entry: if (layoutEntry.contentKey) { this.#contents.appendOne(content); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index 4c0ad16a16..b9f7bbde7f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -352,7 +352,10 @@ export class UmbBlockWorkspaceContext { if (layoutData) { - this.#blockManager?.setOneLayout(layoutData); + this.#blockManager?.setOneLayout( + layoutData, + this.#modalContext?.data.originData as UmbBlockWorkspaceOriginData, + ); } }, 'observeThisLayout', @@ -448,7 +451,7 @@ export class UmbBlockWorkspaceContext Date: Wed, 16 Oct 2024 21:12:47 +0200 Subject: [PATCH 079/246] docs(storybook): remove invalid argType that is not useful --- .../core/localization/stories/localize.element.stories.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts index 36991cac5e..cef1a3f7ee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts @@ -9,13 +9,6 @@ const meta: Meta = { args: { key: 'general_areyousure', }, - argTypes: { - args: { - control: { - type: 'array', - }, - }, - }, decorators: [ (story) => { return html`
      From e445ce989fd999dc886d56f6334e0d32a730cb93 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:17:29 +0200 Subject: [PATCH 080/246] docs: add generated file to ignore for typedoc --- src/Umbraco.Web.UI.Client/typedoc.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/typedoc.config.js b/src/Umbraco.Web.UI.Client/typedoc.config.js index 55816e1c05..7af62f460f 100644 --- a/src/Umbraco.Web.UI.Client/typedoc.config.js +++ b/src/Umbraco.Web.UI.Client/typedoc.config.js @@ -1,6 +1,6 @@ import { packageJsonExports } from './devops/package/meta.js'; -const excludePaths = ['./src/external', '.src/apps']; +const excludePaths = ['./src/external', '.src/apps', './src/packages/extension-types/index.d.ts']; const entryPoints = []; for (const [key, value] of Object.entries(packageJsonExports || {})) { From 2067e0dc586bce01d0770fa8a087568d0a8dcfe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Kottal?= Date: Thu, 17 Oct 2024 11:31:12 +0200 Subject: [PATCH 081/246] Removes unnecessary margin in ufm-render-element (#2461) --- .../ufm/components/ufm-render/ufm-render.element.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts index 76de2ba178..a589c32d34 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts @@ -59,6 +59,14 @@ export class UmbUfmRenderElement extends UmbLitElement { pre { overflow: auto; } + + :host > :first-child { + margin-block-start: 0; + } + + :host > :last-child { + margin-block-end: 0; + } `, ]; } From ca174016945727178af0b63972298d125c963eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 17 Oct 2024 12:45:55 +0200 Subject: [PATCH 082/246] use server paths for preview url construction --- .../documents/workspace/document-workspace.context.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 560ca482df..6d4cbb73b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -75,6 +75,7 @@ import { UmbIsTrashedEntityContext } from '@umbraco-cms/backoffice/recycle-bin'; import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils'; import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type'; import type { UmbRepositoryResponse } from '@umbraco-cms/backoffice/repository'; +import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; type EntityModel = UmbDocumentDetailModel; type EntityTypeModel = UmbDocumentTypeDetailModel; @@ -600,7 +601,9 @@ export class UmbDocumentWorkspaceContext // Tell the server that we're entering preview mode. await new UmbDocumentPreviewRepository(this).enter(); - const previewUrl = new URL('preview', window.location.origin); + const appContext = await this.getContext(UMB_APP_CONTEXT); + + const previewUrl = new URL(appContext.getBackofficePath() + '/preview', appContext.getServerUrl()); previewUrl.searchParams.set('id', unique); if (culture && culture !== UMB_INVARIANT_CULTURE) { From dc215171c454e531cc0e7bb9e589e5ff89c7e456 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Thu, 17 Oct 2024 12:38:45 +0100 Subject: [PATCH 083/246] Feature: Collection Toolbar Filter Field (#2467) * Sets `umb-collection-action-bundle` to use `display:contents` This should only display if the component has any contents. * Refactored Dictionary collection toolbar * Refactored Document collection toolbar Deprecates `umb-document-collection-toolbar` * Refactored Media collection toolbar Deprecates `umb-media-collection-toolbar` * Refactored Extension collection toolbar Enables support for future Create and Views functionality. * Exported collection element classes as `element` deprecated the "default" export * Adds `elementName` constant * Refactored UserGroup collection toolbar Deprecates `umb-user-group-collection-header` * Code formatting * Added `umb-collection-filter-field` component Reusable filter field for a collection toolbar. * Used `umb-collection-filter-field` component on existing collections, removed duplicated code. * Reverted adding `elementName` constant Seems that this may cause issues with the eslint plugin (for ensuring element names start with "umb-"). --- .../collection-action-bundle.element.ts | 10 ++- .../collection-filter-field.element.ts | 47 ++++++++++++++ .../collection-view-bundle.element.ts | 7 +-- .../core/collection/components/index.ts | 10 +-- .../dictionary-collection.element.ts | 49 +++------------ .../document-collection-toolbar.element.ts | 1 + .../collection/document-collection.element.ts | 13 ++-- .../extension-collection.element.ts | 49 +++++++-------- .../media-collection-toolbar.element.ts | 1 + .../collection/media-collection.element.ts | 25 +++++--- .../member-collection-header.element.ts | 33 +++------- .../collection/member-collection.element.ts | 5 +- .../relation-type-collection.element.ts | 8 ++- .../user-group-collection-header.element.ts | 2 + .../user-group-collection.element.ts | 46 ++++++++++++-- .../user-collection-header.element.ts | 63 +++++++------------ .../collection/user-collection.element.ts | 5 +- 17 files changed, 209 insertions(+), 165 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-filter-field.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-action-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-action-bundle.element.ts index 40bcbe93b6..eb205435e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-action-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-action-bundle.element.ts @@ -1,4 +1,4 @@ -import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-collection-action-bundle') @@ -6,6 +6,14 @@ export class UmbCollectionActionBundleElement extends UmbLitElement { override render() { return html``; } + + static override readonly styles = [ + css` + :host { + display: contents; + } + `, + ]; } declare global { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-filter-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-filter-field.element.ts new file mode 100644 index 0000000000..7f1d3f9f8b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-filter-field.element.ts @@ -0,0 +1,47 @@ +import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; +import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit'; +import { debounce } from '@umbraco-cms/backoffice/utils'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +@customElement('umb-collection-filter-field') +export class UmbCollectionFilterFieldElement extends UmbLitElement { + #collectionContext?: typeof UMB_COLLECTION_CONTEXT.TYPE; + + constructor() { + super(); + + this.consumeContext(UMB_COLLECTION_CONTEXT, (context) => { + this.#collectionContext = context; + }); + } + + #debouncedFilter = debounce((filter: string) => this.#collectionContext?.setFilter({ filter }), 500); + + #onInput(event: InputEvent & { target: HTMLInputElement }) { + const filter = event.target.value ?? ''; + this.#debouncedFilter(filter); + } + + override render() { + return html` + + `; + } + + static override readonly styles = [ + css` + uui-input { + display: block; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-collection-filter-field': UmbCollectionFilterFieldElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts index ff873f9671..d26d5aaccd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts @@ -1,8 +1,7 @@ -import type { UmbDefaultCollectionContext } from '../default/index.js'; import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; -import type { UmbCollectionLayoutConfiguration } from '../types.js'; import type { ManifestCollectionView } from '../extensions/index.js'; -import { css, html, customElement, state, nothing, repeat, query } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbCollectionLayoutConfiguration } from '../types.js'; +import { css, customElement, html, nothing, query, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -30,7 +29,7 @@ export class UmbCollectionViewBundleElement extends UmbLitElement { @state() private _entityUnique?: string; - #collectionContext?: UmbDefaultCollectionContext; + #collectionContext?: typeof UMB_COLLECTION_CONTEXT.TYPE; constructor() { super(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/index.ts index 4b753400bf..7abcffff90 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/index.ts @@ -1,11 +1,13 @@ -import './pagination/collection-pagination.element.js'; +import './collection-action-bundle.element.js'; +import './collection-filter-field.element.js'; import './collection-selection-actions.element.js'; import './collection-toolbar.element.js'; import './collection-view-bundle.element.js'; -import './collection-action-bundle.element.js'; +import './pagination/collection-pagination.element.js'; -export * from './pagination/collection-pagination.element.js'; +export * from './collection-action-bundle.element.js'; +export * from './collection-filter-field.element.js'; export * from './collection-selection-actions.element.js'; export * from './collection-toolbar.element.js'; export * from './collection-view-bundle.element.js'; -export * from './collection-action-bundle.element.js'; +export * from './pagination/collection-pagination.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/dictionary-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/dictionary-collection.element.ts index d4372f22ec..f6eac66c42 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/dictionary-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/dictionary-collection.element.ts @@ -1,51 +1,18 @@ -import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit'; -import { - UMB_COLLECTION_CONTEXT, - UmbCollectionDefaultElement, - type UmbDefaultCollectionContext, -} from '@umbraco-cms/backoffice/collection'; +import { customElement, html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection'; @customElement('umb-dictionary-collection') export class UmbDictionaryCollectionElement extends UmbCollectionDefaultElement { - #collectionContext?: UmbDefaultCollectionContext; - #inputTimer?: NodeJS.Timeout; - #inputTimerAmount = 500; - - constructor() { - super(); - this.consumeContext(UMB_COLLECTION_CONTEXT, (context) => { - this.#collectionContext = context; - }); - } - - #updateSearch(event: InputEvent) { - const target = event.target as HTMLInputElement; - const filter = target.value || ''; - clearTimeout(this.#inputTimer); - this.#inputTimer = setTimeout(() => this.#collectionContext?.setFilter({ filter }), this.#inputTimerAmount); - } - protected override renderToolbar() { - return html`${this.#renderSearch()}`; + return html` + + + + `; } - - #renderSearch() { - return html``; - } - - static override styles = [ - css` - #input-search { - width: 100%; - } - `, - ]; } -export default UmbDictionaryCollectionElement; +export { UmbDictionaryCollectionElement as element }; declare global { interface HTMLElementTagNameMap { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection-toolbar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection-toolbar.element.ts index e65071e87e..ed675276b4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection-toolbar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection-toolbar.element.ts @@ -3,6 +3,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection'; import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection'; +/** @deprecated This component is no longer used in core; to be removed in Umbraco 17. */ @customElement('umb-document-collection-toolbar') export class UmbDocumentCollectionToolbarElement extends UmbLitElement { #collectionContext?: UmbDefaultCollectionContext; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection.element.ts index 1befc2e76f..f1bf71c7a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/document-collection.element.ts @@ -1,17 +1,22 @@ -import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { customElement, html } from '@umbraco-cms/backoffice/external/lit'; import { UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection'; -import './document-collection-toolbar.element.js'; - @customElement('umb-document-collection') export class UmbDocumentCollectionElement extends UmbCollectionDefaultElement { protected override renderToolbar() { - return html``; + return html` + + + + `; } } +/** @deprecated Should be exported as `element` only; to be removed in Umbraco 17. */ export default UmbDocumentCollectionElement; +export { UmbDocumentCollectionElement as element }; + declare global { interface HTMLElementTagNameMap { 'umb-document-collection': UmbDocumentCollectionElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/extension-insights/collection/extension-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/extension-insights/collection/extension-collection.element.ts index 3c22b9e54a..375daeb232 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/extension-insights/collection/extension-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/extension-insights/collection/extension-collection.element.ts @@ -1,17 +1,14 @@ -import type { UmbExtensionCollectionFilterModel } from './types.js'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, css } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbExtensionCollectionFilterModel, UmbExtensionDetailModel } from './types.js'; +import { css, customElement, html } from '@umbraco-cms/backoffice/external/lit'; import { fromCamelCase } from '@umbraco-cms/backoffice/utils'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UMB_COLLECTION_CONTEXT, UmbCollectionDefaultElement } from '@umbraco-cms/backoffice/collection'; import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection'; import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-extension-collection') export class UmbExtensionCollectionElement extends UmbCollectionDefaultElement { - #collectionContext?: UmbDefaultCollectionContext; - - #inputTimer?: NodeJS.Timeout; - #inputTimerAmount = 500; + #collectionContext?: UmbDefaultCollectionContext; #options: Array
      `; From 4bcca9928b8082036e8bcee6bea2f71dfe355106 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 21 Oct 2024 12:54:58 +0200 Subject: [PATCH 086/246] render readonly tag in app language dropdown --- .../app-language-select.element.ts | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts index 940bd928a5..fe0a58b166 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts @@ -2,8 +2,18 @@ import { UmbLanguageCollectionRepository } from '../collection/index.js'; import type { UmbLanguageDetailModel } from '../types.js'; import { type UmbAppLanguageContext, UMB_APP_LANGUAGE_CONTEXT } from '../global-contexts/index.js'; import type { UUIMenuItemEvent, UUIPopoverContainerElement } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement, state, repeat, ifDefined, query } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + html, + customElement, + state, + repeat, + ifDefined, + query, + nothing, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; @customElement('umb-app-language-select') export class UmbAppLanguageSelectElement extends UmbLitElement { @@ -23,6 +33,12 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { #appLanguageContext?: UmbAppLanguageContext; #languagesObserver?: any; + #currentUserAllowedLanguages?: Array; + #currentUserHasAccessToAllLanguages?: boolean; + + @state() + _disallowedLanguages: Array = []; + constructor() { super(); @@ -30,6 +46,29 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { this.#appLanguageContext = instance; this.#observeAppLanguage(); }); + + this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { + this.observe(context.languages, (languages) => { + this.#currentUserAllowedLanguages = languages; + this.#checkForLanguageAccess(); + }); + + this.observe(context.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { + this.#currentUserHasAccessToAllLanguages = hasAccessToAllLanguages; + this.#checkForLanguageAccess(); + }); + }); + } + + #checkForLanguageAccess() { + // find all disallowed languages + this._disallowedLanguages = this._languages?.filter((language) => { + if (this.#currentUserHasAccessToAllLanguages) { + return false; + } + + return !this.#currentUserAllowedLanguages?.includes(language.unique); + }); } async #observeAppLanguage() { @@ -46,6 +85,7 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { // TODO: listen to changes if (data) { this._languages = data.items; + this.#checkForLanguageAccess(); } } @@ -98,13 +138,25 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { label=${ifDefined(language.name)} @click-label=${this.#onLabelClick} data-unique=${ifDefined(language.unique)} - ?active=${language.unique === this._appLanguage?.unique}> + ?active=${language.unique === this._appLanguage?.unique}> + ${this.#renderReadOnlyTag(language.unique)} + `, )} `; } + #isReadOnly(culture: string | null) { + if (!culture) return false; + return this._disallowedLanguages.find((language) => language.unique === culture) ? true : false; + } + + #renderReadOnlyTag(culture?: string | null) { + if (!culture) return nothing; + return this.#isReadOnly(culture) ? html`Read-only` : nothing; + } + static override styles = [ css` :host { From 7c54064f59cfeefd5835c659df2a6d2b3aa12e8f Mon Sep 17 00:00:00 2001 From: Busra Sengul Date: Mon, 21 Oct 2024 12:05:39 +0100 Subject: [PATCH 087/246] Bugfix: Tiptap RTE custom dimensions configuration (#2469) * tiptop min height configuration * Removed `min-height`; credit to @innovoix * Clarified the use of `display:flex` * Changed to use `height` instead of `min-height` as this will control the maximum height of the editor input area. --------- Co-authored-by: leekelleher --- .../tiptap/components/input-tiptap/input-tiptap.element.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index e0f083f65a..367d2c6edc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -93,7 +93,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin('dimensions'); if (dimensions?.width) this.setAttribute('style', `max-width: ${dimensions.width}px;`); - if (dimensions?.height) element.setAttribute('style', `max-height: ${dimensions.height}px;`); + if (dimensions?.height) element.setAttribute('style', `height: ${dimensions.height}px;`); this._toolbar = this.configuration?.getValueByAlias('toolbar') ?? [[[]]]; @@ -173,6 +173,8 @@ export class UmbInputTiptapElement extends UmbFormControlMixin Date: Mon, 21 Oct 2024 12:05:39 +0100 Subject: [PATCH 088/246] Bugfix: Tiptap RTE custom dimensions configuration (#2469) * tiptop min height configuration * Removed `min-height`; credit to @innovoix * Clarified the use of `display:flex` * Changed to use `height` instead of `min-height` as this will control the maximum height of the editor input area. --------- Co-authored-by: leekelleher (cherry picked from commit 7c54064f59cfeefd5835c659df2a6d2b3aa12e8f) --- .../tiptap/components/input-tiptap/input-tiptap.element.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index e0f083f65a..367d2c6edc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -93,7 +93,7 @@ export class UmbInputTiptapElement extends UmbFormControlMixin('dimensions'); if (dimensions?.width) this.setAttribute('style', `max-width: ${dimensions.width}px;`); - if (dimensions?.height) element.setAttribute('style', `max-height: ${dimensions.height}px;`); + if (dimensions?.height) element.setAttribute('style', `height: ${dimensions.height}px;`); this._toolbar = this.configuration?.getValueByAlias('toolbar') ?? [[[]]]; @@ -173,6 +173,8 @@ export class UmbInputTiptapElement extends UmbFormControlMixin Date: Mon, 21 Oct 2024 16:07:35 +0200 Subject: [PATCH 089/246] render tag in app language selector --- .../app-language-select.element.ts | 21 ++++-- .../global-contexts/app-language.context.ts | 73 ++++++++++++++++--- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts index fe0a58b166..282deb16dc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts @@ -26,6 +26,9 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { @state() private _appLanguage?: UmbLanguageDetailModel; + @state() + private _appLanguageIsReadOnly = false; + @state() private _isOpen = false; @@ -77,6 +80,10 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { this.observe(this.#appLanguageContext.appLanguage, (language) => { this._appLanguage = language; }); + + this.observe(this.#appLanguageContext.appLanguageReadOnlyState.isReadOnly, (isReadOnly) => { + this._appLanguageIsReadOnly = isReadOnly; + }); } async #observeLanguages() { @@ -123,7 +130,11 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { #renderTrigger() { return html``; } @@ -139,7 +150,7 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { @click-label=${this.#onLabelClick} data-unique=${ifDefined(language.unique)} ?active=${language.unique === this._appLanguage?.unique}> - ${this.#renderReadOnlyTag(language.unique)} + ${this.#isLanguageReadOnly(language.unique) ? this.#renderReadOnlyTag(language.unique) : nothing} `, )} @@ -147,14 +158,14 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { `; } - #isReadOnly(culture: string | null) { + #isLanguageReadOnly(culture?: string) { if (!culture) return false; return this._disallowedLanguages.find((language) => language.unique === culture) ? true : false; } - #renderReadOnlyTag(culture?: string | null) { + #renderReadOnlyTag(culture?: string) { if (!culture) return nothing; - return this.#isReadOnly(culture) ? html`Read-only` : nothing; + return html`Read-only`; } static override styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts index 6a0d4b7d8b..270858b99b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts @@ -6,30 +6,34 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; +import { UmbReadOnlyStateManager } from '@umbraco-cms/backoffice/utils'; +import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; // TODO: Make a store for the App Languages. // TODO: Implement default language end-point, in progress at backend team, so we can avoid getting all languages. export class UmbAppLanguageContext extends UmbContextBase implements UmbApi { - #languageCollectionRepository: UmbLanguageCollectionRepository; #languages = new UmbArrayState([], (x) => x.unique); - moreThanOneLanguage = this.#languages.asObservablePart((x) => x.length > 1); #appLanguage = new UmbObjectState(undefined); - appLanguage = this.#appLanguage.asObservable(); + public readonly appLanguage = this.#appLanguage.asObservable(); + public readonly appLanguageCulture = this.#appLanguage.asObservablePart((x) => x?.unique); - appLanguageCulture = this.#appLanguage.asObservablePart((x) => x?.unique); + public readonly appLanguageReadOnlyState = new UmbReadOnlyStateManager(this); - appDefaultLanguage = createObservablePart(this.#languages.asObservable(), (languages) => + public readonly appDefaultLanguage = createObservablePart(this.#languages.asObservable(), (languages) => languages.find((language) => language.isDefault), ); - getAppCulture() { - return this.#appLanguage.getValue()?.unique; - } + public readonly moreThanOneLanguage = this.#languages.asObservablePart((x) => x.length > 1); + + #languageCollectionRepository = new UmbLanguageCollectionRepository(this); + #currentUserAllowedLanguages: Array = []; + #currentUserHasAccessToAllLanguages = false; + + #readOnlyStateIdentifier = 'UMB_LANGUAGE_PERMISSION_'; constructor(host: UmbControllerHost) { super(host, UMB_APP_LANGUAGE_CONTEXT); - this.#languageCollectionRepository = new UmbLanguageCollectionRepository(this); // TODO: We need to ensure this request is called every time the user logs in, but this should be done somewhere across the app and not here [JOV] this.consumeContext(UMB_AUTH_CONTEXT, (authContext) => { @@ -38,12 +42,39 @@ export class UmbAppLanguageContext extends UmbContextBase this.#observeLanguages(); }); }); + + this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { + this.observe(context.languages, (languages) => { + this.#currentUserAllowedLanguages = languages || []; + this.#setIsReadOnly(); + }); + + this.observe(context.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { + this.#currentUserHasAccessToAllLanguages = hasAccessToAllLanguages || false; + this.#setIsReadOnly(); + }); + }); + } + + getAppCulture() { + return this.#appLanguage.getValue()?.unique; } setLanguage(unique: string) { + const appLanguage = this.#appLanguage.getValue(); + + // clear the previous read-only state + if (appLanguage?.unique) { + this.appLanguageReadOnlyState.removeState(this.#readOnlyStateIdentifier + appLanguage.unique); + } + + // set the new language const languages = this.#languages.getValue(); const language = languages.find((x) => x.unique === unique); this.#appLanguage.update(language); + + // set the new read-only state + this.#setIsReadOnly(); } async #observeLanguages() { @@ -67,6 +98,30 @@ export class UmbAppLanguageContext extends UmbContextBase // in that case do we then need an endpoint to get the default language? if (!defaultLanguage?.unique) return; this.setLanguage(defaultLanguage.unique); + this.#setIsReadOnly(); + } + + #setIsReadOnly() { + const appLanguage = this.#appLanguage.getValue(); + + if (!appLanguage) { + this.appLanguageReadOnlyState.clear(); + return; + } + + const unique = this.#readOnlyStateIdentifier + appLanguage.unique; + this.appLanguageReadOnlyState.removeState(unique); + + const isReadOnly = !this.#currentUserAllowedLanguages.includes(appLanguage.unique); + + if (isReadOnly) { + const readOnlyState = { + unique, + message: 'You do not have permission to edit to this culture', + }; + + this.appLanguageReadOnlyState.addState(readOnlyState); + } } } From 5deab9571df30316845668cd9c22657b1f94f588 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 21 Oct 2024 19:19:02 +0200 Subject: [PATCH 090/246] localize read only text --- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 1 + .../workspace-split-view-variant-selector.element.ts | 4 +++- .../app-language-select/app-language-select.element.ts | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 985e14d610..d4a9d69ad7 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -936,6 +936,7 @@ export default { skipToMenu: 'Skip to menu', skipToContent: 'Skip to content', restore: 'Restore', + readOnly: 'Read-only', newVersionAvailable: 'New version available', }, colors: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts index d7be226d99..f32f98bc68 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts @@ -307,7 +307,9 @@ export class UmbWorkspaceSplitViewVariantSelectorElement extends UmbLitElement { #renderReadOnlyTag(culture?: string | null) { if (!culture) return nothing; - return this.#isReadOnly(culture) ? html`Read-only` : nothing; + return this.#isReadOnly(culture) + ? html`${this.localize.term('general_readOnly')}` + : nothing; } #renderSplitViewButton(variant: UmbDocumentVariantOptionModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts index 282deb16dc..4b76521814 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts @@ -165,7 +165,7 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { #renderReadOnlyTag(culture?: string) { if (!culture) return nothing; - return html`Read-only`; + return html`${this.localize.term('general_readOnly')}`; } static override styles = [ From 9a23ad2e50fd946b94a541851e00fa559cb2b776 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 21 Oct 2024 19:46:29 +0200 Subject: [PATCH 091/246] check for access to all languages --- .../packages/language/global-contexts/app-language.context.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts index 270858b99b..1504b31603 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts @@ -112,6 +112,10 @@ export class UmbAppLanguageContext extends UmbContextBase const unique = this.#readOnlyStateIdentifier + appLanguage.unique; this.appLanguageReadOnlyState.removeState(unique); + if (this.#currentUserHasAccessToAllLanguages) { + return; + } + const isReadOnly = !this.#currentUserAllowedLanguages.includes(appLanguage.unique); if (isReadOnly) { From b095902bf51a02b8f8f529569bcff61918687a9e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 21 Oct 2024 20:12:34 +0200 Subject: [PATCH 092/246] store selected app language in local storage --- .../global-contexts/app-language.context.ts | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts index 1504b31603..bb6da03b19 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts @@ -31,6 +31,7 @@ export class UmbAppLanguageContext extends UmbContextBase #currentUserHasAccessToAllLanguages = false; #readOnlyStateIdentifier = 'UMB_LANGUAGE_PERMISSION_'; + #localStorageKey = 'umb:appLanguage'; constructor(host: UmbControllerHost) { super(host, UMB_APP_LANGUAGE_CONTEXT); @@ -61,18 +62,25 @@ export class UmbAppLanguageContext extends UmbContextBase } setLanguage(unique: string) { - const appLanguage = this.#appLanguage.getValue(); - // clear the previous read-only state + const appLanguage = this.#appLanguage.getValue(); if (appLanguage?.unique) { this.appLanguageReadOnlyState.removeState(this.#readOnlyStateIdentifier + appLanguage.unique); } + // find the language + const language = this.#findLanguage(unique); + + if (!language) { + throw new Error(`Language with unique ${unique} not found`); + } + // set the new language - const languages = this.#languages.getValue(); - const language = languages.find((x) => x.unique === unique); this.#appLanguage.update(language); + // store the new language in local storage + localStorage.setItem(this.#localStorageKey, language?.unique); + // set the new read-only state this.#setIsReadOnly(); } @@ -92,13 +100,27 @@ export class UmbAppLanguageContext extends UmbContextBase } #initAppLanguage() { + // get the selected language from local storage + const uniqueFromLocalStorage = localStorage.getItem(this.#localStorageKey); + + if (uniqueFromLocalStorage) { + const language = this.#findLanguage(uniqueFromLocalStorage); + if (language) { + this.setLanguage(language.unique); + return; + } + } + const defaultLanguage = this.#languages.getValue().find((x) => x.isDefault); // TODO: do we always have a default language? // do we always get the default language on the first request, or could it be on page 2? // in that case do we then need an endpoint to get the default language? if (!defaultLanguage?.unique) return; this.setLanguage(defaultLanguage.unique); - this.#setIsReadOnly(); + } + + #findLanguage(unique: string) { + return this.#languages.getValue().find((x) => x.unique === unique); } #setIsReadOnly() { From 59d4f8852cc976c463a27b10818772dca0f44838 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 23 Oct 2024 11:49:03 +0200 Subject: [PATCH 093/246] Hotfix: document variant publication info (#2478) * export token * show current variant status, fix published pending changes + create date * remove unused * temp type casting --- .../property-dataset-context/index.ts | 1 + .../document-workspace-view-info.element.ts | 86 +++++++------------ 2 files changed, 34 insertions(+), 53 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/index.ts new file mode 100644 index 0000000000..6585fe3792 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/index.ts @@ -0,0 +1 @@ +export * from './document-property-dataset-context.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index 3a0eee8dc7..c6a42baecf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -1,16 +1,17 @@ +import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../../property-dataset-context/index.js'; +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; +import type { UmbDocumentVariantModel } from '../../../types.js'; import { TimeOptions } from './utils.js'; -import { css, customElement, html, ifDefined, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, ifDefined, nothing, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/document'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UMB_TEMPLATE_PICKER_MODAL, UmbTemplateItemRepository } from '@umbraco-cms/backoffice/template'; import type { DocumentUrlInfoModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; -import type { UmbDocumentVariantModel } from '@umbraco-cms/backoffice/document'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; // import of local components @@ -28,9 +29,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { @state() private _urls?: Array; - @state() - private _createDate?: string; - /**Document Type */ @state() private _documentTypeUnique = ''; @@ -52,7 +50,7 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { private _templateName?: string; @state() - private _variants: UmbDocumentVariantModel[] = []; + private _variant?: UmbDocumentVariantModel; #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; @@ -78,6 +76,13 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { this._documentTypeUnique = this.#workspaceContext.getContentTypeId()!; this.#observeContent(); }); + + this.consumeContext(UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT, (context) => { + this.observe(context.currentVariant, (value) => { + // TODO: get the correct type automatically + this._variant = value as UmbDocumentVariantModel; + }); + }); } #observeContent() { @@ -121,44 +126,10 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { }, '_templateUnique', ); - - this.observe( - this.#workspaceContext.variants, - (variants) => { - this._variants = variants; - this.#observeVariants(); - }, - '_variants', - ); } - #observeVariants() { - // Find the oldest variant - const oldestVariant = - this._variants.length > 0 - ? this._variants - .filter((v) => !!v.createDate) - .reduce((prev, current) => (prev.createDate! < current.createDate! ? prev : current)) - : null; - - this._createDate = oldestVariant?.createDate ?? new Date().toISOString(); - } - - #renderVariantStates() { - return repeat( - this._variants, - (variant) => `${variant.culture}_${variant.segment}`, - (variant) => html` -
      - ${variant.culture ?? this._invariantCulture} - ${this.#renderStateTag(variant)} -
      - `, - ); - } - - #renderStateTag(variant: UmbDocumentVariantModel) { - switch (variant.state) { + #renderStateTag() { + switch (this._variant?.state) { case DocumentVariantStateModel.DRAFT: return html` @@ -174,13 +145,13 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { case DocumentVariantStateModel.PUBLISHED_PENDING_CHANGES: return html` - ${this.localize.term('content_published')} + ${this.localize.term('content_publishedPendingChanges')} `; default: return html` - - ${this.localize.term('content_published')} + + ${this.localize.term('content_notCreated')} `; } @@ -240,14 +211,10 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { return html`
      Publication Status - ${this.#renderVariantStates()} -
      -
      - Created - - - + ${this.#renderStateTag()}
      + ${this.#renderCreateDate()} +
      Document Type + Created + + + +
      + `; + } + async #openTemplatePicker() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const modal = modalManager.open(this, UMB_TEMPLATE_PICKER_MODAL, { From 9df26e95d73e6d76d5d9677ae1fc7329b2ec3fdb Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Wed, 23 Oct 2024 11:56:27 +0100 Subject: [PATCH 094/246] Feature: Link Picker modal refactor (#2477) * Adds `hideTarget` flag * Sets default modal size to "medium" * Code tidy-up * Updates "defaultdialogs_linkinternal" localizations to remove the `:` suffix (from all languages) * Applied `standalone` to single Document Picker item * Adds `icon` to the document/media detail types * Link Picker modal: total refactor! Swaps the inline trees with input pickers. Makes use of `` component. + plenty of TLC in the UI/UX! * Sets the `allowedMediaTypeIds` for media picker filtering e.g. folders are not selectable --- .../src/assets/lang/ar.ts | 2 +- .../src/assets/lang/bs.ts | 2 +- .../src/assets/lang/cs-cz.ts | 2 +- .../src/assets/lang/cy-gb.ts | 2 +- .../src/assets/lang/da-dk.ts | 2 +- .../src/assets/lang/de-de.ts | 2 +- .../src/assets/lang/en-us.ts | 4 +- .../src/assets/lang/en.ts | 4 +- .../src/assets/lang/fr-fr.ts | 2 +- .../src/assets/lang/he-il.ts | 2 +- .../src/assets/lang/hr-hr.ts | 2 +- .../src/assets/lang/it-it.ts | 2 +- .../src/assets/lang/ja-jp.ts | 2 +- .../src/assets/lang/ko-kr.ts | 2 +- .../src/assets/lang/nb-no.ts | 2 +- .../src/assets/lang/nl-nl.ts | 2 +- .../src/assets/lang/pl-pl.ts | 2 +- .../src/assets/lang/pt-br.ts | 2 +- .../src/assets/lang/ru-ru.ts | 2 +- .../src/assets/lang/sv-se.ts | 2 +- .../src/assets/lang/tr-tr.ts | 2 +- .../src/assets/lang/uk-ua.ts | 2 +- .../src/assets/lang/zh-cn.ts | 2 +- .../src/assets/lang/zh-tw.ts | 2 +- .../input-document/input-document.element.ts | 55 ++- .../document-detail.server.data-source.ts | 2 + .../src/packages/documents/documents/types.ts | 1 + .../input-media/input-media.element.ts | 2 +- .../detail/media-detail.server.data-source.ts | 2 + .../src/packages/media/media/types.ts | 1 + .../input-multi-url.element.ts | 27 +- .../link-picker-modal.element.ts | 393 ++++++++++-------- .../link-picker-modal.token.ts | 4 +- 33 files changed, 291 insertions(+), 248 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts index 5f57427859..8211f08edc 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts @@ -481,7 +481,7 @@ export default { 'قد يكون تغيير الثقافة للغة عملية مكلفة وستؤدي إلى إعادة بناء ذاكرة التخزين المؤقت للمحتوى والفهارس', lastEdited: 'آخر تحرير', link: 'رابط', - linkinternal: 'رابط داخلي:', + linkinternal: 'رابط داخلي', linklocaltip: 'عند استخدام الروابط المحلية، أدخل "#" أمام الرابط', linknewwindow: 'فتح في نافذة جديدة؟', macroDoesNotHaveProperties: 'هذا الماكرو لا يحتوي على خصائص يمكنك تحريرها', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts index 159d15d541..eebc3ee1e5 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/bs.ts @@ -482,7 +482,7 @@ export default { 'Promjena kulture jezika može biti skupa operacija i rezultirat će\n u kešu sadržaja i indeksima koji se rekonstruišu\n ', lastEdited: 'Posljednji put uređeno', link: 'Link', - linkinternal: 'Interni link:', + linkinternal: 'Interni link', linklocaltip: 'Kada koristite lokalne veze, umetnite "#" ispred linka', linknewwindow: 'Otvori u novom prozoru?', macroDoesNotHaveProperties: 'Ovaj makro ne sadrži svojstva koja možete uređivati', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts index 0f47ba053f..90f89601a6 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/cs-cz.ts @@ -429,7 +429,7 @@ export default { 'Změna kultury jazyka může být náročná operace a bude mít za následek opětovné sestavení mezipaměti obsahu a indexů', lastEdited: 'Naposledy editováno', link: 'Odkaz', - linkinternal: 'Místní odkaz:', + linkinternal: 'Místní odkaz', linklocaltip: 'Při používání místních odkazů vložte znak "#" před odkaz', linknewwindow: 'Otevřít v novém okně?', macroDoesNotHaveProperties: 'Toto makro nemá žádné vlastnosti, které by bylo možno editovat', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts index 01ca531714..a3b0dc27b5 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/cy-gb.ts @@ -504,7 +504,7 @@ export default { "Gall newid y diwylliant ar gyfer iaith fod yn weithrediad drud a bydd yn arwain at ailadeiladu'r storfa cynnwys a'r mynegeion", lastEdited: 'Golygwyd ddiwethaf', link: 'Dolen', - linkinternal: 'Dolen fewnol:', + linkinternal: 'Dolen fewnol', linklocaltip: 'Wrth ddefnyddio dolenni leol, defnyddiwch "#" o flaen y ddolen', linknewwindow: 'Agor mewn ffenestr newydd?', macroDoesNotHaveProperties: "Nid yw'r macro yma yn cynnwys unrhyw briodweddau gallwch chi olygu", diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index d7d5b6d9be..0b05cfbb8d 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -499,7 +499,7 @@ export default { 'Ændring af kulturen for et sprog kan forsage en krævende opration og vil\n resultere i indholds cache og indeksering vil blive genlavet\n ', lastEdited: 'Sidst redigeret', link: 'Link', - linkinternal: 'Internt link:', + linkinternal: 'Internt link', linklocaltip: 'Ved lokalt link, indsæt da en "#" foran linket', linknewwindow: 'Åben i nyt vindue?', macroDoesNotHaveProperties: 'Denne makro har ingen egenskaber du kan redigere', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts index 66000861c1..7733d6fa34 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/de-de.ts @@ -503,7 +503,7 @@ export default { '\n Die Kultur-Variante einer Sprache zu ändern ist möglicherweise eine aufwendige Operation und führt zum Erneuern von Inhalts-Zwischenspeicher und Such-Index.\n ', lastEdited: 'Zuletzt bearbeitet', link: 'Verknüpfung', - linkinternal: 'Anker:', + linkinternal: 'Internen Link', linklocaltip: 'Wenn lokale Links verwendet werden, füge ein "#" vor den Link ein', linknewwindow: 'In einem neuen Fenster öffnen?', macroDoesNotHaveProperties: 'Dieses Makro enthält keine einstellbaren Eigenschaften.', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 985e14d610..1c296f2a86 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -521,7 +521,7 @@ export default { 'Changing the culture for a language may be an expensive operation and will result\n in the content cache and indexes being rebuilt\n ', lastEdited: 'Last Edited', link: 'Link', - linkinternal: 'Internal link:', + linkinternal: 'Internal link', linklocaltip: 'When using local links, insert "#" in front of link', linknewwindow: 'Open in new window?', macroDoesNotHaveProperties: 'This macro does not contain any properties you can edit', @@ -553,7 +553,7 @@ export default { relateToOriginalLabel: 'Relate to original', includeDescendants: 'Include descendants', theFriendliestCommunity: 'The friendliest community', - linkToPage: 'Link to page', + linkToPage: 'Link to document', openInNewWindow: 'Opens the linked document in a new window or tab', linkToMedia: 'Link to media', selectContentStartNode: 'Select content start node', 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 0421ac8467..1830171106 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -519,7 +519,7 @@ export default { 'Changing the culture for a language may be an expensive operation and will result\n in the content cache and indexes being rebuilt\n ', lastEdited: 'Last Edited', link: 'Link', - linkinternal: 'Internal link:', + linkinternal: 'Internal link', linklocaltip: 'When using local links, insert "#" in front of link', linknewwindow: 'Open in new window?', macroDoesNotHaveProperties: 'This macro does not contain any properties you can edit', @@ -551,7 +551,7 @@ export default { relateToOriginalLabel: 'Relate to original', includeDescendants: 'Include descendants', theFriendliestCommunity: 'The friendliest community', - linkToPage: 'Link to page', + linkToPage: 'Link to document', openInNewWindow: 'Opens the linked document in a new window or tab', linkToMedia: 'Link to media', selectContentStartNode: 'Select content start node', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts index f465f3c76d..f62092bcea 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/fr-fr.ts @@ -442,7 +442,7 @@ export default { "Modifier la culture d'une langue peut être une opération lourde qui aura pour conséquence la réinitialisation de la cache de contenu et des index", lastEdited: 'Dernière modification', link: 'Lien', - linkinternal: 'Lien interne :', + linkinternal: 'Lien interne', linklocaltip: 'Si vous utilisez des ancres, insérez # au début du lien', linknewwindow: 'Ouvrir dans une nouvelle fenêtre?', macroDoesNotHaveProperties: 'Cette macro ne contient aucune propriété éditable', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts index 827b5e8b09..005f465fcc 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/he-il.ts @@ -178,7 +178,7 @@ export default { inserttable: 'הוסף טבלה', lastEdited: 'נערך לאחרונה', link: 'קישור', - linkinternal: 'קישור פנימי:', + linkinternal: 'קישור פנימי', linklocaltip: 'בעת שימוש בקישוריים פנימיים, הוסף "#" בתחילת הקישור', linknewwindow: 'לפתוח בחלון חדש?', macroDoesNotHaveProperties: 'המאקרו לא מכיל מאפיינים שניתן לערוך', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts index 3519e19060..23ee4b8d21 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/hr-hr.ts @@ -484,7 +484,7 @@ export default { 'Promjena kulture jezika može biti skupa operacija i rezultirat će promjenama u predmemoriji sadržaja i indeksima koji se rekonstruiraju\n ', lastEdited: 'Zadnje uređivano', link: 'Link', - linkinternal: 'Interni link:', + linkinternal: 'Interni link', linklocaltip: 'Kada koristite lokalni linkovi, umetnite "#" ispred linka', linknewwindow: 'Otvoriti u novom prozoru?', macroDoesNotHaveProperties: 'Ovaj makro ne sadrži svojstva koja možete uređivati', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts index 9a7dfb9eec..e991e84f29 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/it-it.ts @@ -495,7 +495,7 @@ export default { "La modifica della cultura di una lingua può essere un'operazione costosa e comporterà la ricostruzione della cache dei contenuti e degli indici", lastEdited: 'Ultima modifica', link: 'Link', - linkinternal: 'Link interno:', + linkinternal: 'Link interno', linklocaltip: 'Quando usi il link locale, inserisci # prima del link', linknewwindow: 'Apri in nuova finestra?', macroContainerSettings: 'Impostazioni della macro', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts index 8f1c6130e6..489fc8c939 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ja-jp.ts @@ -227,7 +227,7 @@ export default { inserttable: '表の挿入', lastEdited: '最近の更新', link: 'リンク', - linkinternal: '内部リンク:', + linkinternal: '内部リンク', linklocaltip: '内部リンクを使うときは、リンクの前に "#" を挿入してください。', linknewwindow: '新規ウィンドウで開きますか?', macroDoesNotHaveProperties: 'このマクロは編集できるプロパティがありません', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts index 961d322c5a..2b3508ca9b 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ko-kr.ts @@ -178,7 +178,7 @@ export default { inserttable: '테이블 삽입', lastEdited: '마지막 수정', link: '링크', - linkinternal: '내부링크:', + linkinternal: '내부링크', linklocaltip: '내부링크를 사용하실 때 링크앞에 "#"를 넣어주세요', linknewwindow: '새 창으로 여시겠습니까?', macroDoesNotHaveProperties: '이 매크로에는 편집할 수 있는 항목이 포함되어 있지 않습니다.', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts index 92e082b4db..f25989e84d 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/nb-no.ts @@ -222,7 +222,7 @@ export default { inserttable: 'Sett inn tabell', lastEdited: 'Sist redigert', link: 'Lenke', - linkinternal: 'Intern link:', + linkinternal: 'Intern link', linklocaltip: 'Ved lokal link, sett inn "#" foran link', linknewwindow: 'Åpne i nytt vindu?', macroDoesNotHaveProperties: 'Denne makroen har ingen egenskaper du kan endre', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts index 9833b8905d..5b7a3e7408 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/nl-nl.ts @@ -452,7 +452,7 @@ export default { 'De cultuur veranderen voor een taal kan een langdurige operatie zijn en zal ertoe\n leiden dat de inhoudscache en indexen opnieuw worden opgebouwd\n ', lastEdited: 'Laatst aangepast op', link: 'Link', - linkinternal: 'Interne link:', + linkinternal: 'Interne link', linklocaltip: 'Plaats een hekje (“#”) voor voor interne links.', linknewwindow: 'In nieuw venster openen?', macroDoesNotHaveProperties: 'Deze macro heeft geen eigenschappen die u kunt bewerken', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts index b02b668dcc..cd22efb437 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/pl-pl.ts @@ -302,7 +302,7 @@ export default { inserttable: 'Wstaw tabelę', lastEdited: 'Ostatnio edytowane', link: 'Link', - linkinternal: 'Link wewnętrzny:', + linkinternal: 'Link wewnętrzny', linklocaltip: 'Kiedy używasz odnośników lokalnych, wstaw znak "#" na początku linku', linknewwindow: 'Otworzyć w nowym oknie?', macroDoesNotHaveProperties: 'To makro nie posiada żadnych właściwości, które można edytować', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts index 5ab8d07bc2..49e374abb5 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/pt-br.ts @@ -178,7 +178,7 @@ export default { inserttable: 'Inserir tabela', lastEdited: 'Última Edição', link: 'Link', - linkinternal: 'Link interno:', + linkinternal: 'Link interno', linklocaltip: 'Ao usar links locais insira "#" na frente do link', linknewwindow: 'Abrir em nova janela?', macroDoesNotHaveProperties: 'Este macro não contém nenhuma propriedade que possa ser editada', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts index 7dd7d145de..4bb00f41c4 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ru-ru.ts @@ -359,7 +359,7 @@ export default { inserttable: 'Вставить таблицу', lastEdited: 'Последняя правка', link: 'Ссылка', - linkinternal: 'Внутренняя ссылка:', + linkinternal: 'Внутренняя ссылка', linklocaltip: 'Для того чтобы определить локальную ссылку, используйте "#" первым символом', linknewwindow: 'Открыть в новом окне?', macroDoesNotHaveProperties: 'Этот макрос не имеет редактируемых свойств', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts index f4f0a7e2da..95ff3be286 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/sv-se.ts @@ -372,7 +372,7 @@ export default { inserttable: 'Infoga tabell', lastEdited: 'Senast redigerad', link: 'Länk', - linkinternal: 'Intern länk:', + linkinternal: 'Intern länk', linklocaltip: 'När du använder lokala länkar, lägg till "#" framför länken', linknewwindow: 'Öppna i nytt fönster?', macroDoesNotHaveProperties: 'Detta makro innehåller inga egenskaper som du kan redigera', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts index 681a683680..a347f09442 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/tr-tr.ts @@ -437,7 +437,7 @@ export default { 'Bir dil için kültürü değiştirmek pahalı bir işlem olabilir ve içerik önbelleğinin ve dizinlerin yeniden oluşturulmasına neden olabilir', lastEdited: 'Son Düzenleme', link: 'Bağlantı', - linkinternal: 'Dahili bağlantı:', + linkinternal: 'Dahili bağlantı', linklocaltip: 'Yerel bağlantıları kullanırken, bağlantının önüne "#" ekleyin', linknewwindow: 'Yeni pencerede açılsın mı?', macroDoesNotHaveProperties: 'Bu makro düzenleyebileceğiniz herhangi bir özellik içermiyor', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts index 687193843a..d480b68234 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/uk-ua.ts @@ -358,7 +358,7 @@ export default { inserttable: 'Вставити таблицю', lastEdited: 'Остання зміна', link: 'Посилання', - linkinternal: 'Внутрішнє посилання:', + linkinternal: 'Внутрішнє посилання', linklocaltip: 'Для визначення локального посилання, використовуйте "#" першим символом', linknewwindow: 'Відкрити у новому вікні?', macroDoesNotHaveProperties: 'Цей макрос не має властивостей, що редагуються.', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts index 1681a72f11..41809f04d0 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-cn.ts @@ -233,7 +233,7 @@ export default { inserttable: '插入表格', lastEdited: '最近编辑', link: '链接', - linkinternal: '内部链接:', + linkinternal: '内部链接', linklocaltip: '本地链接请用“#”号开头', linknewwindow: '在新窗口中打开?', macroDoesNotHaveProperties: '该宏没有可编辑的属性', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts index 6dfd7f5186..3d08d514a5 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/zh-tw.ts @@ -232,7 +232,7 @@ export default { inserttable: '插入表格', lastEdited: '最近編輯', link: '連結', - linkinternal: '內部連結:', + linkinternal: '內部連結', linklocaltip: '本地連結請用“#”號開頭', linknewwindow: '在新視窗中打開?', macroDoesNotHaveProperties: '本巨集沒有包含您可以編輯的屬性', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts index 7ade0434a2..05015e1cf8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts @@ -4,10 +4,12 @@ import { css, customElement, html, + ifDefined, nothing, property, repeat, state, + when, } from '@umbraco-cms/backoffice/external/lit'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @@ -201,12 +203,14 @@ export class UmbInputDocumentElement extends UmbFormControlMixin 0) { return nothing; } else { - return html` `; + return html` + + `; } } @@ -225,16 +229,26 @@ export class UmbInputDocumentElement extends UmbFormControlMixin + name=${item.name} + href=${ifDefined(href)} + ?readonly=${this.readonly} + ?standalone=${this.max === 1}> ${this.#renderIcon(item)} ${this.#renderIsTrashed(item)} - - ${this.#renderOpenButton(item)} ${this.#renderRemoveButton(item)} - + ${when( + !this.readonly, + () => html` + + this.#onRemove(item)}> + + `, + )} `; } @@ -249,25 +263,6 @@ export class UmbInputDocumentElement extends UmbFormControlMixinTrashed
      `; } - #renderRemoveButton(item: UmbDocumentItemModel) { - if (this.readonly) return nothing; - return html` - this.#onRemove(item)} label=${this.localize.term('general_remove')}> - `; - } - - #renderOpenButton(item: UmbDocumentItemModel) { - if (this.readonly) return nothing; - if (!this.showOpenButton) return nothing; - return html` - - ${this.localize.term('general_open')} - - `; - } - static override styles = [ css` #btn-add { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts index 46708951d5..21eb2be780 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts @@ -42,6 +42,7 @@ export class UmbDocumentServerDataSource implements UmbDetailDataSource | undefined; @property({ type: Boolean }) showOpenButton?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts index 89e4f3ee1f..34cdee7872 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts @@ -38,6 +38,7 @@ export class UmbMediaServerDataSource implements UmbDetailDataSource - - ${this.#renderEditAction(href)} ${this.#renderRemoveAction(index)} - + ${when( + !this.readonly, + () => html` + + this.#requestRemoveItem(index)}> + + `, + )} `; } - #renderEditAction(href?: string) { - if (this.readonly || !href) return nothing; - return html` `; - } - - #renderRemoveAction(index: number) { - if (this.readonly) return nothing; - return html` this.#requestRemoveItem(index)} - label=${this.localize.term('general_remove')}>`; - } - static override styles = [ css` #btn-add { diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.element.ts index 88060e1e19..39c8a87112 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.element.ts @@ -1,145 +1,154 @@ -import type { UmbLinkPickerLink, UmbLinkPickerLinkType } from './types.js'; +import type { UmbLinkPickerLink } from './types.js'; import type { UmbLinkPickerConfig, UmbLinkPickerModalData, UmbLinkPickerModalValue, } from './link-picker-modal.token.js'; -import type { UmbTreeElement, UmbTreeSelectionConfiguration } from '@umbraco-cms/backoffice/tree'; -import { css, html, nothing, customElement, query, state, styleMap } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIBooleanInputEvent, UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; +import { css, customElement, html, nothing, query, state, when } from '@umbraco-cms/backoffice/external/lit'; +import { UmbDocumentDetailRepository } from '@umbraco-cms/backoffice/document'; +import { UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import { UMB_DOCUMENT_TREE_ALIAS } from '@umbraco-cms/backoffice/document'; +import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; +import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media'; +import type { UUIBooleanInputEvent, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import { isUmbracoFolder, UmbMediaTypeStructureRepository } from '@umbraco-cms/backoffice/media-type'; + +type UmbInputPickerEvent = CustomEvent & { target: { value?: string } }; @customElement('umb-link-picker-modal') export class UmbLinkPickerModalElement extends UmbModalBaseElement { @state() - private _selectionConfiguration: UmbTreeSelectionConfiguration = { - multiple: false, - selectable: true, - selection: [], - }; - - @state() - _selectedKey?: string; - - /** - * The link object, notice this is frozen, as it comes directly from the State. So it cannot be manipulated. - */ - @state() - readonly _link: UmbLinkPickerLink = {}; - - @state() - _layout: UmbLinkPickerConfig = { + private _config: UmbLinkPickerConfig = { hideAnchor: false, + hideTarget: false, }; @state() - documentExpand = false; + private _allowedMediaTypeIds?: Array; - @state() - mediaExpanded = false; + @query('umb-input-document') + private _documentPickerElement?: UmbInputDocumentElement; - @query('#link-input') - private _linkInput!: UUIInputElement; + @query('umb-input-media') + private _mediaPickerElement?: UmbInputMediaElement; - @query('#anchor-input') - private _linkQueryInput?: UUIInputElement; - - @query('#link-title-input') - private _linkTitleInput!: UUIInputElement; - - override connectedCallback() { - super.connectedCallback(); - if (!this.data) return; - - if (this.modalContext) { - this.observe(this.modalContext.value, (value) => { - (this._link as any) = value.link; - this._selectedKey = this._link?.unique ?? undefined; - this._selectionConfiguration.selection = this._selectedKey ? [this._selectedKey] : []; - }); + override async firstUpdated() { + if (this.data?.config) { + this._config = this.data.config; } - this._layout = this.data?.config; + + // Get all the media types, excluding the folders, so that files are selectable media items. + const mediaTypeStructureRepository = new UmbMediaTypeStructureRepository(this); + const { data: mediaTypes } = await mediaTypeStructureRepository.requestAllowedChildrenOf(null); + this._allowedMediaTypeIds = mediaTypes?.items.map((x) => x.unique).filter((x) => !isUmbracoFolder(x)) ?? []; } - #handleQueryString() { - if (!this._linkQueryInput) return; - const query = this._linkQueryInput.value as string; + #partialUpdateLink(linkObject: Partial) { + this.modalContext?.updateValue({ link: { ...this.value.link, ...linkObject } }); + } + #onLinkAnchorInput(event: UUIInputEvent) { + const query = (event.target.value as string) ?? ''; if (query.startsWith('#') || query.startsWith('?')) { this.#partialUpdateLink({ queryString: query }); return; } if (query.includes('=')) { - this.#partialUpdateLink({ queryString: `#${query}` }); + this.#partialUpdateLink({ queryString: `?${query}` }); } else { this.#partialUpdateLink({ queryString: `#${query}` }); } } - #handleSelectionChange(e: CustomEvent, entityType: string) { - //TODO: Update icon, published, trashed - e.stopPropagation(); - const element = e.target as UmbTreeElement; - const selection = element.getSelection(); - const selectedKey = selection[selection.length - 1]; - - if (!selectedKey) { - this.#partialUpdateLink({ type: undefined, unique: '', url: undefined }); - this._selectedKey = undefined; - this._selectionConfiguration.selection = []; - this.requestUpdate(); - return; - } - - const linkType = (entityType as UmbLinkPickerLinkType) ?? 'external'; - - this._selectedKey = selectedKey; - if (this._selectedKey === undefined) return; - this._selectionConfiguration.selection = [this._selectedKey]; - this.#partialUpdateLink({ type: linkType, unique: selectedKey, url: selectedKey }); - this.requestUpdate(); + #onLinkTitleInput(event: UUIInputEvent) { + this.#partialUpdateLink({ name: event.target.value as string }); } - #partialUpdateLink(linkObject: Partial) { - this.modalContext?.updateValue({ link: { ...this._link, ...linkObject } }); + #onLinkTargetInput(event: UUIBooleanInputEvent) { + this.#partialUpdateLink({ target: event.target.checked ? '_blank' : undefined }); + } + + #onLinkUrlInput(event: UUIInputEvent) { + const url = event.target.value as string; + + let name; + if (url && !this.value.link.name) { + if (URL.canParse(url)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const parts = URL.parse(url); + name = parts?.hostname ?? url; + } else { + name = url; + } + } + + this.#partialUpdateLink({ + name: this.value.link.name || name, + type: 'external', + url, + }); + } + + async #onPickerSelection(event: UmbInputPickerEvent, type: 'document' | 'media') { + let icon, name, url; + const unique = event.target.value; + + if (unique) { + if (type === 'document') { + const documentRepository = new UmbDocumentDetailRepository(this); + const { data: documentData } = await documentRepository.requestByUnique(unique); + if (documentData) { + icon = documentData.documentType.icon; + name = documentData.variants[0].name; + url = documentData.urls[0].url; + } + } + + if (type === 'media') { + const mediaRepository = new UmbMediaDetailRepository(this); + const { data: mediaData } = await mediaRepository.requestByUnique(unique); + if (mediaData) { + icon = mediaData.mediaType.icon; + name = mediaData.variants[0].name; + url = mediaData.urls[0].url; + } + } + } + + const link = { + icon, + name: this.value.link.name || name, + type: unique ? type : undefined, + unique, + url, + }; + + this.#partialUpdateLink(link); + } + + #triggerDocumentPicker() { + this._documentPickerElement?.shadowRoot?.querySelector('#btn-add')?.dispatchEvent(new Event('click')); + } + + #triggerMediaPicker() { + this._mediaPickerElement?.shadowRoot?.querySelector('#btn-add')?.dispatchEvent(new Event('click')); } override render() { return html` - + - - - ${this.localize.term('defaultdialogs_nodeNameLinkPicker')} - this.#partialUpdateLink({ name: this._linkTitleInput.value as string })} - .value="${this._link.name ?? ''}"> - - ${this.localize.term('content_target')} - - ${this.localize.term('defaultdialogs_openInNewWindow')} - - -
      - - ${this.#renderTrees()} + ${this.#renderLinkUrlInput()} ${this.#renderLinkTitleInput()} ${this.#renderLinkTargetInput()} + ${this.#renderInternals()}
      @@ -147,97 +156,131 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement - ${this.localize.term('defaultdialogs_link')} - this.#partialUpdateLink({ type: 'external', url: this._linkInput.value as string })} - ?disabled="${this._link.unique ? true : false}"> - `; - } - - #renderAnchorInput() { - if (this._layout.hideAnchor) return nothing; - return html` - ${this.localize.term('defaultdialogs_anchorLinkPicker')} - - `; - } - - #renderTrees() { - //TODO: Make search work (temporarily disabled) return html` - (this.documentExpand = !this.documentExpand)} - .open=${!this.documentExpand}> - ${this.localize.term('defaultdialogs_linkToPage')} -
      - this.#handleSelectionChange(event, 'document')}> -
      -
      - (this.mediaExpanded = !this.mediaExpanded)} - .open=${!this.mediaExpanded}> - ${this.localize.term('defaultdialogs_linkToMedia')} -
      - this.#handleSelectionChange(event, 'media')}> -
      + +
      + + + + + ${when( + !this._config.hideAnchor, + () => html` + + + + `, + )} +
      +
      + `; + } + + #renderLinkTitleInput() { + return html` + + + + + `; + } + + #renderLinkTargetInput() { + if (this._config.hideTarget) return nothing; + return html` + + + ${this.localize.term('defaultdialogs_openInNewWindow')} + + + `; + } + + #renderInternals() { + return html` + +
      + ${when( + !this.value.link.unique, + () => html` + + + + + `, + )} + this.#onPickerSelection(e, 'document')}> + + this.#onPickerSelection(e, 'media')}> +
      +
      `; } static override styles = [ css` - hr { - border: none; - border-bottom: 1px solid var(--uui-color-divider); - margin-bottom: var(--uui-size-space-3); + uui-box { + --uui-box-default-padding: 0 var(--uui-size-space-5); } - uui-input, - uui-toggle, - uui-label { + uui-button-group { width: 100%; } - uui-input:not(#search-input), - uui-label { - margin-bottom: var(--uui-size-space-6); + uui-input { + width: 100%; } - .url-link { + .side-by-side { display: flex; - gap: var(--uui-size-space-6); - } - .url-link span { - flex: 1 1 0px; - } + flex-wrap: wrap; + gap: var(--uui-size-space-5); - #select-media { - display: block; + umb-property-layout { + flex: 1 1 0px; + } } `, ]; @@ -245,6 +288,8 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement( @@ -19,7 +19,7 @@ export const UMB_LINK_PICKER_MODAL = new UmbModalToken Date: Thu, 24 Oct 2024 10:42:16 +0200 Subject: [PATCH 095/246] Workaround: Ignore discard changes when in a workspace modal (#2481) ignore discard changes when in a workspace modal --- .../workspace/entity-detail/entity-detail-workspace-base.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts index 4a85b64773..e98b1c527a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts @@ -196,6 +196,12 @@ export abstract class UmbEntityDetailWorkspaceContextBase< #onWillNavigate = async (e: CustomEvent) => { const newUrl = e.detail.url; + /* TODO: temp removal of discard changes in workspace modals. + The modal closes before the discard changes dialog is resolved.*/ + if (newUrl.includes('/modal/umb-modal-workspace/')) { + return true; + } + if (this._checkWillNavigateAway(newUrl) && this._data.getHasUnpersistedChanges()) { e.preventDefault(); const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); From c5fd1885cf4e15714c86ee3e440941ed9378fd44 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 24 Oct 2024 12:25:40 +0200 Subject: [PATCH 096/246] Bugfix: Allow breadcrumb for variant root items (#2482) unique can be null so only check for undefined --- .../menu/menu-variant-tree-structure-workspace-context-base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts index 82ba7df803..8d89588a1d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts @@ -45,7 +45,7 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um let structureItems: Array = []; const unique = (await this.observe(uniqueObservable, () => {})?.asPromise()) as string; - if (!unique) throw new Error('Unique is not available'); + if (unique === undefined) throw new Error('Unique is not available'); const entityType = (await this.observe(entityTypeObservable, () => {})?.asPromise()) as string; if (!entityType) throw new Error('Entity type is not available'); From ce8574d20d5c21b26ca70a41e6f7fb35a2ccc3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 19:56:47 +0200 Subject: [PATCH 097/246] document exports --- .../src/packages/documents/documents/audit-log/index.ts | 1 + .../documents/documents/recycle-bin/repository/types.ts | 0 .../src/packages/documents/documents/repository/index.ts | 2 +- .../src/packages/documents/documents/repository/types.ts | 1 + .../src/packages/documents/documents/tree/index.ts | 2 +- .../src/packages/documents/documents/types.ts | 7 +++++++ .../packages/documents/documents/user-permissions/index.ts | 1 + 7 files changed, 12 insertions(+), 2 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts index b8d46eff26..8dd29326e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts @@ -1 +1,2 @@ export { UmbDocumentAuditLogRepository } from './repository/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts index f80023cfbe..80bb409e2b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts @@ -3,4 +3,4 @@ export { UmbDocumentItemRepository, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '. export { UmbDocumentPublishingRepository, UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALIAS } from './publishing/index.js'; export { UmbDocumentPreviewRepository } from './preview/index.js'; -export type { UmbDocumentItemModel } from './item/types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts new file mode 100644 index 0000000000..204e345ff9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts @@ -0,0 +1 @@ +export type { UmbDocumentItemModel } from './item/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts index db48eed3f7..628bc2c8da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts @@ -6,4 +6,4 @@ export { } from './manifests.js'; export { UMB_DOCUMENT_TREE_STORE_CONTEXT } from './document-tree.store.context-token.js'; export type { UmbDocumentTreeStore } from './document-tree.store.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts index 39c63629e1..e73d5a38f3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts @@ -9,6 +9,13 @@ import { DocumentVariantStateModel as UmbDocumentVariantState } from '@umbraco-c import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content'; export { UmbDocumentVariantState }; +export type * from './audit-log/types.js'; +export type * from './collection/types.js'; +export type * from './modals/types.js'; +export type * from './repository/types.js'; +export type * from './tree/types.js'; +export type * from './user-permissions/types.js'; + export interface UmbDocumentDetailModel extends UmbContentDetailModel { documentType: { unique: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts index 4991633288..3ed3c5c183 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts @@ -1,2 +1,3 @@ export * from './repository/index.js'; export * from './constants.js'; +export type * from './types.js'; From ade5c3061fe431f5bcdc85ee971473da40b27c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:05:29 +0200 Subject: [PATCH 098/246] more exports --- src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts | 4 ++-- src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts | 2 ++ .../src/packages/core/collection/index.ts | 2 +- .../src/packages/core/collection/types.ts | 2 +- .../src/packages/core/content-type/index.ts | 4 ++-- .../src/packages/core/content-type/types.ts | 2 ++ .../src/packages/core/entity-action/index.ts | 2 +- .../src/packages/core/entity-bulk-action/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts | 2 +- .../src/packages/core/icon-registry/index.ts | 2 +- 10 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts index 866baaf319..216c98bbe6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts @@ -1,6 +1,6 @@ export * from './context/index.js'; export * from './modals/index.js'; -export type * from './types.js'; +export * from './property-value-resolver/index.js'; export * from './validation/index.js'; export * from './workspace/index.js'; -export * from './property-value-resolver/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index a95b0dab57..fb7bb095bd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,5 +1,7 @@ import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +export type * from './clipboard/types.js'; + export interface UmbBlockLayoutBaseModel { contentKey: string; settingsKey?: string | null; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts index ba4eedfb8a..5123111d27 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts @@ -10,7 +10,7 @@ export * from './collection-item-picker-modal/index.js'; export * from './default/collection-default.context.js'; export * from './default/collection-default.context-token.js'; export * from './collection-filter-model.interface.js'; -export * from './types.js'; +export type * from './types.js'; export { UMB_COLLECTION_ALIAS_CONDITION } from './collection-alias.manifest.js'; export { UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './collection-bulk-action-permission.manifest.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts index 82eceb01ec..bcb35cb4f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts @@ -50,4 +50,4 @@ export interface UmbCollectionContext { totalItems: Observable; } -export * from './extensions/index.js'; +export type * from './extensions/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts index 03701d17e5..79f883296b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts @@ -1,7 +1,7 @@ export * from './components/index.js'; +export * from './composition/index.js'; export * from './modals/index.js'; export * from './repository/index.js'; export * from './structure/index.js'; -export * from './types.js'; export * from './workspace/index.js'; -export * from './composition/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts index 132af25ee5..3d76913002 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts @@ -1,6 +1,8 @@ import type { CompositionTypeModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +export type * from './composition/types.js'; + export type UmbPropertyContainerTypes = 'Group' | 'Tab'; export interface UmbPropertyTypeContainerModel { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts index 0fd5ba6de0..60881da438 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts @@ -5,8 +5,8 @@ export * from './entity-action-list.element.js'; export * from './entity-action.event.js'; export * from './entity-action.extension.js'; export * from './entity-action.interface.js'; -export * from './types.js'; export type * from './entity-action-element.interface.js'; +export type * from './types.js'; export { UmbRequestReloadStructureForEntityEvent } from './request-reload-structure-for-entity.event.js'; export { UmbRequestReloadChildrenOfEntityEvent } from './request-reload-children-of-entity.event.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts index bf14ffa917..601493c5b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts @@ -1,8 +1,8 @@ -export * from './types.js'; export * from './common/index.js'; export * from './entity-bulk-action-base.js'; export * from './entity-bulk-action.element.js'; export * from './entity-bulk-action.interface.js'; export type * from './entity-bulk-action-element.interface.js'; +export type * from './types.js'; export { UMB_ENTITY_BULK_ACTION_DEFAULT_KIND_MANIFEST } from './default/default.action.kind.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index d3f60a90c0..737d7bf482 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,3 +1,3 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts index 1da66f89d4..d2d7785f3b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts @@ -2,5 +2,5 @@ export * from './icon-picker-modal/index.js'; export * from './icon-registry.context-token.js'; export * from './icon-registry.context.js'; export * from './icon.registry.js'; -export * from './types.js'; +export type * from './types.js'; export type * from './extensions/icons.extension.js'; From 0b937031d50121fe3550d25f2b84703ed2080740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:10:48 +0200 Subject: [PATCH 099/246] exort more types --- src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts index 255e8a9ae8..1509c986d2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts @@ -1,9 +1,9 @@ export * from './components/index.js'; export * from './menu-tree-structure-workspace-context-base.js'; export * from './menu-variant-tree-structure-workspace-context-base.js'; -export * from './types.js'; export type * from './menu-item-element.interface.js'; export type * from './menu-item.extension.js'; export type * from './menu.extension.js'; +export type * from './types.js'; export type { UmbMenuStructureWorkspaceContext } from './menu-structure-workspace-context.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts index 55ca1f1885..5403700cff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts @@ -5,4 +5,4 @@ export * from './component/modal-base.element.js'; export * from './component/modal.element.js'; export * from './context/index.js'; export * from './token/index.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts index 3549e429c8..a1c61b09c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts @@ -1,4 +1,4 @@ -export * from './extensions/index.js'; +export type * from './extensions/index.js'; export interface UmbPickerModalData { multiple?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts index b19f3e47db..0074a61d85 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts @@ -1,4 +1,4 @@ export * from './search/index.js'; export * from './picker.context.js'; export * from './picker.context.token.js'; -export * from './types.js'; +export type * from './types.js'; From 170dada1c806f9e6cf87684d8d397fbff984975a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:28:33 +0200 Subject: [PATCH 100/246] refactor collection conditions --- .../src/packages/block/block/types.ts | 1 + .../collection/collection-alias.manifest.ts | 18 -------------- ...lection-bulk-action-permission.manifest.ts | 17 ------------- .../collection-alias.condition.ts | 4 ++-- ...ection-bulk-action-permission.condition.ts | 4 ++-- .../core/collection/conditions/constants.ts | 3 +++ .../core/collection/conditions/index.ts | 4 ++++ .../core/collection/conditions/manifests.ts | 17 +++++++++++++ .../core/collection/conditions/types.ts | 24 +++++++++++++++++++ .../src/packages/core/collection/index.ts | 4 +--- .../src/packages/core/collection/manifests.ts | 6 ++--- .../src/packages/core/collection/types.ts | 1 + .../extension-registry/conditions/types.ts | 4 ++-- 13 files changed, 59 insertions(+), 48 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts rename src/Umbraco.Web.UI.Client/src/packages/core/collection/{ => conditions}/collection-alias.condition.ts (83%) rename src/Umbraco.Web.UI.Client/src/packages/core/collection/{ => conditions}/collection-bulk-action-permission.condition.ts (89%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index fb7bb095bd..4fa4ce6ba0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,5 +1,6 @@ import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +export type * from './conditions/types.js'; export type * from './clipboard/types.js'; export interface UmbBlockLayoutBaseModel { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts deleted file mode 100644 index 52eadd23f3..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { ManifestCondition, UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; - -export type CollectionAliasConditionConfig = UmbConditionConfigBase & { - /** - * The collection that this extension should be available in - * @example - * "Umb.Collection.User" - */ - match: string; -}; - -export const UMB_COLLECTION_ALIAS_CONDITION = 'Umb.Condition.CollectionAlias'; -export const manifest: ManifestCondition = { - type: 'condition', - name: 'Collection Alias Condition', - alias: UMB_COLLECTION_ALIAS_CONDITION, - api: () => import('./collection-alias.condition.js'), -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts deleted file mode 100644 index 17fb2ba24c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { UmbCollectionBulkActionPermissions } from './types.js'; -import type { ManifestCondition, UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; - -export type CollectionBulkActionPermissionConditionConfig = UmbConditionConfigBase< - typeof UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION -> & { - match: (permissions: UmbCollectionBulkActionPermissions) => boolean; -}; - -export const UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION = 'Umb.Condition.CollectionBulkActionPermission'; - -export const manifest: ManifestCondition = { - type: 'condition', - name: 'Collection Bulk Action Permission Condition', - alias: UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, - api: () => import('./collection-bulk-action-permission.condition.js'), -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts similarity index 83% rename from src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts index 166d81e131..6a4a03f6e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts @@ -1,5 +1,5 @@ -import { UMB_COLLECTION_CONTEXT } from './default/index.js'; -import type { CollectionAliasConditionConfig } from './collection-alias.manifest.js'; +import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; +import type { CollectionAliasConditionConfig } from './types.js'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts similarity index 89% rename from src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts index 3b13ad47e2..885ad3f982 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts @@ -1,5 +1,5 @@ -import { UMB_COLLECTION_CONTEXT } from './default/index.js'; -import type { CollectionBulkActionPermissionConditionConfig } from './collection-bulk-action-permission.manifest.js'; +import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; +import type { CollectionBulkActionPermissionConditionConfig } from './types.js'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts new file mode 100644 index 0000000000..36fa086ad7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts @@ -0,0 +1,3 @@ +export const UMB_COLLECTION_ALIAS_CONDITION = 'Umb.Condition.CollectionAlias'; + +export const UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION = 'Umb.Condition.CollectionBulkActionPermission'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts new file mode 100644 index 0000000000..83279e8836 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts @@ -0,0 +1,4 @@ +export * from './collection-bulk-action-permission.condition.js'; +export * from './collection-alias.condition.js'; +export * from './constants.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts new file mode 100644 index 0000000000..3e4eadfc62 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts @@ -0,0 +1,17 @@ +import { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './constants.js'; +import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'Collection Alias Condition', + alias: UMB_COLLECTION_ALIAS_CONDITION, + api: () => import('./collection-alias.condition.js'), + }, + { + type: 'condition', + name: 'Collection Bulk Action Permission Condition', + alias: UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, + api: () => import('./collection-bulk-action-permission.condition.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts new file mode 100644 index 0000000000..11801e6225 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts @@ -0,0 +1,24 @@ +import type { UmbCollectionBulkActionPermissions } from '../types.js'; +import type { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +export type CollectionBulkActionPermissionConditionConfig = UmbConditionConfigBase< + typeof UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION +> & { + match: (permissions: UmbCollectionBulkActionPermissions) => boolean; +}; + +export type CollectionAliasConditionConfig = UmbConditionConfigBase & { + /** + * The collection that this extension should be available in + * @example + * "Umb.Collection.User" + */ + match: string; +}; + +declare global { + interface UmbExtensionConditionConfigMap { + CollectionAliasConditionConfig: CollectionAliasConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts index 5123111d27..ca9701d258 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts @@ -5,6 +5,7 @@ import './components/index.js'; export * from './default/collection-default.element.js'; export * from './collection.element.js'; export * from './components/index.js'; +export * from './conditions/index.js'; export * from './collection-item-picker-modal/index.js'; export * from './default/collection-default.context.js'; @@ -12,8 +13,5 @@ export * from './default/collection-default.context-token.js'; export * from './collection-filter-model.interface.js'; export type * from './types.js'; -export { UMB_COLLECTION_ALIAS_CONDITION } from './collection-alias.manifest.js'; -export { UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './collection-bulk-action-permission.manifest.js'; - export { UmbCollectionActionElement, UmbCollectionActionBase } from './action/index.js'; export type { UmbCollectionDataSource, UmbCollectionRepository } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts index 1ee0674ee8..0e211901ca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts @@ -1,10 +1,8 @@ import type { UmbExtensionManifestKind } from '../extension-registry/registry.js'; -import { manifest as collectionAliasCondition } from './collection-alias.manifest.js'; -import { manifest as collectionBulkActionPermissionCondition } from './collection-bulk-action-permission.manifest.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as workspaceViewManifests } from './workspace-view/manifests.js'; export const manifests: Array = [ ...workspaceViewManifests, - collectionAliasCondition, - collectionBulkActionPermissionCondition, + ...conditionManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts index bcb35cb4f9..8845ccd715 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts @@ -3,6 +3,7 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbPaginationManager } from '@umbraco-cms/backoffice/utils'; export type * from './extensions/index.js'; +export type * from './conditions/types.js'; export interface UmbCollectionBulkActionPermissions { allowBulkCopy: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts index 9005394877..48d244d804 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts @@ -1,5 +1,5 @@ -import type { CollectionAliasConditionConfig } from '../../collection/collection-alias.manifest.js'; -import type { CollectionBulkActionPermissionConditionConfig } from '../../collection/collection-bulk-action-permission.manifest.js'; +import type { CollectionAliasConditionConfig } from '../../collection/conditions/collection-alias.types.js'; +import type { CollectionBulkActionPermissionConditionConfig } from '../../collection/conditions/collection-bulk-action-permission.manifest.js'; import type { SwitchConditionConfig } from './switch.condition.js'; import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; From 6cdef32514f37e98b78224c99b7f9256cea2882e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:29:02 +0200 Subject: [PATCH 101/246] remove reference --- .../packages/core/extension-registry/conditions/types.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts index 48d244d804..ee46b35085 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts @@ -1,13 +1,7 @@ -import type { CollectionAliasConditionConfig } from '../../collection/conditions/collection-alias.types.js'; -import type { CollectionBulkActionPermissionConditionConfig } from '../../collection/conditions/collection-bulk-action-permission.manifest.js'; import type { SwitchConditionConfig } from './switch.condition.js'; import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; -export type UmbCoreConditionConfigs = - | CollectionAliasConditionConfig - | CollectionBulkActionPermissionConditionConfig - | SwitchConditionConfig - | UmbConditionConfigBase; +export type UmbCoreConditionConfigs = SwitchConditionConfig | UmbConditionConfigBase; /** * @deprecated instead use global UmbExtensionConditionConfig From 9d0b0c5f0cceb89600f7111eb3cdbe21aa87bade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 09:32:38 +0200 Subject: [PATCH 102/246] is admin --- .../user/current-user/conditions/is-admin/index.ts | 1 + .../conditions/is-admin/is-admin.condition-config.ts | 12 ++++++++++++ .../packages/user/current-user/conditions/types.ts | 1 + .../src/packages/user/current-user/types.ts | 2 ++ 4 files changed, 16 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts index 4f07201dcf..07a3192a17 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts @@ -1 +1,2 @@ export * from './constants.js'; +export * from './is-admin.condition-config.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts new file mode 100644 index 0000000000..8e8f47a516 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts @@ -0,0 +1,12 @@ +import type { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbIsAdminConditionConfig + extends UmbConditionConfigBase {} + +declare global { + interface UmbExtensionConditionConfigMap { + UmbIsAdminConditionConfig: UmbIsAdminConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts new file mode 100644 index 0000000000..17dc928ab5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts @@ -0,0 +1 @@ +export type * from './is-admin/is-admin.condition-config.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts index 0453be866b..32bd2469e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts @@ -8,6 +8,8 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +export type * from './conditions/types.js'; + export interface UmbCurrentUserModel { allowedSections: Array; avatarUrls: Array; From 9c624e32ba75d21cef3083a1f89c9f2f456d0d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 09:41:33 +0200 Subject: [PATCH 103/246] user conditions --- .../allow-change-password/constants.ts | 1 + .../allow-change-password/manifests.ts | 4 +++- .../user/conditions/allow-delete/constants.ts | 1 + .../user/conditions/allow-delete/manifests.ts | 4 +++- .../conditions/allow-disable/constants.ts | 1 + .../conditions/allow-disable/manifests.ts | 4 +++- .../user/conditions/allow-enable/constants.ts | 1 + .../allow-external-login/constants.ts | 1 + .../allow-external-login/manifests.ts | 4 +++- .../user/conditions/allow-mfa/constants.ts | 1 + .../user/conditions/allow-mfa/manifests.ts | 4 +++- .../user/conditions/allow-unlock/constants.ts | 1 + .../user/conditions/allow-unlock/manifests.ts | 4 +++- .../packages/user/user/conditions/types.ts | 23 +++++++++++++++++++ 14 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts new file mode 100644 index 0000000000..31baf82e9f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS = 'Umb.Condition.User.AllowChangePassword'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts index 368f12e683..568650836e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Change Password Condition', - alias: 'Umb.Condition.User.AllowChangePassword', + alias: UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS, api: () => import('./user-allow-change-password-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts new file mode 100644 index 0000000000..8183df1002 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_DELETE_CONDITION_ALIAS = 'Umb.Condition.User.AllowDeleteAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts index b25eba1462..d05317a682 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_DELETE_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Delete Action Condition', - alias: 'Umb.Condition.User.AllowDeleteAction', + alias: UMB_USER_ALLOW_DELETE_CONDITION_ALIAS, api: () => import('./user-allow-delete-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts new file mode 100644 index 0000000000..965922176c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS = 'Umb.Condition.User.AllowDisableAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts index 34ba7e7d38..a7ce9b3a1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Disable Action Condition', - alias: 'Umb.Condition.User.AllowDisableAction', + alias: UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS, api: () => import('./user-allow-disable-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts new file mode 100644 index 0000000000..f2221ec92a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_ENABLE_CONDITION_ALIAS = 'Umb.Condition.User.AllowEnableAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts new file mode 100644 index 0000000000..8b7e01c6c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS = 'Umb.Condition.User.AllowExternalLoginAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts index 966f5aa137..4ff36ca25c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow ExternalLogin Action Condition', - alias: 'Umb.Condition.User.AllowExternalLoginAction', + alias: UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS, api: () => import('./user-allow-external-login-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts new file mode 100644 index 0000000000..872ba596a7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_MFA_CONDITION_ALIAS = 'Umb.Condition.User.AllowMfaAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts index a9cb89568d..c25c206618 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_MFA_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Mfa Action Condition', - alias: 'Umb.Condition.User.AllowMfaAction', + alias: UMB_USER_ALLOW_MFA_CONDITION_ALIAS, api: () => import('./user-allow-mfa-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts new file mode 100644 index 0000000000..8e29b48475 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS = 'Umb.Condition.User.AllowUnlockAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts index 9fafc5d5be..69c89702a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Unlock Action Condition', - alias: 'Umb.Condition.User.AllowUnlockAction', + alias: UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS, api: () => import('./user-allow-unlock-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts new file mode 100644 index 0000000000..006ccf837d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts @@ -0,0 +1,23 @@ +import type { UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS } from './allow-change-password/constants.js'; +import type { UMB_USER_ALLOW_DELETE_CONDITION_ALIAS } from './allow-delete/constants.js'; +import type { UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS } from './allow-disable/constants.js'; +import type { UMB_USER_ALLOW_ENABLE_CONDITION_ALIAS } from './allow-enable/constants.js'; +import type { UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS } from './allow-external-login/constants.js'; +import type { UMB_USER_ALLOW_MFA_CONDITION_ALIAS } from './allow-mfa/constants.js'; +import type { UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS } from './allow-unlock/constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +type UmbUserConditionConfigs = + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase; + +declare global { + interface UmbExtensionConditionConfigMap { + UmbUserConditionConfigs: UmbUserConditionConfigs; + } +} From 56b5925b0d372458d0c631a7c3abbc773a4590c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:17:34 +0200 Subject: [PATCH 104/246] export types --- .../src/packages/block/block-grid/constants.ts | 2 ++ .../src/packages/block/block-grid/index.ts | 3 ++- .../src/packages/block/block-grid/types.ts | 3 --- .../src/packages/block/block-list/constants.ts | 2 ++ .../src/packages/block/block-list/index.ts | 3 ++- .../src/packages/block/block-list/types.ts | 3 --- .../src/packages/block/block-rte/constants.ts | 2 ++ .../src/packages/block/block-rte/index.ts | 3 ++- .../src/packages/block/block-rte/types.ts | 3 --- .../src/packages/block/block-type/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts | 2 +- .../detail/data-type-detail.server.data-source.ts | 4 ++-- src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts | 6 +++--- .../data-type/workspace/data-type-workspace.context.ts | 4 ++-- .../src/packages/dictionary/collection/index.ts | 2 ++ .../src/packages/dictionary/tree/index.ts | 3 ++- src/Umbraco.Web.UI.Client/src/packages/language/index.ts | 2 +- .../src/packages/media/imaging/index.ts | 2 ++ .../src/packages/media/media-types/index.ts | 3 ++- .../src/packages/media/media/modals/media-picker/index.ts | 2 +- .../src/packages/media/media/tree/index.ts | 2 +- .../src/packages/members/member/collection/index.ts | 2 ++ .../src/packages/members/member/types.ts | 1 + src/Umbraco.Web.UI.Client/src/packages/search/index.ts | 2 +- .../src/packages/templating/partial-views/index.ts | 1 + .../src/packages/templating/scripts/index.ts | 2 +- .../src/packages/templating/stylesheets/index.ts | 7 +++---- src/Umbraco.Web.UI.Client/src/packages/user/index.ts | 5 +++-- .../src/packages/user/user-group/index.ts | 4 ++-- .../src/packages/user/user-permission/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts | 4 ++-- 32 files changed, 51 insertions(+), 39 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts new file mode 100644 index 0000000000..9f70d25c93 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts @@ -0,0 +1,2 @@ +export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; +export const UMB_BLOCK_GRID = 'block-grid'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts index 577eea75f4..79d559f5c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts @@ -1,3 +1,4 @@ +export * from './constants.js'; export * from './context/index.js'; -export * from './types.js'; export * from './workspace/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts index 5f192aedfe..b22f5a7b07 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts @@ -1,9 +1,6 @@ import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockTypeWithGroupKey } from '@umbraco-cms/backoffice/block-type'; -export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; -export const UMB_BLOCK_GRID = 'block-grid'; - // Configuration models: export interface UmbBlockGridTypeModel extends UmbBlockTypeWithGroupKey { columnSpanOptions: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts new file mode 100644 index 0000000000..cae284bdee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts @@ -0,0 +1,2 @@ +export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; +export const UMB_BLOCK_LIST = 'block-list'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts index 577eea75f4..79d559f5c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts @@ -1,3 +1,4 @@ +export * from './constants.js'; export * from './context/index.js'; -export * from './types.js'; export * from './workspace/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts index 94ff232c27..2903ee03b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts @@ -1,9 +1,6 @@ import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; -export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; -export const UMB_BLOCK_LIST = 'block-list'; - // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts new file mode 100644 index 0000000000..4aaa6a7406 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts @@ -0,0 +1,2 @@ +export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; +export const UMB_BLOCK_RTE = 'block-rte'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts index 5ce24a84b0..40cb3510e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts @@ -1,4 +1,5 @@ +export * from './constants.js'; export * from './components/index.js'; export * from './context/index.js'; export * from './workspace/index.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts index f6e44b3beb..c7e8bff28b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts @@ -1,9 +1,6 @@ import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; -export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; -export const UMB_BLOCK_RTE = 'block-rte'; - export interface UmbBlockRteTypeModel extends UmbBlockTypeBaseModel { displayInline: boolean; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts index 814adba5f3..76a7e33393 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts @@ -1,3 +1,3 @@ export * from './components/index.js'; -export * from './types.js'; export * from './workspace/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts index 5b2c179b14..c516f24d51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts @@ -9,4 +9,4 @@ export * from './paths.js'; export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './entity-actions/move-to/index.js'; -export type { UmbDataTypeDetailModel } from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts index 9e31fd975a..3eb91ed61f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts @@ -1,4 +1,4 @@ -import type { UmbDataTypeDetailModel, UmbDataTypePropertyModel } from '../../types.js'; +import type { UmbDataTypeDetailModel, UmbDataTypePropertyValueModel } from '../../types.js'; import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; @@ -70,7 +70,7 @@ export class UmbDataTypeServerDataSource implements UmbDetailDataSource, + values: data.values as Array, }; return { data: dataType }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts index 366f7823f3..53c18c6e45 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts @@ -6,10 +6,10 @@ export interface UmbDataTypeDetailModel { name: string; editorAlias: string | undefined; editorUiAlias: string | null; - values: Array; + values: Array; } -export interface UmbDataTypePropertyModel { +export interface UmbDataTypePropertyValueModel { alias: string; - value: any; + value: ValueType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index d2c01bc008..17944705b7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -1,4 +1,4 @@ -import type { UmbDataTypeDetailModel, UmbDataTypePropertyModel } from '../types.js'; +import type { UmbDataTypeDetailModel, UmbDataTypePropertyValueModel } from '../types.js'; import { type UmbDataTypeDetailRepository, UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_DATA_TYPE_ENTITY_TYPE } from '../entity.js'; import { UmbDataTypeWorkspaceEditorElement } from './data-type-workspace-editor.element.js'; @@ -242,7 +242,7 @@ export class UmbDataTypeWorkspaceContext this.#settingsDefaultData = [ ...this.#propertyEditorSchemaSettingsDefaultData, ...this.#propertyEditorUISettingsDefaultData, - ] satisfies Array; + ] satisfies Array; // We check for satisfied type, because we will be directly transferring them to become value. Future note, if they are not satisfied, we need to transfer alias and value. [NL] this._data.updatePersisted({ values: this.#settingsDefaultData }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts index 1001b2fa0f..ea8abf649f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts @@ -1,2 +1,4 @@ export { UmbDictionaryCollectionRepository } from './repository/index.js'; export { UMB_DICTIONARY_COLLECTION_ALIAS } from './constants.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts index 0940ddc29a..4f23f5ab53 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts @@ -6,4 +6,5 @@ export { } from './constants.js'; export { UMB_DICTIONARY_TREE_STORE_CONTEXT } from './dictionary-tree.store.js'; export { type UmbDictionaryTreeStore } from './dictionary-tree.store.js'; -export * from './types.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/index.ts b/src/Umbraco.Web.UI.Client/src/packages/language/index.ts index 37e1e94844..b3a5c61dcc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/index.ts @@ -7,4 +7,4 @@ export * from './repository/index.js'; export * from './collection/index.js'; export * from './global-contexts/index.js'; -export type { UmbLanguageDetailModel } from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts index d05152d5dc..2b1564e061 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts @@ -1,3 +1,5 @@ export * from './components/index.js'; export { UmbImagingRepository } from './imaging.repository.js'; export { UMB_IMAGING_REPOSITORY_ALIAS } from './constants.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts index 4fdc741116..4c4642c7cb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts @@ -4,8 +4,9 @@ export * from './components/index.js'; export * from './entity.js'; export * from './repository/index.js'; export * from './tree/types.js'; -export * from './types.js'; export * from './utils.ts/index.js'; export * from './workspace/index.js'; +export type * from './types.js'; + export { UMB_MEDIA_TYPE_PICKER_MODAL } from './tree/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts index 134ffc53a6..16952e6ae1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts @@ -1,4 +1,4 @@ export * from './components/index.js'; export * from './media-picker-modal.element.js'; export * from './media-picker-modal.token.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts index ee32f4921b..f46e1142c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts @@ -3,4 +3,4 @@ export { UMB_MEDIA_TREE_REPOSITORY_ALIAS, UMB_MEDIA_TREE_STORE_ALIAS, UMB_MEDIA_ export { UMB_MEDIA_TREE_STORE_CONTEXT } from './media-tree.store.context-token.js'; export { UMB_MEDIA_TREE_PICKER_MODAL } from './media-tree-picker-modal.token.js'; export { type UmbMediaTreeStore } from './media-tree.store.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts index 89461c5f07..7e24407b1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts @@ -1,2 +1,4 @@ export { UmbMemberCollectionRepository } from './repository/index.js'; export { UMB_MEMBER_COLLECTION_ALIAS } from './manifests.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index ca70bdbb59..4a210c544c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -3,6 +3,7 @@ import type { UmbMemberKindType } from './utils/index.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content'; +export type * from './collection/types.js'; export interface UmbMemberDetailModel extends UmbContentDetailModel { email: string; entityType: UmbMemberEntityType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/index.ts b/src/Umbraco.Web.UI.Client/src/packages/search/index.ts index c750f51952..1ed91d9469 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/index.ts @@ -1,4 +1,4 @@ -export type { UmbSearchResultItemModel, UmbSearchRequestArgs, UmbSearchProvider } from './types.js'; +export type * from './types.js'; export type { UmbSearchDataSource } from './search-data-source.interface.js'; export type { UmbSearchRepository } from './search-repository.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts index 2ca9dc61a5..66315e994b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts @@ -1,5 +1,6 @@ export * from './entity.js'; export * from './global-components/index.js'; export * from './repository/index.js'; +export type * from './types.js'; export { UMB_PARTIAL_VIEW_PICKER_MODAL } from './partial-view-picker/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts index cce5d23b51..315274ee1d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts @@ -2,7 +2,7 @@ export * from './entity.js'; export * from './global-components/index.js'; export * from './repository/index.js'; export * from './tree/index.js'; -export * from './types.js'; export * from './workspace/script-workspace.context-token.js'; +export type * from './types.js'; export { UMB_SCRIPT_PICKER_MODAL } from './modals/script-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts index 1848331d21..81b2e7e339 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts @@ -1,10 +1,9 @@ import './global-components/index.js'; -export * from './repository/index.js'; export * from './entity.js'; export * from './global-components/index.js'; +export * from './repository/index.js'; +export * from './utils/index.js'; +export type * from './types.js'; export { UmbStylesheetTreeRepository } from './tree/index.js'; - -// Utils -export { UmbStylesheetRuleManager } from './utils/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/index.ts index dc92400e30..40765df7a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/index.ts @@ -1,4 +1,5 @@ export * from './current-user/index.js'; -export * from './user-group/index.js'; -export * from './user/index.js'; export * from './manifests.js'; +export * from './user-group/index.js'; +export * from './user-permission/index.js'; +export * from './user/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts index ac05b1f292..47adea1251 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts @@ -1,7 +1,7 @@ export * from './collection/index.js'; export * from './components/index.js'; -export * from './repository/index.js'; -export * from './types.js'; export * from './entity.js'; +export * from './repository/index.js'; +export type * from './types.js'; export { UMB_USER_GROUP_PICKER_MODAL } from './modals/user-group-picker/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts index 856a12661c..a23bfc02a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts @@ -3,4 +3,4 @@ export * from './modals/index.js'; export * from './user-granular-permission.extension.js'; export * from './entity-user-permission.extension.js'; -export type { UmbUserPermissionModel } from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts index cbb8fe2fe2..804493858d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts @@ -7,6 +7,8 @@ import { type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; +export type * from './conditions/types.js'; + export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts index db0f1027eb..ebe4439610 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts @@ -1,4 +1,4 @@ +export * from './repository/index.js'; export * from './collection/index.js'; - -export type * from './types.js'; export * from './entity.js'; +export type * from './types.js'; From 2c206d4f3a3f73a16a3214f6dd7298ee58b763c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:22:34 +0200 Subject: [PATCH 105/246] add CollectionBulkActionPermissionConditionConfig --- .../src/packages/core/collection/conditions/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts index 11801e6225..6a19e0a3c9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts @@ -19,6 +19,7 @@ export type CollectionAliasConditionConfig = UmbConditionConfigBase Date: Fri, 25 Oct 2024 10:28:46 +0200 Subject: [PATCH 106/246] export condition types --- .../entity-is-not-trashed.condition-config.ts | 12 ++++++++++++ .../is-trashed/entity-is-trashed.condition-config.ts | 12 ++++++++++++ .../packages/core/recycle-bin/conditions/types.ts | 2 ++ .../src/packages/core/recycle-bin/types.ts | 2 ++ 4 files changed, 28 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts new file mode 100644 index 0000000000..d15c08ade0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts @@ -0,0 +1,12 @@ +import type { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbEntityIsNotTrashedConditionConfig + extends UmbConditionConfigBase {} + +declare global { + interface UmbExtensionConditionConfigMap { + UmbEntityIsNotTrashedConditionConfig: UmbEntityIsNotTrashedConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts new file mode 100644 index 0000000000..9aeff180b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts @@ -0,0 +1,12 @@ +import type { UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbEntityIsTrashedConditionConfig + extends UmbConditionConfigBase {} + +declare global { + interface UmbExtensionConditionConfigMap { + UmbEntityIsTrashedConditionConfig: UmbEntityIsTrashedConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts new file mode 100644 index 0000000000..906a89c23d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts @@ -0,0 +1,2 @@ +export type * from './is-not-trashed/entity-is-not-trashed.condition-config.js'; +export type * from './is-trashed/entity-is-trashed.condition-config.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts index 3a74c7c86f..358d08e0d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts @@ -1,3 +1,5 @@ +export type * from './conditions/types.js'; + export interface UmbRecycleBinRestoreRequestArgs { unique: string; destination: { From 373e542fb5c4ab31a3638fd7854cd22a68484305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:36:33 +0200 Subject: [PATCH 107/246] move section types --- .../src/packages/core/section/extensions/index.ts | 13 ------------- .../src/packages/core/section/extensions/types.ts | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts index 7e9361b328..398e7201da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts @@ -1,19 +1,6 @@ -import type { ManifestSectionRoute } from './section-route.extension.js'; -import type { ManifestSectionSidebarApp } from './section-sidebar-app.extension.js'; -import type { ManifestSectionView } from './section-view.extension.js'; -import type { ManifestSection } from './section.extension.js'; - export type * from './section-route.extension.js'; export type * from './section-sidebar-app.extension.js'; export type * from './section-view.extension.js'; export type * from './section.extension.js'; export type * from './types.js'; - -type UmbSectionExtensions = ManifestSection | ManifestSectionRoute | ManifestSectionSidebarApp | ManifestSectionView; - -declare global { - interface UmbExtensionManifestMap { - UmbSectionExtensions: UmbSectionExtensions; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts index 028e21bc99..e4d5de7f8b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts @@ -1,3 +1,16 @@ export type * from './section-element.interface.js'; export type * from './section-sidebar-app-element.interface.js'; export type * from './section-view-element.interface.js'; + +import type { ManifestSectionRoute } from './section-route.extension.js'; +import type { ManifestSectionSidebarApp } from './section-sidebar-app.extension.js'; +import type { ManifestSectionView } from './section-view.extension.js'; +import type { ManifestSection } from './section.extension.js'; + +type UmbSectionExtensions = ManifestSection | ManifestSectionRoute | ManifestSectionSidebarApp | ManifestSectionView; + +declare global { + interface UmbExtensionManifestMap { + UmbSectionExtensions: UmbSectionExtensions; + } +} From e49a74236ecba019d983969ccf7823863bd6213b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:38:37 +0200 Subject: [PATCH 108/246] tip tap extensions --- .../src/packages/tiptap/extensions/index.ts | 2 -- .../src/packages/tiptap/extensions/tiptap-extension.ts | 2 +- .../src/packages/tiptap/extensions/tiptap-toolbar-extension.ts | 2 +- .../src/packages/tiptap/extensions/types.ts | 3 +++ 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts index 8f09498433..d4702960d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts @@ -1,3 +1 @@ -export type * from './tiptap-extension.js'; -export type * from './tiptap-toolbar-extension.js'; export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts index 619792c6bb..351325ec37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts @@ -15,6 +15,6 @@ export interface MetaTiptapExtension { declare global { interface UmbExtensionManifestMap { - tiptapExtension: ManifestTiptapExtension; + umbTiptapExtension: ManifestTiptapExtension; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts index 3c178b4e85..36d5c74f4a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts @@ -25,6 +25,6 @@ export interface ManifestTiptapToolbarExtensionButtonKind< declare global { interface UmbExtensionManifestMap { - tiptapToolbarExtension: ManifestTiptapToolbarExtension | ManifestTiptapToolbarExtensionButtonKind; + umbTiptapToolbarExtension: ManifestTiptapToolbarExtension | ManifestTiptapToolbarExtensionButtonKind; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts index ec2bcc1f8c..49fa890922 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts @@ -5,6 +5,9 @@ import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/exte import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +export type * from './tiptap-extension.js'; +export type * from './tiptap-toolbar-extension.js'; + export interface UmbTiptapExtensionApi extends UmbApi { /** * The manifest for the extension. From 2febbc5f4ca672df670ab8399fe1d307597825d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:41:11 +0200 Subject: [PATCH 109/246] ufm types --- .../src/packages/tiptap/extensions/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts index d4702960d5..06c33f562f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts @@ -1 +1 @@ -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts index f0f1ade33d..72d8944e05 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts @@ -1,2 +1,4 @@ export * from './components/index.js'; export * from './extensions/index.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts index 1d9964b88b..fcbfd9b7eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts @@ -1,6 +1,8 @@ import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockRteLayoutModel } from '@umbraco-cms/backoffice/block-rte'; +export type * from './extensions/types.js'; + // TODO: Rename this type: export interface UmbPropertyEditorUiValueType { markup: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts index 066099c1db..8b2395e4a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts @@ -1,5 +1,6 @@ import type { UmbUfmFilterApi } from './ufm-filter.extension.js'; +// TODO: this is not a type, in TypeScript world, as it is an actual class. So it should be moved elsewhere [NL] export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { abstract filter(...args: Array): string | undefined | null; destroy() {} From 64b7d1194c16738560243b993143457daa7befbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:43:56 +0200 Subject: [PATCH 110/246] fix tsc --- .../workspace/block-grid-type-workspace.modal-token.ts | 3 ++- .../views/block-grid-type-workspace-view-advanced.element.ts | 2 +- .../components/block-list-entry/block-list-entry.element.ts | 3 ++- ...property-editor-ui-block-list-type-configuration.element.ts | 2 +- .../components/block-rte-entry/block-rte-entry.element.ts | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts index 61b344ca99..fdd64d49ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts @@ -1,4 +1,5 @@ -import { UMB_BLOCK_GRID_TYPE, type UmbBlockGridTypeModel } from '../types.js'; +import type { UmbBlockGridTypeModel } from '../types.js'; +import { UMB_BLOCK_GRID_TYPE } from '../constants.js'; import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts index 9879949f7c..c11ea6c9b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts @@ -1,4 +1,4 @@ -import { UMB_BLOCK_GRID } from '../../types.js'; +import { UMB_BLOCK_GRID } from '../../constants.js'; import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 1075f327bc..b318a804d2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -1,5 +1,6 @@ import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js'; -import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js'; +import type { UmbBlockListLayoutModel } from '../../types.js'; +import { UMB_BLOCK_LIST } from '../../constants.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts index 772b8068c2..054b47d124 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts @@ -1,5 +1,5 @@ import '../../../block-type/components/input-block-type/index.js'; -import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; +import { UMB_BLOCK_LIST_TYPE } from '../../constants.js'; import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; import { type UmbPropertyEditorUiElement, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index f835c064c1..1082b890dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -1,4 +1,5 @@ -import { UMB_BLOCK_RTE, type UmbBlockRteLayoutModel } from '../../types.js'; +import type { UmbBlockRteLayoutModel } from '../../types.js'; +import { UMB_BLOCK_RTE } from '../../constants.js'; import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; From 5d2ca17198dbab40fbcfe80acfe2102370aaedd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:51:56 +0200 Subject: [PATCH 111/246] move abstract classes out of types --- .../src/packages/tiptap/extensions/base.ts | 61 +++++++++++++++++++ .../src/packages/tiptap/extensions/index.ts | 1 + .../src/packages/tiptap/extensions/types.ts | 52 ---------------- .../src/packages/ufm/filters/base.filter.ts | 6 ++ .../src/packages/ufm/index.ts | 3 +- .../src/packages/ufm/types.ts | 8 +-- 6 files changed, 71 insertions(+), 60 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts new file mode 100644 index 0000000000..3fba20f6ba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts @@ -0,0 +1,61 @@ +import type { + ManifestTiptapExtension, + ManifestTiptapToolbarExtension, + UmbTiptapExtensionApi, + UmbTiptapExtensionArgs, + UmbTiptapToolbarElementApi, +} from './types.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap'; +import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; + +export abstract class UmbTiptapExtensionApiBase extends UmbControllerBase implements UmbTiptapExtensionApi { + /** + * The manifest for the extension. + */ + manifest?: ManifestTiptapExtension; + + /** + * The editor instance. + */ + protected _editor?: Editor; + + /** + * @inheritdoc + */ + setEditor(editor: Editor): void { + this._editor = editor; + } + + /** + * @inheritdoc + */ + abstract getTiptapExtensions(args?: UmbTiptapExtensionArgs): Array; +} + +export abstract class UmbTiptapToolbarElementApiBase extends UmbControllerBase implements UmbTiptapToolbarElementApi { + /** + * The manifest for the extension. + */ + manifest?: ManifestTiptapToolbarExtension; + + /** + * The data type configuration for the property editor that the editor is used for. + */ + configuration?: UmbPropertyEditorConfigCollection; + + /** + * A method to execute the toolbar element action. + */ + public abstract execute(editor: Editor): void; + + /** + * Informs the toolbar element if it is active or not. It uses the manifest meta alias to check if the toolbar element is active. + * @see {ManifestTiptapToolbarExtension} + * @param {Editor} editor The editor instance. + * @returns {boolean} Returns true if the toolbar element is active. + */ + public isActive(editor: Editor) { + return editor && this.manifest?.meta.alias ? editor?.isActive(this.manifest.meta.alias) : false; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts index 06c33f562f..ffd2be35b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts @@ -1 +1,2 @@ +export * from './base.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts index 49fa890922..67bdb4adfc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts @@ -1,6 +1,5 @@ import type { ManifestTiptapExtension } from './tiptap-extension.js'; import type { ManifestTiptapToolbarExtension } from './tiptap-toolbar-extension.js'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @@ -25,30 +24,6 @@ export interface UmbTiptapExtensionApi extends UmbApi { getTiptapExtensions(args?: UmbTiptapExtensionArgs): Array; } -export abstract class UmbTiptapExtensionApiBase extends UmbControllerBase implements UmbTiptapExtensionApi { - /** - * The manifest for the extension. - */ - manifest?: ManifestTiptapExtension; - - /** - * The editor instance. - */ - protected _editor?: Editor; - - /** - * @inheritdoc - */ - setEditor(editor: Editor): void { - this._editor = editor; - } - - /** - * @inheritdoc - */ - abstract getTiptapExtensions(args?: UmbTiptapExtensionArgs): Array; -} - export interface UmbTiptapExtensionArgs { /** * The data type configuration for the property editor that the editor is used for. @@ -74,30 +49,3 @@ export interface UmbTiptapToolbarElementApi extends UmbApi, UmbTiptapExtensionAr */ isActive(editor: Editor): boolean; } - -export abstract class UmbTiptapToolbarElementApiBase extends UmbControllerBase implements UmbTiptapToolbarElementApi { - /** - * The manifest for the extension. - */ - manifest?: ManifestTiptapToolbarExtension; - - /** - * The data type configuration for the property editor that the editor is used for. - */ - configuration?: UmbPropertyEditorConfigCollection; - - /** - * A method to execute the toolbar element action. - */ - public abstract execute(editor: Editor): void; - - /** - * Informs the toolbar element if it is active or not. It uses the manifest meta alias to check if the toolbar element is active. - * @see {ManifestTiptapToolbarExtension} - * @param {Editor} editor The editor instance. - * @returns {boolean} Returns true if the toolbar element is active. - */ - public isActive(editor: Editor) { - return editor && this.manifest?.meta.alias ? editor?.isActive(this.manifest.meta.alias) : false; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts new file mode 100644 index 0000000000..76433cbe17 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts @@ -0,0 +1,6 @@ +import type { UmbUfmFilterApi } from '../ufm-filter.extension.js'; + +export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { + abstract filter(...args: Array): string | undefined | null; + destroy() {} +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts index 481d5818a8..4eee789e2b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts @@ -1,6 +1,7 @@ -export * from './types.js'; export * from './components/index.js'; export * from './contexts/index.js'; +export * from './filters/base.filter.js'; export * from './plugins/index.js'; +export * from './types.js'; export * from './ufm-component.extension.js'; export * from './ufm-filter.extension.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts index 8b2395e4a6..5a25901cdb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts @@ -1,7 +1 @@ -import type { UmbUfmFilterApi } from './ufm-filter.extension.js'; - -// TODO: this is not a type, in TypeScript world, as it is an actual class. So it should be moved elsewhere [NL] -export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { - abstract filter(...args: Array): string | undefined | null; - destroy() {} -} +export type * from './ufm-filter.extension.js'; From 456566e0e29797770fcc06596dc852b31583093b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:55:17 +0200 Subject: [PATCH 112/246] imports --- .../packages/tiptap/extensions/core/embedded-media.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/figure.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/image.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/link.extension.ts | 2 +- .../packages/tiptap/extensions/core/media-upload.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/subscript.extension.ts | 2 +- .../packages/tiptap/extensions/core/superscript.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/table.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/text-align.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/underline.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/blockquote.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/bold.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/bullet-list.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/code-block.extension.ts | 2 +- .../tiptap/extensions/toolbar/embedded-media.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/heading1.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/heading2.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/heading3.extension.ts | 2 +- .../tiptap/extensions/toolbar/horizontal-rule.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/italic.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/link.extension.ts | 2 +- .../tiptap/extensions/toolbar/media-picker.extension.ts | 2 +- .../tiptap/extensions/toolbar/ordered-list.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/redo.extension.ts | 2 +- .../tiptap/extensions/toolbar/source-editor.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/strike.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/subscript.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/superscript.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/table.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-center.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-justify.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-left.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-right.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/underline.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/undo.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/unlink.extension.ts | 2 +- .../src/packages/ufm/filters/fallback.filter.ts | 2 +- .../src/packages/ufm/filters/lowercase.filter.ts | 2 +- .../src/packages/ufm/filters/strip-html.filter.ts | 2 +- .../src/packages/ufm/filters/title-case.filter.ts | 2 +- .../src/packages/ufm/filters/truncate.filter.ts | 2 +- .../src/packages/ufm/filters/uppercase.filter.ts | 2 +- .../src/packages/ufm/filters/word-limit.filter.ts | 2 +- 43 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts index 0e64a0153a..4cbc0188f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { umbEmbeddedMedia } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapEmbeddedMediaExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts index 1da6bdec35..0b879bb89e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Figure, Figcaption } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapFigureExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts index 7254da3b61..7bb79bf2c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { UmbImage } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapImageExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts index 4800000fda..e09d36f5dc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { UmbLink } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapLinkExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts index 22fe093aaa..b6770bc230 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import type { UmbTiptapExtensionArgs } from '../types.js'; import { imageSize } from '@umbraco-cms/backoffice/utils'; import { Extension } from '@umbraco-cms/backoffice/external/tiptap'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts index 57bfb91472..be83a3236e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Subscript } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapBoldExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts index 453efb13e5..e7757efc5d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Superscript } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapBoldExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts index d8c00b5d39..d3acf8c647 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Table, TableHeader, TableRow, TableCell } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapTableExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts index 9855c4d150..3d2598d5e3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { TextAlign } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapTextAlignExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts index f9663f91c8..3946d0b259 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Underline } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapUnderlineExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts index f061e7e6b6..efd704be60 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarBlockquoteExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts index 5ec1124963..8206a62dc4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarBoldExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts index 983adb0c3d..79fb5d338f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarBulletListExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts index a3a30b0f5d..f1c8930516 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarCodeBlockExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts index b50872c1f0..0a91f0801b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { umbEmbeddedMedia } from '@umbraco-cms/backoffice/external/tiptap'; import { UMB_EMBEDDED_MEDIA_MODAL } from '@umbraco-cms/backoffice/embedded-media'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts index b301f438e1..a9fd015ba9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHeading1ExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts index 663bc09d22..1274bd0e26 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHeading2ExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts index 3c3aed7cba..cb40b09cde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHeading3ExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts index 58836d2257..2ac3ddd0ab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHorizontalRuleExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts index 2ac2c77649..9e329a1c37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarItalicExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts index 3c1ef5f0af..31760d8f07 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { UmbLink } from '@umbraco-cms/backoffice/external/tiptap'; import { UMB_LINK_PICKER_MODAL } from '@umbraco-cms/backoffice/multi-url-picker'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts index 0ba24357bd..e77af1787d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { getGuidFromUdi, getProcessedImageUrl, imageSize } from '@umbraco-cms/backoffice/utils'; import { ImageCropModeModel } from '@umbraco-cms/backoffice/external/backend-api'; import { UMB_MEDIA_CAPTION_ALT_TEXT_MODAL, UMB_MEDIA_PICKER_MODAL } from '@umbraco-cms/backoffice/media'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts index f95d7da3d2..26956cfcde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { OrderedList, ListItem } from '@umbraco-cms/backoffice/external/tiptap'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts index 0aae301bba..74c6696158 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarRedoExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts index 7ff4fcd4ca..b40bd86234 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { UMB_CODE_EDITOR_MODAL } from '@umbraco-cms/backoffice/code-editor'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts index 1428e2009b..7062ab000e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarStrikeExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts index 121e5210a6..d78312e01e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarSubscriptExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts index d46e966d29..5da21dc34d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarSuperscriptExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts index 3ef38f6f13..3589f6f138 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTableExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts index a027bc18c1..683f9cef2c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignCenterExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts index 38a53fc008..10e4825664 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignJustifyExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts index 86b90b7e81..df6fb9fedb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignLeftExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts index 8f3984bb5c..1f0c703b87 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignRightExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts index 9a2aab8b50..f0c91ab0af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarUnderlineExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts index 1cc600442b..63b6183323 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarUndoExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts index a3137f6ec5..947ff35307 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarUnlinkExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts index ceb8001754..fe99db94a3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmFallbackFilterApi extends UmbUfmFilterBase { filter(str: string, fallback: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts index bf175a2a65..3b70e65cee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmLowercaseFilterApi extends UmbUfmFilterBase { filter(str?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts index 6d19708e59..98b7e394d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmStripHtmlFilterApi extends UmbUfmFilterBase { filter(value: string | { markup: string } | undefined | null) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts index ab546b7ee3..d4204a6203 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmTitleCaseFilterApi extends UmbUfmFilterBase { filter(str?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts index 34360ae41d..49d78554af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmTruncateFilterApi extends UmbUfmFilterBase { filter(str: string, length: number, tail?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts index 76af187aa9..b260f195fc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmUppercaseFilterApi extends UmbUfmFilterBase { filter(str?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts index 8924386638..6abaea4680 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmWordLimitFilterApi extends UmbUfmFilterBase { filter(str: string, limit: number) { From 64f018da37b45dc8b2371181aa497ef9ede26b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 11:45:32 +0200 Subject: [PATCH 113/246] en + da translation --- src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 1 + src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index d7d5b6d9be..77dff557f4 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -901,6 +901,7 @@ export default { avatar: 'Avatar til', header: 'Overskrift', systemField: 'system felt', + readOnly: 'Skrivebeskyttet', restore: 'Genskab', generic: 'Generic', media: 'Media', 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 0421ac8467..4ba60e0705 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -47,6 +47,7 @@ export default { notify: 'Notifications', protect: 'Public Access', publish: 'Publish', + readOnly: 'Read-only', refreshNode: 'Reload', remove: 'Remove', rename: 'Rename', From 368d0a0b0c5e6072a0c492c62f5b66df3036933b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 25 Oct 2024 14:10:54 +0200 Subject: [PATCH 114/246] Merge pull request #2470 from bjarnef/bug/content-type-design-editor-property-zindex Remove z-index from header in content type design editor property --- .../views/design/content-type-design-editor-property.element.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts index b34a765d96..02374f4f8a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts @@ -414,7 +414,6 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement { position: sticky; top: var(--uui-size-space-4); height: min-content; - z-index: 2; } #editor { From 48b9c7e232e043e7e4bc94647062b63ff9805e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 15:04:41 +0200 Subject: [PATCH 115/246] variant block validation --- .../property-editor-ui-block-list.element.ts | 1 - ...y-validation-path-translator.controller.ts | 28 ------------------- ...-validation-path-translator.controller.ts} | 0 ...s-validation-path-translator.controller.ts | 17 +++++++++++ .../packages/block/block/validation/index.ts | 3 +- .../block/workspace/block-element-manager.ts | 9 ++++++ ...-workspace-view-edit-properties.element.ts | 26 +++++++++++++++++ .../property/property/property.element.ts | 1 - ...data-path-property-value-query.function.ts | 4 +-- 9 files changed, 56 insertions(+), 33 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts rename src/Umbraco.Web.UI.Client/src/packages/block/block/validation/{block-data-validation-path-translator.controller.ts => block-element-data-validation-path-translator.controller.ts} (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 3accdffc9c..32ad807db5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -118,7 +118,6 @@ export class UmbPropertyEditorUIBlockListElement /** * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. * @type {boolean} - * @attr * @default */ @property({ type: Boolean, reflect: true }) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts deleted file mode 100644 index 096eec3967..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { - GetPropertyNameFromPath, - UmbDataPathPropertyValueQuery, - UmbValidationPathTranslatorBase, -} from '@umbraco-cms/backoffice/validation'; - -export class UmbBlockElementDataValidationPathTranslator extends UmbValidationPathTranslatorBase { - constructor(host: UmbControllerHost) { - super(host); - } - - translate(path: string) { - if (!this._context) return; - if (path.indexOf('$.') !== 0) { - // We do not handle this path. - return false; - } - - const rest = path.substring(2); - const key = GetPropertyNameFromPath(rest); - - const specificValue = { alias: key }; - // replace the values[ number ] with JSON-Path filter values[@.(...)], continues by the rest of the path: - //return '$.values' + UmbVariantValuesValidationPathTranslator(specificValue) + path.substring(path.indexOf(']')); - return '$.values[' + UmbDataPathPropertyValueQuery(specificValue) + '.value'; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-validation-path-translator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-data-validation-path-translator.controller.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-validation-path-translator.controller.ts rename to src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-data-validation-path-translator.controller.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts new file mode 100644 index 0000000000..2c2b9da88c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts @@ -0,0 +1,17 @@ +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { + UmbAbstractArrayValidationPathTranslator, + UmbDataPathPropertyValueQuery, +} from '@umbraco-cms/backoffice/validation'; + +export class UmbBlockElementValuesDataValidationPathTranslator extends UmbAbstractArrayValidationPathTranslator { + constructor(host: UmbControllerHost) { + super(host, '$.values[', UmbDataPathPropertyValueQuery); + } + + getDataFromIndex(index: number) { + if (!this._context) return; + const data = this._context.getTranslationData(); + return data.values[index]; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts index 331352a0d8..f2af316128 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts @@ -1,2 +1,3 @@ -export * from './block-data-validation-path-translator.controller.js'; +export * from './block-element-values-validation-path-translator.controller.js'; +export * from './block-element-data-validation-path-translator.controller.js'; export * from './data-path-element-data-query.function.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index 868fbb81bb..cef6c15939 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -1,4 +1,5 @@ import type { UmbBlockDataModel, UmbBlockDataValueModel } from '../types.js'; +import { UmbBlockElementValuesDataValidationPathTranslator } from '../validation/block-element-values-validation-path-translator.controller.js'; import { UmbBlockElementPropertyDatasetContext } from './block-element-property-dataset.context.js'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type'; @@ -40,6 +41,11 @@ export class UmbBlockElementManager extends UmbControllerBase { constructor(host: UmbControllerHost, dataPathPropertyName: string) { super(host); + console.log('dataPathPropertyName', dataPathPropertyName); + if (dataPathPropertyName === 'contentData') { + this.validation.messages.debug(dataPathPropertyName); + } + this.observe(this.contentTypeId, (id) => this.structure.loadType(id)); this.observe(this.unique, (key) => { if (key) { @@ -198,6 +204,9 @@ export class UmbBlockElementManager extends UmbControllerBase { // Provide Validation Context for this view: this.validation.provideAt(host); + + // TODO: Implement ctrl alias. + new UmbBlockElementValuesDataValidationPathTranslator(host); } public override destroy(): void { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts index cd570f360d..1b1acc7425 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts @@ -5,6 +5,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/content-type'; import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; @customElement('umb-block-workspace-view-edit-properties') export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { @@ -38,12 +40,22 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { @state() private _ownerEntityType?: string; + #variantId?: UmbVariantId; + constructor() { super(); this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspaceContext) => { this.#blockWorkspace = workspaceContext; this._ownerEntityType = this.#blockWorkspace.getEntityType(); + this.observe( + workspaceContext.variantId, + (variantId) => { + this.#variantId = variantId; + this.#generatePropertyDataPath(); + }, + 'observeVariantId', + ); this.#setStructureManager(); }); } @@ -61,10 +73,24 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { ); } + /* #generatePropertyDataPath() { if (!this._propertyStructure) return; this._dataPaths = this._propertyStructure.map((property) => `$.${property.alias}`); } + */ + + #generatePropertyDataPath() { + if (!this.#variantId || !this._propertyStructure) return; + this._dataPaths = this._propertyStructure.map( + (property) => + `$.values[${UmbDataPathPropertyValueQuery({ + alias: property.alias, + culture: property.variesByCulture ? this.#variantId!.culture : null, + segment: property.variesBySegment ? this.#variantId!.segment : null, + })}].value`, + ); + } override render() { return repeat( diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts index 7fbd02e7ba..e069c69ccb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property/property.element.ts @@ -130,7 +130,6 @@ export class UmbPropertyElement extends UmbLitElement { * DataPath, declare the path to the value of the data that this property represents. * @public * @type {string} - * @attr * @default */ @property({ type: String, attribute: 'data-path' }) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts index d184f6e205..438b6e2d6e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts @@ -5,8 +5,8 @@ import type { UmbVariantPropertyValueModel } from '@umbraco-cms/backoffice/varia * Validation Data Path Query generator for Property Value. * write a JSON-Path filter similar to `?(@.alias = 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')` * where culture and segment are optional - * @param value - * @returns + * @param {UmbVariantPropertyValueModel} value - the object holding value and alias. + * @returns {string} - a JSON-path query */ export function UmbDataPathPropertyValueQuery( value: UmbPartialSome, 'culture' | 'segment'>, From b24bedb93af93e55f3be31f184c409c37d07c331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 15:14:32 +0200 Subject: [PATCH 116/246] update to use == in JSON Path Queries --- .../block-grid-entries.element.ts | 2 +- .../data-path-element-data-query.function.ts | 6 ++-- .../block/workspace/block-element-manager.ts | 2 +- .../src/packages/core/validation/README.md | 8 ++--- .../controllers/validation.controller.ts | 4 +-- ...data-path-property-value-query.function.ts | 8 ++--- .../utils/data-path-variant-query.function.ts | 4 +-- .../validation/utils/json-path.function.ts | 33 ++++++------------- .../core/validation/utils/json-path.test.ts | 2 +- 9 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts index 4df96b1c01..50074d598c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts @@ -149,7 +149,7 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen // Currently there is no server validation for areas. So we can leave out the data path for it for now. [NL] this.#controlValidator = new UmbFormControlValidator(this, this); - //new UmbBindServerValidationToFormControl(this, this, "$.values.[?(@.alias = 'my-input-alias')].value"); + //new UmbBindServerValidationToFormControl(this, this, "$.values.[?(@.alias == 'my-input-alias')].value"); } } public get areaKey(): string | null | undefined { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts index 517e393897..1d624a3123 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts @@ -2,14 +2,14 @@ import type { UmbBlockDataModel } from '../types.js'; /** * Validation Data Path Query generator for Block Element Data. - * write a JSON-Path filter similar to `?(@.key = 'my-key://1234')` + * write a JSON-Path filter similar to `?(@.key == 'my-key://1234')` * @param key {string} - The key of the block Element data. * @param data {{key: string}} - A data object with the key property. * @returns */ export function UmbDataPathBlockElementDataQuery(data: Pick): string { // write a array of strings for each property, where alias must be present and culture and segment are optional - //const filters: Array = [`@.key = '${key}'`]; + //const filters: Array = [`@.key == '${key}'`]; //return `?(${filters.join(' && ')})`; - return `?(@.key = '${data.key}')`; + return `?(@.key == '${data.key}')`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index cef6c15939..72ae4aaf01 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -49,7 +49,7 @@ export class UmbBlockElementManager extends UmbControllerBase { this.observe(this.contentTypeId, (id) => this.structure.loadType(id)); this.observe(this.unique, (key) => { if (key) { - this.validation.setDataPath('$.' + dataPathPropertyName + `[?(@.key = '${key}')]`); + this.validation.setDataPath('$.' + dataPathPropertyName + `[?(@.key == '${key}')]`); } }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md b/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md index d034fb6ca4..b5a79df4e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md @@ -15,7 +15,7 @@ A Validation message consist of a type, path and body. This typically looks like ``` { type: "client", - path: "$.values[?(@.alias = 'my-property-alias')].value", + path: "$.values[?(@.alias == 'my-property-alias')].value", message: "Must contain at least 3 words" } ``` @@ -61,7 +61,7 @@ Data: JsonPath: ``` -"$.values.[?(@.alias = 'my-alias')].value" +"$.values.[?(@.alias == 'my-alias')].value" ``` Paths are based on JSONPath, using JSON Path Queries when looking up data of an Array. Using Queries enables Paths to not point to specific index, but what makes a entry unique. @@ -107,7 +107,7 @@ Such conversation could be from this path: To this path: ``` -"$.values.[?(@.alias = 'my-alias')].value" +"$.values.[?(@.alias == 'my-alias')].value" ``` Once this path is converted to use Json Path Queries, the Data can be changed. The concerned entry might get another index. Without that affecting the accuracy of the path. @@ -135,7 +135,7 @@ The Data Path is a JSON Path defining where the data of this input is located in this.#validationMessageBinder = new UmbBindServerValidationToFormControl( this, this.querySelector('#myInput"), - "$.values.[?(@.alias = 'my-input-alias')].value", + "$.values.[?(@.alias == 'my-input-alias')].value", ); ``` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts index 594b65ca45..bdae375157 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts @@ -100,10 +100,10 @@ export class UmbValidationController extends UmbControllerBase implements UmbVal * @example * ```ts * const validationContext = new UmbValidationContext(this); - * validationContext.setDataPath("$.values[?(@.alias='my-property')].value"); + * validationContext.setDataPath("$.values[?(@.alias == 'my-property')].value"); * ``` * - * A message with the path: '$.values[?(@.alias='my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context. + * A message with the path: '$.values[?(@.alias == 'my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context. */ setDataPath(dataPath: string): void { if (this.#baseDataPath) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts index 438b6e2d6e..76fb54ce10 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts @@ -3,7 +3,7 @@ import type { UmbVariantPropertyValueModel } from '@umbraco-cms/backoffice/varia /** * Validation Data Path Query generator for Property Value. - * write a JSON-Path filter similar to `?(@.alias = 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')` + * write a JSON-Path filter similar to `?(@.alias == 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')` * where culture and segment are optional * @param {UmbVariantPropertyValueModel} value - the object holding value and alias. * @returns {string} - a JSON-path query @@ -12,12 +12,12 @@ export function UmbDataPathPropertyValueQuery( value: UmbPartialSome, 'culture' | 'segment'>, ): string { // write a array of strings for each property, where alias must be present and culture and segment are optional - const filters: Array = [`@.alias = '${value.alias}'`]; + const filters: Array = [`@.alias == '${value.alias}'`]; if (value.culture !== undefined) { - filters.push(`@.culture = ${value.culture ? `'${value.culture}'` : 'null'}`); + filters.push(`@.culture == ${value.culture ? `'${value.culture}'` : 'null'}`); } if (value.segment !== undefined) { - filters.push(`@.segment = ${value.segment ? `'${value.segment}'` : 'null'}`); + filters.push(`@.segment == ${value.segment ? `'${value.segment}'` : 'null'}`); } return `?(${filters.join(' && ')})`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts index 25666269cd..175b744992 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts @@ -12,9 +12,9 @@ export function UmbDataPathVariantQuery( value: UmbPartialSome, 'segment'>, ): string { // write a array of strings for each property, where culture must be present and segment is optional - const filters: Array = [`@.culture = ${value.culture ? `'${value.culture}'` : 'null'}`]; + const filters: Array = [`@.culture == ${value.culture ? `'${value.culture}'` : 'null'}`]; if (value.segment !== undefined) { - filters.push(`@.segment = ${value.segment ? `'${value.segment}'` : 'null'}`); + filters.push(`@.segment == ${value.segment ? `'${value.segment}'` : 'null'}`); } return `?(${filters.join(' && ')})`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts index c7c1244fc0..40ceb3f9da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts @@ -1,9 +1,10 @@ /** * - * @param data - * @param path + * @param {object} data - object to traverse for the value. + * @param {string} path - the JSON path to the value that should be found + * @returns {unknown} - the found value. */ -export function GetValueByJsonPath(data: any, path: string): any { +export function GetValueByJsonPath(data: unknown, path: string): unknown { // strip $ from the path: const strippedPath = path.startsWith('$.') ? path.slice(2) : path; // get value from the path: @@ -12,23 +13,9 @@ export function GetValueByJsonPath(data: any, path: string): any { /** * - * @param path - */ -export function GetPropertyNameFromPath(path: string): string { - // find next '.' or '[' in the path, using regex: - const match = path.match(/\.|\[/); - // If no match is found, we assume its a single key so lets return the value of the key: - if (match === null || match.index === undefined) return path; - - // split the path at the first match: - return path.slice(0, match.index); -} - -/** - * - * @param data - * @param path - * @returns {any} + * @param {object} data - object to traverse for the value. + * @param {string} path - the JSON path to the value that should be found + * @returns {unknown} - the found value. */ function GetNextPropertyValueFromPath(data: any, path: string): any { if (!data) return undefined; @@ -90,8 +77,8 @@ function GetNextPropertyValueFromPath(data: any, path: string): any { } /** - * @param filter - * @returns {Array<(queryFilter: any) => boolean>} - array of methods that returns true if the given items property value matches the value of the query. + * @param {string} filter - A JSON Query, limited to filtering features. Do not support other JSON PATH Query features. + * @returns {Array<(queryFilter: any) => boolean>} - An array of methods that returns true if the given items property value matches the value of the query. */ function JsFilterFromJsonPathFilter(filter: string): Array<(item: any) => boolean> { // strip ?( and ) from the filter @@ -101,7 +88,7 @@ function JsFilterFromJsonPathFilter(filter: string): Array<(item: any) => boolea // map each part to a function that returns true if the part is true return parts.map((part) => { // split the part into key and value - const [path, equal] = part.split(' = '); + const [path, equal] = part.split(' == '); // remove @. const key = path.slice(2); // remove quotes: diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts index 3673b28ecd..906463e1e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts @@ -30,7 +30,7 @@ describe('UmbJsonPathFunctions', () => { }); it('query of first entry in an array', () => { - const result = GetValueByJsonPath({ values: [{ id: '123', value: 'test' }] }, "$.values[?(@.id = '123')].value"); + const result = GetValueByJsonPath({ values: [{ id: '123', value: 'test' }] }, "$.values[?(@.id == '123')].value"); expect(result).to.eq('test'); }); From b08e87978aedece85c95a80fcae8fa385cb5a306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 19:47:16 +0200 Subject: [PATCH 117/246] clean up --- .../property-editor-ui-block-list.element.ts | 2 -- .../packages/block/block/workspace/block-element-manager.ts | 5 ----- 2 files changed, 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 32ad807db5..c09879f9a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -155,8 +155,6 @@ export class UmbPropertyEditorUIBlockListElement constructor() { super(); - //this.#validationContext.messages.debug('block list'); - this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { this.observe( context.dataPath, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index 72ae4aaf01..efadfcfb2e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -41,11 +41,6 @@ export class UmbBlockElementManager extends UmbControllerBase { constructor(host: UmbControllerHost, dataPathPropertyName: string) { super(host); - console.log('dataPathPropertyName', dataPathPropertyName); - if (dataPathPropertyName === 'contentData') { - this.validation.messages.debug(dataPathPropertyName); - } - this.observe(this.contentTypeId, (id) => this.structure.loadType(id)); this.observe(this.unique, (key) => { if (key) { From 0aeaf9ab6537b2c4cd6ac8d2ac2fe0cf38c4f531 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 28 Oct 2024 10:24:50 +0000 Subject: [PATCH 118/246] Bugfix: Prevent delete a template when has children (#2479) * Adds "Template Has No Children Condition" to prevent the "delete" action being displayed for templates that have child templates. * Removed condition config type it didn't have any configurable properties. Lazy-loaded the manifest api. * Renamed "Template Has No Children" condition to "Template Allow Delete Action" condition. --- .../conditions/allow-delete/const.ts | 1 + .../conditions/allow-delete/manifest.ts | 8 +++++++ .../template-allow-delete-action.condition.ts | 22 +++++++++++++++++++ .../templates/conditions/manifests.ts | 3 +++ .../templates/entity-actions/manifests.ts | 2 ++ .../templating/templates/manifests.ts | 2 ++ 6 files changed, 38 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts new file mode 100644 index 0000000000..b986c98f18 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts @@ -0,0 +1 @@ +export const UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS = 'Umb.Condition.Template.AllowDeleteAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts new file mode 100644 index 0000000000..37a4793a92 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts @@ -0,0 +1,8 @@ +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from './const.js'; + +export const manifest: UmbExtensionManifest = { + type: 'condition', + name: 'Template Allow Delete Action Condition', + alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS, + api: () => import('./template-allow-delete-action.condition.js'), +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts new file mode 100644 index 0000000000..c1550dab72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts @@ -0,0 +1,22 @@ +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_TREE_ITEM_CONTEXT } from '@umbraco-cms/backoffice/tree'; +import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbTemplateAllowDeleteActionCondition extends UmbConditionBase implements UmbExtensionCondition { + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + + this.consumeContext(UMB_TREE_ITEM_CONTEXT, (context) => { + this.observe( + context.hasChildren, + (hasChildren) => { + this.permitted = hasChildren === false; + }, + '_templateAllowDeleteActionCondition', + ); + }); + } +} + +export { UmbTemplateAllowDeleteActionCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts new file mode 100644 index 0000000000..731fde0ccd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as templateAllowDeleteActionCondition } from './allow-delete/manifest.js'; + +export const manifests: Array = [templateAllowDeleteActionCondition]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts index fb548f4166..7912a433e2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts @@ -1,5 +1,6 @@ import { UMB_TEMPLATE_DETAIL_REPOSITORY_ALIAS, UMB_TEMPLATE_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_TEMPLATE_ENTITY_TYPE, UMB_TEMPLATE_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from '../conditions/allow-delete/const.js'; export const manifests: Array = [ { @@ -26,5 +27,6 @@ export const manifests: Array = [ detailRepositoryAlias: UMB_TEMPLATE_DETAIL_REPOSITORY_ALIAS, itemRepositoryAlias: UMB_TEMPLATE_ITEM_REPOSITORY_ALIAS, }, + conditions: [{ alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS }], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts index eb8a2594d5..da057a5daa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts @@ -1,3 +1,4 @@ +import { manifests as conditionsManifests } from './conditions/manifests.js'; import { manifests as entityActionsManifests } from './entity-actions/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; @@ -7,6 +8,7 @@ import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; export const manifests: Array = [ + ...conditionsManifests, ...entityActionsManifests, ...menuManifests, ...modalManifests, From c9f8f62b844e7f163d2d5b84d02992f9a22fc56d Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Mon, 28 Oct 2024 11:28:00 +0100 Subject: [PATCH 119/246] Tags matchlist on top of following markdown toolbar (#2489) Set z-index of matchlist to ensure on top of following markdown toolbar --- .../packages/tags/components/tags-input/tags-input.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts index bbe9e20bae..2c51692616 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts @@ -393,7 +393,6 @@ export class UmbTagsInputElement extends UUIFormControlMixin(UmbLitElement, '') } #matchlist { - display: none; display: flex; flex-direction: column; background-color: var(--uui-color-surface); @@ -403,6 +402,7 @@ export class UmbTagsInputElement extends UUIFormControlMixin(UmbLitElement, '') top: var(--uui-size-space-6); border-radius: var(--uui-border-radius); border: 1px solid var(--uui-color-border); + z-index: 10; } #matchlist label { From 92028a2b1cfb7429684d9f516d4a5eb6cd89f18d Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Mon, 28 Oct 2024 11:28:00 +0100 Subject: [PATCH 120/246] Tags matchlist on top of following markdown toolbar (#2489) Set z-index of matchlist to ensure on top of following markdown toolbar (cherry picked from commit c9f8f62b844e7f163d2d5b84d02992f9a22fc56d) --- .../packages/tags/components/tags-input/tags-input.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts index bbe9e20bae..2c51692616 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.element.ts @@ -393,7 +393,6 @@ export class UmbTagsInputElement extends UUIFormControlMixin(UmbLitElement, '') } #matchlist { - display: none; display: flex; flex-direction: column; background-color: var(--uui-color-surface); @@ -403,6 +402,7 @@ export class UmbTagsInputElement extends UUIFormControlMixin(UmbLitElement, '') top: var(--uui-size-space-6); border-radius: var(--uui-border-radius); border: 1px solid var(--uui-color-border); + z-index: 10; } #matchlist label { From 9b94b4abc9aa298a6f60c46bfc536eea6d38423b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:35:32 +0100 Subject: [PATCH 121/246] Bugfix: Hide template input when there are no allowed templates (#2484) hide template input when there are no allowed templates --- .../document-workspace-view-info.element.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index c6a42baecf..f19154a2aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -206,7 +206,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { #renderGeneralSection() { const editDocumentTypePath = this._routeBuilder?.({ entityType: 'document-type' }) ?? ''; - const editTemplatePath = this._routeBuilder?.({ entityType: 'template' }) ?? ''; return html`
      @@ -224,6 +223,20 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
      + ${this.#renderTemplateInput()} +
      + Id + ${this._documentUnique} +
      + `; + } + + #renderTemplateInput() { + if (this._allowedTemplates?.length === 0) return nothing; + + const editTemplatePath = this._routeBuilder?.({ entityType: 'template' }) ?? ''; + + return html`
      Template ${this._templateUnique @@ -247,10 +260,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { @click=${this.#openTemplatePicker}> `}
      -
      - Id - ${this._documentUnique} -
      `; } From 2d9e8d0a4c87bc915ef6161d28e36769a4a1ada2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:39:45 +0100 Subject: [PATCH 122/246] align naming --- .../allow-delete/{const.ts => constants.ts} | 0 .../templates/conditions/allow-delete/index.ts | 1 + .../conditions/allow-delete/manifest.ts | 16 +++++++++------- .../templating/templates/conditions/index.ts | 1 + .../templating/templates/conditions/manifests.ts | 4 ++-- .../templates/entity-actions/manifests.ts | 2 +- .../src/packages/templating/templates/index.ts | 1 + 7 files changed, 15 insertions(+), 10 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/{const.ts => constants.ts} (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts rename to src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts index 37a4793a92..d1aac15331 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts @@ -1,8 +1,10 @@ -import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from './const.js'; +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from './constants.js'; -export const manifest: UmbExtensionManifest = { - type: 'condition', - name: 'Template Allow Delete Action Condition', - alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS, - api: () => import('./template-allow-delete-action.condition.js'), -}; +export const manifests: Array = [ + { + type: 'condition', + name: 'Template Allow Delete Action Condition', + alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS, + api: () => import('./template-allow-delete-action.condition.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts new file mode 100644 index 0000000000..dc6ddce39a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts @@ -0,0 +1 @@ +export * from './allow-delete/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts index 731fde0ccd..d11b41693e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts @@ -1,3 +1,3 @@ -import { manifest as templateAllowDeleteActionCondition } from './allow-delete/manifest.js'; +import { manifests as allowDeleteManifests } from './allow-delete/manifest.js'; -export const manifests: Array = [templateAllowDeleteActionCondition]; +export const manifests: Array = [...allowDeleteManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts index 7912a433e2..4816de0c1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts @@ -1,6 +1,6 @@ import { UMB_TEMPLATE_DETAIL_REPOSITORY_ALIAS, UMB_TEMPLATE_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_TEMPLATE_ENTITY_TYPE, UMB_TEMPLATE_ROOT_ENTITY_TYPE } from '../entity.js'; -import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from '../conditions/allow-delete/const.js'; +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from '../conditions/allow-delete/constants.js'; export const manifests: Array = [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts index 392b743cee..9bec7964b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts @@ -5,5 +5,6 @@ export * from './entity.js'; export * from './modals/index.js'; export * from './repository/index.js'; export * from './tree/index.js'; +export * from './conditions/index.js'; export type { UmbTemplateDetailModel } from './types.js'; From 18f1df46a5625fe8af8cde89747a3b944593f21a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:41:45 +0100 Subject: [PATCH 123/246] Hotfix: Publish with decendants structure reload (#2486) * ensure we always have the latest variant data * use enum value * Update document-tree-item.element.ts * only dispatch event if there is no error * reload structure after publish with descendants * only request update if it succeeds * rename private method --- .../entity-actions/unpublish.action.ts | 16 ++++--- .../tree-item/document-tree-item.element.ts | 17 ++++--- .../workspace/document-workspace.context.ts | 45 ++++++++++++++----- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts index ff9d645a17..46d3471ea3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts @@ -77,15 +77,17 @@ export class UmbUnpublishDocumentEntityAction extends UmbEntityActionBase if (variantIds.length) { const publishingRepository = new UmbDocumentPublishingRepository(this._host); - await publishingRepository.unpublish(this.args.unique, variantIds); + const { error } = await publishingRepository.unpublish(this.args.unique, variantIds); - const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadStructureForEntityEvent({ - unique: this.args.unique, - entityType: this.args.entityType, - }); + if (!error) { + const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadStructureForEntityEvent({ + unique: this.args.unique, + entityType: this.args.entityType, + }); - actionEventContext.dispatchEvent(event); + actionEventContext.dispatchEvent(event); + } } } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts index 3c5c94c536..634f3d8bad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts @@ -1,4 +1,5 @@ import type { UmbDocumentTreeItemModel, UmbDocumentTreeItemVariantModel } from '../types.js'; +import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { css, html, nothing, customElement, state, classMap } from '@umbraco-cms/backoffice/external/lit'; import type { UmbAppLanguageContext } from '@umbraco-cms/backoffice/language'; import { UMB_APP_LANGUAGE_CONTEXT } from '@umbraco-cms/backoffice/language'; @@ -31,7 +32,7 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase { this._currentCulture = value; - this._variant = this.#getVariant(value); + this._variant = this.#findVariant(value); }); } @@ -41,7 +42,7 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase x.culture === culture); } @@ -56,16 +57,22 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase ({ variantId })), ); - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadStructureForEntityEvent({ - unique: this.getUnique()!, - entityType: this.getEntityType(), - }); + if (!error) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadStructureForEntityEvent({ + unique: this.getUnique()!, + entityType: this.getEntityType(), + }); - eventContext.dispatchEvent(event); + eventContext.dispatchEvent(event); + } } async #handleSave() { @@ -826,6 +828,12 @@ export class UmbDocumentWorkspaceContext } public async publishWithDescendants() { + const unique = this.getUnique(); + if (!unique) throw new Error('Unique is missing'); + + const entityType = this.getEntityType(); + if (!entityType) throw new Error('Entity type is missing'); + const { options, selected } = await this.#determineVariantOptions(); const modalManagerContext = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); @@ -847,13 +855,30 @@ export class UmbDocumentWorkspaceContext if (!variantIds.length) return; - const unique = this.getUnique(); - if (!unique) throw new Error('Unique is missing'); - await this.publishingRepository.publishWithDescendants( + const { error } = await this.publishingRepository.publishWithDescendants( unique, variantIds, result.includeUnpublishedDescendants ?? false, ); + + if (!error) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + + // request reload of this entity + const structureEvent = new UmbRequestReloadStructureForEntityEvent({ + entityType, + unique, + }); + + // request reload of the children + const childrenEvent = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(structureEvent); + eventContext.dispatchEvent(childrenEvent); + } } async delete() { From 848ddb774b8fdf72d15d270bd619627fac74c6c4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:48:32 +0100 Subject: [PATCH 124/246] Hotfix: Correct user enable notification (#2487) * show localized notification when user is enabled * localize disable messages --- .../disable/disable-user.repository.ts | 17 ++++++++++++++++- .../repository/enable/enable-user.repository.ts | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts index d7c94c6beb..81bc35ff41 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts @@ -1,10 +1,14 @@ import { UmbUserRepositoryBase } from '../user-repository-base.js'; +import { UmbUserItemRepository } from '../item/index.js'; import { UmbDisableUserServerDataSource } from './disable-user.server.data-source.js'; +import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDisableUserRepository extends UmbUserRepositoryBase { #disableSource: UmbDisableUserServerDataSource; + #localize = new UmbLocalizationController(this); + #userItemRepository = new UmbUserItemRepository(this); constructor(host: UmbControllerHost) { super(host); @@ -18,11 +22,22 @@ export class UmbDisableUserRepository extends UmbUserRepositoryBase { const { data, error } = await this.#disableSource.disable(ids); if (!error) { + const { data: items } = await this.#userItemRepository.requestItems(ids); + if (!items) throw new Error('Could not load user item'); + + // TODO: get state from item when available ids.forEach((id) => { this.detailStore?.updateItem(id, { state: UserStateModel.DISABLED }); }); - const notification = { data: { message: `User disabled` } }; + let message = this.#localize.term('speechBubbles_disableUsersSuccess', items.length); + + if (items.length === 1) { + const names = items?.map((item) => item.name).join(', '); + message = this.#localize.term('speechBubbles_disableUserSuccess', names); + } + + const notification = { data: { message } }; this.notificationContext?.peek('positive', notification); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts index 2728c4807d..4c871e5fd5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts @@ -1,10 +1,14 @@ import { UmbUserRepositoryBase } from '../user-repository-base.js'; +import { UmbUserItemRepository } from '../item/index.js'; import { UmbEnableUserServerDataSource } from './enable-user.server.data-source.js'; +import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbEnableUserRepository extends UmbUserRepositoryBase { #enableSource: UmbEnableUserServerDataSource; + #localize = new UmbLocalizationController(this); + #userItemRepository = new UmbUserItemRepository(this); constructor(host: UmbControllerHost) { super(host); @@ -18,11 +22,22 @@ export class UmbEnableUserRepository extends UmbUserRepositoryBase { const { data, error } = await this.#enableSource.enable(ids); if (!error) { + const { data: items } = await this.#userItemRepository.requestItems(ids); + if (!items) throw new Error('Could not load user item'); + + // TODO: get state from item when available ids.forEach((id) => { this.detailStore?.updateItem(id, { state: UserStateModel.ACTIVE }); }); - const notification = { data: { message: `User disabled` } }; + let message = this.#localize.term('speechBubbles_enableUsersSuccess', items.length); + + if (items.length === 1) { + const names = items?.map((item) => item.name).join(', '); + message = this.#localize.term('speechBubbles_enableUserSuccess', names); + } + + const notification = { data: { message } }; this.notificationContext?.peek('positive', notification); } From 0858ea8423ad3b026a7f0d87699a5663c8b411c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 28 Oct 2024 13:56:37 +0100 Subject: [PATCH 125/246] deprecate ManifestTypes --- .../core/extension-registry/models/index.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index 7c562c37af..2b3c1e5178 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -1,6 +1,29 @@ import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; -export type ManifestTypes = ManifestBundle | ManifestCondition | ManifestBase; +/** + * @deprecated Follow these steps to get Extension Manifest Type for v.15+ projects: + * + * Setup your `tsconfig.json` to include the extension-types as global types. Like this: + * ``` + { + "compilerOptions": { + ... + "types": [ + "@umbraco-cms/backoffice/extension-types" + ] + } + } + * ``` + * + * Once done, you can use the global type `UmbExtensionManifest`. + * + * If defining your own extension types, then follow the link below for more information. + * + * [Read more on the change announcement]{https://github.com/umbraco/Announcements/issues/22} + */ +export type ManifestTypes = never; + +type UmbCoreManifestTypes = ManifestBundle | ManifestCondition | ManifestBase; type UnionOfProperties = T extends object ? T[keyof T] : never; @@ -25,7 +48,7 @@ declare global { ``` */ interface UmbExtensionManifestMap { - UMB_CORE: ManifestTypes; + UMB_CORE: UmbCoreManifestTypes; } /** From c9332ad03c00cd75909481f76691f17ca7e62ab8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 14:56:14 +0100 Subject: [PATCH 126/246] wip add entity-create-option-action extension point --- .../entity-create-option-action.element.ts | 87 ++++++++++++++ .../create-option-action/default/index.ts | 1 + .../create-option-action/default/manifests.ts | 20 ++++ .../create-option-action/default/types.ts | 44 +++++++ .../entity-create-option-action-base.ts | 27 +++++ ...-create-option-action-element.interface.ts | 4 + ...ntity-create-option-action-list.element.ts | 108 ++++++++++++++++++ .../entity-create-option-action.extension.ts | 13 +++ .../entity-create-option-action.interface.ts | 17 +++ .../core/entity/create-option-action/index.ts | 7 ++ .../entity/create-option-action/manifests.ts | 4 + .../core/entity/create-option-action/types.ts | 5 + 12 files changed, 337 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts new file mode 100644 index 0000000000..5c926bbe3e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts @@ -0,0 +1,87 @@ +import type { UmbEntityCreateOptionAction } from '../entity-create-option-action.interface.js'; +import type { UmbEntityCreateOptionActionElement } from '../entity-create-option-action-element.interface.js'; +import type { ManifestEntityCreateOptionAction } from '../entity-create-option-action.extension.js'; +import type { MetaEntityCreateOptionActionDefaultKind } from './types.js'; +import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; +import { html, nothing, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import type { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-entity-create-option-action'; +@customElement(elementName) +export class UmbEntityCreateOptionActionDefaultElement< + MetaType extends MetaEntityCreateOptionActionDefaultKind = MetaEntityCreateOptionActionDefaultKind, + ApiType extends UmbEntityCreateOptionAction = UmbEntityCreateOptionAction, + > + extends UmbLitElement + implements UmbEntityCreateOptionActionElement +{ + #api?: ApiType; + + // TODO: Do these need to be properties? [NL] + @property({ type: String }) + entityType?: string | null; + + // TODO: Do these need to be properties? [NL] + @property({ type: String }) + public unique?: string | null; + + @property({ attribute: false }) + public manifest?: ManifestEntityCreateOptionAction; + + public set api(api: ApiType | undefined) { + this.#api = api; + + // TODO: Fix so when we use a HREF it does not refresh the page? + this.#api?.getHref?.().then((href) => { + this._href = href; + // TODO: Do we need to update the component here? [NL] + }); + } + + @state() + _href?: string; + + override async focus() { + await this.updateComplete; + this.shadowRoot?.querySelector('uui-menu-item')?.focus(); + } + + async #onClickLabel(event: UUIMenuItemEvent) { + if (!this._href) { + event.stopPropagation(); + await this.#api?.execute(); + } + this.dispatchEvent(new UmbActionExecutedEvent()); + } + + // TODO: we need to stop the regular click event from bubbling up to the table so it doesn't select the row. + // This should probably be handled in the UUI Menu item component. so we don't dispatch a label-click event and click event at the same time. + #onClick(event: PointerEvent) { + event.stopPropagation(); + } + + override render() { + const label = this.manifest?.meta.label ? this.localize.string(this.manifest.meta.label) : this.manifest?.name; + + return html` + + ${this.manifest?.meta.icon + ? html`` + : nothing} + + `; + } +} + +export { UmbEntityCreateOptionActionDefaultElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbEntityCreateOptionActionDefaultElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts new file mode 100644 index 0000000000..d4702960d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts @@ -0,0 +1 @@ +export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts new file mode 100644 index 0000000000..b1b7de24bf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts @@ -0,0 +1,20 @@ +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.EntityCreateOptionAction.Default', + matchKind: 'default', + matchType: 'entityCreateOptionAction', + manifest: { + type: 'entityCreateOptionAction', + kind: 'default', + weight: 1000, + element: () => import('./entity-create-option-action.element.js'), + meta: { + icon: '', + label: 'Default Entity Create Option Action', + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts new file mode 100644 index 0000000000..465664c91c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts @@ -0,0 +1,44 @@ +import type { + ManifestEntityCreateOptionAction, + MetaEntityCreateOptionAction, +} from '../entity-create-option-action.extension.js'; + +export interface ManifestEntityCreateOptionActionDefaultKind + extends ManifestEntityCreateOptionAction { + type: 'entityCreateOptionAction'; + kind: 'default'; +} + +export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { + /** + * An icon to represent the action to be performed + * @examples [ + * "icon-box", + * "icon-grid" + * ] + */ + icon: string; + + /** + * The friendly name of the action to perform + * @examples [ + * "Create", + * "Create Content Template" + * ] + */ + label: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + * @memberof MetaEntityCreateOptionActionDefaultKind + */ + additionalOptions?: boolean; +} + +declare global { + interface UmbExtensionManifestMap { + umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts new file mode 100644 index 0000000000..c8daf62492 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts @@ -0,0 +1,27 @@ +import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; +import { UmbActionBase } from '@umbraco-cms/backoffice/action'; + +export abstract class UmbEntityCreateOptionActionBase + extends UmbActionBase> + implements UmbEntityCreateOptionAction +{ + /** + * By specifying the href, the action will act as a link. + * The `execute` method will not be called. + * @abstract + * @returns {string | undefined} + */ + public getHref(): Promise { + return Promise.resolve(undefined); + } + + /** + * By specifying the `execute` method, the action will act as a button. + * @abstract + * @returns {Promise} + */ + public execute(): Promise { + return Promise.resolve(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts new file mode 100644 index 0000000000..6f2c9ab833 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts @@ -0,0 +1,4 @@ +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbEntityCreateOptionActionElement extends UmbControllerHostElement {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts new file mode 100644 index 0000000000..082816e24f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts @@ -0,0 +1,108 @@ +import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { + ManifestEntityCreateOptionAction, + MetaEntityCreateOptionAction, +} from './entity-create-option-action.extension.js'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; +import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbApiConstructorArgumentsMethodType } from '@umbraco-cms/backoffice/extension-api'; + +const elementName = 'umb-entity-create-option-action-list'; +@customElement(elementName) +export class UmbEntityCreateOptionActionListElement extends UmbLitElement { + @property({ type: String, attribute: 'entity-type' }) + public get entityType(): string | undefined { + return this._props.entityType; + } + public set entityType(value: string | undefined) { + if (value === undefined || value === this._props.entityType) return; + this._props.entityType = value; + this.#generateApiArgs(); + this.requestUpdate('_props'); + // Update filter: + //const oldValue = this._filter; + this._filter = (extension: ManifestEntityCreateOptionAction) => + extension.forEntityTypes.includes(value); + //this.requestUpdate('_filter', oldValue); + } + + @state() + _filter?: (extension: ManifestEntityCreateOptionAction) => boolean; + + @property({ type: String }) + public get unique(): string | null | undefined { + return this._props.unique; + } + public set unique(value: string | null | undefined) { + if (value === this._props.unique) return; + this._props.unique = value; + this.#generateApiArgs(); + this.requestUpdate('_props'); + } + + @state() + _props: Partial> = {}; + + @state() + _apiArgs?: UmbApiConstructorArgumentsMethodType< + ManifestEntityCreateOptionAction, + [UmbEntityCreateOptionActionArgs] + >; + + #entityContext = new UmbEntityContext(this); + + #generateApiArgs() { + if (!this._props.entityType || this._props.unique === undefined) return; + + this.#entityContext.setEntityType(this._props.entityType); + this.#entityContext.setUnique(this._props.unique); + this.#hasRenderedOnce = false; + + this._apiArgs = (manifest: ManifestEntityCreateOptionAction) => { + return [{ entityType: this._props.entityType!, unique: this._props.unique!, meta: manifest.meta }]; + }; + } + + #hasRenderedOnce?: boolean; + override render() { + return this._filter + ? html` + { + if (!this.#hasRenderedOnce && i === 0) { + // TODO: Replace this block: + ext.component?.updateComplete.then(async () => { + const menuitem = ext.component?.shadowRoot?.querySelector('uui-menu-item'); + menuitem?.updateComplete.then(async () => { + menuitem?.shadowRoot?.querySelector('#label-button')?.focus?.(); + }); + }); + // end of block, with this, when this PR is part of UI Lib: https://github.com/umbraco/Umbraco.UI/pull/789 + // ext.component?.focus(); + this.#hasRenderedOnce = true; + } + return ext.component; + }}> + ` + : ''; + } + + static override styles = [ + css` + :host { + --uui-menu-item-flat-structure: 1; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbEntityCreateOptionActionListElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts new file mode 100644 index 0000000000..2835753767 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts @@ -0,0 +1,13 @@ +import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; + +export interface ManifestEntityCreateOptionAction< + MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, +> extends ManifestElementAndApi, + ManifestWithDynamicConditions { + type: 'entityCreateOptionAction'; + forEntityTypes: Array; + meta: MetaType; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface MetaEntityCreateOptionAction {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts new file mode 100644 index 0000000000..0956868cb7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts @@ -0,0 +1,17 @@ +import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { UmbAction } from '@umbraco-cms/backoffice/action'; + +export interface UmbEntityCreateOptionAction + extends UmbAction> { + /** + * The href location, the action will act as a link. + * @returns {Promise} + */ + getHref(): Promise; + + /** + * The `execute` method, the action will act as a button. + * @returns {Promise} + */ + execute(): Promise; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts new file mode 100644 index 0000000000..c3a44c8f72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts @@ -0,0 +1,7 @@ +export * from './default/index.js'; +export * from './entity-create-option-action-base.js'; +export * from './entity-create-option-action-list.element.js'; +export * from './entity-create-option-action.extension.js'; +export * from './entity-create-option-action.interface.js'; +export * from './types.js'; +export type * from './entity-create-option-action-element.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts new file mode 100644 index 0000000000..84f3b7f88d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as defaultEntityActionManifests } from './default/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...defaultEntityActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts new file mode 100644 index 0000000000..ca6db2fc24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts @@ -0,0 +1,5 @@ +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; + +export interface UmbEntityCreateOptionActionArgs extends UmbEntityModel { + meta: MetaArgsType; +} From 4863745181902720d790b70c7d20adae5be3fd90 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Mon, 28 Oct 2024 15:07:06 +0100 Subject: [PATCH 127/246] Content type group sorting placeholder (#2471) * Make it more clear when content type groups are re-arranged * Hide header slot with input --- .../views/design/content-type-design-editor-group.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts index 31059a012f..ead29d145b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts @@ -228,7 +228,7 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement { opacity: 0.5; } - :host([drag-placeholder]) > * { + :host([drag-placeholder]) > uui-box > * { visibility: hidden; } From b21ae95010e519a29ae889f8d8e00668fbfcde19 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 15:08:14 +0100 Subject: [PATCH 128/246] add global-components folder --- .../entity-create-option-action-list.element.ts | 4 ++-- .../create-option-action/global-components/index.ts | 3 +++ .../packages/core/entity/create-option-action/index.ts | 9 +++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/{ => global-components}/entity-create-option-action-list.element.ts (96%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts similarity index 96% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts index 082816e24f..e8cdaed63f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts @@ -1,8 +1,8 @@ -import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { UmbEntityCreateOptionActionArgs } from '../types.js'; import type { ManifestEntityCreateOptionAction, MetaEntityCreateOptionAction, -} from './entity-create-option-action.extension.js'; +} from '../entity-create-option-action.extension.js'; import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts new file mode 100644 index 0000000000..40da9cdab0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts @@ -0,0 +1,3 @@ +import './entity-create-option-action-list.element.js'; + +export * from './entity-create-option-action-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts index c3a44c8f72..5eb9c9635d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts @@ -1,7 +1,12 @@ +import './global-components/index.js'; + export * from './default/index.js'; +export * from './global-components/index.js'; + export * from './entity-create-option-action-base.js'; -export * from './entity-create-option-action-list.element.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; -export * from './types.js'; + export type * from './entity-create-option-action-element.interface.js'; + +export * from './types.js'; From eb98f2dd65cc5d2cc427b8a2fd673494dac57d90 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 15:08:23 +0100 Subject: [PATCH 129/246] register create options --- .../user/entity-actions/create/manifests.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index b92ae65395..dc08f52bf6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { manifests as modalManifests } from './modal/manifests.js'; @@ -19,5 +19,31 @@ export const manifests: Array = additionalOptions: true, }, }, + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Default', + name: 'Default User Entity Create Option Action', + weight: 1200, + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: 'Default (Extension)', + additionalOptions: true, + }, + }, + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Api', + name: 'Api User Entity Create Option Action', + weight: 1200, + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: 'Api (Extension)', + additionalOptions: true, + }, + }, ...modalManifests, ]; From 4f0606eb8add4f59600026f1b48f7fb79b79dc6e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 15:11:43 +0100 Subject: [PATCH 130/246] Update index.ts --- src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index d3f60a90c0..c9a5284a0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,3 +1,4 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; +export * from './create-option-action/index.js'; export * from './types.js'; From 67b87748c0e7006766622b3cff9b0b00d03d5e6f Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Mon, 28 Oct 2024 15:07:06 +0100 Subject: [PATCH 131/246] Content type group sorting placeholder (#2471) * Make it more clear when content type groups are re-arranged * Hide header slot with input (cherry picked from commit 4863745181902720d790b70c7d20adae5be3fd90) --- .../views/design/content-type-design-editor-group.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts index 31059a012f..ead29d145b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-group.element.ts @@ -228,7 +228,7 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement { opacity: 0.5; } - :host([drag-placeholder]) > * { + :host([drag-placeholder]) > uui-box > * { visibility: hidden; } From 5558acb02ee5eaad1ebb1e7c6cfd03191592abb2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 17:47:09 +0100 Subject: [PATCH 132/246] use entityCreateOptionAction entity type --- .../entity-create-option-action-list.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts index e8cdaed63f..eeb948c5d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts @@ -51,6 +51,7 @@ export class UmbEntityCreateOptionActionListElement extends UmbLitElement { >; #entityContext = new UmbEntityContext(this); + #extensionType = 'entityCreateOptionAction'; #generateApiArgs() { if (!this._props.entityType || this._props.unique === undefined) return; @@ -69,7 +70,7 @@ export class UmbEntityCreateOptionActionListElement extends UmbLitElement { return this._filter ? html` Date: Mon, 28 Oct 2024 17:47:41 +0100 Subject: [PATCH 133/246] export manifests --- .../packages/core/entity/create-option-action/manifests.ts | 4 ++-- .../src/packages/core/entity/manifests.ts | 4 ++++ src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts index 84f3b7f88d..43d020c74e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts @@ -1,4 +1,4 @@ -import { manifests as defaultEntityActionManifests } from './default/manifests.js'; +import { manifests as defaultManifests } from './default/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...defaultEntityActionManifests]; +export const manifests: Array = [...defaultManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts new file mode 100644 index 0000000000..3a24422566 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...createOptionActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index 807e23de70..d01847d9d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -7,6 +7,7 @@ import { manifests as cultureManifests } from './culture/manifests.js'; import { manifests as debugManifests } from './debug/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-action/manifests.js'; +import { manifests as entityManifests } from './entity/manifests.js'; import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; @@ -36,6 +37,7 @@ export const manifests: Array = ...debugManifests, ...entityActionManifests, ...entityBulkActionManifests, + ...entityManifests, ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, From 18a96cff45da643af2d66ee570d407103a7ef9ca Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 28 Oct 2024 17:41:27 +0000 Subject: [PATCH 134/246] Detail repository save returns updated model previously returned the original model, prior to any server updates, e.g. updated date. --- .../packages/core/repository/detail/detail-repository-base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts index 5f7d695eaa..12a77e5437 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts @@ -124,7 +124,7 @@ export abstract class UmbDetailRepositoryBase< this.#notificationContext!.peek('positive', notification); } - return { data: model, error }; + return { data: updatedData, error }; } /** From ac5f8709785af4d6639346f5c154be7f04d95d99 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 22:18:27 +0100 Subject: [PATCH 135/246] register user entity create option actions --- .../api-user-entity-create-option-action.ts | 9 ++ .../create/api-user/manifests.ts | 18 ++++ ...efault-user-entity-create-option-action.ts | 45 +++++++++ .../create/default-user/manifests.ts | 18 ++++ .../user/entity-actions/create/manifests.ts | 33 +------ .../user-create-options-modal.element.ts | 91 ++++--------------- 6 files changed, 112 insertions(+), 102 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts new file mode 100644 index 0000000000..62404d353f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -0,0 +1,9 @@ +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; + +export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { + override async execute() { + debugger; + } +} + +export { UmbApiUserEntityCreateOptionAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts new file mode 100644 index 0000000000..5c5ea02ca8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; + +export const manifests: Array = [ + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Api', + name: 'Api User Entity Create Option Action', + weight: 1100, + api: () => import('./api-user-entity-create-option-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-unplug', + label: '#user_userKindApi', + additionalOptions: true, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts new file mode 100644 index 0000000000..e661e70363 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -0,0 +1,45 @@ +import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; +import type { UmbUserKindType } from '../../../utils/index.js'; +import { UmbUserKind } from '../../../utils/index.js'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const kind: UmbUserKindType = UmbUserKind.DEFAULT; + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); + + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity(); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity(); + }); + } + + async #requestReloadChildrenOfEntity() { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType: this.args.entityType, + unique: this.args.unique, + }); + + eventContext.dispatchEvent(event); + } +} + +export { UmbDefaultUserEntityCreateOptionAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts new file mode 100644 index 0000000000..4e12d1e039 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; + +export const manifests: Array = [ + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Default', + name: 'Default User Entity Create Option Action', + weight: 1200, + api: () => import('./default-user-entity-create-option-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-user', + label: '#user_userKindDefault', + additionalOptions: true, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index dc08f52bf6..658fa547d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,5 +1,6 @@ -import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; - +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { manifests as apiUser } from './api-user/manifests.js'; +import { manifests as defaultUser } from './default-user/manifests.js'; import { manifests as modalManifests } from './modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -19,31 +20,7 @@ export const manifests: Array = additionalOptions: true, }, }, - { - type: 'entityCreateOptionAction', - kind: 'default', - alias: 'Umb.EntityCreateOptionAction.User.Default', - name: 'Default User Entity Create Option Action', - weight: 1200, - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-add', - label: 'Default (Extension)', - additionalOptions: true, - }, - }, - { - type: 'entityCreateOptionAction', - kind: 'default', - alias: 'Umb.EntityCreateOptionAction.User.Api', - name: 'Api User Entity Create Option Action', - weight: 1200, - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-add', - label: 'Api (Extension)', - additionalOptions: true, - }, - }, + ...apiUser, + ...defaultUser, ...modalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts index 74e8646990..cc9ba965f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -1,92 +1,35 @@ -import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; -import { UmbUserKind, type UmbUserKindType } from '../../../utils/index.js'; -import { html, customElement, map } from '@umbraco-cms/backoffice/external/lit'; -import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; - -interface UmbUserCreateOptionModel { - label: string; - description?: string; - icon: string; - kind: UmbUserKindType; -} const elementName = 'umb-user-create-options-modal'; @customElement(elementName) export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { - #options: Array = [ - { - label: this.localize.term('user_userKindDefault'), - icon: 'icon-user', - kind: UmbUserKind.DEFAULT, - }, - { - label: this.localize.term('user_userKindApi'), - icon: 'icon-unplug', - kind: UmbUserKind.API, - }, - ]; + @state() + entity: UmbEntityModel = { + entityType: '', + unique: '', + }; - async #onClick(event: Event, kind: UmbUserKindType) { - event.stopPropagation(); - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + constructor() { + super(); - const unique = entityContext.getUnique(); - const entityType = entityContext.getEntityType(); - - if (unique === undefined) throw new Error('Missing unique'); - if (!entityType) throw new Error('Missing entityType'); - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { - data: { - user: { - kind, - }, - }, + this.consumeContext(UMB_ENTITY_CONTEXT, (context) => { + this.entity = { + entityType: context.getEntityType(), + unique: context.getUnique(), + }; }); - - modalContext - ?.onSubmit() - .then(() => { - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }) - .catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }); - } - - async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - - eventContext.dispatchEvent(event); } override render() { return html` - - ${map( - this.#options, - (item) => html` - this.#onClick(event, item.kind)}> - `, - )} - + Date: Mon, 28 Oct 2024 22:49:05 +0100 Subject: [PATCH 136/246] setup common action and generic modal --- .../common/create/create.action.kind.ts | 22 +++++++++ .../common/create/create.action.ts | 20 ++++++++ .../core/entity-action/common/create/index.ts | 1 + .../entity-action/common/create/manifests.ts | 4 ++ .../common/create/modal/constants.ts | 1 + ...create-option-action-list-modal.element.ts | 37 ++++++++++++++ ...y-create-option-action-list-modal.token.ts | 20 ++++++++ .../common/create/modal/index.ts | 2 + .../common/create/modal/manifests.ts | 10 ++++ .../core/entity-action/common/create/types.ts | 16 ++++++ .../core/entity-action/common/index.ts | 3 +- .../packages/core/entity-action/manifests.ts | 3 ++ .../create/create-user-entity-action.ts | 21 -------- .../user/entity-actions/create/manifests.ts | 11 +---- .../user/entity-actions/create/modal/index.ts | 8 --- .../entity-actions/create/modal/manifests.ts | 8 --- .../user-create-options-modal.element.ts | 49 ------------------- 17 files changed, 139 insertions(+), 97 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts new file mode 100644 index 0000000000..a220d955aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts @@ -0,0 +1,22 @@ +import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest: UmbExtensionManifestKind = { + type: 'kind', + alias: 'Umb.Kind.EntityAction.Create', + matchKind: 'create', + matchType: 'entityAction', + manifest: { + ...UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST.manifest, + type: 'entityAction', + kind: 'create', + api: () => import('./create.action.js'), + weight: 1200, + forEntityTypes: [], + meta: { + icon: 'icon-add', + label: '#actions_create', + additionalOptions: true, + }, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts new file mode 100644 index 0000000000..35f0dda58a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -0,0 +1,20 @@ +import { UmbEntityActionBase } from '../../entity-action-base.js'; +import type { MetaEntityActionCreateKind } from './types.js'; +import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modalContext = modalManager.open(this, UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL, { + data: { + unique: this.args.unique, + entityType: this.args.entityType, + }, + }); + + await modalContext.onSubmit(); + } +} + +export { UmbCreateEntityAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts new file mode 100644 index 0000000000..d44c5eca74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -0,0 +1 @@ +export { UmbCreateEntityAction } from './create.action.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts new file mode 100644 index 0000000000..d1e496f559 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts @@ -0,0 +1,4 @@ +import { manifest as createKindManifest } from './create.action.kind.js'; +import { manifests as modalManifests } from './modal/manifests.js'; + +export const manifests = [createKindManifest, ...modalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts new file mode 100644 index 0000000000..ab81577a04 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts @@ -0,0 +1 @@ +export const UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS = 'Umb.Modal.Entity.CreateOptionActionList'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts new file mode 100644 index 0000000000..e9ada04e69 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -0,0 +1,37 @@ +import type { + UmbEntityCreateOptionActionListModalData, + UmbEntityCreateOptionActionListModalValue, +} from './entity-create-option-action-list-modal.token.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; + +const elementName = 'umb-entity-create-option-action-list-modal'; +@customElement(elementName) +export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseElement< + UmbEntityCreateOptionActionListModalData, + UmbEntityCreateOptionActionListModalValue +> { + override render() { + return html` + + + + + + + `; + } +} + +export { UmbEntityCreateOptionActionListModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbEntityCreateOptionActionListModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts new file mode 100644 index 0000000000..dd1aba66b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts @@ -0,0 +1,20 @@ +import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS } from './constants.js'; +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbEntityCreateOptionActionListModalData { + unique: UmbEntityUnique; + entityType: string; +} + +export type UmbEntityCreateOptionActionListModalValue = never; + +export const UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL = new UmbModalToken< + UmbEntityCreateOptionActionListModalData, + UmbEntityCreateOptionActionListModalValue +>(UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts new file mode 100644 index 0000000000..876d392b23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts @@ -0,0 +1,2 @@ +export * from './constants.js'; +export * from './entity-create-option-action-list-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts new file mode 100644 index 0000000000..2b6ee6ed47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts @@ -0,0 +1,10 @@ +import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS } from './constants.js'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS, + name: 'Entity Create Option Action List Modal', + element: () => import('./entity-create-option-action-list-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts new file mode 100644 index 0000000000..7d102e750a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts @@ -0,0 +1,16 @@ +import type { MetaEntityActionDefaultKind } from '../../default/index.js'; +import type { ManifestEntityAction } from '../../entity-action.extension.js'; + +export interface ManifestEntityActionCreateKind extends ManifestEntityAction { + type: 'entityAction'; + kind: 'create'; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface MetaEntityActionCreateKind extends MetaEntityActionDefaultKind {} + +declare global { + interface UmbExtensionManifestMap { + umbEntityActionCreateKind: ManifestEntityActionCreateKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts index 30877954f8..5a7c2ae86b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts @@ -1,2 +1,3 @@ -export * from './duplicate/index.js'; +export * from './create/index.js'; export * from './delete/index.js'; +export * from './duplicate/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index aeaaceafc0..7d6813e49a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,9 +1,12 @@ +import { manifests as createEntityActionManifests } from './common/create/manifests.js'; import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; + import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + ...createEntityActionManifests, ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts deleted file mode 100644 index a6da26da4f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UMB_USER_CREATE_OPTIONS_MODAL } from './modal/index.js'; -import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; - -export class UmbCreateUserEntityAction extends UmbEntityActionBase { - override async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const modalContext = modalManager.open(this, UMB_USER_CREATE_OPTIONS_MODAL, { - data: { - parent: { - unique: this.args.unique, - entityType: this.args.entityType, - }, - }, - }); - - await modalContext.onSubmit(); - } -} - -export { UmbCreateUserEntityAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index 658fa547d3..2e67f026d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,26 +1,17 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { manifests as apiUser } from './api-user/manifests.js'; import { manifests as defaultUser } from './default-user/manifests.js'; -import { manifests as modalManifests } from './modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'entityAction', - kind: 'default', + kind: 'create', alias: 'Umb.EntityAction.User.Create', name: 'Create User Entity Action', - weight: 1200, - api: () => import('./create-user-entity-action.js'), forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], - meta: { - icon: 'icon-add', - label: '#actions_create', - additionalOptions: true, - }, }, ...apiUser, ...defaultUser, - ...modalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts deleted file mode 100644 index 778a1fe38d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -export const UMB_USER_CREATE_OPTIONS_MODAL = new UmbModalToken('Umb.Modal.User.CreateOptions', { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts deleted file mode 100644 index 08dc77d154..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const manifests: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.User.CreateOptions', - name: 'User Create Options Modal', - element: () => import('./user-create-options-modal.element.js'), - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts deleted file mode 100644 index cc9ba965f2..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; - -const elementName = 'umb-user-create-options-modal'; -@customElement(elementName) -export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { - @state() - entity: UmbEntityModel = { - entityType: '', - unique: '', - }; - - constructor() { - super(); - - this.consumeContext(UMB_ENTITY_CONTEXT, (context) => { - this.entity = { - entityType: context.getEntityType(), - unique: context.getUnique(), - }; - }); - } - - override render() { - return html` - - - - - - - `; - } -} - -export { UmbUserCreateOptionsModalElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbUserCreateOptionsModalElement; - } -} From ca4ff01934a58b1ea71132c114f3f948adb81afc Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Tue, 29 Oct 2024 08:07:02 +0000 Subject: [PATCH 137/246] Feature: Tiptap "Clear Formatting" toolbar action (#2494) Tiptap: adds "Clear Formatting" toolbar action --- .../core/icon-registry/icon-dictionary.json | 4 ++++ .../src/packages/core/icon-registry/icons.ts | 4 ++++ .../icons/icon-clear-formatting.ts | 18 ++++++++++++++++++ .../packages/tiptap/extensions/manifests.ts | 12 ++++++++++++ .../toolbar/clear-formatting.extension.ts | 8 ++++++++ 5 files changed, 46 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-clear-formatting.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json index cc6923a5d9..d358487927 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-dictionary.json @@ -366,6 +366,10 @@ "name": "icon-circuits", "file": "circuit-board.svg" }, + { + "name": "icon-clear-formatting", + "file": "remove-formatting.svg" + }, { "name": "icon-client", "file": "user.svg", diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts index 6edd8ec784..8855310df5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons.ts @@ -355,6 +355,10 @@ name: "icon-circuits", path: () => import("./icons/icon-circuits.js"), },{ +name: "icon-clear-formatting", + +path: () => import("./icons/icon-clear-formatting.js"), +},{ name: "icon-client", legacy: true, path: () => import("./icons/icon-client.js"), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-clear-formatting.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-clear-formatting.ts new file mode 100644 index 0000000000..09fbab564a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icons/icon-clear-formatting.ts @@ -0,0 +1,18 @@ +export default ` + + + + + + + +`; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts index 8f27df5139..719793c65f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/manifests.ts @@ -193,6 +193,18 @@ const toolbarExtensions: Array = [ label: 'Strike', }, }, + { + type: 'tiptapToolbarExtension', + kind: 'button', + alias: 'Umb.Tiptap.Toolbar.ClearFormatting', + name: 'Clear Formatting Tiptap Extension', + api: () => import('./toolbar/clear-formatting.extension.js'), + meta: { + alias: 'clear-formatting', + icon: 'icon-clear-formatting', + label: 'Clear Formatting', + }, + }, { type: 'tiptapToolbarExtension', kind: 'button', diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts new file mode 100644 index 0000000000..159e932a14 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts @@ -0,0 +1,8 @@ +import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; + +export default class UmbTiptapToolbarClearFormattingExtensionApi extends UmbTiptapToolbarElementApiBase { + override execute(editor?: Editor) { + editor?.chain().focus().unsetAllMarks().run(); + } +} From 40c7bc95828caabaa0333e5828593e70b0ab605e Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 29 Oct 2024 07:16:38 +0000 Subject: [PATCH 138/246] Tiptap toolbar, background color + box shadow --- .../components/input-tiptap/tiptap-toolbar.element.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts index a799d05907..087ee86123 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/tiptap-toolbar.element.ts @@ -93,11 +93,16 @@ export class UmbTiptapToolbarElement extends UmbLitElement { border: 1px solid var(--uui-color-border); border-bottom-left-radius: 0; border-bottom-right-radius: 0; - background-color: var(--uui-color-surface); + box-shadow: + 0 2px 2px -2px rgba(34, 47, 62, 0.1), + 0 8px 8px -4px rgba(34, 47, 62, 0.07); + + background-color: var(--uui-color-surface-alt); color: var(--color-text); display: grid; grid-template-columns: repeat(auto-fill, 10px); grid-auto-flow: row; + position: sticky; top: -25px; left: 0px; From d26fdcaedff00add9092220225b36e5d442eea6c Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Tue, 29 Oct 2024 08:08:42 +0000 Subject: [PATCH 139/246] Feature: Document Workspace Info reload components (#2492) * Adds Document URL Repository * Extracts Document Workspace Info Links to its own component Refactored to use the new Document URL Repository. Plus other housekeeping on the main Document Workspace Info component. * Refactored Document Workspace Info History component to listen for the "Request Reload Structure" event * Refactored Document Workspace Info Reference component --- .../history/history-item.element.ts | 1 + .../documents/documents/repository/index.ts | 1 + .../documents/repository/manifests.ts | 8 +- .../documents/repository/url/constants.ts | 2 + .../repository/url/document-url.repository.ts | 13 ++ .../url/document-url.server.data-source.ts | 29 ++++ .../url/document-url.store.context-token.ts | 4 + .../repository/url/document-url.store.ts | 23 +++ .../documents/repository/url/index.ts | 2 + .../documents/repository/url/manifests.ts | 18 +++ .../documents/repository/url/types.ts | 9 ++ ...ent-workspace-view-info-history.element.ts | 146 +++++++++--------- ...ument-workspace-view-info-links.element.ts | 134 ++++++++++++++++ ...t-workspace-view-info-reference.element.ts | 118 +++++++------- .../document-workspace-view-info.element.ts | 110 ++----------- 15 files changed, 390 insertions(+), 228 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.repository.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.server.data-source.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-item.element.ts index 92671b347c..a5814884c3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-item.element.ts @@ -63,6 +63,7 @@ export class UmbHistoryItemElement extends UmbLitElement { .user-info div { display: flex; flex-direction: column; + min-width: var(--uui-size-60); } .detail { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts index f80023cfbe..be04ad8020 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts @@ -1,6 +1,7 @@ export { UmbDocumentDetailRepository, UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from './detail/index.js'; export { UmbDocumentItemRepository, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from './item/index.js'; export { UmbDocumentPublishingRepository, UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALIAS } from './publishing/index.js'; +export { UmbDocumentUrlRepository, UMB_DOCUMENT_URL_REPOSITORY_ALIAS } from './url/index.js'; export { UmbDocumentPreviewRepository } from './preview/index.js'; export type { UmbDocumentItemModel } from './item/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts index 71c01115e5..c7ab4b7fdc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts @@ -1,5 +1,11 @@ import { manifests as detailManifests } from './detail/manifests.js'; import { manifests as itemManifests } from './item/manifests.js'; import { manifests as publishingManifests } from './publishing/manifests.js'; +import { manifests as urlManifests } from './url/manifests.js'; -export const manifests: Array = [...detailManifests, ...itemManifests, ...publishingManifests]; +export const manifests: Array = [ + ...detailManifests, + ...itemManifests, + ...publishingManifests, + ...urlManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/constants.ts new file mode 100644 index 0000000000..ba77e1ff72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/constants.ts @@ -0,0 +1,2 @@ +export const UMB_DOCUMENT_URL_REPOSITORY_ALIAS = 'Umb.Repository.Document.Url'; +export const UMB_DOCUMENT_URL_STORE_ALIAS = 'Umb.Store.Document.Url'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.repository.ts new file mode 100644 index 0000000000..6b65fe3545 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.repository.ts @@ -0,0 +1,13 @@ +import type { UmbDocumentUrlsModel } from './types.js'; +import { UMB_DOCUMENT_URL_STORE_CONTEXT } from './document-url.store.context-token.js'; +import { UmbDocumentUrlServerDataSource } from './document-url.server.data-source.js'; +import { UmbItemRepositoryBase } from '@umbraco-cms/backoffice/repository'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbDocumentUrlRepository extends UmbItemRepositoryBase { + constructor(host: UmbControllerHost) { + super(host, UmbDocumentUrlServerDataSource, UMB_DOCUMENT_URL_STORE_CONTEXT); + } +} + +export { UmbDocumentUrlRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.server.data-source.ts new file mode 100644 index 0000000000..2993e37a40 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.server.data-source.ts @@ -0,0 +1,29 @@ +import type { UmbDocumentUrlsModel } from './types.js'; +import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; +import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository'; +import type { DocumentUrlInfoResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +/** + * A server data source for Document URLs + * @class UmbDocumentUrlServerDataSource + * @implements {DocumentTreeDataSource} + */ +export class UmbDocumentUrlServerDataSource extends UmbItemServerDataSourceBase< + DocumentUrlInfoResponseModel, + UmbDocumentUrlsModel +> { + /** + * Creates an instance of UmbDocumentUrlServerDataSource. + * @param {UmbControllerHost} host - The controller host for this controller to be appended to + * @memberof UmbDocumentUrlServerDataSource + */ + constructor(host: UmbControllerHost) { + super(host, { getItems, mapper }); + } +} + +/* eslint-disable local-rules/no-direct-api-import */ +const getItems = (uniques: Array) => DocumentService.getDocumentUrls({ id: uniques }); + +const mapper = (item: DocumentUrlInfoResponseModel): UmbDocumentUrlsModel => ({ unique: item.id, urls: item.urlInfos }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.context-token.ts new file mode 100644 index 0000000000..f2ac89657f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.context-token.ts @@ -0,0 +1,4 @@ +import type UmbDocumentUrlStore from './document-url.store.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export const UMB_DOCUMENT_URL_STORE_CONTEXT = new UmbContextToken('UmbDocumentUrlStore'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.ts new file mode 100644 index 0000000000..3f5a9f514e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/document-url.store.ts @@ -0,0 +1,23 @@ +import type { UmbDocumentDetailModel } from '../../types.js'; +import { UMB_DOCUMENT_URL_STORE_CONTEXT } from './document-url.store.context-token.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbItemStoreBase } from '@umbraco-cms/backoffice/store'; + +/** + * @class UmbDocumentUrlStore + * @augments {UmbStoreBase} + * @description - Data Store for Document URLs + */ + +export class UmbDocumentUrlStore extends UmbItemStoreBase { + /** + * Creates an instance of UmbDocumentUrlStore. + * @param {UmbControllerHost} host - The controller host for this controller to be appended to + * @memberof UmbDocumentUrlStore + */ + constructor(host: UmbControllerHost) { + super(host, UMB_DOCUMENT_URL_STORE_CONTEXT.toString()); + } +} + +export default UmbDocumentUrlStore; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/index.ts new file mode 100644 index 0000000000..f5bc60dacd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/index.ts @@ -0,0 +1,2 @@ +export { UmbDocumentUrlRepository } from './document-url.repository.js'; +export { UMB_DOCUMENT_URL_REPOSITORY_ALIAS } from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/manifests.ts new file mode 100644 index 0000000000..d4545015b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_DOCUMENT_URL_REPOSITORY_ALIAS, UMB_DOCUMENT_URL_STORE_ALIAS } from './constants.js'; +import type { ManifestItemStore, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +const urlRepository: ManifestRepository = { + type: 'repository', + alias: UMB_DOCUMENT_URL_REPOSITORY_ALIAS, + name: 'Document Url Repository', + api: () => import('./document-url.repository.js'), +}; + +const urlStore: ManifestItemStore = { + type: 'itemStore', + alias: UMB_DOCUMENT_URL_STORE_ALIAS, + name: 'Document Url Store', + api: () => import('./document-url.store.js'), +}; + +export const manifests = [urlRepository, urlStore]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/types.ts new file mode 100644 index 0000000000..7291179f31 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/url/types.ts @@ -0,0 +1,9 @@ +export interface UmbDocumentUrlsModel { + unique: string; + urls: Array; +} + +export interface UmbDocumentUrlModel { + culture?: string | null; + url?: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts index 889c24988a..cfa0bc151a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-history.element.ts @@ -1,32 +1,40 @@ import type { UmbDocumentAuditLogModel } from '../../../audit-log/types.js'; import { UmbDocumentAuditLogRepository } from '../../../audit-log/index.js'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; -import { TimeOptions, getDocumentHistoryTagStyleAndText } from './utils.js'; -import { css, html, customElement, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { getDocumentHistoryTagStyleAndText, TimeOptions } from './utils.js'; +import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbPaginationManager } from '@umbraco-cms/backoffice/utils'; -import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui'; -import type { UmbUserItemModel } from '@umbraco-cms/backoffice/user'; +import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/entity-action'; +import type { UmbUserItemModel } from '@umbraco-cms/backoffice/user'; +import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-document-workspace-view-info-history') export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { - @state() - _currentPageNumber = 1; + #allowedActions = new Set(['Umb.EntityAction.Document.Rollback']); + + #auditLogRepository = new UmbDocumentAuditLogRepository(this); + + #pagination = new UmbPaginationManager(); + + #userItemRepository = new UmbUserItemRepository(this); + + #userMap = new Map(); + + #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; @state() - _totalPages = 1; + private _currentPageNumber = 1; @state() private _items: Array = []; - #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; - #auditLogRepository = new UmbDocumentAuditLogRepository(this); - #pagination = new UmbPaginationManager(); - #userItemRepository = new UmbUserItemRepository(this); - - #userMap = new Map(); + @state() + private _totalPages = 1; constructor() { super(); @@ -35,12 +43,23 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { this.observe(this.#pagination.currentPage, (number) => (this._currentPageNumber = number)); this.observe(this.#pagination.totalPages, (number) => (this._totalPages = number)); + this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => { + context.addEventListener(UmbRequestReloadStructureForEntityEvent.TYPE, () => { + this.#requestAuditLogs(); + }); + }); + this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; this.#requestAuditLogs(); }); } + #onPageChange(event: UUIPaginationEvent) { + this.#pagination.setCurrentPageNumber(event.target?.current); + this.#requestAuditLogs(); + } + async #requestAuditLogs() { const unique = this.#workspaceContext?.getUnique(); if (!unique) throw new Error('Document unique is required'); @@ -58,11 +77,6 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { } } - #onPageChange(event: UUIPaginationEvent) { - this.#pagination.setCurrentPageNumber(event.target?.current); - this.#requestAuditLogs(); - } - async #requestAndCacheUserItems() { const allUsers = this._items?.map((item) => item.user.unique).filter(Boolean) as string[]; const uniqueUsers = [...new Set(allUsers)]; @@ -83,90 +97,84 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement { } override render() { - return html` - History - + manifest.alias === 'Umb.EntityAction.Document.Rollback'}> + .filter=${(manifest: ManifestEntityAction) => this.#allowedActions.has(manifest.alias)}> - ${this._items ? this.#renderHistory() : html` `} + ${when( + this._items, + () => this.#renderHistory(), + () => html`
      `, + )} ${this.#renderPagination()} - `; + + `; } #renderHistory() { - if (this._items && this._items.length) { - return html` - - ${repeat( - this._items, - (item) => item.timestamp, - (item) => { - const { text, style } = getDocumentHistoryTagStyleAndText(item.logType); - const user = this.#userMap.get(item.user.unique); + if (!this._items?.length) return html`${this.localize.term('content_noItemsToShow')}`; + return html` + + ${repeat( + this._items, + (item) => item.timestamp, + (item) => { + const { text, style } = getDocumentHistoryTagStyleAndText(item.logType); + const user = this.#userMap.get(item.user.unique); - return html` - - + .imgUrls=${user?.avatarUrls ?? []}> + +
      ${this.localize.term(text.label, item.parameters)} - ${this.localize.term(text.desc, item.parameters)} - - `; - }, - )} - - `; - } else { - return html`${this.localize.term('content_noItemsToShow')}`; - } + ${this.localize.term(text.desc, item.parameters)} +
      +
      + `; + }, + )} +
      + `; } #renderPagination() { + if (this._totalPages <= 1) return nothing; return html` - ${this._totalPages > 1 - ? html` - - ` - : nothing} + `; } static override styles = [ UmbTextStyles, css` - uui-loader-circle { - font-size: 2rem; - } - - uui-tag uui-icon { - margin-right: var(--uui-size-space-1); + #loader { + display: flex; + justify-content: center; } .log-type { - flex-grow: 1; - gap: var(--uui-size-space-2); + display: grid; + grid-template-columns: var(--uui-size-40) auto; + gap: var(--uui-size-layout-1); } uui-pagination { flex: 1; - display: inline-block; - } - - .pagination { display: flex; justify-content: center; margin-top: var(--uui-size-layout-1); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts new file mode 100644 index 0000000000..6b0fcb58ab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts @@ -0,0 +1,134 @@ +import { UmbDocumentUrlRepository } from '../../../repository/url/document-url.repository.js'; +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; +import type { UmbDocumentUrlModel } from '../../../repository/url/types.js'; +import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; + +@customElement('umb-document-workspace-view-info-links') +export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { + #documentUrlRepository = new UmbDocumentUrlRepository(this); + + #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; + + @state() + private _invariantCulture = 'en-US'; + + @state() + private _items?: Array; + + constructor() { + super(); + + this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => { + context.addEventListener(UmbRequestReloadStructureForEntityEvent.TYPE, () => { + this.#requestUrls(); + }); + }); + + this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { + this.#workspaceContext = context; + this.#requestUrls(); + }); + } + + async #requestUrls() { + const unique = this.#workspaceContext?.getUnique(); + if (!unique) throw new Error('Document unique is required'); + + const { data } = await this.#documentUrlRepository.requestItems([unique]); + + if (data?.length) { + this._items = data[0].urls; + } + } + + override render() { + return html` + + + + `; + } + + #renderUrls() { + if (!this._items) return nothing; + return html` + ${repeat( + this._items!, + (item) => item.culture, + (item) => html` + + ${item.culture} + ${item.url} + + + `, + )} + `; + } + + #renderUnpublished() { + return html` + + `; + } + + static override styles = [ + UmbTextStyles, + css` + #link-section { + display: flex; + flex-direction: column; + text-align: left; + } + + .link-item { + padding: var(--uui-size-space-4) var(--uui-size-space-6); + display: grid; + grid-template-columns: auto 1fr auto; + gap: var(--uui-size-6); + color: inherit; + text-decoration: none; + + &:is(a) { + cursor: pointer; + } + + &:is(a):hover { + background: var(--uui-color-divider); + } + + .culture { + color: var(--uui-color-divider-emphasis); + } + + uui-icon { + margin-right: var(--uui-size-space-2); + vertical-align: middle; + } + } + `, + ]; +} + +export default UmbDocumentWorkspaceViewInfoLinksElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-workspace-view-info-links': UmbDocumentWorkspaceViewInfoLinksElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts index 28ad1b37ae..12cccd21f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-reference.element.ts @@ -1,21 +1,18 @@ import { UmbDocumentReferenceRepository } from '../../../reference/index.js'; -import { css, html, customElement, state, nothing, repeat, property } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui'; +import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; +import { isDefaultReference, isDocumentReference, isMediaReference } from '@umbraco-cms/backoffice/relations'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; -import { - isDefaultReference, - isDocumentReference, - isMediaReference, - type UmbReferenceModel, -} from '@umbraco-cms/backoffice/relations'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; +import type { UmbReferenceModel } from '@umbraco-cms/backoffice/relations'; +import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-document-workspace-view-info-reference') export class UmbDocumentWorkspaceViewInfoReferenceElement extends UmbLitElement { #itemsPerPage = 10; - #referenceRepository; + + #referenceRepository = new UmbDocumentReferenceRepository(this); @property() documentUnique = ''; @@ -34,7 +31,6 @@ export class UmbDocumentWorkspaceViewInfoReferenceElement extends UmbLitElement constructor() { super(); - this.#referenceRepository = new UmbDocumentReferenceRepository(this); new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) .addAdditionalPath('document') @@ -113,63 +109,65 @@ export class UmbDocumentWorkspaceViewInfoReferenceElement extends UmbLitElement } override render() { - if (this._items && this._items.length > 0) { - return html` - - - - Name - Status - Type Name - Type - - - ${repeat( - this._items, - (item) => item.id, - (item) => - html` - - - - - ${isDocumentReference(item) - ? html` - ${item.name} - ` - : item.name} - - - ${this.#getPublishedStatus(item) - ? this.localize.term('content_published') - : this.localize.term('content_unpublished')} - - ${this.#getContentTypeName(item)} - ${this.#getContentType(item)} - `, - )} - - - ${this.#renderReferencePagination()}`; - } else { - return nothing; - } + if (!this._items?.length) return nothing; + return html` + + + + + Name + Status + Type Name + Type + + ${repeat( + this._items, + (item) => item.id, + (item) => html` + + + + + + ${when( + isDocumentReference(item), + () => html` + + ${item.name} + + `, + () => item.name, + )} + + + ${this.#getPublishedStatus(item) + ? this.localize.term('content_published') + : this.localize.term('content_unpublished')} + + ${this.#getContentTypeName(item)} + ${this.#getContentType(item)} + + `, + )} + + + ${this.#renderReferencePagination()} + `; } #renderReferencePagination() { if (!this._total) return nothing; const totalPages = Math.ceil(this._total / this.#itemsPerPage); - if (totalPages <= 1) return nothing; - return html``; + return html` + + `; } static override styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index c6a42baecf..212f78cf05 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -2,36 +2,29 @@ import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../../property-dataset import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; import type { UmbDocumentVariantModel } from '../../../types.js'; import { TimeOptions } from './utils.js'; -import { css, customElement, html, ifDefined, nothing, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, ifDefined, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; import { UMB_TEMPLATE_PICKER_MODAL, UmbTemplateItemRepository } from '@umbraco-cms/backoffice/template'; -import type { DocumentUrlInfoModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; // import of local components +import './document-workspace-view-info-links.element.js'; import './document-workspace-view-info-history.element.js'; import './document-workspace-view-info-reference.element.js'; @customElement('umb-document-workspace-view-info') export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { - @state() - private _invariantCulture = 'en-US'; - @state() private _documentUnique = ''; + // Document Type @state() - private _urls?: Array; - - /**Document Type */ - @state() - private _documentTypeUnique = ''; + private _documentTypeUnique?: string = ''; @state() private _documentTypeName?: string; @@ -42,7 +35,7 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { @state() private _allowedTemplates?: UmbDocumentTypeDetailModel['allowedTemplates']; - /**Template */ + // Template @state() private _templateUnique = ''; @@ -78,9 +71,8 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { }); this.consumeContext(UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT, (context) => { - this.observe(context.currentVariant, (value) => { - // TODO: get the correct type automatically - this._variant = value as UmbDocumentVariantModel; + this.observe(context.currentVariant, (currentVariant) => { + this._variant = currentVariant; }); }); } @@ -98,14 +90,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { '_documentType', ); - this.observe( - this.#workspaceContext.urls, - (urls) => { - this._urls = urls; - }, - '_documentUrls', - ); - this.observe( this.#workspaceContext.unique, (unique) => { @@ -160,50 +144,19 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { override render() { return html`
      - - - - + - - +
      - ${this.#renderGeneralSection()} + + ${this.#renderGeneralSection()} +
      `; } - #renderLinksSection() { - /** TODO Make sure link section is completed */ - if (this._urls && this._urls.length) { - return html` - ${repeat( - this._urls, - (url) => url.culture, - (url) => html` - - ${url.culture} - ${url.url} - - - `, - )} - `; - } else { - return html` - - `; - } - } - #renderGeneralSection() { const editDocumentTypePath = this._routeBuilder?.({ entityType: 'document-type' }) ?? ''; const editTemplatePath = this._routeBuilder?.({ entityType: 'template' }) ?? ''; @@ -292,7 +245,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { } static override styles = [ - UmbTextStyles, css` :host { display: grid; @@ -332,44 +284,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { .variant-state > span { color: var(--uui-color-divider-emphasis); } - - // Link section - - #link-section { - display: flex; - flex-direction: column; - text-align: left; - } - - .link-item { - padding: var(--uui-size-space-4) var(--uui-size-space-6); - display: grid; - grid-template-columns: auto 1fr auto; - gap: var(--uui-size-6); - color: inherit; - text-decoration: none; - } - - .link-language { - color: var(--uui-color-divider-emphasis); - } - - .link-content.italic { - font-style: italic; - } - - .link-item uui-icon { - margin-right: var(--uui-size-space-2); - vertical-align: middle; - } - - .link-item.with-href { - cursor: pointer; - } - - .link-item.with-href:hover { - background: var(--uui-color-divider); - } `, ]; } From 5926517207d62de04987616976a22eef4d3c2ca0 Mon Sep 17 00:00:00 2001 From: Debasish Gracias Date: Tue, 29 Oct 2024 16:06:39 +0530 Subject: [PATCH 140/246] Bugfix: Word wraps long Data Type names in picker (#2496) Fix for 17036 Co-authored-by: Debasish Gracias --- .../data-type-picker-flow-data-type-picker-modal.element.ts | 1 + .../data-type-picker-flow/data-type-picker-flow-modal.element.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts index aaf4b0dfdf..b266122c4f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts @@ -169,6 +169,7 @@ export class UmbDataTypePickerFlowDataTypePickerModalElement extends UmbModalBas grid-template-rows: 40px 1fr; height: 100%; width: 100%; + word-break: break-word; } .icon { font-size: 2em; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index d42bd3f948..44daf00885 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -448,6 +448,7 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< grid-template-rows: 40px 1fr; height: 100%; width: 100%; + word-break: break-word; } #item-grid .item .icon { From 74695de57b3913ce7c83e637dc1e78b7dab71522 Mon Sep 17 00:00:00 2001 From: Debasish Gracias Date: Tue, 29 Oct 2024 16:06:39 +0530 Subject: [PATCH 141/246] Bugfix: Word wraps long Data Type names in picker (#2496) Fix for 17036 Co-authored-by: Debasish Gracias (cherry picked from commit 5926517207d62de04987616976a22eef4d3c2ca0) --- .../data-type-picker-flow-data-type-picker-modal.element.ts | 1 + .../data-type-picker-flow/data-type-picker-flow-modal.element.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts index aaf4b0dfdf..b266122c4f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts @@ -169,6 +169,7 @@ export class UmbDataTypePickerFlowDataTypePickerModalElement extends UmbModalBas grid-template-rows: 40px 1fr; height: 100%; width: 100%; + word-break: break-word; } .icon { font-size: 2em; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index d42bd3f948..44daf00885 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -448,6 +448,7 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< grid-template-rows: 40px 1fr; height: 100%; width: 100%; + word-break: break-word; } #item-grid .item .icon { From 7c8b1432f2d6d531fd997c14f5c2130ead45d5a2 Mon Sep 17 00:00:00 2001 From: Nikolaj Brask-Nielsen Date: Tue, 29 Oct 2024 12:03:50 +0100 Subject: [PATCH 142/246] feat: Add validation hints to unnamed tabs (#2493) --- .../content-type-design-editor.element.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts index 9ab77fca89..9105d91fd0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts @@ -478,7 +478,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements const ownedTab = this.#tabsStructureHelper.isOwnerChildContainer(tab.id!) ?? false; return html` ${ownedTab - ? html` ${tab.name!} + ? html` ${tabName} this.#tabNameChanged(e, tab)} @input=${(e: InputEvent) => this.#tabNameChanged(e, tab)} @blur=${(e: FocusEvent) => this.#tabNameBlur(e, tab)}> @@ -521,7 +524,11 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements } if (ownedTab) { - return html`
      ${tab.name!} ${this.renderDeleteFor(tab)}
      `; + return html`
      + ${hasTabName ? tab.name : 'Unnamed'} ${this.renderDeleteFor( + tab, + )} +
      `; } else { return html`
      ${tab.name!}
      `; } @@ -630,6 +637,10 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements gap: var(--uui-size-space-3); } + .invaild { + color: var(--uui-color-danger, #d42054); + } + .trash { opacity: 1; transition: opacity 100ms; @@ -640,7 +651,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements transition: opacity 100ms; } - uui-input:not(:focus, :hover) { + uui-input:not(:focus, :hover, :invalid) { border: 1px solid transparent; } From 74fec69782e6d41d517b450f5856772a53e3c0a0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 13:18:14 +0100 Subject: [PATCH 143/246] restructure modules --- .../entity-create-option-action.element.ts | 0 .../create-option-action/default/index.ts | 0 .../create-option-action/default/manifests.ts | 0 .../create-option-action/default/types.ts | 0 .../entity-create-option-action-base.ts | 0 ...-create-option-action-element.interface.ts | 0 .../entity-create-option-action.extension.ts | 0 .../entity-create-option-action.interface.ts | 0 ...ntity-create-option-action-list.element.ts | 0 .../global-components/index.ts | 0 .../create}/create-option-action/index.ts | 0 .../create}/create-option-action/manifests.ts | 0 .../create}/create-option-action/types.ts | 0 .../common/create/create.action.ts | 39 +++++++++++++++++++ .../core/entity-action/common/create/index.ts | 1 + .../entity-action/common/create/manifests.ts | 3 +- .../packages/core/entity-action/manifests.ts | 2 - .../src/packages/core/entity/index.ts | 1 - .../src/packages/core/entity/manifests.ts | 4 -- .../src/packages/core/manifests.ts | 2 - .../api-user-entity-create-option-action.ts | 2 +- ...efault-user-entity-create-option-action.ts | 8 ++-- 22 files changed, 48 insertions(+), 14 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/entity-create-option-action.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/types.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action-base.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action-element.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action.extension.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/global-components/entity-create-option-action-list.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/global-components/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/types.ts (100%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index 35f0dda58a..d96860c9b9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -1,10 +1,49 @@ import { UmbEntityActionBase } from '../../entity-action-base.js'; +import type { UmbEntityActionArgs } from '../../types.js'; import type { MetaEntityActionCreateKind } from './types.js'; import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; +import type { ManifestEntityCreateOptionAction } from './create-option-action/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { createExtensionApi, UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; export class UmbCreateEntityAction extends UmbEntityActionBase { + #hasSingleOption = true; + #singleActionOptionManifest?: ManifestEntityCreateOptionAction; + + constructor(host: UmbControllerHost, args: UmbEntityActionArgs) { + super(host, args); + + new UmbExtensionsManifestInitializer( + this, + umbExtensionsRegistry, + 'entityCreateOptionAction', + (ext) => ext.forEntityTypes.includes(this.args.entityType), + async (actionOptions) => { + this.#hasSingleOption = actionOptions.length === 1; + this.#singleActionOptionManifest = this.#hasSingleOption + ? (actionOptions[0].manifest as ManifestEntityCreateOptionAction) + : undefined; + }, + 'umbEntityActionsObserver', + ); + } + override async execute() { + if (this.#hasSingleOption) { + if (!this.#singleActionOptionManifest) throw new Error('No first action manifest found'); + + const api = await createExtensionApi(this, this.#singleActionOptionManifest, [ + { unique: this.args.unique, entityType: this.args.entityType, meta: this.#singleActionOptionManifest.meta }, + ]); + + if (!api) throw new Error(`Could not create api for ${this.#singleActionOptionManifest.alias}`); + + await api.execute(); + return; + } + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const modalContext = modalManager.open(this, UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL, { data: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts index d44c5eca74..e3989cd62d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -1 +1,2 @@ export { UmbCreateEntityAction } from './create.action.js'; +export * from './create-option-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts index d1e496f559..6aee3f93b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts @@ -1,4 +1,5 @@ import { manifest as createKindManifest } from './create.action.kind.js'; import { manifests as modalManifests } from './modal/manifests.js'; +import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; -export const manifests = [createKindManifest, ...modalManifests]; +export const manifests = [createKindManifest, ...modalManifests, ...createOptionActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index 7d6813e49a..2f9fa9adc4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,4 +1,3 @@ -import { manifests as createEntityActionManifests } from './common/create/manifests.js'; import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; @@ -6,7 +5,6 @@ import { manifests as duplicateEntityActionManifests } from './common/duplicate/ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ - ...createEntityActionManifests, ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index c9a5284a0c..d3f60a90c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,4 +1,3 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; -export * from './create-option-action/index.js'; export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts deleted file mode 100644 index 3a24422566..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [...createOptionActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index d01847d9d0..807e23de70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -7,7 +7,6 @@ import { manifests as cultureManifests } from './culture/manifests.js'; import { manifests as debugManifests } from './debug/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-action/manifests.js'; -import { manifests as entityManifests } from './entity/manifests.js'; import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; @@ -37,7 +36,6 @@ export const manifests: Array = ...debugManifests, ...entityActionManifests, ...entityBulkActionManifests, - ...entityManifests, ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts index 62404d353f..e0c48579b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -1,4 +1,4 @@ -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-action'; export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { override async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts index e661e70363..7da007dc51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -2,8 +2,10 @@ import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal. import type { UmbUserKindType } from '../../../utils/index.js'; import { UmbUserKind } from '../../../utils/index.js'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { + UmbEntityCreateOptionActionBase, + UmbRequestReloadChildrenOfEntityEvent, +} from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { @@ -19,7 +21,7 @@ export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptio }, }); - modalContext + await modalContext ?.onSubmit() .then(() => { this.#requestReloadChildrenOfEntity(); From 51171a2f336318fed1975367eee5fc7445198fa4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 13:25:39 +0100 Subject: [PATCH 144/246] import after restructure --- .../entity-create-option-action.extension.ts | 3 ++- .../src/packages/core/entity-action/manifests.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts index 2835753767..9aff339da4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts @@ -1,8 +1,9 @@ +import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, -> extends ManifestElementAndApi, +> extends ManifestElementAndApi>, ManifestWithDynamicConditions { type: 'entityCreateOptionAction'; forEntityTypes: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index 2f9fa9adc4..7d6813e49a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,3 +1,4 @@ +import { manifests as createEntityActionManifests } from './common/create/manifests.js'; import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; @@ -5,6 +6,7 @@ import { manifests as duplicateEntityActionManifests } from './common/duplicate/ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + ...createEntityActionManifests, ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, From 2180b6ef24fbf03218fae9d1bfd9fd50e4f956d4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 17:03:27 +0100 Subject: [PATCH 145/246] render create options --- .../create-user-collection-action.element.ts | 127 +++++++++--------- 1 file changed, 65 insertions(+), 62 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 4ffcc353d0..6ddc1b57cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -1,13 +1,7 @@ -import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; -import type { UmbUserKindType } from '../../utils/index.js'; -import { UmbUserKind } from '../../utils/index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; const elementName = 'umb-create-user-collection-action-button'; @customElement(elementName) @@ -15,83 +9,92 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @state() private _popoverOpen = false; - async #onClick(event: Event, kind: UmbUserKindType) { - event.stopPropagation(); - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + @state() + private _multipleOptions = false; - const unique = entityContext.getUnique(); - const entityType = entityContext.getEntityType(); + #apiControllers: Array = []; + #createLabel = this.localize.term('general_create'); - if (unique === undefined) throw new Error('Missing unique'); - if (!entityType) throw new Error('Missing entityType'); - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { - data: { - user: { - kind, - }, - }, - }); - - modalContext - ?.onSubmit() - .then(() => { - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }) - .catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }); - } - - async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - - eventContext.dispatchEvent(event); - } - - #onPopoverToggle(event: ToggleEvent) { + #onPopoverToggle(event: PointerEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._popoverOpen = event.newState === 'open'; } - override render() { - const label = this.localize.term('general_create'); + async #onClick(event: Event, controller: any) { + event.stopPropagation(); + await controller.api.execute(); + } + constructor() { + super(); + + new UmbExtensionsApiInitializer( + this, + umbExtensionsRegistry, + 'entityCreateOptionAction', + [], + undefined, + (controllers) => { + this.#apiControllers = controllers; + this._multipleOptions = controllers.length > 1; + }, + ); + } + + override render() { + return this._multipleOptions ? this.#renderMultiOptionAction() : this.#renderSingleOptionAction(); + } + + #renderSingleOptionAction() { + return html` this.#onClick(event, this.#apiControllers[0])}>`; + } + + #renderMultiOptionAction() { return html` - - ${label} + + ${this.#createLabel} + ${this.#renderDropdown()} + `; + } + + #renderDropdown() { + return html` - this.#onClick(event, UmbUserKind.DEFAULT)}> - - - this.#onClick(event, UmbUserKind.API)}> - - + ${this.#apiControllers.map((controller) => this.#renderMenuItem(controller))} `; } + + #renderMenuItem(controller: any) { + const label = controller.manifest.meta.label + ? this.localize.string(controller.manifest.meta.label) + : controller.manifest.meta.name; + + return html` + this.#onClick(event, controller)}> + + + `; + } } export { UmbCollectionActionButtonElement as element }; From 3941d78db3b8e329e55aeb2f6bac8ea06544afdc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:11:03 +0100 Subject: [PATCH 146/246] rename button --- .../action/create-user-collection-action.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 6ddc1b57cc..41c36a27d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -3,9 +3,9 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -const elementName = 'umb-create-user-collection-action-button'; +const elementName = 'umb-collection-create-action-button'; @customElement(elementName) -export class UmbCollectionActionButtonElement extends UmbLitElement { +export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @state() private _popoverOpen = false; @@ -97,10 +97,10 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { } } -export { UmbCollectionActionButtonElement as element }; +export { UmbCollectionCreateActionButtonElement as element }; declare global { interface HTMLElementTagNameMap { - [elementName]: UmbCollectionActionButtonElement; + [elementName]: UmbCollectionCreateActionButtonElement; } } From ec4720baa20f2fddfe00df252e43b3867320b7bb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:13:17 +0100 Subject: [PATCH 147/246] rename file --- ...on-action.element.ts => collection-create-action.element.ts} | 0 .../src/packages/user/user/collection/action/manifests.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/{create-user-collection-action.element.ts => collection-create-action.element.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts index 70aa992311..d2228e9b1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts @@ -5,7 +5,7 @@ export const manifests: Array = [ type: 'collectionAction', name: 'Create User Collection Action', alias: 'Umb.CollectionAction.User.Create', - element: () => import('./create-user-collection-action.element.js'), + element: () => import('./collection-create-action.element.js'), weight: 200, conditions: [ { From 44d1e244418f26f009283ad75ee6f5715082882e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:14:36 +0100 Subject: [PATCH 148/246] use constants --- .../src/packages/user/user/collection/action/manifests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts index d2228e9b1b..640a712e12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_USER_COLLECTION_ALIAS } from '../constants.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; export const manifests: Array = [ @@ -10,7 +11,7 @@ export const manifests: Array = [ conditions: [ { alias: UMB_COLLECTION_ALIAS_CONDITION, - match: 'Umb.Collection.User', + match: UMB_USER_COLLECTION_ALIAS, }, ], }, From 3575a6baed3c1c13d1fcc7fbc4b95d992cb99574 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:24:41 +0100 Subject: [PATCH 149/246] remove element from create action option manifest --- .../entity-create-option-action.element.ts | 87 ------------------- .../create-option-action/default/index.ts | 1 - .../create-option-action/default/manifests.ts | 20 ----- .../create-option-action/default/types.ts | 44 ---------- ...-create-option-action-element.interface.ts | 4 - .../entity-create-option-action.extension.ts | 4 +- .../create/create-option-action/index.ts | 5 -- .../create/create-option-action/manifests.ts | 4 - .../common/create/create.action.ts | 2 +- .../entity-action/common/create/manifests.ts | 3 +- 10 files changed, 4 insertions(+), 170 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts deleted file mode 100644 index 5c926bbe3e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { UmbEntityCreateOptionAction } from '../entity-create-option-action.interface.js'; -import type { UmbEntityCreateOptionActionElement } from '../entity-create-option-action-element.interface.js'; -import type { ManifestEntityCreateOptionAction } from '../entity-create-option-action.extension.js'; -import type { MetaEntityCreateOptionActionDefaultKind } from './types.js'; -import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; -import { html, nothing, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; - -const elementName = 'umb-entity-create-option-action'; -@customElement(elementName) -export class UmbEntityCreateOptionActionDefaultElement< - MetaType extends MetaEntityCreateOptionActionDefaultKind = MetaEntityCreateOptionActionDefaultKind, - ApiType extends UmbEntityCreateOptionAction = UmbEntityCreateOptionAction, - > - extends UmbLitElement - implements UmbEntityCreateOptionActionElement -{ - #api?: ApiType; - - // TODO: Do these need to be properties? [NL] - @property({ type: String }) - entityType?: string | null; - - // TODO: Do these need to be properties? [NL] - @property({ type: String }) - public unique?: string | null; - - @property({ attribute: false }) - public manifest?: ManifestEntityCreateOptionAction; - - public set api(api: ApiType | undefined) { - this.#api = api; - - // TODO: Fix so when we use a HREF it does not refresh the page? - this.#api?.getHref?.().then((href) => { - this._href = href; - // TODO: Do we need to update the component here? [NL] - }); - } - - @state() - _href?: string; - - override async focus() { - await this.updateComplete; - this.shadowRoot?.querySelector('uui-menu-item')?.focus(); - } - - async #onClickLabel(event: UUIMenuItemEvent) { - if (!this._href) { - event.stopPropagation(); - await this.#api?.execute(); - } - this.dispatchEvent(new UmbActionExecutedEvent()); - } - - // TODO: we need to stop the regular click event from bubbling up to the table so it doesn't select the row. - // This should probably be handled in the UUI Menu item component. so we don't dispatch a label-click event and click event at the same time. - #onClick(event: PointerEvent) { - event.stopPropagation(); - } - - override render() { - const label = this.manifest?.meta.label ? this.localize.string(this.manifest.meta.label) : this.manifest?.name; - - return html` - - ${this.manifest?.meta.icon - ? html`` - : nothing} - - `; - } -} - -export { UmbEntityCreateOptionActionDefaultElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbEntityCreateOptionActionDefaultElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts deleted file mode 100644 index d4702960d5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts deleted file mode 100644 index b1b7de24bf..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'kind', - alias: 'Umb.Kind.EntityCreateOptionAction.Default', - matchKind: 'default', - matchType: 'entityCreateOptionAction', - manifest: { - type: 'entityCreateOptionAction', - kind: 'default', - weight: 1000, - element: () => import('./entity-create-option-action.element.js'), - meta: { - icon: '', - label: 'Default Entity Create Option Action', - }, - }, - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts deleted file mode 100644 index 465664c91c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { - ManifestEntityCreateOptionAction, - MetaEntityCreateOptionAction, -} from '../entity-create-option-action.extension.js'; - -export interface ManifestEntityCreateOptionActionDefaultKind - extends ManifestEntityCreateOptionAction { - type: 'entityCreateOptionAction'; - kind: 'default'; -} - -export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { - /** - * An icon to represent the action to be performed - * @examples [ - * "icon-box", - * "icon-grid" - * ] - */ - icon: string; - - /** - * The friendly name of the action to perform - * @examples [ - * "Create", - * "Create Content Template" - * ] - */ - label: string; - - /** - * The action requires additional input from the user. - * A dialog will prompt the user for more information or to make a choice. - * @type {boolean} - * @memberof MetaEntityCreateOptionActionDefaultKind - */ - additionalOptions?: boolean; -} - -declare global { - interface UmbExtensionManifestMap { - umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts deleted file mode 100644 index 6f2c9ab833..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; - -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbEntityCreateOptionActionElement extends UmbControllerHostElement {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts index 9aff339da4..37341069c2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts @@ -1,9 +1,9 @@ import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; -import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; +import type { ManifestApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, -> extends ManifestElementAndApi>, +> extends ManifestApi>, ManifestWithDynamicConditions { type: 'entityCreateOptionAction'; forEntityTypes: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts index 5eb9c9635d..f14590182c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts @@ -1,12 +1,7 @@ import './global-components/index.js'; -export * from './default/index.js'; export * from './global-components/index.js'; - export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; - -export type * from './entity-create-option-action-element.interface.js'; - export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts deleted file mode 100644 index 43d020c74e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { manifests as defaultManifests } from './default/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [...defaultManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index d96860c9b9..a912365d80 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -23,7 +23,7 @@ export class UmbCreateEntityAction extends UmbEntityActionBase { this.#hasSingleOption = actionOptions.length === 1; this.#singleActionOptionManifest = this.#hasSingleOption - ? (actionOptions[0].manifest as ManifestEntityCreateOptionAction) + ? (actionOptions[0].manifest as unknown as ManifestEntityCreateOptionAction) : undefined; }, 'umbEntityActionsObserver', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts index 6aee3f93b6..d1e496f559 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts @@ -1,5 +1,4 @@ import { manifest as createKindManifest } from './create.action.kind.js'; import { manifests as modalManifests } from './modal/manifests.js'; -import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; -export const manifests = [createKindManifest, ...modalManifests, ...createOptionActionManifests]; +export const manifests = [createKindManifest, ...modalManifests]; From 311cdc4d1dbb1edb5f3b62a833f3ac2b4d129185 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 20:00:45 +0100 Subject: [PATCH 150/246] render as ref item --- ...ntity-create-option-action-list.element.ts | 109 ------------------ .../global-components/index.ts | 3 - .../create/create-option-action/index.ts | 3 - ...create-option-action-list-modal.element.ts | 50 +++++++- .../collection-create-action.element.ts | 10 +- 5 files changed, 52 insertions(+), 123 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts deleted file mode 100644 index eeb948c5d3..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts +++ /dev/null @@ -1,109 +0,0 @@ -import type { UmbEntityCreateOptionActionArgs } from '../types.js'; -import type { - ManifestEntityCreateOptionAction, - MetaEntityCreateOptionAction, -} from '../entity-create-option-action.extension.js'; -import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; -import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbApiConstructorArgumentsMethodType } from '@umbraco-cms/backoffice/extension-api'; - -const elementName = 'umb-entity-create-option-action-list'; -@customElement(elementName) -export class UmbEntityCreateOptionActionListElement extends UmbLitElement { - @property({ type: String, attribute: 'entity-type' }) - public get entityType(): string | undefined { - return this._props.entityType; - } - public set entityType(value: string | undefined) { - if (value === undefined || value === this._props.entityType) return; - this._props.entityType = value; - this.#generateApiArgs(); - this.requestUpdate('_props'); - // Update filter: - //const oldValue = this._filter; - this._filter = (extension: ManifestEntityCreateOptionAction) => - extension.forEntityTypes.includes(value); - //this.requestUpdate('_filter', oldValue); - } - - @state() - _filter?: (extension: ManifestEntityCreateOptionAction) => boolean; - - @property({ type: String }) - public get unique(): string | null | undefined { - return this._props.unique; - } - public set unique(value: string | null | undefined) { - if (value === this._props.unique) return; - this._props.unique = value; - this.#generateApiArgs(); - this.requestUpdate('_props'); - } - - @state() - _props: Partial> = {}; - - @state() - _apiArgs?: UmbApiConstructorArgumentsMethodType< - ManifestEntityCreateOptionAction, - [UmbEntityCreateOptionActionArgs] - >; - - #entityContext = new UmbEntityContext(this); - #extensionType = 'entityCreateOptionAction'; - - #generateApiArgs() { - if (!this._props.entityType || this._props.unique === undefined) return; - - this.#entityContext.setEntityType(this._props.entityType); - this.#entityContext.setUnique(this._props.unique); - this.#hasRenderedOnce = false; - - this._apiArgs = (manifest: ManifestEntityCreateOptionAction) => { - return [{ entityType: this._props.entityType!, unique: this._props.unique!, meta: manifest.meta }]; - }; - } - - #hasRenderedOnce?: boolean; - override render() { - return this._filter - ? html` - { - if (!this.#hasRenderedOnce && i === 0) { - // TODO: Replace this block: - ext.component?.updateComplete.then(async () => { - const menuitem = ext.component?.shadowRoot?.querySelector('uui-menu-item'); - menuitem?.updateComplete.then(async () => { - menuitem?.shadowRoot?.querySelector('#label-button')?.focus?.(); - }); - }); - // end of block, with this, when this PR is part of UI Lib: https://github.com/umbraco/Umbraco.UI/pull/789 - // ext.component?.focus(); - this.#hasRenderedOnce = true; - } - return ext.component; - }}> - ` - : ''; - } - - static override styles = [ - css` - :host { - --uui-menu-item-flat-structure: 1; - } - `, - ]; -} - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbEntityCreateOptionActionListElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts deleted file mode 100644 index 40da9cdab0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import './entity-create-option-action-list.element.js'; - -export * from './entity-create-option-action-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts index f14590182c..1794649010 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts @@ -1,6 +1,3 @@ -import './global-components/index.js'; - -export * from './global-components/index.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index e9ada04e69..f3ac6ad2a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -2,7 +2,9 @@ import type { UmbEntityCreateOptionActionListModalData, UmbEntityCreateOptionActionListModalValue, } from './entity-create-option-action-list-modal.token.js'; -import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; const elementName = 'umb-entity-create-option-action-list-modal'; @@ -11,13 +13,40 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle UmbEntityCreateOptionActionListModalData, UmbEntityCreateOptionActionListModalValue > { + @state() + private _apiControllers: Array = []; + + constructor() { + super(); + + new UmbExtensionsApiInitializer( + this, + umbExtensionsRegistry, + 'entityCreateOptionAction', + [], + undefined, + (controllers) => { + this._apiControllers = controllers; + }, + ); + } + + async #onClick(event: Event, controller: any) { + event.stopPropagation(); + await controller.api.execute(); + } + override render() { return html` - + + ${repeat( + this._apiControllers, + (controller) => controller.manifest.alias, + (controller) => this.#renderRefItem(controller), + )} + `; } + + #renderRefItem(controller: any) { + const manifest = controller.manifest; + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; + + return html` + this.#onClick(event, controller)}> + `; + } } export { UmbEntityCreateOptionActionListModalElement as element }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts index 41c36a27d1..90805b018e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts @@ -12,7 +12,9 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @state() private _multipleOptions = false; - #apiControllers: Array = []; + @state() + private _apiControllers: Array = []; + #createLabel = this.localize.term('general_create'); #onPopoverToggle(event: PointerEvent) { @@ -37,7 +39,7 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { [], undefined, (controllers) => { - this.#apiControllers = controllers; + this._apiControllers = controllers; this._multipleOptions = controllers.length > 1; }, ); @@ -52,7 +54,7 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { label=${this.#createLabel} color="default" look="outline" - @click=${(event: Event) => this.#onClick(event, this.#apiControllers[0])}>`; + @click=${(event: Event) => this.#onClick(event, this._apiControllers[0])}>`; } #renderMultiOptionAction() { @@ -77,7 +79,7 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - ${this.#apiControllers.map((controller) => this.#renderMenuItem(controller))} + ${this._apiControllers.map((controller) => this.#renderMenuItem(controller))} From 19b9c0756fd1c6336f065c31970e8d412d85c3ae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 20:03:02 +0100 Subject: [PATCH 151/246] render icon from manifest --- .../collection/action/collection-create-action.element.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts index 90805b018e..f0a2d88b95 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts @@ -87,13 +87,12 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { } #renderMenuItem(controller: any) { - const label = controller.manifest.meta.label - ? this.localize.string(controller.manifest.meta.label) - : controller.manifest.meta.name; + const manifest = controller.manifest; + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; return html` this.#onClick(event, controller)}> - + `; } From f93153a7aaaccbd257fdb522d4119f624a01c6fa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 22:02:22 +0100 Subject: [PATCH 152/246] add default kind --- .../create-option-action/default/index.ts | 1 + .../create-option-action/default/manifests.ts | 18 +++++++ .../create-option-action/default/types.ts | 52 +++++++++++++++++++ .../create/create-option-action/index.ts | 1 + .../create/create-option-action/manifests.ts | 3 ++ 5 files changed, 75 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts new file mode 100644 index 0000000000..d4702960d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts @@ -0,0 +1 @@ +export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts new file mode 100644 index 0000000000..1aa548f357 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts @@ -0,0 +1,18 @@ +export const manifests = [ + { + type: 'kind', + alias: 'Umb.Kind.EntityCreateOptionAction.Default', + matchKind: 'default', + matchType: 'entityCreateOptionAction', + manifest: { + type: 'entityCreateOptionAction', + kind: 'default', + weight: 1000, + meta: { + icon: '', + label: 'Fill out label', + description: 'Fill out description', + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts new file mode 100644 index 0000000000..f131c65468 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts @@ -0,0 +1,52 @@ +import type { + ManifestEntityCreateOptionAction, + MetaEntityCreateOptionAction, +} from '../entity-create-option-action.extension.js'; + +export interface ManifestEntityCreateOptionActionDefaultKind + extends ManifestEntityCreateOptionAction { + type: 'entityCreateOptionAction'; + kind: 'default'; +} + +export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { + /** + * An icon to represent the action to be performed + * @examples [ + * "icon-box", + * "icon-grid" + * ] + */ + icon: string; + + /** + * The friendly name of the action to perform + * @examples [ + * "Create with Template", + * "Create from Blueprint" + * ] + */ + label: string; + + /** + * A description of the action to be performed + * @examples [ + * "Create a document type with a template", + * "Create a document from a blueprint" + * ] + */ + description: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + */ + additionalOptions?: boolean; +} + +declare global { + interface UmbExtensionManifestMap { + umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts index 1794649010..3134f695a1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts @@ -1,3 +1,4 @@ +export * from './default/index.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts new file mode 100644 index 0000000000..a61fc1b883 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts @@ -0,0 +1,3 @@ +import { manifests as defaultManifests } from './default/manifests.js'; + +export const manifests = [...defaultManifests]; From b3ce981fadaa7510f9b9abd2af71fb7f60b96a38 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Tue, 29 Oct 2024 22:01:51 +0000 Subject: [PATCH 153/246] Feature: Markdown Editor toolbar styling (#2498) Stylizes the Markdown Editor toolbar to align with the Tiptap RTE toolbar style. --- .../input-markdown.element.ts | 293 ++++++++++-------- ...monaco-markdown-editor-action.extension.ts | 5 +- .../manifests.ts | 6 +- 3 files changed, 181 insertions(+), 123 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts index 9921108fdc..39e3004534 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.element.ts @@ -7,6 +7,7 @@ import { query, state, unsafeHTML, + when, } from '@umbraco-cms/backoffice/external/lit'; import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; import { marked } from '@umbraco-cms/backoffice/external/marked'; @@ -23,13 +24,15 @@ import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import { sanitizeHTML } from '@umbraco-cms/backoffice/utils'; -const elementName = 'umb-input-markdown'; +interface UmbMarkdownEditorAction extends monaco.editor.IActionDescriptor { + icon?: string | null; +} /** * @element umb-input-markdown * @fires change - when the value of the input changes */ -@customElement(elementName) +@customElement('umb-input-markdown') export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, '') { protected override getFormElement() { return this._codeEditor; @@ -65,7 +68,7 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, private _codeEditor?: UmbCodeEditorElement; @state() - private _actionExtensions: Array = []; + private _actionExtensions: Array = []; #mediaUrlRepository = new UmbMediaUrlRepository(this); @@ -82,9 +85,10 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, this.observe(umbExtensionsRegistry.byType('monacoMarkdownEditorAction'), (manifests) => { manifests.forEach(async (manifest) => { const api = await createExtensionApi(this, manifest, [this]); - const action: monaco.editor.IActionDescriptor = { - id: api.getUnique(), - label: api.getLabel(), + const action: UmbMarkdownEditorAction = { + id: manifest.alias ?? api.getUnique(), + label: this.localize.string(manifest.meta?.label ?? api.getLabel()), + icon: manifest.meta?.icon, keybindings: api.getKeybindings(), run: async () => await api.execute({ editor: this.#editor, overlaySize: this.overlaySize }), }; @@ -180,7 +184,7 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, run: () => this._insertBetweenSelection('```', '```', 'Code'), }); this.#editor?.monacoEditor?.addAction({ - label: 'Add Line', + label: 'Add Horizontal Line', id: 'line', run: () => this._insertLine(), }); @@ -193,7 +197,7 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, }); } - #onActionClick(event: any, action: monaco.editor.IActionDescriptor) { + #onActionClick(event: Event, action: monaco.editor.IActionDescriptor) { event.stopPropagation(); const hasAction = this.#editor?.monacoEditor?.getAction(action.id); if (!hasAction) throw new Error(`Action ${action.id} not found in the editor.`); @@ -429,6 +433,7 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, override render() { return html` ${this.#renderToolbar()} + + ${this.#renderPreview()} `; } @@ -447,112 +453,120 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, if (this.readonly) return nothing; return html`
      - - this.#editor?.monacoEditor?.getAction('h1')?.run()}> - H - - this.#editor?.monacoEditor?.getAction('b')?.run()}> - B - - this.#editor?.monacoEditor?.getAction('i')?.run()}> - I - - +
      + + this.#editor?.monacoEditor?.getAction('h1')?.run()}> + + + this.#editor?.monacoEditor?.getAction('b')?.run()}> + + + this.#editor?.monacoEditor?.getAction('i')?.run()}> + + + - - this.#editor?.monacoEditor?.getAction('q')?.run()}> - - - this.#editor?.monacoEditor?.getAction('ol')?.run()}> - - - this.#editor?.monacoEditor?.getAction('ul')?.run()}> - - - - - this.#editor?.monacoEditor?.getAction('code')?.run()}> - - - this.#editor?.monacoEditor?.getAction('line')?.run()}> - - - this.#editor?.monacoEditor?.getAction('image')?.run()}> - - - + + this.#editor?.monacoEditor?.getAction('q')?.run()}> + + + this.#editor?.monacoEditor?.getAction('ol')?.run()}> + + + this.#editor?.monacoEditor?.getAction('ul')?.run()}> + + + + + this.#editor?.monacoEditor?.getAction('code')?.run()}> + + + this.#editor?.monacoEditor?.getAction('line')?.run()}> + + + this.#editor?.monacoEditor?.getAction('image')?.run()}> + + + - - ${this._actionExtensions.map( - (action) => html` - this.#onActionClick(event, action)}> - - - `, - )} - - - - { - this._focusEditor(); - this.#editor?.monacoEditor?.trigger('', 'editor.action.quickCommand', ''); - }}> - F1 - - + + ${this._actionExtensions.map( + (action) => html` + this.#onActionClick(event, action)}> + ${when( + action.icon, + () => html``, + () => html`${this.localize.string(action.label)}`, + )} + + `, + )} + +
      +
      + + { + this._focusEditor(); + this.#editor?.monacoEditor?.trigger('', 'editor.action.quickCommand', ''); + }}> + F1 + + +
      `; } @@ -573,21 +587,58 @@ export class UmbInputMarkdownElement extends UmbFormControlMixin(UmbLitElement, } #toolbar { - background-color: var(--uui-color-background-alt); + display: flex; + justify-content: space-between; + align-items: center; + + border-radius: var(--uui-border-radius); + border: 1px solid var(--uui-color-border); + border-bottom: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + box-shadow: + 0 2px 2px -2px rgba(34, 47, 62, 0.1), + 0 8px 8px -4px rgba(34, 47, 62, 0.07); + + background-color: var(--uui-color-surface-alt); + color: var(--color-text); + + position: sticky; + top: -25px; + left: 0px; + right: 0px; + padding: var(--uui-size-3); + z-index: 9999999; + + uui-key { + text-transform: uppercase; + } + } + + #buttons { + flex: 1; display: flex; flex-wrap: wrap; - gap: var(--uui-size-2); - margin-bottom: var(--uui-size-2); + align-items: center; + + uui-button-group:not(:last-child)::after { + content: ''; + background-color: var(--uui-color-border); + width: 1px; + place-self: center; + height: 22px; + margin: 0 var(--uui-size-3); + } } umb-code-editor { height: 200px; border-radius: var(--uui-border-radius); - border: 1px solid var(--uui-color-divider-emphasis); - } - - uui-button { - width: 50px; + border: 1px solid var(--uui-color-border); + border-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; + padding-top: var(--uui-size-3); } #preview { @@ -623,6 +674,6 @@ export default UmbInputMarkdownElement; declare global { interface HTMLElementTagNameMap { - [elementName]: UmbInputMarkdownElement; + 'umb-input-markdown': UmbInputMarkdownElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/monaco-markdown-editor-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/monaco-markdown-editor-action.extension.ts index ebe216aa1b..95aedbe030 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/monaco-markdown-editor-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/monaco-markdown-editor-action.extension.ts @@ -5,7 +5,10 @@ export interface ManifestMonacoMarkdownEditorAction extends ManifestApi { meta?: MetaMonacoMarkdownEditorAction; } -export type MetaMonacoMarkdownEditorAction = object; +export type MetaMonacoMarkdownEditorAction = { + icon?: string | null; + label?: string | null; +}; declare global { interface UmbExtensionManifestMap { diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/monaco-markdown-editor-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/monaco-markdown-editor-action/manifests.ts index 78748548a1..d76b047df1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/monaco-markdown-editor-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/monaco-markdown-editor-action/manifests.ts @@ -3,6 +3,10 @@ export const manifests = [ type: 'monacoMarkdownEditorAction', alias: 'Umb.MonacoMarkdownEditorAction.MultiUrlPicker', name: 'Multi Url Picker Monaco Markdown Editor Action', - js: () => import('./url-picker-monaco-markdown-editor-action.js'), + api: () => import('./url-picker-monaco-markdown-editor-action.js'), + meta: { + label: '#buttons_linkInsert', + icon: 'icon-link', + }, }, ]; From 4c4566cda5ab076c1afbcb71eb84dac4351d0299 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Tue, 29 Oct 2024 22:09:41 +0000 Subject: [PATCH 154/246] Feature: Document Workspace Info Link State (#2497) Adds document link state to the workspace info links component. --- ...ument-workspace-view-info-links.element.ts | 156 +++++++++++------- 1 file changed, 100 insertions(+), 56 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts index 6b0fcb58ab..f244371dfa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts @@ -1,23 +1,28 @@ import { UmbDocumentUrlRepository } from '../../../repository/url/document-url.repository.js'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js'; -import type { UmbDocumentUrlModel } from '../../../repository/url/types.js'; -import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbDocumentVariantOptionModel } from '../../../types.js'; +import { css, customElement, html, map, nothing, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; @customElement('umb-document-workspace-view-info-links') export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { #documentUrlRepository = new UmbDocumentUrlRepository(this); - #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; + @state() + private _isNew = false; @state() - private _invariantCulture = 'en-US'; + private _unique?: string; @state() - private _items?: Array; + private _variantOptions?: Array; + + @state() + private _lookup: Record = {}; constructor() { super(); @@ -29,96 +34,135 @@ export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { }); this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { - this.#workspaceContext = context; - this.#requestUrls(); + this.observe( + observeMultiple([context.isNew, context.unique, context.variantOptions]), + ([isNew, unique, variantOptions]) => { + this._isNew = isNew === true; + this._unique = unique; + this._variantOptions = variantOptions; + this.#requestUrls(); + }, + ); }); } async #requestUrls() { - const unique = this.#workspaceContext?.getUnique(); - if (!unique) throw new Error('Document unique is required'); + if (this._isNew) return; - const { data } = await this.#documentUrlRepository.requestItems([unique]); + if (!this._unique) throw new Error('Document unique is required'); + + const { data } = await this.#documentUrlRepository.requestItems([this._unique]); if (data?.length) { - this._items = data[0].urls; + data[0].urls.forEach((item) => { + if (item.culture && item.url) { + this._lookup[item.culture] = item.url; + } + }); + this.requestUpdate('_lookup'); + } + } + + #getStateLocalizationKey(variantOption: UmbDocumentVariantOptionModel) { + switch (variantOption.variant?.state) { + case null: + case undefined: + case DocumentVariantStateModel.NOT_CREATED: + return 'content_notCreated'; + case DocumentVariantStateModel.DRAFT: + return 'content_itemNotPublished'; + case DocumentVariantStateModel.PUBLISHED: + return 'content_routeErrorCannotRoute'; + default: + return 'content_parentNotPublishedAnomaly'; } } override render() { return html` - - + + ${when( + this._isNew, + () => this.#renderNotCreated(), + () => this.#renderUrls(), + )} `; } - #renderUrls() { - if (!this._items) return nothing; - return html` - ${repeat( - this._items!, - (item) => item.culture, - (item) => html` - - ${item.culture} - ${item.url} - - - `, - )} - `; - } - - #renderUnpublished() { + #renderNotCreated() { return html` `; } + #renderUrls() { + if (!this._variantOptions?.length) return nothing; + return map(this._variantOptions, (variantOption) => this.#renderUrl(variantOption)); + } + + #renderUrl(variantOption: UmbDocumentVariantOptionModel) { + const varies = !!variantOption.culture; + const culture = varies ? variantOption.culture! : variantOption.language.unique; + const url = this._lookup[culture]; + return when( + url, + () => html` + + + ${varies ? culture : nothing} + ${url} + + + + `, + () => html` + + `, + ); + } + static override styles = [ - UmbTextStyles, css` - #link-section { - display: flex; - flex-direction: column; - text-align: left; + uui-box { + --uui-box-default-padding: 0; } .link-item { - padding: var(--uui-size-space-4) var(--uui-size-space-6); - display: grid; - grid-template-columns: auto 1fr auto; + display: flex; + justify-content: space-between; + align-items: center; gap: var(--uui-size-6); - color: inherit; - text-decoration: none; + + padding: var(--uui-size-space-4) var(--uui-size-space-6); &:is(a) { cursor: pointer; + color: inherit; + text-decoration: none; } &:is(a):hover { background: var(--uui-color-divider); } - .culture { - color: var(--uui-color-divider-emphasis); + & > span { + display: flex; + align-items: center; + gap: var(--uui-size-6); } - uui-icon { - margin-right: var(--uui-size-space-2); - vertical-align: middle; + .culture { + color: var(--uui-color-divider-emphasis); } } `, From b5f9ba06e0abc30512cf64dc3a218e02cd9e0044 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 Oct 2024 19:02:53 +0100 Subject: [PATCH 155/246] add module --- src/Umbraco.Web.UI.Client/package.json | 1 + .../packages/core/entity-action/common/create/create.action.ts | 2 +- .../src/packages/core/entity-action/common/create/index.ts | 2 +- .../default/index.ts | 0 .../default/manifests.ts | 0 .../default/types.ts | 0 .../entity-create-option-action-base.ts | 0 .../entity-create-option-action.extension.ts | 0 .../entity-create-option-action.interface.ts | 0 .../index.ts | 0 .../manifests.ts | 0 .../types.ts | 0 src/Umbraco.Web.UI.Client/tsconfig.json | 3 +++ 13 files changed, 6 insertions(+), 2 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/default/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/default/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/default/types.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/entity-create-option-action-base.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/entity-create-option-action.extension.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/entity-create-option-action.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/types.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index e8c3c25519..3b2715be05 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -41,6 +41,7 @@ "./document": "./dist-cms/packages/documents/documents/index.js", "./entity-action": "./dist-cms/packages/core/entity-action/index.js", "./entity-bulk-action": "./dist-cms/packages/core/entity-bulk-action/index.js", + "./entity-create-option-action": "./dist-cms/packages/core/entity-create-option-action/index.js", "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index a912365d80..e92c8813d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -2,7 +2,7 @@ import { UmbEntityActionBase } from '../../entity-action-base.js'; import type { UmbEntityActionArgs } from '../../types.js'; import type { MetaEntityActionCreateKind } from './types.js'; import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; -import type { ManifestEntityCreateOptionAction } from './create-option-action/index.js'; +import type { ManifestEntityCreateOptionAction } from '../../../entity-create-option-action/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts index e3989cd62d..3a3fdc0b1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -1,2 +1,2 @@ export { UmbCreateEntityAction } from './create.action.js'; -export * from './create-option-action/index.js'; +export * from '../../../entity-create-option-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index 40f18ca7ce..3fc4bfabed 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -68,6 +68,9 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/document": ["./src/packages/documents/documents/index.ts"], "@umbraco-cms/backoffice/entity-action": ["./src/packages/core/entity-action/index.ts"], "@umbraco-cms/backoffice/entity-bulk-action": ["./src/packages/core/entity-bulk-action/index.ts"], + "@umbraco-cms/backoffice/entity-create-option-action": [ + "./src/packages/core/entity-create-option-action/index.ts" + ], "@umbraco-cms/backoffice/entity": ["./src/packages/core/entity/index.ts"], "@umbraco-cms/backoffice/event": ["./src/packages/core/event/index.ts"], "@umbraco-cms/backoffice/extension-registry": ["./src/packages/core/extension-registry/index.ts"], From 8144af48bf812250c2901c797957718b30906207 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 13:03:22 +0100 Subject: [PATCH 156/246] remove default kind and require in on the base --- .../common/create/create.action.ts | 2 +- .../core/entity-action/common/create/index.ts | 1 - ...create-option-action-list-modal.element.ts | 44 ++++++++++++---- .../default/index.ts | 1 - .../default/manifests.ts | 18 ------- .../default/types.ts | 52 ------------------- .../entity-create-option-action-base.ts | 5 +- .../entity-create-option-action.extension.ts | 44 +++++++++++++++- .../entity-create-option-action.interface.ts | 6 ++- .../core/entity-create-option-action/index.ts | 1 - .../entity-create-option-action/manifests.ts | 3 -- .../api-user-entity-create-option-action.ts | 2 +- .../create/api-user/manifests.ts | 1 - ...efault-user-entity-create-option-action.ts | 8 ++- .../create/default-user/manifests.ts | 1 - 15 files changed, 90 insertions(+), 99 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index e92c8813d4..e341354768 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -2,11 +2,11 @@ import { UmbEntityActionBase } from '../../entity-action-base.js'; import type { UmbEntityActionArgs } from '../../types.js'; import type { MetaEntityActionCreateKind } from './types.js'; import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; -import type { ManifestEntityCreateOptionAction } from '../../../entity-create-option-action/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { createExtensionApi, UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; +import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action'; export class UmbCreateEntityAction extends UmbEntityActionBase { #hasSingleOption = true; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts index 3a3fdc0b1b..d44c5eca74 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -1,2 +1 @@ export { UmbCreateEntityAction } from './create.action.js'; -export * from '../../../entity-create-option-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index f3ac6ad2a8..a261169e90 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -2,11 +2,15 @@ import type { UmbEntityCreateOptionActionListModalData, UmbEntityCreateOptionActionListModalValue, } from './entity-create-option-action-list-modal.token.js'; +import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action'; +import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +type ManifestType = ManifestEntityCreateOptionAction; + const elementName = 'umb-entity-create-option-action-list-modal'; @customElement(elementName) export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseElement< @@ -14,7 +18,9 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle UmbEntityCreateOptionActionListModalValue > { @state() - private _apiControllers: Array = []; + private _apiControllers: Array> = []; + + #hrefMap = new Map(); constructor() { super(); @@ -26,13 +32,29 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle [], undefined, (controllers) => { - this._apiControllers = controllers; + this._apiControllers = controllers as unknown as Array>; + + this._apiControllers.forEach((controller) => { + controller.api?.getHref().then((href) => { + const alias = controller.manifest?.alias; + if (!alias) throw new Error('No alias found'); + // only apply to map if href is defined + if (href) { + this.#hrefMap.set(alias, href); + } + }); + }); }, ); } - async #onClick(event: Event, controller: any) { + async #onClick(event: Event, controller: UmbExtensionApiInitializer) { event.stopPropagation(); + + if (!controller.api) throw new Error('No api found'); + + const href = this.#hrefMap.get(controller.manifest?.alias); + await controller.api.execute(); } @@ -43,7 +65,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle ${repeat( this._apiControllers, - (controller) => controller.manifest.alias, + (controller) => controller.manifest?.alias, (controller) => this.#renderRefItem(controller), )} @@ -56,16 +78,20 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle `; } - #renderRefItem(controller: any) { + #renderRefItem(controller: UmbExtensionApiInitializer) { const manifest = controller.manifest; - const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; + if (!manifest) throw new Error('No manifest found'); + + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; + const href = this.#hrefMap.get(manifest.alias); return html` this.#onClick(event, controller)}> + @click=${(event: Event) => this.#onClick(event, controller)} + .href=${href}> `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts deleted file mode 100644 index d4702960d5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts deleted file mode 100644 index 1aa548f357..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const manifests = [ - { - type: 'kind', - alias: 'Umb.Kind.EntityCreateOptionAction.Default', - matchKind: 'default', - matchType: 'entityCreateOptionAction', - manifest: { - type: 'entityCreateOptionAction', - kind: 'default', - weight: 1000, - meta: { - icon: '', - label: 'Fill out label', - description: 'Fill out description', - }, - }, - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts deleted file mode 100644 index f131c65468..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { - ManifestEntityCreateOptionAction, - MetaEntityCreateOptionAction, -} from '../entity-create-option-action.extension.js'; - -export interface ManifestEntityCreateOptionActionDefaultKind - extends ManifestEntityCreateOptionAction { - type: 'entityCreateOptionAction'; - kind: 'default'; -} - -export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { - /** - * An icon to represent the action to be performed - * @examples [ - * "icon-box", - * "icon-grid" - * ] - */ - icon: string; - - /** - * The friendly name of the action to perform - * @examples [ - * "Create with Template", - * "Create from Blueprint" - * ] - */ - label: string; - - /** - * A description of the action to be performed - * @examples [ - * "Create a document type with a template", - * "Create a document from a blueprint" - * ] - */ - description: string; - - /** - * The action requires additional input from the user. - * A dialog will prompt the user for more information or to make a choice. - * @type {boolean} - */ - additionalOptions?: boolean; -} - -declare global { - interface UmbExtensionManifestMap { - umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts index c8daf62492..2800261185 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts @@ -1,8 +1,11 @@ import type { UmbEntityCreateOptionActionArgs } from './types.js'; import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; +import type { MetaEntityCreateOptionAction } from './entity-create-option-action.extension.js'; import { UmbActionBase } from '@umbraco-cms/backoffice/action'; -export abstract class UmbEntityCreateOptionActionBase +export abstract class UmbEntityCreateOptionActionBase< + ArgsMetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, + > extends UmbActionBase> implements UmbEntityCreateOptionAction { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts index 37341069c2..cce0b9a4f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts @@ -3,7 +3,7 @@ import type { ManifestApi, ManifestWithDynamicConditions } from '@umbraco-cms/ba export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, -> extends ManifestApi>, +> extends ManifestApi>, ManifestWithDynamicConditions { type: 'entityCreateOptionAction'; forEntityTypes: Array; @@ -11,4 +11,44 @@ export interface ManifestEntityCreateOptionAction< } // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface MetaEntityCreateOptionAction {} +export interface MetaEntityCreateOptionAction { + /** + * An icon to represent the action to be performed + * @examples [ + * "icon-box", + * "icon-grid" + * ] + */ + icon: string; + + /** + * The friendly name of the action to perform + * @examples [ + * "Create with Template", + * "Create from Blueprint" + * ] + */ + label: string; + + /** + * A description of the action to be performed + * @examples [ + * "Create a document type with a template", + * "Create a document from a blueprint" + * ] + */ + description?: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + */ + additionalOptions?: boolean; +} + +declare global { + interface UmbExtensionManifestMap { + umbEntityCreateOptionAction: ManifestEntityCreateOptionAction; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts index 0956868cb7..141e9dd084 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts @@ -1,8 +1,10 @@ +import type { MetaEntityCreateOptionAction } from './entity-create-option-action.extension.js'; import type { UmbEntityCreateOptionActionArgs } from './types.js'; import type { UmbAction } from '@umbraco-cms/backoffice/action'; -export interface UmbEntityCreateOptionAction - extends UmbAction> { +export interface UmbEntityCreateOptionAction< + ArgsMetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, +> extends UmbAction> { /** * The href location, the action will act as a link. * @returns {Promise} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index 3134f695a1..1794649010 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,4 +1,3 @@ -export * from './default/index.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts deleted file mode 100644 index a61fc1b883..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { manifests as defaultManifests } from './default/manifests.js'; - -export const manifests = [...defaultManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts index e0c48579b8..ebb5d4571a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -1,4 +1,4 @@ -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { override async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts index 5c5ea02ca8..8232d63fbc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts @@ -3,7 +3,6 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; export const manifests: Array = [ { type: 'entityCreateOptionAction', - kind: 'default', alias: 'Umb.EntityCreateOptionAction.User.Api', name: 'Api User Entity Create Option Action', weight: 1100, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts index 7da007dc51..3d67778126 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -1,14 +1,12 @@ import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; import type { UmbUserKindType } from '../../../utils/index.js'; import { UmbUserKind } from '../../../utils/index.js'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { - UmbEntityCreateOptionActionBase, - UmbRequestReloadChildrenOfEntityEvent, -} from '@umbraco-cms/backoffice/entity-action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { +export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { override async execute() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const kind: UmbUserKindType = UmbUserKind.DEFAULT; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts index 4e12d1e039..cccb602cfc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts @@ -3,7 +3,6 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; export const manifests: Array = [ { type: 'entityCreateOptionAction', - kind: 'default', alias: 'Umb.EntityCreateOptionAction.User.Default', name: 'Default User Entity Create Option Action', weight: 1200, From bf94b4aa3fdfbb2274294ad6e2d1fd2b77b22373 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 13:57:59 +0100 Subject: [PATCH 157/246] get ref for item --- ...create-option-action-list-modal.element.ts | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index a261169e90..1db65a8f85 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -20,7 +20,11 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() private _apiControllers: Array> = []; - #hrefMap = new Map(); + @state() + _hrefMap = new Map(); + + @state() + _hrefList: Array = []; constructor() { super(); @@ -31,19 +35,11 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle 'entityCreateOptionAction', [], undefined, - (controllers) => { + async (controllers) => { this._apiControllers = controllers as unknown as Array>; - this._apiControllers.forEach((controller) => { - controller.api?.getHref().then((href) => { - const alias = controller.manifest?.alias; - if (!alias) throw new Error('No alias found'); - // only apply to map if href is defined - if (href) { - this.#hrefMap.set(alias, href); - } - }); - }); + const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); + this._hrefList = await Promise.all(hrefPromises); }, ); } @@ -51,10 +47,15 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle async #onClick(event: Event, controller: UmbExtensionApiInitializer) { event.stopPropagation(); - if (!controller.api) throw new Error('No api found'); + if (!controller.manifest) throw new Error('No manifest found'); + const href = this._hrefMap.get(controller.manifest?.alias); - const href = this.#hrefMap.get(controller.manifest?.alias); + // skip if href is defined + if (href) { + return; + } + if (!controller.api) throw new Error('No API found'); await controller.api.execute(); } @@ -66,7 +67,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle ${repeat( this._apiControllers, (controller) => controller.manifest?.alias, - (controller) => this.#renderRefItem(controller), + (controller, index) => this.#renderRefItem(controller, index), )} @@ -78,12 +79,12 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle `; } - #renderRefItem(controller: UmbExtensionApiInitializer) { + #renderRefItem(controller: UmbExtensionApiInitializer, index: number) { const manifest = controller.manifest; if (!manifest) throw new Error('No manifest found'); const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; - const href = this.#hrefMap.get(manifest.alias); + const href = this._hrefList[index]; return html` this.#onClick(event, controller)} - .href=${href}> + href=${ifDefined(href)}> `; } } From a01b10238d96707ea0cb193980cafccc49492cd8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 14:20:56 +0100 Subject: [PATCH 158/246] switch between button and link state --- ...ity-create-option-action-list-modal.element.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 1db65a8f85..270bd46805 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -59,6 +59,14 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle await controller.api.execute(); } + #getTarget(href?: string) { + if (href && href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + override render() { return html` @@ -87,12 +95,15 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle const href = this._hrefList[index]; return html` - this.#onClick(event, controller)} - href=${ifDefined(href)}> + href=${ifDefined(href)} + target=${this.#getTarget(href)} + ?selectable=${!href} + ?readonly=${!href}> `; } } From fbc71153ba29cb479ee401b77dc798d63fa90198 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 15:41:11 +0100 Subject: [PATCH 159/246] pass args to api --- ...create-option-action-list-modal.element.ts | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 270bd46805..2bdc224261 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -6,7 +6,7 @@ import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/e import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, repeat, ifDefined, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; type ManifestType = ManifestEntityCreateOptionAction; @@ -26,18 +26,29 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() _hrefList: Array = []; - constructor() { - super(); + @property({ attribute: false }) + public override set data(value: UmbEntityCreateOptionActionListModalData | undefined) { + super.data = value; + + if (value) { + this.#initApi(); + } + } + + #initApi() { + if (this._data?.entityType === undefined) throw new Error('No entityType found'); + if (this._data?.unique === undefined) throw new Error('No unique found'); new UmbExtensionsApiInitializer( this, umbExtensionsRegistry, 'entityCreateOptionAction', - [], + (manifest: ManifestType) => { + return [{ entityType: this._data!.entityType, unique: this._data!.unique, meta: manifest.meta }]; + }, undefined, async (controllers) => { this._apiControllers = controllers as unknown as Array>; - const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); this._hrefList = await Promise.all(hrefPromises); }, From 32a11d85579d88094c84ea2ee70ddba4f352da51 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 18:44:05 +0100 Subject: [PATCH 160/246] null check + render correct icon --- ...create-option-action-list-modal.element.ts | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 2bdc224261..03360e282c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -6,7 +6,15 @@ import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/e import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state, repeat, ifDefined, property } from '@umbraco-cms/backoffice/external/lit'; +import { + html, + customElement, + state, + repeat, + ifDefined, + property, + type PropertyValues, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; type ManifestType = ManifestEntityCreateOptionAction; @@ -26,25 +34,27 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() _hrefList: Array = []; - @property({ attribute: false }) - public override set data(value: UmbEntityCreateOptionActionListModalData | undefined) { - super.data = value; + protected override updated(_changedProperties: PropertyValues): void { + super.updated(_changedProperties); - if (value) { + if (_changedProperties.has('data')) { this.#initApi(); } } #initApi() { - if (this._data?.entityType === undefined) throw new Error('No entityType found'); - if (this._data?.unique === undefined) throw new Error('No unique found'); + const data = this.data; + if (!data) throw new Error('No data found'); + + if (data.entityType === undefined) throw new Error('No entityType found'); + if (data.unique === undefined) throw new Error('No unique found'); new UmbExtensionsApiInitializer( this, umbExtensionsRegistry, 'entityCreateOptionAction', (manifest: ManifestType) => { - return [{ entityType: this._data!.entityType, unique: this._data!.unique, meta: manifest.meta }]; + return [{ entityType: data.entityType, unique: data.unique, meta: manifest.meta }]; }, undefined, async (controllers) => { @@ -109,12 +119,13 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle this.#onClick(event, controller)} href=${ifDefined(href)} target=${this.#getTarget(href)} ?selectable=${!href} - ?readonly=${!href}> + ?readonly=${!href}> + + `; } } From 1ce1ee458f46c5da5dc68a2c7dfbd646241883f7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 19:14:18 +0100 Subject: [PATCH 161/246] extract to base class --- .../api-user-entity-create-option-action.ts | 17 ++++-- ...efault-user-entity-create-option-action.ts | 49 ++++------------ .../user-entity-create-option-action-base.ts | 58 +++++++++++++++++++ 3 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts index ebb5d4571a..2fd165fed7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -1,8 +1,17 @@ -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; +import { UmbUserEntityCreateOptionActionBase } from '../user-entity-create-option-action-base.js'; +import { UmbUserKind } from '../../../utils/index.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + MetaEntityCreateOptionAction, + UmbEntityCreateOptionActionArgs, +} from '@umbraco-cms/backoffice/entity-create-option-action'; -export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { - override async execute() { - debugger; +export class UmbApiUserEntityCreateOptionAction extends UmbUserEntityCreateOptionActionBase { + constructor(host: UmbControllerHost, args: UmbEntityCreateOptionActionArgs) { + super(host, { + ...args, + kind: UmbUserKind.API, + }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts index 3d67778126..9c67384285 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -1,44 +1,17 @@ -import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; -import type { UmbUserKindType } from '../../../utils/index.js'; import { UmbUserKind } from '../../../utils/index.js'; -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UmbUserEntityCreateOptionActionBase } from '../user-entity-create-option-action-base.js'; +import type { + MetaEntityCreateOptionAction, + UmbEntityCreateOptionActionArgs, +} from '@umbraco-cms/backoffice/entity-create-option-action'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { - override async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const kind: UmbUserKindType = UmbUserKind.DEFAULT; - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { - data: { - user: { - kind, - }, - }, +export class UmbDefaultUserEntityCreateOptionAction extends UmbUserEntityCreateOptionActionBase { + constructor(host: UmbControllerHost, args: UmbEntityCreateOptionActionArgs) { + super(host, { + ...args, + kind: UmbUserKind.DEFAULT, }); - - await modalContext - ?.onSubmit() - .then(() => { - this.#requestReloadChildrenOfEntity(); - }) - .catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - this.#requestReloadChildrenOfEntity(); - }); - } - - async #requestReloadChildrenOfEntity() { - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType: this.args.entityType, - unique: this.args.unique, - }); - - eventContext.dispatchEvent(event); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts new file mode 100644 index 0000000000..ea74db1f15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts @@ -0,0 +1,58 @@ +import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; +import type { UmbUserKindType } from '../../utils/index.js'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { + UmbEntityCreateOptionActionBase, + type MetaEntityCreateOptionAction, + type UmbEntityCreateOptionActionArgs, +} from '@umbraco-cms/backoffice/entity-create-option-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export interface UmbUserEntityCreateOptionActionBaseArgs + extends UmbEntityCreateOptionActionArgs { + kind: UmbUserKindType; +} + +export abstract class UmbUserEntityCreateOptionActionBase extends UmbEntityCreateOptionActionBase { + #kind: UmbUserKindType; + + constructor(host: UmbControllerHost, args: UmbUserEntityCreateOptionActionBaseArgs) { + super(host, args); + this.#kind = args.kind; + } + + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind: this.#kind, + }, + }, + }); + + await modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity(); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity(); + }); + } + + async #requestReloadChildrenOfEntity() { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType: this.args.entityType, + unique: this.args.unique, + }); + + eventContext.dispatchEvent(event); + } +} From c2d186de2bf3bf14c334943181e3656a4b806cc9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 20:29:53 +0100 Subject: [PATCH 162/246] clean up --- .../entity-create-option-action-list-modal.element.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 03360e282c..e3c871d6ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -12,7 +12,6 @@ import { state, repeat, ifDefined, - property, type PropertyValues, } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @@ -28,9 +27,6 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() private _apiControllers: Array> = []; - @state() - _hrefMap = new Map(); - @state() _hrefList: Array = []; @@ -65,12 +61,9 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle ); } - async #onClick(event: Event, controller: UmbExtensionApiInitializer) { + async #onClick(event: Event, controller: UmbExtensionApiInitializer, href?: string) { event.stopPropagation(); - if (!controller.manifest) throw new Error('No manifest found'); - const href = this._hrefMap.get(controller.manifest?.alias); - // skip if href is defined if (href) { return; @@ -119,7 +112,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle this.#onClick(event, controller)} + @click=${(event: Event) => this.#onClick(event, controller, href)} href=${ifDefined(href)} target=${this.#getTarget(href)} ?selectable=${!href} From b0fc2644672713af14d2c235a5766bae67e0d4e7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 20:30:32 +0100 Subject: [PATCH 163/246] clean up --- .../modal/entity-create-option-action-list-modal.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index e3c871d6ec..3675770b96 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -42,7 +42,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle const data = this.data; if (!data) throw new Error('No data found'); - if (data.entityType === undefined) throw new Error('No entityType found'); + if (!data.entityType) throw new Error('No entityType found'); if (data.unique === undefined) throw new Error('No unique found'); new UmbExtensionsApiInitializer( From d8cbfcfaadb638f1d3f44227b9f873a10a0c1cb2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 20:41:41 +0100 Subject: [PATCH 164/246] move create modal into create folder --- .../user/user/entity-actions/create/index.ts | 1 + .../user/user/entity-actions/create/manifests.ts | 2 ++ .../create/modal}/constants.ts | 0 .../create/modal}/create-user-modal.element.ts | 4 ++-- .../create/modal}/create-user-modal.token.ts | 2 +- .../modal}/create-user-success-modal.element.ts | 8 ++++---- .../modal}/create-user-success-modal.token.ts | 0 .../user/entity-actions/create/modal/index.ts | 1 + .../entity-actions/create/modal/manifests.ts | 16 ++++++++++++++++ .../user-entity-create-option-action-base.ts | 2 +- .../src/packages/user/user/modals/manifests.ts | 14 -------------- 11 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/constants.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-modal.element.ts (97%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-modal.token.ts (85%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-success-modal.element.ts (92%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-success-modal.token.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts new file mode 100644 index 0000000000..28d9f38fba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts @@ -0,0 +1 @@ +export * from './modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index 2e67f026d0..095b44610b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,6 +1,7 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { manifests as apiUser } from './api-user/manifests.js'; import { manifests as defaultUser } from './default-user/manifests.js'; +import { manifests as modalManifests } from './modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -14,4 +15,5 @@ export const manifests: Array = }, ...apiUser, ...defaultUser, + ...modalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.element.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.element.ts index 863fc88bec..cea24184d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.element.ts @@ -1,5 +1,5 @@ -import { UmbUserDetailRepository } from '../../repository/index.js'; -import { UmbUserKind } from '../../utils/index.js'; +import { UmbUserDetailRepository } from '../../../repository/index.js'; +import { UmbUserKind } from '../../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbCreateUserModalData } from './create-user-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.token.ts similarity index 85% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.token.ts index 4486b12f4f..3fb7a19847 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.token.ts @@ -1,4 +1,4 @@ -import type { UmbUserKindType } from '../../utils/index.js'; +import type { UmbUserKindType } from '../../../utils/index.js'; import { UMB_CREATE_USER_MODAL_ALIAS } from './constants.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.element.ts similarity index 92% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.element.ts index f30bf145be..d3c43c0a0d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.element.ts @@ -1,7 +1,7 @@ -import { UmbUserItemRepository } from '../../repository/item/index.js'; -import { UmbNewUserPasswordRepository } from '../../repository/new-password/index.js'; -import type { UmbUserItemModel } from '../../repository/item/types.js'; -import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; +import { UmbUserItemRepository } from '../../../repository/item/index.js'; +import { UmbNewUserPasswordRepository } from '../../../repository/new-password/index.js'; +import type { UmbUserItemModel } from '../../../repository/item/index.js'; +import { UMB_USER_WORKSPACE_PATH } from '../../../paths.js'; import type { UmbCreateUserSuccessModalData, UmbCreateUserSuccessModalValue, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts new file mode 100644 index 0000000000..ca86e33e91 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts @@ -0,0 +1,16 @@ +import { UMB_CREATE_USER_MODAL_ALIAS } from './constants.js'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_CREATE_USER_MODAL_ALIAS, + name: 'Create User Modal', + js: () => import('./create-user-modal.element.js'), + }, + { + type: 'modal', + alias: 'Umb.Modal.User.CreateSuccess', + name: 'Create Success User Modal', + js: () => import('./create-user-success-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts index ea74db1f15..ca55652d5a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts @@ -1,5 +1,5 @@ -import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; import type { UmbUserKindType } from '../../utils/index.js'; +import { UMB_CREATE_USER_MODAL } from './modal/create-user-modal.token.js'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts index 614f3e0d7b..03273e88df 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts @@ -1,18 +1,4 @@ -import { UMB_CREATE_USER_MODAL_ALIAS } from './create/constants.js'; - export const manifests: Array = [ - { - type: 'modal', - alias: UMB_CREATE_USER_MODAL_ALIAS, - name: 'Create User Modal', - js: () => import('./create/create-user-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.User.CreateSuccess', - name: 'Create Success User Modal', - js: () => import('./create/create-user-success-modal.element.js'), - }, { type: 'modal', alias: 'Umb.Modal.User.Picker', From 2f8fba9512cae3c537beb0597dde79db71cc6014 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 21:00:48 +0100 Subject: [PATCH 165/246] add create collection action kind --- .../collection-create-action.element.ts | 0 .../collection/action/create/manifests.ts | 19 +++++++++++++++++++ .../core/collection/action/create/types.ts | 12 ++++++++++++ .../core/collection/action/manifests.ts | 4 ++++ .../src/packages/core/collection/manifests.ts | 2 ++ ...create-option-action-list-modal.element.ts | 16 +++++++++------- .../user/user/collection/action/manifests.ts | 3 +-- 7 files changed, 47 insertions(+), 9 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/{user/user/collection/action => core/collection/action/create}/collection-create-action.element.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts new file mode 100644 index 0000000000..429fb41b26 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts @@ -0,0 +1,19 @@ +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.CollectionAction.Create', + matchKind: 'create', + matchType: 'collectionAction', + manifest: { + type: 'collectionAction', + kind: 'create', + element: () => import('./collection-create-action.element.js'), + weight: 1200, + meta: { + label: '#actions_create', + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts new file mode 100644 index 0000000000..50ef773e2c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts @@ -0,0 +1,12 @@ +import type { ManifestCollectionAction } from '../../extensions/index.js'; + +export interface ManifestCollectionActionCreateKind extends ManifestCollectionAction { + type: 'collectionAction'; + kind: 'create'; +} + +declare global { + interface UmbExtensionManifestMap { + umbCollectionActionCreateKind: ManifestCollectionActionCreateKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts new file mode 100644 index 0000000000..19f4780244 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as createManifests } from './create/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...createManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts index 1ee0674ee8..7433177e0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts @@ -1,9 +1,11 @@ import type { UmbExtensionManifestKind } from '../extension-registry/registry.js'; import { manifest as collectionAliasCondition } from './collection-alias.manifest.js'; import { manifest as collectionBulkActionPermissionCondition } from './collection-bulk-action-permission.manifest.js'; +import { manifests as actionManifests } from './action/manifests.js'; import { manifests as workspaceViewManifests } from './workspace-view/manifests.js'; export const manifests: Array = [ + ...actionManifests, ...workspaceViewManifests, collectionAliasCondition, collectionBulkActionPermissionCondition, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 3675770b96..2cb2537636 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -85,13 +85,15 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle return html` - - ${repeat( - this._apiControllers, - (controller) => controller.manifest?.alias, - (controller, index) => this.#renderRefItem(controller, index), - )} - + ${this._apiControllers.length === 0 + ? html`
      No create options available.
      ` + : html` + ${repeat( + this._apiControllers, + (controller) => controller.manifest?.alias, + (controller, index) => this.#renderRefItem(controller, index), + )} + `}
      = [ { type: 'collectionAction', + kind: 'create', name: 'Create User Collection Action', alias: 'Umb.CollectionAction.User.Create', - element: () => import('./collection-create-action.element.js'), - weight: 200, conditions: [ { alias: UMB_COLLECTION_ALIAS_CONDITION, From 75731a0f9dc179d16b4a8ae26ad78867db50829e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 22:29:38 +0100 Subject: [PATCH 166/246] filter + add types --- .../modal/entity-create-option-action-list-modal.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 2cb2537636..5150c3946d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -28,7 +28,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle private _apiControllers: Array> = []; @state() - _hrefList: Array = []; + _hrefList: Array = []; protected override updated(_changedProperties: PropertyValues): void { super.updated(_changedProperties); @@ -52,7 +52,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle (manifest: ManifestType) => { return [{ entityType: data.entityType, unique: data.unique, meta: manifest.meta }]; }, - undefined, + (manifest: ManifestType) => manifest.forEntityTypes.includes(data.entityType), async (controllers) => { this._apiControllers = controllers as unknown as Array>; const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); From 1c089a6aa8d1d1a779c25bd1964cde786fa094b0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 22:29:48 +0100 Subject: [PATCH 167/246] align with modal --- .../collection-create-action.element.ts | 72 ++++++++++++++++--- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts index f0a2d88b95..fd80de09a2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts @@ -1,7 +1,12 @@ -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action'; + +type ManifestType = ManifestEntityCreateOptionAction; const elementName = 'umb-collection-create-action-button'; @customElement(elementName) @@ -13,9 +18,13 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { private _multipleOptions = false; @state() - private _apiControllers: Array = []; + private _apiControllers: Array> = []; + + @state() + _hrefList: Array = []; #createLabel = this.localize.term('general_create'); + #entityContext?: typeof UMB_ENTITY_CONTEXT.TYPE; #onPopoverToggle(event: PointerEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. @@ -24,27 +33,61 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { this._popoverOpen = event.newState === 'open'; } - async #onClick(event: Event, controller: any) { + async #onClick(event: Event, controller: UmbExtensionApiInitializer, href?: string) { event.stopPropagation(); + + // skip if href is defined + if (href) { + return; + } + + if (!controller.api) throw new Error('No API found'); await controller.api.execute(); } constructor() { super(); + this.consumeContext(UMB_ENTITY_CONTEXT, (context) => { + this.#entityContext = context; + this.#initApi(); + }); + } + + #initApi() { + if (!this.#entityContext) return; + + const entityType = this.#entityContext.getEntityType(); + if (!entityType) throw new Error('No entityType found'); + + const unique = this.#entityContext.getUnique(); + if (unique === undefined) throw new Error('No unique found'); + new UmbExtensionsApiInitializer( this, umbExtensionsRegistry, 'entityCreateOptionAction', - [], - undefined, - (controllers) => { - this._apiControllers = controllers; + (manifest: ManifestType) => { + return [{ entityType, unique, meta: manifest.meta }]; + }, + (manifest: ManifestType) => manifest.forEntityTypes.includes(entityType), + async (controllers) => { + this._apiControllers = controllers as unknown as Array>; this._multipleOptions = controllers.length > 1; + const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); + this._hrefList = await Promise.all(hrefPromises); }, ); } + #getTarget(href?: string) { + if (href && href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + override render() { return this._multipleOptions ? this.#renderMultiOptionAction() : this.#renderSingleOptionAction(); } @@ -79,19 +122,26 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - ${this._apiControllers.map((controller) => this.#renderMenuItem(controller))} + ${this._apiControllers.map((controller, index) => this.#renderMenuItem(controller, index))} `; } - #renderMenuItem(controller: any) { + #renderMenuItem(controller: UmbExtensionApiInitializer, index: number) { const manifest = controller.manifest; - const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; + if (!manifest) throw new Error('No manifest found'); + + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; + const href = this._hrefList[index]; return html` - this.#onClick(event, controller)}> + this.#onClick(event, controller, href)} + href=${ifDefined(href)} + target=${this.#getTarget(href)}> `; From 39fe9a86e2482a93f16190ca94e3a05ce8f1596f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 12:38:41 +0100 Subject: [PATCH 168/246] lint corrections --- .../src/assets/lang/ar.ts | 3160 +++++++++-------- .../entity-create-option-action.extension.ts | 1 - .../packages/core/localization/manifests.ts | 2 +- .../section-sidebar-menu.element.ts | 2 +- ...-tiny-mce-toolbar-configuration.element.ts | 14 +- 5 files changed, 1634 insertions(+), 1545 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts index 64bb555510..5f57427859 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/ar.ts @@ -1,541 +1,561 @@ import type { UmbLocalizationDictionary } from '@umbraco-cms/backoffice/localization-api'; export default { - actions: { - assigndomain: 'الثقافة وأسماء النطاقات', - auditTrail: 'سجل التدقيق', - browse: 'تصفح ', - changeDataType: 'تغيير نوع البيانات', - changeDocType: 'تغيير نوع الوثيقة', - chooseWhereToCopy: 'اختر مكان النسخ', - chooseWhereToImport: 'اختر مكان الاستيراد', - chooseWhereToMove: 'اختر مكان النقل', - copy: 'نسخ', - copyTo: 'نسخ إلى', - create: 'إنشاء', - createblueprint: 'إنشاء مخطط انشائي للمستند', - createGroup: 'إنشاء مجموعة', - createPackage: 'إنشاء حزمة', - delete: 'حذف', - disable: 'تعطيل', - editContent: 'تحرير المحتوى', - editSettings: 'تحرير الإعدادات', - emptyrecyclebin: 'إفراغ سلة المحذوفات', - enable: 'تمكين', - export: 'تصدير', - exportDocumentType: 'تصدير نوع الوثيقة', - folderCreate: 'إنشاء مجلد', - folderDelete: 'حذف مجلد', - folderRename: 'إعادة تسمية مجلد', - import: 'استيراد', - importdocumenttype: 'استيراد نوع وثيقة', - importPackage: 'استيراد حزمة', - infiniteEditorChooseWhereToCopy: 'اختر مكان نسخ العنصر (العناصر) المحددة', - infiniteEditorChooseWhereToMove: 'اختر مكان نقل العنصر (العناصر) المحددة', - liveEdit: 'تحرير مباشر', - logout: 'تسجيل خروج', - move: 'نقل إلى', - notify: 'الإشعارات', - protect: 'الوصول العام', - publish: 'نشر', - refreshNode: 'إعادة تحميل', - remove: 'إزالة', - rename: 'إعادة تسمية', - republish: 'إعادة نشر الموقع بالكامل', - resendInvite: 'إعادة إرسال الدعوة', - restore: 'استعادة', - rights: 'الأذونات', - rollback: 'التراجع', - sendtopublish: 'إرسال للنشر', - sendToTranslate: 'إرسال للترجمة', - setGroup: 'تعيين مجموعة', - setPermissions: 'تعيين الأذونات', - sort: 'ترتيب الابناء', - toInTheTreeStructureBelow: 'في هيكل الشجري أدناه', - translate: 'ترجمة', - trash: 'سلة المهملات', - unlock: 'فتح القفل', - unpublish: 'إلغاء النشر', - update: 'تحديث', - wasCopiedTo: 'تم نسخه إلى', - wasDeleted: 'تم حذفه', - wasMovedTo: 'تم نقله إلى', - }, - actionCategories: { - content: 'المحتوى', - administration: 'الإدارة', - structure: 'الهيكل', - other: 'أخرى', - }, - actionDescriptions: { - assignDomain: 'السماح بالوصول لتعيين الثقافة وأسماء النطاقات', - auditTrail: 'السماح بالوصول لعرض سجل تاريخ العقدة', - browse: 'السماح بالوصول لعرض العقدة', - changeDocType: 'السماح بالوصول لتغيير نوع وثيقة للعقدة', - copy: 'السماح بالوصول لنسخ العقدة', - create: 'السماح بالوصول لإنشاء العقد', - delete: 'السماح بالوصول لحذف العقد', - move: 'السماح بالوصول لنقل العقدة', - protect: 'السماح بالوصول لتعيين وتغيير قيود الوصول للعقدة', - publish: 'السماح بالوصول لنشر العقدة', - unpublish: 'السماح بالوصول لإلغاء نشر العقدة', - rights: 'السماح بالوصول لتغيير الأذونات للعقدة', - rollback: 'السماح بالوصول للتراجع عن العقدة إلى حالة سابقة', - sendtopublish: 'السماح بالوصول لإرسال العقدة للموافقة قبل النشر', - sendToTranslate: 'السماح بالوصول لإرسال العقدة للترجمة', - sort: 'السماح بالوصول لتغيير ترتيب العقد', - translate: 'السماح بالوصول لترجمة العقدة', - update: 'السماح بالوصول لحفظ العقدة', - createblueprint: 'السماح بالوصول لإنشاء مخطط الوثيقة', - notify: 'السماح بالوصول لإعداد الإشعارات لعقد المحتوى', - }, - apps: { - umbContent: 'المحتوى', - umbInfo: 'المعلومات', - }, - assignDomain: { - permissionDenied: 'تم رفض الإذن.', - addNew: 'إضافة نطاق جديد', - addCurrent: 'إضافة النطاق الحالي', - remove: 'إزالة', - invalidNode: 'عقدة غير صالحة.', - invalidDomain: 'واحد أو أكثر من النطاقات لها تنسيق غير صالح.', - duplicateDomain: 'تم تعيين النطاق بالفعل.', - language: 'اللغة', - domain: 'النطاق', - domainCreated: "تم إنشاء النطاق الجديد '%0%'", - domainDeleted: "تم حذف النطاق '%0%'", - domainExists: "تم تعيين النطاق '%0%' بالفعل", - domainUpdated: "تم تحديث النطاق '%0%'", - orEdit: 'تحرير النطاقات الحالية', - domainHelpWithVariants: 'أسماء النطاقات الصالحة هي: "example.com"، "www.example.com"، "example.com:8080"، أو "https://www.example.com/".\\n علاوة على ذلك، يتم دعم المسارات ذات المستوى الواحد في النطاقات، مثل "example.com/en" أو "/en".', - inherit: 'وراثة', - setLanguage: 'الثقافة', - setLanguageHelp: 'تعيين الثقافة للعقد أدناه العقدة الحالية،
      أو وراثة الثقافة من العقد الأصلية. سيتم تطبيقها أيضًا
      \\n على العقدة الحالية، ما لم يتم تطبيق نطاق أدناه أيضًا.', - setDomains: 'النطاقات', - }, - buttons: { - clearSelection: 'مسح التحديد', - select: 'تحديد', - somethingElse: 'افعل شيئًا آخر', - bold: 'غامق', - deindent: 'إلغاء الفقرة', - formFieldInsert: 'إدراج حقل النموذج', - graphicHeadline: 'إدراج عنوان رسومي', - htmlEdit: 'تحرير HTML', - indent: 'فقرة', - italic: 'مائل', - justifyCenter: 'توسيط', - justifyLeft: 'محاذاة لليسار', - justifyRight: 'محاذاة لليمين', - linkInsert: 'إدراج رابط', - linkLocal: 'إدراج رابط محلي (مرساة)', - listBullet: 'قائمة نقطية', - listNumeric: 'قائمة رقمية', - macroInsert: 'إدراج ماكرو', - pictureInsert: 'إدراج صورة', - publishAndClose: 'نشر وإغلاق', - publishDescendants: 'نشر مع الفروع', - relations: 'تحرير العلاقات', - returnToList: 'العودة إلى القائمة', - save: 'حفظ', - saveAndClose: 'حفظ وإغلاق', - saveAndPublish: 'حفظ ونشر', - saveToPublish: 'إرسال للموافقة', - saveListView: 'حفظ عرض القائمة', - schedulePublish: 'جدولة', - saveAndPreview: 'حفظ ومعاينة', - showPageDisabled: "تم تعطيل المعاينة لأنه لم يتم تعيين قالب", - styleChoose: 'اختر النمط', - styleShow: 'عرض الأنماط', - tableInsert: 'إدراج جدول', - generateModelsAndClose: 'توليد النماذج وإغلاق', - saveAndGenerateModels: 'حفظ وتوليد النماذج', - undo: 'تراجع', - redo: 'إعادة', - deleteTag: 'حذف العلامة', - confirmActionCancel: 'إلغاء', - confirmActionConfirm: 'تأكيد', - morePublishingOptions: 'خيارات نشر إضافية', - submitChanges: 'إرسال التغييرات', - }, - auditTrails: { - atViewingFor: "عرض ل", - delete: "تم حذف المحتوى", - unpublish: "تم إلغاء نشر المحتوى", - unpublishvariant: "تم إلغاء نشر المحتوى للغات: %0%", - publish: "تم نشر المحتوى", - publishvariant: "تم نشر المحتوى للغات: %0%", - save: "تم حفظ المحتوى", - savevariant: "تم حفظ المحتوى للغات: %0%", - move: "تم نقل المحتوى", - copy: "تم نسخ المحتوى", - rollback: "تم التراجع عن المحتوى", - sendtopublish: "تم إرسال المحتوى للنشر", - sendtopublishvariant: "تم إرسال المحتوى للنشر للغات: %0%", - sort: "ترتيب العناصر الفرعية بواسطة المستخدم", - custom: "%0%", - contentversionpreventcleanup: "إيقاف التنظيف للإصدار: %0%", - contentversionenablecleanup: "تفعيل التنظيف للإصدار: %0%", - smallCopy: "نسخ", - smallPublish: "نشر", - smallPublishVariant: "نشر", - smallMove: "نقل", - smallSave: "حفظ", - smallSaveVariant: "حفظ", - smallDelete: "حذف", - smallUnpublish: "إلغاء نشر", - smallUnpublishVariant: "إلغاء نشر", - smallRollBack: "التراجع", - smallSendToPublish: "إرسال للنشر", - smallSendToPublishVariant: "إرسال للنشر", - smallSort: "ترتيب", - smallCustom: "مخصص", - smallContentVersionPreventCleanup: "حفظ", - smallContentVersionEnableCleanup: "حفظ", - historyIncludingVariants: "التاريخ (جميع النسخ)" - }, - codefile: { - createFolderIllegalChars: "لا يمكن أن يحتوي اسم المجلد على أحرف غير قانونية.", - deleteItemFailed: "فشل في حذف العنصر: %0%" - }, - content: { - isPublished: "تم نشره", - about: "حول هذه الصفحة", - alias: "اللقب", - alternativeTextHelp: "(كيف يمكنك وصف الصورة عبر الهاتف)", - alternativeUrls: "روابط بديلة", - clickToEdit: "انقر لتحرير هذا العنصر", - createBy: "أنشأه", - createByDesc: "المؤلف الأصلي", - updatedBy: "تم التحديث بواسطة", - createDate: "تاريخ الإنشاء", - createDateDesc: "تاريخ/وقت إنشاء هذه الوثيقة", - documentType: "نوع الوثيقة", - editing: "تحرير", - expireDate: "إزالة في", - itemChanged: "تم تغيير هذا العنصر بعد النشر", - itemNotPublished: "هذا العنصر غير منشور", - lastPublished: "تم نشره آخر مرة", - noItemsToShow: "لا توجد عناصر لعرضها", - listViewNoItems: "لا توجد عناصر لعرضها في القائمة.", - listViewNoContent: "لم تتم إضافة عناصر فرعية", - listViewNoMembers: "لم تتم إضافة أعضاء", - mediatype: "نوع الوسائط", - mediaLinks: "رابط إلى عنصر/عناصر الوسائط", - membergroup: "مجموعة الأعضاء", - memberrole: "دور", - membertype: "نوع العضو", - noChanges: "لم يتم إجراء تغييرات", - noDate: "لم يتم اختيار تاريخ", - nodeName: "عنوان الصفحة", - noMediaLink: "لا يحتوي هذا العنصر الإعلامي على رابط", - noProperties: "لا يمكن إضافة محتوى لهذا العنصر", - otherElements: "الخصائص", - parentNotPublished: "هذه الوثيقة منشورة ولكنها غير مرئية لأن الأصل '%0%' غير منشور", - parentCultureNotPublished: "هذه الثقافة منشورة ولكنها غير مرئية لأنها غير منشورة على الأصل '%0%'", - parentNotPublishedAnomaly: "هذه الوثيقة منشورة ولكنها ليست في الذاكرة المؤقتة", - getUrlException: "لم يتمكن من الحصول على عنوان URL", - routeError: "هذه الوثيقة منشورة ولكن عنوان URL الخاص بها يتداخل مع المحتوى %0%", - routeErrorCannotRoute: "هذه الوثيقة منشورة ولكن لا يمكن توجيه عنوان URL الخاص بها", - publish: "نشر", - published: "منشور", - publishedPendingChanges: "منشور (تغييرات معلقة)", - publishStatus: "حالة النشر", - publishDescendantsHelp: "نشر %0% وجميع عناصر المحتوى أسفله وبالتالي جعل محتواها متاحًا للعامة.", - publishDescendantsWithVariantsHelp: "نشر النسخ ونسخ نفس النوع أسفله وبالتالي جعل محتواها متاحًا للعامة.", - noVariantsToProcess: "لا توجد نسخ متاحة", - releaseDate: "نشر في", - unpublishDate: "إلغاء نشر في", - removeDate: "مسح التاريخ", - setDate: "تعيين التاريخ", - sortDone: "تم تحديث ترتيب الفرز", - sortHelp: 'لترتيب العقد، ببساطة اسحب العقد أو انقر على أحد رؤوس الأعمدة. يمكنك تحديد عناصر متعددة عن طريق الضغط على مفتاح "shift" أو "control" أثناء التحديد', - statistics: "الإحصاءات", - titleOptional: "العنوان (اختياري)", - altTextOptional: "نص بديل (اختياري)", - captionTextOptional: "التعليق (اختياري)", - type: "النوع", - unpublish: "إلغاء نشر", - unpublished: "غير منشور", - notCreated: "لم يتم إنشاؤه", - updateDate: "آخر تعديل", - updateDateDesc: "تاريخ/وقت تعديل هذه الوثيقة", - uploadClear: "إزالة الملف/الملفات", - uploadClearImageContext: "انقر هنا لإزالة الصورة من عنصر الوسائط", - uploadClearFileContext: "انقر هنا لإزالة الملف من عنصر الوسائط", - urls: "رابط إلى الوثيقة", - memberof: "عضو في المجموعة(s)", - notmemberof: "ليس عضوًا في المجموعة(s)", - childItems: "العناصر الفرعية", - target: "الهدف", - scheduledPublishServerTime: "يترجم هذا إلى الوقت التالي على الخادم:", - scheduledPublishDocumentation: "ماذا يعني هذا؟", - nestedContentDeleteItem: "هل أنت متأكد أنك تريد حذف هذا العنصر؟", - nestedContentDeleteAllItems: "هل أنت متأكد أنك تريد حذف جميع العناصر؟", - nestedContentEditorNotSupported: "الخاصية %0% تستخدم محرر %1% والذي لا يدعمه المحتوى المتداخل.", - nestedContentNoContentTypes: "لم يتم تكوين أنواع المحتوى لهذه الخاصية.", - nestedContentAddElementType: "إضافة نوع عنصر", - nestedContentSelectElementTypeModalTitle: "اختر نوع العنصر", - nestedContentGroupHelpText: "حدد المجموعة التي يجب عرض خصائصها. إذا تركت فارغة، ستستخدم المجموعة الأولى على نوع العنصر.", - nestedContentTemplateHelpTextPart1: "أدخل تعبير Angular لتقييمه لكل عنصر للحصول على اسمه. استخدم", - nestedContentTemplateHelpTextPart2: "لعرض مؤشر العنصر", - nestedContentNoGroups: "نوع العنصر المحدد لا يحتوي على أي مجموعات مدعومة (التبويبات غير مدعومة بواسطة هذا المحرر، إما قم بتغييرها إلى مجموعات أو استخدم محرر قائمة الكتل).", - addTextBox: "إضافة مربع نص آخر", - removeTextBox: "إزالة هذا مربع النص", - contentRoot: "جذر المحتوى", - includeUnpublished: "تضمين عناصر المحتوى غير المنشورة.", - isSensitiveValue: "هذه القيمة مخفية. إذا كنت بحاجة إلى الوصول لعرض هذه القيمة، يرجى الاتصال بمدير موقعك.", - isSensitiveValue_short: "هذه القيمة مخفية.", - languagesToPublish: "ما اللغات التي ترغب في نشرها؟", - languagesToSendForApproval: "ما اللغات التي ترغب في إرسالها للموافقة؟", - languagesToSchedule: "ما اللغات التي ترغب في جدولتها؟", - languagesToUnpublish: "حدد اللغات التي ترغب في إلغاء نشرها. إلغاء نشر لغة إلزامية سيؤدي إلى إلغاء نشر جميع اللغات.", - variantsWillBeSaved: "جميع النسخ الجديدة سيتم حفظها.", - variantsToPublish: "أي النسخ ترغب في نشرها؟", - variantsToSave: "اختر النسخ التي سيتم حفظها.", - publishRequiresVariants: "النسخ التالية مطلوبة لعملية النشر:", - notReadyToPublish: "لسنا جاهزين للنشر", - readyToPublish: "جاهز للنشر؟", - readyToSave: "جاهز للحفظ؟", - resetFocalPoint: "إعادة تعيين نقطة التركيز", - sendForApproval: "إرسال للموافقة", - schedulePublishHelp: "حدد التاريخ والوقت للنشر و/أو إلغاء نشر عنصر المحتوى.", - createEmpty: "إنشاء جديد", - createFromClipboard: "الصق من الحافظة", - nodeIsInTrash: "هذا العنصر في سلة المهملات", - variantSaveNotAllowed: "الحفظ غير مسموح به", - variantPublishNotAllowed: "النشر غير مسموح به", - variantSendForApprovalNotAllowed: "إرسال للموافقة غير مسموح به", - variantScheduleNotAllowed: "الجدولة غير مسموح بها", - variantUnpublishNotAllowed: "إلغاء النشر غير مسموح به" - }, - blueprints: { - createBlueprintFrom: "إنشاء نموذج وثيقة جديد من '%0%'", - createBlueprintItemUnder: "إنشاء عنصر جديد تحت '%0%'", - createBlueprintFolderUnder: "إنشاء مجلد جديد تحت '%0%'", - blankBlueprint: "فارغ", - selectBlueprint: "حدد نموذج وثيقة", - createdBlueprintHeading: "تم إنشاء نموذج الوثيقة", - createdBlueprintMessage: "تم إنشاء نموذج وثيقة من '%0%'", - duplicateBlueprintMessage: "يوجد نموذج وثيقة آخر بنفس الاسم بالفعل", - blueprintDescription: "نموذج الوثيقة هو محتوى محدد مسبقًا يمكن للمحرر تحديده لاستخدامه كأساس لإنشاء محتوى جديد" - }, - media: { - clickToUpload: "انقر لتحميل", - orClickHereToUpload: "أو انقر هنا لاختيار الملفات", - disallowedFileType: "لا يمكن تحميل هذا الملف، فهو لا يحتوي على نوع ملف معتمد", - disallowedMediaType: "لا يمكن تحميل هذا الملف، نوع الوسائط باللقب '%0%' غير مسموح به هنا", - invalidFileName: "لا يمكن تحميل هذا الملف، فهو لا يحتوي على اسم ملف صحيح", - maxFileSize: "أقصى حجم للملف هو", - mediaRoot: "جذر الوسائط", - moveToSameFolderFailed: "لا يمكن أن تكون المجلدات الأصلية والوجهة هي نفسها", - createFolderFailed: "فشل في إنشاء مجلد تحت المعرف %0%", - renameFolderFailed: "فشل في إعادة تسمية المجلد بالمعرف %0%", - dragAndDropYourFilesIntoTheArea: "اسحب وأفلت ملفاتك في المنطقة", - uploadNotAllowed: "التحميل غير مسموح به في هذا الموقع" - }, - member: { - createNewMember: "إنشاء عضو جديد", - allMembers: "جميع الأعضاء", - duplicateMemberLogin: "يوجد عضو بهذا تسجيل الدخول بالفعل", - memberGroupNoProperties: "مجموعات الأعضاء لا تحتوي على خصائص إضافية للتعديل.", - memberHasGroup: "العضو بالفعل في المجموعة '%0%'", - memberHasPassword: "العضو لديه كلمة مرور محددة بالفعل", - memberLockoutNotEnabled: "التحقق من القفل غير مفعل لهذا العضو", - memberNotInGroup: "العضو ليس في المجموعة '%0%'", - '2fa': "التحقق بخطوتين" - }, - contentType: { - copyFailed: "فشل في نسخ نوع المحتوى", - moveFailed: "فشل في نقل نوع المحتوى" - }, - mediaType: { - copyFailed: "فشل في نسخ نوع الوسائط", - moveFailed: "فشل في نقل نوع الوسائط", - autoPickMediaType: "اختيار تلقائي" - }, - memberType: { - copyFailed: "فشل في نسخ نوع العضو" - }, + actions: { + assigndomain: 'الثقافة وأسماء النطاقات', + auditTrail: 'سجل التدقيق', + browse: 'تصفح ', + changeDataType: 'تغيير نوع البيانات', + changeDocType: 'تغيير نوع الوثيقة', + chooseWhereToCopy: 'اختر مكان النسخ', + chooseWhereToImport: 'اختر مكان الاستيراد', + chooseWhereToMove: 'اختر مكان النقل', + copy: 'نسخ', + copyTo: 'نسخ إلى', + create: 'إنشاء', + createblueprint: 'إنشاء مخطط انشائي للمستند', + createGroup: 'إنشاء مجموعة', + createPackage: 'إنشاء حزمة', + delete: 'حذف', + disable: 'تعطيل', + editContent: 'تحرير المحتوى', + editSettings: 'تحرير الإعدادات', + emptyrecyclebin: 'إفراغ سلة المحذوفات', + enable: 'تمكين', + export: 'تصدير', + exportDocumentType: 'تصدير نوع الوثيقة', + folderCreate: 'إنشاء مجلد', + folderDelete: 'حذف مجلد', + folderRename: 'إعادة تسمية مجلد', + import: 'استيراد', + importdocumenttype: 'استيراد نوع وثيقة', + importPackage: 'استيراد حزمة', + infiniteEditorChooseWhereToCopy: 'اختر مكان نسخ العنصر (العناصر) المحددة', + infiniteEditorChooseWhereToMove: 'اختر مكان نقل العنصر (العناصر) المحددة', + liveEdit: 'تحرير مباشر', + logout: 'تسجيل خروج', + move: 'نقل إلى', + notify: 'الإشعارات', + protect: 'الوصول العام', + publish: 'نشر', + refreshNode: 'إعادة تحميل', + remove: 'إزالة', + rename: 'إعادة تسمية', + republish: 'إعادة نشر الموقع بالكامل', + resendInvite: 'إعادة إرسال الدعوة', + restore: 'استعادة', + rights: 'الأذونات', + rollback: 'التراجع', + sendtopublish: 'إرسال للنشر', + sendToTranslate: 'إرسال للترجمة', + setGroup: 'تعيين مجموعة', + setPermissions: 'تعيين الأذونات', + sort: 'ترتيب الابناء', + toInTheTreeStructureBelow: 'في هيكل الشجري أدناه', + translate: 'ترجمة', + trash: 'سلة المهملات', + unlock: 'فتح القفل', + unpublish: 'إلغاء النشر', + update: 'تحديث', + wasCopiedTo: 'تم نسخه إلى', + wasDeleted: 'تم حذفه', + wasMovedTo: 'تم نقله إلى', + }, + actionCategories: { + content: 'المحتوى', + administration: 'الإدارة', + structure: 'الهيكل', + other: 'أخرى', + }, + actionDescriptions: { + assignDomain: 'السماح بالوصول لتعيين الثقافة وأسماء النطاقات', + auditTrail: 'السماح بالوصول لعرض سجل تاريخ العقدة', + browse: 'السماح بالوصول لعرض العقدة', + changeDocType: 'السماح بالوصول لتغيير نوع وثيقة للعقدة', + copy: 'السماح بالوصول لنسخ العقدة', + create: 'السماح بالوصول لإنشاء العقد', + delete: 'السماح بالوصول لحذف العقد', + move: 'السماح بالوصول لنقل العقدة', + protect: 'السماح بالوصول لتعيين وتغيير قيود الوصول للعقدة', + publish: 'السماح بالوصول لنشر العقدة', + unpublish: 'السماح بالوصول لإلغاء نشر العقدة', + rights: 'السماح بالوصول لتغيير الأذونات للعقدة', + rollback: 'السماح بالوصول للتراجع عن العقدة إلى حالة سابقة', + sendtopublish: 'السماح بالوصول لإرسال العقدة للموافقة قبل النشر', + sendToTranslate: 'السماح بالوصول لإرسال العقدة للترجمة', + sort: 'السماح بالوصول لتغيير ترتيب العقد', + translate: 'السماح بالوصول لترجمة العقدة', + update: 'السماح بالوصول لحفظ العقدة', + createblueprint: 'السماح بالوصول لإنشاء مخطط الوثيقة', + notify: 'السماح بالوصول لإعداد الإشعارات لعقد المحتوى', + }, + apps: { + umbContent: 'المحتوى', + umbInfo: 'المعلومات', + }, + assignDomain: { + permissionDenied: 'تم رفض الإذن.', + addNew: 'إضافة نطاق جديد', + addCurrent: 'إضافة النطاق الحالي', + remove: 'إزالة', + invalidNode: 'عقدة غير صالحة.', + invalidDomain: 'واحد أو أكثر من النطاقات لها تنسيق غير صالح.', + duplicateDomain: 'تم تعيين النطاق بالفعل.', + language: 'اللغة', + domain: 'النطاق', + domainCreated: "تم إنشاء النطاق الجديد '%0%'", + domainDeleted: "تم حذف النطاق '%0%'", + domainExists: "تم تعيين النطاق '%0%' بالفعل", + domainUpdated: "تم تحديث النطاق '%0%'", + orEdit: 'تحرير النطاقات الحالية', + domainHelpWithVariants: + 'أسماء النطاقات الصالحة هي: "example.com"، "www.example.com"، "example.com:8080"، أو "https://www.example.com/".\\n علاوة على ذلك، يتم دعم المسارات ذات المستوى الواحد في النطاقات، مثل "example.com/en" أو "/en".', + inherit: 'وراثة', + setLanguage: 'الثقافة', + setLanguageHelp: + 'تعيين الثقافة للعقد أدناه العقدة الحالية،
      أو وراثة الثقافة من العقد الأصلية. سيتم تطبيقها أيضًا
      \\n على العقدة الحالية، ما لم يتم تطبيق نطاق أدناه أيضًا.', + setDomains: 'النطاقات', + }, + buttons: { + clearSelection: 'مسح التحديد', + select: 'تحديد', + somethingElse: 'افعل شيئًا آخر', + bold: 'غامق', + deindent: 'إلغاء الفقرة', + formFieldInsert: 'إدراج حقل النموذج', + graphicHeadline: 'إدراج عنوان رسومي', + htmlEdit: 'تحرير HTML', + indent: 'فقرة', + italic: 'مائل', + justifyCenter: 'توسيط', + justifyLeft: 'محاذاة لليسار', + justifyRight: 'محاذاة لليمين', + linkInsert: 'إدراج رابط', + linkLocal: 'إدراج رابط محلي (مرساة)', + listBullet: 'قائمة نقطية', + listNumeric: 'قائمة رقمية', + macroInsert: 'إدراج ماكرو', + pictureInsert: 'إدراج صورة', + publishAndClose: 'نشر وإغلاق', + publishDescendants: 'نشر مع الفروع', + relations: 'تحرير العلاقات', + returnToList: 'العودة إلى القائمة', + save: 'حفظ', + saveAndClose: 'حفظ وإغلاق', + saveAndPublish: 'حفظ ونشر', + saveToPublish: 'إرسال للموافقة', + saveListView: 'حفظ عرض القائمة', + schedulePublish: 'جدولة', + saveAndPreview: 'حفظ ومعاينة', + showPageDisabled: 'تم تعطيل المعاينة لأنه لم يتم تعيين قالب', + styleChoose: 'اختر النمط', + styleShow: 'عرض الأنماط', + tableInsert: 'إدراج جدول', + generateModelsAndClose: 'توليد النماذج وإغلاق', + saveAndGenerateModels: 'حفظ وتوليد النماذج', + undo: 'تراجع', + redo: 'إعادة', + deleteTag: 'حذف العلامة', + confirmActionCancel: 'إلغاء', + confirmActionConfirm: 'تأكيد', + morePublishingOptions: 'خيارات نشر إضافية', + submitChanges: 'إرسال التغييرات', + }, + auditTrails: { + atViewingFor: 'عرض ل', + delete: 'تم حذف المحتوى', + unpublish: 'تم إلغاء نشر المحتوى', + unpublishvariant: 'تم إلغاء نشر المحتوى للغات: %0%', + publish: 'تم نشر المحتوى', + publishvariant: 'تم نشر المحتوى للغات: %0%', + save: 'تم حفظ المحتوى', + savevariant: 'تم حفظ المحتوى للغات: %0%', + move: 'تم نقل المحتوى', + copy: 'تم نسخ المحتوى', + rollback: 'تم التراجع عن المحتوى', + sendtopublish: 'تم إرسال المحتوى للنشر', + sendtopublishvariant: 'تم إرسال المحتوى للنشر للغات: %0%', + sort: 'ترتيب العناصر الفرعية بواسطة المستخدم', + custom: '%0%', + contentversionpreventcleanup: 'إيقاف التنظيف للإصدار: %0%', + contentversionenablecleanup: 'تفعيل التنظيف للإصدار: %0%', + smallCopy: 'نسخ', + smallPublish: 'نشر', + smallPublishVariant: 'نشر', + smallMove: 'نقل', + smallSave: 'حفظ', + smallSaveVariant: 'حفظ', + smallDelete: 'حذف', + smallUnpublish: 'إلغاء نشر', + smallUnpublishVariant: 'إلغاء نشر', + smallRollBack: 'التراجع', + smallSendToPublish: 'إرسال للنشر', + smallSendToPublishVariant: 'إرسال للنشر', + smallSort: 'ترتيب', + smallCustom: 'مخصص', + smallContentVersionPreventCleanup: 'حفظ', + smallContentVersionEnableCleanup: 'حفظ', + historyIncludingVariants: 'التاريخ (جميع النسخ)', + }, + codefile: { + createFolderIllegalChars: 'لا يمكن أن يحتوي اسم المجلد على أحرف غير قانونية.', + deleteItemFailed: 'فشل في حذف العنصر: %0%', + }, + content: { + isPublished: 'تم نشره', + about: 'حول هذه الصفحة', + alias: 'اللقب', + alternativeTextHelp: '(كيف يمكنك وصف الصورة عبر الهاتف)', + alternativeUrls: 'روابط بديلة', + clickToEdit: 'انقر لتحرير هذا العنصر', + createBy: 'أنشأه', + createByDesc: 'المؤلف الأصلي', + updatedBy: 'تم التحديث بواسطة', + createDate: 'تاريخ الإنشاء', + createDateDesc: 'تاريخ/وقت إنشاء هذه الوثيقة', + documentType: 'نوع الوثيقة', + editing: 'تحرير', + expireDate: 'إزالة في', + itemChanged: 'تم تغيير هذا العنصر بعد النشر', + itemNotPublished: 'هذا العنصر غير منشور', + lastPublished: 'تم نشره آخر مرة', + noItemsToShow: 'لا توجد عناصر لعرضها', + listViewNoItems: 'لا توجد عناصر لعرضها في القائمة.', + listViewNoContent: 'لم تتم إضافة عناصر فرعية', + listViewNoMembers: 'لم تتم إضافة أعضاء', + mediatype: 'نوع الوسائط', + mediaLinks: 'رابط إلى عنصر/عناصر الوسائط', + membergroup: 'مجموعة الأعضاء', + memberrole: 'دور', + membertype: 'نوع العضو', + noChanges: 'لم يتم إجراء تغييرات', + noDate: 'لم يتم اختيار تاريخ', + nodeName: 'عنوان الصفحة', + noMediaLink: 'لا يحتوي هذا العنصر الإعلامي على رابط', + noProperties: 'لا يمكن إضافة محتوى لهذا العنصر', + otherElements: 'الخصائص', + parentNotPublished: "هذه الوثيقة منشورة ولكنها غير مرئية لأن الأصل '%0%' غير منشور", + parentCultureNotPublished: "هذه الثقافة منشورة ولكنها غير مرئية لأنها غير منشورة على الأصل '%0%'", + parentNotPublishedAnomaly: 'هذه الوثيقة منشورة ولكنها ليست في الذاكرة المؤقتة', + getUrlException: 'لم يتمكن من الحصول على عنوان URL', + routeError: 'هذه الوثيقة منشورة ولكن عنوان URL الخاص بها يتداخل مع المحتوى %0%', + routeErrorCannotRoute: 'هذه الوثيقة منشورة ولكن لا يمكن توجيه عنوان URL الخاص بها', + publish: 'نشر', + published: 'منشور', + publishedPendingChanges: 'منشور (تغييرات معلقة)', + publishStatus: 'حالة النشر', + publishDescendantsHelp: 'نشر %0% وجميع عناصر المحتوى أسفله وبالتالي جعل محتواها متاحًا للعامة.', + publishDescendantsWithVariantsHelp: 'نشر النسخ ونسخ نفس النوع أسفله وبالتالي جعل محتواها متاحًا للعامة.', + noVariantsToProcess: 'لا توجد نسخ متاحة', + releaseDate: 'نشر في', + unpublishDate: 'إلغاء نشر في', + removeDate: 'مسح التاريخ', + setDate: 'تعيين التاريخ', + sortDone: 'تم تحديث ترتيب الفرز', + sortHelp: + 'لترتيب العقد، ببساطة اسحب العقد أو انقر على أحد رؤوس الأعمدة. يمكنك تحديد عناصر متعددة عن طريق الضغط على مفتاح "shift" أو "control" أثناء التحديد', + statistics: 'الإحصاءات', + titleOptional: 'العنوان (اختياري)', + altTextOptional: 'نص بديل (اختياري)', + captionTextOptional: 'التعليق (اختياري)', + type: 'النوع', + unpublish: 'إلغاء نشر', + unpublished: 'غير منشور', + notCreated: 'لم يتم إنشاؤه', + updateDate: 'آخر تعديل', + updateDateDesc: 'تاريخ/وقت تعديل هذه الوثيقة', + uploadClear: 'إزالة الملف/الملفات', + uploadClearImageContext: 'انقر هنا لإزالة الصورة من عنصر الوسائط', + uploadClearFileContext: 'انقر هنا لإزالة الملف من عنصر الوسائط', + urls: 'رابط إلى الوثيقة', + memberof: 'عضو في المجموعة(s)', + notmemberof: 'ليس عضوًا في المجموعة(s)', + childItems: 'العناصر الفرعية', + target: 'الهدف', + scheduledPublishServerTime: 'يترجم هذا إلى الوقت التالي على الخادم:', + scheduledPublishDocumentation: + 'ماذا يعني هذا؟', + nestedContentDeleteItem: 'هل أنت متأكد أنك تريد حذف هذا العنصر؟', + nestedContentDeleteAllItems: 'هل أنت متأكد أنك تريد حذف جميع العناصر؟', + nestedContentEditorNotSupported: 'الخاصية %0% تستخدم محرر %1% والذي لا يدعمه المحتوى المتداخل.', + nestedContentNoContentTypes: 'لم يتم تكوين أنواع المحتوى لهذه الخاصية.', + nestedContentAddElementType: 'إضافة نوع عنصر', + nestedContentSelectElementTypeModalTitle: 'اختر نوع العنصر', + nestedContentGroupHelpText: + 'حدد المجموعة التي يجب عرض خصائصها. إذا تركت فارغة، ستستخدم المجموعة الأولى على نوع العنصر.', + nestedContentTemplateHelpTextPart1: 'أدخل تعبير Angular لتقييمه لكل عنصر للحصول على اسمه. استخدم', + nestedContentTemplateHelpTextPart2: 'لعرض مؤشر العنصر', + nestedContentNoGroups: + 'نوع العنصر المحدد لا يحتوي على أي مجموعات مدعومة (التبويبات غير مدعومة بواسطة هذا المحرر، إما قم بتغييرها إلى مجموعات أو استخدم محرر قائمة الكتل).', + addTextBox: 'إضافة مربع نص آخر', + removeTextBox: 'إزالة هذا مربع النص', + contentRoot: 'جذر المحتوى', + includeUnpublished: 'تضمين عناصر المحتوى غير المنشورة.', + isSensitiveValue: 'هذه القيمة مخفية. إذا كنت بحاجة إلى الوصول لعرض هذه القيمة، يرجى الاتصال بمدير موقعك.', + isSensitiveValue_short: 'هذه القيمة مخفية.', + languagesToPublish: 'ما اللغات التي ترغب في نشرها؟', + languagesToSendForApproval: 'ما اللغات التي ترغب في إرسالها للموافقة؟', + languagesToSchedule: 'ما اللغات التي ترغب في جدولتها؟', + languagesToUnpublish: 'حدد اللغات التي ترغب في إلغاء نشرها. إلغاء نشر لغة إلزامية سيؤدي إلى إلغاء نشر جميع اللغات.', + variantsWillBeSaved: 'جميع النسخ الجديدة سيتم حفظها.', + variantsToPublish: 'أي النسخ ترغب في نشرها؟', + variantsToSave: 'اختر النسخ التي سيتم حفظها.', + publishRequiresVariants: 'النسخ التالية مطلوبة لعملية النشر:', + notReadyToPublish: 'لسنا جاهزين للنشر', + readyToPublish: 'جاهز للنشر؟', + readyToSave: 'جاهز للحفظ؟', + resetFocalPoint: 'إعادة تعيين نقطة التركيز', + sendForApproval: 'إرسال للموافقة', + schedulePublishHelp: 'حدد التاريخ والوقت للنشر و/أو إلغاء نشر عنصر المحتوى.', + createEmpty: 'إنشاء جديد', + createFromClipboard: 'الصق من الحافظة', + nodeIsInTrash: 'هذا العنصر في سلة المهملات', + variantSaveNotAllowed: 'الحفظ غير مسموح به', + variantPublishNotAllowed: 'النشر غير مسموح به', + variantSendForApprovalNotAllowed: 'إرسال للموافقة غير مسموح به', + variantScheduleNotAllowed: 'الجدولة غير مسموح بها', + variantUnpublishNotAllowed: 'إلغاء النشر غير مسموح به', + }, + blueprints: { + createBlueprintFrom: "إنشاء نموذج وثيقة جديد من '%0%'", + createBlueprintItemUnder: "إنشاء عنصر جديد تحت '%0%'", + createBlueprintFolderUnder: "إنشاء مجلد جديد تحت '%0%'", + blankBlueprint: 'فارغ', + selectBlueprint: 'حدد نموذج وثيقة', + createdBlueprintHeading: 'تم إنشاء نموذج الوثيقة', + createdBlueprintMessage: "تم إنشاء نموذج وثيقة من '%0%'", + duplicateBlueprintMessage: 'يوجد نموذج وثيقة آخر بنفس الاسم بالفعل', + blueprintDescription: 'نموذج الوثيقة هو محتوى محدد مسبقًا يمكن للمحرر تحديده لاستخدامه كأساس لإنشاء محتوى جديد', + }, + media: { + clickToUpload: 'انقر لتحميل', + orClickHereToUpload: 'أو انقر هنا لاختيار الملفات', + disallowedFileType: 'لا يمكن تحميل هذا الملف، فهو لا يحتوي على نوع ملف معتمد', + disallowedMediaType: "لا يمكن تحميل هذا الملف، نوع الوسائط باللقب '%0%' غير مسموح به هنا", + invalidFileName: 'لا يمكن تحميل هذا الملف، فهو لا يحتوي على اسم ملف صحيح', + maxFileSize: 'أقصى حجم للملف هو', + mediaRoot: 'جذر الوسائط', + moveToSameFolderFailed: 'لا يمكن أن تكون المجلدات الأصلية والوجهة هي نفسها', + createFolderFailed: 'فشل في إنشاء مجلد تحت المعرف %0%', + renameFolderFailed: 'فشل في إعادة تسمية المجلد بالمعرف %0%', + dragAndDropYourFilesIntoTheArea: 'اسحب وأفلت ملفاتك في المنطقة', + uploadNotAllowed: 'التحميل غير مسموح به في هذا الموقع', + }, + member: { + createNewMember: 'إنشاء عضو جديد', + allMembers: 'جميع الأعضاء', + duplicateMemberLogin: 'يوجد عضو بهذا تسجيل الدخول بالفعل', + memberGroupNoProperties: 'مجموعات الأعضاء لا تحتوي على خصائص إضافية للتعديل.', + memberHasGroup: "العضو بالفعل في المجموعة '%0%'", + memberHasPassword: 'العضو لديه كلمة مرور محددة بالفعل', + memberLockoutNotEnabled: 'التحقق من القفل غير مفعل لهذا العضو', + memberNotInGroup: "العضو ليس في المجموعة '%0%'", + '2fa': 'التحقق بخطوتين', + }, + contentType: { + copyFailed: 'فشل في نسخ نوع المحتوى', + moveFailed: 'فشل في نقل نوع المحتوى', + }, + mediaType: { + copyFailed: 'فشل في نسخ نوع الوسائط', + moveFailed: 'فشل في نقل نوع الوسائط', + autoPickMediaType: 'اختيار تلقائي', + }, + memberType: { + copyFailed: 'فشل في نسخ نوع العضو', + }, create: { - chooseNode: "أين تريد إنشاء %0% الجديد", - createUnder: "إنشاء عنصر تحت", - createContentBlueprint: "حدد نوع الوثيقة الذي تريد إنشاء نموذج وثيقة له", - enterFolderName: "أدخل اسم المجلد", - updateData: "اختر نوعًا وعنوانًا", - noDocumentTypes: "لا توجد أنواع وثائق مسموح بها متاحة لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.", - noDocumentTypesAtRoot: "لا توجد أنواع وثائق متاحة لإنشاء المحتوى هنا. يجب عليك إنشاء هذه الأنواع في أنواع الوثائق ضمن قسم الإعدادات.", - noDocumentTypesWithNoSettingsAccess: "الصفحة المحددة في شجرة المحتوى لا تسمح بإنشاء أي صفحات أسفلها.", - noDocumentTypesEditPermissions: "تعديل الأذونات لهذا النوع من الوثائق", - noDocumentTypesCreateNew: "إنشاء نوع وثيقة جديد", - noDocumentTypesAllowedAtRoot: "لا توجد أنواع وثائق مسموح بها لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تغيير خيار السماح كجذر ضمن الأذونات.", - noMediaTypes: "لا توجد أنواع وسائط مسموح بها لإنشاء الوسائط هنا. يجب تمكينها في أنواع الوسائط ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.", - noMediaTypesWithNoSettingsAccess: "الوسائط المحددة في الشجرة لا تسمح بإنشاء أي وسائط أخرى أسفلها.", - noMediaTypesEditPermissions: "تعديل الأذونات لهذا النوع من الوسائط", - documentTypeWithoutTemplate: "نوع الوثيقة بدون قالب", - documentTypeWithTemplate: "نوع الوثيقة مع قالب", - documentTypeWithTemplateDescription: "تعريف البيانات لصفحة محتوى يمكن إنشاؤها من قبل المحررين في شجرة المحتوى ويمكن الوصول إليها مباشرة عبر URL.", - documentType: "نوع الوثيقة", - documentTypeDescription: "تعريف البيانات لمكون محتوى يمكن إنشاؤه من قبل المحررين في شجرة المحتوى ويمكن اختياره في صفحات أخرى ولكنه لا يحتوي على URL مباشر.", - elementType: "نوع العنصر", - elementTypeDescription: "يحدد المخطط لمجموعة متكررة من الخصائص، على سبيل المثال، في محرر 'قائمة الكتل' أو 'شبكة الكتل'.", - composition: "تركيب", - compositionDescription: "يحدد مجموعة قابلة لإعادة الاستخدام من الخصائص يمكن تضمينها في تعريف أنواع وثائق متعددة. على سبيل المثال، مجموعة من 'إعدادات الصفحة المشتركة'.", - folder: "مجلد", - folderDescription: "يستخدم لتنظيم أنواع الوثائق، والتركيبات، وأنواع العناصر التي تم إنشاؤها في شجرة نوع الوثيقة هذه.", - newFolder: "مجلد جديد", - newDataType: "نوع بيانات جديد", - newJavascriptFile: "ملف JavaScript جديد", - newEmptyPartialView: "عرض جزئي فارغ جديد", - newPartialViewMacro: "ماكرو عرض جزئي جديد", - newPartialViewFromSnippet: "عرض جزئي جديد من مقطع", - newPartialViewMacroFromSnippet: "ماكرو عرض جزئي جديد من مقطع", - newPartialViewMacroNoMacro: "ماكرو عرض جزئي جديد (بدون ماكرو)", - newStyleSheetFile: "ملف ورقة أنماط جديد", - newRteStyleSheetFile: "ملف ورقة أنماط محرر النصوص الغني الجديد" - }, - dashboard: { - browser: "تصفح موقعك", - dontShowAgain: "- إخفاء", - nothinghappens: "إذا لم يفتح Umbraco، قد تحتاج إلى السماح بالنوافذ المنبثقة من هذا الموقع", - openinnew: "تم فتحه في نافذة جديدة", - restart: "إعادة تشغيل", - visit: "زيارة", - welcome: "مرحبا" - }, - prompt: { - stay: "ابق", - discardChanges: "تجاهل التغييرات", - unsavedChanges: "لديك تغييرات غير محفوظة", - unsavedChangesWarning: "هل أنت متأكد أنك تريد الانتقال بعيدًا عن هذه الصفحة؟ - لديك تغييرات غير محفوظة", - confirmListViewPublish: "النشر سيجعل العناصر المحددة مرئية على الموقع.", - confirmListViewUnpublish: "إلغاء النشر سيزيل العناصر المحددة وجميع نسلها من الموقع.", - confirmUnpublish: "إلغاء النشر سيزيل هذه الصفحة وجميع نسلها من الموقع.", - doctypeChangeWarning: "لديك تغييرات غير محفوظة. إجراء تغييرات على نوع الوثيقة سيتسبب في تجاهل التغييرات." - }, - bulk: { - done: "تم", - deletedItem: "تم حذف %0% عنصر", - deletedItems: "تم حذف %0% عناصر", - deletedItemOfItem: "تم حذف %0% من %1% عنصر", - deletedItemOfItems: "تم حذف %0% من %1% عناصر", - publishedItem: "تم نشر %0% عنصر", - publishedItems: "تم نشر %0% عناصر", - publishedItemOfItem: "تم نشر %0% من %1% عنصر", - publishedItemOfItems: "تم نشر %0% من %1% عناصر", - unpublishedItem: "تم إلغاء نشر %0% عنصر", - unpublishedItems: "تم إلغاء نشر %0% عناصر", - unpublishedItemOfItem: "تم إلغاء نشر %0% من %1% عنصر", - unpublishedItemOfItems: "تم إلغاء نشر %0% من %1% عناصر", - movedItem: "تم نقل %0% عنصر", - movedItems: "تم نقل %0% عناصر", - movedItemOfItem: "تم نقل %0% من %1% عنصر", - movedItemOfItems: "تم نقل %0% من %1% عناصر", - copiedItem: "تم نسخ %0% عنصر", - copiedItems: "تم نسخ %0% عناصر", - copiedItemOfItem: "تم نسخ %0% من %1% عنصر", - copiedItemOfItems: "تم نسخ %0% من %1% عناصر" - }, - defaultdialogs: { - nodeNameLinkPicker: "عنوان الرابط", - urlLinkPicker: "الرابط", - anchorLinkPicker: "مرساة / سلسلة استعلام", - anchorInsert: "اسم", - closeThisWindow: "أغلق هذه النافذة", - confirmdelete: "هل أنت متأكد أنك تريد الحذف", - confirmdeleteNumberOfItems: "هل أنت متأكد أنك تريد حذف %0% من %1% العناصر", - confirmdisable: "هل أنت متأكد أنك تريد التعطيل", - confirmremove: "هل أنت متأكد أنك تريد الإزالة", - confirmremoveusageof: "هل أنت متأكد أنك تريد إزالة استخدام %0%", - confirmlogout: "هل أنت متأكد؟", - confirmSure: "هل أنت متأكد؟", - cut: "قص", - editDictionary: "تحرير عنصر القاموس", - editLanguage: "تحرير اللغة", - editSelectedMedia: "تحرير الوسائط المحددة", - insertAnchor: "إدراج رابط محلي", - insertCharacter: "إدراج حرف", - insertgraphicheadline: "إدراج عنوان رسومي", - insertimage: "إدراج صورة", - insertlink: "إدراج رابط", - insertMacro: "انقر لإضافة ماكرو", - inserttable: "إدراج جدول", - languagedeletewarning: "سيؤدي هذا إلى حذف اللغة", - languageChangeWarning: "قد يكون تغيير الثقافة للغة عملية مكلفة وستؤدي إلى إعادة بناء ذاكرة التخزين المؤقت للمحتوى والفهارس", - lastEdited: "آخر تحرير", - link: "رابط", - linkinternal: "رابط داخلي:", - linklocaltip: "عند استخدام الروابط المحلية، أدخل \"#\" أمام الرابط", - linknewwindow: "فتح في نافذة جديدة؟", - macroDoesNotHaveProperties: "هذا الماكرو لا يحتوي على خصائص يمكنك تحريرها", - paste: "لصق", - permissionsEdit: "تحرير الأذونات لـ", - permissionsSet: "تعيين الأذونات لـ", - permissionsSetForGroup: "تعيين الأذونات لـ %0% لمجموعة المستخدمين %1%", - permissionsHelp: "اختر مجموعات المستخدمين التي تريد تعيين الأذونات لها", - recycleBinDeleting: "يتم الآن حذف العناصر في سلة المهملات. يرجى عدم إغلاق هذه النافذة أثناء تنفيذ هذه العملية", - recycleBinIsEmpty: "سلة المهملات فارغة الآن", - recycleBinWarning: "عند حذف العناصر من سلة المهملات، ستختفي إلى الأبد", - regexSearchError: "خدمة الويب الخاصة بـ regexlib.com تواجه حالياً بعض المشاكل، ونحن لا نملك السيطرة على ذلك. نحن آسفون لهذا الإزعاج.", - regexSearchHelp: "ابحث عن تعبير منتظم لإضافته كتحقق لحقل النموذج. مثال: 'بريد إلكتروني،' 'رمز بريدي'، 'عنوان URL'.", - removeMacro: "إزالة الماكرو", - requiredField: "حقل مطلوب", - sitereindexed: "تمت إعادة فهرسة الموقع", - siterepublished: "تم تحديث ذاكرة التخزين المؤقت للموقع. جميع المحتويات المنشورة محدثة الآن، بينما تظل جميع المحتويات غير المنشورة كما هي", - siterepublishHelp: "سيتم تحديث ذاكرة التخزين المؤقت للموقع. سيتم تحديث جميع المحتويات المنشورة، بينما ستظل المحتويات غير المنشورة كما هي.", - tableColumns: "عدد الأعمدة", - tableRows: "عدد الصفوف", - thumbnailimageclickfororiginal: "انقر على الصورة لرؤية الحجم الكامل", - treepicker: "اختيار العنصر", - viewCacheItem: "عرض عنصر ذاكرة التخزين المؤقت", - relateToOriginalLabel: "يرتبط بالأصل", - includeDescendants: "تضمين الأحفاد", - theFriendliestCommunity: "أكثر مجتمع ودود", - linkToPage: "رابط إلى الصفحة", - openInNewWindow: "فتح الوثيقة المرتبطة في نافذة أو علامة تبويب جديدة", - linkToMedia: "رابط إلى الوسائط", - selectContentStartNode: "اختر العقدة الأساسية للمحتوى", - selectMedia: "اختر الوسائط", - selectMediaType: "اختر نوع الوسائط", - selectIcon: "اختر الأيقونة", - selectItem: "اختر العنصر", - selectLink: "اختر الرابط", - selectMacro: "اختر الماكرو", - selectContent: "اختر المحتوى", - selectContentType: "اختر نوع المحتوى", - selectMediaStartNode: "اختر العقدة الأساسية للوسائط", - selectMember: "اختر العضو", - selectMembers: "اختر الأعضاء", - selectMemberGroup: "اختر مجموعة الأعضاء", - selectMemberType: "اختر نوع العضو", - selectNode: "اختر العقدة", - selectLanguages: "اختر اللغات", - selectSections: "اختر الأقسام", - selectUser: "اختر المستخدم", - selectUsers: "اختر المستخدمين", - noIconsFound: "لم يتم العثور على أيقونات", - noMacroParams: "لا توجد معلمات لهذا الماكرو", - noMacros: "لا توجد ماكروات لإدراجها", - externalLoginProviders: "تسجيل الدخول الخارجي", - exceptionDetail: "تفاصيل الاستثناء", - stacktrace: "التتبع الكامل", - innerException: "الاستثناء الداخلي", - linkYour: "ربط حساب {0} الخاص بك", - linkYourConfirm: "أنت على وشك ربط حسابك في Umbraco وحسابك في {0} وسيتم توجيهك إلى {0} للتأكيد.", - unLinkYour: "إلغاء ربط حساب {0} الخاص بك", - unLinkYourConfirm: "أنت على وشك إلغاء ربط حسابك في Umbraco وحسابك في {0} وسيتم تسجيل خروجك.", - linkedToService: "حسابك مرتبط بهذه الخدمة", - selectEditor: "اختر المحرر", - selectEditorConfiguration: "اختر التكوين", - selectSnippet: "اختر الشريحة", - variantdeletewarning: "سيؤدي ذلك إلى حذف العقدة وجميع اللغات المرتبطة بها. إذا كنت ترغب فقط في حذف لغة واحدة، يجب عليك إلغاء نشر العقدة في تلك اللغة بدلاً من ذلك.", - propertyuserpickerremovewarning: "سيتم إزالة المستخدم %0%.", - userremovewarning: "سيتم إزالة المستخدم %0% من المجموعة %1%", - yesRemove: "نعم، أزل", - deleteLayout: "أنت تقوم بحذف التخطيط", - deletingALayout: "سيؤدي تعديل التخطيط إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين." - }, + chooseNode: 'أين تريد إنشاء %0% الجديد', + createUnder: 'إنشاء عنصر تحت', + createContentBlueprint: 'حدد نوع الوثيقة الذي تريد إنشاء نموذج وثيقة له', + enterFolderName: 'أدخل اسم المجلد', + updateData: 'اختر نوعًا وعنوانًا', + noDocumentTypes: + 'لا توجد أنواع وثائق مسموح بها متاحة لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.', + noDocumentTypesAtRoot: + 'لا توجد أنواع وثائق متاحة لإنشاء المحتوى هنا. يجب عليك إنشاء هذه الأنواع في أنواع الوثائق ضمن قسم الإعدادات.', + noDocumentTypesWithNoSettingsAccess: 'الصفحة المحددة في شجرة المحتوى لا تسمح بإنشاء أي صفحات أسفلها.', + noDocumentTypesEditPermissions: 'تعديل الأذونات لهذا النوع من الوثائق', + noDocumentTypesCreateNew: 'إنشاء نوع وثيقة جديد', + noDocumentTypesAllowedAtRoot: + 'لا توجد أنواع وثائق مسموح بها لإنشاء المحتوى هنا. يجب تمكينها في أنواع الوثائق ضمن قسم الإعدادات، عن طريق تغيير خيار السماح كجذر ضمن الأذونات.', + noMediaTypes: + 'لا توجد أنواع وسائط مسموح بها لإنشاء الوسائط هنا. يجب تمكينها في أنواع الوسائط ضمن قسم الإعدادات، عن طريق تعديل أنواع العقد الفرعية المسموح بها ضمن الأذونات.', + noMediaTypesWithNoSettingsAccess: 'الوسائط المحددة في الشجرة لا تسمح بإنشاء أي وسائط أخرى أسفلها.', + noMediaTypesEditPermissions: 'تعديل الأذونات لهذا النوع من الوسائط', + documentTypeWithoutTemplate: 'نوع الوثيقة بدون قالب', + documentTypeWithTemplate: 'نوع الوثيقة مع قالب', + documentTypeWithTemplateDescription: + 'تعريف البيانات لصفحة محتوى يمكن إنشاؤها من قبل المحررين في شجرة المحتوى ويمكن الوصول إليها مباشرة عبر URL.', + documentType: 'نوع الوثيقة', + documentTypeDescription: + 'تعريف البيانات لمكون محتوى يمكن إنشاؤه من قبل المحررين في شجرة المحتوى ويمكن اختياره في صفحات أخرى ولكنه لا يحتوي على URL مباشر.', + elementType: 'نوع العنصر', + elementTypeDescription: + "يحدد المخطط لمجموعة متكررة من الخصائص، على سبيل المثال، في محرر 'قائمة الكتل' أو 'شبكة الكتل'.", + composition: 'تركيب', + compositionDescription: + "يحدد مجموعة قابلة لإعادة الاستخدام من الخصائص يمكن تضمينها في تعريف أنواع وثائق متعددة. على سبيل المثال، مجموعة من 'إعدادات الصفحة المشتركة'.", + folder: 'مجلد', + folderDescription: + 'يستخدم لتنظيم أنواع الوثائق، والتركيبات، وأنواع العناصر التي تم إنشاؤها في شجرة نوع الوثيقة هذه.', + newFolder: 'مجلد جديد', + newDataType: 'نوع بيانات جديد', + newJavascriptFile: 'ملف JavaScript جديد', + newEmptyPartialView: 'عرض جزئي فارغ جديد', + newPartialViewMacro: 'ماكرو عرض جزئي جديد', + newPartialViewFromSnippet: 'عرض جزئي جديد من مقطع', + newPartialViewMacroFromSnippet: 'ماكرو عرض جزئي جديد من مقطع', + newPartialViewMacroNoMacro: 'ماكرو عرض جزئي جديد (بدون ماكرو)', + newStyleSheetFile: 'ملف ورقة أنماط جديد', + newRteStyleSheetFile: 'ملف ورقة أنماط محرر النصوص الغني الجديد', + }, + dashboard: { + browser: 'تصفح موقعك', + dontShowAgain: '- إخفاء', + nothinghappens: 'إذا لم يفتح Umbraco، قد تحتاج إلى السماح بالنوافذ المنبثقة من هذا الموقع', + openinnew: 'تم فتحه في نافذة جديدة', + restart: 'إعادة تشغيل', + visit: 'زيارة', + welcome: 'مرحبا', + }, + prompt: { + stay: 'ابق', + discardChanges: 'تجاهل التغييرات', + unsavedChanges: 'لديك تغييرات غير محفوظة', + unsavedChangesWarning: 'هل أنت متأكد أنك تريد الانتقال بعيدًا عن هذه الصفحة؟ - لديك تغييرات غير محفوظة', + confirmListViewPublish: 'النشر سيجعل العناصر المحددة مرئية على الموقع.', + confirmListViewUnpublish: 'إلغاء النشر سيزيل العناصر المحددة وجميع نسلها من الموقع.', + confirmUnpublish: 'إلغاء النشر سيزيل هذه الصفحة وجميع نسلها من الموقع.', + doctypeChangeWarning: 'لديك تغييرات غير محفوظة. إجراء تغييرات على نوع الوثيقة سيتسبب في تجاهل التغييرات.', + }, + bulk: { + done: 'تم', + deletedItem: 'تم حذف %0% عنصر', + deletedItems: 'تم حذف %0% عناصر', + deletedItemOfItem: 'تم حذف %0% من %1% عنصر', + deletedItemOfItems: 'تم حذف %0% من %1% عناصر', + publishedItem: 'تم نشر %0% عنصر', + publishedItems: 'تم نشر %0% عناصر', + publishedItemOfItem: 'تم نشر %0% من %1% عنصر', + publishedItemOfItems: 'تم نشر %0% من %1% عناصر', + unpublishedItem: 'تم إلغاء نشر %0% عنصر', + unpublishedItems: 'تم إلغاء نشر %0% عناصر', + unpublishedItemOfItem: 'تم إلغاء نشر %0% من %1% عنصر', + unpublishedItemOfItems: 'تم إلغاء نشر %0% من %1% عناصر', + movedItem: 'تم نقل %0% عنصر', + movedItems: 'تم نقل %0% عناصر', + movedItemOfItem: 'تم نقل %0% من %1% عنصر', + movedItemOfItems: 'تم نقل %0% من %1% عناصر', + copiedItem: 'تم نسخ %0% عنصر', + copiedItems: 'تم نسخ %0% عناصر', + copiedItemOfItem: 'تم نسخ %0% من %1% عنصر', + copiedItemOfItems: 'تم نسخ %0% من %1% عناصر', + }, + defaultdialogs: { + nodeNameLinkPicker: 'عنوان الرابط', + urlLinkPicker: 'الرابط', + anchorLinkPicker: 'مرساة / سلسلة استعلام', + anchorInsert: 'اسم', + closeThisWindow: 'أغلق هذه النافذة', + confirmdelete: 'هل أنت متأكد أنك تريد الحذف', + confirmdeleteNumberOfItems: 'هل أنت متأكد أنك تريد حذف %0% من %1% العناصر', + confirmdisable: 'هل أنت متأكد أنك تريد التعطيل', + confirmremove: 'هل أنت متأكد أنك تريد الإزالة', + confirmremoveusageof: 'هل أنت متأكد أنك تريد إزالة استخدام %0%', + confirmlogout: 'هل أنت متأكد؟', + confirmSure: 'هل أنت متأكد؟', + cut: 'قص', + editDictionary: 'تحرير عنصر القاموس', + editLanguage: 'تحرير اللغة', + editSelectedMedia: 'تحرير الوسائط المحددة', + insertAnchor: 'إدراج رابط محلي', + insertCharacter: 'إدراج حرف', + insertgraphicheadline: 'إدراج عنوان رسومي', + insertimage: 'إدراج صورة', + insertlink: 'إدراج رابط', + insertMacro: 'انقر لإضافة ماكرو', + inserttable: 'إدراج جدول', + languagedeletewarning: 'سيؤدي هذا إلى حذف اللغة', + languageChangeWarning: + 'قد يكون تغيير الثقافة للغة عملية مكلفة وستؤدي إلى إعادة بناء ذاكرة التخزين المؤقت للمحتوى والفهارس', + lastEdited: 'آخر تحرير', + link: 'رابط', + linkinternal: 'رابط داخلي:', + linklocaltip: 'عند استخدام الروابط المحلية، أدخل "#" أمام الرابط', + linknewwindow: 'فتح في نافذة جديدة؟', + macroDoesNotHaveProperties: 'هذا الماكرو لا يحتوي على خصائص يمكنك تحريرها', + paste: 'لصق', + permissionsEdit: 'تحرير الأذونات لـ', + permissionsSet: 'تعيين الأذونات لـ', + permissionsSetForGroup: 'تعيين الأذونات لـ %0% لمجموعة المستخدمين %1%', + permissionsHelp: 'اختر مجموعات المستخدمين التي تريد تعيين الأذونات لها', + recycleBinDeleting: 'يتم الآن حذف العناصر في سلة المهملات. يرجى عدم إغلاق هذه النافذة أثناء تنفيذ هذه العملية', + recycleBinIsEmpty: 'سلة المهملات فارغة الآن', + recycleBinWarning: 'عند حذف العناصر من سلة المهملات، ستختفي إلى الأبد', + regexSearchError: + "خدمة الويب الخاصة بـ regexlib.com تواجه حالياً بعض المشاكل، ونحن لا نملك السيطرة على ذلك. نحن آسفون لهذا الإزعاج.", + regexSearchHelp: "ابحث عن تعبير منتظم لإضافته كتحقق لحقل النموذج. مثال: 'بريد إلكتروني،' 'رمز بريدي'، 'عنوان URL'.", + removeMacro: 'إزالة الماكرو', + requiredField: 'حقل مطلوب', + sitereindexed: 'تمت إعادة فهرسة الموقع', + siterepublished: + 'تم تحديث ذاكرة التخزين المؤقت للموقع. جميع المحتويات المنشورة محدثة الآن، بينما تظل جميع المحتويات غير المنشورة كما هي', + siterepublishHelp: + 'سيتم تحديث ذاكرة التخزين المؤقت للموقع. سيتم تحديث جميع المحتويات المنشورة، بينما ستظل المحتويات غير المنشورة كما هي.', + tableColumns: 'عدد الأعمدة', + tableRows: 'عدد الصفوف', + thumbnailimageclickfororiginal: 'انقر على الصورة لرؤية الحجم الكامل', + treepicker: 'اختيار العنصر', + viewCacheItem: 'عرض عنصر ذاكرة التخزين المؤقت', + relateToOriginalLabel: 'يرتبط بالأصل', + includeDescendants: 'تضمين الأحفاد', + theFriendliestCommunity: 'أكثر مجتمع ودود', + linkToPage: 'رابط إلى الصفحة', + openInNewWindow: 'فتح الوثيقة المرتبطة في نافذة أو علامة تبويب جديدة', + linkToMedia: 'رابط إلى الوسائط', + selectContentStartNode: 'اختر العقدة الأساسية للمحتوى', + selectMedia: 'اختر الوسائط', + selectMediaType: 'اختر نوع الوسائط', + selectIcon: 'اختر الأيقونة', + selectItem: 'اختر العنصر', + selectLink: 'اختر الرابط', + selectMacro: 'اختر الماكرو', + selectContent: 'اختر المحتوى', + selectContentType: 'اختر نوع المحتوى', + selectMediaStartNode: 'اختر العقدة الأساسية للوسائط', + selectMember: 'اختر العضو', + selectMembers: 'اختر الأعضاء', + selectMemberGroup: 'اختر مجموعة الأعضاء', + selectMemberType: 'اختر نوع العضو', + selectNode: 'اختر العقدة', + selectLanguages: 'اختر اللغات', + selectSections: 'اختر الأقسام', + selectUser: 'اختر المستخدم', + selectUsers: 'اختر المستخدمين', + noIconsFound: 'لم يتم العثور على أيقونات', + noMacroParams: 'لا توجد معلمات لهذا الماكرو', + noMacros: 'لا توجد ماكروات لإدراجها', + externalLoginProviders: 'تسجيل الدخول الخارجي', + exceptionDetail: 'تفاصيل الاستثناء', + stacktrace: 'التتبع الكامل', + innerException: 'الاستثناء الداخلي', + linkYour: 'ربط حساب {0} الخاص بك', + linkYourConfirm: 'أنت على وشك ربط حسابك في Umbraco وحسابك في {0} وسيتم توجيهك إلى {0} للتأكيد.', + unLinkYour: 'إلغاء ربط حساب {0} الخاص بك', + unLinkYourConfirm: 'أنت على وشك إلغاء ربط حسابك في Umbraco وحسابك في {0} وسيتم تسجيل خروجك.', + linkedToService: 'حسابك مرتبط بهذه الخدمة', + selectEditor: 'اختر المحرر', + selectEditorConfiguration: 'اختر التكوين', + selectSnippet: 'اختر الشريحة', + variantdeletewarning: + 'سيؤدي ذلك إلى حذف العقدة وجميع اللغات المرتبطة بها. إذا كنت ترغب فقط في حذف لغة واحدة، يجب عليك إلغاء نشر العقدة في تلك اللغة بدلاً من ذلك.', + propertyuserpickerremovewarning: 'سيتم إزالة المستخدم %0%.', + userremovewarning: 'سيتم إزالة المستخدم %0% من المجموعة %1%', + yesRemove: 'نعم، أزل', + deleteLayout: 'أنت تقوم بحذف التخطيط', + deletingALayout: 'سيؤدي تعديل التخطيط إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.', + }, dictionary: { importDictionaryItemHelp: '\n لاستيراد عنصر قاموس، ابحث عن ملف ".udt" على جهاز الكمبيوتر الخاص بك بالنقر على زر "استيراد"\n (سيُطلب منك التأكيد في الشاشة التالية)\n ', @@ -554,8 +574,7 @@ export default { }, examineManagement: { configuredSearchers: 'باحثون مكوّنون', - configuredSearchersDescription: - 'يعرض الخصائص والأدوات لأي باحث مكوّن (مثل الباحث متعدد الفهارس)', + configuredSearchersDescription: 'يعرض الخصائص والأدوات لأي باحث مكوّن (مثل الباحث متعدد الفهارس)', fieldValues: 'قيم الحقول', healthStatus: 'حالة الصحة', healthStatusDescription: 'حالة صحة الفهرس وما إذا كان يمكن قراءته', @@ -564,8 +583,7 @@ export default { contentInIndex: 'المحتوى في الفهرس', indexInfoDescription: 'يعرض خصائص الفهرس', manageIndexes: 'إدارة فهارس Examine', - manageIndexesDescription: - 'يسمح لك بمشاهدة تفاصيل كل فهرس ويوفر بعض الأدوات لإدارة الفهارس', + manageIndexesDescription: 'يسمح لك بمشاهدة تفاصيل كل فهرس ويوفر بعض الأدوات لإدارة الفهارس', rebuildIndex: 'إعادة بناء الفهرس', rebuildIndexWarning: 'سيؤدي هذا إلى إعادة بناء الفهرس.
      بناءً على حجم المحتوى الموجود في موقعك، قد يستغرق هذا بعض الوقت.
      لا يُنصح بإعادة بناء الفهرس في أوقات حركة المرور العالية على الموقع أو عند قيام المحررين بتحرير المحتوى.', @@ -630,8 +648,7 @@ export default { selectFolder: 'اختر المجلد للتحريك', inTheTree: 'إلى في هيكل الشجرة أدناه', wasMoved: 'تم نقله تحت', - hasReferencesDeleteConsequence: - 'حذف %0% سيؤدي إلى حذف الخصائص وبياناتها من العناصر التالية', + hasReferencesDeleteConsequence: 'حذف %0% سيؤدي إلى حذف الخصائص وبياناتها من العناصر التالية', acceptDeleteConsequence: 'أفهم أن هذا الإجراء سيؤدي إلى حذف الخصائص والبيانات الوثائق إلى هذا النوع من البيانات\n \n ', }, @@ -657,19 +674,19 @@ export default { receivedErrorFromServer: 'تم استلام خطأ من الخادم', dissallowedMediaType: 'تم رفض نوع الملف المحدد من قبل المسؤول', codemirroriewarning: - "ملاحظة! حتى مع تمكين CodeMirror عن طريق التكوين، فإنه معطل في\n Internet Explorer لأنه ليس مستقرًا بما فيه الكفاية.\n ", + 'ملاحظة! حتى مع تمكين CodeMirror عن طريق التكوين، فإنه معطل في\n Internet Explorer لأنه ليس مستقرًا بما فيه الكفاية.\n ', contentTypeAliasAndNameNotNull: 'يرجى ملء كل من الاسم المستعار والاسم في نوع الخاصية الجديد!', filePermissionsError: 'هناك مشكلة في الوصول للقراءة/الكتابة لملف أو مجلد محدد', macroErrorLoadingPartialView: 'خطأ في تحميل برنامج عرض جزئي (الملف: %0%)', missingTitle: 'يرجى إدخال عنوان', missingType: 'يرجى اختيار نوع', pictureResizeBiggerThanOrg: - "أنت على وشك جعل الصورة أكبر من حجمها الأصلي. هل أنت متأكد\n أنك تريد المتابعة؟\n ", + 'أنت على وشك جعل الصورة أكبر من حجمها الأصلي. هل أنت متأكد\n أنك تريد المتابعة؟\n ', startNodeDoesNotExists: 'تم حذف العقدة البداية، يرجى الاتصال بالمسؤول الخاص بك', stylesMustMarkBeforeSelect: 'يرجى تمييز المحتوى قبل تغيير النمط', stylesNoStylesOnPage: 'لا توجد أنماط نشطة متاحة', tableColMergeLeft: 'يرجى وضع المؤشر على يسار الخليتين اللتين ترغب في دمجهما', - tableSplitNotSplittable: "لا يمكنك تقسيم خلية لم يتم دمجها.", + tableSplitNotSplittable: 'لا يمكنك تقسيم خلية لم يتم دمجها.', propertyHasErrors: 'هذه الخاصية غير صالحة', externalLoginError: 'تسجيل الدخول الخارجي', unauthorized: 'لم تكن مصرحًا لك قبل القيام بهذا الإجراء', @@ -691,7 +708,7 @@ export default { serverError: 'خطأ في الخادم', temporarilyUnavailable: 'الخدمة غير متاحة مؤقتًا', }, - general: { + general: { options: 'خيارات', about: 'حول', action: 'إجراء', @@ -908,690 +925,745 @@ export default { headers: { page: 'صفحة', }, - installer: { - databaseErrorCannotConnect: "لا يمكن للمثبت الاتصال بقاعدة البيانات.", - databaseErrorWebConfig: "تعذر حفظ ملف web.config. يرجى تعديل سلسلة الاتصال يدويًا.", - databaseFound: "تم العثور على قاعدة بياناتك وتم التعرف عليها كـ", - databaseHeader: "تكوين قاعدة البيانات", - databaseInstall: "اضغط على زر التثبيت لتثبيت قاعدة بيانات Umbraco %0%", - databaseInstallDone: "تم نسخ Umbraco %0% الآن إلى قاعدة بياناتك. اضغط على التالي للمتابعة.", - databaseNotFound: "

      لم يتم العثور على قاعدة البيانات! يرجى التحقق من أن المعلومات في سلسلة الاتصال في ملف \"web.config\" صحيحة.

      \n

      للمتابعة، يرجى تعديل ملف \"web.config\" (باستخدام Visual Studio أو محرر النصوص المفضل لديك)، والتمرير إلى الأسفل، وإضافة سلسلة الاتصال لقاعدة البيانات الخاصة بك في المفتاح المسمى \"UmbracoDbDSN\" وحفظ الملف.

      \n

      اضغط على زر إعادة المحاولة عند الانتهاء.
      \n\t\t\t مزيد من المعلومات حول تحرير web.config هنا.

      ", - databaseText: "لإكمال هذه الخطوة، يجب أن تكون لديك بعض المعلومات حول خادم قاعدة البيانات الخاص بك (\"سلسلة الاتصال\").
      \n يرجى الاتصال بمزود خدمة الإنترنت الخاص بك إذا لزم الأمر.\n إذا كنت تقوم بالتثبيت على جهاز محلي أو خادم، قد تحتاج إلى معلومات من مسؤول النظام الخاص بك.", - databaseUpgrade: "

      اضغط على زر الترقية لترقية قاعدة البيانات إلى Umbraco %0%

      \n

      لا تقلق - لن يتم حذف أي محتوى وكل شيء سيستمر في العمل بعد ذلك!

      ", - databaseUpgradeDone: "تم ترقية قاعدة البيانات الخاصة بك إلى الإصدار النهائي %0%.
      اضغط على التالي للمتابعة.", - databaseUpToDate: "قاعدة البيانات الحالية محدثة! اضغط على التالي لمتابعة معالج التكوين", - defaultUserChangePass: "يجب تغيير كلمة مرور المستخدم الافتراضي!", - defaultUserDisabled: "تم تعطيل المستخدم الافتراضي أو لا يمكنه الوصول إلى Umbraco!

      لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.", - defaultUserPassChanged: "تم تغيير كلمة مرور المستخدم الافتراضي بنجاح منذ التثبيت!

      لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.", - defaultUserPasswordChanged: "تم تغيير كلمة المرور!", - greatStart: "ابدأ بداية رائعة، شاهد مقاطع الفيديو التمهيدية الخاصة بنا", - licenseText: "بالنقر على الزر التالي (أو تعديل umbracoConfigurationStatus في web.config)، فإنك توافق على رخصة هذا البرنامج كما هو موضح في الصندوق أدناه. لاحظ أن توزيع Umbraco يتكون من رخصتين مختلفتين، رخصة MIT مفتوحة المصدر للإطار ورخصة البرمجيات المجانية الخاصة بـ Umbraco التي تغطي واجهة المستخدم.", - None: "لم يتم تثبيته بعد.", - permissionsAffectedFolders: "الملفات والمجلدات المتأثرة", - permissionsAffectedFoldersMoreInfo: "مزيد من المعلومات حول إعداد الأذونات لـ Umbraco هنا", - permissionsAffectedFoldersText: "يجب منح أذونات تعديل لـ ASP.NET على الملفات/المجلدات التالية", - permissionsAlmostPerfect: "إعدادات الأذونات الخاصة بك تقريبًا مثالية!

      \n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.", - permissionsHowtoResolve: "كيفية الحل", - permissionsHowtoResolveLink: "اضغط هنا لقراءة النسخة النصية", - permissionsHowtoResolveText: "شاهد الفيديو التعليمي الخاص بإعداد أذونات المجلدات لـ Umbraco أو اقرأ النسخة النصية.", - permissionsMaybeAnIssue: "قد تكون إعدادات الأذونات الخاصة بك مشكلة!\n

      \n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من إنشاء مجلدات أو تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.", - permissionsNotReady: "إعدادات الأذونات الخاصة بك غير جاهزة لـ Umbraco!\n

      \n لتشغيل Umbraco، ستحتاج إلى تحديث إعدادات الأذونات الخاصة بك.", - permissionsPerfect: "إعدادات الأذونات الخاصة بك مثالية!

      \n أنت جاهز لتشغيل Umbraco وتثبيت الحزم!", - permissionsResolveFolderIssues: "حل مشكلة المجلد", - permissionsResolveFolderIssuesLink: "اتبع هذا الرابط للحصول على مزيد من المعلومات حول مشاكل ASP.NET وإنشاء المجلدات", - permissionsSettingUpPermissions: "إعداد أذونات المجلدات", - permissionsText: "يحتاج Umbraco إلى أذونات الكتابة/التعديل لبعض الأدلة لتخزين الملفات مثل الصور وملفات PDF. كما أنه يخزن بيانات مؤقتة (المعروفة باسم: ذاكرة التخزين المؤقت) لتحسين أداء موقع الويب الخاص بك.", - runwayFromScratch: "أريد البدء من الصفر", - runwayFromScratchText: "موقع الويب الخاص بك فارغ تمامًا في الوقت الحالي، وهذا مثالي إذا كنت ترغب في البدء من الصفر وإنشاء الأنواع الوثائق والقوالب الخاصة بك. (تعرف على الكيفية) لا يزال بإمكانك اختيار تثبيت Runway لاحقًا. يرجى الانتقال إلى قسم المطور واختيار الحزم.", - runwayHeader: "لقد قمت بإعداد منصة Umbraco نظيفة. ماذا تريد أن تفعل بعد ذلك؟", - runwayInstalled: "تم تثبيت Runway", - runwayInstalledText: "لديك الأساس في مكانه. اختر الوحدات التي ترغب في تثبيتها فوقه.
      \n هذه هي قائمتنا الموصى بها من الوحدات، قم بتحديد الوحدات التي ترغب في تثبيتها، أو عرض القائمة الكاملة للوحدات", - runwayOnlyProUsers: "يوصى بها فقط للمستخدمين ذوي الخبرة", - runwaySimpleSite: "أريد البدء بموقع ويب بسيط", - runwaySimpleSiteText: "

      \"Runway\" هو موقع ويب بسيط يوفر بعض الأنواع الوثائق والقوالب الأساسية. يمكن للمثبت إعداد Runway لك تلقائيًا، لكن يمكنك بسهولة تحريره أو توسيعه أو إزالته. ليس ضروريًا ويمكنك استخدام Umbraco بشكل مثالي بدونها. ومع ذلك، يوفر Runway أساسًا سهلًا يعتمد على أفضل الممارسات لبدء التشغيل بسرعة أكبر من أي وقت مضى. إذا اخترت تثبيت Runway، يمكنك اختيار الوحدات الأساسية الاختيارية المعروفة باسم وحدات Runway لتعزيز صفحات Runway الخاصة بك.

      \n متضمن مع Runway: الصفحة الرئيسية، صفحة البدء، صفحة تثبيت الوحدات.
      \n الوحدات الاختيارية: التنقل العلوي، خريطة الموقع، الاتصال، المعرض.
      ", - runwayWhatIsRunway: "ما هو Runway", - step1: "الخطوة 1/5 قبول الترخيص", - step2: "الخطوة 2/5: تكوين قاعدة البيانات", - step3: "الخطوة 3/5: التحقق من أذونات الملفات", - step4: "الخطوة 4/5: التحقق من أمان Umbraco", - step5: "الخطوة 5/5: Umbraco جاهز للبدء", - thankYou: "شكرًا لاختيارك Umbraco", - theEndBrowseSite: "

      تصفح موقعك الجديد

      \nلقد قمت بتثبيت Runway، فلماذا لا ترى كيف يبدو موقع الويب الجديد الخاص بك.", - theEndFurtherHelp: "

      مزيد من المساعدة والمعلومات

      \nاحصل على المساعدة من مجتمعنا الحائز على جوائز، تصفح الوثائق أو شاهد بعض مقاطع الفيديو المجانية حول كيفية بناء موقع بسيط، كيفية استخدام الحزم ودليل سريع لمصطلحات Umbraco", - theEndHeader: "تم تثبيت Umbraco %0% وهو جاهز للاستخدام", - theEndInstallFailed: "لإكمال التثبيت، ستحتاج إلى تحرير /web.config file يدويًا وتحديث المفتاح AppSetting UmbracoConfigurationStatus في الأسفل إلى القيمة '%0%'.", - theEndInstallSuccess: "يمكنك البدء فورًا بالنقر على زر \"إطلاق Umbraco\" أدناه.
      إذا كنت جديدًا على Umbraco، يمكنك العثور على الكثير من الموارد على صفحات البدء الخاصة بنا.", - theEndOpenUmbraco: "

      إطلاق Umbraco

      \nلإدارة موقع الويب الخاص بك، افتح ببساطة الخلفية لـ Umbraco وابدأ بإضافة المحتوى أو تحديث القوالب والأنماط أو إضافة ميزات جديدة", - Unavailable: "فشل الاتصال بقاعدة البيانات.", - Version3: "إصدار Umbraco 3", - Version4: "إصدار Umbraco 4", - watch: "شاهد", - welcomeIntro: "سيقوم هذا المعالج بتوجيهك خلال عملية تكوين Umbraco %0% لتثبيت جديد أو الترقية من الإصدار 3.0.\n

      \n اضغط على التالي لبدء المعالج." - }, + installer: { + databaseErrorCannotConnect: 'لا يمكن للمثبت الاتصال بقاعدة البيانات.', + databaseErrorWebConfig: 'تعذر حفظ ملف web.config. يرجى تعديل سلسلة الاتصال يدويًا.', + databaseFound: 'تم العثور على قاعدة بياناتك وتم التعرف عليها كـ', + databaseHeader: 'تكوين قاعدة البيانات', + databaseInstall: 'اضغط على زر التثبيت لتثبيت قاعدة بيانات Umbraco %0%', + databaseInstallDone: 'تم نسخ Umbraco %0% الآن إلى قاعدة بياناتك. اضغط على التالي للمتابعة.', + databaseNotFound: + '

      لم يتم العثور على قاعدة البيانات! يرجى التحقق من أن المعلومات في سلسلة الاتصال في ملف "web.config" صحيحة.

      \n

      للمتابعة، يرجى تعديل ملف "web.config" (باستخدام Visual Studio أو محرر النصوص المفضل لديك)، والتمرير إلى الأسفل، وإضافة سلسلة الاتصال لقاعدة البيانات الخاصة بك في المفتاح المسمى "UmbracoDbDSN" وحفظ الملف.

      \n

      اضغط على زر إعادة المحاولة عند الانتهاء.
      \n\t\t\t مزيد من المعلومات حول تحرير web.config هنا.

      ', + databaseText: + 'لإكمال هذه الخطوة، يجب أن تكون لديك بعض المعلومات حول خادم قاعدة البيانات الخاص بك ("سلسلة الاتصال").
      \n يرجى الاتصال بمزود خدمة الإنترنت الخاص بك إذا لزم الأمر.\n إذا كنت تقوم بالتثبيت على جهاز محلي أو خادم، قد تحتاج إلى معلومات من مسؤول النظام الخاص بك.', + databaseUpgrade: + '

      اضغط على زر الترقية لترقية قاعدة البيانات إلى Umbraco %0%

      \n

      لا تقلق - لن يتم حذف أي محتوى وكل شيء سيستمر في العمل بعد ذلك!

      ', + databaseUpgradeDone: + 'تم ترقية قاعدة البيانات الخاصة بك إلى الإصدار النهائي %0%.
      اضغط على التالي للمتابعة.', + databaseUpToDate: 'قاعدة البيانات الحالية محدثة! اضغط على التالي لمتابعة معالج التكوين', + defaultUserChangePass: 'يجب تغيير كلمة مرور المستخدم الافتراضي!', + defaultUserDisabled: + 'تم تعطيل المستخدم الافتراضي أو لا يمكنه الوصول إلى Umbraco!

      لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.', + defaultUserPassChanged: + 'تم تغيير كلمة مرور المستخدم الافتراضي بنجاح منذ التثبيت!

      لا حاجة إلى اتخاذ أي إجراءات أخرى. اضغط على التالي للمتابعة.', + defaultUserPasswordChanged: 'تم تغيير كلمة المرور!', + greatStart: 'ابدأ بداية رائعة، شاهد مقاطع الفيديو التمهيدية الخاصة بنا', + licenseText: + 'بالنقر على الزر التالي (أو تعديل umbracoConfigurationStatus في web.config)، فإنك توافق على رخصة هذا البرنامج كما هو موضح في الصندوق أدناه. لاحظ أن توزيع Umbraco يتكون من رخصتين مختلفتين، رخصة MIT مفتوحة المصدر للإطار ورخصة البرمجيات المجانية الخاصة بـ Umbraco التي تغطي واجهة المستخدم.', + None: 'لم يتم تثبيته بعد.', + permissionsAffectedFolders: 'الملفات والمجلدات المتأثرة', + permissionsAffectedFoldersMoreInfo: 'مزيد من المعلومات حول إعداد الأذونات لـ Umbraco هنا', + permissionsAffectedFoldersText: 'يجب منح أذونات تعديل لـ ASP.NET على الملفات/المجلدات التالية', + permissionsAlmostPerfect: + 'إعدادات الأذونات الخاصة بك تقريبًا مثالية!

      \n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.', + permissionsHowtoResolve: 'كيفية الحل', + permissionsHowtoResolveLink: 'اضغط هنا لقراءة النسخة النصية', + permissionsHowtoResolveText: + 'شاهد الفيديو التعليمي الخاص بإعداد أذونات المجلدات لـ Umbraco أو اقرأ النسخة النصية.', + permissionsMaybeAnIssue: + 'قد تكون إعدادات الأذونات الخاصة بك مشكلة!\n

      \n يمكنك تشغيل Umbraco بدون مشاكل، لكن لن تتمكن من إنشاء مجلدات أو تثبيت الحزم الموصى بها للاستفادة الكاملة من Umbraco.', + permissionsNotReady: + 'إعدادات الأذونات الخاصة بك غير جاهزة لـ Umbraco!\n

      \n لتشغيل Umbraco، ستحتاج إلى تحديث إعدادات الأذونات الخاصة بك.', + permissionsPerfect: + 'إعدادات الأذونات الخاصة بك مثالية!

      \n أنت جاهز لتشغيل Umbraco وتثبيت الحزم!', + permissionsResolveFolderIssues: 'حل مشكلة المجلد', + permissionsResolveFolderIssuesLink: + 'اتبع هذا الرابط للحصول على مزيد من المعلومات حول مشاكل ASP.NET وإنشاء المجلدات', + permissionsSettingUpPermissions: 'إعداد أذونات المجلدات', + permissionsText: + 'يحتاج Umbraco إلى أذونات الكتابة/التعديل لبعض الأدلة لتخزين الملفات مثل الصور وملفات PDF. كما أنه يخزن بيانات مؤقتة (المعروفة باسم: ذاكرة التخزين المؤقت) لتحسين أداء موقع الويب الخاص بك.', + runwayFromScratch: 'أريد البدء من الصفر', + runwayFromScratchText: + 'موقع الويب الخاص بك فارغ تمامًا في الوقت الحالي، وهذا مثالي إذا كنت ترغب في البدء من الصفر وإنشاء الأنواع الوثائق والقوالب الخاصة بك. (تعرف على الكيفية) لا يزال بإمكانك اختيار تثبيت Runway لاحقًا. يرجى الانتقال إلى قسم المطور واختيار الحزم.', + runwayHeader: 'لقد قمت بإعداد منصة Umbraco نظيفة. ماذا تريد أن تفعل بعد ذلك؟', + runwayInstalled: 'تم تثبيت Runway', + runwayInstalledText: + 'لديك الأساس في مكانه. اختر الوحدات التي ترغب في تثبيتها فوقه.
      \n هذه هي قائمتنا الموصى بها من الوحدات، قم بتحديد الوحدات التي ترغب في تثبيتها، أو عرض القائمة الكاملة للوحدات', + runwayOnlyProUsers: 'يوصى بها فقط للمستخدمين ذوي الخبرة', + runwaySimpleSite: 'أريد البدء بموقع ويب بسيط', + runwaySimpleSiteText: + '

      "Runway" هو موقع ويب بسيط يوفر بعض الأنواع الوثائق والقوالب الأساسية. يمكن للمثبت إعداد Runway لك تلقائيًا، لكن يمكنك بسهولة تحريره أو توسيعه أو إزالته. ليس ضروريًا ويمكنك استخدام Umbraco بشكل مثالي بدونها. ومع ذلك، يوفر Runway أساسًا سهلًا يعتمد على أفضل الممارسات لبدء التشغيل بسرعة أكبر من أي وقت مضى. إذا اخترت تثبيت Runway، يمكنك اختيار الوحدات الأساسية الاختيارية المعروفة باسم وحدات Runway لتعزيز صفحات Runway الخاصة بك.

      \n متضمن مع Runway: الصفحة الرئيسية، صفحة البدء، صفحة تثبيت الوحدات.
      \n الوحدات الاختيارية: التنقل العلوي، خريطة الموقع، الاتصال، المعرض.
      ', + runwayWhatIsRunway: 'ما هو Runway', + step1: 'الخطوة 1/5 قبول الترخيص', + step2: 'الخطوة 2/5: تكوين قاعدة البيانات', + step3: 'الخطوة 3/5: التحقق من أذونات الملفات', + step4: 'الخطوة 4/5: التحقق من أمان Umbraco', + step5: 'الخطوة 5/5: Umbraco جاهز للبدء', + thankYou: 'شكرًا لاختيارك Umbraco', + theEndBrowseSite: + '

      تصفح موقعك الجديد

      \nلقد قمت بتثبيت Runway، فلماذا لا ترى كيف يبدو موقع الويب الجديد الخاص بك.', + theEndFurtherHelp: + '

      مزيد من المساعدة والمعلومات

      \nاحصل على المساعدة من مجتمعنا الحائز على جوائز، تصفح الوثائق أو شاهد بعض مقاطع الفيديو المجانية حول كيفية بناء موقع بسيط، كيفية استخدام الحزم ودليل سريع لمصطلحات Umbraco', + theEndHeader: 'تم تثبيت Umbraco %0% وهو جاهز للاستخدام', + theEndInstallFailed: + "لإكمال التثبيت، ستحتاج إلى تحرير /web.config file يدويًا وتحديث المفتاح AppSetting UmbracoConfigurationStatus في الأسفل إلى القيمة '%0%'.", + theEndInstallSuccess: + 'يمكنك البدء فورًا بالنقر على زر "إطلاق Umbraco" أدناه.
      إذا كنت جديدًا على Umbraco، يمكنك العثور على الكثير من الموارد على صفحات البدء الخاصة بنا.', + theEndOpenUmbraco: + '

      إطلاق Umbraco

      \nلإدارة موقع الويب الخاص بك، افتح ببساطة الخلفية لـ Umbraco وابدأ بإضافة المحتوى أو تحديث القوالب والأنماط أو إضافة ميزات جديدة', + Unavailable: 'فشل الاتصال بقاعدة البيانات.', + Version3: 'إصدار Umbraco 3', + Version4: 'إصدار Umbraco 4', + watch: 'شاهد', + welcomeIntro: + 'سيقوم هذا المعالج بتوجيهك خلال عملية تكوين Umbraco %0% لتثبيت جديد أو الترقية من الإصدار 3.0.\n

      \n اضغط على التالي لبدء المعالج.', + }, language: { - cultureCode: 'رمز الثقافة', - displayName: 'اسم الثقافة', - noFallbackLanguages: 'لا توجد لغات أخرى للاختيار من بينها', - }, - lockout: { - lockoutWillOccur: "لقد كنت غير نشط وسيتم تسجيل خروجك تلقائيًا في", - renewSession: 'جدد الآن لحفظ عملك', - }, - login: { - greeting0: 'مرحبًا! بداية أسبوع مثمرة مع Umbraco!', - greeting1: 'مرحبًا! يوم ثلاثاء إبداعي في Umbraco!', - greeting2: 'مرحبًا! يوم أربعاء موفق في إدارة محتواك!', - greeting3: 'مرحبًا! يوم خميس مليء بالإنجازات مع Umbraco!', - greeting4: 'مرحبًا! إنه يوم جمعة رائع لإدارة محتوى موقعك!', - greeting5: 'مرحبًا! عطلة نهاية أسبوع سعيدة مع Umbraco!', - greeting6: 'مرحبًا! يوم أحد جديد، فرص جديدة في Umbraco!', - instruction: 'سجل الدخول إلى Umbraco', - signInWith: 'سجل الدخول باستخدام {0}', - timeout: 'انتهت جلستك. يرجى تسجيل الدخول مرة أخرى أدناه.', - }, - main: { - dashboard: 'لوحة التحكم', - sections: 'الأقسام', - tree: 'المحتوى', - }, - moveOrCopy: { - choose: 'اختر الصفحة أعلاه...', - copyDone: '%0% تم نسخه إلى %1%', - copyTo: 'حدد المكان الذي يجب نسخ الوثيقة %0% إليه أدناه', - moveDone: '%0% تم نقله إلى %1%', - moveTo: 'حدد المكان الذي يجب نقل الوثيقة %0% إليه أدناه', - nodeSelected: "تم تحديده كجذر لمحتواك الجديد، انقر على 'موافق' أدناه.", - noNodeSelected: "لم يتم تحديد أي عقدة بعد، يرجى تحديد عقدة في القائمة أعلاه قبل النقر على 'موافق'", - notAllowedByContentType: 'العقدة الحالية غير مسموح بها تحت العقدة المحددة بسبب نوعها', - notAllowedByPath: 'لا يمكن نقل العقدة الحالية إلى إحدى صفحاتها الفرعية، ولا يمكن أن تكون الوالد والوجهة هي نفسها', - notAllowedAtRoot: 'لا يمكن أن توجد العقدة الحالية في الجذر', - notValid: "لا يُسمح بالإجراء نظرًا لأن لديك أذونات غير كافية على 1 أو أكثر من الوثيقة الفرعية.\n", - relateToOriginal: 'ربط العناصر المنسوخة بالأصل', - }, - notifications: { - editNotifications: 'حدد إشعارك لـ %0%', - notificationsSavedFor: 'تم حفظ إعدادات الإشعارات لـ', - notifications: 'الإشعارات', - }, - packager: { - actions: 'إجراءات', - created: 'أنشئ', - createPackage: 'إنشاء حزمة', - chooseLocalPackageText: '\n اختر حزمة من جهازك، بالنقر على زر تصفح
      \n وتحديد الحزمة. عادةً ما تحتوي حزم Umbraco على امتداد ".umb" أو ".zip".\n ', - deletewarning: 'سيؤدي ذلك إلى حذف الحزمة', - includeAllChildNodes: 'تضمين جميع العقد الفرعية', - installed: 'مثبتة', - installedPackages: 'الحزم المثبتة', - installInstructions: 'تعليمات التثبيت', - noConfigurationView: 'لا تحتوي هذه الحزمة على عرض تكوين', - noPackagesCreated: 'لم يتم إنشاء أي حزم بعد', - noPackages: 'لم يتم تثبيت أي حزم', - noPackagesDescription: "تصفح الحزم المتاحة باستخدام أيقونة 'الحزم' في أعلى يمين الشاشة", - packageContent: 'محتوى الحزمة', - packageLicense: 'الرخصة', - packageSearch: 'البحث عن الحزم', - packageSearchResults: 'نتائج البحث عن', - packageNoResults: 'لم نجد شيئًا لـ', - packageNoResultsDescription: 'يرجى محاولة البحث عن حزمة أخرى أو تصفح الفئات\n', - packagesPopular: 'الأكثر شيوعًا', - packagesPromoted: 'مروج لها', - packagesNew: 'الإصدارات الجديدة', - packageHas: 'لديه', - packageKarmaPoints: 'نقاط الكارما', - packageInfo: 'معلومات', - packageOwner: 'المالك', - packageContrib: 'المساهمون', - packageCreated: 'أنشئ', - packageCurrentVersion: 'الإصدار الحالي', - packageNetVersion: 'إصدار .NET', - packageDownloads: 'التنزيلات', - packageLikes: 'الإعجابات', - packageCompatibility: 'التوافق', - packageCompatibilityDescription: 'تكون هذه الحزمة متوافقة مع الإصدارات التالية من Umbraco، حسب\n ما أبلغ عنه أعضاء المجتمع. لا يمكن ضمان التوافق الكامل للإصدارات المبلغ عنها أقل من 100%\n ', - packageExternalSources: 'المصادر الخارجية', - packageAuthor: 'المؤلف', - packageDocumentation: 'الوثائق', - packageMetaData: 'بيانات الحزمة', - packageName: 'اسم الحزمة', - packageNoItemsHeader: "لا تحتوي الحزمة على أي عناصر", - packageNoItemsText: 'لا تحتوي هذه الحزمة على أي عناصر لإلغاء التثبيت.

      \n يمكنك إزالة هذا بأمان من النظام بالنقر على "إلغاء تثبيت الحزمة" أدناه.', - packageOptions: 'خيارات الحزمة', - packageMigrationsRun: 'تشغيل ترحيلات الحزمة المعلقة', - packageMigrationsComplete: 'تم إكمال ترحيلات الحزمة بنجاح.', - packageMigrationsNonePending: 'تم إكمال جميع ترحيلات الحزمة بنجاح.', - packageReadme: 'ملف README الخاص بالحزمة', - packageRepository: 'مستودع الحزمة', - packageUninstallConfirm: 'تأكيد إلغاء تثبيت الحزمة', - packageUninstalledHeader: 'تم إلغاء تثبيت الحزمة', - packageUninstalledText: 'تم إلغاء تثبيت الحزمة بنجاح', - packageUninstallHeader: 'إلغاء تثبيت الحزمة', - packageUninstallText: 'يمكنك إلغاء تحديد العناصر التي لا ترغب في إزالتها في الوقت الحالي أدناه. عند النقر على "تأكيد الإلغاء"، ستتم إزالة جميع العناصر المحددة.
      \n ملاحظة: أي مستندات أو وسائط تعتمد على العناصر التي تقوم بإزالتها، ستتوقف عن العمل، وقد يؤدي ذلك إلى عدم استقرار النظام، لذا قم بإلغاء التثبيت بحذر. إذا كان لديك أي شكوك، اتصل بمؤلف الحزمة.', - packageVersion: 'إصدار الحزمة', - verifiedToWorkOnUmbracoCloud: 'تم التحقق من عمله على Umbraco Cloud', - }, + cultureCode: 'رمز الثقافة', + displayName: 'اسم الثقافة', + noFallbackLanguages: 'لا توجد لغات أخرى للاختيار من بينها', + }, + lockout: { + lockoutWillOccur: 'لقد كنت غير نشط وسيتم تسجيل خروجك تلقائيًا في', + renewSession: 'جدد الآن لحفظ عملك', + }, + login: { + greeting0: 'مرحبًا! بداية أسبوع مثمرة مع Umbraco!', + greeting1: 'مرحبًا! يوم ثلاثاء إبداعي في Umbraco!', + greeting2: 'مرحبًا! يوم أربعاء موفق في إدارة محتواك!', + greeting3: 'مرحبًا! يوم خميس مليء بالإنجازات مع Umbraco!', + greeting4: 'مرحبًا! إنه يوم جمعة رائع لإدارة محتوى موقعك!', + greeting5: 'مرحبًا! عطلة نهاية أسبوع سعيدة مع Umbraco!', + greeting6: 'مرحبًا! يوم أحد جديد، فرص جديدة في Umbraco!', + instruction: 'سجل الدخول إلى Umbraco', + signInWith: 'سجل الدخول باستخدام {0}', + timeout: 'انتهت جلستك. يرجى تسجيل الدخول مرة أخرى أدناه.', + }, + main: { + dashboard: 'لوحة التحكم', + sections: 'الأقسام', + tree: 'المحتوى', + }, + moveOrCopy: { + choose: 'اختر الصفحة أعلاه...', + copyDone: '%0% تم نسخه إلى %1%', + copyTo: 'حدد المكان الذي يجب نسخ الوثيقة %0% إليه أدناه', + moveDone: '%0% تم نقله إلى %1%', + moveTo: 'حدد المكان الذي يجب نقل الوثيقة %0% إليه أدناه', + nodeSelected: "تم تحديده كجذر لمحتواك الجديد، انقر على 'موافق' أدناه.", + noNodeSelected: "لم يتم تحديد أي عقدة بعد، يرجى تحديد عقدة في القائمة أعلاه قبل النقر على 'موافق'", + notAllowedByContentType: 'العقدة الحالية غير مسموح بها تحت العقدة المحددة بسبب نوعها', + notAllowedByPath: 'لا يمكن نقل العقدة الحالية إلى إحدى صفحاتها الفرعية، ولا يمكن أن تكون الوالد والوجهة هي نفسها', + notAllowedAtRoot: 'لا يمكن أن توجد العقدة الحالية في الجذر', + notValid: 'لا يُسمح بالإجراء نظرًا لأن لديك أذونات غير كافية على 1 أو أكثر من الوثيقة الفرعية.\n', + relateToOriginal: 'ربط العناصر المنسوخة بالأصل', + }, + notifications: { + editNotifications: 'حدد إشعارك لـ %0%', + notificationsSavedFor: 'تم حفظ إعدادات الإشعارات لـ', + notifications: 'الإشعارات', + }, + packager: { + actions: 'إجراءات', + created: 'أنشئ', + createPackage: 'إنشاء حزمة', + chooseLocalPackageText: + '\n اختر حزمة من جهازك، بالنقر على زر تصفح
      \n وتحديد الحزمة. عادةً ما تحتوي حزم Umbraco على امتداد ".umb" أو ".zip".\n ', + deletewarning: 'سيؤدي ذلك إلى حذف الحزمة', + includeAllChildNodes: 'تضمين جميع العقد الفرعية', + installed: 'مثبتة', + installedPackages: 'الحزم المثبتة', + installInstructions: 'تعليمات التثبيت', + noConfigurationView: 'لا تحتوي هذه الحزمة على عرض تكوين', + noPackagesCreated: 'لم يتم إنشاء أي حزم بعد', + noPackages: 'لم يتم تثبيت أي حزم', + noPackagesDescription: "تصفح الحزم المتاحة باستخدام أيقونة 'الحزم' في أعلى يمين الشاشة", + packageContent: 'محتوى الحزمة', + packageLicense: 'الرخصة', + packageSearch: 'البحث عن الحزم', + packageSearchResults: 'نتائج البحث عن', + packageNoResults: 'لم نجد شيئًا لـ', + packageNoResultsDescription: 'يرجى محاولة البحث عن حزمة أخرى أو تصفح الفئات\n', + packagesPopular: 'الأكثر شيوعًا', + packagesPromoted: 'مروج لها', + packagesNew: 'الإصدارات الجديدة', + packageHas: 'لديه', + packageKarmaPoints: 'نقاط الكارما', + packageInfo: 'معلومات', + packageOwner: 'المالك', + packageContrib: 'المساهمون', + packageCreated: 'أنشئ', + packageCurrentVersion: 'الإصدار الحالي', + packageNetVersion: 'إصدار .NET', + packageDownloads: 'التنزيلات', + packageLikes: 'الإعجابات', + packageCompatibility: 'التوافق', + packageCompatibilityDescription: + 'تكون هذه الحزمة متوافقة مع الإصدارات التالية من Umbraco، حسب\n ما أبلغ عنه أعضاء المجتمع. لا يمكن ضمان التوافق الكامل للإصدارات المبلغ عنها أقل من 100%\n ', + packageExternalSources: 'المصادر الخارجية', + packageAuthor: 'المؤلف', + packageDocumentation: 'الوثائق', + packageMetaData: 'بيانات الحزمة', + packageName: 'اسم الحزمة', + packageNoItemsHeader: 'لا تحتوي الحزمة على أي عناصر', + packageNoItemsText: + 'لا تحتوي هذه الحزمة على أي عناصر لإلغاء التثبيت.

      \n يمكنك إزالة هذا بأمان من النظام بالنقر على "إلغاء تثبيت الحزمة" أدناه.', + packageOptions: 'خيارات الحزمة', + packageMigrationsRun: 'تشغيل ترحيلات الحزمة المعلقة', + packageMigrationsComplete: 'تم إكمال ترحيلات الحزمة بنجاح.', + packageMigrationsNonePending: 'تم إكمال جميع ترحيلات الحزمة بنجاح.', + packageReadme: 'ملف README الخاص بالحزمة', + packageRepository: 'مستودع الحزمة', + packageUninstallConfirm: 'تأكيد إلغاء تثبيت الحزمة', + packageUninstalledHeader: 'تم إلغاء تثبيت الحزمة', + packageUninstalledText: 'تم إلغاء تثبيت الحزمة بنجاح', + packageUninstallHeader: 'إلغاء تثبيت الحزمة', + packageUninstallText: + 'يمكنك إلغاء تحديد العناصر التي لا ترغب في إزالتها في الوقت الحالي أدناه. عند النقر على "تأكيد الإلغاء"، ستتم إزالة جميع العناصر المحددة.
      \n ملاحظة: أي مستندات أو وسائط تعتمد على العناصر التي تقوم بإزالتها، ستتوقف عن العمل، وقد يؤدي ذلك إلى عدم استقرار النظام، لذا قم بإلغاء التثبيت بحذر. إذا كان لديك أي شكوك، اتصل بمؤلف الحزمة.', + packageVersion: 'إصدار الحزمة', + verifiedToWorkOnUmbracoCloud: 'تم التحقق من عمله على Umbraco Cloud', + }, paste: { - doNothing: 'الصق مع التنسيق الكامل (غير موصى به)', - errorMessage: "النص الذي تحاول لصقه يحتوي على أحرف خاصة أو تنسيق. قد يكون ذلك بسبب نسخ النص من Microsoft Word. يمكن لـ Umbraco إزالة الأحرف الخاصة أو التنسيق تلقائيًا، بحيث يكون المحتوى الملصق أكثر ملاءمة للويب.\n", - removeAll: 'الصق كـ نص خام بدون أي تنسيق على الإطلاق', - removeSpecialFormattering: 'الصق، ولكن قم بإزالة التنسيق (موصى به)', - }, - publicAccess: { - paGroups: 'حماية قائمة على المجموعة', - paGroupsHelp: 'إذا كنت ترغب في منح الوصول إلى جميع أعضاء مجموعات الأعضاء المحددة', - paGroupsNoGroups: 'تحتاج إلى إنشاء مجموعة أعضاء قبل أن تتمكن من استخدام المصادقة القائمة على المجموعة', - paErrorPage: 'صفحة الخطأ', - paErrorPageHelp: 'تستخدم عندما يكون الأشخاص مسجلين الدخول، ولكن ليس لديهم وصول', - paHowWould: 'اختر كيفية تقييد الوصول إلى الصفحة %0%', - paIsProtected: '%0% محمية الآن', - paIsRemoved: 'تمت إزالة الحماية من %0%', - paLoginPage: 'صفحة تسجيل الدخول', - paLoginPageHelp: 'اختر الصفحة التي تحتوي على نموذج تسجيل الدخول', - paRemoveProtection: 'إزالة الحماية...', - paRemoveProtectionConfirm: 'هل أنت متأكد أنك تريد إزالة الحماية من الصفحة %0%؟', - paSelectPages: 'اختر الصفحات التي تحتوي على نموذج تسجيل الدخول ورسائل الخطأ', - paSelectGroups: 'اختر المجموعات التي لديها وصول إلى الصفحة %0%', - paSelectMembers: 'اختر الأعضاء الذين لديهم وصول إلى الصفحة %0%', - paMembers: 'حماية الأعضاء المحددين', - paMembersHelp: 'إذا كنت ترغب في منح الوصول إلى أعضاء محددين', - }, - publish: { - invalidPublishBranchPermissions: 'أذونات المستخدم غير كافية لنشر جميع الوثائق التابعة', - contentPublishedFailedIsTrashed: '\n %0% لم يتم نشره لأن العنصر في سلة المهملات.\n ', - contentPublishedFailedAwaitingRelease: '\n %0% لم يتم نشره لأن العنصر مجدول للإصدار.\n ', - contentPublishedFailedExpired: '\n %0% لم يتم نشره لأن العنصر منتهي الصلاحية.\n ', - contentPublishedFailedInvalid: '\n %0% لم يتم نشره لأن بعض الخصائص لم تتجاوز قواعد التحقق.\n ', - contentPublishedFailedByEvent: '\n %0% لم يتم نشره، ألغى ملحق طرف ثالث الإجراء.\n ', - contentPublishedFailedByParent: '\n %0% لا يمكن نشره، لأن صفحة الوالد غير منشورة.\n ', - contentPublishedFailedByMissingName: '%0% لا يمكن نشره، لأنه يفتقر إلى اسم.', - contentPublishedFailedReqCultureValidationError: "فشل التحقق من اللغة المطلوبة '%0%'. تم حفظ هذه اللغة ولكن لم يتم نشرها.\n", - inProgress: 'النشر جارٍ - يرجى الانتظار...', - inProgressCounter: '%0% من أصل %1% صفحات تم نشرها...', - nodePublish: '%0% تم نشره', - nodePublishAll: '%0% والصفحات الفرعية تم نشرها', - publishAll: 'نشر %0% وجميع الصفحات الفرعية الخاصة به', - publishHelp: 'انقر على نشر لنشر %0% وجعل محتواه متاحًا علنًا.

      \n يمكنك نشر هذه الصفحة وجميع صفحاتها الفرعية عن طريق تحديد تضمين الصفحات الفرعية غير المنشورة أدناه.\n ', - }, - colorpicker: { - noColors: 'لم تقم بتكوين أي ألوان معتمدة', - }, - contentPicker: { - allowedItemTypes: 'يمكنك فقط اختيار العناصر من النوع(s): %0%', - defineDynamicRoot: 'حدد الجذر', - defineRootNode: 'اختر جذر العقدة', - pickedTrashedItem: 'لقد اخترت عنصر محتوى محذوف حاليًا أو في سلة المهملات', - pickedTrashedItems: 'لقد اخترت عناصر محتوى محذوفة حاليًا أو في سلة المهملات', - }, - dynamicRoot: { - configurationTitle: 'استعلام الجذر الديناميكي', - pickDynamicRootOriginTitle: 'اختر الأصل', - pickDynamicRootOriginDesc: 'حدد الأصل لاستعلام الجذر الديناميكي الخاص بك', - originRootTitle: 'الجذر', - originRootDesc: 'العقدة الجذرية لجلسة التحرير هذه', - originParentTitle: 'الوالد', - originParentDesc: 'العقدة الأم للمصدر في جلسة التحرير هذه', - originCurrentTitle: 'الحالي', - originCurrentDesc: 'عقدة المحتوى التي هي المصدر لجلسة التحرير هذه', - originSiteTitle: 'الموقع', - originSiteDesc: 'ابحث عن أقرب عقدة بها اسم مضيف', - originByKeyTitle: 'عقدة محددة', - originByKeyDesc: 'اختر عقدة محددة كأصل لهذا الاستعلام', - pickDynamicRootQueryStepTitle: 'أضف خطوة إلى الاستعلام', - pickDynamicRootQueryStepDesc: 'حدد الخطوة التالية لاستعلام الجذر الديناميكي الخاص بك', - queryStepNearestAncestorOrSelfTitle: 'أقرب سلف أو نفس', - queryStepNearestAncestorOrSelfDesc: 'استعلام أقرب سلف أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepFurthestAncestorOrSelfTitle: 'أبعد سلف أو نفس', - queryStepFurthestAncestorOrSelfDesc: 'استعلام أبعد سلف أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepNearestDescendantOrSelfTitle: 'أقرب نسل أو نفس', - queryStepNearestDescendantOrSelfDesc: 'استعلام أقرب نسل أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepFurthestDescendantOrSelfTitle: 'أبعد نسل أو نفس', - queryStepFurthestDescendantOrSelfDesc: 'استعلام أبعد نسل أو نفس يتطابق مع أحد الأنواع المكونة', - queryStepCustomTitle: 'مخصص', - queryStepCustomDesc: 'استعلام باستخدام خطوة استعلام مخصصة', - addQueryStep: 'إضافة خطوة استعلام', - queryStepTypes: 'التي تتطابق مع الأنواع: ', - noValidStartNodeTitle: 'لا توجد محتويات متطابقة', - noValidStartNodeDesc: 'تكوين هذه الخاصية لا يتطابق مع أي محتوى. أنشئ المحتوى المفقود أو اتصل بمسؤولك لضبط إعدادات الجذر الديناميكي لهذه الخاصية.', - }, - mediaPicker: { - deletedItem: 'عنصر محذوف', - pickedTrashedItem: 'لقد اخترت عنصر وسائط محذوف حاليًا أو في سلة المهملات', - pickedTrashedItems: 'لقد اخترت عناصر وسائط محذوفة حاليًا أو في سلة المهملات', - trashed: 'محذوف', - openMedia: 'افتح في مكتبة الوسائط', - changeMedia: 'تغيير عنصر الوسائط', - editMediaEntryLabel: 'تحرير %0% على %1%', - confirmCancelMediaEntryCreationHeadline: 'تجاهل الإنشاء؟', - confirmCancelMediaEntryCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', - confirmCancelMediaEntryHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد\n تجاهلها؟\n ', - confirmRemoveAllMediaEntryMessage: 'إزالة جميع الوسائط؟', - tabClipboard: 'الحافظة', - notAllowed: 'غير مسموح', - openMediaPicker: 'افتح محدد الوسائط', - }, - propertyEditorPicker: { - title: 'اختر محرر الخصائص', - openPropertyEditorPicker: 'اختر واجهة مستخدم محرر الخصائص', - }, - relatedlinks: { - enterExternal: 'أدخل رابط خارجي', - chooseInternal: 'اختر صفحة داخلية', - caption: 'التسمية التوضيحية', - link: 'رابط', - newWindow: 'فتح في نافذة جديدة', - captionPlaceholder: 'أدخل التسمية التوضيحية للعرض', - externalLinkPlaceholder: 'أدخل الرابط', - }, - imagecropper: { - reset: 'إعادة تعيين', - updateEditCrop: 'تم', - undoEditCrop: 'تراجع عن التعديلات', - customCrop: 'مخصص', - }, - rollback: { - changes: 'التغييرات', - created: 'أنشئ', - headline: 'اختر إصدارًا للمقارنة مع الإصدار الحالي', - currentVersion: 'الإصدار الحالي', - diffHelp: 'يظهر هذا الاختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد
      النص الأحمر سيتم حذفه في الإصدار المحدد، النص الأخضر سيتم إضافته', - noDiff: 'لا توجد اختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد', - documentRolledBack: 'تمت استعادة الوثيقة', - htmlHelp: 'يعرض هذا الإصدار المحدد كـ HTML، إذا كنت ترغب في رؤية الفرق بين إصدارين في نفس الوقت، استخدم عرض الفرق\n ', - rollbackTo: 'استعادة إلى', - selectVersion: 'اختر الإصدار', - view: 'عرض', - pagination: 'عرض الإصدار %0% إلى %1% من %2% إصدارات', - versions: 'الإصدارات', - currentDraftVersion: 'الإصدار الحالي المسودة', - currentPublishedVersion: 'الإصدار الحالي المنشور', - }, - scripts: { - editscript: 'تحرير ملف السكربت', - }, - sections: { - content: 'المحتوى', - media: 'الوسائط', - member: 'الأعضاء', - packages: 'الحزم', - marketplace: 'السوق', - settings: 'الإعدادات', - translation: 'القاموس', - users: 'المستخدمون', - }, + doNothing: 'الصق مع التنسيق الكامل (غير موصى به)', + errorMessage: + 'النص الذي تحاول لصقه يحتوي على أحرف خاصة أو تنسيق. قد يكون ذلك بسبب نسخ النص من Microsoft Word. يمكن لـ Umbraco إزالة الأحرف الخاصة أو التنسيق تلقائيًا، بحيث يكون المحتوى الملصق أكثر ملاءمة للويب.\n', + removeAll: 'الصق كـ نص خام بدون أي تنسيق على الإطلاق', + removeSpecialFormattering: 'الصق، ولكن قم بإزالة التنسيق (موصى به)', + }, + publicAccess: { + paGroups: 'حماية قائمة على المجموعة', + paGroupsHelp: 'إذا كنت ترغب في منح الوصول إلى جميع أعضاء مجموعات الأعضاء المحددة', + paGroupsNoGroups: 'تحتاج إلى إنشاء مجموعة أعضاء قبل أن تتمكن من استخدام المصادقة القائمة على المجموعة', + paErrorPage: 'صفحة الخطأ', + paErrorPageHelp: 'تستخدم عندما يكون الأشخاص مسجلين الدخول، ولكن ليس لديهم وصول', + paHowWould: 'اختر كيفية تقييد الوصول إلى الصفحة %0%', + paIsProtected: '%0% محمية الآن', + paIsRemoved: 'تمت إزالة الحماية من %0%', + paLoginPage: 'صفحة تسجيل الدخول', + paLoginPageHelp: 'اختر الصفحة التي تحتوي على نموذج تسجيل الدخول', + paRemoveProtection: 'إزالة الحماية...', + paRemoveProtectionConfirm: 'هل أنت متأكد أنك تريد إزالة الحماية من الصفحة %0%؟', + paSelectPages: 'اختر الصفحات التي تحتوي على نموذج تسجيل الدخول ورسائل الخطأ', + paSelectGroups: 'اختر المجموعات التي لديها وصول إلى الصفحة %0%', + paSelectMembers: 'اختر الأعضاء الذين لديهم وصول إلى الصفحة %0%', + paMembers: 'حماية الأعضاء المحددين', + paMembersHelp: 'إذا كنت ترغب في منح الوصول إلى أعضاء محددين', + }, + publish: { + invalidPublishBranchPermissions: 'أذونات المستخدم غير كافية لنشر جميع الوثائق التابعة', + contentPublishedFailedIsTrashed: '\n %0% لم يتم نشره لأن العنصر في سلة المهملات.\n ', + contentPublishedFailedAwaitingRelease: '\n %0% لم يتم نشره لأن العنصر مجدول للإصدار.\n ', + contentPublishedFailedExpired: '\n %0% لم يتم نشره لأن العنصر منتهي الصلاحية.\n ', + contentPublishedFailedInvalid: '\n %0% لم يتم نشره لأن بعض الخصائص لم تتجاوز قواعد التحقق.\n ', + contentPublishedFailedByEvent: '\n %0% لم يتم نشره، ألغى ملحق طرف ثالث الإجراء.\n ', + contentPublishedFailedByParent: '\n %0% لا يمكن نشره، لأن صفحة الوالد غير منشورة.\n ', + contentPublishedFailedByMissingName: '%0% لا يمكن نشره، لأنه يفتقر إلى اسم.', + contentPublishedFailedReqCultureValidationError: + "فشل التحقق من اللغة المطلوبة '%0%'. تم حفظ هذه اللغة ولكن لم يتم نشرها.\n", + inProgress: 'النشر جارٍ - يرجى الانتظار...', + inProgressCounter: '%0% من أصل %1% صفحات تم نشرها...', + nodePublish: '%0% تم نشره', + nodePublishAll: '%0% والصفحات الفرعية تم نشرها', + publishAll: 'نشر %0% وجميع الصفحات الفرعية الخاصة به', + publishHelp: + 'انقر على نشر لنشر %0% وجعل محتواه متاحًا علنًا.

      \n يمكنك نشر هذه الصفحة وجميع صفحاتها الفرعية عن طريق تحديد تضمين الصفحات الفرعية غير المنشورة أدناه.\n ', + }, + colorpicker: { + noColors: 'لم تقم بتكوين أي ألوان معتمدة', + }, + contentPicker: { + allowedItemTypes: 'يمكنك فقط اختيار العناصر من النوع(s): %0%', + defineDynamicRoot: 'حدد الجذر', + defineRootNode: 'اختر جذر العقدة', + pickedTrashedItem: 'لقد اخترت عنصر محتوى محذوف حاليًا أو في سلة المهملات', + pickedTrashedItems: 'لقد اخترت عناصر محتوى محذوفة حاليًا أو في سلة المهملات', + }, + dynamicRoot: { + configurationTitle: 'استعلام الجذر الديناميكي', + pickDynamicRootOriginTitle: 'اختر الأصل', + pickDynamicRootOriginDesc: 'حدد الأصل لاستعلام الجذر الديناميكي الخاص بك', + originRootTitle: 'الجذر', + originRootDesc: 'العقدة الجذرية لجلسة التحرير هذه', + originParentTitle: 'الوالد', + originParentDesc: 'العقدة الأم للمصدر في جلسة التحرير هذه', + originCurrentTitle: 'الحالي', + originCurrentDesc: 'عقدة المحتوى التي هي المصدر لجلسة التحرير هذه', + originSiteTitle: 'الموقع', + originSiteDesc: 'ابحث عن أقرب عقدة بها اسم مضيف', + originByKeyTitle: 'عقدة محددة', + originByKeyDesc: 'اختر عقدة محددة كأصل لهذا الاستعلام', + pickDynamicRootQueryStepTitle: 'أضف خطوة إلى الاستعلام', + pickDynamicRootQueryStepDesc: 'حدد الخطوة التالية لاستعلام الجذر الديناميكي الخاص بك', + queryStepNearestAncestorOrSelfTitle: 'أقرب سلف أو نفس', + queryStepNearestAncestorOrSelfDesc: 'استعلام أقرب سلف أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepFurthestAncestorOrSelfTitle: 'أبعد سلف أو نفس', + queryStepFurthestAncestorOrSelfDesc: 'استعلام أبعد سلف أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepNearestDescendantOrSelfTitle: 'أقرب نسل أو نفس', + queryStepNearestDescendantOrSelfDesc: 'استعلام أقرب نسل أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepFurthestDescendantOrSelfTitle: 'أبعد نسل أو نفس', + queryStepFurthestDescendantOrSelfDesc: 'استعلام أبعد نسل أو نفس يتطابق مع أحد الأنواع المكونة', + queryStepCustomTitle: 'مخصص', + queryStepCustomDesc: 'استعلام باستخدام خطوة استعلام مخصصة', + addQueryStep: 'إضافة خطوة استعلام', + queryStepTypes: 'التي تتطابق مع الأنواع: ', + noValidStartNodeTitle: 'لا توجد محتويات متطابقة', + noValidStartNodeDesc: + 'تكوين هذه الخاصية لا يتطابق مع أي محتوى. أنشئ المحتوى المفقود أو اتصل بمسؤولك لضبط إعدادات الجذر الديناميكي لهذه الخاصية.', + }, + mediaPicker: { + deletedItem: 'عنصر محذوف', + pickedTrashedItem: 'لقد اخترت عنصر وسائط محذوف حاليًا أو في سلة المهملات', + pickedTrashedItems: 'لقد اخترت عناصر وسائط محذوفة حاليًا أو في سلة المهملات', + trashed: 'محذوف', + openMedia: 'افتح في مكتبة الوسائط', + changeMedia: 'تغيير عنصر الوسائط', + editMediaEntryLabel: 'تحرير %0% على %1%', + confirmCancelMediaEntryCreationHeadline: 'تجاهل الإنشاء؟', + confirmCancelMediaEntryCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', + confirmCancelMediaEntryHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد\n تجاهلها؟\n ', + confirmRemoveAllMediaEntryMessage: 'إزالة جميع الوسائط؟', + tabClipboard: 'الحافظة', + notAllowed: 'غير مسموح', + openMediaPicker: 'افتح محدد الوسائط', + }, + propertyEditorPicker: { + title: 'اختر محرر الخصائص', + openPropertyEditorPicker: 'اختر واجهة مستخدم محرر الخصائص', + }, + relatedlinks: { + enterExternal: 'أدخل رابط خارجي', + chooseInternal: 'اختر صفحة داخلية', + caption: 'التسمية التوضيحية', + link: 'رابط', + newWindow: 'فتح في نافذة جديدة', + captionPlaceholder: 'أدخل التسمية التوضيحية للعرض', + externalLinkPlaceholder: 'أدخل الرابط', + }, + imagecropper: { + reset: 'إعادة تعيين', + updateEditCrop: 'تم', + undoEditCrop: 'تراجع عن التعديلات', + customCrop: 'مخصص', + }, + rollback: { + changes: 'التغييرات', + created: 'أنشئ', + headline: 'اختر إصدارًا للمقارنة مع الإصدار الحالي', + currentVersion: 'الإصدار الحالي', + diffHelp: + 'يظهر هذا الاختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد
      النص الأحمر سيتم حذفه في الإصدار المحدد، النص الأخضر سيتم إضافته', + noDiff: 'لا توجد اختلافات بين الإصدار الحالي (المسودة) والإصدار المحدد', + documentRolledBack: 'تمت استعادة الوثيقة', + htmlHelp: + 'يعرض هذا الإصدار المحدد كـ HTML، إذا كنت ترغب في رؤية الفرق بين إصدارين في نفس الوقت، استخدم عرض الفرق\n ', + rollbackTo: 'استعادة إلى', + selectVersion: 'اختر الإصدار', + view: 'عرض', + pagination: 'عرض الإصدار %0% إلى %1% من %2% إصدارات', + versions: 'الإصدارات', + currentDraftVersion: 'الإصدار الحالي المسودة', + currentPublishedVersion: 'الإصدار الحالي المنشور', + }, + scripts: { + editscript: 'تحرير ملف السكربت', + }, + sections: { + content: 'المحتوى', + media: 'الوسائط', + member: 'الأعضاء', + packages: 'الحزم', + marketplace: 'السوق', + settings: 'الإعدادات', + translation: 'القاموس', + users: 'المستخدمون', + }, help: { - tours: 'الجولات', - theBestUmbracoVideoTutorials: 'أفضل دروس الفيديو في Umbraco', - umbracoForum: 'زيارة our.umbraco.com', - umbracoTv: 'زيارة umbraco.tv', - umbracoLearningBase: 'شاهد دروس الفيديو المجانية لدينا', - umbracoLearningBaseDescription: 'على قاعدة تعلم Umbraco', - }, - settings: { - defaulttemplate: 'القالب الافتراضي', - importDocumentTypeHelp: 'للاستيراد نوع الوثيقة ابحث عن ملف ".udt" على جهاز الكمبيوتر الخاص بك بالنقر على زر "استيراد" (سيُطلب منك تأكيد ذلك في الشاشة التالية)', - newtabname: 'عنوان التبويب الجديد', - nodetype: 'نوع العقدة', - objecttype: 'النوع', - stylesheet: 'ورقة الأنماط', - script: 'السكريبت', - tab: 'التبويب', - tabname: 'عنوان التبويب', - tabs: 'التبويبات', - contentTypeEnabled: 'نوع المحتوى الرئيسي مفعل', - contentTypeUses: 'هذا النوع من المحتوى يستخدم', - noPropertiesDefinedOnTab: 'لا توجد خصائص محددة على هذا التبويب. انقر على رابط "إضافة خاصية جديدة" في الأعلى لإنشاء خاصية جديدة.', - createMatchingTemplate: 'إنشاء قالب مطابق', - addIcon: 'إضافة أيقونة', - }, - sort: { - sortOrder: 'ترتيب الفرز', - sortCreationDate: 'تاريخ الإنشاء', - sortDone: 'تمت عملية الفرز.', - sortHelp: 'اسحب العناصر المختلفة لأعلى أو لأسفل أدناه لتحديد كيفية ترتيبها. أو انقر على رؤوس الأعمدة لفرز جميع العناصر.', - sortPleaseWait: 'يرجى الانتظار. يتم فرز العناصر، قد يستغرق ذلك بعض الوقت.', - sortEmptyState: 'لا تحتوي هذه العقدة على عقدة فرعية لفرزها', - }, - speechBubbles: { - validationFailedHeader: 'التحقق', - validationFailedMessage: 'يجب إصلاح أخطاء التحقق قبل أن يمكن حفظ العنصر', - operationFailedHeader: 'فشل', - operationSavedHeader: 'تم الحفظ', - operationSavedHeaderReloadUser: 'تم الحفظ. لعرض التغييرات، يرجى إعادة تحميل متصفحك', - invalidUserPermissionsText: 'أذونات المستخدم غير كافية، لم نتمكن من إتمام العملية', - operationCancelledHeader: 'ملغي', - operationCancelledText: 'تم إلغاء العملية بواسطة ملحق طرف ثالث', - folderUploadNotAllowed: 'يتم تحميل هذا الملف كجزء من مجلد، ولكن إنشاء مجلد جديد غير مسموح هنا', - folderCreationNotAllowed: 'إنشاء مجلد جديد غير مسموح هنا', - contentTypeDublicatePropertyType: 'نوع الخاصية موجود بالفعل', - contentTypePropertyTypeCreated: 'تم إنشاء نوع الخاصية', - contentTypePropertyTypeCreatedText: 'الاسم: %0%
      نوع البيانات: %1%', - contentTypePropertyTypeDeleted: 'تم حذف نوع الخاصية', - contentTypeSavedHeader: 'تم حفظ نوع الوثيقة', - contentTypeTabCreated: 'تم إنشاء التبويب', - contentTypeTabDeleted: 'تم حذف التبويب', - contentTypeTabDeletedText: 'تم حذف التبويب بالمعرف: %0%', - cssErrorHeader: 'لم يتم حفظ ورقة الأنماط', - cssSavedHeader: 'تم حفظ ورقة الأنماط', - cssSavedText: 'تم حفظ ورقة الأنماط بدون أي أخطاء', - dataTypeSaved: 'تم حفظ نوع البيانات', - dictionaryItemSaved: 'تم حفظ عنصر القاموس', - editContentPublishedHeader: 'تم نشر المحتوى', - editContentPublishedText: 'وهو مرئي على الموقع', - editMultiContentPublishedText: 'تم نشر %0% مستندات وهي مرئية على الموقع', - editVariantPublishedText: '%0% تم نشره وهو مرئي على الموقع', - editMultiVariantPublishedText: '%0% مستندات تم نشرها للغات %1% وهي مرئية على الموقع', - editBlueprintSavedHeader: 'تم حفظ مخطط الوثيقة', - editBlueprintSavedText: 'تم حفظ التغييرات بنجاح', - editContentSavedHeader: 'تم حفظ المحتوى', - editContentSavedText: 'تذكر النشر لجعل التغييرات مرئية', - editContentScheduledSavedText: 'تم تحديث جدول النشر', - editVariantSavedText: '%0% تم حفظه', - editContentSendToPublish: 'تم إرسالها للموافقة', - editContentSendToPublishText: 'تم إرسال التغييرات للموافقة', - editVariantSendToPublishText: '%0% تغييرات تم إرسالها للموافقة', - editMediaSaved: 'تم حفظ الوسائط', - editMediaSavedText: 'تم حفظ الوسائط بدون أي أخطاء', - editMemberSaved: 'تم حفظ العضو', - editStylesheetPropertySaved: 'تم حفظ خاصية ورقة الأنماط', - editStylesheetSaved: 'تم حفظ ورقة الأنماط', - editTemplateSaved: 'تم حفظ القالب', - editUserError: 'حدث خطأ عند حفظ المستخدم (تحقق من السجل)', - editUserSaved: 'تم حفظ المستخدم', - editUserTypeSaved: 'تم حفظ نوع المستخدم', - editUserGroupSaved: 'تم حفظ مجموعة المستخدمين', - editCulturesAndHostnamesSaved: 'تم حفظ الثقافات وأسماء المضيفين', - editCulturesAndHostnamesError: 'حدث خطأ عند حفظ الثقافات وأسماء المضيفين', - fileErrorHeader: 'لم يتم حفظ الملف', - fileErrorText: 'لم يتم حفظ الملف. يرجى التحقق من أذونات الملف', - fileSavedHeader: 'تم حفظ الملف', - fileSavedText: 'تم حفظ الملف بدون أي أخطاء', - languageSaved: 'تم حفظ اللغة', - mediaTypeSavedHeader: 'تم حفظ نوع الوسائط', - memberTypeSavedHeader: 'تم حفظ نوع العضو', - memberGroupSavedHeader: 'تم حفظ مجموعة الأعضاء', - memberGroupNameDuplicate: 'مجموعة أعضاء أخرى بنفس الاسم موجودة بالفعل', - templateErrorHeader: 'لم يتم حفظ القالب', - templateErrorText: 'يرجى التأكد من عدم وجود قالبين بنفس الاسم المستعار', - templateSavedHeader: 'تم حفظ القالب', - templateSavedText: 'تم حفظ القالب بدون أي أخطاء!', - contentUnpublished: 'تم إلغاء نشر المحتوى', - contentCultureUnpublished: 'تم إلغاء نشر التباين %0%', - contentMandatoryCultureUnpublished: "اللغة الإلزامية '%0%' تم إلغاء نشرها. جميع اللغات لهذا العنصر المحتوى أصبحت الآن غير منشورة.", - partialViewSavedHeader: 'تم حفظ العرض الجزئي', - partialViewSavedText: 'تم حفظ العرض الجزئي بدون أي أخطاء!', - partialViewErrorHeader: 'لم يتم حفظ العرض الجزئي', - partialViewErrorText: 'حدث خطأ أثناء حفظ الملف.', - permissionsSavedFor: 'تم حفظ الأذونات لـ', - deleteUserGroupsSuccess: 'تم حذف %0% مجموعات مستخدمين', - deleteUserGroupSuccess: '%0% تم حذفه', - enableUsersSuccess: 'تم تفعيل %0% مستخدمين', - disableUsersSuccess: 'تم تعطيل %0% مستخدمين', - enableUserSuccess: '%0% تم تفعيله الآن', - disableUserSuccess: '%0% تم تعطيله الآن', - setUserGroupOnUsersSuccess: 'تم تعيين مجموعات المستخدمين', - unlockUsersSuccess: 'تم فك قفل %0% مستخدمين', - unlockUserSuccess: '%0% تم فك قفله الآن', - memberExportedSuccess: 'تم تصدير العضو إلى ملف', - memberExportedError: 'حدث خطأ أثناء تصدير العضو', - deleteUserSuccess: 'تم حذف المستخدم %0%', - resendInviteHeader: 'دعوة المستخدم', - resendInviteSuccess: 'تم إعادة إرسال الدعوة إلى %0%', - contentReqCulturePublishError: "لا يمكن نشر الوثيقة لأن '%0%' المطلوب غير منشور", - contentCultureValidationError: "فشل التحقق من اللغة '%0%'", - documentTypeExportedSuccess: 'تم تصدير نوع الوثيقة إلى ملف', - documentTypeExportedError: 'حدث خطأ أثناء تصدير نوع الوثيقة', - dictionaryItemExportedSuccess: 'تم تصدير عنصر (عناصر) القاموس إلى ملف', - dictionaryItemExportedError: 'حدث خطأ أثناء تصدير عنصر (عناصر) القاموس', - dictionaryItemImported: 'تم استيراد عنصر (عناصر) القاموس التالية!', - scheduleErrReleaseDate1: 'تاريخ الإصدار لا يمكن أن يكون في الماضي', - scheduleErrReleaseDate2: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب غير منشور", - scheduleErrReleaseDate3: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب له تاريخ نشر لاحق من لغة غير إلزامية", - scheduleErrExpireDate1: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون في الماضي', - scheduleErrExpireDate2: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون قبل تاريخ الإصدار', - publishWithNoDomains: 'لم يتم تكوين النطاقات لموقع متعدد اللغات، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', - publishWithMissingDomain: 'لا يوجد مجال مكون لـ %0%، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', - preventCleanupEnableError: 'حدث خطأ أثناء تمكين تنظيف الإصدارات لـ %0%', - preventCleanupDisableError: 'حدث خطأ أثناء تعطيل تنظيف الإصدارات لـ %0%', - copySuccessMessage: 'تم نسخ معلومات النظام الخاصة بك بنجاح إلى الحافظة', - cannotCopyInformation: 'لم نتمكن من نسخ معلومات النظام الخاصة بك إلى الحافظة', - }, - stylesheet: { - addRule: 'إضافة نمط', - editRule: 'تعديل النمط', - editorRules: 'أنماط محرر النصوص الغني', - editorRulesHelp: 'حدد الأنماط التي يجب أن تكون متاحة في محرر النصوص الغني لهذه ورقة الأنماط', - editstylesheet: 'تعديل ورقة الأنماط', - editstylesheetproperty: 'تعديل خاصية ورقة الأنماط', - nameHelp: 'الاسم المعروض في قائمة اختيار الأنماط في المحرر', - preview: 'معاينة', - previewHelp: 'كيف سيبدو النص في محرر النصوص الغني.', - selector: 'المحدد', - selectorHelp: 'يستخدم بناء جملة CSS، على سبيل المثال "h1" أو ".redHeader"', - styles: 'الأنماط', - stylesHelp: 'CSS الذي يجب تطبيقه في محرر النصوص الغني، على سبيل المثال "color:red;"', - tabCode: 'الكود', - tabRules: 'محرر النصوص الغني', - }, - template: { - runtimeModeProduction: 'المحتوى غير قابل للتحرير عند استخدام وضع التشغيل Production.', - deleteByIdFailed: 'فشل في حذف القالب بالمعرف %0%', - edittemplate: 'تعديل القالب', - insertSections: 'الأقسام', - insertContentArea: 'إدراج منطقة المحتوى', - insertContentAreaPlaceHolder: 'إدراج عنصر نائبة لمنطقة المحتوى', - insert: 'إدراج', - insertDesc: 'اختر ما تريد إدراجه في قالبك', - insertDictionaryItem: 'عنصر القاموس', - insertDictionaryItemDesc: 'عنصر القاموس هو عنصر نائبة لنص قابل للترجمة، مما يسهل إنشاء تصميمات لمواقع متعددة اللغات.', - insertMacro: 'ماكرو', - insertMacroDesc: 'ماكرو هو مكون قابل للتكوين رائع للأجزاء القابلة لإعادة الاستخدام من التصميم الخاص بك، حيث تحتاج إلى خيار لتوفير معلمات، مثل المعارض والنماذج والقوائم.', - insertPageField: 'القيمة', - insertPageFieldDesc: 'يعرض قيمة حقل مسمى من الصفحة الحالية، مع خيارات لتعديل القيمة أو الرجوع إلى القيم البديلة.', - insertPartialView: 'عرض جزئي', - insertPartialViewDesc: 'العرض الجزئي هو ملف قالب منفصل يمكن عرضه داخل قالب آخر، وهو رائع لإعادة استخدام الترميز أو لفصل القوالب المعقدة إلى ملفات منفصلة.', - mastertemplate: 'القالب الرئيسي', - noMaster: 'لا يوجد رئيسي', - renderBody: 'عرض القالب الفرعي', - renderBodyDesc: 'يعرض محتويات القالب الفرعي، من خلال إدراج عنصر نائبة @RenderBody().', - defineSection: 'تحديد قسم مسمى', - defineSectionDesc: 'يحدد جزء من القالب كقسم مسمى عن طريق لفه في @section { ... }. يمكن عرض هذا في منطقة محددة من القالب الرئيسي لهذا القالب، باستخدام @RenderSection.', - renderSection: 'عرض قسم مسمى', - renderSectionDesc: 'يعرض منطقة مسمى من قالب فرعي، من خلال إدراج عنصر نائبة @RenderSection(name). هذا يعرض منطقة من قالب فرعي والتي يتم لفها في تعريف @section [name]{ ... } المقابل.', - sectionName: 'اسم القسم', - sectionMandatory: 'القسم إلزامي', - sectionMandatoryDesc: 'إذا كان إلزاميًا، يجب أن يحتوي القالب الفرعي على تعريف @section، خلاف ذلك يتم عرض خطأ.', - queryBuilder: 'باني الاستعلام', - itemsReturned: 'العناصر التي تم إرجاعها، في', - iWant: 'أريد', - allContent: 'جميع المحتويات', - contentOfType: 'محتوى من نوع "%0%"', - from: 'من', - websiteRoot: 'موقعي', - where: 'حيث', - and: 'و', - is: 'هو', - isNot: 'ليس', - before: 'قبل', - beforeIncDate: 'قبل (بما في ذلك التاريخ المحدد)', - after: 'بعد', - afterIncDate: 'بعد (بما في ذلك التاريخ المحدد)', - equals: 'يساوي', - doesNotEqual: 'لا يساوي', - contains: 'يحتوي على', - doesNotContain: 'لا يحتوي على', - greaterThan: 'أكبر من', - greaterThanEqual: 'أكبر من أو يساوي', - lessThan: 'أقل من', - lessThanEqual: 'أقل من أو يساوي', - id: 'المعرف', - name: 'الاسم', - createdDate: 'تاريخ الإنشاء', - lastUpdatedDate: 'تاريخ آخر تحديث', - orderBy: 'ترتيب حسب', - ascending: 'تصاعدي', - descending: 'تنازلي', - template: 'القالب', - }, + tours: 'الجولات', + theBestUmbracoVideoTutorials: 'أفضل دروس الفيديو في Umbraco', + umbracoForum: 'زيارة our.umbraco.com', + umbracoTv: 'زيارة umbraco.tv', + umbracoLearningBase: 'شاهد دروس الفيديو المجانية لدينا', + umbracoLearningBaseDescription: 'على قاعدة تعلم Umbraco', + }, + settings: { + defaulttemplate: 'القالب الافتراضي', + importDocumentTypeHelp: + 'للاستيراد نوع الوثيقة ابحث عن ملف ".udt" على جهاز الكمبيوتر الخاص بك بالنقر على زر "استيراد" (سيُطلب منك تأكيد ذلك في الشاشة التالية)', + newtabname: 'عنوان التبويب الجديد', + nodetype: 'نوع العقدة', + objecttype: 'النوع', + stylesheet: 'ورقة الأنماط', + script: 'السكريبت', + tab: 'التبويب', + tabname: 'عنوان التبويب', + tabs: 'التبويبات', + contentTypeEnabled: 'نوع المحتوى الرئيسي مفعل', + contentTypeUses: 'هذا النوع من المحتوى يستخدم', + noPropertiesDefinedOnTab: + 'لا توجد خصائص محددة على هذا التبويب. انقر على رابط "إضافة خاصية جديدة" في الأعلى لإنشاء خاصية جديدة.', + createMatchingTemplate: 'إنشاء قالب مطابق', + addIcon: 'إضافة أيقونة', + }, + sort: { + sortOrder: 'ترتيب الفرز', + sortCreationDate: 'تاريخ الإنشاء', + sortDone: 'تمت عملية الفرز.', + sortHelp: + 'اسحب العناصر المختلفة لأعلى أو لأسفل أدناه لتحديد كيفية ترتيبها. أو انقر على رؤوس الأعمدة لفرز جميع العناصر.', + sortPleaseWait: 'يرجى الانتظار. يتم فرز العناصر، قد يستغرق ذلك بعض الوقت.', + sortEmptyState: 'لا تحتوي هذه العقدة على عقدة فرعية لفرزها', + }, + speechBubbles: { + validationFailedHeader: 'التحقق', + validationFailedMessage: 'يجب إصلاح أخطاء التحقق قبل أن يمكن حفظ العنصر', + operationFailedHeader: 'فشل', + operationSavedHeader: 'تم الحفظ', + operationSavedHeaderReloadUser: 'تم الحفظ. لعرض التغييرات، يرجى إعادة تحميل متصفحك', + invalidUserPermissionsText: 'أذونات المستخدم غير كافية، لم نتمكن من إتمام العملية', + operationCancelledHeader: 'ملغي', + operationCancelledText: 'تم إلغاء العملية بواسطة ملحق طرف ثالث', + folderUploadNotAllowed: 'يتم تحميل هذا الملف كجزء من مجلد، ولكن إنشاء مجلد جديد غير مسموح هنا', + folderCreationNotAllowed: 'إنشاء مجلد جديد غير مسموح هنا', + contentTypeDublicatePropertyType: 'نوع الخاصية موجود بالفعل', + contentTypePropertyTypeCreated: 'تم إنشاء نوع الخاصية', + contentTypePropertyTypeCreatedText: 'الاسم: %0%
      نوع البيانات: %1%', + contentTypePropertyTypeDeleted: 'تم حذف نوع الخاصية', + contentTypeSavedHeader: 'تم حفظ نوع الوثيقة', + contentTypeTabCreated: 'تم إنشاء التبويب', + contentTypeTabDeleted: 'تم حذف التبويب', + contentTypeTabDeletedText: 'تم حذف التبويب بالمعرف: %0%', + cssErrorHeader: 'لم يتم حفظ ورقة الأنماط', + cssSavedHeader: 'تم حفظ ورقة الأنماط', + cssSavedText: 'تم حفظ ورقة الأنماط بدون أي أخطاء', + dataTypeSaved: 'تم حفظ نوع البيانات', + dictionaryItemSaved: 'تم حفظ عنصر القاموس', + editContentPublishedHeader: 'تم نشر المحتوى', + editContentPublishedText: 'وهو مرئي على الموقع', + editMultiContentPublishedText: 'تم نشر %0% مستندات وهي مرئية على الموقع', + editVariantPublishedText: '%0% تم نشره وهو مرئي على الموقع', + editMultiVariantPublishedText: '%0% مستندات تم نشرها للغات %1% وهي مرئية على الموقع', + editBlueprintSavedHeader: 'تم حفظ مخطط الوثيقة', + editBlueprintSavedText: 'تم حفظ التغييرات بنجاح', + editContentSavedHeader: 'تم حفظ المحتوى', + editContentSavedText: 'تذكر النشر لجعل التغييرات مرئية', + editContentScheduledSavedText: 'تم تحديث جدول النشر', + editVariantSavedText: '%0% تم حفظه', + editContentSendToPublish: 'تم إرسالها للموافقة', + editContentSendToPublishText: 'تم إرسال التغييرات للموافقة', + editVariantSendToPublishText: '%0% تغييرات تم إرسالها للموافقة', + editMediaSaved: 'تم حفظ الوسائط', + editMediaSavedText: 'تم حفظ الوسائط بدون أي أخطاء', + editMemberSaved: 'تم حفظ العضو', + editStylesheetPropertySaved: 'تم حفظ خاصية ورقة الأنماط', + editStylesheetSaved: 'تم حفظ ورقة الأنماط', + editTemplateSaved: 'تم حفظ القالب', + editUserError: 'حدث خطأ عند حفظ المستخدم (تحقق من السجل)', + editUserSaved: 'تم حفظ المستخدم', + editUserTypeSaved: 'تم حفظ نوع المستخدم', + editUserGroupSaved: 'تم حفظ مجموعة المستخدمين', + editCulturesAndHostnamesSaved: 'تم حفظ الثقافات وأسماء المضيفين', + editCulturesAndHostnamesError: 'حدث خطأ عند حفظ الثقافات وأسماء المضيفين', + fileErrorHeader: 'لم يتم حفظ الملف', + fileErrorText: 'لم يتم حفظ الملف. يرجى التحقق من أذونات الملف', + fileSavedHeader: 'تم حفظ الملف', + fileSavedText: 'تم حفظ الملف بدون أي أخطاء', + languageSaved: 'تم حفظ اللغة', + mediaTypeSavedHeader: 'تم حفظ نوع الوسائط', + memberTypeSavedHeader: 'تم حفظ نوع العضو', + memberGroupSavedHeader: 'تم حفظ مجموعة الأعضاء', + memberGroupNameDuplicate: 'مجموعة أعضاء أخرى بنفس الاسم موجودة بالفعل', + templateErrorHeader: 'لم يتم حفظ القالب', + templateErrorText: 'يرجى التأكد من عدم وجود قالبين بنفس الاسم المستعار', + templateSavedHeader: 'تم حفظ القالب', + templateSavedText: 'تم حفظ القالب بدون أي أخطاء!', + contentUnpublished: 'تم إلغاء نشر المحتوى', + contentCultureUnpublished: 'تم إلغاء نشر التباين %0%', + contentMandatoryCultureUnpublished: + "اللغة الإلزامية '%0%' تم إلغاء نشرها. جميع اللغات لهذا العنصر المحتوى أصبحت الآن غير منشورة.", + partialViewSavedHeader: 'تم حفظ العرض الجزئي', + partialViewSavedText: 'تم حفظ العرض الجزئي بدون أي أخطاء!', + partialViewErrorHeader: 'لم يتم حفظ العرض الجزئي', + partialViewErrorText: 'حدث خطأ أثناء حفظ الملف.', + permissionsSavedFor: 'تم حفظ الأذونات لـ', + deleteUserGroupsSuccess: 'تم حذف %0% مجموعات مستخدمين', + deleteUserGroupSuccess: '%0% تم حذفه', + enableUsersSuccess: 'تم تفعيل %0% مستخدمين', + disableUsersSuccess: 'تم تعطيل %0% مستخدمين', + enableUserSuccess: '%0% تم تفعيله الآن', + disableUserSuccess: '%0% تم تعطيله الآن', + setUserGroupOnUsersSuccess: 'تم تعيين مجموعات المستخدمين', + unlockUsersSuccess: 'تم فك قفل %0% مستخدمين', + unlockUserSuccess: '%0% تم فك قفله الآن', + memberExportedSuccess: 'تم تصدير العضو إلى ملف', + memberExportedError: 'حدث خطأ أثناء تصدير العضو', + deleteUserSuccess: 'تم حذف المستخدم %0%', + resendInviteHeader: 'دعوة المستخدم', + resendInviteSuccess: 'تم إعادة إرسال الدعوة إلى %0%', + contentReqCulturePublishError: "لا يمكن نشر الوثيقة لأن '%0%' المطلوب غير منشور", + contentCultureValidationError: "فشل التحقق من اللغة '%0%'", + documentTypeExportedSuccess: 'تم تصدير نوع الوثيقة إلى ملف', + documentTypeExportedError: 'حدث خطأ أثناء تصدير نوع الوثيقة', + dictionaryItemExportedSuccess: 'تم تصدير عنصر (عناصر) القاموس إلى ملف', + dictionaryItemExportedError: 'حدث خطأ أثناء تصدير عنصر (عناصر) القاموس', + dictionaryItemImported: 'تم استيراد عنصر (عناصر) القاموس التالية!', + scheduleErrReleaseDate1: 'تاريخ الإصدار لا يمكن أن يكون في الماضي', + scheduleErrReleaseDate2: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب غير منشور", + scheduleErrReleaseDate3: "لا يمكن جدولة الوثيقة للنشر لأن '%0%' المطلوب له تاريخ نشر لاحق من لغة غير إلزامية", + scheduleErrExpireDate1: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون في الماضي', + scheduleErrExpireDate2: 'تاريخ انتهاء الصلاحية لا يمكن أن يكون قبل تاريخ الإصدار', + publishWithNoDomains: + 'لم يتم تكوين النطاقات لموقع متعدد اللغات، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', + publishWithMissingDomain: 'لا يوجد مجال مكون لـ %0%، يرجى الاتصال بالمسؤول، راجع السجل لمزيد من المعلومات', + preventCleanupEnableError: 'حدث خطأ أثناء تمكين تنظيف الإصدارات لـ %0%', + preventCleanupDisableError: 'حدث خطأ أثناء تعطيل تنظيف الإصدارات لـ %0%', + copySuccessMessage: 'تم نسخ معلومات النظام الخاصة بك بنجاح إلى الحافظة', + cannotCopyInformation: 'لم نتمكن من نسخ معلومات النظام الخاصة بك إلى الحافظة', + }, + stylesheet: { + addRule: 'إضافة نمط', + editRule: 'تعديل النمط', + editorRules: 'أنماط محرر النصوص الغني', + editorRulesHelp: 'حدد الأنماط التي يجب أن تكون متاحة في محرر النصوص الغني لهذه ورقة الأنماط', + editstylesheet: 'تعديل ورقة الأنماط', + editstylesheetproperty: 'تعديل خاصية ورقة الأنماط', + nameHelp: 'الاسم المعروض في قائمة اختيار الأنماط في المحرر', + preview: 'معاينة', + previewHelp: 'كيف سيبدو النص في محرر النصوص الغني.', + selector: 'المحدد', + selectorHelp: 'يستخدم بناء جملة CSS، على سبيل المثال "h1" أو ".redHeader"', + styles: 'الأنماط', + stylesHelp: 'CSS الذي يجب تطبيقه في محرر النصوص الغني، على سبيل المثال "color:red;"', + tabCode: 'الكود', + tabRules: 'محرر النصوص الغني', + }, + template: { + runtimeModeProduction: 'المحتوى غير قابل للتحرير عند استخدام وضع التشغيل Production.', + deleteByIdFailed: 'فشل في حذف القالب بالمعرف %0%', + edittemplate: 'تعديل القالب', + insertSections: 'الأقسام', + insertContentArea: 'إدراج منطقة المحتوى', + insertContentAreaPlaceHolder: 'إدراج عنصر نائبة لمنطقة المحتوى', + insert: 'إدراج', + insertDesc: 'اختر ما تريد إدراجه في قالبك', + insertDictionaryItem: 'عنصر القاموس', + insertDictionaryItemDesc: + 'عنصر القاموس هو عنصر نائبة لنص قابل للترجمة، مما يسهل إنشاء تصميمات لمواقع متعددة اللغات.', + insertMacro: 'ماكرو', + insertMacroDesc: + 'ماكرو هو مكون قابل للتكوين رائع للأجزاء القابلة لإعادة الاستخدام من التصميم الخاص بك، حيث تحتاج إلى خيار لتوفير معلمات، مثل المعارض والنماذج والقوائم.', + insertPageField: 'القيمة', + insertPageFieldDesc: 'يعرض قيمة حقل مسمى من الصفحة الحالية، مع خيارات لتعديل القيمة أو الرجوع إلى القيم البديلة.', + insertPartialView: 'عرض جزئي', + insertPartialViewDesc: + 'العرض الجزئي هو ملف قالب منفصل يمكن عرضه داخل قالب آخر، وهو رائع لإعادة استخدام الترميز أو لفصل القوالب المعقدة إلى ملفات منفصلة.', + mastertemplate: 'القالب الرئيسي', + noMaster: 'لا يوجد رئيسي', + renderBody: 'عرض القالب الفرعي', + renderBodyDesc: 'يعرض محتويات القالب الفرعي، من خلال إدراج عنصر نائبة @RenderBody().', + defineSection: 'تحديد قسم مسمى', + defineSectionDesc: + 'يحدد جزء من القالب كقسم مسمى عن طريق لفه في @section { ... }. يمكن عرض هذا في منطقة محددة من القالب الرئيسي لهذا القالب، باستخدام @RenderSection.', + renderSection: 'عرض قسم مسمى', + renderSectionDesc: + 'يعرض منطقة مسمى من قالب فرعي، من خلال إدراج عنصر نائبة @RenderSection(name). هذا يعرض منطقة من قالب فرعي والتي يتم لفها في تعريف @section [name]{ ... } المقابل.', + sectionName: 'اسم القسم', + sectionMandatory: 'القسم إلزامي', + sectionMandatoryDesc: + 'إذا كان إلزاميًا، يجب أن يحتوي القالب الفرعي على تعريف @section، خلاف ذلك يتم عرض خطأ.', + queryBuilder: 'باني الاستعلام', + itemsReturned: 'العناصر التي تم إرجاعها، في', + iWant: 'أريد', + allContent: 'جميع المحتويات', + contentOfType: 'محتوى من نوع "%0%"', + from: 'من', + websiteRoot: 'موقعي', + where: 'حيث', + and: 'و', + is: 'هو', + isNot: 'ليس', + before: 'قبل', + beforeIncDate: 'قبل (بما في ذلك التاريخ المحدد)', + after: 'بعد', + afterIncDate: 'بعد (بما في ذلك التاريخ المحدد)', + equals: 'يساوي', + doesNotEqual: 'لا يساوي', + contains: 'يحتوي على', + doesNotContain: 'لا يحتوي على', + greaterThan: 'أكبر من', + greaterThanEqual: 'أكبر من أو يساوي', + lessThan: 'أقل من', + lessThanEqual: 'أقل من أو يساوي', + id: 'المعرف', + name: 'الاسم', + createdDate: 'تاريخ الإنشاء', + lastUpdatedDate: 'تاريخ آخر تحديث', + orderBy: 'ترتيب حسب', + ascending: 'تصاعدي', + descending: 'تنازلي', + template: 'القالب', + }, grid: { - media: 'صورة', - macro: 'ماكرو', - insertControl: 'اختر نوع المحتوى', - chooseLayout: 'اختر تخطيطاً', - addRows: 'أضف صفاً', - addElement: 'أضف محتوى', - dropElement: 'إسقاط المحتوى', - settingsApplied: 'تم تطبيق الإعدادات', - contentNotAllowed: 'هذا المحتوى غير مسموح به هنا', - contentAllowed: 'هذا المحتوى مسموح به هنا', - clickToEmbed: 'انقر للتضمين', - clickToInsertImage: 'انقر لإدراج صورة', - clickToInsertMacro: 'انقر لإدراج ماكرو', - placeholderWriteHere: 'اكتب هنا...', - gridLayouts: 'تخطيطات الشبكة', - gridLayoutsDetail: 'التخطيطات هي منطقة العمل العامة لمحرر الشبكة، وعادةً ما تحتاج فقط إلى واحد أو اثنين من التخطيطات المختلفة', - addGridLayout: 'إضافة تخطيط شبكة', - editGridLayout: 'تعديل تخطيط الشبكة', - addGridLayoutDetail: 'ضبط التخطيط من خلال تعيين عرض الأعمدة وإضافة أقسام إضافية', - rowConfigurations: 'تكوينات الصفوف', - rowConfigurationsDetail: 'الصفوف هي خلايا محددة مسبقاً مرتبة أفقياً', - addRowConfiguration: 'إضافة تكوين صف', - editRowConfiguration: 'تعديل تكوين الصف', - addRowConfigurationDetail: 'ضبط الصف من خلال تعيين عرض الخلايا وإضافة خلايا إضافية', - noConfiguration: 'لا يوجد تكوين إضافي متاح', - columns: 'الأعمدة', - columnsDetails: 'إجمالي عدد الأعمدة في تخطيط الشبكة', - settings: 'الإعدادات', - settingsDetails: 'تكوين الإعدادات التي يمكن للمحررين تغييرها', - styles: 'الأنماط', - stylesDetails: 'تكوين التنسيق الذي يمكن للمحررين تغييره', - allowAllEditors: 'السماح لجميع المحررين', - allowAllRowConfigurations: 'السماح بجميع تكوينات الصفوف', - maxItems: 'الحد الأقصى للعناصر', - maxItemsDescription: 'اتركه فارغًا أو اضبطه على 0 لغير المحدود', - setAsDefault: 'تعيين كافتراضي', - chooseExtra: 'اختر إضافي', - chooseDefault: 'اختر افتراضي', - areAdded: 'تمت إضافتها', - warning: 'تحذير', - warningText: '

      تعديل اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.

      تعديل التسمية فقط لن يؤدي إلى فقدان البيانات.

      ', - youAreDeleting: 'أنت تقوم بحذف تكوين الصف', - deletingARow: '\n حذف اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا\n التكوين.\n ', - deleteLayout: 'أنت تقوم بحذف التخطيط', - deletingALayout: 'تعديل التخطيط سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.\n ', - }, - contentTypeEditor: { - compositions: 'التركيبات', - group: 'مجموعة', - groupReorderSameAliasError: 'لا يمكنك نقل المجموعة %0% إلى هذا التبويب لأن المجموعة ستأخذ نفس الاسم المستعار كالتبويب: "%1%". قم بإعادة تسمية المجموعة للمتابعة.\n ', - noGroups: 'لم تقم بإضافة أي مجموعات', - addGroup: 'إضافة مجموعة', - inheritedFrom: 'موروث من', - addProperty: 'إضافة خاصية', - editProperty: 'تعديل الخاصية', - requiredLabel: 'التسمية المطلوبة', - enableListViewHeading: 'تمكين عرض القائمة', - enableListViewDescription: 'تكوين العنصر لعرض قائمة قابلة للفرز والبحث من أبنائه.', - allowedTemplatesHeading: 'القوالب المسموح بها', - allowedTemplatesDescription: 'اختر القوالب التي يُسمح للمحررين باستخدامها على محتوى من هذا النوع', - allowAtRootHeading: 'السماح في الجذر', - allowAtRootDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع في جذر شجرة المحتوى.\n ', - childNodesHeading: 'أنواع العقد الفرعية المسموح بها', - childNodesDescription: 'السماح بإنشاء محتوى من الأنواع المحددة أسفل محتوى من هذا النوع.', - chooseChildNode: 'اختر العقدة الفرعية', - compositionsDescription: 'ارث التبويبات والخصائص من نوع مستند موجود. سيتم إضافة التبويبات الجديدة إلى نوع الوثيقة الحالي أو دمجها إذا كان هناك تبويب بنفس الاسم.', - compositionInUse: 'هذا النوع من المحتوى قيد الاستخدام في تركيب، وبالتالي لا يمكن تركيبه بنفسه.\n ', - noAvailableCompositions: 'لا توجد أنواع محتوى متاحة لاستخدامها كتركيب.', - compositionRemoveWarning: 'إزالة التركيب ستؤدي إلى حذف جميع بيانات الخصائص المرتبطة. بمجرد حفظ نوع الوثيقة لا يوجد طريق للعودة.', - availableEditors: 'إنشاء جديد', - reuse: 'استخدام موجود', - editorSettings: 'إعدادات المحرر', - searchResultSettings: 'الإعدادات المتاحة', - searchResultEditors: 'إنشاء تكوين جديد', - configuration: 'التكوين', - yesDelete: 'نعم، احذف', - movedUnderneath: 'تم نقله تحت', - copiedUnderneath: 'تم نسخه تحت', - folderToMove: 'اختر المجلد للتحريك', - folderToCopy: 'اختر المجلد للنسخ', - structureBelow: 'إلى هيكل الشجرة أدناه', - allDocumentTypes: 'جميع أنواع الوثائق', - allDocuments: 'جميع الوثائق', - allMediaItems: 'جميع العناصر الإعلامية', - usingThisDocument: 'استخدام هذا النوع من الوثائق سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', - usingThisMedia: 'استخدام هذا النوع من الوسائط سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', - usingThisMember: 'استخدام هذا النوع من الأعضاء سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا\n ', - andAllDocuments: 'وجميع الوثائق التي تستخدم هذا النوع', - andAllMediaItems: 'وجميع العناصر الإعلامية التي تستخدم هذا النوع', - andAllMembers: 'وجميع الأعضاء الذين يستخدمون هذا النوع', - memberCanEdit: 'يمكن للعضو التعديل', - memberCanEditDescription: 'السماح بتعديل قيمة هذه الخاصية من قبل العضو في صفحة ملفه الشخصي\n ', - isSensitiveData: 'بيانات حساسة', - isSensitiveDataDescription: 'إخفاء قيمة هذه الخاصية عن محرري المحتوى الذين لا يملكون حق الوصول لعرض المعلومات الحساسة\n ', - showOnMemberProfile: 'عرض على ملف العضو', - showOnMemberProfileDescription: 'السماح بعرض قيمة هذه الخاصية في صفحة ملف العضو\n ', - tabHasNoSortOrder: 'التبويب ليس له ترتيب فرز', - compositionUsageHeading: 'أين يتم استخدام هذا التركيب؟', - compositionUsageSpecification: 'يتم استخدام هذا التركيب حاليًا في تركيب أنواع المحتوى التالية:\n ', - variantsHeading: 'السماح بالاختلافات', - cultureVariantHeading: 'السماح بالاختلاف حسب الثقافة', - segmentVariantHeading: 'السماح بالتجزئة', - cultureVariantLabel: 'الاختلاف حسب الثقافة', - segmentVariantLabel: 'الاختلاف حسب القطاعات', - variantsDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع بلغات مختلفة.', - cultureVariantDescription: 'السماح للمحررين بإنشاء محتوى بلغات مختلفة.', - segmentVariantDescription: 'السماح للمحررين بإنشاء قطاعات من هذا المحتوى.', - allowVaryByCulture: 'السماح بالاختلاف حسب الثقافة', - allowVaryBySegment: 'السماح بالتجزئة', - elementType: 'نوع العنصر', - elementHeading: 'هو نوع عنصر', - elementDescription: 'نوع العنصر مخصص للاستخدام ضمن أنواع مستندات أخرى، وليس في شجرة المحتوى.\n ', - elementCannotToggle: 'لا يمكن تغيير نوع مستند إلى نوع عنصر بمجرد أن يتم استخدامه لإنشاء عنصر أو أكثر من محتوى.\n ', - elementDoesNotSupport: 'هذا غير قابل للتطبيق لنوع العنصر', - propertyHasChanges: 'لقد أجريت تغييرات على هذه الخاصية. هل أنت متأكد أنك تريد التخلص منها؟', - displaySettingsHeadline: 'المظهر', - displaySettingsLabelOnTop: 'التسمية في الأعلى (عرض كامل)', - confirmDeleteTabMessage: 'هل أنت متأكد أنك تريد حذف التبويب %0%؟', - confirmDeleteGroupMessage: 'هل أنت متأكد أنك تريد حذف المجموعة %0%؟', - confirmDeletePropertyMessage: 'هل أنت متأكد أنك تريد حذف الخاصية %0%؟', - confirmDeleteTabNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذا التبويب.', - confirmDeleteGroupNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذه المجموعة.', - addTab: 'إضافة تبويب', - convertToTab: 'تحويل إلى تبويب', - tabDirectPropertiesDropZone: 'اسحب الخصائص هنا لوضعها مباشرة على التبويب', - removeChildNode: 'أنت تقوم بإزالة العقدة الفرعية', - removeChildNodeWarning: 'إزالة عقدة فرعية ستحد من خيارات المحررين لإنشاء أنواع محتوى مختلفة أسفل عقدة.', - usingEditor: 'استخدام هذا المحرر سيتم تحديثه بالإعدادات الجديدة.', - historyCleanupHeading: 'تنظيف السجل', - historyCleanupDescription: 'السماح بتجاوز الإعدادات العالمية لتنظيف السجل.', - historyCleanupKeepAllVersionsNewerThanDays: 'احتفظ بجميع الإصدارات الأحدث من الأيام', - historyCleanupKeepLatestVersionPerDayForDays: 'احتفظ بأحدث إصدار لكل يوم لعدد من الأيام', - historyCleanupPreventCleanup: 'منع التنظيف', - historyCleanupEnableCleanup: 'تمكين التنظيف', - historyCleanupGloballyDisabled: 'ملاحظة! تنظيف إصدارات المحتوى التاريخية معطل عالميًا. لن تكون هذه الإعدادات فعالة حتى يتم تمكينها.', - changeDataTypeHelpText: 'تغيير نوع البيانات مع القيم المخزنة معطل. للسماح بذلك، يمكنك تغيير إعداد Umbraco:CMS:DataTypes:CanBeChanged في appsettings.json.', - collections: 'المجموعات', - collectionsDescription: 'تكوين العنصر لعرض قائمة بأبنائه.', - structure: 'الهيكل', - presentation: 'العرض', - }, - languages: { - addLanguage: 'إضافة لغة', - culture: 'رمز ISO', - mandatoryLanguage: 'اللغة الإلزامية', - mandatoryLanguageHelp: 'يجب ملء الخصائص في هذه اللغة قبل أن يتم نشر العقدة.\n ', - defaultLanguage: 'اللغة الافتراضية', - defaultLanguageHelp: 'يمكن لموقع Umbraco أن يحتوي فقط على لغة افتراضية واحدة.', - changingDefaultLanguageWarning: 'تغيير اللغة الافتراضية قد يؤدي إلى فقدان المحتوى الافتراضي.', - fallsbackToLabel: 'يعود إلى', - noFallbackLanguageOption: 'لا توجد لغة بديلة', - fallbackLanguageDescription: 'للسماح للمحتوى متعدد اللغات بالرجوع إلى لغة أخرى إذا لم يكن موجوداً باللغة المطلوبة، اخترها هنا.\n ', - fallbackLanguage: 'لغة بديلة', - none: 'لا شيء', - invariantPropertyUnlockHelp: '%0% مشتركة عبر اللغات والأقسام.', - invariantCulturePropertyUnlockHelp: '%0% مشتركة عبر جميع اللغات.', - invariantSegmentPropertyUnlockHelp: '%0% مشتركة عبر جميع الأقسام.', - invariantLanguageProperty: 'مشتركة: اللغات', - invariantSegmentProperty: 'مشتركة: الأقسام', - }, + media: 'صورة', + macro: 'ماكرو', + insertControl: 'اختر نوع المحتوى', + chooseLayout: 'اختر تخطيطاً', + addRows: 'أضف صفاً', + addElement: 'أضف محتوى', + dropElement: 'إسقاط المحتوى', + settingsApplied: 'تم تطبيق الإعدادات', + contentNotAllowed: 'هذا المحتوى غير مسموح به هنا', + contentAllowed: 'هذا المحتوى مسموح به هنا', + clickToEmbed: 'انقر للتضمين', + clickToInsertImage: 'انقر لإدراج صورة', + clickToInsertMacro: 'انقر لإدراج ماكرو', + placeholderWriteHere: 'اكتب هنا...', + gridLayouts: 'تخطيطات الشبكة', + gridLayoutsDetail: + 'التخطيطات هي منطقة العمل العامة لمحرر الشبكة، وعادةً ما تحتاج فقط إلى واحد أو اثنين من التخطيطات المختلفة', + addGridLayout: 'إضافة تخطيط شبكة', + editGridLayout: 'تعديل تخطيط الشبكة', + addGridLayoutDetail: 'ضبط التخطيط من خلال تعيين عرض الأعمدة وإضافة أقسام إضافية', + rowConfigurations: 'تكوينات الصفوف', + rowConfigurationsDetail: 'الصفوف هي خلايا محددة مسبقاً مرتبة أفقياً', + addRowConfiguration: 'إضافة تكوين صف', + editRowConfiguration: 'تعديل تكوين الصف', + addRowConfigurationDetail: 'ضبط الصف من خلال تعيين عرض الخلايا وإضافة خلايا إضافية', + noConfiguration: 'لا يوجد تكوين إضافي متاح', + columns: 'الأعمدة', + columnsDetails: 'إجمالي عدد الأعمدة في تخطيط الشبكة', + settings: 'الإعدادات', + settingsDetails: 'تكوين الإعدادات التي يمكن للمحررين تغييرها', + styles: 'الأنماط', + stylesDetails: 'تكوين التنسيق الذي يمكن للمحررين تغييره', + allowAllEditors: 'السماح لجميع المحررين', + allowAllRowConfigurations: 'السماح بجميع تكوينات الصفوف', + maxItems: 'الحد الأقصى للعناصر', + maxItemsDescription: 'اتركه فارغًا أو اضبطه على 0 لغير المحدود', + setAsDefault: 'تعيين كافتراضي', + chooseExtra: 'اختر إضافي', + chooseDefault: 'اختر افتراضي', + areAdded: 'تمت إضافتها', + warning: 'تحذير', + warningText: + '

      تعديل اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.

      تعديل التسمية فقط لن يؤدي إلى فقدان البيانات.

      ', + youAreDeleting: 'أنت تقوم بحذف تكوين الصف', + deletingARow: + '\n حذف اسم تكوين الصف سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا\n التكوين.\n ', + deleteLayout: 'أنت تقوم بحذف التخطيط', + deletingALayout: 'تعديل التخطيط سيؤدي إلى فقدان البيانات لأي محتوى موجود يعتمد على هذا التكوين.\n ', + }, + contentTypeEditor: { + compositions: 'التركيبات', + group: 'مجموعة', + groupReorderSameAliasError: + 'لا يمكنك نقل المجموعة %0% إلى هذا التبويب لأن المجموعة ستأخذ نفس الاسم المستعار كالتبويب: "%1%". قم بإعادة تسمية المجموعة للمتابعة.\n ', + noGroups: 'لم تقم بإضافة أي مجموعات', + addGroup: 'إضافة مجموعة', + inheritedFrom: 'موروث من', + addProperty: 'إضافة خاصية', + editProperty: 'تعديل الخاصية', + requiredLabel: 'التسمية المطلوبة', + enableListViewHeading: 'تمكين عرض القائمة', + enableListViewDescription: 'تكوين العنصر لعرض قائمة قابلة للفرز والبحث من أبنائه.', + allowedTemplatesHeading: 'القوالب المسموح بها', + allowedTemplatesDescription: 'اختر القوالب التي يُسمح للمحررين باستخدامها على محتوى من هذا النوع', + allowAtRootHeading: 'السماح في الجذر', + allowAtRootDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع في جذر شجرة المحتوى.\n ', + childNodesHeading: 'أنواع العقد الفرعية المسموح بها', + childNodesDescription: 'السماح بإنشاء محتوى من الأنواع المحددة أسفل محتوى من هذا النوع.', + chooseChildNode: 'اختر العقدة الفرعية', + compositionsDescription: + 'ارث التبويبات والخصائص من نوع مستند موجود. سيتم إضافة التبويبات الجديدة إلى نوع الوثيقة الحالي أو دمجها إذا كان هناك تبويب بنفس الاسم.', + compositionInUse: 'هذا النوع من المحتوى قيد الاستخدام في تركيب، وبالتالي لا يمكن تركيبه بنفسه.\n ', + noAvailableCompositions: 'لا توجد أنواع محتوى متاحة لاستخدامها كتركيب.', + compositionRemoveWarning: + 'إزالة التركيب ستؤدي إلى حذف جميع بيانات الخصائص المرتبطة. بمجرد حفظ نوع الوثيقة لا يوجد طريق للعودة.', + availableEditors: 'إنشاء جديد', + reuse: 'استخدام موجود', + editorSettings: 'إعدادات المحرر', + searchResultSettings: 'الإعدادات المتاحة', + searchResultEditors: 'إنشاء تكوين جديد', + configuration: 'التكوين', + yesDelete: 'نعم، احذف', + movedUnderneath: 'تم نقله تحت', + copiedUnderneath: 'تم نسخه تحت', + folderToMove: 'اختر المجلد للتحريك', + folderToCopy: 'اختر المجلد للنسخ', + structureBelow: 'إلى هيكل الشجرة أدناه', + allDocumentTypes: 'جميع أنواع الوثائق', + allDocuments: 'جميع الوثائق', + allMediaItems: 'جميع العناصر الإعلامية', + usingThisDocument: 'استخدام هذا النوع من الوثائق سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', + usingThisMedia: 'استخدام هذا النوع من الوسائط سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا.\n ', + usingThisMember: 'استخدام هذا النوع من الأعضاء سيتم حذفه نهائيًا، يرجى تأكيد أنك تريد حذف هذه أيضًا\n ', + andAllDocuments: 'وجميع الوثائق التي تستخدم هذا النوع', + andAllMediaItems: 'وجميع العناصر الإعلامية التي تستخدم هذا النوع', + andAllMembers: 'وجميع الأعضاء الذين يستخدمون هذا النوع', + memberCanEdit: 'يمكن للعضو التعديل', + memberCanEditDescription: 'السماح بتعديل قيمة هذه الخاصية من قبل العضو في صفحة ملفه الشخصي\n ', + isSensitiveData: 'بيانات حساسة', + isSensitiveDataDescription: + 'إخفاء قيمة هذه الخاصية عن محرري المحتوى الذين لا يملكون حق الوصول لعرض المعلومات الحساسة\n ', + showOnMemberProfile: 'عرض على ملف العضو', + showOnMemberProfileDescription: 'السماح بعرض قيمة هذه الخاصية في صفحة ملف العضو\n ', + tabHasNoSortOrder: 'التبويب ليس له ترتيب فرز', + compositionUsageHeading: 'أين يتم استخدام هذا التركيب؟', + compositionUsageSpecification: 'يتم استخدام هذا التركيب حاليًا في تركيب أنواع المحتوى التالية:\n ', + variantsHeading: 'السماح بالاختلافات', + cultureVariantHeading: 'السماح بالاختلاف حسب الثقافة', + segmentVariantHeading: 'السماح بالتجزئة', + cultureVariantLabel: 'الاختلاف حسب الثقافة', + segmentVariantLabel: 'الاختلاف حسب القطاعات', + variantsDescription: 'السماح للمحررين بإنشاء محتوى من هذا النوع بلغات مختلفة.', + cultureVariantDescription: 'السماح للمحررين بإنشاء محتوى بلغات مختلفة.', + segmentVariantDescription: 'السماح للمحررين بإنشاء قطاعات من هذا المحتوى.', + allowVaryByCulture: 'السماح بالاختلاف حسب الثقافة', + allowVaryBySegment: 'السماح بالتجزئة', + elementType: 'نوع العنصر', + elementHeading: 'هو نوع عنصر', + elementDescription: 'نوع العنصر مخصص للاستخدام ضمن أنواع مستندات أخرى، وليس في شجرة المحتوى.\n ', + elementCannotToggle: + 'لا يمكن تغيير نوع مستند إلى نوع عنصر بمجرد أن يتم استخدامه لإنشاء عنصر أو أكثر من محتوى.\n ', + elementDoesNotSupport: 'هذا غير قابل للتطبيق لنوع العنصر', + propertyHasChanges: 'لقد أجريت تغييرات على هذه الخاصية. هل أنت متأكد أنك تريد التخلص منها؟', + displaySettingsHeadline: 'المظهر', + displaySettingsLabelOnTop: 'التسمية في الأعلى (عرض كامل)', + confirmDeleteTabMessage: 'هل أنت متأكد أنك تريد حذف التبويب %0%؟', + confirmDeleteGroupMessage: 'هل أنت متأكد أنك تريد حذف المجموعة %0%؟', + confirmDeletePropertyMessage: 'هل أنت متأكد أنك تريد حذف الخاصية %0%؟', + confirmDeleteTabNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذا التبويب.', + confirmDeleteGroupNotice: 'سوف يؤدي ذلك أيضًا إلى حذف جميع العناصر أسفل هذه المجموعة.', + addTab: 'إضافة تبويب', + convertToTab: 'تحويل إلى تبويب', + tabDirectPropertiesDropZone: 'اسحب الخصائص هنا لوضعها مباشرة على التبويب', + removeChildNode: 'أنت تقوم بإزالة العقدة الفرعية', + removeChildNodeWarning: 'إزالة عقدة فرعية ستحد من خيارات المحررين لإنشاء أنواع محتوى مختلفة أسفل عقدة.', + usingEditor: 'استخدام هذا المحرر سيتم تحديثه بالإعدادات الجديدة.', + historyCleanupHeading: 'تنظيف السجل', + historyCleanupDescription: 'السماح بتجاوز الإعدادات العالمية لتنظيف السجل.', + historyCleanupKeepAllVersionsNewerThanDays: 'احتفظ بجميع الإصدارات الأحدث من الأيام', + historyCleanupKeepLatestVersionPerDayForDays: 'احتفظ بأحدث إصدار لكل يوم لعدد من الأيام', + historyCleanupPreventCleanup: 'منع التنظيف', + historyCleanupEnableCleanup: 'تمكين التنظيف', + historyCleanupGloballyDisabled: + 'ملاحظة! تنظيف إصدارات المحتوى التاريخية معطل عالميًا. لن تكون هذه الإعدادات فعالة حتى يتم تمكينها.', + changeDataTypeHelpText: + 'تغيير نوع البيانات مع القيم المخزنة معطل. للسماح بذلك، يمكنك تغيير إعداد Umbraco:CMS:DataTypes:CanBeChanged في appsettings.json.', + collections: 'المجموعات', + collectionsDescription: 'تكوين العنصر لعرض قائمة بأبنائه.', + structure: 'الهيكل', + presentation: 'العرض', + }, + languages: { + addLanguage: 'إضافة لغة', + culture: 'رمز ISO', + mandatoryLanguage: 'اللغة الإلزامية', + mandatoryLanguageHelp: 'يجب ملء الخصائص في هذه اللغة قبل أن يتم نشر العقدة.\n ', + defaultLanguage: 'اللغة الافتراضية', + defaultLanguageHelp: 'يمكن لموقع Umbraco أن يحتوي فقط على لغة افتراضية واحدة.', + changingDefaultLanguageWarning: 'تغيير اللغة الافتراضية قد يؤدي إلى فقدان المحتوى الافتراضي.', + fallsbackToLabel: 'يعود إلى', + noFallbackLanguageOption: 'لا توجد لغة بديلة', + fallbackLanguageDescription: + 'للسماح للمحتوى متعدد اللغات بالرجوع إلى لغة أخرى إذا لم يكن موجوداً باللغة المطلوبة، اخترها هنا.\n ', + fallbackLanguage: 'لغة بديلة', + none: 'لا شيء', + invariantPropertyUnlockHelp: '%0% مشتركة عبر اللغات والأقسام.', + invariantCulturePropertyUnlockHelp: '%0% مشتركة عبر جميع اللغات.', + invariantSegmentPropertyUnlockHelp: '%0% مشتركة عبر جميع الأقسام.', + invariantLanguageProperty: 'مشتركة: اللغات', + invariantSegmentProperty: 'مشتركة: الأقسام', + }, macro: { addParameter: 'إضافة معلمة', editParameter: 'تعديل المعلمة', @@ -1602,7 +1674,7 @@ export default { }, modelsBuilder: { buildingModels: 'بناء النماذج', - waitingMessage: "قد يستغرق هذا بعض الوقت، لا داعي للقلق", + waitingMessage: 'قد يستغرق هذا بعض الوقت، لا داعي للقلق', modelsGenerated: 'تم إنشاء النماذج', modelsGeneratedError: 'لم يتم إنشاء النماذج', modelsExceptionInUlog: 'فشل إنشاء النماذج، راجع الاستثناء في سجل U', @@ -1644,15 +1716,14 @@ export default { DownloadXmlDTD: 'تنزيل XML DTD', fields: 'الحقول', includeSubpages: 'تضمين الصفحات الفرعية', - noTranslators: - 'لم يتم العثور على مستخدمين مترجمين. يرجى إنشاء مستخدم مترجم قبل البدء في إرسال المحتوى للترجمة', + noTranslators: 'لم يتم العثور على مستخدمين مترجمين. يرجى إنشاء مستخدم مترجم قبل البدء في إرسال المحتوى للترجمة', pageHasBeenSendToTranslation: "تم إرسال الصفحة '%0%' للترجمة", sendToTranslate: "إرسال الصفحة '%0%' للترجمة", totalWords: 'إجمالي الكلمات', translateTo: 'ترجم إلى', translationDone: 'الترجمة مكتملة.', translationDoneHelp: - "يمكنك معاينة الصفحات التي قمت بترجمتها للتو بالنقر أدناه. إذا تم العثور على الصفحة الأصلية، ستتلقى مقارنة بين الصفحتين.", + 'يمكنك معاينة الصفحات التي قمت بترجمتها للتو بالنقر أدناه. إذا تم العثور على الصفحة الأصلية، ستتلقى مقارنة بين الصفحتين.', translationFailed: 'فشلت الترجمة، قد يكون ملف XML تالفاً', translationOptions: 'خيارات الترجمة', translator: 'المترجم', @@ -1705,7 +1776,7 @@ export default { updateNoServer: 'لا يوجد اتصال بالخادم', updateNoServerError: 'خطأ في التحقق من التحديث. يرجى مراجعة تتبع الأخطاء لمزيد من المعلومات', }, - user: { + user: { access: 'الوصول', accessHelp: 'استناداً إلى المجموعات المعينة وعقد البداية، يتمتع المستخدم بالوصول إلى العقد التالية', assignAccess: 'تعيين الوصول', @@ -1724,8 +1795,8 @@ export default { newPassword: 'كلمة مرور جديدة', newPasswordFormatLengthTip: 'الحد الأدنى هو %0% حرفاً!', newPasswordFormatNonAlphaTip: 'يجب أن تحتوي على %0% حرفاً خاصاً على الأقل.', - noLockouts: "لم يتم قفله", - noPasswordChange: "لم يتم تغيير كلمة المرور", + noLockouts: 'لم يتم قفله', + noPasswordChange: 'لم يتم تغيير كلمة المرور', confirmNewPassword: 'تأكيد كلمة المرور الجديدة', changePasswordDescription: "يمكنك تغيير كلمة مرورك للوصول إلى واجهة Umbraco من خلال ملء النموذج أدناه والنقر على زر 'تغيير كلمة المرور'", @@ -1772,9 +1843,8 @@ export default { passwordIsBlank: 'لا يمكن أن تكون كلمة المرور الجديدة فارغة!', passwordCurrent: 'كلمة المرور الحالية', passwordInvalid: 'كلمة المرور الحالية غير صحيحة', - passwordIsDifferent: - 'كان هناك اختلاف بين كلمة المرور الجديدة وكلمة المرور المؤكدة. يرجى المحاولة مرة أخرى!', - passwordMismatch: "كلمة المرور المؤكدة لا تطابق كلمة المرور الجديدة!", + passwordIsDifferent: 'كان هناك اختلاف بين كلمة المرور الجديدة وكلمة المرور المؤكدة. يرجى المحاولة مرة أخرى!', + passwordMismatch: 'كلمة المرور المؤكدة لا تطابق كلمة المرور الجديدة!', passwordRequiresDigit: "يجب أن تحتوي كلمة المرور على رقم واحد على الأقل ('0'-'9')", passwordRequiresLower: "يجب أن تحتوي كلمة المرور على حرف صغير واحد على الأقل ('a'-'z')", passwordRequiresNonAlphanumeric: 'يجب أن تحتوي كلمة المرور على حرف غير أبجدي رقمي واحد على الأقل', @@ -1809,8 +1879,7 @@ export default { startnodeshelp: 'تقييد شجرة المحتوى إلى عقد بداية محددة', updateDate: 'تاريخ آخر تحديث للمستخدم', userCreated: 'تم إنشاؤه', - userCreatedSuccessHelp: - 'تم إنشاء المستخدم الجديد بنجاح. لتسجيل الدخول إلى Umbraco استخدم كلمة المرور أدناه.', + userCreatedSuccessHelp: 'تم إنشاء المستخدم الجديد بنجاح. لتسجيل الدخول إلى Umbraco استخدم كلمة المرور أدناه.', userHasPassword: 'تم تعيين كلمة مرور للمستخدم بالفعل', userHasGroup: "المستخدم موجود بالفعل في المجموعة '%0%'", userLockoutNotEnabled: 'القفل غير مفعل لهذا المستخدم', @@ -1821,14 +1890,12 @@ export default { usergroup: 'مجموعة المستخدمين', usergroups: 'مجموعات المستخدمين', userInvited: 'تمت دعوته', - userInvitedSuccessHelp: - 'تم إرسال دعوة إلى المستخدم الجديد مع تفاصيل حول كيفية تسجيل الدخول إلى Umbraco.', + userInvitedSuccessHelp: 'تم إرسال دعوة إلى المستخدم الجديد مع تفاصيل حول كيفية تسجيل الدخول إلى Umbraco.', userinviteWelcomeMessage: 'مرحباً بك في Umbraco! في دقيقة واحدة فقط ستكون جاهزاً، نحن فقط بحاجة منك لتعيين كلمة مرور وإضافة صورة لملفك الشخصي.', userinviteExpiredMessage: 'مرحباً بك في Umbraco! للأسف انتهت صلاحية دعوتك. يرجى الاتصال بالمسؤول الخاص بك واطلب منهم إعادة إرسالها.', - userinviteAvatarMessage: - 'رفع صورة لنفسك سيساعد الآخرين على التعرف عليك بسهولة. انقر على الدائرة أعلاه لرفع صورتك.', + userinviteAvatarMessage: 'رفع صورة لنفسك سيساعد الآخرين على التعرف عليك بسهولة. انقر على الدائرة أعلاه لرفع صورتك.', writer: 'كاتب', configureTwoFactor: 'تكوين التحقق بخطوتين', change: 'تغيير', @@ -1915,10 +1982,10 @@ export default { macroErrorModeCheckSuccessMessage: "MacroErrors تم تعيينها إلى '%0%'.", macroErrorModeCheckErrorMessage: "MacroErrors تم تعيينها إلى '%0%' مما سيمنع بعض أو جميع الصفحات في\n موقعك من التحميل بالكامل إذا كانت هناك أي أخطاء في الماكرو. تصحيح ذلك سيجعل القيمة تُعيّن إلى '%1%'.\n ", - httpsCheckValidCertificate: "شهادة موقعك صالحة.", + httpsCheckValidCertificate: 'شهادة موقعك صالحة.', httpsCheckInvalidCertificate: "خطأ في التحقق من الشهادة: '%0%'", - httpsCheckExpiredCertificate: "شهادة SSL لموقعك قد انتهت صلاحيتها.", - httpsCheckExpiringCertificate: "شهادة SSL لموقعك تنتهي صلاحيتها في %0% يوماً.", + httpsCheckExpiredCertificate: 'شهادة SSL لموقعك قد انتهت صلاحيتها.', + httpsCheckExpiringCertificate: 'شهادة SSL لموقعك تنتهي صلاحيتها في %0% يوماً.', healthCheckInvalidUrl: "خطأ في اختبار URL %0% - '%1%'", httpsCheckIsCurrentSchemeHttps: 'أنت حالياً %0% تعرض الموقع باستخدام مخطط HTTPS.', httpsCheckConfigurationRectifyNotPossible: @@ -1953,15 +2020,12 @@ export default { 'تم العثور على الرؤوس التالية التي تكشف عن معلومات حول تكنولوجيا الموقع: %0%.', excessiveHeadersNotFound: 'لم يتم العثور على رؤوس تكشف عن معلومات حول تكنولوجيا الموقع.\n ', smtpMailSettingsNotFound: "إعدادات 'Umbraco:CMS:Global:Smtp' لم يتم العثور عليها.", - smtpMailSettingsHostNotConfigured: - "إعداد 'Umbraco:CMS:Global:Smtp:Host' لم يتم العثور عليه.\n ", - smtpMailSettingsConnectionSuccess: - 'تم تكوين إعدادات SMTP بشكل صحيح والخدمة تعمل كما هو متوقع.\n ', + smtpMailSettingsHostNotConfigured: "إعداد 'Umbraco:CMS:Global:Smtp:Host' لم يتم العثور عليه.\n ", + smtpMailSettingsConnectionSuccess: 'تم تكوين إعدادات SMTP بشكل صحيح والخدمة تعمل كما هو متوقع.\n ', smtpMailSettingsConnectionFail: "لم يتم الوصول إلى خادم SMTP المُعين بالمضيف '%0%' والمنفذ '%1%'. يرجى التحقق للتأكد من صحة إعدادات SMTP في التكوين 'Umbraco:CMS:Global:Smtp'.\n ", notificationEmailsCheckSuccessMessage: 'تم تعيين بريد الإشعارات إلى %0%.', - notificationEmailsCheckErrorMessage: - 'بريد الإشعارات ما زال مضبوطًا على القيمة الافتراضية %0%.', + notificationEmailsCheckErrorMessage: 'بريد الإشعارات ما زال مضبوطًا على القيمة الافتراضية %0%.', checkGroup: 'فحص المجموعة', helpText: '\n

      مدقق الصحة يقيم مجالات مختلفة في موقعك لأفضل إعدادات الممارسات والتكوين والمشاكل المحتملة، وما إلى ذلك. يمكنك إصلاح المشكلات بسهولة عن طريق الضغط على زر.\n يمكنك إضافة فحوصات صحية خاصة بك، راجع التوثيق لمزيد من المعلومات حول فحوصات الصحة المخصصة.

      \n ', @@ -1975,8 +2039,7 @@ export default { redirectUrlManagement: 'إدارة URL التحويل', panelInformation: 'توجه URLs التالية إلى هذا العنصر المحتوى:', noRedirects: 'لم يتم إجراء أي تحويلات', - noRedirectsDescription: - 'عند إعادة تسمية صفحة منشورة أو نقلها، سيتم تلقائيًا إجراء تحويل إلى الصفحة الجديدة.\n ', + noRedirectsDescription: 'عند إعادة تسمية صفحة منشورة أو نقلها، سيتم تلقائيًا إجراء تحويل إلى الصفحة الجديدة.\n ', redirectRemoved: 'تمت إزالة URL التحويل.', redirectRemoveError: 'خطأ في إزالة URL التحويل.', redirectRemoveWarning: 'سيتم إزالة التحويل', @@ -2098,8 +2161,7 @@ export default { labelUsedItems: 'العناصر التالية يتم الاستشهاد بها', labelUsedDescendants: 'العناصر اللاحقة التالية لها تبعيات', labelDependentDescendants: 'العناصر اللاحقة التالية لها تبعيات', - deleteWarning: - 'يتم الاستشهاد بهذا العنصر أو أحفاده. يمكن أن تؤدي الحذف إلى روابط مكسورة على موقعك الإلكتروني.', + deleteWarning: 'يتم الاستشهاد بهذا العنصر أو أحفاده. يمكن أن تؤدي الحذف إلى روابط مكسورة على موقعك الإلكتروني.', unpublishWarning: 'يتم الاستشهاد بهذا العنصر أو أحفاده. يمكن أن يؤدي إلغاء النشر إلى روابط مكسورة على موقعك الإلكتروني. يرجى اتخاذ الإجراءات المناسبة.', deleteDisabledWarning: 'يتم الاستشهاد بهذا العنصر أو أحفاده. لذلك، تم تعطيل الحذف.', @@ -2109,286 +2171,314 @@ export default { return `...ومزيد من ${count} عناصر`; }, }, - logViewer: { - deleteSavedSearch: 'حذف البحث المحفوظ', - logLevels: 'مستويات السجل', - selectAllLogLevelFilters: 'تحديد الكل', - deselectAllLogLevelFilters: 'إلغاء تحديد الكل', - savedSearches: 'البحث المحفوظ', - saveSearch: 'حفظ البحث', - saveSearchDescription: 'أدخل اسمًا وديًا لاستعلام البحث الخاص بك', - filterSearch: 'تصفية البحث', - totalItems: 'إجمالي العناصر', - timestamp: 'الطابع الزمني', - level: 'المستوى', - machine: 'الآلة', - message: 'الرسالة', - exception: 'الاستثناء', - properties: 'الخصائص', - searchWithGoogle: 'البحث باستخدام جوجل', - searchThisMessageWithGoogle: 'ابحث عن هذه الرسالة باستخدام جوجل', - searchWithBing: 'البحث باستخدام بينج', - searchThisMessageWithBing: 'ابحث عن هذه الرسالة باستخدام بينج', - searchOurUmbraco: 'البحث في Umbraco الخاص بنا', - searchThisMessageOnOurUmbracoForumsAndDocs: 'ابحث عن هذه الرسالة في منتديات ومراسلات Umbraco الخاصة بنا', - searchOurUmbracoWithGoogle: 'البحث في Umbraco الخاص بنا باستخدام جوجل', - searchOurUmbracoForumsUsingGoogle: 'البحث في منتديات Umbraco الخاصة بنا باستخدام جوجل', - searchUmbracoSource: 'البحث في مصدر Umbraco', - searchWithinUmbracoSourceCodeOnGithub: 'البحث ضمن كود مصدر Umbraco على Github', - searchUmbracoIssues: 'البحث في قضايا Umbraco', - searchUmbracoIssuesOnGithub: 'البحث في قضايا Umbraco على Github', - deleteThisSearch: 'حذف هذا البحث', - findLogsWithRequestId: 'البحث في السجلات باستخدام معرّف الطلب', - findLogsWithNamespace: 'البحث في السجلات باستخدام النطاق', - findLogsWithMachineName: 'البحث في السجلات باستخدام اسم الآلة', - open: 'فتح', - polling: 'استطلاع', - every2: 'كل 2 ثانية', - every5: 'كل 5 ثوانٍ', - every10: 'كل 10 ثوانٍ', - every20: 'كل 20 ثانية', - every30: 'كل 30 ثانية', - pollingEvery2: 'استطلاع كل 2 ثانية', - pollingEvery5: 'استطلاع كل 5 ثوانٍ', - pollingEvery10: 'استطلاع كل 10 ثوانٍ', - pollingEvery20: 'استطلاع كل 20 ثانية', - pollingEvery30: 'استطلاع كل 30 ثانية' - }, - clipboard: { - labelForCopyAllEntries: 'نسخ %0%', - labelForArrayOfItemsFrom: '%0% من %1%', - labelForArrayOfItems: 'مجموعة من %0%', - labelForRemoveAllEntries: 'إزالة جميع العناصر', - labelForClearClipboard: 'مسح الحافظة', - labelForCopyToClipboard: 'نسخ إلى الحافظة' - }, - propertyActions: { - tooltipForPropertyActionsMenu: 'فتح إجراءات الخصائص', - tooltipForPropertyActionsMenuClose: 'إغلاق إجراءات الخصائص' - }, - nuCache: { - refreshStatus: 'تحديث الحالة', - memoryCache: 'ذاكرة التخزين المؤقت', - memoryCacheDescription: 'هذا الزر يتيح لك إعادة تحميل ذاكرة التخزين المؤقت في الذاكرة، من خلال إعادة تحميلها بالكامل من قاعدة البيانات (ولكنه لا يعيد بناء تلك الذاكرة المؤقتة في قاعدة البيانات). هذا سريع نسبيًا. استخدمه عندما تعتقد أن ذاكرة التخزين المؤقت في الذاكرة لم يتم تحديثها بشكل صحيح، بعد بعض الأحداث التي تم تشغيلها—مما قد يشير إلى مشكلة طفيفة في Umbraco. (ملاحظة: يشغل إعادة التحميل على جميع الخوادم في بيئة LB).', - reload: 'إعادة تحميل', - databaseCache: 'ذاكرة التخزين المؤقت لقاعدة البيانات', - databaseCacheDescription: 'هذا الزر يتيح لك إعادة بناء ذاكرة التخزين المؤقت لقاعدة البيانات، أي محتوى جدول cmsContentNu. إعادة البناء يمكن أن تكون مكلفة. استخدمه عندما لا يكون إعادة التحميل كافيًا، وتعتقد أن ذاكرة التخزين المؤقت لقاعدة البيانات لم يتم إنشاؤها بشكل صحيح—مما قد يشير إلى مشكلة حاسمة في Umbraco.', - rebuild: 'إعادة بناء', - internals: 'الأنظمة الداخلية', - internalsDescription: 'هذا الزر يتيح لك تشغيل مجموعة لقطات NuCache (بعد تشغيل GC الكامل). ما لم تكن تعرف ما يعني ذلك، فمن المحتمل أنك لا تحتاج إلى استخدامه.', - collect: 'جمع', - publishedCacheStatus: 'حالة ذاكرة التخزين المؤقت المنشورة', - caches: 'ذاكرات التخزين المؤقت' - }, - profiling: { - performanceProfiling: 'تحليل الأداء', - performanceProfilingDescription: "

      تشغيل Umbraco حاليًا في وضع التصحيح. هذا يعني أنه يمكنك استخدام أداة تحليل الأداء المدمجة لتقييم الأداء عند عرض الصفحات.

      إذا كنت تريد تفعيل أداة التحليل لعرض صفحة معينة، أضف ببساطة umbDebug=true إلى سلسلة الاستعلام عند طلب الصفحة.

      إذا كنت تريد أن يتم تفعيل أداة التحليل بشكل افتراضي لجميع عمليات عرض الصفحات، يمكنك استخدام التبديل أدناه. سيقوم بتعيين ملف تعريف في متصفحك، والذي يقوم بعد ذلك بتفعيل أداة التحليل تلقائيًا. بعبارة أخرى، ستكون أداة التحليل نشطة افتراضيًا فقط في متصفحك - وليس في متصفحات الآخرين.

      ", - activateByDefault: 'تفعيل أداة التحليل بشكل افتراضي', - reminder: 'تذكير ودي', - reminderDescription: '

      يجب ألا تدع موقع الإنتاج يعمل في وضع التصحيح. يتم إيقاف وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى false في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

      ', - profilerEnabledDescription: "

      Umbraco حاليًا لا يعمل في وضع التصحيح، لذا لا يمكنك استخدام أداة التحليل المدمجة. هذا هو الوضع الصحيح لموقع الإنتاج.

      يتم تشغيل وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى true في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

      " - }, - settingsDashboardVideos: { - trainingHeadline: 'ساعات من مقاطع فيديو تدريب Umbraco على بعد نقرة واحدة', - trainingDescription: '

      هل تريد إتقان Umbraco؟ اقض بضع دقائق في تعلم بعض الممارسات الأفضل من خلال مشاهدة واحدة من هذه الفيديوهات حول استخدام Umbraco. وزيارة umbraco.tv لمزيد من مقاطع الفيديو حول Umbraco

      ' - }, - settingsDashboard: { - documentationHeader: 'التوثيق', - documentationDescription: 'اقرأ المزيد عن العمل مع العناصر في الإعدادات في توثيقنا.', - communityHeader: 'المجتمع', - communityDescription: 'اطرح سؤالاً في منتدى المجتمع أو مجتمع Discord لدينا.', - trainingHeader: 'التدريب', - trainingDescription: 'اكتشف فرص التدريب والتأهيل الرسمية', - supportHeader: 'الدعم', - supportDescription: 'قم بتوسيع فريقك مع مجموعة ماهرة ومتحمسة من خبراء Umbraco.', - videosHeader: 'مقاطع الفيديو', - videosDescription: 'شاهد مقاطع الفيديو التعليمية المجانية لدينا على قناة YouTube الخاصة بأساسيات Umbraco، لتصبح على اطلاع سريع بـ Umbraco.', - getHelp: 'احصل على المساعدة التي تحتاجها', - getCertified: 'احصل على الشهادة', - goForum: 'اذهب إلى المنتدى', - chatWithCommunity: 'الدردشة مع المجتمع', - watchVideos: 'شاهد مقاطع الفيديو' - }, - startupDashboard: { - fallbackHeadline: 'مرحبًا بك في نظام إدارة المحتوى الودود', - fallbackDescription: "شكرًا لاختيارك Umbraco - نعتقد أن هذه قد تكون بداية شيء جميل. بينما قد يبدو الأمر مربكًا في البداية، لقد بذلنا الكثير لجعل منحنى التعلم سلسًا وسريعًا قدر الإمكان." - }, - welcomeDashboard: { - ourUmbracoHeadline: 'Umbraco الخاص بنا - أكثر المجتمعات صداقة', - ourUmbracoDescription: "Umbraco الخاص بنا، الموقع الرسمي للمجتمع، هو وجهتك الشاملة لكل شيء متعلق بـ Umbraco. سواء كنت بحاجة إلى إجابة على سؤال، أو إضافات رائعة، أو دليل حول كيفية القيام بشيء ما في Umbraco، فإن أفضل وأصدق مجتمع في العالم هو مجرد نقرة بعيدًا.", - ourUmbracoButton: 'زيارة Umbraco الخاص بنا', - documentationHeadline: 'التوثيق', - documentationDescription: 'ابحث عن إجابات لجميع أسئلتك حول Umbraco', - communityHeadline: 'المجتمع', - communityDescription: 'احصل على الدعم والإلهام من خبراء Umbraco المتحمسين', - resourcesHeadline: 'الموارد', - resourcesDescription: 'دروس فيديو مجانية لبدء رحلتك مع نظام إدارة المحتوى', - trainingHeadline: 'التدريب', - trainingDescription: 'التدريب الواقعي وشهادات Umbraco الرسمية' - }, - blockEditor: { - headlineCreateBlock: 'اختيار نوع العنصر', - headlineAddSettingsElementType: 'إضافة نوع عنصر الإعدادات', - headlineAddCustomView: 'اختيار العرض', - headlineAddCustomStylesheet: 'اختيار ورقة الأنماط', - headlineAddThumbnail: 'اختيار الصورة المصغرة', - labelcreateNewElementType: 'إنشاء نوع عنصر جديد', - labelCustomStylesheet: 'ورقة أنماط مخصصة', - addCustomStylesheet: 'إضافة ورقة أنماط', - headlineEditorAppearance: 'مظهر الكتلة', - headlineDataModels: 'نماذج البيانات', - headlineCatalogueAppearance: 'مظهر الكتالوج', - labelBackgroundColor: 'لون الخلفية', - labelIconColor: 'لون الأيقونة', - labelContentElementType: 'نموذج المحتوى', - labelLabelTemplate: 'التسمية', - labelCustomView: 'عرض مخصص', - labelCustomViewInfoTitle: 'عرض وصف العرض المخصص', - labelCustomViewDescription: 'تجاوز كيفية ظهور هذه الكتلة في واجهة المستخدم الخلفية. اختر ملف .html يحتوي على تقديمك.', - labelSettingsElementType: 'نموذج الإعدادات', - labelEditorSize: 'حجم محرر التراكب', - addCustomView: 'إضافة عرض مخصص', - addSettingsElementType: 'إضافة إعدادات', - confirmDeleteBlockMessage: 'هل أنت متأكد أنك تريد حذف المحتوى %0%؟', - confirmDeleteBlockTypeMessage: 'هل أنت متأكد أنك تريد حذف تكوين الكتلة %0%؟', - confirmDeleteBlockTypeNotice: 'سيظل محتوى هذه الكتلة موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', - confirmDeleteBlockGroupMessage: 'هل أنت متأكد أنك تريد حذف المجموعة %0% وجميع تكوينات الكتلة الخاصة بها؟', - confirmDeleteBlockGroupNotice: 'سيظل محتوى هذه الكتل موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', - blockConfigurationOverlayTitle: "تكوين '%0%'", - elementTypeDoesNotExist: 'لا يمكن تحريره لأن نوع العنصر غير موجود.', - thumbnail: 'صورة مصغرة', - addThumbnail: 'إضافة صورة مصغرة', - tabCreateEmpty: 'إنشاء فارغ', - tabClipboard: 'الحافظة', - tabBlockSettings: 'الإعدادات', - headlineAdvanced: 'متقدم', - headlineCustomView: 'عرض مخصص', - forceHideContentEditor: 'إخفاء محرر المحتوى', - forceHideContentEditorHelp: 'إخفاء زر تحرير المحتوى ومحرر المحتوى من تراكب محرر الكتل', - gridInlineEditing: 'تحرير مباشر', - gridInlineEditingHelp: 'يتيح التحرير المباشر لأول خاصية. يمكن تحرير الخصائص الإضافية في التراكب.', - blockHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد تجاهلها؟', - confirmCancelBlockCreationHeadline: 'تجاهل الإنشاء؟', - confirmCancelBlockCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', - elementTypeDoesNotExistHeadline: 'خطأ!', - elementTypeDoesNotExistDescription: 'نوع العنصر لهذه الكتلة لم يعد موجودًا', - addBlock: 'إضافة محتوى', - addThis: 'إضافة %0%', - propertyEditorNotSupported: "الخاصية '%0%' تستخدم المحرر '%1%' والذي لا يدعمه الكتل.", - focusParentBlock: 'تعيين التركيز على الكتلة الحاوية', - areaIdentification: 'التحديد', - areaValidation: 'التحقق', - areaValidationEntriesShort: '%0% يجب أن تكون موجودة على الأقل %2% مرة(s).', - areaValidationEntriesExceed: '%0% يجب أن تكون موجودة بحد أقصى %3% مرة(s).', - areaNumberOfBlocks: 'عدد الكتل', - areaDisallowAllBlocks: 'السماح بأنواع كتل محددة فقط', - areaAllowedBlocks: 'أنواع الكتل المسموح بها', - areaAllowedBlocksHelp: 'حدد أنواع الكتل المسموح بها في هذه المنطقة، واختياريًا عدد كل نوع من الأنواع التي يجب أن تكون موجودة.', - confirmDeleteBlockAreaMessage: 'هل أنت متأكد أنك تريد حذف هذه المنطقة؟', - confirmDeleteBlockAreaNotice: 'أي كتل تم إنشاؤها حاليًا داخل هذه المنطقة سيتم حذفها.', - layoutOptions: 'خيارات التخطيط', - structuralOptions: 'هيكلية', - sizeOptions: 'خيارات الحجم', - sizeOptionsHelp: 'حدد خيارًا أو أكثر من خيارات الحجم، هذا يمكن أن يتيح تغيير حجم الكتلة', - allowedBlockColumns: 'امتدادات الأعمدة المتاحة', - allowedBlockColumnsHelp: 'حدد عدد الأعمدة المختلفة التي يُسمح لهذه الكتلة بالامتداد عبرها. هذا لا يمنع الكتل من وضعها في مناطق ذات امتداد أعمدة أصغر.', - allowedBlockRows: 'امتدادات الصفوف المتاحة', - allowedBlockRowsHelp: 'حدد نطاق الصفوف التخطيطية التي يُسمح لهذه الكتلة بالامتداد عبرها.', - allowBlockInRoot: 'السماح في الجذر', - allowBlockInRootHelp: 'اجعل هذه الكتلة متاحة في جذر التخطيط.', - allowBlockInAreas: 'السماح في المناطق', - allowBlockInAreasHelp: 'اجعل هذه الكتلة متاحة افتراضيًا ضمن مناطق كتل أخرى (ما لم يتم تعيين أذونات صريحة لهذه المناطق).', - areaAllowedBlocksEmpty: 'افتراضيًا، جميع أنواع الكتل مسموح بها في منطقة، استخدم هذا الخيار للسماح بأنواع محددة فقط.', - areas: 'المناطق', - areasLayoutColumns: 'أعمدة الشبكة للمناطق', - areasLayoutColumnsHelp: 'حدد عدد الأعمدة المتاحة للمناطق. إذا لم يتم تحديدها، سيتم استخدام عدد الأعمدة المحدد للتخطيط الكامل.', - areasConfigurations: 'المناطق', - areasConfigurationsHelp: 'لتمكين تداخل الكتل داخل هذه الكتلة، حدد منطقة واحدة أو أكثر. تتبع المناطق التخطيط المحدد من خلال تكوين عمود الشبكة الخاص بها. يمكن تعديل "امتداد العمود" و "امتداد الصف" لكل منطقة باستخدام مربع مقبض التدرج في الزاوية السفلى اليمنى من المنطقة المحددة.', - invalidDropPosition: '%0% غير مسموح به في هذا الموضع.', - defaultLayoutStylesheet: 'ورقة أنماط التخطيط الافتراضية', - confirmPasteDisallowedNestedBlockHeadline: 'تم رفض المحتوى غير المسموح به', - confirmPasteDisallowedNestedBlockMessage: 'احتوى المحتوى الذي تم إدراجه على محتوى غير مسموح به، والذي لم يتم إنشاؤه. هل ترغب في الاحتفاظ ببقية هذا المحتوى على أي حال؟', - areaAliasHelp: 'عند استخدام GetBlockGridHTML() لعرض شبكة الكتل، سيتم عرض الاسم المستعار في الشيفرة المصدرية كخاصية \'data-area-alias\'. استخدم خاصية الاسم المستعار لاستهداف العنصر للمنطقة. مثال. .umb-block-grid__area[data-area-alias="MyAreaAlias"] { ... }', - scaleHandlerButtonTitle: 'اسحب للتغيير الحجم', - areaCreateLabelTitle: 'تسمية زر الإنشاء', - areaCreateLabelHelp: 'تجاوز نص التسمية لإضافة كتلة جديدة إلى هذه المنطقة، مثال: "إضافة عنصر واجهة المستخدم"', - showSizeOptions: 'عرض خيارات تغيير الحجم', - addBlockType: 'إضافة كتلة', - addBlockGroup: 'إضافة مجموعة', - pickSpecificAllowance: 'اختر مجموعة أو كتلة', - allowanceMinimum: 'تحديد الحد الأدنى المطلوب', - allowanceMaximum: 'تحديد الحد الأقصى المطلوب', - block: 'كتلة', - tabBlock: 'كتلة', - tabBlockTypeSettings: 'الإعدادات', - tabAreas: 'المناطق', - tabAdvanced: 'متقدم', - headlineAllowance: 'الأذونات', - getSampleHeadline: 'تثبيت التكوين التجريبي', - getSampleDescription: "سيضيف هذا كتل أساسية ويساعدك على البدء باستخدام محرر شبكة الكتل. ستحصل على كتل للعناوين والنصوص الغنية والصور، بالإضافة إلى تخطيط بعمودين.", - getSampleButton: 'تثبيت', - actionEnterSortMode: 'وضع الترتيب', - actionExitSortMode: 'إنهاء وضع الترتيب', - areaAliasIsNotUnique: 'يجب أن يكون اسم المنطقة هذا فريد مقارنةً بالمناطق الأخرى لهذه الكتلة.', - configureArea: 'تكوين المنطقة', - deleteArea: 'حذف المنطقة', - addColumnSpanOption: 'إضافة خيار امتداد %0% عمود' - }, - contentTemplatesDashboard: { - whatHeadline: 'ما هي المخططات الوثائقية؟', - whatDescription: 'المخططات الوثائقية هي محتوى مُعرّف مسبقًا يمكن تحديده عند إنشاء عقدة محتوى جديدة.', - createHeadline: 'كيف يمكنني إنشاء مخطط وثائقي؟', - createDescription: '

      هناك طريقتان لإنشاء مخطط وثائقي:

      • انقر بزر الماوس الأيمن على عقدة المحتوى واختر "إنشاء مخطط وثائقي" لإنشاء مخطط وثائقي جديد.
      • انقر بزر الماوس الأيمن على شجرة المخططات الوثائقية في قسم الإعدادات واختر نوع الوثيقة الذي تريد إنشاء مخطط وثائقي له.

      بمجرد إعطائها اسمًا، يمكن للمحررين البدء في استخدام المخطط الوثائقي كأساس لصفحتهم الجديدة.

      ', - manageHeadline: 'كيف يمكنني إدارة المخططات الوثائقية؟', - manageDescription: 'يمكنك تعديل وحذف المخططات الوثائقية من "شجرة المخططات الوثائقية" في قسم الإعدادات. قم بتوسيع نوع الوثيقة الذي يعتمد عليه المخطط الوثائقي وانقر عليه لتعديله أو حذفه.' - }, - preview: { - endLabel: 'نهاية', - endTitle: 'إنهاء وضع المعاينة', - openWebsiteLabel: 'معاينة الموقع', - openWebsiteTitle: 'فتح الموقع في وضع المعاينة', - returnToPreviewHeadline: 'معاينة الموقع؟', - returnToPreviewDescription: 'لقد انتهيت من وضع المعاينة، هل ترغب في تمكينه مرة أخرى لعرض أحدث إصدار محفوظ من موقعك؟', - returnToPreviewAcceptButton: 'معاينة أحدث إصدار', - returnToPreviewDeclineButton: 'عرض الإصدار المنشور', - viewPublishedContentHeadline: 'عرض الإصدار المنشور؟', - viewPublishedContentDescription: 'أنت في وضع المعاينة، هل تريد الخروج لعرض الإصدار المنشور لموقعك؟', - viewPublishedContentAcceptButton: 'عرض الإصدار المنشور', - viewPublishedContentDeclineButton: 'البقاء في وضع المعاينة' - }, - permissions: { - FolderCreation: 'إنشاء مجلد', - FileWritingForPackages: 'كتابة الملفات للحزم', - FileWriting: 'كتابة الملفات', - MediaFolderCreation: 'إنشاء مجلد الوسائط' - }, - treeSearch: { - searchResult: 'عنصر تم إرجاعه', - searchResults: 'عناصر تم إرجاعها' - }, - analytics: { - consentForAnalytics: 'الموافقة على بيانات التتبع', - analyticsLevelSavedSuccess: 'تم حفظ مستوى التتبع!', - analyticsDescription: '\n لتحسين Umbraco وإضافة ميزات جديدة بناءً على معلومات ذات صلة قدر الإمكان،\n
      نود جمع معلومات النظام والاستخدام من تثبيتك.\n
      سيتم مشاركة البيانات المجمعة بانتظام بالإضافة إلى الدروس المستفادة من هذه المقاييس.\n
      نأمل أن تساعدنا في جمع بعض البيانات القيمة.\n
      \n
      نحن لن نقوم بجمع أي بيانات شخصية مثل المحتوى أو الكود أو معلومات المستخدم، وستكون جميع البيانات مجهولة الهوية تمامًا.\n ', - minimalLevelDescription: 'سوف نرسل فقط معرف موقع مجهول الهوية لإعلامنا بوجود الموقع.', - basicLevelDescription: 'سوف نرسل معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة', - detailedLevelDescription: '\n سوف نرسل:\n
        \n
      • معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة.
      • \n
      • عدد: العقد الجذرية، العقد المحتوى، الوسائط، أنواع الوثائق، القوالب، اللغات، النطاقات، مجموعات المستخدمين، المستخدمين، الأعضاء، مقدمي تسجيل الدخول الخارجيين إلى المكتب الخلفي، ومحرري الخصائص قيد الاستخدام.
      • \n
      • معلومات النظام: خادم الويب، نظام تشغيل الخادم، إطار عمل الخادم، لغة نظام تشغيل الخادم، ومزود قاعدة البيانات.
      • \n
      • إعدادات التكوين: وضع Modelsbuilder، إذا كان هناك مسار Umbraco مخصص، بيئة ASP، ما إذا كان API التوصيل مفعلًا، ويتيح الوصول العام، وإذا كنت في وضع التصحيح.
      • \n
      \n قد نغير ما نرسله على المستوى التفصيلي في المستقبل. إذا كان الأمر كذلك، فسيتم سردها أعلاه.\n
      من خلال اختيار "تفصيلي" توافق على جمع المعلومات المجهولة الهوية الحالية والمستقبلية.
      \n ' - }, - routing: { - routeNotFoundTitle: 'لم يتم العثور على الصفحة', - routeNotFoundDescription: 'لم يتم العثور على المسار المطلوب. يرجى التحقق من عنوان URL والمحاولة مرة أخرى.' - }, - codeEditor: { - label: 'محرر الأكواد', - languageConfigLabel: 'اللغة', - languageConfigDescription: 'اختر اللغة لتظليل بناء الجملة وIntelliSense.', - heightConfigLabel: 'الارتفاع', - heightConfigDescription: 'حدد ارتفاع محرر الأكواد بالبكسل.', - lineNumbersConfigLabel: 'أرقام الأسطر', - lineNumbersConfigDescription: 'عرض أرقام الأسطر في محرر الأكواد.', - minimapConfigLabel: 'خريطة مصغرة', - minimapConfigDescription: 'عرض خريطة مصغرة في محرر الأكواد.', - wordWrapConfigLabel: 'تغليف الكلمات', - wordWrapConfigDescription: 'تفعيل تغليف الكلمات في محرر الأكواد.' - } + logViewer: { + deleteSavedSearch: 'حذف البحث المحفوظ', + logLevels: 'مستويات السجل', + selectAllLogLevelFilters: 'تحديد الكل', + deselectAllLogLevelFilters: 'إلغاء تحديد الكل', + savedSearches: 'البحث المحفوظ', + saveSearch: 'حفظ البحث', + saveSearchDescription: 'أدخل اسمًا وديًا لاستعلام البحث الخاص بك', + filterSearch: 'تصفية البحث', + totalItems: 'إجمالي العناصر', + timestamp: 'الطابع الزمني', + level: 'المستوى', + machine: 'الآلة', + message: 'الرسالة', + exception: 'الاستثناء', + properties: 'الخصائص', + searchWithGoogle: 'البحث باستخدام جوجل', + searchThisMessageWithGoogle: 'ابحث عن هذه الرسالة باستخدام جوجل', + searchWithBing: 'البحث باستخدام بينج', + searchThisMessageWithBing: 'ابحث عن هذه الرسالة باستخدام بينج', + searchOurUmbraco: 'البحث في Umbraco الخاص بنا', + searchThisMessageOnOurUmbracoForumsAndDocs: 'ابحث عن هذه الرسالة في منتديات ومراسلات Umbraco الخاصة بنا', + searchOurUmbracoWithGoogle: 'البحث في Umbraco الخاص بنا باستخدام جوجل', + searchOurUmbracoForumsUsingGoogle: 'البحث في منتديات Umbraco الخاصة بنا باستخدام جوجل', + searchUmbracoSource: 'البحث في مصدر Umbraco', + searchWithinUmbracoSourceCodeOnGithub: 'البحث ضمن كود مصدر Umbraco على Github', + searchUmbracoIssues: 'البحث في قضايا Umbraco', + searchUmbracoIssuesOnGithub: 'البحث في قضايا Umbraco على Github', + deleteThisSearch: 'حذف هذا البحث', + findLogsWithRequestId: 'البحث في السجلات باستخدام معرّف الطلب', + findLogsWithNamespace: 'البحث في السجلات باستخدام النطاق', + findLogsWithMachineName: 'البحث في السجلات باستخدام اسم الآلة', + open: 'فتح', + polling: 'استطلاع', + every2: 'كل 2 ثانية', + every5: 'كل 5 ثوانٍ', + every10: 'كل 10 ثوانٍ', + every20: 'كل 20 ثانية', + every30: 'كل 30 ثانية', + pollingEvery2: 'استطلاع كل 2 ثانية', + pollingEvery5: 'استطلاع كل 5 ثوانٍ', + pollingEvery10: 'استطلاع كل 10 ثوانٍ', + pollingEvery20: 'استطلاع كل 20 ثانية', + pollingEvery30: 'استطلاع كل 30 ثانية', + }, + clipboard: { + labelForCopyAllEntries: 'نسخ %0%', + labelForArrayOfItemsFrom: '%0% من %1%', + labelForArrayOfItems: 'مجموعة من %0%', + labelForRemoveAllEntries: 'إزالة جميع العناصر', + labelForClearClipboard: 'مسح الحافظة', + labelForCopyToClipboard: 'نسخ إلى الحافظة', + }, + propertyActions: { + tooltipForPropertyActionsMenu: 'فتح إجراءات الخصائص', + tooltipForPropertyActionsMenuClose: 'إغلاق إجراءات الخصائص', + }, + nuCache: { + refreshStatus: 'تحديث الحالة', + memoryCache: 'ذاكرة التخزين المؤقت', + memoryCacheDescription: + 'هذا الزر يتيح لك إعادة تحميل ذاكرة التخزين المؤقت في الذاكرة، من خلال إعادة تحميلها بالكامل من قاعدة البيانات (ولكنه لا يعيد بناء تلك الذاكرة المؤقتة في قاعدة البيانات). هذا سريع نسبيًا. استخدمه عندما تعتقد أن ذاكرة التخزين المؤقت في الذاكرة لم يتم تحديثها بشكل صحيح، بعد بعض الأحداث التي تم تشغيلها—مما قد يشير إلى مشكلة طفيفة في Umbraco. (ملاحظة: يشغل إعادة التحميل على جميع الخوادم في بيئة LB).', + reload: 'إعادة تحميل', + databaseCache: 'ذاكرة التخزين المؤقت لقاعدة البيانات', + databaseCacheDescription: + 'هذا الزر يتيح لك إعادة بناء ذاكرة التخزين المؤقت لقاعدة البيانات، أي محتوى جدول cmsContentNu. إعادة البناء يمكن أن تكون مكلفة. استخدمه عندما لا يكون إعادة التحميل كافيًا، وتعتقد أن ذاكرة التخزين المؤقت لقاعدة البيانات لم يتم إنشاؤها بشكل صحيح—مما قد يشير إلى مشكلة حاسمة في Umbraco.', + rebuild: 'إعادة بناء', + internals: 'الأنظمة الداخلية', + internalsDescription: + 'هذا الزر يتيح لك تشغيل مجموعة لقطات NuCache (بعد تشغيل GC الكامل). ما لم تكن تعرف ما يعني ذلك، فمن المحتمل أنك لا تحتاج إلى استخدامه.', + collect: 'جمع', + publishedCacheStatus: 'حالة ذاكرة التخزين المؤقت المنشورة', + caches: 'ذاكرات التخزين المؤقت', + }, + profiling: { + performanceProfiling: 'تحليل الأداء', + performanceProfilingDescription: + '

      تشغيل Umbraco حاليًا في وضع التصحيح. هذا يعني أنه يمكنك استخدام أداة تحليل الأداء المدمجة لتقييم الأداء عند عرض الصفحات.

      إذا كنت تريد تفعيل أداة التحليل لعرض صفحة معينة، أضف ببساطة umbDebug=true إلى سلسلة الاستعلام عند طلب الصفحة.

      إذا كنت تريد أن يتم تفعيل أداة التحليل بشكل افتراضي لجميع عمليات عرض الصفحات، يمكنك استخدام التبديل أدناه. سيقوم بتعيين ملف تعريف في متصفحك، والذي يقوم بعد ذلك بتفعيل أداة التحليل تلقائيًا. بعبارة أخرى، ستكون أداة التحليل نشطة افتراضيًا فقط في متصفحك - وليس في متصفحات الآخرين.

      ', + activateByDefault: 'تفعيل أداة التحليل بشكل افتراضي', + reminder: 'تذكير ودي', + reminderDescription: + '

      يجب ألا تدع موقع الإنتاج يعمل في وضع التصحيح. يتم إيقاف وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى false في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

      ', + profilerEnabledDescription: + '

      Umbraco حاليًا لا يعمل في وضع التصحيح، لذا لا يمكنك استخدام أداة التحليل المدمجة. هذا هو الوضع الصحيح لموقع الإنتاج.

      يتم تشغيل وضع التصحيح عن طريق تعيين Umbraco:CMS:Hosting:Debug إلى true في appsettings.json أو appsettings.{Environment}.json أو عبر متغير بيئة.

      ', + }, + settingsDashboardVideos: { + trainingHeadline: 'ساعات من مقاطع فيديو تدريب Umbraco على بعد نقرة واحدة', + trainingDescription: + '

      هل تريد إتقان Umbraco؟ اقض بضع دقائق في تعلم بعض الممارسات الأفضل من خلال مشاهدة واحدة من هذه الفيديوهات حول استخدام Umbraco. وزيارة umbraco.tv لمزيد من مقاطع الفيديو حول Umbraco

      ', + }, + settingsDashboard: { + documentationHeader: 'التوثيق', + documentationDescription: 'اقرأ المزيد عن العمل مع العناصر في الإعدادات في توثيقنا.', + communityHeader: 'المجتمع', + communityDescription: 'اطرح سؤالاً في منتدى المجتمع أو مجتمع Discord لدينا.', + trainingHeader: 'التدريب', + trainingDescription: 'اكتشف فرص التدريب والتأهيل الرسمية', + supportHeader: 'الدعم', + supportDescription: 'قم بتوسيع فريقك مع مجموعة ماهرة ومتحمسة من خبراء Umbraco.', + videosHeader: 'مقاطع الفيديو', + videosDescription: + 'شاهد مقاطع الفيديو التعليمية المجانية لدينا على قناة YouTube الخاصة بأساسيات Umbraco، لتصبح على اطلاع سريع بـ Umbraco.', + getHelp: 'احصل على المساعدة التي تحتاجها', + getCertified: 'احصل على الشهادة', + goForum: 'اذهب إلى المنتدى', + chatWithCommunity: 'الدردشة مع المجتمع', + watchVideos: 'شاهد مقاطع الفيديو', + }, + startupDashboard: { + fallbackHeadline: 'مرحبًا بك في نظام إدارة المحتوى الودود', + fallbackDescription: + 'شكرًا لاختيارك Umbraco - نعتقد أن هذه قد تكون بداية شيء جميل. بينما قد يبدو الأمر مربكًا في البداية، لقد بذلنا الكثير لجعل منحنى التعلم سلسًا وسريعًا قدر الإمكان.', + }, + welcomeDashboard: { + ourUmbracoHeadline: 'Umbraco الخاص بنا - أكثر المجتمعات صداقة', + ourUmbracoDescription: + 'Umbraco الخاص بنا، الموقع الرسمي للمجتمع، هو وجهتك الشاملة لكل شيء متعلق بـ Umbraco. سواء كنت بحاجة إلى إجابة على سؤال، أو إضافات رائعة، أو دليل حول كيفية القيام بشيء ما في Umbraco، فإن أفضل وأصدق مجتمع في العالم هو مجرد نقرة بعيدًا.', + ourUmbracoButton: 'زيارة Umbraco الخاص بنا', + documentationHeadline: 'التوثيق', + documentationDescription: 'ابحث عن إجابات لجميع أسئلتك حول Umbraco', + communityHeadline: 'المجتمع', + communityDescription: 'احصل على الدعم والإلهام من خبراء Umbraco المتحمسين', + resourcesHeadline: 'الموارد', + resourcesDescription: 'دروس فيديو مجانية لبدء رحلتك مع نظام إدارة المحتوى', + trainingHeadline: 'التدريب', + trainingDescription: 'التدريب الواقعي وشهادات Umbraco الرسمية', + }, + blockEditor: { + headlineCreateBlock: 'اختيار نوع العنصر', + headlineAddSettingsElementType: 'إضافة نوع عنصر الإعدادات', + headlineAddCustomView: 'اختيار العرض', + headlineAddCustomStylesheet: 'اختيار ورقة الأنماط', + headlineAddThumbnail: 'اختيار الصورة المصغرة', + labelcreateNewElementType: 'إنشاء نوع عنصر جديد', + labelCustomStylesheet: 'ورقة أنماط مخصصة', + addCustomStylesheet: 'إضافة ورقة أنماط', + headlineEditorAppearance: 'مظهر الكتلة', + headlineDataModels: 'نماذج البيانات', + headlineCatalogueAppearance: 'مظهر الكتالوج', + labelBackgroundColor: 'لون الخلفية', + labelIconColor: 'لون الأيقونة', + labelContentElementType: 'نموذج المحتوى', + labelLabelTemplate: 'التسمية', + labelCustomView: 'عرض مخصص', + labelCustomViewInfoTitle: 'عرض وصف العرض المخصص', + labelCustomViewDescription: + 'تجاوز كيفية ظهور هذه الكتلة في واجهة المستخدم الخلفية. اختر ملف .html يحتوي على تقديمك.', + labelSettingsElementType: 'نموذج الإعدادات', + labelEditorSize: 'حجم محرر التراكب', + addCustomView: 'إضافة عرض مخصص', + addSettingsElementType: 'إضافة إعدادات', + confirmDeleteBlockMessage: 'هل أنت متأكد أنك تريد حذف المحتوى %0%؟', + confirmDeleteBlockTypeMessage: 'هل أنت متأكد أنك تريد حذف تكوين الكتلة %0%؟', + confirmDeleteBlockTypeNotice: + 'سيظل محتوى هذه الكتلة موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', + confirmDeleteBlockGroupMessage: + 'هل أنت متأكد أنك تريد حذف المجموعة %0% وجميع تكوينات الكتلة الخاصة بها؟', + confirmDeleteBlockGroupNotice: + 'سيظل محتوى هذه الكتل موجودًا، ولكن تحرير هذا المحتوى لن يكون متاحًا وسيظهر كمحتوى غير مدعوم.', + blockConfigurationOverlayTitle: "تكوين '%0%'", + elementTypeDoesNotExist: 'لا يمكن تحريره لأن نوع العنصر غير موجود.', + thumbnail: 'صورة مصغرة', + addThumbnail: 'إضافة صورة مصغرة', + tabCreateEmpty: 'إنشاء فارغ', + tabClipboard: 'الحافظة', + tabBlockSettings: 'الإعدادات', + headlineAdvanced: 'متقدم', + headlineCustomView: 'عرض مخصص', + forceHideContentEditor: 'إخفاء محرر المحتوى', + forceHideContentEditorHelp: 'إخفاء زر تحرير المحتوى ومحرر المحتوى من تراكب محرر الكتل', + gridInlineEditing: 'تحرير مباشر', + gridInlineEditingHelp: 'يتيح التحرير المباشر لأول خاصية. يمكن تحرير الخصائص الإضافية في التراكب.', + blockHasChanges: 'لقد أجريت تغييرات على هذا المحتوى. هل أنت متأكد أنك تريد تجاهلها؟', + confirmCancelBlockCreationHeadline: 'تجاهل الإنشاء؟', + confirmCancelBlockCreationMessage: 'هل أنت متأكد أنك تريد إلغاء الإنشاء.', + elementTypeDoesNotExistHeadline: 'خطأ!', + elementTypeDoesNotExistDescription: 'نوع العنصر لهذه الكتلة لم يعد موجودًا', + addBlock: 'إضافة محتوى', + addThis: 'إضافة %0%', + propertyEditorNotSupported: "الخاصية '%0%' تستخدم المحرر '%1%' والذي لا يدعمه الكتل.", + focusParentBlock: 'تعيين التركيز على الكتلة الحاوية', + areaIdentification: 'التحديد', + areaValidation: 'التحقق', + areaValidationEntriesShort: '%0% يجب أن تكون موجودة على الأقل %2% مرة(s).', + areaValidationEntriesExceed: '%0% يجب أن تكون موجودة بحد أقصى %3% مرة(s).', + areaNumberOfBlocks: 'عدد الكتل', + areaDisallowAllBlocks: 'السماح بأنواع كتل محددة فقط', + areaAllowedBlocks: 'أنواع الكتل المسموح بها', + areaAllowedBlocksHelp: + 'حدد أنواع الكتل المسموح بها في هذه المنطقة، واختياريًا عدد كل نوع من الأنواع التي يجب أن تكون موجودة.', + confirmDeleteBlockAreaMessage: 'هل أنت متأكد أنك تريد حذف هذه المنطقة؟', + confirmDeleteBlockAreaNotice: 'أي كتل تم إنشاؤها حاليًا داخل هذه المنطقة سيتم حذفها.', + layoutOptions: 'خيارات التخطيط', + structuralOptions: 'هيكلية', + sizeOptions: 'خيارات الحجم', + sizeOptionsHelp: 'حدد خيارًا أو أكثر من خيارات الحجم، هذا يمكن أن يتيح تغيير حجم الكتلة', + allowedBlockColumns: 'امتدادات الأعمدة المتاحة', + allowedBlockColumnsHelp: + 'حدد عدد الأعمدة المختلفة التي يُسمح لهذه الكتلة بالامتداد عبرها. هذا لا يمنع الكتل من وضعها في مناطق ذات امتداد أعمدة أصغر.', + allowedBlockRows: 'امتدادات الصفوف المتاحة', + allowedBlockRowsHelp: 'حدد نطاق الصفوف التخطيطية التي يُسمح لهذه الكتلة بالامتداد عبرها.', + allowBlockInRoot: 'السماح في الجذر', + allowBlockInRootHelp: 'اجعل هذه الكتلة متاحة في جذر التخطيط.', + allowBlockInAreas: 'السماح في المناطق', + allowBlockInAreasHelp: + 'اجعل هذه الكتلة متاحة افتراضيًا ضمن مناطق كتل أخرى (ما لم يتم تعيين أذونات صريحة لهذه المناطق).', + areaAllowedBlocksEmpty: + 'افتراضيًا، جميع أنواع الكتل مسموح بها في منطقة، استخدم هذا الخيار للسماح بأنواع محددة فقط.', + areas: 'المناطق', + areasLayoutColumns: 'أعمدة الشبكة للمناطق', + areasLayoutColumnsHelp: + 'حدد عدد الأعمدة المتاحة للمناطق. إذا لم يتم تحديدها، سيتم استخدام عدد الأعمدة المحدد للتخطيط الكامل.', + areasConfigurations: 'المناطق', + areasConfigurationsHelp: + 'لتمكين تداخل الكتل داخل هذه الكتلة، حدد منطقة واحدة أو أكثر. تتبع المناطق التخطيط المحدد من خلال تكوين عمود الشبكة الخاص بها. يمكن تعديل "امتداد العمود" و "امتداد الصف" لكل منطقة باستخدام مربع مقبض التدرج في الزاوية السفلى اليمنى من المنطقة المحددة.', + invalidDropPosition: '%0% غير مسموح به في هذا الموضع.', + defaultLayoutStylesheet: 'ورقة أنماط التخطيط الافتراضية', + confirmPasteDisallowedNestedBlockHeadline: 'تم رفض المحتوى غير المسموح به', + confirmPasteDisallowedNestedBlockMessage: + 'احتوى المحتوى الذي تم إدراجه على محتوى غير مسموح به، والذي لم يتم إنشاؤه. هل ترغب في الاحتفاظ ببقية هذا المحتوى على أي حال؟', + areaAliasHelp: + 'عند استخدام GetBlockGridHTML() لعرض شبكة الكتل، سيتم عرض الاسم المستعار في الشيفرة المصدرية كخاصية \'data-area-alias\'. استخدم خاصية الاسم المستعار لاستهداف العنصر للمنطقة. مثال. .umb-block-grid__area[data-area-alias="MyAreaAlias"] { ... }', + scaleHandlerButtonTitle: 'اسحب للتغيير الحجم', + areaCreateLabelTitle: 'تسمية زر الإنشاء', + areaCreateLabelHelp: 'تجاوز نص التسمية لإضافة كتلة جديدة إلى هذه المنطقة، مثال: "إضافة عنصر واجهة المستخدم"', + showSizeOptions: 'عرض خيارات تغيير الحجم', + addBlockType: 'إضافة كتلة', + addBlockGroup: 'إضافة مجموعة', + pickSpecificAllowance: 'اختر مجموعة أو كتلة', + allowanceMinimum: 'تحديد الحد الأدنى المطلوب', + allowanceMaximum: 'تحديد الحد الأقصى المطلوب', + block: 'كتلة', + tabBlock: 'كتلة', + tabBlockTypeSettings: 'الإعدادات', + tabAreas: 'المناطق', + tabAdvanced: 'متقدم', + headlineAllowance: 'الأذونات', + getSampleHeadline: 'تثبيت التكوين التجريبي', + getSampleDescription: + 'سيضيف هذا كتل أساسية ويساعدك على البدء باستخدام محرر شبكة الكتل. ستحصل على كتل للعناوين والنصوص الغنية والصور، بالإضافة إلى تخطيط بعمودين.', + getSampleButton: 'تثبيت', + actionEnterSortMode: 'وضع الترتيب', + actionExitSortMode: 'إنهاء وضع الترتيب', + areaAliasIsNotUnique: 'يجب أن يكون اسم المنطقة هذا فريد مقارنةً بالمناطق الأخرى لهذه الكتلة.', + configureArea: 'تكوين المنطقة', + deleteArea: 'حذف المنطقة', + addColumnSpanOption: 'إضافة خيار امتداد %0% عمود', + }, + contentTemplatesDashboard: { + whatHeadline: 'ما هي المخططات الوثائقية؟', + whatDescription: 'المخططات الوثائقية هي محتوى مُعرّف مسبقًا يمكن تحديده عند إنشاء عقدة محتوى جديدة.', + createHeadline: 'كيف يمكنني إنشاء مخطط وثائقي؟', + createDescription: + '

      هناك طريقتان لإنشاء مخطط وثائقي:

      • انقر بزر الماوس الأيمن على عقدة المحتوى واختر "إنشاء مخطط وثائقي" لإنشاء مخطط وثائقي جديد.
      • انقر بزر الماوس الأيمن على شجرة المخططات الوثائقية في قسم الإعدادات واختر نوع الوثيقة الذي تريد إنشاء مخطط وثائقي له.

      بمجرد إعطائها اسمًا، يمكن للمحررين البدء في استخدام المخطط الوثائقي كأساس لصفحتهم الجديدة.

      ', + manageHeadline: 'كيف يمكنني إدارة المخططات الوثائقية؟', + manageDescription: + 'يمكنك تعديل وحذف المخططات الوثائقية من "شجرة المخططات الوثائقية" في قسم الإعدادات. قم بتوسيع نوع الوثيقة الذي يعتمد عليه المخطط الوثائقي وانقر عليه لتعديله أو حذفه.', + }, + preview: { + endLabel: 'نهاية', + endTitle: 'إنهاء وضع المعاينة', + openWebsiteLabel: 'معاينة الموقع', + openWebsiteTitle: 'فتح الموقع في وضع المعاينة', + returnToPreviewHeadline: 'معاينة الموقع؟', + returnToPreviewDescription: + 'لقد انتهيت من وضع المعاينة، هل ترغب في تمكينه مرة أخرى لعرض أحدث إصدار محفوظ من موقعك؟', + returnToPreviewAcceptButton: 'معاينة أحدث إصدار', + returnToPreviewDeclineButton: 'عرض الإصدار المنشور', + viewPublishedContentHeadline: 'عرض الإصدار المنشور؟', + viewPublishedContentDescription: 'أنت في وضع المعاينة، هل تريد الخروج لعرض الإصدار المنشور لموقعك؟', + viewPublishedContentAcceptButton: 'عرض الإصدار المنشور', + viewPublishedContentDeclineButton: 'البقاء في وضع المعاينة', + }, + permissions: { + FolderCreation: 'إنشاء مجلد', + FileWritingForPackages: 'كتابة الملفات للحزم', + FileWriting: 'كتابة الملفات', + MediaFolderCreation: 'إنشاء مجلد الوسائط', + }, + treeSearch: { + searchResult: 'عنصر تم إرجاعه', + searchResults: 'عناصر تم إرجاعها', + }, + analytics: { + consentForAnalytics: 'الموافقة على بيانات التتبع', + analyticsLevelSavedSuccess: 'تم حفظ مستوى التتبع!', + analyticsDescription: + '\n لتحسين Umbraco وإضافة ميزات جديدة بناءً على معلومات ذات صلة قدر الإمكان،\n
      نود جمع معلومات النظام والاستخدام من تثبيتك.\n
      سيتم مشاركة البيانات المجمعة بانتظام بالإضافة إلى الدروس المستفادة من هذه المقاييس.\n
      نأمل أن تساعدنا في جمع بعض البيانات القيمة.\n
      \n
      نحن لن نقوم بجمع أي بيانات شخصية مثل المحتوى أو الكود أو معلومات المستخدم، وستكون جميع البيانات مجهولة الهوية تمامًا.\n ', + minimalLevelDescription: 'سوف نرسل فقط معرف موقع مجهول الهوية لإعلامنا بوجود الموقع.', + basicLevelDescription: 'سوف نرسل معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة', + detailedLevelDescription: + '\n سوف نرسل:\n
        \n
      • معرف موقع مجهول الهوية، إصدار Umbraco، والحزم المثبتة.
      • \n
      • عدد: العقد الجذرية، العقد المحتوى، الوسائط، أنواع الوثائق، القوالب، اللغات، النطاقات، مجموعات المستخدمين، المستخدمين، الأعضاء، مقدمي تسجيل الدخول الخارجيين إلى المكتب الخلفي، ومحرري الخصائص قيد الاستخدام.
      • \n
      • معلومات النظام: خادم الويب، نظام تشغيل الخادم، إطار عمل الخادم، لغة نظام تشغيل الخادم، ومزود قاعدة البيانات.
      • \n
      • إعدادات التكوين: وضع Modelsbuilder، إذا كان هناك مسار Umbraco مخصص، بيئة ASP، ما إذا كان API التوصيل مفعلًا، ويتيح الوصول العام، وإذا كنت في وضع التصحيح.
      • \n
      \n قد نغير ما نرسله على المستوى التفصيلي في المستقبل. إذا كان الأمر كذلك، فسيتم سردها أعلاه.\n
      من خلال اختيار "تفصيلي" توافق على جمع المعلومات المجهولة الهوية الحالية والمستقبلية.
      \n ', + }, + routing: { + routeNotFoundTitle: 'لم يتم العثور على الصفحة', + routeNotFoundDescription: 'لم يتم العثور على المسار المطلوب. يرجى التحقق من عنوان URL والمحاولة مرة أخرى.', + }, + codeEditor: { + label: 'محرر الأكواد', + languageConfigLabel: 'اللغة', + languageConfigDescription: 'اختر اللغة لتظليل بناء الجملة وIntelliSense.', + heightConfigLabel: 'الارتفاع', + heightConfigDescription: 'حدد ارتفاع محرر الأكواد بالبكسل.', + lineNumbersConfigLabel: 'أرقام الأسطر', + lineNumbersConfigDescription: 'عرض أرقام الأسطر في محرر الأكواد.', + minimapConfigLabel: 'خريطة مصغرة', + minimapConfigDescription: 'عرض خريطة مصغرة في محرر الأكواد.', + wordWrapConfigLabel: 'تغليف الكلمات', + wordWrapConfigDescription: 'تفعيل تغليف الكلمات في محرر الأكواد.', + }, } as UmbLocalizationDictionary; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts index cce0b9a4f2..0139e7ba5d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts @@ -10,7 +10,6 @@ export interface ManifestEntityCreateOptionAction< meta: MetaType; } -// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface MetaEntityCreateOptionAction { /** * An icon to represent the action to be performed diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts index cec662b335..576c677f65 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/manifests.ts @@ -260,5 +260,5 @@ export const manifests: Array = [ culture: 'zh-tw', }, js: () => import('../../../assets/lang/zh-tw.js'), - } + }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts index 8ac5aaaf70..cbf60d85a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.element.ts @@ -1,10 +1,10 @@ +import type { ManifestMenu } from '../menu.extension.js'; import type { ManifestSectionSidebarAppBaseMenu, ManifestSectionSidebarAppMenuKind } from './types.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { ManifestMenu } from '../menu.extension.js'; // TODO: Move to separate file: const manifest: UmbExtensionManifestKind = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts index 5ada737930..a63effc1e6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts @@ -114,17 +114,17 @@ export class UmbPropertyEditorUITinyMceToolbarConfigurationElement override render() { return html`
        - ${repeat( - this._toolbarConfig, - (v) => v.alias, + ${repeat( + this._toolbarConfig, + (v) => v.alias, (v) => html`
      • - - + + ${v.label} - +
      • `, - )} + )}
      `; } From 6b6b05c7269570becc26982406474f9f2f8ebf00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 12:39:31 +0100 Subject: [PATCH 169/246] type export --- .../src/packages/core/entity-create-option-action/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index 1794649010..9d1c5d4520 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,4 +1,4 @@ export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; -export * from './types.js'; +export type * from './types.js'; From 5be1e8ef0a09386b167a1957a9956c15f928f90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 12:42:21 +0100 Subject: [PATCH 170/246] update all-packages list --- src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts b/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts index 11e3b72b14..2f8a997a00 100644 --- a/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts +++ b/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts @@ -33,6 +33,7 @@ import '@umbraco-cms/backoffice/document-type'; import '@umbraco-cms/backoffice/document'; import '@umbraco-cms/backoffice/entity-action'; import '@umbraco-cms/backoffice/entity-bulk-action'; +import '@umbraco-cms/backoffice/entity-create-option-action'; import '@umbraco-cms/backoffice/entity'; import '@umbraco-cms/backoffice/event'; import '@umbraco-cms/backoffice/extension-registry'; From bcc3073b2a57f8fecbde736915f141ca378436da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 13:31:50 +0100 Subject: [PATCH 171/246] constants --- .../src/packages/core/entity-create-option-action/constants.ts | 1 + .../entity-create-option-action.extension.ts | 3 ++- .../src/packages/core/entity-create-option-action/index.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts new file mode 100644 index 0000000000..4c25e59099 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts @@ -0,0 +1 @@ +export const UMB_EXTENSION_TYPE_ENTITY_CREATE_OPTION_ACTION = 'entityCreateOptionAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts index 0139e7ba5d..4f62ecd3de 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts @@ -1,11 +1,12 @@ import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; +import type { UMB_EXTENSION_TYPE_ENTITY_CREATE_OPTION_ACTION } from './constants.js'; import type { ManifestApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, > extends ManifestApi>, ManifestWithDynamicConditions { - type: 'entityCreateOptionAction'; + type: typeof UMB_EXTENSION_TYPE_ENTITY_CREATE_OPTION_ACTION; forEntityTypes: Array; meta: MetaType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index 9d1c5d4520..566d9306e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,3 +1,4 @@ +export * from './constants.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; From 15ac89271a03153320b5878aada4a94354fa46df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 13:31:55 +0100 Subject: [PATCH 172/246] jsdocs --- .../entity-create-option-action-base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts index 2800261185..236d7e6394 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts @@ -13,7 +13,7 @@ export abstract class UmbEntityCreateOptionActionBase< * By specifying the href, the action will act as a link. * The `execute` method will not be called. * @abstract - * @returns {string | undefined} + * @returns {string | undefined} - A promise which resolves into a HREF string or undefined. */ public getHref(): Promise { return Promise.resolve(undefined); From 004e58cd861e3606c0d714b1ac03e96b7677e189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 13:38:36 +0100 Subject: [PATCH 173/246] update vite.config for core package --- src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts index a4cb479492..5a0214273d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts @@ -23,6 +23,7 @@ export default defineConfig({ 'debug/index': './debug/index.ts', 'entity-action/index': './entity-action/index.ts', 'entity-bulk-action/index': './entity-bulk-action/index.ts', + 'entity-create-option-action/index': './entity-create-option-action/index.ts', 'entity/index': './entity/index.ts', 'entry-point': 'entry-point.ts', 'event/index': './event/index.ts', From 192c0d76e84cd46da3c7f67a03c2332dc51fdb23 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 4 Nov 2024 13:07:13 +0000 Subject: [PATCH 174/246] Bugfix: Block Type card thunbnail image path/URL (#2480) Block Type Cards: Fixed image URL Removed the backoffice path from the URL, as the image paths are relative to the root of the website. --- .../block-type-card/block-type-card.element.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts index 7acba0d8be..ec00d7fa94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts @@ -6,14 +6,14 @@ import { html, customElement, property, state, ifDefined } from '@umbraco-cms/ba import { UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; -import { removeLastSlashFromPath, transformServerPathToClientPath } from '@umbraco-cms/backoffice/utils'; +import { transformServerPathToClientPath } from '@umbraco-cms/backoffice/utils'; import { UUICardEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-block-type-card') export class UmbBlockTypeCardElement extends UmbLitElement { // #init: Promise; - #appUrl: string = ''; + #serverUrl: string = ''; #itemManager = new UmbRepositoryItemsManager( this, @@ -29,7 +29,8 @@ export class UmbBlockTypeCardElement extends UmbLitElement { value = transformServerPathToClientPath(value); if (value) { this.#init.then(() => { - this._iconFile = removeLastSlashFromPath(this.#appUrl) + value; + const url = new URL(value, this.#serverUrl); + this._iconFile = url.href; }); } else { this._iconFile = undefined; @@ -77,7 +78,7 @@ export class UmbBlockTypeCardElement extends UmbLitElement { super(); this.#init = this.getContext(UMB_APP_CONTEXT).then((appContext) => { - this.#appUrl = appContext.getServerUrl() + appContext.getBackofficePath(); + this.#serverUrl = appContext.getServerUrl(); }); this.observe(this.#itemManager.items, (items) => { From e93b86bdae90893c7cf676844299f7a3cb622bd7 Mon Sep 17 00:00:00 2001 From: Nathaniel Nunes Date: Mon, 4 Nov 2024 18:37:26 +0530 Subject: [PATCH 175/246] Feature: Set the URL field as required and focus on it (#2500) * Feature: Set the URL field as required and focus on it * Added mandatory asterix to webhook url label --------- Co-authored-by: Nathaniel Nunes --- .../views/webhook-details-workspace-view.element.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts index cab305752c..c727415667 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts @@ -2,7 +2,7 @@ import { UMB_WEBHOOK_WORKSPACE_CONTEXT } from '../webhook-workspace.context-toke import type { UmbInputWebhookHeadersElement } from '../../../components/input-webhook-headers.element.js'; import type { UmbInputWebhookEventsElement } from '../../../components/input-webhook-events.element.js'; import { css, customElement, html, state, nothing } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbInputDocumentTypeElement } from '@umbraco-cms/backoffice/document-type'; @@ -110,9 +110,15 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme return html` - + Date: Mon, 4 Nov 2024 18:37:26 +0530 Subject: [PATCH 176/246] Feature: Set the URL field as required and focus on it (#2500) * Feature: Set the URL field as required and focus on it * Added mandatory asterix to webhook url label --------- Co-authored-by: Nathaniel Nunes (cherry picked from commit e93b86bdae90893c7cf676844299f7a3cb622bd7) --- .../views/webhook-details-workspace-view.element.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts index cab305752c..c727415667 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts @@ -2,7 +2,7 @@ import { UMB_WEBHOOK_WORKSPACE_CONTEXT } from '../webhook-workspace.context-toke import type { UmbInputWebhookHeadersElement } from '../../../components/input-webhook-headers.element.js'; import type { UmbInputWebhookEventsElement } from '../../../components/input-webhook-events.element.js'; import { css, customElement, html, state, nothing } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbInputDocumentTypeElement } from '@umbraco-cms/backoffice/document-type'; @@ -110,9 +110,15 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme return html` - + Date: Mon, 4 Nov 2024 13:28:51 +0000 Subject: [PATCH 177/246] Hotfix: UFM alias prefixes (#2510) * Adds `alias` to UFM component registrations * Adds support for `alias` prefix in UFM syntax e.g. `{(alias:|marker)(text)}` would be `{umbContentName: propertyAlias}` or `{~propertyAlias}` * UFM Content Name: adds warning for using the `~` prefix marker The `~` prefix will be deprecated in a future major release. --- .../content-name/content-name.component.ts | 7 +++++++ .../src/packages/ufm/components/manifests.ts | 6 +++--- .../src/packages/ufm/contexts/ufm.context.ts | 2 +- .../src/packages/ufm/plugins/marked-ufm.plugin.ts | 11 +++++++---- .../src/packages/ufm/plugins/marked-ufm.test.ts | 12 +++++++++--- .../src/packages/ufm/ufm-component.extension.ts | 3 ++- 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts index dfcd5c6e2b..49a84361e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts @@ -7,6 +7,13 @@ export class UmbUfmContentNameComponent extends UmbUfmComponentBase { render(token: UfmToken) { if (!token.text) return; + if (token.prefix === '~') { + /* + * @deprecated since version 15.0-rc3 + */ + console.warn(`Please update your UFM syntax from \`${token.raw}\` to \`{umbContentName:${token.text}}\`.`); + } + const attributes = super.getAttributes(token.text); return ``; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts index 99ec024f17..b9c7f5dc6f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts @@ -6,20 +6,20 @@ export const manifests: Array = [ alias: 'Umb.Markdown.LabelValue', name: 'Label Value UFM Component', api: () => import('./label-value/label-value.component.js'), - meta: { marker: '=' }, + meta: { alias: 'umbValue', marker: '=' }, }, { type: 'ufmComponent', alias: 'Umb.Markdown.Localize', name: 'Localize UFM Component', api: () => import('./localize/localize.component.js'), - meta: { marker: '#' }, + meta: { alias: 'umbLocalize', marker: '#' }, }, { type: 'ufmComponent', alias: 'Umb.Markdown.ContentName', name: 'Content Name UFM Component', api: () => import('./content-name/content-name.component.js'), - meta: { marker: '~' }, + meta: { alias: 'umbContentName', marker: '~' }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts index 86563bc56d..a82415085e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts @@ -60,7 +60,7 @@ export class UmbUfmContext extends UmbContextBase { const ctrl = controller as unknown as UmbExtensionApiInitializer; if (!ctrl.manifest || !ctrl.api) return; return { - alias: ctrl.manifest.alias, + alias: ctrl.manifest.meta.alias || ctrl.manifest.alias, marker: ctrl.manifest.meta.marker, render: ctrl.api.render, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts index edebdefcca..604b4a4b1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts @@ -2,11 +2,12 @@ import type { MarkedExtension, Tokens } from '@umbraco-cms/backoffice/external/m export interface UfmPlugin { alias: string; - marker: string; + marker?: string; render?: (token: UfmToken) => string | undefined; } export interface UfmToken extends Tokens.Generic { + prefix: string; text?: string; } @@ -18,21 +19,23 @@ export interface UfmToken extends Tokens.Generic { export function ufm(plugins: Array = []): MarkedExtension { return { extensions: plugins.map(({ alias, marker, render }) => { + const prefix = `(${alias}:${marker ? `|${marker}` : ''})`; return { name: alias, level: 'inline', - start: (src: string) => src.indexOf(`{${marker}`), + start: (src: string) => src.search(`{${prefix}`), tokenizer: (src: string) => { - const pattern = `^\\{${marker}([^}]*)\\}`; + const pattern = `^\\{${prefix}([^}]*)\\}`; const regex = new RegExp(pattern); const match = src.match(regex); if (match) { - const [raw, content = ''] = match; + const [raw, prefix, content = ''] = match; return { type: alias, raw: raw, tokens: [], + prefix: prefix, text: content.trim(), }; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts index 71a2177ddb..565040a143 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts @@ -16,16 +16,22 @@ describe('UmbMarkedUfm', () => { ufm: '{= prop1 | strip-html | truncate:30}', expected: '', }, + { ufm: '{umbValue:prop1}', expected: '' }, { ufm: '{#general_add}', expected: '' }, + { ufm: '{umbLocalize:general_add}', expected: '' }, { ufm: '{~contentPicker}', expected: '' }, + { + ufm: '{umbContentName: contentPicker}', + expected: '', + }, ]; // Manually configuring the UFM components for testing. UmbMarked.use( ufm([ - { alias: 'Umb.Markdown.ContentName', marker: '~', render: new UmbUfmContentNameComponent().render }, - { alias: 'Umb.Markdown.LabelValue', marker: '=', render: new UmbUfmLabelValueComponent().render }, - { alias: 'Umb.Markdown.Localize', marker: '#', render: new UmbUfmLocalizeComponent().render }, + { alias: 'umbContentName', marker: '~', render: new UmbUfmContentNameComponent().render }, + { alias: 'umbValue', marker: '=', render: new UmbUfmLabelValueComponent().render }, + { alias: 'umbLocalize', marker: '#', render: new UmbUfmLocalizeComponent().render }, ]), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts index bf3c3ee9d5..bc321232e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts @@ -6,7 +6,8 @@ export interface UmbUfmComponentApi extends UmbApi { } export interface MetaUfmComponent { - marker: string; + alias: string; + marker?: string; } export interface ManifestUfmComponent extends ManifestApi { From 69d9cfab9affea197fc16dbddd5f4dfb116a2cbc Mon Sep 17 00:00:00 2001 From: Nathaniel Nunes Date: Mon, 4 Nov 2024 19:06:14 +0530 Subject: [PATCH 178/246] Allow for the document create options to be opened on space/enter clicked (#2501) allow for the document create options to be opened on space/enter clicked Co-authored-by: Nathaniel Nunes --- .../create/document-create-options-modal.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index a0eca87a0e..b31709a246 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -176,7 +176,8 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< .alias=${this.localize.string(documentType.description ?? '')} select-only selectable - @selected=${() => this.#onSelectDocumentType(documentType.unique)}> + @selected=${() => this.#onSelectDocumentType(documentType.unique)} + @open=${() => this.#onSelectDocumentType(documentType.unique)}> `, From 9a80b2cf8ca5d18b3d00bdaba0cce46d935e1f7f Mon Sep 17 00:00:00 2001 From: Nathaniel Nunes Date: Mon, 4 Nov 2024 19:06:14 +0530 Subject: [PATCH 179/246] Allow for the document create options to be opened on space/enter clicked (#2501) allow for the document create options to be opened on space/enter clicked Co-authored-by: Nathaniel Nunes (cherry picked from commit 69d9cfab9affea197fc16dbddd5f4dfb116a2cbc) --- .../create/document-create-options-modal.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index a0eca87a0e..b31709a246 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -176,7 +176,8 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< .alias=${this.localize.string(documentType.description ?? '')} select-only selectable - @selected=${() => this.#onSelectDocumentType(documentType.unique)}> + @selected=${() => this.#onSelectDocumentType(documentType.unique)} + @open=${() => this.#onSelectDocumentType(documentType.unique)}> `, From f0734cfef4d70064dda37c5a468e4912c5d3f1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 15:04:41 +0200 Subject: [PATCH 180/246] variant block validation --- .../property-editor-ui-block-list.element.ts | 1 - ...y-validation-path-translator.controller.ts | 28 ------------------- ...-validation-path-translator.controller.ts} | 0 ...s-validation-path-translator.controller.ts | 17 +++++++++++ .../packages/block/block/validation/index.ts | 3 +- .../block/workspace/block-element-manager.ts | 4 +++ ...-workspace-view-edit-properties.element.ts | 26 +++++++++++++++++ ...data-path-property-value-query.function.ts | 4 +-- 8 files changed, 51 insertions(+), 32 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts rename src/Umbraco.Web.UI.Client/src/packages/block/block/validation/{block-data-validation-path-translator.controller.ts => block-element-data-validation-path-translator.controller.ts} (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index f86b7c72c3..0ceb5e7abf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -117,7 +117,6 @@ export class UmbPropertyEditorUIBlockListElement /** * Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content. * @type {boolean} - * @attr * @default */ @property({ type: Boolean, reflect: true }) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts deleted file mode 100644 index 096eec3967..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-property-validation-path-translator.controller.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { - GetPropertyNameFromPath, - UmbDataPathPropertyValueQuery, - UmbValidationPathTranslatorBase, -} from '@umbraco-cms/backoffice/validation'; - -export class UmbBlockElementDataValidationPathTranslator extends UmbValidationPathTranslatorBase { - constructor(host: UmbControllerHost) { - super(host); - } - - translate(path: string) { - if (!this._context) return; - if (path.indexOf('$.') !== 0) { - // We do not handle this path. - return false; - } - - const rest = path.substring(2); - const key = GetPropertyNameFromPath(rest); - - const specificValue = { alias: key }; - // replace the values[ number ] with JSON-Path filter values[@.(...)], continues by the rest of the path: - //return '$.values' + UmbVariantValuesValidationPathTranslator(specificValue) + path.substring(path.indexOf(']')); - return '$.values[' + UmbDataPathPropertyValueQuery(specificValue) + '.value'; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-validation-path-translator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-data-validation-path-translator.controller.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-data-validation-path-translator.controller.ts rename to src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-data-validation-path-translator.controller.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts new file mode 100644 index 0000000000..2c2b9da88c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/block-element-values-validation-path-translator.controller.ts @@ -0,0 +1,17 @@ +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { + UmbAbstractArrayValidationPathTranslator, + UmbDataPathPropertyValueQuery, +} from '@umbraco-cms/backoffice/validation'; + +export class UmbBlockElementValuesDataValidationPathTranslator extends UmbAbstractArrayValidationPathTranslator { + constructor(host: UmbControllerHost) { + super(host, '$.values[', UmbDataPathPropertyValueQuery); + } + + getDataFromIndex(index: number) { + if (!this._context) return; + const data = this._context.getTranslationData(); + return data.values[index]; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts index 331352a0d8..f2af316128 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/index.ts @@ -1,2 +1,3 @@ -export * from './block-data-validation-path-translator.controller.js'; +export * from './block-element-values-validation-path-translator.controller.js'; +export * from './block-element-data-validation-path-translator.controller.js'; export * from './data-path-element-data-query.function.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index 65af1b54db..a0b151ab9b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -1,4 +1,5 @@ import type { UmbBlockDataModel, UmbBlockDataValueModel, UmbBlockLayoutBaseModel } from '../types.js'; +import { UmbBlockElementValuesDataValidationPathTranslator } from '../validation/block-element-values-validation-path-translator.controller.js'; import { UmbBlockElementPropertyDatasetContext } from './block-element-property-dataset.context.js'; import type { UmbBlockWorkspaceContext } from './block-workspace.context.js'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; @@ -226,6 +227,9 @@ export class UmbBlockElementManager { this.#blockWorkspace = workspaceContext; this._ownerEntityType = this.#blockWorkspace.getEntityType(); + this.observe( + workspaceContext.variantId, + (variantId) => { + this.#variantId = variantId; + this.#generatePropertyDataPath(); + }, + 'observeVariantId', + ); this.#setStructureManager(); }); } @@ -61,10 +73,24 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { ); } + /* #generatePropertyDataPath() { if (!this._propertyStructure) return; this._dataPaths = this._propertyStructure.map((property) => `$.${property.alias}`); } + */ + + #generatePropertyDataPath() { + if (!this.#variantId || !this._propertyStructure) return; + this._dataPaths = this._propertyStructure.map( + (property) => + `$.values[${UmbDataPathPropertyValueQuery({ + alias: property.alias, + culture: property.variesByCulture ? this.#variantId!.culture : null, + segment: property.variesBySegment ? this.#variantId!.segment : null, + })}].value`, + ); + } override render() { return repeat( diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts index d184f6e205..438b6e2d6e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts @@ -5,8 +5,8 @@ import type { UmbVariantPropertyValueModel } from '@umbraco-cms/backoffice/varia * Validation Data Path Query generator for Property Value. * write a JSON-Path filter similar to `?(@.alias = 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')` * where culture and segment are optional - * @param value - * @returns + * @param {UmbVariantPropertyValueModel} value - the object holding value and alias. + * @returns {string} - a JSON-path query */ export function UmbDataPathPropertyValueQuery( value: UmbPartialSome, 'culture' | 'segment'>, From ebbe5a955c751c46e7bfe94d381bec7d6ea20c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 15:14:32 +0200 Subject: [PATCH 181/246] update to use == in JSON Path Queries --- .../block-grid-entries.element.ts | 2 +- .../data-path-element-data-query.function.ts | 6 ++-- .../block/workspace/block-element-manager.ts | 2 +- .../src/packages/core/validation/README.md | 8 ++--- .../controllers/validation.controller.ts | 4 +-- ...data-path-property-value-query.function.ts | 8 ++--- .../utils/data-path-variant-query.function.ts | 4 +-- .../validation/utils/json-path.function.ts | 33 ++++++------------- .../core/validation/utils/json-path.test.ts | 2 +- 9 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts index 57047f4b4e..6c4a76df0e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts @@ -149,7 +149,7 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen // Currently there is no server validation for areas. So we can leave out the data path for it for now. [NL] this.#controlValidator = new UmbFormControlValidator(this, this); - //new UmbBindServerValidationToFormControl(this, this, "$.values.[?(@.alias = 'my-input-alias')].value"); + //new UmbBindServerValidationToFormControl(this, this, "$.values.[?(@.alias == 'my-input-alias')].value"); } } public get areaKey(): string | null | undefined { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts index 517e393897..1d624a3123 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/validation/data-path-element-data-query.function.ts @@ -2,14 +2,14 @@ import type { UmbBlockDataModel } from '../types.js'; /** * Validation Data Path Query generator for Block Element Data. - * write a JSON-Path filter similar to `?(@.key = 'my-key://1234')` + * write a JSON-Path filter similar to `?(@.key == 'my-key://1234')` * @param key {string} - The key of the block Element data. * @param data {{key: string}} - A data object with the key property. * @returns */ export function UmbDataPathBlockElementDataQuery(data: Pick): string { // write a array of strings for each property, where alias must be present and culture and segment are optional - //const filters: Array = [`@.key = '${key}'`]; + //const filters: Array = [`@.key == '${key}'`]; //return `?(${filters.join(' && ')})`; - return `?(@.key = '${data.key}')`; + return `?(@.key == '${data.key}')`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts index a0b151ab9b..bac6c7d5bd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-manager.ts @@ -69,7 +69,7 @@ export class UmbBlockElementManager this.structure.loadType(id)); this.observe(this.unique, (key) => { if (key) { - this.validation.setDataPath('$.' + dataPathPropertyName + `[?(@.key = '${key}')]`); + this.validation.setDataPath('$.' + dataPathPropertyName + `[?(@.key == '${key}')]`); } }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md b/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md index d034fb6ca4..b5a79df4e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/README.md @@ -15,7 +15,7 @@ A Validation message consist of a type, path and body. This typically looks like ``` { type: "client", - path: "$.values[?(@.alias = 'my-property-alias')].value", + path: "$.values[?(@.alias == 'my-property-alias')].value", message: "Must contain at least 3 words" } ``` @@ -61,7 +61,7 @@ Data: JsonPath: ``` -"$.values.[?(@.alias = 'my-alias')].value" +"$.values.[?(@.alias == 'my-alias')].value" ``` Paths are based on JSONPath, using JSON Path Queries when looking up data of an Array. Using Queries enables Paths to not point to specific index, but what makes a entry unique. @@ -107,7 +107,7 @@ Such conversation could be from this path: To this path: ``` -"$.values.[?(@.alias = 'my-alias')].value" +"$.values.[?(@.alias == 'my-alias')].value" ``` Once this path is converted to use Json Path Queries, the Data can be changed. The concerned entry might get another index. Without that affecting the accuracy of the path. @@ -135,7 +135,7 @@ The Data Path is a JSON Path defining where the data of this input is located in this.#validationMessageBinder = new UmbBindServerValidationToFormControl( this, this.querySelector('#myInput"), - "$.values.[?(@.alias = 'my-input-alias')].value", + "$.values.[?(@.alias == 'my-input-alias')].value", ); ``` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts index 499783244c..feaf76897a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts @@ -100,10 +100,10 @@ export class UmbValidationController extends UmbControllerBase implements UmbVal * @example * ```ts * const validationContext = new UmbValidationContext(this); - * validationContext.setDataPath("$.values[?(@.alias='my-property')].value"); + * validationContext.setDataPath("$.values[?(@.alias == 'my-property')].value"); * ``` * - * A message with the path: '$.values[?(@.alias='my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context. + * A message with the path: '$.values[?(@.alias == 'my-property')].value.innerProperty', will for above example become '$.innerProperty' for the local Validation Context. */ setDataPath(dataPath: string): void { if (this.#baseDataPath) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts index 438b6e2d6e..76fb54ce10 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-property-value-query.function.ts @@ -3,7 +3,7 @@ import type { UmbVariantPropertyValueModel } from '@umbraco-cms/backoffice/varia /** * Validation Data Path Query generator for Property Value. - * write a JSON-Path filter similar to `?(@.alias = 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')` + * write a JSON-Path filter similar to `?(@.alias == 'myAlias' && @.culture == 'en-us' && @.segment == 'mySegment')` * where culture and segment are optional * @param {UmbVariantPropertyValueModel} value - the object holding value and alias. * @returns {string} - a JSON-path query @@ -12,12 +12,12 @@ export function UmbDataPathPropertyValueQuery( value: UmbPartialSome, 'culture' | 'segment'>, ): string { // write a array of strings for each property, where alias must be present and culture and segment are optional - const filters: Array = [`@.alias = '${value.alias}'`]; + const filters: Array = [`@.alias == '${value.alias}'`]; if (value.culture !== undefined) { - filters.push(`@.culture = ${value.culture ? `'${value.culture}'` : 'null'}`); + filters.push(`@.culture == ${value.culture ? `'${value.culture}'` : 'null'}`); } if (value.segment !== undefined) { - filters.push(`@.segment = ${value.segment ? `'${value.segment}'` : 'null'}`); + filters.push(`@.segment == ${value.segment ? `'${value.segment}'` : 'null'}`); } return `?(${filters.join(' && ')})`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts index 25666269cd..175b744992 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/data-path-variant-query.function.ts @@ -12,9 +12,9 @@ export function UmbDataPathVariantQuery( value: UmbPartialSome, 'segment'>, ): string { // write a array of strings for each property, where culture must be present and segment is optional - const filters: Array = [`@.culture = ${value.culture ? `'${value.culture}'` : 'null'}`]; + const filters: Array = [`@.culture == ${value.culture ? `'${value.culture}'` : 'null'}`]; if (value.segment !== undefined) { - filters.push(`@.segment = ${value.segment ? `'${value.segment}'` : 'null'}`); + filters.push(`@.segment == ${value.segment ? `'${value.segment}'` : 'null'}`); } return `?(${filters.join(' && ')})`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts index c7c1244fc0..40ceb3f9da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.function.ts @@ -1,9 +1,10 @@ /** * - * @param data - * @param path + * @param {object} data - object to traverse for the value. + * @param {string} path - the JSON path to the value that should be found + * @returns {unknown} - the found value. */ -export function GetValueByJsonPath(data: any, path: string): any { +export function GetValueByJsonPath(data: unknown, path: string): unknown { // strip $ from the path: const strippedPath = path.startsWith('$.') ? path.slice(2) : path; // get value from the path: @@ -12,23 +13,9 @@ export function GetValueByJsonPath(data: any, path: string): any { /** * - * @param path - */ -export function GetPropertyNameFromPath(path: string): string { - // find next '.' or '[' in the path, using regex: - const match = path.match(/\.|\[/); - // If no match is found, we assume its a single key so lets return the value of the key: - if (match === null || match.index === undefined) return path; - - // split the path at the first match: - return path.slice(0, match.index); -} - -/** - * - * @param data - * @param path - * @returns {any} + * @param {object} data - object to traverse for the value. + * @param {string} path - the JSON path to the value that should be found + * @returns {unknown} - the found value. */ function GetNextPropertyValueFromPath(data: any, path: string): any { if (!data) return undefined; @@ -90,8 +77,8 @@ function GetNextPropertyValueFromPath(data: any, path: string): any { } /** - * @param filter - * @returns {Array<(queryFilter: any) => boolean>} - array of methods that returns true if the given items property value matches the value of the query. + * @param {string} filter - A JSON Query, limited to filtering features. Do not support other JSON PATH Query features. + * @returns {Array<(queryFilter: any) => boolean>} - An array of methods that returns true if the given items property value matches the value of the query. */ function JsFilterFromJsonPathFilter(filter: string): Array<(item: any) => boolean> { // strip ?( and ) from the filter @@ -101,7 +88,7 @@ function JsFilterFromJsonPathFilter(filter: string): Array<(item: any) => boolea // map each part to a function that returns true if the part is true return parts.map((part) => { // split the part into key and value - const [path, equal] = part.split(' = '); + const [path, equal] = part.split(' == '); // remove @. const key = path.slice(2); // remove quotes: diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts index 3673b28ecd..906463e1e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/utils/json-path.test.ts @@ -30,7 +30,7 @@ describe('UmbJsonPathFunctions', () => { }); it('query of first entry in an array', () => { - const result = GetValueByJsonPath({ values: [{ id: '123', value: 'test' }] }, "$.values[?(@.id = '123')].value"); + const result = GetValueByJsonPath({ values: [{ id: '123', value: 'test' }] }, "$.values[?(@.id == '123')].value"); expect(result).to.eq('test'); }); From 27c1cc952adb7b1700102709360cb89dece199cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 19:47:16 +0200 Subject: [PATCH 182/246] clean up --- .../block-list-editor/property-editor-ui-block-list.element.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 0ceb5e7abf..67e1291272 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -154,8 +154,6 @@ export class UmbPropertyEditorUIBlockListElement constructor() { super(); - //this.#validationContext.messages.debug('block list'); - this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { this.observe( context.dataPath, From a87afb69bad0a1c6abf910dcd2faac3d836ca32f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 19:56:47 +0200 Subject: [PATCH 183/246] document exports --- .../src/packages/documents/documents/audit-log/index.ts | 1 + .../documents/documents/recycle-bin/repository/types.ts | 0 .../src/packages/documents/documents/repository/index.ts | 2 +- .../src/packages/documents/documents/repository/types.ts | 1 + .../src/packages/documents/documents/tree/index.ts | 2 +- .../src/packages/documents/documents/types.ts | 7 +++++++ .../packages/documents/documents/user-permissions/index.ts | 1 + 7 files changed, 12 insertions(+), 2 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts index b8d46eff26..8dd29326e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/index.ts @@ -1 +1,2 @@ export { UmbDocumentAuditLogRepository } from './repository/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/repository/types.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts index be04ad8020..1a4cea0484 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts @@ -4,4 +4,4 @@ export { UmbDocumentPublishingRepository, UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALI export { UmbDocumentUrlRepository, UMB_DOCUMENT_URL_REPOSITORY_ALIAS } from './url/index.js'; export { UmbDocumentPreviewRepository } from './preview/index.js'; -export type { UmbDocumentItemModel } from './item/types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts new file mode 100644 index 0000000000..204e345ff9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts @@ -0,0 +1 @@ +export type { UmbDocumentItemModel } from './item/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts index db48eed3f7..628bc2c8da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/index.ts @@ -6,4 +6,4 @@ export { } from './manifests.js'; export { UMB_DOCUMENT_TREE_STORE_CONTEXT } from './document-tree.store.context-token.js'; export type { UmbDocumentTreeStore } from './document-tree.store.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts index b81855f41c..8f27a81993 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts @@ -9,6 +9,13 @@ import { DocumentVariantStateModel as UmbDocumentVariantState } from '@umbraco-c import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; export { UmbDocumentVariantState }; +export type * from './audit-log/types.js'; +export type * from './collection/types.js'; +export type * from './modals/types.js'; +export type * from './repository/types.js'; +export type * from './tree/types.js'; +export type * from './user-permissions/types.js'; + export interface UmbDocumentDetailModel extends UmbContentDetailModel { documentType: { unique: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts index 4991633288..3ed3c5c183 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts @@ -1,2 +1,3 @@ export * from './repository/index.js'; export * from './constants.js'; +export type * from './types.js'; From 8513e0918d22d5190a24438ad62cd6ec8334bf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:05:29 +0200 Subject: [PATCH 184/246] more exports --- src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts | 4 ++-- src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts | 2 ++ .../src/packages/core/collection/index.ts | 2 +- .../src/packages/core/collection/types.ts | 2 +- .../src/packages/core/content-type/index.ts | 4 ++-- .../src/packages/core/content-type/types.ts | 2 ++ .../src/packages/core/entity-action/index.ts | 2 +- .../src/packages/core/entity-bulk-action/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts | 2 +- .../src/packages/core/icon-registry/index.ts | 2 +- 10 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts index 866baaf319..216c98bbe6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts @@ -1,6 +1,6 @@ export * from './context/index.js'; export * from './modals/index.js'; -export type * from './types.js'; +export * from './property-value-resolver/index.js'; export * from './validation/index.js'; export * from './workspace/index.js'; -export * from './property-value-resolver/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index 77f43f22d6..b027622c03 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,5 +1,7 @@ import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; +export type * from './clipboard/types.js'; + export interface UmbBlockLayoutBaseModel { contentKey: string; settingsKey?: string | null; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts index ba4eedfb8a..5123111d27 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts @@ -10,7 +10,7 @@ export * from './collection-item-picker-modal/index.js'; export * from './default/collection-default.context.js'; export * from './default/collection-default.context-token.js'; export * from './collection-filter-model.interface.js'; -export * from './types.js'; +export type * from './types.js'; export { UMB_COLLECTION_ALIAS_CONDITION } from './collection-alias.manifest.js'; export { UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './collection-bulk-action-permission.manifest.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts index 153dae2e3d..9270f28463 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts @@ -48,4 +48,4 @@ export interface UmbCollectionContext { totalItems: Observable; } -export * from './extensions/index.js'; +export type * from './extensions/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts index 03701d17e5..79f883296b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/index.ts @@ -1,7 +1,7 @@ export * from './components/index.js'; +export * from './composition/index.js'; export * from './modals/index.js'; export * from './repository/index.js'; export * from './structure/index.js'; -export * from './types.js'; export * from './workspace/index.js'; -export * from './composition/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts index 132af25ee5..3d76913002 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts @@ -1,6 +1,8 @@ import type { CompositionTypeModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +export type * from './composition/types.js'; + export type UmbPropertyContainerTypes = 'Group' | 'Tab'; export interface UmbPropertyTypeContainerModel { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts index 0fd5ba6de0..60881da438 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/index.ts @@ -5,8 +5,8 @@ export * from './entity-action-list.element.js'; export * from './entity-action.event.js'; export * from './entity-action.extension.js'; export * from './entity-action.interface.js'; -export * from './types.js'; export type * from './entity-action-element.interface.js'; +export type * from './types.js'; export { UmbRequestReloadStructureForEntityEvent } from './request-reload-structure-for-entity.event.js'; export { UmbRequestReloadChildrenOfEntityEvent } from './request-reload-children-of-entity.event.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts index bf14ffa917..601493c5b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/index.ts @@ -1,8 +1,8 @@ -export * from './types.js'; export * from './common/index.js'; export * from './entity-bulk-action-base.js'; export * from './entity-bulk-action.element.js'; export * from './entity-bulk-action.interface.js'; export type * from './entity-bulk-action-element.interface.js'; +export type * from './types.js'; export { UMB_ENTITY_BULK_ACTION_DEFAULT_KIND_MANIFEST } from './default/default.action.kind.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index d3f60a90c0..737d7bf482 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,3 +1,3 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts index 1da66f89d4..d2d7785f3b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/index.ts @@ -2,5 +2,5 @@ export * from './icon-picker-modal/index.js'; export * from './icon-registry.context-token.js'; export * from './icon-registry.context.js'; export * from './icon.registry.js'; -export * from './types.js'; +export type * from './types.js'; export type * from './extensions/icons.extension.js'; From 5a460a15c6cd6a67e23fc47d609e86f5e8eaa40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:10:48 +0200 Subject: [PATCH 185/246] exort more types --- src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts index 255e8a9ae8..1509c986d2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/index.ts @@ -1,9 +1,9 @@ export * from './components/index.js'; export * from './menu-tree-structure-workspace-context-base.js'; export * from './menu-variant-tree-structure-workspace-context-base.js'; -export * from './types.js'; export type * from './menu-item-element.interface.js'; export type * from './menu-item.extension.js'; export type * from './menu.extension.js'; +export type * from './types.js'; export type { UmbMenuStructureWorkspaceContext } from './menu-structure-workspace-context.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts index 55ca1f1885..5403700cff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/index.ts @@ -5,4 +5,4 @@ export * from './component/modal-base.element.js'; export * from './component/modal.element.js'; export * from './context/index.js'; export * from './token/index.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts index 3549e429c8..a1c61b09c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/types.ts @@ -1,4 +1,4 @@ -export * from './extensions/index.js'; +export type * from './extensions/index.js'; export interface UmbPickerModalData { multiple?: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts index b19f3e47db..0074a61d85 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/index.ts @@ -1,4 +1,4 @@ export * from './search/index.js'; export * from './picker.context.js'; export * from './picker.context.token.js'; -export * from './types.js'; +export type * from './types.js'; From 55e84d0564a07e5784303ef31baa30dd6ce911f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:28:33 +0200 Subject: [PATCH 186/246] refactor collection conditions --- .../src/packages/block/block/types.ts | 1 + .../collection/collection-alias.manifest.ts | 18 -------------- ...lection-bulk-action-permission.manifest.ts | 17 ------------- .../collection-alias.condition.ts | 4 ++-- ...ection-bulk-action-permission.condition.ts | 4 ++-- .../core/collection/conditions/constants.ts | 3 +++ .../core/collection/conditions/index.ts | 4 ++++ .../core/collection/conditions/manifests.ts | 17 +++++++++++++ .../core/collection/conditions/types.ts | 24 +++++++++++++++++++ .../src/packages/core/collection/index.ts | 4 +--- .../src/packages/core/collection/manifests.ts | 6 ++--- .../src/packages/core/collection/types.ts | 1 + .../extension-registry/conditions/types.ts | 4 ++-- 13 files changed, 59 insertions(+), 48 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts rename src/Umbraco.Web.UI.Client/src/packages/core/collection/{ => conditions}/collection-alias.condition.ts (83%) rename src/Umbraco.Web.UI.Client/src/packages/core/collection/{ => conditions}/collection-bulk-action-permission.condition.ts (89%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index b027622c03..011f9763f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,5 +1,6 @@ import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; +export type * from './conditions/types.js'; export type * from './clipboard/types.js'; export interface UmbBlockLayoutBaseModel { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts deleted file mode 100644 index 52eadd23f3..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.manifest.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { ManifestCondition, UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; - -export type CollectionAliasConditionConfig = UmbConditionConfigBase & { - /** - * The collection that this extension should be available in - * @example - * "Umb.Collection.User" - */ - match: string; -}; - -export const UMB_COLLECTION_ALIAS_CONDITION = 'Umb.Condition.CollectionAlias'; -export const manifest: ManifestCondition = { - type: 'condition', - name: 'Collection Alias Condition', - alias: UMB_COLLECTION_ALIAS_CONDITION, - api: () => import('./collection-alias.condition.js'), -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts deleted file mode 100644 index 17fb2ba24c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.manifest.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { UmbCollectionBulkActionPermissions } from './types.js'; -import type { ManifestCondition, UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; - -export type CollectionBulkActionPermissionConditionConfig = UmbConditionConfigBase< - typeof UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION -> & { - match: (permissions: UmbCollectionBulkActionPermissions) => boolean; -}; - -export const UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION = 'Umb.Condition.CollectionBulkActionPermission'; - -export const manifest: ManifestCondition = { - type: 'condition', - name: 'Collection Bulk Action Permission Condition', - alias: UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, - api: () => import('./collection-bulk-action-permission.condition.js'), -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts similarity index 83% rename from src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts index 166d81e131..6a4a03f6e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts @@ -1,5 +1,5 @@ -import { UMB_COLLECTION_CONTEXT } from './default/index.js'; -import type { CollectionAliasConditionConfig } from './collection-alias.manifest.js'; +import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; +import type { CollectionAliasConditionConfig } from './types.js'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts similarity index 89% rename from src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts index 3b13ad47e2..885ad3f982 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-bulk-action-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts @@ -1,5 +1,5 @@ -import { UMB_COLLECTION_CONTEXT } from './default/index.js'; -import type { CollectionBulkActionPermissionConditionConfig } from './collection-bulk-action-permission.manifest.js'; +import { UMB_COLLECTION_CONTEXT } from '../default/index.js'; +import type { CollectionBulkActionPermissionConditionConfig } from './types.js'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts new file mode 100644 index 0000000000..36fa086ad7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/constants.ts @@ -0,0 +1,3 @@ +export const UMB_COLLECTION_ALIAS_CONDITION = 'Umb.Condition.CollectionAlias'; + +export const UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION = 'Umb.Condition.CollectionBulkActionPermission'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts new file mode 100644 index 0000000000..83279e8836 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/index.ts @@ -0,0 +1,4 @@ +export * from './collection-bulk-action-permission.condition.js'; +export * from './collection-alias.condition.js'; +export * from './constants.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts new file mode 100644 index 0000000000..3e4eadfc62 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/manifests.ts @@ -0,0 +1,17 @@ +import { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './constants.js'; +import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'Collection Alias Condition', + alias: UMB_COLLECTION_ALIAS_CONDITION, + api: () => import('./collection-alias.condition.js'), + }, + { + type: 'condition', + name: 'Collection Bulk Action Permission Condition', + alias: UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION, + api: () => import('./collection-bulk-action-permission.condition.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts new file mode 100644 index 0000000000..11801e6225 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts @@ -0,0 +1,24 @@ +import type { UmbCollectionBulkActionPermissions } from '../types.js'; +import type { UMB_COLLECTION_ALIAS_CONDITION, UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +export type CollectionBulkActionPermissionConditionConfig = UmbConditionConfigBase< + typeof UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION +> & { + match: (permissions: UmbCollectionBulkActionPermissions) => boolean; +}; + +export type CollectionAliasConditionConfig = UmbConditionConfigBase & { + /** + * The collection that this extension should be available in + * @example + * "Umb.Collection.User" + */ + match: string; +}; + +declare global { + interface UmbExtensionConditionConfigMap { + CollectionAliasConditionConfig: CollectionAliasConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts index 5123111d27..ca9701d258 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/index.ts @@ -5,6 +5,7 @@ import './components/index.js'; export * from './default/collection-default.element.js'; export * from './collection.element.js'; export * from './components/index.js'; +export * from './conditions/index.js'; export * from './collection-item-picker-modal/index.js'; export * from './default/collection-default.context.js'; @@ -12,8 +13,5 @@ export * from './default/collection-default.context-token.js'; export * from './collection-filter-model.interface.js'; export type * from './types.js'; -export { UMB_COLLECTION_ALIAS_CONDITION } from './collection-alias.manifest.js'; -export { UMB_COLLECTION_BULK_ACTION_PERMISSION_CONDITION } from './collection-bulk-action-permission.manifest.js'; - export { UmbCollectionActionElement, UmbCollectionActionBase } from './action/index.js'; export type { UmbCollectionDataSource, UmbCollectionRepository } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts index 1ee0674ee8..0e211901ca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts @@ -1,10 +1,8 @@ import type { UmbExtensionManifestKind } from '../extension-registry/registry.js'; -import { manifest as collectionAliasCondition } from './collection-alias.manifest.js'; -import { manifest as collectionBulkActionPermissionCondition } from './collection-bulk-action-permission.manifest.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as workspaceViewManifests } from './workspace-view/manifests.js'; export const manifests: Array = [ ...workspaceViewManifests, - collectionAliasCondition, - collectionBulkActionPermissionCondition, + ...conditionManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts index 9270f28463..352a8176c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts @@ -3,6 +3,7 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbPaginationManager } from '@umbraco-cms/backoffice/utils'; export type * from './extensions/index.js'; +export type * from './conditions/types.js'; export interface UmbCollectionBulkActionPermissions { allowBulkCopy: boolean; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts index 9005394877..48d244d804 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts @@ -1,5 +1,5 @@ -import type { CollectionAliasConditionConfig } from '../../collection/collection-alias.manifest.js'; -import type { CollectionBulkActionPermissionConditionConfig } from '../../collection/collection-bulk-action-permission.manifest.js'; +import type { CollectionAliasConditionConfig } from '../../collection/conditions/collection-alias.types.js'; +import type { CollectionBulkActionPermissionConditionConfig } from '../../collection/conditions/collection-bulk-action-permission.manifest.js'; import type { SwitchConditionConfig } from './switch.condition.js'; import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; From 7bf087504164130c528985c0beab313dbdc642dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 24 Oct 2024 20:29:02 +0200 Subject: [PATCH 187/246] remove reference --- .../packages/core/extension-registry/conditions/types.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts index 48d244d804..ee46b35085 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts @@ -1,13 +1,7 @@ -import type { CollectionAliasConditionConfig } from '../../collection/conditions/collection-alias.types.js'; -import type { CollectionBulkActionPermissionConditionConfig } from '../../collection/conditions/collection-bulk-action-permission.manifest.js'; import type { SwitchConditionConfig } from './switch.condition.js'; import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; -export type UmbCoreConditionConfigs = - | CollectionAliasConditionConfig - | CollectionBulkActionPermissionConditionConfig - | SwitchConditionConfig - | UmbConditionConfigBase; +export type UmbCoreConditionConfigs = SwitchConditionConfig | UmbConditionConfigBase; /** * @deprecated instead use global UmbExtensionConditionConfig From 1726702c45d43dcf475465e88fb18609a84ab719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 09:32:38 +0200 Subject: [PATCH 188/246] is admin --- .../user/current-user/conditions/is-admin/index.ts | 1 + .../conditions/is-admin/is-admin.condition-config.ts | 12 ++++++++++++ .../packages/user/current-user/conditions/types.ts | 1 + .../src/packages/user/current-user/types.ts | 2 ++ 4 files changed, 16 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts index 4f07201dcf..07a3192a17 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/index.ts @@ -1 +1,2 @@ export * from './constants.js'; +export * from './is-admin.condition-config.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts new file mode 100644 index 0000000000..8e8f47a516 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/is-admin/is-admin.condition-config.ts @@ -0,0 +1,12 @@ +import type { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbIsAdminConditionConfig + extends UmbConditionConfigBase {} + +declare global { + interface UmbExtensionConditionConfigMap { + UmbIsAdminConditionConfig: UmbIsAdminConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts new file mode 100644 index 0000000000..17dc928ab5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/types.ts @@ -0,0 +1 @@ +export type * from './is-admin/is-admin.condition-config.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts index 0453be866b..32bd2469e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts @@ -8,6 +8,8 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +export type * from './conditions/types.js'; + export interface UmbCurrentUserModel { allowedSections: Array; avatarUrls: Array; From ef77734a5d09975a9611ef55ca53828f46201c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 09:41:33 +0200 Subject: [PATCH 189/246] user conditions --- .../allow-change-password/constants.ts | 1 + .../allow-change-password/manifests.ts | 4 +++- .../user/conditions/allow-delete/constants.ts | 1 + .../user/conditions/allow-delete/manifests.ts | 4 +++- .../conditions/allow-disable/constants.ts | 1 + .../conditions/allow-disable/manifests.ts | 4 +++- .../user/conditions/allow-enable/constants.ts | 1 + .../allow-external-login/constants.ts | 1 + .../allow-external-login/manifests.ts | 4 +++- .../user/conditions/allow-mfa/constants.ts | 1 + .../user/conditions/allow-mfa/manifests.ts | 4 +++- .../user/conditions/allow-unlock/constants.ts | 1 + .../user/conditions/allow-unlock/manifests.ts | 4 +++- .../packages/user/user/conditions/types.ts | 23 +++++++++++++++++++ 14 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts new file mode 100644 index 0000000000..31baf82e9f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS = 'Umb.Condition.User.AllowChangePassword'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts index 368f12e683..568650836e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-change-password/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Change Password Condition', - alias: 'Umb.Condition.User.AllowChangePassword', + alias: UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS, api: () => import('./user-allow-change-password-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts new file mode 100644 index 0000000000..8183df1002 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_DELETE_CONDITION_ALIAS = 'Umb.Condition.User.AllowDeleteAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts index b25eba1462..d05317a682 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-delete/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_DELETE_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Delete Action Condition', - alias: 'Umb.Condition.User.AllowDeleteAction', + alias: UMB_USER_ALLOW_DELETE_CONDITION_ALIAS, api: () => import('./user-allow-delete-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts new file mode 100644 index 0000000000..965922176c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS = 'Umb.Condition.User.AllowDisableAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts index 34ba7e7d38..a7ce9b3a1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-disable/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Disable Action Condition', - alias: 'Umb.Condition.User.AllowDisableAction', + alias: UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS, api: () => import('./user-allow-disable-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts new file mode 100644 index 0000000000..f2221ec92a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-enable/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_ENABLE_CONDITION_ALIAS = 'Umb.Condition.User.AllowEnableAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts new file mode 100644 index 0000000000..8b7e01c6c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS = 'Umb.Condition.User.AllowExternalLoginAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts index 966f5aa137..4ff36ca25c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-external-login/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow ExternalLogin Action Condition', - alias: 'Umb.Condition.User.AllowExternalLoginAction', + alias: UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS, api: () => import('./user-allow-external-login-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts new file mode 100644 index 0000000000..872ba596a7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_MFA_CONDITION_ALIAS = 'Umb.Condition.User.AllowMfaAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts index a9cb89568d..c25c206618 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-mfa/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_MFA_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Mfa Action Condition', - alias: 'Umb.Condition.User.AllowMfaAction', + alias: UMB_USER_ALLOW_MFA_CONDITION_ALIAS, api: () => import('./user-allow-mfa-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts new file mode 100644 index 0000000000..8e29b48475 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS = 'Umb.Condition.User.AllowUnlockAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts index 9fafc5d5be..69c89702a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/allow-unlock/manifests.ts @@ -1,8 +1,10 @@ +import { UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS } from './constants.js'; + export const manifests: Array = [ { type: 'condition', name: 'User Allow Unlock Action Condition', - alias: 'Umb.Condition.User.AllowUnlockAction', + alias: UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS, api: () => import('./user-allow-unlock-action.condition.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts new file mode 100644 index 0000000000..006ccf837d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/conditions/types.ts @@ -0,0 +1,23 @@ +import type { UMB_USER_ALLOW_CHANGE_PASSWORD_CONDITION_ALIAS } from './allow-change-password/constants.js'; +import type { UMB_USER_ALLOW_DELETE_CONDITION_ALIAS } from './allow-delete/constants.js'; +import type { UMB_USER_ALLOW_DISABLE_CONDITION_ALIAS } from './allow-disable/constants.js'; +import type { UMB_USER_ALLOW_ENABLE_CONDITION_ALIAS } from './allow-enable/constants.js'; +import type { UMB_USER_ALLOW_EXTERNAL_LOGIN_CONDITION_ALIAS } from './allow-external-login/constants.js'; +import type { UMB_USER_ALLOW_MFA_CONDITION_ALIAS } from './allow-mfa/constants.js'; +import type { UMB_USER_ALLOW_UNLOCK_CONDITION_ALIAS } from './allow-unlock/constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +type UmbUserConditionConfigs = + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase + | UmbConditionConfigBase; + +declare global { + interface UmbExtensionConditionConfigMap { + UmbUserConditionConfigs: UmbUserConditionConfigs; + } +} From 1890dfeb434207696326eb699dd0e0f5cdbd3dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:17:34 +0200 Subject: [PATCH 190/246] export types --- .../src/packages/block/block-grid/constants.ts | 2 ++ .../src/packages/block/block-grid/index.ts | 3 ++- .../src/packages/block/block-grid/types.ts | 3 --- .../src/packages/block/block-list/constants.ts | 2 ++ .../src/packages/block/block-list/index.ts | 3 ++- .../src/packages/block/block-list/types.ts | 3 --- .../src/packages/block/block-rte/constants.ts | 2 ++ .../src/packages/block/block-rte/index.ts | 3 ++- .../src/packages/block/block-rte/types.ts | 3 --- .../src/packages/block/block-type/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts | 2 +- .../detail/data-type-detail.server.data-source.ts | 4 ++-- src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts | 6 +++--- .../data-type/workspace/data-type-workspace.context.ts | 4 ++-- .../src/packages/dictionary/collection/index.ts | 2 ++ .../src/packages/dictionary/tree/index.ts | 3 ++- src/Umbraco.Web.UI.Client/src/packages/language/index.ts | 2 +- .../src/packages/media/imaging/index.ts | 2 ++ .../src/packages/media/media-types/index.ts | 3 ++- .../src/packages/media/media/modals/media-picker/index.ts | 2 +- .../src/packages/media/media/tree/index.ts | 2 +- .../src/packages/members/member/collection/index.ts | 2 ++ .../src/packages/members/member/types.ts | 1 + src/Umbraco.Web.UI.Client/src/packages/search/index.ts | 2 +- .../src/packages/templating/partial-views/index.ts | 1 + .../src/packages/templating/scripts/index.ts | 2 +- .../src/packages/templating/stylesheets/index.ts | 7 +++---- src/Umbraco.Web.UI.Client/src/packages/user/index.ts | 5 +++-- .../src/packages/user/user-group/index.ts | 4 ++-- .../src/packages/user/user-permission/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts | 4 ++-- 32 files changed, 51 insertions(+), 39 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts new file mode 100644 index 0000000000..9f70d25c93 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/constants.ts @@ -0,0 +1,2 @@ +export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; +export const UMB_BLOCK_GRID = 'block-grid'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts index 577eea75f4..79d559f5c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts @@ -1,3 +1,4 @@ +export * from './constants.js'; export * from './context/index.js'; -export * from './types.js'; export * from './workspace/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts index 5f192aedfe..b22f5a7b07 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts @@ -1,9 +1,6 @@ import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockTypeWithGroupKey } from '@umbraco-cms/backoffice/block-type'; -export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; -export const UMB_BLOCK_GRID = 'block-grid'; - // Configuration models: export interface UmbBlockGridTypeModel extends UmbBlockTypeWithGroupKey { columnSpanOptions: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts new file mode 100644 index 0000000000..cae284bdee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/constants.ts @@ -0,0 +1,2 @@ +export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; +export const UMB_BLOCK_LIST = 'block-list'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts index 577eea75f4..79d559f5c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts @@ -1,3 +1,4 @@ +export * from './constants.js'; export * from './context/index.js'; -export * from './types.js'; export * from './workspace/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts index 94ff232c27..2903ee03b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts @@ -1,9 +1,6 @@ import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; -export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; -export const UMB_BLOCK_LIST = 'block-list'; - // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {} // eslint-disable-next-line @typescript-eslint/no-empty-object-type diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts new file mode 100644 index 0000000000..4aaa6a7406 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/constants.ts @@ -0,0 +1,2 @@ +export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; +export const UMB_BLOCK_RTE = 'block-rte'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts index 5ce24a84b0..40cb3510e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/index.ts @@ -1,4 +1,5 @@ +export * from './constants.js'; export * from './components/index.js'; export * from './context/index.js'; export * from './workspace/index.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts index f6e44b3beb..c7e8bff28b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts @@ -1,9 +1,6 @@ import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; -export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; -export const UMB_BLOCK_RTE = 'block-rte'; - export interface UmbBlockRteTypeModel extends UmbBlockTypeBaseModel { displayInline: boolean; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts index 814adba5f3..76a7e33393 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/index.ts @@ -1,3 +1,3 @@ export * from './components/index.js'; -export * from './types.js'; export * from './workspace/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts index 5b2c179b14..c516f24d51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/index.ts @@ -9,4 +9,4 @@ export * from './paths.js'; export { UmbMoveDataTypeRepository, UMB_MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './entity-actions/move-to/index.js'; -export type { UmbDataTypeDetailModel } from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts index 9e31fd975a..3eb91ed61f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/detail/data-type-detail.server.data-source.ts @@ -1,4 +1,4 @@ -import type { UmbDataTypeDetailModel, UmbDataTypePropertyModel } from '../../types.js'; +import type { UmbDataTypeDetailModel, UmbDataTypePropertyValueModel } from '../../types.js'; import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; @@ -70,7 +70,7 @@ export class UmbDataTypeServerDataSource implements UmbDetailDataSource, + values: data.values as Array, }; return { data: dataType }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts index 366f7823f3..53c18c6e45 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/types.ts @@ -6,10 +6,10 @@ export interface UmbDataTypeDetailModel { name: string; editorAlias: string | undefined; editorUiAlias: string | null; - values: Array; + values: Array; } -export interface UmbDataTypePropertyModel { +export interface UmbDataTypePropertyValueModel { alias: string; - value: any; + value: ValueType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index cd1b9b5839..b29b1beac2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -1,4 +1,4 @@ -import type { UmbDataTypeDetailModel, UmbDataTypePropertyModel } from '../types.js'; +import type { UmbDataTypeDetailModel, UmbDataTypePropertyValueModel } from '../types.js'; import { type UmbDataTypeDetailRepository, UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_DATA_TYPE_ENTITY_TYPE } from '../entity.js'; import { UmbDataTypeWorkspaceEditorElement } from './data-type-workspace-editor.element.js'; @@ -247,7 +247,7 @@ export class UmbDataTypeWorkspaceContext this.#settingsDefaultData = [ ...this.#propertyEditorSchemaSettingsDefaultData, ...this.#propertyEditorUISettingsDefaultData, - ] satisfies Array; + ] satisfies Array; // We check for satisfied type, because we will be directly transferring them to become value. Future note, if they are not satisfied, we need to transfer alias and value. [NL] this._data.updatePersisted({ values: this.#settingsDefaultData }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts index 1001b2fa0f..ea8abf649f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/collection/index.ts @@ -1,2 +1,4 @@ export { UmbDictionaryCollectionRepository } from './repository/index.js'; export { UMB_DICTIONARY_COLLECTION_ALIAS } from './constants.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts index 0940ddc29a..4f23f5ab53 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/tree/index.ts @@ -6,4 +6,5 @@ export { } from './constants.js'; export { UMB_DICTIONARY_TREE_STORE_CONTEXT } from './dictionary-tree.store.js'; export { type UmbDictionaryTreeStore } from './dictionary-tree.store.js'; -export * from './types.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/index.ts b/src/Umbraco.Web.UI.Client/src/packages/language/index.ts index 37e1e94844..b3a5c61dcc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/index.ts @@ -7,4 +7,4 @@ export * from './repository/index.js'; export * from './collection/index.js'; export * from './global-contexts/index.js'; -export type { UmbLanguageDetailModel } from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts index d05152d5dc..2b1564e061 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/imaging/index.ts @@ -1,3 +1,5 @@ export * from './components/index.js'; export { UmbImagingRepository } from './imaging.repository.js'; export { UMB_IMAGING_REPOSITORY_ALIAS } from './constants.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts index 4fdc741116..4c4642c7cb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts @@ -4,8 +4,9 @@ export * from './components/index.js'; export * from './entity.js'; export * from './repository/index.js'; export * from './tree/types.js'; -export * from './types.js'; export * from './utils.ts/index.js'; export * from './workspace/index.js'; +export type * from './types.js'; + export { UMB_MEDIA_TYPE_PICKER_MODAL } from './tree/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts index 134ffc53a6..16952e6ae1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/index.ts @@ -1,4 +1,4 @@ export * from './components/index.js'; export * from './media-picker-modal.element.js'; export * from './media-picker-modal.token.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts index ee32f4921b..f46e1142c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/index.ts @@ -3,4 +3,4 @@ export { UMB_MEDIA_TREE_REPOSITORY_ALIAS, UMB_MEDIA_TREE_STORE_ALIAS, UMB_MEDIA_ export { UMB_MEDIA_TREE_STORE_CONTEXT } from './media-tree.store.context-token.js'; export { UMB_MEDIA_TREE_PICKER_MODAL } from './media-tree-picker-modal.token.js'; export { type UmbMediaTreeStore } from './media-tree.store.js'; -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts index 89461c5f07..7e24407b1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/collection/index.ts @@ -1,2 +1,4 @@ export { UmbMemberCollectionRepository } from './repository/index.js'; export { UMB_MEMBER_COLLECTION_ALIAS } from './manifests.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index db66e77104..ffc39069ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -3,6 +3,7 @@ import type { UmbMemberKindType } from './utils/index.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; +export type * from './collection/types.js'; export interface UmbMemberDetailModel extends UmbContentDetailModel { email: string; entityType: UmbMemberEntityType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/index.ts b/src/Umbraco.Web.UI.Client/src/packages/search/index.ts index c750f51952..1ed91d9469 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/search/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/search/index.ts @@ -1,4 +1,4 @@ -export type { UmbSearchResultItemModel, UmbSearchRequestArgs, UmbSearchProvider } from './types.js'; +export type * from './types.js'; export type { UmbSearchDataSource } from './search-data-source.interface.js'; export type { UmbSearchRepository } from './search-repository.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts index 2ca9dc61a5..66315e994b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/index.ts @@ -1,5 +1,6 @@ export * from './entity.js'; export * from './global-components/index.js'; export * from './repository/index.js'; +export type * from './types.js'; export { UMB_PARTIAL_VIEW_PICKER_MODAL } from './partial-view-picker/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts index cce5d23b51..315274ee1d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/index.ts @@ -2,7 +2,7 @@ export * from './entity.js'; export * from './global-components/index.js'; export * from './repository/index.js'; export * from './tree/index.js'; -export * from './types.js'; export * from './workspace/script-workspace.context-token.js'; +export type * from './types.js'; export { UMB_SCRIPT_PICKER_MODAL } from './modals/script-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts index 1848331d21..81b2e7e339 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts @@ -1,10 +1,9 @@ import './global-components/index.js'; -export * from './repository/index.js'; export * from './entity.js'; export * from './global-components/index.js'; +export * from './repository/index.js'; +export * from './utils/index.js'; +export type * from './types.js'; export { UmbStylesheetTreeRepository } from './tree/index.js'; - -// Utils -export { UmbStylesheetRuleManager } from './utils/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/index.ts index dc92400e30..40765df7a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/index.ts @@ -1,4 +1,5 @@ export * from './current-user/index.js'; -export * from './user-group/index.js'; -export * from './user/index.js'; export * from './manifests.js'; +export * from './user-group/index.js'; +export * from './user-permission/index.js'; +export * from './user/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts index ac05b1f292..47adea1251 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/index.ts @@ -1,7 +1,7 @@ export * from './collection/index.js'; export * from './components/index.js'; -export * from './repository/index.js'; -export * from './types.js'; export * from './entity.js'; +export * from './repository/index.js'; +export type * from './types.js'; export { UMB_USER_GROUP_PICKER_MODAL } from './modals/user-group-picker/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts index 856a12661c..a23bfc02a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/index.ts @@ -3,4 +3,4 @@ export * from './modals/index.js'; export * from './user-granular-permission.extension.js'; export * from './entity-user-permission.extension.js'; -export type { UmbUserPermissionModel } from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts index cbb8fe2fe2..804493858d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/types.ts @@ -7,6 +7,8 @@ import { type UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; +export type * from './conditions/types.js'; + export type UmbUserStateEnum = UserStateModel; export const UmbUserStateEnum = UserStateModel; diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts index db0f1027eb..ebe4439610 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/index.ts @@ -1,4 +1,4 @@ +export * from './repository/index.js'; export * from './collection/index.js'; - -export type * from './types.js'; export * from './entity.js'; +export type * from './types.js'; From 419e00e4944e0c90536b95d0f062bb2e765db3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:22:34 +0200 Subject: [PATCH 191/246] add CollectionBulkActionPermissionConditionConfig --- .../src/packages/core/collection/conditions/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts index 11801e6225..6a19e0a3c9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/types.ts @@ -19,6 +19,7 @@ export type CollectionAliasConditionConfig = UmbConditionConfigBase Date: Fri, 25 Oct 2024 10:28:46 +0200 Subject: [PATCH 192/246] export condition types --- .../entity-is-not-trashed.condition-config.ts | 12 ++++++++++++ .../is-trashed/entity-is-trashed.condition-config.ts | 12 ++++++++++++ .../packages/core/recycle-bin/conditions/types.ts | 2 ++ .../src/packages/core/recycle-bin/types.ts | 2 ++ 4 files changed, 28 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts new file mode 100644 index 0000000000..d15c08ade0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition-config.ts @@ -0,0 +1,12 @@ +import type { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbEntityIsNotTrashedConditionConfig + extends UmbConditionConfigBase {} + +declare global { + interface UmbExtensionConditionConfigMap { + UmbEntityIsNotTrashedConditionConfig: UmbEntityIsNotTrashedConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts new file mode 100644 index 0000000000..9aeff180b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition-config.ts @@ -0,0 +1,12 @@ +import type { UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbEntityIsTrashedConditionConfig + extends UmbConditionConfigBase {} + +declare global { + interface UmbExtensionConditionConfigMap { + UmbEntityIsTrashedConditionConfig: UmbEntityIsTrashedConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts new file mode 100644 index 0000000000..906a89c23d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/types.ts @@ -0,0 +1,2 @@ +export type * from './is-not-trashed/entity-is-not-trashed.condition-config.js'; +export type * from './is-trashed/entity-is-trashed.condition-config.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts index 3a74c7c86f..358d08e0d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/types.ts @@ -1,3 +1,5 @@ +export type * from './conditions/types.js'; + export interface UmbRecycleBinRestoreRequestArgs { unique: string; destination: { From f28cacd79d974eb64a3afc6cbb614205326903b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:36:33 +0200 Subject: [PATCH 193/246] move section types --- .../src/packages/core/section/extensions/index.ts | 13 ------------- .../src/packages/core/section/extensions/types.ts | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts index 7e9361b328..398e7201da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/index.ts @@ -1,19 +1,6 @@ -import type { ManifestSectionRoute } from './section-route.extension.js'; -import type { ManifestSectionSidebarApp } from './section-sidebar-app.extension.js'; -import type { ManifestSectionView } from './section-view.extension.js'; -import type { ManifestSection } from './section.extension.js'; - export type * from './section-route.extension.js'; export type * from './section-sidebar-app.extension.js'; export type * from './section-view.extension.js'; export type * from './section.extension.js'; export type * from './types.js'; - -type UmbSectionExtensions = ManifestSection | ManifestSectionRoute | ManifestSectionSidebarApp | ManifestSectionView; - -declare global { - interface UmbExtensionManifestMap { - UmbSectionExtensions: UmbSectionExtensions; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts index 028e21bc99..e4d5de7f8b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/extensions/types.ts @@ -1,3 +1,16 @@ export type * from './section-element.interface.js'; export type * from './section-sidebar-app-element.interface.js'; export type * from './section-view-element.interface.js'; + +import type { ManifestSectionRoute } from './section-route.extension.js'; +import type { ManifestSectionSidebarApp } from './section-sidebar-app.extension.js'; +import type { ManifestSectionView } from './section-view.extension.js'; +import type { ManifestSection } from './section.extension.js'; + +type UmbSectionExtensions = ManifestSection | ManifestSectionRoute | ManifestSectionSidebarApp | ManifestSectionView; + +declare global { + interface UmbExtensionManifestMap { + UmbSectionExtensions: UmbSectionExtensions; + } +} From 5533926e6ae080da908794e219c311e9b495d591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:38:37 +0200 Subject: [PATCH 194/246] tip tap extensions --- .../src/packages/tiptap/extensions/index.ts | 2 -- .../src/packages/tiptap/extensions/tiptap-extension.ts | 2 +- .../src/packages/tiptap/extensions/tiptap-toolbar-extension.ts | 2 +- .../src/packages/tiptap/extensions/types.ts | 3 +++ 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts index 8f09498433..d4702960d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts @@ -1,3 +1 @@ -export type * from './tiptap-extension.js'; -export type * from './tiptap-toolbar-extension.js'; export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts index 619792c6bb..351325ec37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-extension.ts @@ -15,6 +15,6 @@ export interface MetaTiptapExtension { declare global { interface UmbExtensionManifestMap { - tiptapExtension: ManifestTiptapExtension; + umbTiptapExtension: ManifestTiptapExtension; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts index 3c178b4e85..36d5c74f4a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/tiptap-toolbar-extension.ts @@ -25,6 +25,6 @@ export interface ManifestTiptapToolbarExtensionButtonKind< declare global { interface UmbExtensionManifestMap { - tiptapToolbarExtension: ManifestTiptapToolbarExtension | ManifestTiptapToolbarExtensionButtonKind; + umbTiptapToolbarExtension: ManifestTiptapToolbarExtension | ManifestTiptapToolbarExtensionButtonKind; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts index ec2bcc1f8c..49fa890922 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts @@ -5,6 +5,9 @@ import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/exte import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +export type * from './tiptap-extension.js'; +export type * from './tiptap-toolbar-extension.js'; + export interface UmbTiptapExtensionApi extends UmbApi { /** * The manifest for the extension. From 002b4baf473e8e505ff26fd777540be53b6a661f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:41:11 +0200 Subject: [PATCH 195/246] ufm types --- .../src/packages/tiptap/extensions/index.ts | 2 +- src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts | 2 ++ src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts index d4702960d5..06c33f562f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts @@ -1 +1 @@ -export * from './types.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts index f0f1ade33d..72d8944e05 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/index.ts @@ -1,2 +1,4 @@ export * from './components/index.js'; export * from './extensions/index.js'; + +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts index 1d9964b88b..fcbfd9b7eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/types.ts @@ -1,6 +1,8 @@ import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block'; import type { UmbBlockRteLayoutModel } from '@umbraco-cms/backoffice/block-rte'; +export type * from './extensions/types.js'; + // TODO: Rename this type: export interface UmbPropertyEditorUiValueType { markup: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts index e97116b6c1..8b2395e4a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts @@ -1,6 +1,6 @@ import type { UmbUfmFilterApi } from './ufm-filter.extension.js'; -// TODO: This is not a type? So it should ideally be move to a different file. [NL] +// TODO: this is not a type, in TypeScript world, as it is an actual class. So it should be moved elsewhere [NL] export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { abstract filter(...args: Array): string | undefined | null; destroy() {} From 3b152b68da542f5d4ce8c182677163e1f9ccfbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:43:56 +0200 Subject: [PATCH 196/246] fix tsc --- .../workspace/block-grid-type-workspace.modal-token.ts | 3 ++- .../views/block-grid-type-workspace-view-advanced.element.ts | 2 +- .../components/block-list-entry/block-list-entry.element.ts | 3 ++- ...property-editor-ui-block-list-type-configuration.element.ts | 2 +- .../components/block-rte-entry/block-rte-entry.element.ts | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts index 61b344ca99..fdd64d49ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts @@ -1,4 +1,5 @@ -import { UMB_BLOCK_GRID_TYPE, type UmbBlockGridTypeModel } from '../types.js'; +import type { UmbBlockGridTypeModel } from '../types.js'; +import { UMB_BLOCK_GRID_TYPE } from '../constants.js'; import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/workspace'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts index 9879949f7c..c11ea6c9b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-advanced.element.ts @@ -1,4 +1,4 @@ -import { UMB_BLOCK_GRID } from '../../types.js'; +import { UMB_BLOCK_GRID } from '../../constants.js'; import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 336c7e0710..f23b039e1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -1,5 +1,6 @@ import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js'; -import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js'; +import type { UmbBlockListLayoutModel } from '../../types.js'; +import { UMB_BLOCK_LIST } from '../../constants.js'; import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts index 772b8068c2..054b47d124 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts @@ -1,5 +1,5 @@ import '../../../block-type/components/input-block-type/index.js'; -import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; +import { UMB_BLOCK_LIST_TYPE } from '../../constants.js'; import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; import { type UmbPropertyEditorUiElement, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 96b7c0de0a..e5f8fd3486 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -1,4 +1,5 @@ -import { UMB_BLOCK_RTE, type UmbBlockRteLayoutModel } from '../../types.js'; +import type { UmbBlockRteLayoutModel } from '../../types.js'; +import { UMB_BLOCK_RTE } from '../../constants.js'; import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement, nothing } from '@umbraco-cms/backoffice/external/lit'; From e718367f15ec40913a7dced13529999d35eaa907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:51:56 +0200 Subject: [PATCH 197/246] move abstract classes out of types --- .../src/packages/tiptap/extensions/base.ts | 61 +++++++++++++++++++ .../src/packages/tiptap/extensions/index.ts | 1 + .../src/packages/tiptap/extensions/types.ts | 52 ---------------- .../src/packages/ufm/filters/base.filter.ts | 6 ++ .../src/packages/ufm/index.ts | 1 + .../src/packages/ufm/types.ts | 8 +-- 6 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts new file mode 100644 index 0000000000..3fba20f6ba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/base.ts @@ -0,0 +1,61 @@ +import type { + ManifestTiptapExtension, + ManifestTiptapToolbarExtension, + UmbTiptapExtensionApi, + UmbTiptapExtensionArgs, + UmbTiptapToolbarElementApi, +} from './types.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap'; +import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; + +export abstract class UmbTiptapExtensionApiBase extends UmbControllerBase implements UmbTiptapExtensionApi { + /** + * The manifest for the extension. + */ + manifest?: ManifestTiptapExtension; + + /** + * The editor instance. + */ + protected _editor?: Editor; + + /** + * @inheritdoc + */ + setEditor(editor: Editor): void { + this._editor = editor; + } + + /** + * @inheritdoc + */ + abstract getTiptapExtensions(args?: UmbTiptapExtensionArgs): Array; +} + +export abstract class UmbTiptapToolbarElementApiBase extends UmbControllerBase implements UmbTiptapToolbarElementApi { + /** + * The manifest for the extension. + */ + manifest?: ManifestTiptapToolbarExtension; + + /** + * The data type configuration for the property editor that the editor is used for. + */ + configuration?: UmbPropertyEditorConfigCollection; + + /** + * A method to execute the toolbar element action. + */ + public abstract execute(editor: Editor): void; + + /** + * Informs the toolbar element if it is active or not. It uses the manifest meta alias to check if the toolbar element is active. + * @see {ManifestTiptapToolbarExtension} + * @param {Editor} editor The editor instance. + * @returns {boolean} Returns true if the toolbar element is active. + */ + public isActive(editor: Editor) { + return editor && this.manifest?.meta.alias ? editor?.isActive(this.manifest.meta.alias) : false; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts index 06c33f562f..ffd2be35b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/index.ts @@ -1 +1,2 @@ +export * from './base.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts index 49fa890922..67bdb4adfc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts @@ -1,6 +1,5 @@ import type { ManifestTiptapExtension } from './tiptap-extension.js'; import type { ManifestTiptapToolbarExtension } from './tiptap-toolbar-extension.js'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { Editor, Extension, Mark, Node } from '@umbraco-cms/backoffice/external/tiptap'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @@ -25,30 +24,6 @@ export interface UmbTiptapExtensionApi extends UmbApi { getTiptapExtensions(args?: UmbTiptapExtensionArgs): Array; } -export abstract class UmbTiptapExtensionApiBase extends UmbControllerBase implements UmbTiptapExtensionApi { - /** - * The manifest for the extension. - */ - manifest?: ManifestTiptapExtension; - - /** - * The editor instance. - */ - protected _editor?: Editor; - - /** - * @inheritdoc - */ - setEditor(editor: Editor): void { - this._editor = editor; - } - - /** - * @inheritdoc - */ - abstract getTiptapExtensions(args?: UmbTiptapExtensionArgs): Array; -} - export interface UmbTiptapExtensionArgs { /** * The data type configuration for the property editor that the editor is used for. @@ -74,30 +49,3 @@ export interface UmbTiptapToolbarElementApi extends UmbApi, UmbTiptapExtensionAr */ isActive(editor: Editor): boolean; } - -export abstract class UmbTiptapToolbarElementApiBase extends UmbControllerBase implements UmbTiptapToolbarElementApi { - /** - * The manifest for the extension. - */ - manifest?: ManifestTiptapToolbarExtension; - - /** - * The data type configuration for the property editor that the editor is used for. - */ - configuration?: UmbPropertyEditorConfigCollection; - - /** - * A method to execute the toolbar element action. - */ - public abstract execute(editor: Editor): void; - - /** - * Informs the toolbar element if it is active or not. It uses the manifest meta alias to check if the toolbar element is active. - * @see {ManifestTiptapToolbarExtension} - * @param {Editor} editor The editor instance. - * @returns {boolean} Returns true if the toolbar element is active. - */ - public isActive(editor: Editor) { - return editor && this.manifest?.meta.alias ? editor?.isActive(this.manifest.meta.alias) : false; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts new file mode 100644 index 0000000000..76433cbe17 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/base.filter.ts @@ -0,0 +1,6 @@ +import type { UmbUfmFilterApi } from '../ufm-filter.extension.js'; + +export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { + abstract filter(...args: Array): string | undefined | null; + destroy() {} +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts index 6735e76614..0a2edf9d05 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/index.ts @@ -1,6 +1,7 @@ export * from './components/index.js'; export * from './contexts/index.js'; export * from './controllers/ufm-virtual-render.controller.js'; +export * from './filters/base.filter.js'; export * from './plugins/index.js'; export * from './types.js'; export * from './ufm-component.extension.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts index 8b2395e4a6..5a25901cdb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/types.ts @@ -1,7 +1 @@ -import type { UmbUfmFilterApi } from './ufm-filter.extension.js'; - -// TODO: this is not a type, in TypeScript world, as it is an actual class. So it should be moved elsewhere [NL] -export abstract class UmbUfmFilterBase implements UmbUfmFilterApi { - abstract filter(...args: Array): string | undefined | null; - destroy() {} -} +export type * from './ufm-filter.extension.js'; From 6f6b4a74661e8658469fe8d39b85c0ac1e8f4941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 25 Oct 2024 10:55:17 +0200 Subject: [PATCH 198/246] imports --- .../packages/tiptap/extensions/core/embedded-media.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/figure.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/image.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/link.extension.ts | 2 +- .../packages/tiptap/extensions/core/media-upload.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/subscript.extension.ts | 2 +- .../packages/tiptap/extensions/core/superscript.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/table.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/text-align.extension.ts | 2 +- .../src/packages/tiptap/extensions/core/underline.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/blockquote.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/bold.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/bullet-list.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/code-block.extension.ts | 2 +- .../tiptap/extensions/toolbar/embedded-media.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/heading1.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/heading2.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/heading3.extension.ts | 2 +- .../tiptap/extensions/toolbar/horizontal-rule.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/italic.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/link.extension.ts | 2 +- .../tiptap/extensions/toolbar/media-picker.extension.ts | 2 +- .../tiptap/extensions/toolbar/ordered-list.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/redo.extension.ts | 2 +- .../tiptap/extensions/toolbar/source-editor.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/strike.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/subscript.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/superscript.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/table.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-center.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-justify.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-left.extension.ts | 2 +- .../tiptap/extensions/toolbar/text-align-right.extension.ts | 2 +- .../packages/tiptap/extensions/toolbar/underline.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/undo.extension.ts | 2 +- .../src/packages/tiptap/extensions/toolbar/unlink.extension.ts | 2 +- .../src/packages/ufm/filters/fallback.filter.ts | 2 +- .../src/packages/ufm/filters/lowercase.filter.ts | 2 +- .../src/packages/ufm/filters/strip-html.filter.ts | 2 +- .../src/packages/ufm/filters/title-case.filter.ts | 2 +- .../src/packages/ufm/filters/truncate.filter.ts | 2 +- .../src/packages/ufm/filters/uppercase.filter.ts | 2 +- .../src/packages/ufm/filters/word-limit.filter.ts | 2 +- 43 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts index 0e64a0153a..4cbc0188f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/embedded-media.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { umbEmbeddedMedia } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapEmbeddedMediaExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts index 1da6bdec35..0b879bb89e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/figure.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Figure, Figcaption } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapFigureExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts index 7254da3b61..7bb79bf2c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/image.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { UmbImage } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapImageExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts index 4800000fda..e09d36f5dc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/link.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { UmbLink } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapLinkExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts index 22fe093aaa..b6770bc230 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/media-upload.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import type { UmbTiptapExtensionArgs } from '../types.js'; import { imageSize } from '@umbraco-cms/backoffice/utils'; import { Extension } from '@umbraco-cms/backoffice/external/tiptap'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts index 57bfb91472..be83a3236e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/subscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Subscript } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapBoldExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts index 453efb13e5..e7757efc5d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/superscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Superscript } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapBoldExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts index d8c00b5d39..d3acf8c647 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/table.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Table, TableHeader, TableRow, TableCell } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapTableExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts index 9855c4d150..3d2598d5e3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/text-align.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { TextAlign } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapTextAlignExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts index f9663f91c8..3946d0b259 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/core/underline.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapExtensionApiBase } from '../types.js'; +import { UmbTiptapExtensionApiBase } from '../base.js'; import { Underline } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapUnderlineExtensionApi extends UmbTiptapExtensionApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts index f061e7e6b6..efd704be60 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/blockquote.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarBlockquoteExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts index 5ec1124963..8206a62dc4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bold.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarBoldExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts index 983adb0c3d..79fb5d338f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/bullet-list.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarBulletListExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts index a3a30b0f5d..f1c8930516 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/code-block.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarCodeBlockExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts index b50872c1f0..0a91f0801b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/embedded-media.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { umbEmbeddedMedia } from '@umbraco-cms/backoffice/external/tiptap'; import { UMB_EMBEDDED_MEDIA_MODAL } from '@umbraco-cms/backoffice/embedded-media'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts index b301f438e1..a9fd015ba9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading1.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHeading1ExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts index 663bc09d22..1274bd0e26 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading2.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHeading2ExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts index 3c3aed7cba..cb40b09cde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/heading3.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHeading3ExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts index 58836d2257..2ac3ddd0ab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/horizontal-rule.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarHorizontalRuleExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts index 2ac2c77649..9e329a1c37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/italic.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarItalicExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts index 3c1ef5f0af..31760d8f07 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/link.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { UmbLink } from '@umbraco-cms/backoffice/external/tiptap'; import { UMB_LINK_PICKER_MODAL } from '@umbraco-cms/backoffice/multi-url-picker'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts index 0ba24357bd..e77af1787d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/media-picker.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { getGuidFromUdi, getProcessedImageUrl, imageSize } from '@umbraco-cms/backoffice/utils'; import { ImageCropModeModel } from '@umbraco-cms/backoffice/external/backend-api'; import { UMB_MEDIA_CAPTION_ALT_TEXT_MODAL, UMB_MEDIA_PICKER_MODAL } from '@umbraco-cms/backoffice/media'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts index f95d7da3d2..26956cfcde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/ordered-list.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { OrderedList, ListItem } from '@umbraco-cms/backoffice/external/tiptap'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts index 0aae301bba..74c6696158 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/redo.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarRedoExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts index 7ff4fcd4ca..b40bd86234 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/source-editor.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import { UMB_CODE_EDITOR_MODAL } from '@umbraco-cms/backoffice/code-editor'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts index 1428e2009b..7062ab000e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/strike.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarStrikeExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts index 121e5210a6..d78312e01e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/subscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarSubscriptExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts index d46e966d29..5da21dc34d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/superscript.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarSuperscriptExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts index 3ef38f6f13..3589f6f138 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/table.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTableExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts index a027bc18c1..683f9cef2c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-center.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignCenterExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts index 38a53fc008..10e4825664 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-justify.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignJustifyExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts index 86b90b7e81..df6fb9fedb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-left.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignLeftExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts index 8f3984bb5c..1f0c703b87 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/text-align-right.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarTextAlignRightExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts index 9a2aab8b50..f0c91ab0af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/underline.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarUnderlineExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts index 1cc600442b..63b6183323 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/undo.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarUndoExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts index a3137f6ec5..947ff35307 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/unlink.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarUnlinkExtensionApi extends UmbTiptapToolbarElementApiBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts index ceb8001754..fe99db94a3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/fallback.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmFallbackFilterApi extends UmbUfmFilterBase { filter(str: string, fallback: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts index bf175a2a65..3b70e65cee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/lowercase.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmLowercaseFilterApi extends UmbUfmFilterBase { filter(str?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts index 6d19708e59..98b7e394d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/strip-html.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmStripHtmlFilterApi extends UmbUfmFilterBase { filter(value: string | { markup: string } | undefined | null) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts index ab546b7ee3..d4204a6203 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/title-case.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmTitleCaseFilterApi extends UmbUfmFilterBase { filter(str?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts index 34360ae41d..49d78554af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/truncate.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmTruncateFilterApi extends UmbUfmFilterBase { filter(str: string, length: number, tail?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts index 76af187aa9..b260f195fc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/uppercase.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmUppercaseFilterApi extends UmbUfmFilterBase { filter(str?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts index 8924386638..6abaea4680 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/filters/word-limit.filter.ts @@ -1,4 +1,4 @@ -import { UmbUfmFilterBase } from '../types.js'; +import { UmbUfmFilterBase } from './base.filter.js'; class UmbUfmWordLimitFilterApi extends UmbUfmFilterBase { filter(str: string, limit: number) { From 4c50f15cc57906ce205b77f2be6abd415b1beac1 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 28 Oct 2024 10:24:50 +0000 Subject: [PATCH 199/246] Bugfix: Prevent delete a template when has children (#2479) * Adds "Template Has No Children Condition" to prevent the "delete" action being displayed for templates that have child templates. * Removed condition config type it didn't have any configurable properties. Lazy-loaded the manifest api. * Renamed "Template Has No Children" condition to "Template Allow Delete Action" condition. --- .../conditions/allow-delete/const.ts | 1 + .../conditions/allow-delete/manifest.ts | 8 +++++++ .../template-allow-delete-action.condition.ts | 22 +++++++++++++++++++ .../templates/conditions/manifests.ts | 3 +++ .../templates/entity-actions/manifests.ts | 2 ++ .../templating/templates/manifests.ts | 2 ++ 6 files changed, 38 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts new file mode 100644 index 0000000000..b986c98f18 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts @@ -0,0 +1 @@ +export const UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS = 'Umb.Condition.Template.AllowDeleteAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts new file mode 100644 index 0000000000..37a4793a92 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts @@ -0,0 +1,8 @@ +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from './const.js'; + +export const manifest: UmbExtensionManifest = { + type: 'condition', + name: 'Template Allow Delete Action Condition', + alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS, + api: () => import('./template-allow-delete-action.condition.js'), +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts new file mode 100644 index 0000000000..c1550dab72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts @@ -0,0 +1,22 @@ +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_TREE_ITEM_CONTEXT } from '@umbraco-cms/backoffice/tree'; +import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbTemplateAllowDeleteActionCondition extends UmbConditionBase implements UmbExtensionCondition { + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + + this.consumeContext(UMB_TREE_ITEM_CONTEXT, (context) => { + this.observe( + context.hasChildren, + (hasChildren) => { + this.permitted = hasChildren === false; + }, + '_templateAllowDeleteActionCondition', + ); + }); + } +} + +export { UmbTemplateAllowDeleteActionCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts new file mode 100644 index 0000000000..731fde0ccd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as templateAllowDeleteActionCondition } from './allow-delete/manifest.js'; + +export const manifests: Array = [templateAllowDeleteActionCondition]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts index fb548f4166..7912a433e2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts @@ -1,5 +1,6 @@ import { UMB_TEMPLATE_DETAIL_REPOSITORY_ALIAS, UMB_TEMPLATE_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_TEMPLATE_ENTITY_TYPE, UMB_TEMPLATE_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from '../conditions/allow-delete/const.js'; export const manifests: Array = [ { @@ -26,5 +27,6 @@ export const manifests: Array = [ detailRepositoryAlias: UMB_TEMPLATE_DETAIL_REPOSITORY_ALIAS, itemRepositoryAlias: UMB_TEMPLATE_ITEM_REPOSITORY_ALIAS, }, + conditions: [{ alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS }], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts index eb8a2594d5..da057a5daa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/manifests.ts @@ -1,3 +1,4 @@ +import { manifests as conditionsManifests } from './conditions/manifests.js'; import { manifests as entityActionsManifests } from './entity-actions/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; @@ -7,6 +8,7 @@ import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; export const manifests: Array = [ + ...conditionsManifests, ...entityActionsManifests, ...menuManifests, ...modalManifests, From c848d4569fcb3c0fe7f3762de33d0662a5151504 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:39:45 +0100 Subject: [PATCH 200/246] align naming --- .../allow-delete/{const.ts => constants.ts} | 0 .../templates/conditions/allow-delete/index.ts | 1 + .../conditions/allow-delete/manifest.ts | 16 +++++++++------- .../templating/templates/conditions/index.ts | 1 + .../templating/templates/conditions/manifests.ts | 4 ++-- .../templates/entity-actions/manifests.ts | 2 +- .../src/packages/templating/templates/index.ts | 1 + 7 files changed, 15 insertions(+), 10 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/{const.ts => constants.ts} (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/const.ts rename to src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts index 37a4793a92..d1aac15331 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/manifest.ts @@ -1,8 +1,10 @@ -import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from './const.js'; +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from './constants.js'; -export const manifest: UmbExtensionManifest = { - type: 'condition', - name: 'Template Allow Delete Action Condition', - alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS, - api: () => import('./template-allow-delete-action.condition.js'), -}; +export const manifests: Array = [ + { + type: 'condition', + name: 'Template Allow Delete Action Condition', + alias: UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS, + api: () => import('./template-allow-delete-action.condition.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts new file mode 100644 index 0000000000..dc6ddce39a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/index.ts @@ -0,0 +1 @@ +export * from './allow-delete/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts index 731fde0ccd..d11b41693e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/manifests.ts @@ -1,3 +1,3 @@ -import { manifest as templateAllowDeleteActionCondition } from './allow-delete/manifest.js'; +import { manifests as allowDeleteManifests } from './allow-delete/manifest.js'; -export const manifests: Array = [templateAllowDeleteActionCondition]; +export const manifests: Array = [...allowDeleteManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts index 7912a433e2..4816de0c1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/manifests.ts @@ -1,6 +1,6 @@ import { UMB_TEMPLATE_DETAIL_REPOSITORY_ALIAS, UMB_TEMPLATE_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_TEMPLATE_ENTITY_TYPE, UMB_TEMPLATE_ROOT_ENTITY_TYPE } from '../entity.js'; -import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from '../conditions/allow-delete/const.js'; +import { UMB_TEMPLATE_ALLOW_DELETE_ACTION_CONDITION_ALIAS } from '../conditions/allow-delete/constants.js'; export const manifests: Array = [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts index 392b743cee..9bec7964b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/index.ts @@ -5,5 +5,6 @@ export * from './entity.js'; export * from './modals/index.js'; export * from './repository/index.js'; export * from './tree/index.js'; +export * from './conditions/index.js'; export type { UmbTemplateDetailModel } from './types.js'; From e96013ac295a084df80067ee27d5ab453b3e8027 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:35:32 +0100 Subject: [PATCH 201/246] Bugfix: Hide template input when there are no allowed templates (#2484) hide template input when there are no allowed templates --- .../document-workspace-view-info.element.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index 212f78cf05..576f954bbc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -159,7 +159,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { #renderGeneralSection() { const editDocumentTypePath = this._routeBuilder?.({ entityType: 'document-type' }) ?? ''; - const editTemplatePath = this._routeBuilder?.({ entityType: 'template' }) ?? ''; return html`
      @@ -177,6 +176,20 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement {
      + ${this.#renderTemplateInput()} +
      + Id + ${this._documentUnique} +
      + `; + } + + #renderTemplateInput() { + if (this._allowedTemplates?.length === 0) return nothing; + + const editTemplatePath = this._routeBuilder?.({ entityType: 'template' }) ?? ''; + + return html`
      Template ${this._templateUnique @@ -200,10 +213,6 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { @click=${this.#openTemplatePicker}> `}
      -
      - Id - ${this._documentUnique} -
      `; } From a4e75f40d0ed5cf77ba037645d63b4d71005439f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:41:45 +0100 Subject: [PATCH 202/246] Hotfix: Publish with decendants structure reload (#2486) * ensure we always have the latest variant data * use enum value * Update document-tree-item.element.ts * only dispatch event if there is no error * reload structure after publish with descendants * only request update if it succeeds * rename private method --- .../entity-actions/unpublish.action.ts | 16 ++++--- .../tree-item/document-tree-item.element.ts | 17 +++++-- .../workspace/document-workspace.context.ts | 47 ++++++++++++++----- 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts index ff9d645a17..46d3471ea3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/unpublish.action.ts @@ -77,15 +77,17 @@ export class UmbUnpublishDocumentEntityAction extends UmbEntityActionBase if (variantIds.length) { const publishingRepository = new UmbDocumentPublishingRepository(this._host); - await publishingRepository.unpublish(this.args.unique, variantIds); + const { error } = await publishingRepository.unpublish(this.args.unique, variantIds); - const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadStructureForEntityEvent({ - unique: this.args.unique, - entityType: this.args.entityType, - }); + if (!error) { + const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadStructureForEntityEvent({ + unique: this.args.unique, + entityType: this.args.entityType, + }); - actionEventContext.dispatchEvent(event); + actionEventContext.dispatchEvent(event); + } } } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts index 3c5c94c536..634f3d8bad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/tree-item/document-tree-item.element.ts @@ -1,4 +1,5 @@ import type { UmbDocumentTreeItemModel, UmbDocumentTreeItemVariantModel } from '../types.js'; +import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { css, html, nothing, customElement, state, classMap } from '@umbraco-cms/backoffice/external/lit'; import type { UmbAppLanguageContext } from '@umbraco-cms/backoffice/language'; import { UMB_APP_LANGUAGE_CONTEXT } from '@umbraco-cms/backoffice/language'; @@ -31,7 +32,7 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase { this._currentCulture = value; - this._variant = this.#getVariant(value); + this._variant = this.#findVariant(value); }); } @@ -41,7 +42,7 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase x.culture === culture); } @@ -56,16 +57,22 @@ export class UmbDocumentTreeItemElement extends UmbTreeItemElementBase ({ variantId })), ); - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadStructureForEntityEvent({ - unique: this.getUnique()!, - entityType: this.getEntityType(), - }); + if (!error) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadStructureForEntityEvent({ + unique: this.getUnique()!, + entityType: this.getEntityType(), + }); - eventContext.dispatchEvent(event); + eventContext.dispatchEvent(event); + } } async #handleSave() { @@ -832,6 +834,12 @@ export class UmbDocumentWorkspaceContext } public async publishWithDescendants() { + const unique = this.getUnique(); + if (!unique) throw new Error('Unique is missing'); + + const entityType = this.getEntityType(); + if (!entityType) throw new Error('Entity type is missing'); + const { options, selected } = await this.#determineVariantOptions(); const modalManagerContext = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); @@ -853,15 +861,30 @@ export class UmbDocumentWorkspaceContext if (!variantIds.length) return; - // TODO: Validate content & Save changes for the selected variants — This was how it worked in v.13 [NL] - - const unique = this.getUnique(); - if (!unique) throw new Error('Unique is missing'); - await this.publishingRepository.publishWithDescendants( + const { error } = await this.publishingRepository.publishWithDescendants( unique, variantIds, result.includeUnpublishedDescendants ?? false, ); + + if (!error) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + + // request reload of this entity + const structureEvent = new UmbRequestReloadStructureForEntityEvent({ + entityType, + unique, + }); + + // request reload of the children + const childrenEvent = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(structureEvent); + eventContext.dispatchEvent(childrenEvent); + } } async delete() { From 6756ef076990d08fd7b8bd1b2e579bc2d1abe808 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 11:48:32 +0100 Subject: [PATCH 203/246] Hotfix: Correct user enable notification (#2487) * show localized notification when user is enabled * localize disable messages --- .../disable/disable-user.repository.ts | 17 ++++++++++++++++- .../repository/enable/enable-user.repository.ts | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts index d7c94c6beb..81bc35ff41 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/disable/disable-user.repository.ts @@ -1,10 +1,14 @@ import { UmbUserRepositoryBase } from '../user-repository-base.js'; +import { UmbUserItemRepository } from '../item/index.js'; import { UmbDisableUserServerDataSource } from './disable-user.server.data-source.js'; +import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDisableUserRepository extends UmbUserRepositoryBase { #disableSource: UmbDisableUserServerDataSource; + #localize = new UmbLocalizationController(this); + #userItemRepository = new UmbUserItemRepository(this); constructor(host: UmbControllerHost) { super(host); @@ -18,11 +22,22 @@ export class UmbDisableUserRepository extends UmbUserRepositoryBase { const { data, error } = await this.#disableSource.disable(ids); if (!error) { + const { data: items } = await this.#userItemRepository.requestItems(ids); + if (!items) throw new Error('Could not load user item'); + + // TODO: get state from item when available ids.forEach((id) => { this.detailStore?.updateItem(id, { state: UserStateModel.DISABLED }); }); - const notification = { data: { message: `User disabled` } }; + let message = this.#localize.term('speechBubbles_disableUsersSuccess', items.length); + + if (items.length === 1) { + const names = items?.map((item) => item.name).join(', '); + message = this.#localize.term('speechBubbles_disableUserSuccess', names); + } + + const notification = { data: { message } }; this.notificationContext?.peek('positive', notification); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts index 2728c4807d..4c871e5fd5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/enable/enable-user.repository.ts @@ -1,10 +1,14 @@ import { UmbUserRepositoryBase } from '../user-repository-base.js'; +import { UmbUserItemRepository } from '../item/index.js'; import { UmbEnableUserServerDataSource } from './enable-user.server.data-source.js'; +import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UserStateModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbEnableUserRepository extends UmbUserRepositoryBase { #enableSource: UmbEnableUserServerDataSource; + #localize = new UmbLocalizationController(this); + #userItemRepository = new UmbUserItemRepository(this); constructor(host: UmbControllerHost) { super(host); @@ -18,11 +22,22 @@ export class UmbEnableUserRepository extends UmbUserRepositoryBase { const { data, error } = await this.#enableSource.enable(ids); if (!error) { + const { data: items } = await this.#userItemRepository.requestItems(ids); + if (!items) throw new Error('Could not load user item'); + + // TODO: get state from item when available ids.forEach((id) => { this.detailStore?.updateItem(id, { state: UserStateModel.ACTIVE }); }); - const notification = { data: { message: `User disabled` } }; + let message = this.#localize.term('speechBubbles_enableUsersSuccess', items.length); + + if (items.length === 1) { + const names = items?.map((item) => item.name).join(', '); + message = this.#localize.term('speechBubbles_enableUserSuccess', names); + } + + const notification = { data: { message } }; this.notificationContext?.peek('positive', notification); } From 083ed9d192b8aaa873516dac1fed26738e50fd2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 28 Oct 2024 13:56:37 +0100 Subject: [PATCH 204/246] deprecate ManifestTypes --- .../core/extension-registry/models/index.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index 7c562c37af..2b3c1e5178 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -1,6 +1,29 @@ import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; -export type ManifestTypes = ManifestBundle | ManifestCondition | ManifestBase; +/** + * @deprecated Follow these steps to get Extension Manifest Type for v.15+ projects: + * + * Setup your `tsconfig.json` to include the extension-types as global types. Like this: + * ``` + { + "compilerOptions": { + ... + "types": [ + "@umbraco-cms/backoffice/extension-types" + ] + } + } + * ``` + * + * Once done, you can use the global type `UmbExtensionManifest`. + * + * If defining your own extension types, then follow the link below for more information. + * + * [Read more on the change announcement]{https://github.com/umbraco/Announcements/issues/22} + */ +export type ManifestTypes = never; + +type UmbCoreManifestTypes = ManifestBundle | ManifestCondition | ManifestBase; type UnionOfProperties = T extends object ? T[keyof T] : never; @@ -25,7 +48,7 @@ declare global { ``` */ interface UmbExtensionManifestMap { - UMB_CORE: ManifestTypes; + UMB_CORE: UmbCoreManifestTypes; } /** From 52f03b9c386b2a1d62538c998a20af585ebf93a6 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 28 Oct 2024 17:41:27 +0000 Subject: [PATCH 205/246] Detail repository save returns updated model previously returned the original model, prior to any server updates, e.g. updated date. --- .../packages/core/repository/detail/detail-repository-base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts index 5f7d695eaa..12a77e5437 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts @@ -124,7 +124,7 @@ export abstract class UmbDetailRepositoryBase< this.#notificationContext!.peek('positive', notification); } - return { data: model, error }; + return { data: updatedData, error }; } /** From 59790431c46a0ee60e217989eb02867851ffb794 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 4 Nov 2024 13:07:13 +0000 Subject: [PATCH 206/246] Bugfix: Block Type card thunbnail image path/URL (#2480) Block Type Cards: Fixed image URL Removed the backoffice path from the URL, as the image paths are relative to the root of the website. --- .../block-type-card/block-type-card.element.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts index 5ec53ac6a3..376e077785 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts @@ -6,13 +6,14 @@ import { html, customElement, property, state, ifDefined } from '@umbraco-cms/ba import { UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; -import { removeLastSlashFromPath, transformServerPathToClientPath } from '@umbraco-cms/backoffice/utils'; +import { transformServerPathToClientPath } from '@umbraco-cms/backoffice/utils'; import { UUICardEvent } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-block-type-card') export class UmbBlockTypeCardElement extends UmbLitElement { - readonly #init: Promise; - #appUrl: string = ''; + // + #init: Promise; + #serverUrl: string = ''; readonly #itemManager = new UmbRepositoryItemsManager( this, @@ -28,7 +29,8 @@ export class UmbBlockTypeCardElement extends UmbLitElement { value = transformServerPathToClientPath(value); if (value) { this.#init.then(() => { - this._iconFile = removeLastSlashFromPath(this.#appUrl) + value; + const url = new URL(value, this.#serverUrl); + this._iconFile = url.href; }); } else { this._iconFile = undefined; @@ -76,7 +78,7 @@ export class UmbBlockTypeCardElement extends UmbLitElement { super(); this.#init = this.getContext(UMB_APP_CONTEXT).then((appContext) => { - this.#appUrl = appContext.getServerUrl() + appContext.getBackofficePath(); + this.#serverUrl = appContext.getServerUrl(); }); this.observe(this.#itemManager.items, (items) => { From 42fe0c381913dbe15538e96cf79d863dff90bd3f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 14:56:14 +0100 Subject: [PATCH 207/246] wip add entity-create-option-action extension point --- .../entity-create-option-action.element.ts | 87 ++++++++++++++ .../create-option-action/default/index.ts | 1 + .../create-option-action/default/manifests.ts | 20 ++++ .../create-option-action/default/types.ts | 44 +++++++ .../entity-create-option-action-base.ts | 27 +++++ ...-create-option-action-element.interface.ts | 4 + ...ntity-create-option-action-list.element.ts | 108 ++++++++++++++++++ .../entity-create-option-action.extension.ts | 13 +++ .../entity-create-option-action.interface.ts | 17 +++ .../core/entity/create-option-action/index.ts | 7 ++ .../entity/create-option-action/manifests.ts | 4 + .../core/entity/create-option-action/types.ts | 5 + 12 files changed, 337 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts new file mode 100644 index 0000000000..5c926bbe3e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts @@ -0,0 +1,87 @@ +import type { UmbEntityCreateOptionAction } from '../entity-create-option-action.interface.js'; +import type { UmbEntityCreateOptionActionElement } from '../entity-create-option-action-element.interface.js'; +import type { ManifestEntityCreateOptionAction } from '../entity-create-option-action.extension.js'; +import type { MetaEntityCreateOptionActionDefaultKind } from './types.js'; +import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; +import { html, nothing, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import type { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-entity-create-option-action'; +@customElement(elementName) +export class UmbEntityCreateOptionActionDefaultElement< + MetaType extends MetaEntityCreateOptionActionDefaultKind = MetaEntityCreateOptionActionDefaultKind, + ApiType extends UmbEntityCreateOptionAction = UmbEntityCreateOptionAction, + > + extends UmbLitElement + implements UmbEntityCreateOptionActionElement +{ + #api?: ApiType; + + // TODO: Do these need to be properties? [NL] + @property({ type: String }) + entityType?: string | null; + + // TODO: Do these need to be properties? [NL] + @property({ type: String }) + public unique?: string | null; + + @property({ attribute: false }) + public manifest?: ManifestEntityCreateOptionAction; + + public set api(api: ApiType | undefined) { + this.#api = api; + + // TODO: Fix so when we use a HREF it does not refresh the page? + this.#api?.getHref?.().then((href) => { + this._href = href; + // TODO: Do we need to update the component here? [NL] + }); + } + + @state() + _href?: string; + + override async focus() { + await this.updateComplete; + this.shadowRoot?.querySelector('uui-menu-item')?.focus(); + } + + async #onClickLabel(event: UUIMenuItemEvent) { + if (!this._href) { + event.stopPropagation(); + await this.#api?.execute(); + } + this.dispatchEvent(new UmbActionExecutedEvent()); + } + + // TODO: we need to stop the regular click event from bubbling up to the table so it doesn't select the row. + // This should probably be handled in the UUI Menu item component. so we don't dispatch a label-click event and click event at the same time. + #onClick(event: PointerEvent) { + event.stopPropagation(); + } + + override render() { + const label = this.manifest?.meta.label ? this.localize.string(this.manifest.meta.label) : this.manifest?.name; + + return html` + + ${this.manifest?.meta.icon + ? html`` + : nothing} + + `; + } +} + +export { UmbEntityCreateOptionActionDefaultElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbEntityCreateOptionActionDefaultElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts new file mode 100644 index 0000000000..d4702960d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts @@ -0,0 +1 @@ +export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts new file mode 100644 index 0000000000..b1b7de24bf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts @@ -0,0 +1,20 @@ +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.EntityCreateOptionAction.Default', + matchKind: 'default', + matchType: 'entityCreateOptionAction', + manifest: { + type: 'entityCreateOptionAction', + kind: 'default', + weight: 1000, + element: () => import('./entity-create-option-action.element.js'), + meta: { + icon: '', + label: 'Default Entity Create Option Action', + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts new file mode 100644 index 0000000000..465664c91c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts @@ -0,0 +1,44 @@ +import type { + ManifestEntityCreateOptionAction, + MetaEntityCreateOptionAction, +} from '../entity-create-option-action.extension.js'; + +export interface ManifestEntityCreateOptionActionDefaultKind + extends ManifestEntityCreateOptionAction { + type: 'entityCreateOptionAction'; + kind: 'default'; +} + +export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { + /** + * An icon to represent the action to be performed + * @examples [ + * "icon-box", + * "icon-grid" + * ] + */ + icon: string; + + /** + * The friendly name of the action to perform + * @examples [ + * "Create", + * "Create Content Template" + * ] + */ + label: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + * @memberof MetaEntityCreateOptionActionDefaultKind + */ + additionalOptions?: boolean; +} + +declare global { + interface UmbExtensionManifestMap { + umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts new file mode 100644 index 0000000000..c8daf62492 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts @@ -0,0 +1,27 @@ +import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; +import { UmbActionBase } from '@umbraco-cms/backoffice/action'; + +export abstract class UmbEntityCreateOptionActionBase + extends UmbActionBase> + implements UmbEntityCreateOptionAction +{ + /** + * By specifying the href, the action will act as a link. + * The `execute` method will not be called. + * @abstract + * @returns {string | undefined} + */ + public getHref(): Promise { + return Promise.resolve(undefined); + } + + /** + * By specifying the `execute` method, the action will act as a button. + * @abstract + * @returns {Promise} + */ + public execute(): Promise { + return Promise.resolve(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts new file mode 100644 index 0000000000..6f2c9ab833 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts @@ -0,0 +1,4 @@ +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbEntityCreateOptionActionElement extends UmbControllerHostElement {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts new file mode 100644 index 0000000000..082816e24f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts @@ -0,0 +1,108 @@ +import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { + ManifestEntityCreateOptionAction, + MetaEntityCreateOptionAction, +} from './entity-create-option-action.extension.js'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; +import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbApiConstructorArgumentsMethodType } from '@umbraco-cms/backoffice/extension-api'; + +const elementName = 'umb-entity-create-option-action-list'; +@customElement(elementName) +export class UmbEntityCreateOptionActionListElement extends UmbLitElement { + @property({ type: String, attribute: 'entity-type' }) + public get entityType(): string | undefined { + return this._props.entityType; + } + public set entityType(value: string | undefined) { + if (value === undefined || value === this._props.entityType) return; + this._props.entityType = value; + this.#generateApiArgs(); + this.requestUpdate('_props'); + // Update filter: + //const oldValue = this._filter; + this._filter = (extension: ManifestEntityCreateOptionAction) => + extension.forEntityTypes.includes(value); + //this.requestUpdate('_filter', oldValue); + } + + @state() + _filter?: (extension: ManifestEntityCreateOptionAction) => boolean; + + @property({ type: String }) + public get unique(): string | null | undefined { + return this._props.unique; + } + public set unique(value: string | null | undefined) { + if (value === this._props.unique) return; + this._props.unique = value; + this.#generateApiArgs(); + this.requestUpdate('_props'); + } + + @state() + _props: Partial> = {}; + + @state() + _apiArgs?: UmbApiConstructorArgumentsMethodType< + ManifestEntityCreateOptionAction, + [UmbEntityCreateOptionActionArgs] + >; + + #entityContext = new UmbEntityContext(this); + + #generateApiArgs() { + if (!this._props.entityType || this._props.unique === undefined) return; + + this.#entityContext.setEntityType(this._props.entityType); + this.#entityContext.setUnique(this._props.unique); + this.#hasRenderedOnce = false; + + this._apiArgs = (manifest: ManifestEntityCreateOptionAction) => { + return [{ entityType: this._props.entityType!, unique: this._props.unique!, meta: manifest.meta }]; + }; + } + + #hasRenderedOnce?: boolean; + override render() { + return this._filter + ? html` + { + if (!this.#hasRenderedOnce && i === 0) { + // TODO: Replace this block: + ext.component?.updateComplete.then(async () => { + const menuitem = ext.component?.shadowRoot?.querySelector('uui-menu-item'); + menuitem?.updateComplete.then(async () => { + menuitem?.shadowRoot?.querySelector('#label-button')?.focus?.(); + }); + }); + // end of block, with this, when this PR is part of UI Lib: https://github.com/umbraco/Umbraco.UI/pull/789 + // ext.component?.focus(); + this.#hasRenderedOnce = true; + } + return ext.component; + }}> + ` + : ''; + } + + static override styles = [ + css` + :host { + --uui-menu-item-flat-structure: 1; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbEntityCreateOptionActionListElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts new file mode 100644 index 0000000000..2835753767 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts @@ -0,0 +1,13 @@ +import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; + +export interface ManifestEntityCreateOptionAction< + MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, +> extends ManifestElementAndApi, + ManifestWithDynamicConditions { + type: 'entityCreateOptionAction'; + forEntityTypes: Array; + meta: MetaType; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface MetaEntityCreateOptionAction {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts new file mode 100644 index 0000000000..0956868cb7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts @@ -0,0 +1,17 @@ +import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { UmbAction } from '@umbraco-cms/backoffice/action'; + +export interface UmbEntityCreateOptionAction + extends UmbAction> { + /** + * The href location, the action will act as a link. + * @returns {Promise} + */ + getHref(): Promise; + + /** + * The `execute` method, the action will act as a button. + * @returns {Promise} + */ + execute(): Promise; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts new file mode 100644 index 0000000000..c3a44c8f72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts @@ -0,0 +1,7 @@ +export * from './default/index.js'; +export * from './entity-create-option-action-base.js'; +export * from './entity-create-option-action-list.element.js'; +export * from './entity-create-option-action.extension.js'; +export * from './entity-create-option-action.interface.js'; +export * from './types.js'; +export type * from './entity-create-option-action-element.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts new file mode 100644 index 0000000000..84f3b7f88d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as defaultEntityActionManifests } from './default/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...defaultEntityActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts new file mode 100644 index 0000000000..ca6db2fc24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts @@ -0,0 +1,5 @@ +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; + +export interface UmbEntityCreateOptionActionArgs extends UmbEntityModel { + meta: MetaArgsType; +} From 824a250df4fb96d8f4ee9d5ecaad2b113d81b886 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 15:08:14 +0100 Subject: [PATCH 208/246] add global-components folder --- .../entity-create-option-action-list.element.ts | 4 ++-- .../create-option-action/global-components/index.ts | 3 +++ .../packages/core/entity/create-option-action/index.ts | 9 +++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/{ => global-components}/entity-create-option-action-list.element.ts (96%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts similarity index 96% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts index 082816e24f..e8cdaed63f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts @@ -1,8 +1,8 @@ -import type { UmbEntityCreateOptionActionArgs } from './types.js'; +import type { UmbEntityCreateOptionActionArgs } from '../types.js'; import type { ManifestEntityCreateOptionAction, MetaEntityCreateOptionAction, -} from './entity-create-option-action.extension.js'; +} from '../entity-create-option-action.extension.js'; import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts new file mode 100644 index 0000000000..40da9cdab0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts @@ -0,0 +1,3 @@ +import './entity-create-option-action-list.element.js'; + +export * from './entity-create-option-action-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts index c3a44c8f72..5eb9c9635d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts @@ -1,7 +1,12 @@ +import './global-components/index.js'; + export * from './default/index.js'; +export * from './global-components/index.js'; + export * from './entity-create-option-action-base.js'; -export * from './entity-create-option-action-list.element.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; -export * from './types.js'; + export type * from './entity-create-option-action-element.interface.js'; + +export * from './types.js'; From bb25b881e912c960d30973261863b2666170f03a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 15:08:23 +0100 Subject: [PATCH 209/246] register create options --- .../user/entity-actions/create/manifests.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index b92ae65395..dc08f52bf6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { manifests as modalManifests } from './modal/manifests.js'; @@ -19,5 +19,31 @@ export const manifests: Array = additionalOptions: true, }, }, + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Default', + name: 'Default User Entity Create Option Action', + weight: 1200, + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: 'Default (Extension)', + additionalOptions: true, + }, + }, + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Api', + name: 'Api User Entity Create Option Action', + weight: 1200, + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: 'Api (Extension)', + additionalOptions: true, + }, + }, ...modalManifests, ]; From 7507c74d516f1d9e529ade928943d9cb135c5a67 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 15:11:43 +0100 Subject: [PATCH 210/246] Update index.ts --- src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index 737d7bf482..7c1422a9ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,3 +1,4 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; +export * from './create-option-action/index.js'; export type * from './types.js'; From 5ab629c6f9beee0facaba261f6f818c52acb7bff Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 17:47:09 +0100 Subject: [PATCH 211/246] use entityCreateOptionAction entity type --- .../entity-create-option-action-list.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts index e8cdaed63f..eeb948c5d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts @@ -51,6 +51,7 @@ export class UmbEntityCreateOptionActionListElement extends UmbLitElement { >; #entityContext = new UmbEntityContext(this); + #extensionType = 'entityCreateOptionAction'; #generateApiArgs() { if (!this._props.entityType || this._props.unique === undefined) return; @@ -69,7 +70,7 @@ export class UmbEntityCreateOptionActionListElement extends UmbLitElement { return this._filter ? html` Date: Mon, 28 Oct 2024 17:47:41 +0100 Subject: [PATCH 212/246] export manifests --- .../packages/core/entity/create-option-action/manifests.ts | 4 ++-- .../src/packages/core/entity/manifests.ts | 4 ++++ src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts index 84f3b7f88d..43d020c74e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts @@ -1,4 +1,4 @@ -import { manifests as defaultEntityActionManifests } from './default/manifests.js'; +import { manifests as defaultManifests } from './default/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...defaultEntityActionManifests]; +export const manifests: Array = [...defaultManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts new file mode 100644 index 0000000000..3a24422566 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...createOptionActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index 807e23de70..d01847d9d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -7,6 +7,7 @@ import { manifests as cultureManifests } from './culture/manifests.js'; import { manifests as debugManifests } from './debug/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-action/manifests.js'; +import { manifests as entityManifests } from './entity/manifests.js'; import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; @@ -36,6 +37,7 @@ export const manifests: Array = ...debugManifests, ...entityActionManifests, ...entityBulkActionManifests, + ...entityManifests, ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, From 53c514e26f7bff2567c43205db4f532c5f7e83b5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 Oct 2024 22:18:27 +0100 Subject: [PATCH 213/246] register user entity create option actions --- .../api-user-entity-create-option-action.ts | 9 ++ .../create/api-user/manifests.ts | 18 ++++ ...efault-user-entity-create-option-action.ts | 45 +++++++++ .../create/default-user/manifests.ts | 18 ++++ .../user/entity-actions/create/manifests.ts | 33 +------ .../user-create-options-modal.element.ts | 91 ++++--------------- 6 files changed, 112 insertions(+), 102 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts new file mode 100644 index 0000000000..62404d353f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -0,0 +1,9 @@ +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; + +export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { + override async execute() { + debugger; + } +} + +export { UmbApiUserEntityCreateOptionAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts new file mode 100644 index 0000000000..5c5ea02ca8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; + +export const manifests: Array = [ + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Api', + name: 'Api User Entity Create Option Action', + weight: 1100, + api: () => import('./api-user-entity-create-option-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-unplug', + label: '#user_userKindApi', + additionalOptions: true, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts new file mode 100644 index 0000000000..e661e70363 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -0,0 +1,45 @@ +import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; +import type { UmbUserKindType } from '../../../utils/index.js'; +import { UmbUserKind } from '../../../utils/index.js'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const kind: UmbUserKindType = UmbUserKind.DEFAULT; + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); + + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity(); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity(); + }); + } + + async #requestReloadChildrenOfEntity() { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType: this.args.entityType, + unique: this.args.unique, + }); + + eventContext.dispatchEvent(event); + } +} + +export { UmbDefaultUserEntityCreateOptionAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts new file mode 100644 index 0000000000..4e12d1e039 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; + +export const manifests: Array = [ + { + type: 'entityCreateOptionAction', + kind: 'default', + alias: 'Umb.EntityCreateOptionAction.User.Default', + name: 'Default User Entity Create Option Action', + weight: 1200, + api: () => import('./default-user-entity-create-option-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-user', + label: '#user_userKindDefault', + additionalOptions: true, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index dc08f52bf6..658fa547d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,5 +1,6 @@ -import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; - +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { manifests as apiUser } from './api-user/manifests.js'; +import { manifests as defaultUser } from './default-user/manifests.js'; import { manifests as modalManifests } from './modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -19,31 +20,7 @@ export const manifests: Array = additionalOptions: true, }, }, - { - type: 'entityCreateOptionAction', - kind: 'default', - alias: 'Umb.EntityCreateOptionAction.User.Default', - name: 'Default User Entity Create Option Action', - weight: 1200, - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-add', - label: 'Default (Extension)', - additionalOptions: true, - }, - }, - { - type: 'entityCreateOptionAction', - kind: 'default', - alias: 'Umb.EntityCreateOptionAction.User.Api', - name: 'Api User Entity Create Option Action', - weight: 1200, - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-add', - label: 'Api (Extension)', - additionalOptions: true, - }, - }, + ...apiUser, + ...defaultUser, ...modalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts index 74e8646990..cc9ba965f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -1,92 +1,35 @@ -import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; -import { UmbUserKind, type UmbUserKindType } from '../../../utils/index.js'; -import { html, customElement, map } from '@umbraco-cms/backoffice/external/lit'; -import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; - -interface UmbUserCreateOptionModel { - label: string; - description?: string; - icon: string; - kind: UmbUserKindType; -} const elementName = 'umb-user-create-options-modal'; @customElement(elementName) export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { - #options: Array = [ - { - label: this.localize.term('user_userKindDefault'), - icon: 'icon-user', - kind: UmbUserKind.DEFAULT, - }, - { - label: this.localize.term('user_userKindApi'), - icon: 'icon-unplug', - kind: UmbUserKind.API, - }, - ]; + @state() + entity: UmbEntityModel = { + entityType: '', + unique: '', + }; - async #onClick(event: Event, kind: UmbUserKindType) { - event.stopPropagation(); - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + constructor() { + super(); - const unique = entityContext.getUnique(); - const entityType = entityContext.getEntityType(); - - if (unique === undefined) throw new Error('Missing unique'); - if (!entityType) throw new Error('Missing entityType'); - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { - data: { - user: { - kind, - }, - }, + this.consumeContext(UMB_ENTITY_CONTEXT, (context) => { + this.entity = { + entityType: context.getEntityType(), + unique: context.getUnique(), + }; }); - - modalContext - ?.onSubmit() - .then(() => { - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }) - .catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }); - } - - async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - - eventContext.dispatchEvent(event); } override render() { return html` - - ${map( - this.#options, - (item) => html` - this.#onClick(event, item.kind)}> - `, - )} - + Date: Mon, 28 Oct 2024 22:49:05 +0100 Subject: [PATCH 214/246] setup common action and generic modal --- .../common/create/create.action.kind.ts | 22 +++++++++ .../common/create/create.action.ts | 20 ++++++++ .../core/entity-action/common/create/index.ts | 1 + .../entity-action/common/create/manifests.ts | 4 ++ .../common/create/modal/constants.ts | 1 + ...create-option-action-list-modal.element.ts | 37 ++++++++++++++ ...y-create-option-action-list-modal.token.ts | 20 ++++++++ .../common/create/modal/index.ts | 2 + .../common/create/modal/manifests.ts | 10 ++++ .../core/entity-action/common/create/types.ts | 16 ++++++ .../core/entity-action/common/index.ts | 3 +- .../packages/core/entity-action/manifests.ts | 3 ++ .../create/create-user-entity-action.ts | 21 -------- .../user/entity-actions/create/manifests.ts | 11 +---- .../user/entity-actions/create/modal/index.ts | 8 --- .../entity-actions/create/modal/manifests.ts | 8 --- .../user-create-options-modal.element.ts | 49 ------------------- 17 files changed, 139 insertions(+), 97 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts new file mode 100644 index 0000000000..a220d955aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.kind.ts @@ -0,0 +1,22 @@ +import { UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST } from '../../default/default.action.kind.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest: UmbExtensionManifestKind = { + type: 'kind', + alias: 'Umb.Kind.EntityAction.Create', + matchKind: 'create', + matchType: 'entityAction', + manifest: { + ...UMB_ENTITY_ACTION_DEFAULT_KIND_MANIFEST.manifest, + type: 'entityAction', + kind: 'create', + api: () => import('./create.action.js'), + weight: 1200, + forEntityTypes: [], + meta: { + icon: 'icon-add', + label: '#actions_create', + additionalOptions: true, + }, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts new file mode 100644 index 0000000000..35f0dda58a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -0,0 +1,20 @@ +import { UmbEntityActionBase } from '../../entity-action-base.js'; +import type { MetaEntityActionCreateKind } from './types.js'; +import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modalContext = modalManager.open(this, UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL, { + data: { + unique: this.args.unique, + entityType: this.args.entityType, + }, + }); + + await modalContext.onSubmit(); + } +} + +export { UmbCreateEntityAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts new file mode 100644 index 0000000000..d44c5eca74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -0,0 +1 @@ +export { UmbCreateEntityAction } from './create.action.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts new file mode 100644 index 0000000000..d1e496f559 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts @@ -0,0 +1,4 @@ +import { manifest as createKindManifest } from './create.action.kind.js'; +import { manifests as modalManifests } from './modal/manifests.js'; + +export const manifests = [createKindManifest, ...modalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts new file mode 100644 index 0000000000..ab81577a04 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/constants.ts @@ -0,0 +1 @@ +export const UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS = 'Umb.Modal.Entity.CreateOptionActionList'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts new file mode 100644 index 0000000000..e9ada04e69 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -0,0 +1,37 @@ +import type { + UmbEntityCreateOptionActionListModalData, + UmbEntityCreateOptionActionListModalValue, +} from './entity-create-option-action-list-modal.token.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; + +const elementName = 'umb-entity-create-option-action-list-modal'; +@customElement(elementName) +export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseElement< + UmbEntityCreateOptionActionListModalData, + UmbEntityCreateOptionActionListModalValue +> { + override render() { + return html` + + + + + + + `; + } +} + +export { UmbEntityCreateOptionActionListModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbEntityCreateOptionActionListModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts new file mode 100644 index 0000000000..dd1aba66b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.token.ts @@ -0,0 +1,20 @@ +import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS } from './constants.js'; +import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbEntityCreateOptionActionListModalData { + unique: UmbEntityUnique; + entityType: string; +} + +export type UmbEntityCreateOptionActionListModalValue = never; + +export const UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL = new UmbModalToken< + UmbEntityCreateOptionActionListModalData, + UmbEntityCreateOptionActionListModalValue +>(UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts new file mode 100644 index 0000000000..876d392b23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/index.ts @@ -0,0 +1,2 @@ +export * from './constants.js'; +export * from './entity-create-option-action-list-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts new file mode 100644 index 0000000000..2b6ee6ed47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/manifests.ts @@ -0,0 +1,10 @@ +import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS } from './constants.js'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL_ALIAS, + name: 'Entity Create Option Action List Modal', + element: () => import('./entity-create-option-action-list-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts new file mode 100644 index 0000000000..7d102e750a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/types.ts @@ -0,0 +1,16 @@ +import type { MetaEntityActionDefaultKind } from '../../default/index.js'; +import type { ManifestEntityAction } from '../../entity-action.extension.js'; + +export interface ManifestEntityActionCreateKind extends ManifestEntityAction { + type: 'entityAction'; + kind: 'create'; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface MetaEntityActionCreateKind extends MetaEntityActionDefaultKind {} + +declare global { + interface UmbExtensionManifestMap { + umbEntityActionCreateKind: ManifestEntityActionCreateKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts index 30877954f8..5a7c2ae86b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/index.ts @@ -1,2 +1,3 @@ -export * from './duplicate/index.js'; +export * from './create/index.js'; export * from './delete/index.js'; +export * from './duplicate/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index aeaaceafc0..7d6813e49a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,9 +1,12 @@ +import { manifests as createEntityActionManifests } from './common/create/manifests.js'; import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; + import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + ...createEntityActionManifests, ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts deleted file mode 100644 index a6da26da4f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/create-user-entity-action.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UMB_USER_CREATE_OPTIONS_MODAL } from './modal/index.js'; -import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; - -export class UmbCreateUserEntityAction extends UmbEntityActionBase { - override async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const modalContext = modalManager.open(this, UMB_USER_CREATE_OPTIONS_MODAL, { - data: { - parent: { - unique: this.args.unique, - entityType: this.args.entityType, - }, - }, - }); - - await modalContext.onSubmit(); - } -} - -export { UmbCreateUserEntityAction as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index 658fa547d3..2e67f026d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,26 +1,17 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { manifests as apiUser } from './api-user/manifests.js'; import { manifests as defaultUser } from './default-user/manifests.js'; -import { manifests as modalManifests } from './modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'entityAction', - kind: 'default', + kind: 'create', alias: 'Umb.EntityAction.User.Create', name: 'Create User Entity Action', - weight: 1200, - api: () => import('./create-user-entity-action.js'), forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], - meta: { - icon: 'icon-add', - label: '#actions_create', - additionalOptions: true, - }, }, ...apiUser, ...defaultUser, - ...modalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts deleted file mode 100644 index 778a1fe38d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -export const UMB_USER_CREATE_OPTIONS_MODAL = new UmbModalToken('Umb.Modal.User.CreateOptions', { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts deleted file mode 100644 index 08dc77d154..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const manifests: Array = [ - { - type: 'modal', - alias: 'Umb.Modal.User.CreateOptions', - name: 'User Create Options Modal', - element: () => import('./user-create-options-modal.element.js'), - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts deleted file mode 100644 index cc9ba965f2..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; - -const elementName = 'umb-user-create-options-modal'; -@customElement(elementName) -export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { - @state() - entity: UmbEntityModel = { - entityType: '', - unique: '', - }; - - constructor() { - super(); - - this.consumeContext(UMB_ENTITY_CONTEXT, (context) => { - this.entity = { - entityType: context.getEntityType(), - unique: context.getUnique(), - }; - }); - } - - override render() { - return html` - - - - - - - `; - } -} - -export { UmbUserCreateOptionsModalElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbUserCreateOptionsModalElement; - } -} From 0664c6e5cad6f8ea41690e901a5b0f86b3eb5873 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 13:18:14 +0100 Subject: [PATCH 215/246] restructure modules --- .../entity-create-option-action.element.ts | 0 .../create-option-action/default/index.ts | 0 .../create-option-action/default/manifests.ts | 0 .../create-option-action/default/types.ts | 0 .../entity-create-option-action-base.ts | 0 ...-create-option-action-element.interface.ts | 0 .../entity-create-option-action.extension.ts | 0 .../entity-create-option-action.interface.ts | 0 ...ntity-create-option-action-list.element.ts | 0 .../global-components/index.ts | 0 .../create}/create-option-action/index.ts | 0 .../create}/create-option-action/manifests.ts | 0 .../create}/create-option-action/types.ts | 0 .../common/create/create.action.ts | 39 +++++++++++++++++++ .../core/entity-action/common/create/index.ts | 1 + .../entity-action/common/create/manifests.ts | 3 +- .../packages/core/entity-action/manifests.ts | 2 - .../src/packages/core/entity/index.ts | 1 - .../src/packages/core/entity/manifests.ts | 4 -- .../src/packages/core/manifests.ts | 2 - .../api-user-entity-create-option-action.ts | 2 +- ...efault-user-entity-create-option-action.ts | 8 ++-- 22 files changed, 48 insertions(+), 14 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/entity-create-option-action.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/default/types.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action-base.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action-element.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action.extension.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/entity-create-option-action.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/global-components/entity-create-option-action-list.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/global-components/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity => entity-action/common/create}/create-option-action/types.ts (100%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/entity-create-option-action.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/default/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-base.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action-element.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.extension.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/entity-create-option-action.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/entity-create-option-action-list.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/global-components/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity/create-option-action/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index 35f0dda58a..d96860c9b9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -1,10 +1,49 @@ import { UmbEntityActionBase } from '../../entity-action-base.js'; +import type { UmbEntityActionArgs } from '../../types.js'; import type { MetaEntityActionCreateKind } from './types.js'; import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; +import type { ManifestEntityCreateOptionAction } from './create-option-action/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { createExtensionApi, UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; export class UmbCreateEntityAction extends UmbEntityActionBase { + #hasSingleOption = true; + #singleActionOptionManifest?: ManifestEntityCreateOptionAction; + + constructor(host: UmbControllerHost, args: UmbEntityActionArgs) { + super(host, args); + + new UmbExtensionsManifestInitializer( + this, + umbExtensionsRegistry, + 'entityCreateOptionAction', + (ext) => ext.forEntityTypes.includes(this.args.entityType), + async (actionOptions) => { + this.#hasSingleOption = actionOptions.length === 1; + this.#singleActionOptionManifest = this.#hasSingleOption + ? (actionOptions[0].manifest as ManifestEntityCreateOptionAction) + : undefined; + }, + 'umbEntityActionsObserver', + ); + } + override async execute() { + if (this.#hasSingleOption) { + if (!this.#singleActionOptionManifest) throw new Error('No first action manifest found'); + + const api = await createExtensionApi(this, this.#singleActionOptionManifest, [ + { unique: this.args.unique, entityType: this.args.entityType, meta: this.#singleActionOptionManifest.meta }, + ]); + + if (!api) throw new Error(`Could not create api for ${this.#singleActionOptionManifest.alias}`); + + await api.execute(); + return; + } + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const modalContext = modalManager.open(this, UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL, { data: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts index d44c5eca74..e3989cd62d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -1 +1,2 @@ export { UmbCreateEntityAction } from './create.action.js'; +export * from './create-option-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts index d1e496f559..6aee3f93b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts @@ -1,4 +1,5 @@ import { manifest as createKindManifest } from './create.action.kind.js'; import { manifests as modalManifests } from './modal/manifests.js'; +import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; -export const manifests = [createKindManifest, ...modalManifests]; +export const manifests = [createKindManifest, ...modalManifests, ...createOptionActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index 7d6813e49a..2f9fa9adc4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,4 +1,3 @@ -import { manifests as createEntityActionManifests } from './common/create/manifests.js'; import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; @@ -6,7 +5,6 @@ import { manifests as duplicateEntityActionManifests } from './common/duplicate/ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ - ...createEntityActionManifests, ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index 7c1422a9ad..737d7bf482 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,4 +1,3 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; -export * from './create-option-action/index.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts deleted file mode 100644 index 3a24422566..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/manifests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [...createOptionActionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index d01847d9d0..807e23de70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -7,7 +7,6 @@ import { manifests as cultureManifests } from './culture/manifests.js'; import { manifests as debugManifests } from './debug/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-action/manifests.js'; -import { manifests as entityManifests } from './entity/manifests.js'; import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; @@ -37,7 +36,6 @@ export const manifests: Array = ...debugManifests, ...entityActionManifests, ...entityBulkActionManifests, - ...entityManifests, ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts index 62404d353f..e0c48579b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -1,4 +1,4 @@ -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-action'; export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { override async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts index e661e70363..7da007dc51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -2,8 +2,10 @@ import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal. import type { UmbUserKindType } from '../../../utils/index.js'; import { UmbUserKind } from '../../../utils/index.js'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { + UmbEntityCreateOptionActionBase, + UmbRequestReloadChildrenOfEntityEvent, +} from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { @@ -19,7 +21,7 @@ export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptio }, }); - modalContext + await modalContext ?.onSubmit() .then(() => { this.#requestReloadChildrenOfEntity(); From 811951b8b671befcf633e10e1b9bb3eedd844dd3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 13:25:39 +0100 Subject: [PATCH 216/246] import after restructure --- .../entity-create-option-action.extension.ts | 3 ++- .../src/packages/core/entity-action/manifests.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts index 2835753767..9aff339da4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts @@ -1,8 +1,9 @@ +import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, -> extends ManifestElementAndApi, +> extends ManifestElementAndApi>, ManifestWithDynamicConditions { type: 'entityCreateOptionAction'; forEntityTypes: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts index 2f9fa9adc4..7d6813e49a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/manifests.ts @@ -1,3 +1,4 @@ +import { manifests as createEntityActionManifests } from './common/create/manifests.js'; import { manifests as defaultEntityActionManifests } from './default/manifests.js'; import { manifests as deleteEntityActionManifests } from './common/delete/manifests.js'; import { manifests as duplicateEntityActionManifests } from './common/duplicate/manifests.js'; @@ -5,6 +6,7 @@ import { manifests as duplicateEntityActionManifests } from './common/duplicate/ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + ...createEntityActionManifests, ...defaultEntityActionManifests, ...deleteEntityActionManifests, ...duplicateEntityActionManifests, From 6acdda0385c4cfabf852b5b992dd58869d581b2b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 17:03:27 +0100 Subject: [PATCH 217/246] render create options --- .../create-user-collection-action.element.ts | 127 +++++++++--------- 1 file changed, 65 insertions(+), 62 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 4ffcc353d0..6ddc1b57cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -1,13 +1,7 @@ -import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; -import type { UmbUserKindType } from '../../utils/index.js'; -import { UmbUserKind } from '../../utils/index.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; const elementName = 'umb-create-user-collection-action-button'; @customElement(elementName) @@ -15,83 +9,92 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { @state() private _popoverOpen = false; - async #onClick(event: Event, kind: UmbUserKindType) { - event.stopPropagation(); - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + @state() + private _multipleOptions = false; - const unique = entityContext.getUnique(); - const entityType = entityContext.getEntityType(); + #apiControllers: Array = []; + #createLabel = this.localize.term('general_create'); - if (unique === undefined) throw new Error('Missing unique'); - if (!entityType) throw new Error('Missing entityType'); - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { - data: { - user: { - kind, - }, - }, - }); - - modalContext - ?.onSubmit() - .then(() => { - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }) - .catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - this.#requestReloadChildrenOfEntity({ entityType, unique }); - }); - } - - async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType, - unique, - }); - - eventContext.dispatchEvent(event); - } - - #onPopoverToggle(event: ToggleEvent) { + #onPopoverToggle(event: PointerEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this._popoverOpen = event.newState === 'open'; } - override render() { - const label = this.localize.term('general_create'); + async #onClick(event: Event, controller: any) { + event.stopPropagation(); + await controller.api.execute(); + } + constructor() { + super(); + + new UmbExtensionsApiInitializer( + this, + umbExtensionsRegistry, + 'entityCreateOptionAction', + [], + undefined, + (controllers) => { + this.#apiControllers = controllers; + this._multipleOptions = controllers.length > 1; + }, + ); + } + + override render() { + return this._multipleOptions ? this.#renderMultiOptionAction() : this.#renderSingleOptionAction(); + } + + #renderSingleOptionAction() { + return html` this.#onClick(event, this.#apiControllers[0])}>`; + } + + #renderMultiOptionAction() { return html` - - ${label} + + ${this.#createLabel} + ${this.#renderDropdown()} + `; + } + + #renderDropdown() { + return html` - this.#onClick(event, UmbUserKind.DEFAULT)}> - - - this.#onClick(event, UmbUserKind.API)}> - - + ${this.#apiControllers.map((controller) => this.#renderMenuItem(controller))} `; } + + #renderMenuItem(controller: any) { + const label = controller.manifest.meta.label + ? this.localize.string(controller.manifest.meta.label) + : controller.manifest.meta.name; + + return html` + this.#onClick(event, controller)}> + + + `; + } } export { UmbCollectionActionButtonElement as element }; From bafd508fd734dcda5347ce5180fa2bd57e8fb9d8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:11:03 +0100 Subject: [PATCH 218/246] rename button --- .../action/create-user-collection-action.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts index 6ddc1b57cc..41c36a27d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts @@ -3,9 +3,9 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -const elementName = 'umb-create-user-collection-action-button'; +const elementName = 'umb-collection-create-action-button'; @customElement(elementName) -export class UmbCollectionActionButtonElement extends UmbLitElement { +export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @state() private _popoverOpen = false; @@ -97,10 +97,10 @@ export class UmbCollectionActionButtonElement extends UmbLitElement { } } -export { UmbCollectionActionButtonElement as element }; +export { UmbCollectionCreateActionButtonElement as element }; declare global { interface HTMLElementTagNameMap { - [elementName]: UmbCollectionActionButtonElement; + [elementName]: UmbCollectionCreateActionButtonElement; } } From c7aaab7261292fb7f62c03751251fdf0a5c40b98 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:13:17 +0100 Subject: [PATCH 219/246] rename file --- ...on-action.element.ts => collection-create-action.element.ts} | 0 .../src/packages/user/user/collection/action/manifests.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/{create-user-collection-action.element.ts => collection-create-action.element.ts} (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/create-user-collection-action.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts index 70aa992311..d2228e9b1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts @@ -5,7 +5,7 @@ export const manifests: Array = [ type: 'collectionAction', name: 'Create User Collection Action', alias: 'Umb.CollectionAction.User.Create', - element: () => import('./create-user-collection-action.element.js'), + element: () => import('./collection-create-action.element.js'), weight: 200, conditions: [ { From 69958b4370123706ab3897ba6a31981c2642abd9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:14:36 +0100 Subject: [PATCH 220/246] use constants --- .../src/packages/user/user/collection/action/manifests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts index d2228e9b1b..640a712e12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_USER_COLLECTION_ALIAS } from '../constants.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; export const manifests: Array = [ @@ -10,7 +11,7 @@ export const manifests: Array = [ conditions: [ { alias: UMB_COLLECTION_ALIAS_CONDITION, - match: 'Umb.Collection.User', + match: UMB_USER_COLLECTION_ALIAS, }, ], }, From 340dff742cd170996bad85509ccd8bb7377a6ab5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 19:24:41 +0100 Subject: [PATCH 221/246] remove element from create action option manifest --- .../entity-create-option-action.element.ts | 87 ------------------- .../create-option-action/default/index.ts | 1 - .../create-option-action/default/manifests.ts | 20 ----- .../create-option-action/default/types.ts | 44 ---------- ...-create-option-action-element.interface.ts | 4 - .../entity-create-option-action.extension.ts | 4 +- .../create/create-option-action/index.ts | 5 -- .../create/create-option-action/manifests.ts | 4 - .../common/create/create.action.ts | 2 +- .../entity-action/common/create/manifests.ts | 3 +- 10 files changed, 4 insertions(+), 170 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts deleted file mode 100644 index 5c926bbe3e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/entity-create-option-action.element.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { UmbEntityCreateOptionAction } from '../entity-create-option-action.interface.js'; -import type { UmbEntityCreateOptionActionElement } from '../entity-create-option-action-element.interface.js'; -import type { ManifestEntityCreateOptionAction } from '../entity-create-option-action.extension.js'; -import type { MetaEntityCreateOptionActionDefaultKind } from './types.js'; -import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event'; -import { html, nothing, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; - -const elementName = 'umb-entity-create-option-action'; -@customElement(elementName) -export class UmbEntityCreateOptionActionDefaultElement< - MetaType extends MetaEntityCreateOptionActionDefaultKind = MetaEntityCreateOptionActionDefaultKind, - ApiType extends UmbEntityCreateOptionAction = UmbEntityCreateOptionAction, - > - extends UmbLitElement - implements UmbEntityCreateOptionActionElement -{ - #api?: ApiType; - - // TODO: Do these need to be properties? [NL] - @property({ type: String }) - entityType?: string | null; - - // TODO: Do these need to be properties? [NL] - @property({ type: String }) - public unique?: string | null; - - @property({ attribute: false }) - public manifest?: ManifestEntityCreateOptionAction; - - public set api(api: ApiType | undefined) { - this.#api = api; - - // TODO: Fix so when we use a HREF it does not refresh the page? - this.#api?.getHref?.().then((href) => { - this._href = href; - // TODO: Do we need to update the component here? [NL] - }); - } - - @state() - _href?: string; - - override async focus() { - await this.updateComplete; - this.shadowRoot?.querySelector('uui-menu-item')?.focus(); - } - - async #onClickLabel(event: UUIMenuItemEvent) { - if (!this._href) { - event.stopPropagation(); - await this.#api?.execute(); - } - this.dispatchEvent(new UmbActionExecutedEvent()); - } - - // TODO: we need to stop the regular click event from bubbling up to the table so it doesn't select the row. - // This should probably be handled in the UUI Menu item component. so we don't dispatch a label-click event and click event at the same time. - #onClick(event: PointerEvent) { - event.stopPropagation(); - } - - override render() { - const label = this.manifest?.meta.label ? this.localize.string(this.manifest.meta.label) : this.manifest?.name; - - return html` - - ${this.manifest?.meta.icon - ? html`` - : nothing} - - `; - } -} - -export { UmbEntityCreateOptionActionDefaultElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbEntityCreateOptionActionDefaultElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts deleted file mode 100644 index d4702960d5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts deleted file mode 100644 index b1b7de24bf..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'kind', - alias: 'Umb.Kind.EntityCreateOptionAction.Default', - matchKind: 'default', - matchType: 'entityCreateOptionAction', - manifest: { - type: 'entityCreateOptionAction', - kind: 'default', - weight: 1000, - element: () => import('./entity-create-option-action.element.js'), - meta: { - icon: '', - label: 'Default Entity Create Option Action', - }, - }, - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts deleted file mode 100644 index 465664c91c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { - ManifestEntityCreateOptionAction, - MetaEntityCreateOptionAction, -} from '../entity-create-option-action.extension.js'; - -export interface ManifestEntityCreateOptionActionDefaultKind - extends ManifestEntityCreateOptionAction { - type: 'entityCreateOptionAction'; - kind: 'default'; -} - -export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { - /** - * An icon to represent the action to be performed - * @examples [ - * "icon-box", - * "icon-grid" - * ] - */ - icon: string; - - /** - * The friendly name of the action to perform - * @examples [ - * "Create", - * "Create Content Template" - * ] - */ - label: string; - - /** - * The action requires additional input from the user. - * A dialog will prompt the user for more information or to make a choice. - * @type {boolean} - * @memberof MetaEntityCreateOptionActionDefaultKind - */ - additionalOptions?: boolean; -} - -declare global { - interface UmbExtensionManifestMap { - umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts deleted file mode 100644 index 6f2c9ab833..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-element.interface.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; - -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbEntityCreateOptionActionElement extends UmbControllerHostElement {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts index 9aff339da4..37341069c2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts @@ -1,9 +1,9 @@ import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; -import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; +import type { ManifestApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, -> extends ManifestElementAndApi>, +> extends ManifestApi>, ManifestWithDynamicConditions { type: 'entityCreateOptionAction'; forEntityTypes: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts index 5eb9c9635d..f14590182c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts @@ -1,12 +1,7 @@ import './global-components/index.js'; -export * from './default/index.js'; export * from './global-components/index.js'; - export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; - -export type * from './entity-create-option-action-element.interface.js'; - export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts deleted file mode 100644 index 43d020c74e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { manifests as defaultManifests } from './default/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [...defaultManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index d96860c9b9..a912365d80 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -23,7 +23,7 @@ export class UmbCreateEntityAction extends UmbEntityActionBase { this.#hasSingleOption = actionOptions.length === 1; this.#singleActionOptionManifest = this.#hasSingleOption - ? (actionOptions[0].manifest as ManifestEntityCreateOptionAction) + ? (actionOptions[0].manifest as unknown as ManifestEntityCreateOptionAction) : undefined; }, 'umbEntityActionsObserver', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts index 6aee3f93b6..d1e496f559 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/manifests.ts @@ -1,5 +1,4 @@ import { manifest as createKindManifest } from './create.action.kind.js'; import { manifests as modalManifests } from './modal/manifests.js'; -import { manifests as createOptionActionManifests } from './create-option-action/manifests.js'; -export const manifests = [createKindManifest, ...modalManifests, ...createOptionActionManifests]; +export const manifests = [createKindManifest, ...modalManifests]; From 38dc028d5ac2889a46072d426a36034bc5050825 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 20:00:45 +0100 Subject: [PATCH 222/246] render as ref item --- ...ntity-create-option-action-list.element.ts | 109 ------------------ .../global-components/index.ts | 3 - .../create/create-option-action/index.ts | 3 - ...create-option-action-list-modal.element.ts | 50 +++++++- .../collection-create-action.element.ts | 10 +- 5 files changed, 52 insertions(+), 123 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts deleted file mode 100644 index eeb948c5d3..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/entity-create-option-action-list.element.ts +++ /dev/null @@ -1,109 +0,0 @@ -import type { UmbEntityCreateOptionActionArgs } from '../types.js'; -import type { - ManifestEntityCreateOptionAction, - MetaEntityCreateOptionAction, -} from '../entity-create-option-action.extension.js'; -import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; -import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbApiConstructorArgumentsMethodType } from '@umbraco-cms/backoffice/extension-api'; - -const elementName = 'umb-entity-create-option-action-list'; -@customElement(elementName) -export class UmbEntityCreateOptionActionListElement extends UmbLitElement { - @property({ type: String, attribute: 'entity-type' }) - public get entityType(): string | undefined { - return this._props.entityType; - } - public set entityType(value: string | undefined) { - if (value === undefined || value === this._props.entityType) return; - this._props.entityType = value; - this.#generateApiArgs(); - this.requestUpdate('_props'); - // Update filter: - //const oldValue = this._filter; - this._filter = (extension: ManifestEntityCreateOptionAction) => - extension.forEntityTypes.includes(value); - //this.requestUpdate('_filter', oldValue); - } - - @state() - _filter?: (extension: ManifestEntityCreateOptionAction) => boolean; - - @property({ type: String }) - public get unique(): string | null | undefined { - return this._props.unique; - } - public set unique(value: string | null | undefined) { - if (value === this._props.unique) return; - this._props.unique = value; - this.#generateApiArgs(); - this.requestUpdate('_props'); - } - - @state() - _props: Partial> = {}; - - @state() - _apiArgs?: UmbApiConstructorArgumentsMethodType< - ManifestEntityCreateOptionAction, - [UmbEntityCreateOptionActionArgs] - >; - - #entityContext = new UmbEntityContext(this); - #extensionType = 'entityCreateOptionAction'; - - #generateApiArgs() { - if (!this._props.entityType || this._props.unique === undefined) return; - - this.#entityContext.setEntityType(this._props.entityType); - this.#entityContext.setUnique(this._props.unique); - this.#hasRenderedOnce = false; - - this._apiArgs = (manifest: ManifestEntityCreateOptionAction) => { - return [{ entityType: this._props.entityType!, unique: this._props.unique!, meta: manifest.meta }]; - }; - } - - #hasRenderedOnce?: boolean; - override render() { - return this._filter - ? html` - { - if (!this.#hasRenderedOnce && i === 0) { - // TODO: Replace this block: - ext.component?.updateComplete.then(async () => { - const menuitem = ext.component?.shadowRoot?.querySelector('uui-menu-item'); - menuitem?.updateComplete.then(async () => { - menuitem?.shadowRoot?.querySelector('#label-button')?.focus?.(); - }); - }); - // end of block, with this, when this PR is part of UI Lib: https://github.com/umbraco/Umbraco.UI/pull/789 - // ext.component?.focus(); - this.#hasRenderedOnce = true; - } - return ext.component; - }}> - ` - : ''; - } - - static override styles = [ - css` - :host { - --uui-menu-item-flat-structure: 1; - } - `, - ]; -} - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbEntityCreateOptionActionListElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts deleted file mode 100644 index 40da9cdab0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/global-components/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import './entity-create-option-action-list.element.js'; - -export * from './entity-create-option-action-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts index f14590182c..1794649010 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts @@ -1,6 +1,3 @@ -import './global-components/index.js'; - -export * from './global-components/index.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index e9ada04e69..f3ac6ad2a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -2,7 +2,9 @@ import type { UmbEntityCreateOptionActionListModalData, UmbEntityCreateOptionActionListModalValue, } from './entity-create-option-action-list-modal.token.js'; -import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; const elementName = 'umb-entity-create-option-action-list-modal'; @@ -11,13 +13,40 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle UmbEntityCreateOptionActionListModalData, UmbEntityCreateOptionActionListModalValue > { + @state() + private _apiControllers: Array = []; + + constructor() { + super(); + + new UmbExtensionsApiInitializer( + this, + umbExtensionsRegistry, + 'entityCreateOptionAction', + [], + undefined, + (controllers) => { + this._apiControllers = controllers; + }, + ); + } + + async #onClick(event: Event, controller: any) { + event.stopPropagation(); + await controller.api.execute(); + } + override render() { return html` - + + ${repeat( + this._apiControllers, + (controller) => controller.manifest.alias, + (controller) => this.#renderRefItem(controller), + )} + `; } + + #renderRefItem(controller: any) { + const manifest = controller.manifest; + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; + + return html` + this.#onClick(event, controller)}> + `; + } } export { UmbEntityCreateOptionActionListModalElement as element }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts index 41c36a27d1..90805b018e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts @@ -12,7 +12,9 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @state() private _multipleOptions = false; - #apiControllers: Array = []; + @state() + private _apiControllers: Array = []; + #createLabel = this.localize.term('general_create'); #onPopoverToggle(event: PointerEvent) { @@ -37,7 +39,7 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { [], undefined, (controllers) => { - this.#apiControllers = controllers; + this._apiControllers = controllers; this._multipleOptions = controllers.length > 1; }, ); @@ -52,7 +54,7 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { label=${this.#createLabel} color="default" look="outline" - @click=${(event: Event) => this.#onClick(event, this.#apiControllers[0])}>`; + @click=${(event: Event) => this.#onClick(event, this._apiControllers[0])}>`; } #renderMultiOptionAction() { @@ -77,7 +79,7 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - ${this.#apiControllers.map((controller) => this.#renderMenuItem(controller))} + ${this._apiControllers.map((controller) => this.#renderMenuItem(controller))} From db65391d3a84e639f67fc4cabc49bc007cdd13e4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 20:03:02 +0100 Subject: [PATCH 223/246] render icon from manifest --- .../collection/action/collection-create-action.element.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts index 90805b018e..f0a2d88b95 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts @@ -87,13 +87,12 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { } #renderMenuItem(controller: any) { - const label = controller.manifest.meta.label - ? this.localize.string(controller.manifest.meta.label) - : controller.manifest.meta.name; + const manifest = controller.manifest; + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; return html` this.#onClick(event, controller)}> - + `; } From 170a813010ac6c6b0d3557d3a6eb16990e9fe8b8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 Oct 2024 22:02:22 +0100 Subject: [PATCH 224/246] add default kind --- .../create-option-action/default/index.ts | 1 + .../create-option-action/default/manifests.ts | 18 +++++++ .../create-option-action/default/types.ts | 52 +++++++++++++++++++ .../create/create-option-action/index.ts | 1 + .../create/create-option-action/manifests.ts | 3 ++ 5 files changed, 75 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts new file mode 100644 index 0000000000..d4702960d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts @@ -0,0 +1 @@ +export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts new file mode 100644 index 0000000000..1aa548f357 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts @@ -0,0 +1,18 @@ +export const manifests = [ + { + type: 'kind', + alias: 'Umb.Kind.EntityCreateOptionAction.Default', + matchKind: 'default', + matchType: 'entityCreateOptionAction', + manifest: { + type: 'entityCreateOptionAction', + kind: 'default', + weight: 1000, + meta: { + icon: '', + label: 'Fill out label', + description: 'Fill out description', + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts new file mode 100644 index 0000000000..f131c65468 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts @@ -0,0 +1,52 @@ +import type { + ManifestEntityCreateOptionAction, + MetaEntityCreateOptionAction, +} from '../entity-create-option-action.extension.js'; + +export interface ManifestEntityCreateOptionActionDefaultKind + extends ManifestEntityCreateOptionAction { + type: 'entityCreateOptionAction'; + kind: 'default'; +} + +export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { + /** + * An icon to represent the action to be performed + * @examples [ + * "icon-box", + * "icon-grid" + * ] + */ + icon: string; + + /** + * The friendly name of the action to perform + * @examples [ + * "Create with Template", + * "Create from Blueprint" + * ] + */ + label: string; + + /** + * A description of the action to be performed + * @examples [ + * "Create a document type with a template", + * "Create a document from a blueprint" + * ] + */ + description: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + */ + additionalOptions?: boolean; +} + +declare global { + interface UmbExtensionManifestMap { + umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts index 1794649010..3134f695a1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts @@ -1,3 +1,4 @@ +export * from './default/index.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts new file mode 100644 index 0000000000..a61fc1b883 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts @@ -0,0 +1,3 @@ +import { manifests as defaultManifests } from './default/manifests.js'; + +export const manifests = [...defaultManifests]; From 9b99fbc3621753ad6a031533cda2c2ca3cd45d5f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 Oct 2024 19:02:53 +0100 Subject: [PATCH 225/246] add module --- src/Umbraco.Web.UI.Client/package.json | 1 + .../packages/core/entity-action/common/create/create.action.ts | 2 +- .../src/packages/core/entity-action/common/create/index.ts | 2 +- .../default/index.ts | 0 .../default/manifests.ts | 0 .../default/types.ts | 0 .../entity-create-option-action-base.ts | 0 .../entity-create-option-action.extension.ts | 0 .../entity-create-option-action.interface.ts | 0 .../index.ts | 0 .../manifests.ts | 0 .../types.ts | 0 src/Umbraco.Web.UI.Client/tsconfig.json | 3 +++ 13 files changed, 6 insertions(+), 2 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/default/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/default/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/default/types.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/entity-create-option-action-base.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/entity-create-option-action.extension.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/entity-create-option-action.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{entity-action/common/create/create-option-action => entity-create-option-action}/types.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 0242e359b1..168c6ae73d 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -41,6 +41,7 @@ "./document": "./dist-cms/packages/documents/documents/index.js", "./entity-action": "./dist-cms/packages/core/entity-action/index.js", "./entity-bulk-action": "./dist-cms/packages/core/entity-bulk-action/index.js", + "./entity-create-option-action": "./dist-cms/packages/core/entity-create-option-action/index.js", "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index a912365d80..e92c8813d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -2,7 +2,7 @@ import { UmbEntityActionBase } from '../../entity-action-base.js'; import type { UmbEntityActionArgs } from '../../types.js'; import type { MetaEntityActionCreateKind } from './types.js'; import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; -import type { ManifestEntityCreateOptionAction } from './create-option-action/index.js'; +import type { ManifestEntityCreateOptionAction } from '../../../entity-create-option-action/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts index e3989cd62d..3a3fdc0b1b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -1,2 +1,2 @@ export { UmbCreateEntityAction } from './create.action.js'; -export * from './create-option-action/index.js'; +export * from '../../../entity-create-option-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/default/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action-base.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.extension.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/entity-create-option-action.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create-option-action/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/types.ts diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index 40f18ca7ce..3fc4bfabed 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -68,6 +68,9 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/document": ["./src/packages/documents/documents/index.ts"], "@umbraco-cms/backoffice/entity-action": ["./src/packages/core/entity-action/index.ts"], "@umbraco-cms/backoffice/entity-bulk-action": ["./src/packages/core/entity-bulk-action/index.ts"], + "@umbraco-cms/backoffice/entity-create-option-action": [ + "./src/packages/core/entity-create-option-action/index.ts" + ], "@umbraco-cms/backoffice/entity": ["./src/packages/core/entity/index.ts"], "@umbraco-cms/backoffice/event": ["./src/packages/core/event/index.ts"], "@umbraco-cms/backoffice/extension-registry": ["./src/packages/core/extension-registry/index.ts"], From 11198d247026d0c6d5bcc890bd16da1a3e814350 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 13:03:22 +0100 Subject: [PATCH 226/246] remove default kind and require in on the base --- .../common/create/create.action.ts | 2 +- .../core/entity-action/common/create/index.ts | 1 - ...create-option-action-list-modal.element.ts | 44 ++++++++++++---- .../default/index.ts | 1 - .../default/manifests.ts | 18 ------- .../default/types.ts | 52 ------------------- .../entity-create-option-action-base.ts | 5 +- .../entity-create-option-action.extension.ts | 44 +++++++++++++++- .../entity-create-option-action.interface.ts | 6 ++- .../core/entity-create-option-action/index.ts | 1 - .../entity-create-option-action/manifests.ts | 3 -- .../api-user-entity-create-option-action.ts | 2 +- .../create/api-user/manifests.ts | 1 - ...efault-user-entity-create-option-action.ts | 8 ++- .../create/default-user/manifests.ts | 1 - 15 files changed, 90 insertions(+), 99 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts index e92c8813d4..e341354768 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/create.action.ts @@ -2,11 +2,11 @@ import { UmbEntityActionBase } from '../../entity-action-base.js'; import type { UmbEntityActionArgs } from '../../types.js'; import type { MetaEntityActionCreateKind } from './types.js'; import { UMB_ENTITY_CREATE_OPTION_ACTION_LIST_MODAL } from './modal/index.js'; -import type { ManifestEntityCreateOptionAction } from '../../../entity-create-option-action/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { createExtensionApi, UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; +import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action'; export class UmbCreateEntityAction extends UmbEntityActionBase { #hasSingleOption = true; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts index 3a3fdc0b1b..d44c5eca74 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/index.ts @@ -1,2 +1 @@ export { UmbCreateEntityAction } from './create.action.js'; -export * from '../../../entity-create-option-action/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index f3ac6ad2a8..a261169e90 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -2,11 +2,15 @@ import type { UmbEntityCreateOptionActionListModalData, UmbEntityCreateOptionActionListModalValue, } from './entity-create-option-action-list-modal.token.js'; +import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action'; +import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +type ManifestType = ManifestEntityCreateOptionAction; + const elementName = 'umb-entity-create-option-action-list-modal'; @customElement(elementName) export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseElement< @@ -14,7 +18,9 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle UmbEntityCreateOptionActionListModalValue > { @state() - private _apiControllers: Array = []; + private _apiControllers: Array> = []; + + #hrefMap = new Map(); constructor() { super(); @@ -26,13 +32,29 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle [], undefined, (controllers) => { - this._apiControllers = controllers; + this._apiControllers = controllers as unknown as Array>; + + this._apiControllers.forEach((controller) => { + controller.api?.getHref().then((href) => { + const alias = controller.manifest?.alias; + if (!alias) throw new Error('No alias found'); + // only apply to map if href is defined + if (href) { + this.#hrefMap.set(alias, href); + } + }); + }); }, ); } - async #onClick(event: Event, controller: any) { + async #onClick(event: Event, controller: UmbExtensionApiInitializer) { event.stopPropagation(); + + if (!controller.api) throw new Error('No api found'); + + const href = this.#hrefMap.get(controller.manifest?.alias); + await controller.api.execute(); } @@ -43,7 +65,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle ${repeat( this._apiControllers, - (controller) => controller.manifest.alias, + (controller) => controller.manifest?.alias, (controller) => this.#renderRefItem(controller), )} @@ -56,16 +78,20 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle `; } - #renderRefItem(controller: any) { + #renderRefItem(controller: UmbExtensionApiInitializer) { const manifest = controller.manifest; - const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; + if (!manifest) throw new Error('No manifest found'); + + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; + const href = this.#hrefMap.get(manifest.alias); return html` this.#onClick(event, controller)}> + @click=${(event: Event) => this.#onClick(event, controller)} + .href=${href}> `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts deleted file mode 100644 index d4702960d5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts deleted file mode 100644 index 1aa548f357..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/manifests.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const manifests = [ - { - type: 'kind', - alias: 'Umb.Kind.EntityCreateOptionAction.Default', - matchKind: 'default', - matchType: 'entityCreateOptionAction', - manifest: { - type: 'entityCreateOptionAction', - kind: 'default', - weight: 1000, - meta: { - icon: '', - label: 'Fill out label', - description: 'Fill out description', - }, - }, - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts deleted file mode 100644 index f131c65468..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/default/types.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { - ManifestEntityCreateOptionAction, - MetaEntityCreateOptionAction, -} from '../entity-create-option-action.extension.js'; - -export interface ManifestEntityCreateOptionActionDefaultKind - extends ManifestEntityCreateOptionAction { - type: 'entityCreateOptionAction'; - kind: 'default'; -} - -export interface MetaEntityCreateOptionActionDefaultKind extends MetaEntityCreateOptionAction { - /** - * An icon to represent the action to be performed - * @examples [ - * "icon-box", - * "icon-grid" - * ] - */ - icon: string; - - /** - * The friendly name of the action to perform - * @examples [ - * "Create with Template", - * "Create from Blueprint" - * ] - */ - label: string; - - /** - * A description of the action to be performed - * @examples [ - * "Create a document type with a template", - * "Create a document from a blueprint" - * ] - */ - description: string; - - /** - * The action requires additional input from the user. - * A dialog will prompt the user for more information or to make a choice. - * @type {boolean} - */ - additionalOptions?: boolean; -} - -declare global { - interface UmbExtensionManifestMap { - umbDefaultEntityCreateOptionActionKind: ManifestEntityCreateOptionActionDefaultKind; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts index c8daf62492..2800261185 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts @@ -1,8 +1,11 @@ import type { UmbEntityCreateOptionActionArgs } from './types.js'; import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; +import type { MetaEntityCreateOptionAction } from './entity-create-option-action.extension.js'; import { UmbActionBase } from '@umbraco-cms/backoffice/action'; -export abstract class UmbEntityCreateOptionActionBase +export abstract class UmbEntityCreateOptionActionBase< + ArgsMetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, + > extends UmbActionBase> implements UmbEntityCreateOptionAction { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts index 37341069c2..cce0b9a4f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts @@ -3,7 +3,7 @@ import type { ManifestApi, ManifestWithDynamicConditions } from '@umbraco-cms/ba export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, -> extends ManifestApi>, +> extends ManifestApi>, ManifestWithDynamicConditions { type: 'entityCreateOptionAction'; forEntityTypes: Array; @@ -11,4 +11,44 @@ export interface ManifestEntityCreateOptionAction< } // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface MetaEntityCreateOptionAction {} +export interface MetaEntityCreateOptionAction { + /** + * An icon to represent the action to be performed + * @examples [ + * "icon-box", + * "icon-grid" + * ] + */ + icon: string; + + /** + * The friendly name of the action to perform + * @examples [ + * "Create with Template", + * "Create from Blueprint" + * ] + */ + label: string; + + /** + * A description of the action to be performed + * @examples [ + * "Create a document type with a template", + * "Create a document from a blueprint" + * ] + */ + description?: string; + + /** + * The action requires additional input from the user. + * A dialog will prompt the user for more information or to make a choice. + * @type {boolean} + */ + additionalOptions?: boolean; +} + +declare global { + interface UmbExtensionManifestMap { + umbEntityCreateOptionAction: ManifestEntityCreateOptionAction; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts index 0956868cb7..141e9dd084 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.interface.ts @@ -1,8 +1,10 @@ +import type { MetaEntityCreateOptionAction } from './entity-create-option-action.extension.js'; import type { UmbEntityCreateOptionActionArgs } from './types.js'; import type { UmbAction } from '@umbraco-cms/backoffice/action'; -export interface UmbEntityCreateOptionAction - extends UmbAction> { +export interface UmbEntityCreateOptionAction< + ArgsMetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, +> extends UmbAction> { /** * The href location, the action will act as a link. * @returns {Promise} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index 3134f695a1..1794649010 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,4 +1,3 @@ -export * from './default/index.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts deleted file mode 100644 index a61fc1b883..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/manifests.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { manifests as defaultManifests } from './default/manifests.js'; - -export const manifests = [...defaultManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts index e0c48579b8..ebb5d4571a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -1,4 +1,4 @@ -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { override async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts index 5c5ea02ca8..8232d63fbc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/manifests.ts @@ -3,7 +3,6 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; export const manifests: Array = [ { type: 'entityCreateOptionAction', - kind: 'default', alias: 'Umb.EntityCreateOptionAction.User.Api', name: 'Api User Entity Create Option Action', weight: 1100, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts index 7da007dc51..3d67778126 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -1,14 +1,12 @@ import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; import type { UmbUserKindType } from '../../../utils/index.js'; import { UmbUserKind } from '../../../utils/index.js'; +import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { - UmbEntityCreateOptionActionBase, - UmbRequestReloadChildrenOfEntityEvent, -} from '@umbraco-cms/backoffice/entity-action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { +export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { override async execute() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); const kind: UmbUserKindType = UmbUserKind.DEFAULT; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts index 4e12d1e039..cccb602cfc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/manifests.ts @@ -3,7 +3,6 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; export const manifests: Array = [ { type: 'entityCreateOptionAction', - kind: 'default', alias: 'Umb.EntityCreateOptionAction.User.Default', name: 'Default User Entity Create Option Action', weight: 1200, From 6c9b17216906b1809099573fc1d9a4985a97b57b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 13:57:59 +0100 Subject: [PATCH 227/246] get ref for item --- ...create-option-action-list-modal.element.ts | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index a261169e90..1db65a8f85 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -20,7 +20,11 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() private _apiControllers: Array> = []; - #hrefMap = new Map(); + @state() + _hrefMap = new Map(); + + @state() + _hrefList: Array = []; constructor() { super(); @@ -31,19 +35,11 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle 'entityCreateOptionAction', [], undefined, - (controllers) => { + async (controllers) => { this._apiControllers = controllers as unknown as Array>; - this._apiControllers.forEach((controller) => { - controller.api?.getHref().then((href) => { - const alias = controller.manifest?.alias; - if (!alias) throw new Error('No alias found'); - // only apply to map if href is defined - if (href) { - this.#hrefMap.set(alias, href); - } - }); - }); + const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); + this._hrefList = await Promise.all(hrefPromises); }, ); } @@ -51,10 +47,15 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle async #onClick(event: Event, controller: UmbExtensionApiInitializer) { event.stopPropagation(); - if (!controller.api) throw new Error('No api found'); + if (!controller.manifest) throw new Error('No manifest found'); + const href = this._hrefMap.get(controller.manifest?.alias); - const href = this.#hrefMap.get(controller.manifest?.alias); + // skip if href is defined + if (href) { + return; + } + if (!controller.api) throw new Error('No API found'); await controller.api.execute(); } @@ -66,7 +67,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle ${repeat( this._apiControllers, (controller) => controller.manifest?.alias, - (controller) => this.#renderRefItem(controller), + (controller, index) => this.#renderRefItem(controller, index), )}
      @@ -78,12 +79,12 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle `; } - #renderRefItem(controller: UmbExtensionApiInitializer) { + #renderRefItem(controller: UmbExtensionApiInitializer, index: number) { const manifest = controller.manifest; if (!manifest) throw new Error('No manifest found'); const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; - const href = this.#hrefMap.get(manifest.alias); + const href = this._hrefList[index]; return html` this.#onClick(event, controller)} - .href=${href}> + href=${ifDefined(href)}> `; } } From 05ff09dbbfaab2b16bf222d57d4b43395901a940 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 14:20:56 +0100 Subject: [PATCH 228/246] switch between button and link state --- ...ity-create-option-action-list-modal.element.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 1db65a8f85..270bd46805 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -59,6 +59,14 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle await controller.api.execute(); } + #getTarget(href?: string) { + if (href && href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + override render() { return html` @@ -87,12 +95,15 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle const href = this._hrefList[index]; return html` - this.#onClick(event, controller)} - href=${ifDefined(href)}> + href=${ifDefined(href)} + target=${this.#getTarget(href)} + ?selectable=${!href} + ?readonly=${!href}>
      `; } } From f8a7a36bd313c194cc5ae85c10fb35b8d6f80f97 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 15:41:11 +0100 Subject: [PATCH 229/246] pass args to api --- ...create-option-action-list-modal.element.ts | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 270bd46805..2bdc224261 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -6,7 +6,7 @@ import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/e import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, repeat, ifDefined, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; type ManifestType = ManifestEntityCreateOptionAction; @@ -26,18 +26,29 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() _hrefList: Array = []; - constructor() { - super(); + @property({ attribute: false }) + public override set data(value: UmbEntityCreateOptionActionListModalData | undefined) { + super.data = value; + + if (value) { + this.#initApi(); + } + } + + #initApi() { + if (this._data?.entityType === undefined) throw new Error('No entityType found'); + if (this._data?.unique === undefined) throw new Error('No unique found'); new UmbExtensionsApiInitializer( this, umbExtensionsRegistry, 'entityCreateOptionAction', - [], + (manifest: ManifestType) => { + return [{ entityType: this._data!.entityType, unique: this._data!.unique, meta: manifest.meta }]; + }, undefined, async (controllers) => { this._apiControllers = controllers as unknown as Array>; - const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); this._hrefList = await Promise.all(hrefPromises); }, From 1a0fa44497de4ed44b791e7b343d5b7ff6f40618 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 18:44:05 +0100 Subject: [PATCH 230/246] null check + render correct icon --- ...create-option-action-list-modal.element.ts | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 2bdc224261..03360e282c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -6,7 +6,15 @@ import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/e import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state, repeat, ifDefined, property } from '@umbraco-cms/backoffice/external/lit'; +import { + html, + customElement, + state, + repeat, + ifDefined, + property, + type PropertyValues, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; type ManifestType = ManifestEntityCreateOptionAction; @@ -26,25 +34,27 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() _hrefList: Array = []; - @property({ attribute: false }) - public override set data(value: UmbEntityCreateOptionActionListModalData | undefined) { - super.data = value; + protected override updated(_changedProperties: PropertyValues): void { + super.updated(_changedProperties); - if (value) { + if (_changedProperties.has('data')) { this.#initApi(); } } #initApi() { - if (this._data?.entityType === undefined) throw new Error('No entityType found'); - if (this._data?.unique === undefined) throw new Error('No unique found'); + const data = this.data; + if (!data) throw new Error('No data found'); + + if (data.entityType === undefined) throw new Error('No entityType found'); + if (data.unique === undefined) throw new Error('No unique found'); new UmbExtensionsApiInitializer( this, umbExtensionsRegistry, 'entityCreateOptionAction', (manifest: ManifestType) => { - return [{ entityType: this._data!.entityType, unique: this._data!.unique, meta: manifest.meta }]; + return [{ entityType: data.entityType, unique: data.unique, meta: manifest.meta }]; }, undefined, async (controllers) => { @@ -109,12 +119,13 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle this.#onClick(event, controller)} href=${ifDefined(href)} target=${this.#getTarget(href)} ?selectable=${!href} - ?readonly=${!href}> + ?readonly=${!href}> + + `; } } From e2456ae6698855ce54f29a9e550d5d32be793406 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 Oct 2024 19:14:18 +0100 Subject: [PATCH 231/246] extract to base class --- .../api-user-entity-create-option-action.ts | 17 ++++-- ...efault-user-entity-create-option-action.ts | 49 ++++------------ .../user-entity-create-option-action-base.ts | 58 +++++++++++++++++++ 3 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts index ebb5d4571a..2fd165fed7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/api-user/api-user-entity-create-option-action.ts @@ -1,8 +1,17 @@ -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; +import { UmbUserEntityCreateOptionActionBase } from '../user-entity-create-option-action-base.js'; +import { UmbUserKind } from '../../../utils/index.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + MetaEntityCreateOptionAction, + UmbEntityCreateOptionActionArgs, +} from '@umbraco-cms/backoffice/entity-create-option-action'; -export class UmbApiUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { - override async execute() { - debugger; +export class UmbApiUserEntityCreateOptionAction extends UmbUserEntityCreateOptionActionBase { + constructor(host: UmbControllerHost, args: UmbEntityCreateOptionActionArgs) { + super(host, { + ...args, + kind: UmbUserKind.API, + }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts index 3d67778126..9c67384285 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/default-user/default-user-entity-create-option-action.ts @@ -1,44 +1,17 @@ -import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; -import type { UmbUserKindType } from '../../../utils/index.js'; import { UmbUserKind } from '../../../utils/index.js'; -import { UmbEntityCreateOptionActionBase } from '@umbraco-cms/backoffice/entity-create-option-action'; -import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UmbUserEntityCreateOptionActionBase } from '../user-entity-create-option-action-base.js'; +import type { + MetaEntityCreateOptionAction, + UmbEntityCreateOptionActionArgs, +} from '@umbraco-cms/backoffice/entity-create-option-action'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbDefaultUserEntityCreateOptionAction extends UmbEntityCreateOptionActionBase { - override async execute() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const kind: UmbUserKindType = UmbUserKind.DEFAULT; - - const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { - data: { - user: { - kind, - }, - }, +export class UmbDefaultUserEntityCreateOptionAction extends UmbUserEntityCreateOptionActionBase { + constructor(host: UmbControllerHost, args: UmbEntityCreateOptionActionArgs) { + super(host, { + ...args, + kind: UmbUserKind.DEFAULT, }); - - await modalContext - ?.onSubmit() - .then(() => { - this.#requestReloadChildrenOfEntity(); - }) - .catch(async () => { - // modal is closed after creation instead of navigating to the new user. - // We therefore need to reload the children of the entity - this.#requestReloadChildrenOfEntity(); - }); - } - - async #requestReloadChildrenOfEntity() { - const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadChildrenOfEntityEvent({ - entityType: this.args.entityType, - unique: this.args.unique, - }); - - eventContext.dispatchEvent(event); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts new file mode 100644 index 0000000000..ea74db1f15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts @@ -0,0 +1,58 @@ +import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; +import type { UmbUserKindType } from '../../utils/index.js'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { + UmbEntityCreateOptionActionBase, + type MetaEntityCreateOptionAction, + type UmbEntityCreateOptionActionArgs, +} from '@umbraco-cms/backoffice/entity-create-option-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export interface UmbUserEntityCreateOptionActionBaseArgs + extends UmbEntityCreateOptionActionArgs { + kind: UmbUserKindType; +} + +export abstract class UmbUserEntityCreateOptionActionBase extends UmbEntityCreateOptionActionBase { + #kind: UmbUserKindType; + + constructor(host: UmbControllerHost, args: UmbUserEntityCreateOptionActionBaseArgs) { + super(host, args); + this.#kind = args.kind; + } + + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind: this.#kind, + }, + }, + }); + + await modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity(); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity(); + }); + } + + async #requestReloadChildrenOfEntity() { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType: this.args.entityType, + unique: this.args.unique, + }); + + eventContext.dispatchEvent(event); + } +} From 51387abeef3ee21d3d2f6d663c946edab34fa8e6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 20:29:53 +0100 Subject: [PATCH 232/246] clean up --- .../entity-create-option-action-list-modal.element.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 03360e282c..e3c871d6ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -12,7 +12,6 @@ import { state, repeat, ifDefined, - property, type PropertyValues, } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @@ -28,9 +27,6 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle @state() private _apiControllers: Array> = []; - @state() - _hrefMap = new Map(); - @state() _hrefList: Array = []; @@ -65,12 +61,9 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle ); } - async #onClick(event: Event, controller: UmbExtensionApiInitializer) { + async #onClick(event: Event, controller: UmbExtensionApiInitializer, href?: string) { event.stopPropagation(); - if (!controller.manifest) throw new Error('No manifest found'); - const href = this._hrefMap.get(controller.manifest?.alias); - // skip if href is defined if (href) { return; @@ -119,7 +112,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle this.#onClick(event, controller)} + @click=${(event: Event) => this.#onClick(event, controller, href)} href=${ifDefined(href)} target=${this.#getTarget(href)} ?selectable=${!href} From 7d14b03a3738bc48e8e37df6781d4d6e31a5b3d1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 20:30:32 +0100 Subject: [PATCH 233/246] clean up --- .../modal/entity-create-option-action-list-modal.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index e3c871d6ec..3675770b96 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -42,7 +42,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle const data = this.data; if (!data) throw new Error('No data found'); - if (data.entityType === undefined) throw new Error('No entityType found'); + if (!data.entityType) throw new Error('No entityType found'); if (data.unique === undefined) throw new Error('No unique found'); new UmbExtensionsApiInitializer( From 8afd06343856132a0ccddd9cc4490690061fd526 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 20:41:41 +0100 Subject: [PATCH 234/246] move create modal into create folder --- .../user/user/entity-actions/create/index.ts | 1 + .../user/user/entity-actions/create/manifests.ts | 2 ++ .../create/modal}/constants.ts | 0 .../create/modal}/create-user-modal.element.ts | 4 ++-- .../create/modal}/create-user-modal.token.ts | 2 +- .../modal}/create-user-success-modal.element.ts | 8 ++++---- .../modal}/create-user-success-modal.token.ts | 0 .../user/entity-actions/create/modal/index.ts | 1 + .../entity-actions/create/modal/manifests.ts | 16 ++++++++++++++++ .../user-entity-create-option-action-base.ts | 2 +- .../src/packages/user/user/modals/manifests.ts | 14 -------------- 11 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/constants.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-modal.element.ts (97%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-modal.token.ts (85%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-success-modal.element.ts (92%) rename src/Umbraco.Web.UI.Client/src/packages/user/user/{modals/create => entity-actions/create/modal}/create-user-success-modal.token.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts new file mode 100644 index 0000000000..28d9f38fba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/index.ts @@ -0,0 +1 @@ +export * from './modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts index 2e67f026d0..095b44610b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/manifests.ts @@ -1,6 +1,7 @@ import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import { manifests as apiUser } from './api-user/manifests.js'; import { manifests as defaultUser } from './default-user/manifests.js'; +import { manifests as modalManifests } from './modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -14,4 +15,5 @@ export const manifests: Array = }, ...apiUser, ...defaultUser, + ...modalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.element.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.element.ts index 863fc88bec..cea24184d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.element.ts @@ -1,5 +1,5 @@ -import { UmbUserDetailRepository } from '../../repository/index.js'; -import { UmbUserKind } from '../../utils/index.js'; +import { UmbUserDetailRepository } from '../../../repository/index.js'; +import { UmbUserKind } from '../../../utils/index.js'; import { UMB_CREATE_USER_SUCCESS_MODAL } from './create-user-success-modal.token.js'; import type { UmbCreateUserModalData } from './create-user-modal.token.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.token.ts similarity index 85% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.token.ts index 4486b12f4f..3fb7a19847 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-modal.token.ts @@ -1,4 +1,4 @@ -import type { UmbUserKindType } from '../../utils/index.js'; +import type { UmbUserKindType } from '../../../utils/index.js'; import { UMB_CREATE_USER_MODAL_ALIAS } from './constants.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.element.ts similarity index 92% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.element.ts index f30bf145be..d3c43c0a0d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.element.ts @@ -1,7 +1,7 @@ -import { UmbUserItemRepository } from '../../repository/item/index.js'; -import { UmbNewUserPasswordRepository } from '../../repository/new-password/index.js'; -import type { UmbUserItemModel } from '../../repository/item/types.js'; -import { UMB_USER_WORKSPACE_PATH } from '../../paths.js'; +import { UmbUserItemRepository } from '../../../repository/item/index.js'; +import { UmbNewUserPasswordRepository } from '../../../repository/new-password/index.js'; +import type { UmbUserItemModel } from '../../../repository/item/index.js'; +import { UMB_USER_WORKSPACE_PATH } from '../../../paths.js'; import type { UmbCreateUserSuccessModalData, UmbCreateUserSuccessModalValue, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/create-user-success-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/create-user-success-modal.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts new file mode 100644 index 0000000000..ca86e33e91 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/modal/manifests.ts @@ -0,0 +1,16 @@ +import { UMB_CREATE_USER_MODAL_ALIAS } from './constants.js'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_CREATE_USER_MODAL_ALIAS, + name: 'Create User Modal', + js: () => import('./create-user-modal.element.js'), + }, + { + type: 'modal', + alias: 'Umb.Modal.User.CreateSuccess', + name: 'Create Success User Modal', + js: () => import('./create-user-success-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts index ea74db1f15..ca55652d5a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/create/user-entity-create-option-action-base.ts @@ -1,5 +1,5 @@ -import { UMB_CREATE_USER_MODAL } from '../../modals/create/create-user-modal.token.js'; import type { UmbUserKindType } from '../../utils/index.js'; +import { UMB_CREATE_USER_MODAL } from './modal/create-user-modal.token.js'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts index 614f3e0d7b..03273e88df 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/manifests.ts @@ -1,18 +1,4 @@ -import { UMB_CREATE_USER_MODAL_ALIAS } from './create/constants.js'; - export const manifests: Array = [ - { - type: 'modal', - alias: UMB_CREATE_USER_MODAL_ALIAS, - name: 'Create User Modal', - js: () => import('./create/create-user-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.User.CreateSuccess', - name: 'Create Success User Modal', - js: () => import('./create/create-user-success-modal.element.js'), - }, { type: 'modal', alias: 'Umb.Modal.User.Picker', From f57e7ce0a0a2863b516278e58e9a926939446f0d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 21:00:48 +0100 Subject: [PATCH 235/246] add create collection action kind --- .../collection-create-action.element.ts | 0 .../collection/action/create/manifests.ts | 19 +++++++++++++++++++ .../core/collection/action/create/types.ts | 12 ++++++++++++ .../core/collection/action/manifests.ts | 4 ++++ .../src/packages/core/collection/manifests.ts | 2 ++ ...create-option-action-list-modal.element.ts | 16 +++++++++------- .../user/user/collection/action/manifests.ts | 3 +-- 7 files changed, 47 insertions(+), 9 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/{user/user/collection/action => core/collection/action/create}/collection-create-action.element.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user/collection/action/collection-create-action.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts new file mode 100644 index 0000000000..429fb41b26 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/manifests.ts @@ -0,0 +1,19 @@ +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.CollectionAction.Create', + matchKind: 'create', + matchType: 'collectionAction', + manifest: { + type: 'collectionAction', + kind: 'create', + element: () => import('./collection-create-action.element.js'), + weight: 1200, + meta: { + label: '#actions_create', + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts new file mode 100644 index 0000000000..50ef773e2c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/types.ts @@ -0,0 +1,12 @@ +import type { ManifestCollectionAction } from '../../extensions/index.js'; + +export interface ManifestCollectionActionCreateKind extends ManifestCollectionAction { + type: 'collectionAction'; + kind: 'create'; +} + +declare global { + interface UmbExtensionManifestMap { + umbCollectionActionCreateKind: ManifestCollectionActionCreateKind; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts new file mode 100644 index 0000000000..19f4780244 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as createManifests } from './create/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...createManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts index 0e211901ca..c59c5fa9f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/manifests.ts @@ -1,8 +1,10 @@ import type { UmbExtensionManifestKind } from '../extension-registry/registry.js'; import { manifests as conditionManifests } from './conditions/manifests.js'; +import { manifests as actionManifests } from './action/manifests.js'; import { manifests as workspaceViewManifests } from './workspace-view/manifests.js'; export const manifests: Array = [ + ...actionManifests, ...workspaceViewManifests, ...conditionManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 3675770b96..2cb2537636 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -85,13 +85,15 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle return html` - - ${repeat( - this._apiControllers, - (controller) => controller.manifest?.alias, - (controller, index) => this.#renderRefItem(controller, index), - )} - + ${this._apiControllers.length === 0 + ? html`
      No create options available.
      ` + : html` + ${repeat( + this._apiControllers, + (controller) => controller.manifest?.alias, + (controller, index) => this.#renderRefItem(controller, index), + )} + `}
      = [ { type: 'collectionAction', + kind: 'create', name: 'Create User Collection Action', alias: 'Umb.CollectionAction.User.Create', - element: () => import('./collection-create-action.element.js'), - weight: 200, conditions: [ { alias: UMB_COLLECTION_ALIAS_CONDITION, From fe0ab5239c71a3927df56822360928efda364e98 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 22:29:38 +0100 Subject: [PATCH 236/246] filter + add types --- .../modal/entity-create-option-action-list-modal.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts index 2cb2537636..5150c3946d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/create/modal/entity-create-option-action-list-modal.element.ts @@ -28,7 +28,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle private _apiControllers: Array> = []; @state() - _hrefList: Array = []; + _hrefList: Array = []; protected override updated(_changedProperties: PropertyValues): void { super.updated(_changedProperties); @@ -52,7 +52,7 @@ export class UmbEntityCreateOptionActionListModalElement extends UmbModalBaseEle (manifest: ManifestType) => { return [{ entityType: data.entityType, unique: data.unique, meta: manifest.meta }]; }, - undefined, + (manifest: ManifestType) => manifest.forEntityTypes.includes(data.entityType), async (controllers) => { this._apiControllers = controllers as unknown as Array>; const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); From 6d166e288b70031178da9e13dcc0ba2354f38112 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sat, 2 Nov 2024 22:29:48 +0100 Subject: [PATCH 237/246] align with modal --- .../collection-create-action.element.ts | 72 ++++++++++++++++--- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts index f0a2d88b95..fd80de09a2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/action/create/collection-create-action.element.ts @@ -1,7 +1,12 @@ -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import type { ManifestEntityCreateOptionAction } from '@umbraco-cms/backoffice/entity-create-option-action'; + +type ManifestType = ManifestEntityCreateOptionAction; const elementName = 'umb-collection-create-action-button'; @customElement(elementName) @@ -13,9 +18,13 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { private _multipleOptions = false; @state() - private _apiControllers: Array = []; + private _apiControllers: Array> = []; + + @state() + _hrefList: Array = []; #createLabel = this.localize.term('general_create'); + #entityContext?: typeof UMB_ENTITY_CONTEXT.TYPE; #onPopoverToggle(event: PointerEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. @@ -24,27 +33,61 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { this._popoverOpen = event.newState === 'open'; } - async #onClick(event: Event, controller: any) { + async #onClick(event: Event, controller: UmbExtensionApiInitializer, href?: string) { event.stopPropagation(); + + // skip if href is defined + if (href) { + return; + } + + if (!controller.api) throw new Error('No API found'); await controller.api.execute(); } constructor() { super(); + this.consumeContext(UMB_ENTITY_CONTEXT, (context) => { + this.#entityContext = context; + this.#initApi(); + }); + } + + #initApi() { + if (!this.#entityContext) return; + + const entityType = this.#entityContext.getEntityType(); + if (!entityType) throw new Error('No entityType found'); + + const unique = this.#entityContext.getUnique(); + if (unique === undefined) throw new Error('No unique found'); + new UmbExtensionsApiInitializer( this, umbExtensionsRegistry, 'entityCreateOptionAction', - [], - undefined, - (controllers) => { - this._apiControllers = controllers; + (manifest: ManifestType) => { + return [{ entityType, unique, meta: manifest.meta }]; + }, + (manifest: ManifestType) => manifest.forEntityTypes.includes(entityType), + async (controllers) => { + this._apiControllers = controllers as unknown as Array>; this._multipleOptions = controllers.length > 1; + const hrefPromises = this._apiControllers.map((controller) => controller.api?.getHref()); + this._hrefList = await Promise.all(hrefPromises); }, ); } + #getTarget(href?: string) { + if (href && href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + override render() { return this._multipleOptions ? this.#renderMultiOptionAction() : this.#renderSingleOptionAction(); } @@ -79,19 +122,26 @@ export class UmbCollectionCreateActionButtonElement extends UmbLitElement { @toggle=${this.#onPopoverToggle}> - ${this._apiControllers.map((controller) => this.#renderMenuItem(controller))} + ${this._apiControllers.map((controller, index) => this.#renderMenuItem(controller, index))} `; } - #renderMenuItem(controller: any) { + #renderMenuItem(controller: UmbExtensionApiInitializer, index: number) { const manifest = controller.manifest; - const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.meta.name; + if (!manifest) throw new Error('No manifest found'); + + const label = manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; + const href = this._hrefList[index]; return html` - this.#onClick(event, controller)}> + this.#onClick(event, controller, href)} + href=${ifDefined(href)} + target=${this.#getTarget(href)}> `; From 3c4c4cb0f2200218339d3c9d5dd943a0c99c9fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 12:38:41 +0100 Subject: [PATCH 238/246] lint corrections --- .../entity-create-option-action.extension.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts index cce0b9a4f2..0139e7ba5d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts @@ -10,7 +10,6 @@ export interface ManifestEntityCreateOptionAction< meta: MetaType; } -// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface MetaEntityCreateOptionAction { /** * An icon to represent the action to be performed From e0fca6fa7bac84dd02205d67e839e4e705013302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 12:39:31 +0100 Subject: [PATCH 239/246] type export --- .../src/packages/core/entity-create-option-action/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index 1794649010..9d1c5d4520 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,4 +1,4 @@ export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; -export * from './types.js'; +export type * from './types.js'; From d0a3ae8ba9f69620d4f593dd92d6e10a33d5bd87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 12:42:21 +0100 Subject: [PATCH 240/246] update all-packages list --- src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts b/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts index 11e3b72b14..2f8a997a00 100644 --- a/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts +++ b/src/Umbraco.Web.UI.Client/src/json-schema/all-packages.ts @@ -33,6 +33,7 @@ import '@umbraco-cms/backoffice/document-type'; import '@umbraco-cms/backoffice/document'; import '@umbraco-cms/backoffice/entity-action'; import '@umbraco-cms/backoffice/entity-bulk-action'; +import '@umbraco-cms/backoffice/entity-create-option-action'; import '@umbraco-cms/backoffice/entity'; import '@umbraco-cms/backoffice/event'; import '@umbraco-cms/backoffice/extension-registry'; From b2af81ba7e38cbc69e758e16a2b33655a6588f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 13:31:50 +0100 Subject: [PATCH 241/246] constants --- .../src/packages/core/entity-create-option-action/constants.ts | 1 + .../entity-create-option-action.extension.ts | 3 ++- .../src/packages/core/entity-create-option-action/index.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts new file mode 100644 index 0000000000..4c25e59099 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/constants.ts @@ -0,0 +1 @@ +export const UMB_EXTENSION_TYPE_ENTITY_CREATE_OPTION_ACTION = 'entityCreateOptionAction'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts index 0139e7ba5d..4f62ecd3de 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action.extension.ts @@ -1,11 +1,12 @@ import type { UmbEntityCreateOptionAction } from './entity-create-option-action.interface.js'; +import type { UMB_EXTENSION_TYPE_ENTITY_CREATE_OPTION_ACTION } from './constants.js'; import type { ManifestApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestEntityCreateOptionAction< MetaType extends MetaEntityCreateOptionAction = MetaEntityCreateOptionAction, > extends ManifestApi>, ManifestWithDynamicConditions { - type: 'entityCreateOptionAction'; + type: typeof UMB_EXTENSION_TYPE_ENTITY_CREATE_OPTION_ACTION; forEntityTypes: Array; meta: MetaType; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts index 9d1c5d4520..566d9306e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/index.ts @@ -1,3 +1,4 @@ +export * from './constants.js'; export * from './entity-create-option-action-base.js'; export * from './entity-create-option-action.extension.js'; export * from './entity-create-option-action.interface.js'; From 6b320415cc9f7f4c3ba0fc1392e813696b9e6605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 13:31:55 +0100 Subject: [PATCH 242/246] jsdocs --- .../entity-create-option-action-base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts index 2800261185..236d7e6394 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-create-option-action/entity-create-option-action-base.ts @@ -13,7 +13,7 @@ export abstract class UmbEntityCreateOptionActionBase< * By specifying the href, the action will act as a link. * The `execute` method will not be called. * @abstract - * @returns {string | undefined} + * @returns {string | undefined} - A promise which resolves into a HREF string or undefined. */ public getHref(): Promise { return Promise.resolve(undefined); From c1b9599fed3d05c35c8329e8e97622b49d9975ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 13:38:36 +0100 Subject: [PATCH 243/246] update vite.config for core package --- src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts index a4cb479492..5a0214273d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/vite.config.ts @@ -23,6 +23,7 @@ export default defineConfig({ 'debug/index': './debug/index.ts', 'entity-action/index': './entity-action/index.ts', 'entity-bulk-action/index': './entity-bulk-action/index.ts', + 'entity-create-option-action/index': './entity-create-option-action/index.ts', 'entity/index': './entity/index.ts', 'entry-point': 'entry-point.ts', 'event/index': './event/index.ts', From 036d14453fd4f5212747ff1daccee8729fe270e9 Mon Sep 17 00:00:00 2001 From: Lee Kelleher Date: Mon, 4 Nov 2024 13:28:51 +0000 Subject: [PATCH 244/246] Hotfix: UFM alias prefixes (#2510) * Adds `alias` to UFM component registrations * Adds support for `alias` prefix in UFM syntax e.g. `{(alias:|marker)(text)}` would be `{umbContentName: propertyAlias}` or `{~propertyAlias}` * UFM Content Name: adds warning for using the `~` prefix marker The `~` prefix will be deprecated in a future major release. --- .../content-name/content-name.component.ts | 7 +++++++ .../src/packages/ufm/components/manifests.ts | 6 +++--- .../src/packages/ufm/contexts/ufm.context.ts | 2 +- .../src/packages/ufm/plugins/marked-ufm.plugin.ts | 11 +++++++---- .../src/packages/ufm/plugins/marked-ufm.test.ts | 12 +++++++++--- .../src/packages/ufm/ufm-component.extension.ts | 3 ++- 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts index dfcd5c6e2b..49a84361e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.component.ts @@ -7,6 +7,13 @@ export class UmbUfmContentNameComponent extends UmbUfmComponentBase { render(token: UfmToken) { if (!token.text) return; + if (token.prefix === '~') { + /* + * @deprecated since version 15.0-rc3 + */ + console.warn(`Please update your UFM syntax from \`${token.raw}\` to \`{umbContentName:${token.text}}\`.`); + } + const attributes = super.getAttributes(token.text); return ``; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts index 99ec024f17..b9c7f5dc6f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/manifests.ts @@ -6,20 +6,20 @@ export const manifests: Array = [ alias: 'Umb.Markdown.LabelValue', name: 'Label Value UFM Component', api: () => import('./label-value/label-value.component.js'), - meta: { marker: '=' }, + meta: { alias: 'umbValue', marker: '=' }, }, { type: 'ufmComponent', alias: 'Umb.Markdown.Localize', name: 'Localize UFM Component', api: () => import('./localize/localize.component.js'), - meta: { marker: '#' }, + meta: { alias: 'umbLocalize', marker: '#' }, }, { type: 'ufmComponent', alias: 'Umb.Markdown.ContentName', name: 'Content Name UFM Component', api: () => import('./content-name/content-name.component.js'), - meta: { marker: '~' }, + meta: { alias: 'umbContentName', marker: '~' }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts index 86563bc56d..a82415085e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts @@ -60,7 +60,7 @@ export class UmbUfmContext extends UmbContextBase { const ctrl = controller as unknown as UmbExtensionApiInitializer; if (!ctrl.manifest || !ctrl.api) return; return { - alias: ctrl.manifest.alias, + alias: ctrl.manifest.meta.alias || ctrl.manifest.alias, marker: ctrl.manifest.meta.marker, render: ctrl.api.render, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts index edebdefcca..604b4a4b1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.plugin.ts @@ -2,11 +2,12 @@ import type { MarkedExtension, Tokens } from '@umbraco-cms/backoffice/external/m export interface UfmPlugin { alias: string; - marker: string; + marker?: string; render?: (token: UfmToken) => string | undefined; } export interface UfmToken extends Tokens.Generic { + prefix: string; text?: string; } @@ -18,21 +19,23 @@ export interface UfmToken extends Tokens.Generic { export function ufm(plugins: Array = []): MarkedExtension { return { extensions: plugins.map(({ alias, marker, render }) => { + const prefix = `(${alias}:${marker ? `|${marker}` : ''})`; return { name: alias, level: 'inline', - start: (src: string) => src.indexOf(`{${marker}`), + start: (src: string) => src.search(`{${prefix}`), tokenizer: (src: string) => { - const pattern = `^\\{${marker}([^}]*)\\}`; + const pattern = `^\\{${prefix}([^}]*)\\}`; const regex = new RegExp(pattern); const match = src.match(regex); if (match) { - const [raw, content = ''] = match; + const [raw, prefix, content = ''] = match; return { type: alias, raw: raw, tokens: [], + prefix: prefix, text: content.trim(), }; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts index 71a2177ddb..565040a143 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/plugins/marked-ufm.test.ts @@ -16,16 +16,22 @@ describe('UmbMarkedUfm', () => { ufm: '{= prop1 | strip-html | truncate:30}', expected: '', }, + { ufm: '{umbValue:prop1}', expected: '' }, { ufm: '{#general_add}', expected: '' }, + { ufm: '{umbLocalize:general_add}', expected: '' }, { ufm: '{~contentPicker}', expected: '' }, + { + ufm: '{umbContentName: contentPicker}', + expected: '', + }, ]; // Manually configuring the UFM components for testing. UmbMarked.use( ufm([ - { alias: 'Umb.Markdown.ContentName', marker: '~', render: new UmbUfmContentNameComponent().render }, - { alias: 'Umb.Markdown.LabelValue', marker: '=', render: new UmbUfmLabelValueComponent().render }, - { alias: 'Umb.Markdown.Localize', marker: '#', render: new UmbUfmLocalizeComponent().render }, + { alias: 'umbContentName', marker: '~', render: new UmbUfmContentNameComponent().render }, + { alias: 'umbValue', marker: '=', render: new UmbUfmLabelValueComponent().render }, + { alias: 'umbLocalize', marker: '#', render: new UmbUfmLocalizeComponent().render }, ]), ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts index bf3c3ee9d5..bc321232e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/ufm-component.extension.ts @@ -6,7 +6,8 @@ export interface UmbUfmComponentApi extends UmbApi { } export interface MetaUfmComponent { - marker: string; + alias: string; + marker?: string; } export interface ManifestUfmComponent extends ManifestApi { From 4dffbf3bcb4155c20e32a6ac3e482664ac3ddf20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 4 Nov 2024 15:06:32 +0100 Subject: [PATCH 245/246] resolve merge conflict --- .../examples/ufm-custom-component/index.ts | 1 + .../tiptap/extensions/toolbar/clear-formatting.extension.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/examples/ufm-custom-component/index.ts b/src/Umbraco.Web.UI.Client/examples/ufm-custom-component/index.ts index af49cdc0f3..67d3281921 100644 --- a/src/Umbraco.Web.UI.Client/examples/ufm-custom-component/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/ufm-custom-component/index.ts @@ -8,6 +8,7 @@ export const manifests: Array = [ api: () => import('./custom-ufm-component.js'), meta: { marker: '%', + alias: 'myCustomComponent', }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts index 159e932a14..2541a24615 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/clear-formatting.extension.ts @@ -1,4 +1,4 @@ -import { UmbTiptapToolbarElementApiBase } from '../types.js'; +import { UmbTiptapToolbarElementApiBase } from '../base.js'; import type { Editor } from '@umbraco-cms/backoffice/external/tiptap'; export default class UmbTiptapToolbarClearFormattingExtensionApi extends UmbTiptapToolbarElementApiBase { From 8424cdf8c2dc215b1e0adf795d14fda3e2f19b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 5 Nov 2024 10:06:59 +0100 Subject: [PATCH 246/246] Feat: condition config types as a generic for extension registry (#2473) get condition config types as a generic for extension registry --- .../src/libs/extension-api/registry/extension.registry.ts | 5 +++-- .../src/packages/core/extension-registry/registry.ts | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts index 580da1cb1f..0d53be4b26 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts @@ -100,6 +100,7 @@ const sortExtensions = (a: ManifestBase, b: ManifestBase): number => (b.weight | export class UmbExtensionRegistry< IncomingManifestTypes extends ManifestBase, + IncomingConditionConfigTypes extends UmbConditionConfigBase = UmbConditionConfigBase, ManifestTypes extends ManifestBase = IncomingManifestTypes | ManifestBase, > { readonly MANIFEST_TYPES: ManifestTypes = undefined as never; @@ -490,7 +491,7 @@ export class UmbExtensionRegistry< * @param {string} alias - The alias of the extension to append the condition to. * @param {UmbConditionConfigBase} newCondition - The condition to append to the extension. */ - appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + appendCondition(alias: string, newCondition: IncomingConditionConfigTypes) { this.appendConditions(alias, [newCondition]); } @@ -499,7 +500,7 @@ export class UmbExtensionRegistry< * @param {string} alias - The alias of the extension to append the condition to * @param {Array} newConditions - An array of conditions to be appended to an extension manifest. */ - appendConditions(alias: string, newConditions: Array) { + appendConditions(alias: string, newConditions: Array) { const existingConditionsToBeAdded = this.#additionalConditions.get(alias); this.#additionalConditions.set( alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/registry.ts index 0985b3226e..22849345b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/registry.ts @@ -2,9 +2,12 @@ import type { ManifestKind } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extension-api'; export type UmbExtensionManifestKind = ManifestKind; -export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; +export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; -export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; +export const umbExtensionsRegistry = new UmbExtensionRegistry< + UmbExtensionManifest, + UmbExtensionConditionConfig +>() as UmbBackofficeExtensionRegistry; /** * @deprecated Use `UmbExtensionManifestKind` instead.