From 7a667efe1b6e39208a27dd756838fcab4c947438 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:40:47 +0100 Subject: [PATCH 01/81] block input groups --- .../manifests.ts | 13 +++ ...-block-grid-group-configuration.element.ts | 61 ++++++++++ ...-block-grid-group-configuration.stories.ts | 15 +++ ...i-block-grid-type-configuration.element.ts | 54 +++++++-- .../block-grid/property-editors/manifests.ts | 9 +- .../src/packages/block/block-grid/types.ts | 5 + .../input-block-type.element.ts | 109 ++++++++++++++++-- 7 files changed, 250 insertions(+), 16 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/manifests.ts new file mode 100644 index 0000000000..7bb496f59d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/manifests.ts @@ -0,0 +1,13 @@ +import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest: ManifestPropertyEditorUi = { + type: 'propertyEditorUi', + alias: 'Umb.PropertyEditorUi.BlockTypeGroupConfiguration', + name: 'Block Grid Group Configuration Property Editor UI', + js: () => import('./property-editor-ui-block-grid-group-configuration.element.js'), + meta: { + label: '', + icon: 'icon-box-alt', + group: 'common', + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts new file mode 100644 index 0000000000..b26157b711 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts @@ -0,0 +1,61 @@ +import { html, customElement, property, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UmbId } from '@umbraco-cms/backoffice/id'; +import { BlockGridGroupConfigration } from '@umbraco-cms/backoffice/block'; + +@customElement('umb-property-editor-ui-block-grid-group-configuration') +export class UmbPropertyEditorUIBlockGridGroupConfigurationElement + extends UmbLitElement + implements UmbPropertyEditorUiElement +{ + private _value: Array = []; + + @property({ type: Array }) + public get value(): Array { + return this._value; + } + public set value(value: Array) { + this._value = value || []; + } + + @property({ attribute: false }) + public set config(config: UmbPropertyEditorConfigCollection | undefined) {} + + #addGroup() { + if (Array.isArray(this.value)) { + this.value = [...this.value, { name: 'Unnamed group', key: UmbId.new() }]; + } else { + this.value = [{ name: 'Unnamed group', key: UmbId.new() }]; + } + + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + render() { + return html` + + ${this.localize.term('blockEditor_addBlockGroup')} + + `; + } + + static styles = [ + UmbTextStyles, + css` + uui-button { + display: block; + } + `, + ]; +} + +export default UmbPropertyEditorUIBlockGridGroupConfigurationElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-property-editor-ui-block-grid-group-configuration': UmbPropertyEditorUIBlockGridGroupConfigurationElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts new file mode 100644 index 0000000000..7e8cb00391 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts @@ -0,0 +1,15 @@ +import { Meta, Story } from '@storybook/web-components'; +import type { UmbPropertyEditorUIBlockGridGroupConfigurationElement } from './property-editor-ui-block-grid-group-configuration.element.js'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './property-editor-ui-block-grid-group-configuration.element.js'; + +export default { + title: 'Property Editor UIs/Block Grid Group Configuration', + component: 'umb-property-editor-ui-block-grid-group-configuration', + id: 'umb-property-editor-ui-block-grid-group-configuration', +} as Meta; + +export const AAAOverview: Story = () => + html` `; +AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 94be84645b..c5b918799c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -1,10 +1,12 @@ -import type { UmbBlockTypeBase, UmbInputBlockTypeElement } from '../../../block-type/index.js'; +import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import { BlockGridGroupConfigration } from '@umbraco-cms/backoffice/block'; /** * @element umb-property-editor-ui-block-grid-type-configuration @@ -14,22 +16,60 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement extends UmbLitElement implements UmbPropertyEditorUiElement { + #context?: UmbPropertyDatasetContext; + @property({ attribute: false }) - value: UmbBlockTypeBase[] = []; + value: UmbBlockTypeWithGroupKey[] = []; @property({ type: Object, attribute: false }) public config?: UmbPropertyEditorConfigCollection; + @state() + private _blockGroups: Array = []; + + // @state() + // private _groups: Array<{ name: string; key: string | null; blocks: UmbBlockTypeWithGroupKey[] }> = []; + + constructor() { + super(); + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { + this.#context = instance; + this.#observeProperties(); + }); + } + + async #observeProperties() { + if (!this.#context) return; + + this.observe(await this.#context.propertyValueByAlias('blockGroups'), (value) => { + this._blockGroups = value as Array; + }); + } + render() { return html` { - this.value = (e.target as UmbInputBlockTypeElement).value; - }}>`; + @change=${(e: Event) => (this.value = (e.target as UmbInputBlockTypeElement).value)}>`; } - static styles = [UmbTextStyles]; + static styles = [ + UmbTextStyles, + css` + uui-input { + margin-top: var(--uui-size-6); + margin-bottom: var(--uui-size-4); + } + + uui-input:not(:hover, :focus) { + border: 1px solid transparent; + } + uui-input:not(:hover, :focus) uui-button { + opacity: 0; + } + `, + ]; } export default UmbPropertyEditorUIBlockGridTypeConfigurationElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/manifests.ts index 11b3d055ed..f1737b0acd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/manifests.ts @@ -2,5 +2,12 @@ import { manifest as blockGridEditor } from './block-grid-editor/manifests.js'; import { manifest as blockGridLayoutStylesheet } from './block-grid-layout-stylesheet/manifests.js'; import { manifest as blockGridTypeConfiguration } from './block-grid-type-configuration/manifests.js'; import { manifest as blockGridColumnSpan } from './block-grid-column-span/manifests.js'; +import { manifest as blockGridGroupConfiguration } from './block-grid-group-configuration/manifests.js'; -export const manifests = [blockGridTypeConfiguration, blockGridEditor, blockGridLayoutStylesheet, blockGridColumnSpan]; +export const manifests = [ + blockGridTypeConfiguration, + blockGridEditor, + blockGridLayoutStylesheet, + blockGridColumnSpan, + blockGridGroupConfiguration, +]; 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 1a58b9ea39..f8dfc9f5f2 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 @@ -11,3 +11,8 @@ export interface UmbBlockGridType extends UmbBlockTypeBase { areas: Array; groupKey: null | string; } + +export interface BlockGridGroupConfigration { + name?: string; + key: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 622c77ed6a..ff15657cac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -1,4 +1,4 @@ -import { UmbBlockTypeBase } from '../../types.js'; +import { UmbBlockTypeBase, UmbBlockTypeGroup, UmbBlockTypeWithGroupKey } from '../../types.js'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT_TOKEN, @@ -9,9 +9,14 @@ import '../block-type-card/index.js'; import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; +import { BlockGridGroupConfigration } from '@umbraco-cms/backoffice/block'; +import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; @customElement('umb-input-block-type') -export class UmbInputBlockTypeElement extends UmbLitElement { +export class UmbInputBlockTypeElement< + BlockType extends UmbBlockTypeWithGroupKey = UmbBlockTypeBase, +> extends UmbLitElement { // @property({ type: Array, attribute: false }) public get value() { @@ -19,6 +24,7 @@ export class UmbInputBlockTypeElement = []; + @property({ type: Array }) + public get groups(): Array { + return this.#groups; + } + public set groups(groups: Array) { + this.#groups = groups ?? []; + this.#mapValues(); + } + + #mapValues() { + const valuesWithNoGroup = this.value.filter( + // Look for values without a group, or with a group that is non existent. + (value) => !value.groupKey || this.#groups.find((group) => group.key !== value.groupKey), + ); + + const valuesWithGroup = this.#groups.map((group) => { + return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; + }); + + this._mappedGroups = [{ key: '', name: '', blocks: valuesWithNoGroup }, ...valuesWithGroup]; + } + @state() private _items: Array = []; + @state() + private _mappedGroups: Array }> = []; + @state() private _workspacePath?: string; @@ -55,8 +87,13 @@ export class UmbInputBlockTypeElement; + #context?: UmbPropertyDatasetContext; + constructor() { super(); + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { + this.#context = instance; + }); } create() { @@ -87,7 +124,7 @@ export class UmbInputBlockTypeElement x.contentElementTypeKey !== contentElementTypeKey); + this.value = this._items.filter((x) => x.contentElementTypeKey !== contentElementTypeKey); this.dispatchEvent(new UmbChangeEvent()); } @@ -95,11 +132,54 @@ export class UmbInputBlockTypeElement (group.key === key ? { ...group, name: groupName } : group)); + + this.#context?.setPropertyValue('blockGroups', groups); + } + + #deleteGroup(key: string) { + this.#context?.setPropertyValue( + 'blockGroups', + this.groups.filter((group) => group.key !== key), + ); + this.value = this.value.filter((block) => block.groupKey !== key); + this.dispatchEvent(new UmbChangeEvent()); + this.#mapValues(); + } + render() { - return html` - ${this._items ? repeat(this._items, (item) => item.contentElementTypeKey, this.#renderItem) : ''} - ${this.#renderButton()} - `; + return html`${repeat( + this._mappedGroups, + (group) => group.key + group.blocks, + (group) => + html` ${group.key + ? html` this.#renameGroup(e, group.key)}> + this.#deleteGroup(group.key)}> + + + ` + : ''} +
+ ${repeat( + group.blocks, + (block) => block.contentElementTypeKey, + (block) => + html` this.deleteItem(block.contentElementTypeKey)}> + `, + )} + ${this.#renderButton()} +
`, + )}`; } #renderButton() { @@ -123,7 +203,7 @@ export class UmbInputBlockTypeElement Date: Thu, 18 Jan 2024 14:42:17 +0100 Subject: [PATCH 02/81] use _value for guaranteed array --- ...rty-editor-ui-block-grid-group-configuration.element.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts index b26157b711..b5f896a42d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts @@ -25,12 +25,7 @@ export class UmbPropertyEditorUIBlockGridGroupConfigurationElement public set config(config: UmbPropertyEditorConfigCollection | undefined) {} #addGroup() { - if (Array.isArray(this.value)) { - this.value = [...this.value, { name: 'Unnamed group', key: UmbId.new() }]; - } else { - this.value = [{ name: 'Unnamed group', key: UmbId.new() }]; - } - + this.value = [...this._value, { name: 'Unnamed group', key: UmbId.new() }]; this.dispatchEvent(new CustomEvent('property-value-change')); } From 67adad5984aba43f1e625a2bc7bb2bb72fd7e37c Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:48:27 +0100 Subject: [PATCH 03/81] datasetcontext --- .../input-block-type/input-block-type.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 5bd561f196..3afaeebed3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -88,12 +88,12 @@ export class UmbInputBlockTypeElement< typeof UMB_WORKSPACE_MODAL.VALUE >; - #context?: UmbPropertyDatasetContext; + #datasetContext?: UmbPropertyDatasetContext; constructor() { super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { - this.#context = instance; + this.#datasetContext = instance; }); } @@ -138,11 +138,11 @@ export class UmbInputBlockTypeElement< const groupName = e.target.value as string; const groups = this.groups.map((group) => (group.key === key ? { ...group, name: groupName } : group)); - this.#context?.setPropertyValue('blockGroups', groups); + this.#datasetContext?.setPropertyValue('blockGroups', groups); } #deleteGroup(key: string) { - this.#context?.setPropertyValue( + this.#datasetContext?.setPropertyValue( 'blockGroups', this.groups.filter((group) => group.key !== key), ); From c545d0853bfb34d79321a31e8b8beb462a7c9862 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:50:35 +0100 Subject: [PATCH 04/81] groupkey --- .../components/input-block-type/input-block-type.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 3afaeebed3..6faacfd6d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -154,7 +154,7 @@ export class UmbInputBlockTypeElement< render() { return html`${repeat( this._mappedGroups, - (group) => group.key + group.blocks, + (group) => group.key, (group) => html` ${group.key ? html` Date: Fri, 19 Jan 2024 09:41:51 +0100 Subject: [PATCH 05/81] grouping logic moved --- ...i-block-grid-type-configuration.element.ts | 63 ++++++++-- .../src/packages/block/block-grid/types.ts | 10 +- .../input-block-type.element.ts | 115 +++++++----------- 3 files changed, 103 insertions(+), 85 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index c5b918799c..cae3b17d09 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -1,12 +1,12 @@ import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, state, css, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; -import { BlockGridGroupConfigration } from '@umbraco-cms/backoffice/block'; +import { UmbBlockGridGroupType, UmbBlockGridGroupTypeConfiguration } from '@umbraco-cms/backoffice/block'; /** * @element umb-property-editor-ui-block-grid-type-configuration @@ -16,7 +16,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement extends UmbLitElement implements UmbPropertyEditorUiElement { - #context?: UmbPropertyDatasetContext; + #datasetContext?: UmbPropertyDatasetContext; @property({ attribute: false }) value: UmbBlockTypeWithGroupKey[] = []; @@ -25,34 +25,75 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement public config?: UmbPropertyEditorConfigCollection; @state() - private _blockGroups: Array = []; + private _blockGroups: Array = []; - // @state() - // private _groups: Array<{ name: string; key: string | null; blocks: UmbBlockTypeWithGroupKey[] }> = []; + @state() + private _mappedValuesAndGroups: Array = []; constructor() { super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { - this.#context = instance; + this.#datasetContext = instance; this.#observeProperties(); }); } async #observeProperties() { - if (!this.#context) return; + if (!this.#datasetContext) return; - this.observe(await this.#context.propertyValueByAlias('blockGroups'), (value) => { - this._blockGroups = value as Array; + this.observe(await this.#datasetContext.propertyValueByAlias('blockGroups'), (value) => { + this._blockGroups = value as Array; + this.#mapValuesToBlockGroups(); + console.log('groups changed', value); + }); + this.observe(await this.#datasetContext.propertyValueByAlias('blocks'), (value) => { + this.#mapValuesToBlockGroups(); + console.log('value changed', value); }); } + #mapValuesToBlockGroups() { + const valuesWithNoGroup = this.value.filter( + // Look for values without a group, or with a group that is non existent. + (value) => !value.groupKey || this._blockGroups.find((group) => group.key !== value.groupKey), + ); + + const valuesWithGroup = this._blockGroups.map((group) => { + return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; + }); + + this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup]; + } + + #onChange(e: Event, groupKey?: string) { + const newValue = (e.target as UmbInputBlockTypeElement).value; + const values = this.value.filter((item) => item.groupKey !== groupKey); + this.value = [...values, ...newValue]; + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + render() { + return html`${repeat( + this._mappedValuesAndGroups, + (group) => group.key, + (group) => + html` this.#onChange(e, group.key)}>`, + )}`; + } + + /* render() { return html` (this.value = (e.target as UmbInputBlockTypeElement).value)}>`; - } + }*/ static styles = [ UmbTextStyles, 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 f8dfc9f5f2..b6c2e2a02e 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,4 +1,4 @@ -import type { UmbBlockTypeBase } from '../block-type/index.js'; +import type { UmbBlockTypeBase, UmbBlockTypeWithGroupKey } from '../block-type/index.js'; export interface UmbBlockGridType extends UmbBlockTypeBase { columnSpanOptions: Array; @@ -12,7 +12,11 @@ export interface UmbBlockGridType extends UmbBlockTypeBase { groupKey: null | string; } -export interface BlockGridGroupConfigration { - name?: string; +export interface UmbBlockGridGroupType { + name: string; key: string; } + +export interface UmbBlockGridGroupTypeConfiguration extends Partial { + blocks: Array; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 6faacfd6d4..b8ec0604e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -9,24 +9,28 @@ import '../block-type-card/index.js'; import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { BlockGridGroupConfigration } from '@umbraco-cms/backoffice/block'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import { UmbBlockGridType } from '@umbraco-cms/backoffice/block'; @customElement('umb-input-block-type') export class UmbInputBlockTypeElement< BlockType extends UmbBlockTypeWithGroupKey = UmbBlockTypeBase, > extends UmbLitElement { - // @property({ type: Array, attribute: false }) public get value() { return this._items; } public set value(items) { this._items = items ?? []; - this.#mapValues(); } + @property() + groupKey?: string; + + @property() + groupName?: string; + @property({ type: String, attribute: 'entity-type' }) public get entityType() { return this.#entityType; @@ -51,35 +55,9 @@ export class UmbInputBlockTypeElement< } #entityType?: string; - #groups: Array = []; - @property({ type: Array }) - public get groups(): Array { - return this.#groups; - } - public set groups(groups: Array) { - this.#groups = groups ?? []; - this.#mapValues(); - } - - #mapValues() { - const valuesWithNoGroup = this.value.filter( - // Look for values without a group, or with a group that is non existent. - (value) => !value.groupKey || this.#groups.find((group) => group.key !== value.groupKey), - ); - - const valuesWithGroup = this.#groups.map((group) => { - return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; - }); - - this._mappedGroups = [{ key: '', name: '', blocks: valuesWithNoGroup }, ...valuesWithGroup]; - } - @state() private _items: Array = []; - @state() - private _mappedGroups: Array }> = []; - @state() private _workspacePath?: string; @@ -89,11 +67,19 @@ export class UmbInputBlockTypeElement< >; #datasetContext?: UmbPropertyDatasetContext; + #blockGroups: Array = []; + #filter?: any; constructor() { super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { this.#datasetContext = instance; + this.observe(await this.#datasetContext?.propertyValueByAlias('blockGroups'), (value) => { + this.#blockGroups = value as Array; + }); + this.observe(await this.#datasetContext?.propertyValueByAlias('blocks'), (value) => { + this.#filter = value as Array; + }); }); } @@ -109,7 +95,7 @@ export class UmbInputBlockTypeElement< // Only pick elements: docType.isElement && // Prevent picking the an already used element type: - this._items.find((x) => x.contentElementTypeKey === docType.id) === undefined, + this.#filter.find((x: UmbBlockGridType) => x.contentElementTypeKey === docType.id) === undefined, }, }); @@ -133,54 +119,41 @@ export class UmbInputBlockTypeElement< return undefined; } - #renameGroup(e: UUIInputEvent, key: string) { - if (!key) return; - const groupName = e.target.value as string; - const groups = this.groups.map((group) => (group.key === key ? { ...group, name: groupName } : group)); - - this.#datasetContext?.setPropertyValue('blockGroups', groups); + render() { + return html`${this.#renderGroupInput()} +
+ ${repeat(this.value, (block) => block.contentElementTypeKey, this.#renderItem)} ${this.#renderButton()} +
`; } - #deleteGroup(key: string) { + #renderGroupInput() { + if (!this.groupKey) return; + return html` + + + + `; + } + + #changeGroupName(e: UUIInputEvent) { + if (!this.groupKey) return; + + const groupName = e.target.value as string; this.#datasetContext?.setPropertyValue( 'blockGroups', - this.groups.filter((group) => group.key !== key), + this.#blockGroups.map((group) => ({ ...group, groupName: this.groupKey === group.key ? groupName : group.name })), ); - this.value = this.value.filter((block) => block.groupKey !== key); - this.dispatchEvent(new UmbChangeEvent()); - this.#mapValues(); } - render() { - return html`${repeat( - this._mappedGroups, - (group) => group.key, - (group) => - html` ${group.key - ? html` this.#renameGroup(e, group.key)}> - this.#deleteGroup(group.key)}> - - - ` - : ''} -
- ${repeat( - group.blocks, - (block) => block.contentElementTypeKey, - (block) => - html` this.deleteItem(block.contentElementTypeKey)}> - `, - )} - ${this.#renderButton()} -
`, - )}`; + #deleteGroup() { + if (!this.groupKey) return; + this.#datasetContext?.setPropertyValue( + 'blockGroups', + this.#blockGroups.filter((group) => group.key !== this.groupKey), + ); + this.value = this._items.filter((block) => block.groupKey !== this.groupKey); + this.dispatchEvent(new UmbChangeEvent()); + console.log(this.value); } #renderButton() { From 3fa16e1256751b686656bd5ec62758fae89cdd73 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:16:54 +0100 Subject: [PATCH 06/81] test with broken group key --- .../src/mocks/data/data-type.data.ts | 7 +++++ .../data/document-type/document-type.data.ts | 27 +++++++++++++++++++ ...i-block-grid-type-configuration.element.ts | 12 ++++++--- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts index 74e7646d41..e8dbbe4cd3 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts @@ -645,6 +645,13 @@ export const data: Array = icon: 'icon-book-alt', groupKey: 'demo-block-group-id', }, + { + label: 'Test broken group key', + contentElementTypeKey: 'test-block-id', + editorSize: 'medium', + icon: 'icon-war', + groupKey: 'group-id-that-does-not-exist', + }, ], }, ], diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts index 921463a1ca..540eb77371 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts @@ -1496,4 +1496,31 @@ export const data: Array = [ properties: [], containers: [], }, + { + type: 'document-type', + allowedTemplateIds: [], + defaultTemplateId: null, + id: 'test-block-id', + alias: 'testBlock', + name: 'Test broken group key', + description: null, + icon: 'icon-war', + allowedAsRoot: true, + variesByCulture: false, + variesBySegment: false, + isElement: true, + hasChildren: false, + isContainer: false, + parentId: null, + isFolder: false, + allowedContentTypes: [], + compositions: [], + cleanup: { + preventCleanup: false, + keepAllVersionsNewerThanDays: null, + keepLatestVersionPerDayForDays: null, + }, + properties: [], + containers: [], + }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index cae3b17d09..d761a60745 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -57,6 +57,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement // Look for values without a group, or with a group that is non existent. (value) => !value.groupKey || this._blockGroups.find((group) => group.key !== value.groupKey), ); + //.map((value) => ({ ...value, groupKey: undefined })); const valuesWithGroup = this._blockGroups.map((group) => { return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; @@ -66,9 +67,14 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement } #onChange(e: Event, groupKey?: string) { - const newValue = (e.target as UmbInputBlockTypeElement).value; - const values = this.value.filter((item) => item.groupKey !== groupKey); - this.value = [...values, ...newValue]; + const newValues = (e.target as UmbInputBlockTypeElement).value; + + // remove all values that are in the group, or have a group that does not exist in the block groups. + const values = this.value + .filter((b) => b.groupKey !== groupKey) + .filter((b) => this._blockGroups.find((group) => group.key === b.groupKey)); + + this.value = [...values, ...newValues]; this.dispatchEvent(new CustomEvent('property-value-change')); } From 0b36a405dd4ea7e2761482b3bc7a627cf05f1675 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:23:56 +0100 Subject: [PATCH 07/81] remove leftovers --- ...i-block-grid-type-configuration.element.ts | 14 +------ .../input-block-type.element.ts | 41 ++++++++++--------- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index d761a60745..0282db6938 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -44,11 +44,9 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this.observe(await this.#datasetContext.propertyValueByAlias('blockGroups'), (value) => { this._blockGroups = value as Array; this.#mapValuesToBlockGroups(); - console.log('groups changed', value); }); - this.observe(await this.#datasetContext.propertyValueByAlias('blocks'), (value) => { + this.observe(await this.#datasetContext.propertyValueByAlias('blocks'), () => { this.#mapValuesToBlockGroups(); - console.log('value changed', value); }); } @@ -57,7 +55,6 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement // Look for values without a group, or with a group that is non existent. (value) => !value.groupKey || this._blockGroups.find((group) => group.key !== value.groupKey), ); - //.map((value) => ({ ...value, groupKey: undefined })); const valuesWithGroup = this._blockGroups.map((group) => { return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; @@ -92,15 +89,6 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement )}`; } - /* - render() { - return html` (this.value = (e.target as UmbInputBlockTypeElement).value)}>`; - }*/ - static styles = [ UmbTextStyles, css` diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index b8ec0604e8..8337b90f0f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -126,6 +126,27 @@ export class UmbInputBlockTypeElement< `; } + #renderItem = (item: BlockType) => { + return html` + this.deleteItem(item.contentElementTypeKey)}> + + `; + }; + + #renderButton() { + return html` + this.create()} label="open"> + + Add + + `; + } + + //Group renders (if exists) + #renderGroupInput() { if (!this.groupKey) return; return html` @@ -153,28 +174,8 @@ export class UmbInputBlockTypeElement< ); this.value = this._items.filter((block) => block.groupKey !== this.groupKey); this.dispatchEvent(new UmbChangeEvent()); - console.log(this.value); } - #renderButton() { - return html` - this.create()} label="open"> - - Add - - `; - } - - #renderItem = (item: BlockType) => { - return html` - this.deleteItem(item.contentElementTypeKey)}> - - `; - }; - static styles = [ css` div { From 288d9e0a759763dc65441bea2f3314e677f90edb Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:28:41 +0100 Subject: [PATCH 08/81] fix group type in group config --- ...ty-editor-ui-block-grid-group-configuration.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts index b5f896a42d..ea8b94c594 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts @@ -4,20 +4,20 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbId } from '@umbraco-cms/backoffice/id'; -import { BlockGridGroupConfigration } from '@umbraco-cms/backoffice/block'; +import { UmbBlockGridGroupType } from '@umbraco-cms/backoffice/block'; @customElement('umb-property-editor-ui-block-grid-group-configuration') export class UmbPropertyEditorUIBlockGridGroupConfigurationElement extends UmbLitElement implements UmbPropertyEditorUiElement { - private _value: Array = []; + private _value: Array = []; @property({ type: Array }) - public get value(): Array { + public get value(): Array { return this._value; } - public set value(value: Array) { + public set value(value: Array) { this._value = value || []; } From 1c7382b95b57feab60f1a824b89b4976bcdaa250 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:32:41 +0100 Subject: [PATCH 09/81] filter fix --- ...rty-editor-ui-block-grid-type-configuration.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 0282db6938..b4ff316d7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -67,10 +67,10 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement const newValues = (e.target as UmbInputBlockTypeElement).value; // remove all values that are in the group, or have a group that does not exist in the block groups. - const values = this.value - .filter((b) => b.groupKey !== groupKey) - .filter((b) => this._blockGroups.find((group) => group.key === b.groupKey)); - + let values = this.value.filter((b) => b.groupKey !== groupKey); + if (!groupKey) { + values = values.filter((b) => this._blockGroups.find((group) => group.key === b.groupKey)); + } this.value = [...values, ...newValues]; this.dispatchEvent(new CustomEvent('property-value-change')); } From 90ae3682dffb1f2571fc4ed4a34ab94dbe401728 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Sun, 21 Jan 2024 15:01:53 +0100 Subject: [PATCH 10/81] types --- .../src/packages/block/block-grid/types.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 b6c2e2a02e..0b2771f457 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,6 +1,6 @@ import type { UmbBlockTypeBase, UmbBlockTypeWithGroupKey } from '../block-type/index.js'; -export interface UmbBlockGridType extends UmbBlockTypeBase { +export interface UmbBlockGridType extends UmbBlockTypeWithGroupKey { columnSpanOptions: Array; allowAtRoot: boolean; allowInAreas: boolean; @@ -9,7 +9,6 @@ export interface UmbBlockGridType extends UmbBlockTypeBase { thumbnail?: string; areaGridColumns?: number; areas: Array; - groupKey: null | string; } export interface UmbBlockGridGroupType { From 038f4fc1c26766559e8483243a75d70b09c09cf8 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Sun, 21 Jan 2024 15:29:32 +0100 Subject: [PATCH 11/81] move grouping to property editor rather than component --- ...i-block-grid-type-configuration.element.ts | 46 +++++++++++++--- .../src/packages/block/block-grid/types.ts | 2 +- .../input-block-type.element.ts | 53 ++----------------- 3 files changed, 45 insertions(+), 56 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index b4ff316d7a..e74c52cce4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -1,12 +1,13 @@ import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, property, state, css, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, state, css, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UmbBlockGridGroupType, UmbBlockGridGroupTypeConfiguration } from '@umbraco-cms/backoffice/block'; +import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; /** * @element umb-property-editor-ui-block-grid-type-configuration @@ -80,15 +81,46 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this._mappedValuesAndGroups, (group) => group.key, (group) => - html` this.#onChange(e, group.key)}>`, + html`${group.key ? this.#renderGroupInput(group.key, group.name) : nothing} + this.#onChange(e, group.key)}>`, )}`; } + #changeGroupName(e: UUIInputEvent, groupKey: string) { + const groupName = e.target.value as string; + this.#datasetContext?.setPropertyValue( + 'blockGroups', + this._blockGroups.map((group) => ({ ...group, groupName: groupKey === group.key ? groupName : group.name })), + ); + } + + #deleteGroup(groupKey: string) { + this.#datasetContext?.setPropertyValue( + 'blockGroups', + this._blockGroups.filter((group) => group.key !== groupKey), + ); + + // Should blocks that belonged to the removed group be deleted as well? + this.value = this.value.filter((block) => block.groupKey !== groupKey); + } + + #renderGroupInput(groupKey: string, groupName?: string) { + return html` this.#changeGroupName(e, groupKey)}> + this.#deleteGroup(groupKey)}> + + + `; + } + static styles = [ UmbTextStyles, css` 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 0b2771f457..41778daab8 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,4 +1,4 @@ -import type { UmbBlockTypeBase, UmbBlockTypeWithGroupKey } from '../block-type/index.js'; +import type { UmbBlockTypeWithGroupKey } from '../block-type/index.js'; export interface UmbBlockGridType extends UmbBlockTypeWithGroupKey { columnSpanOptions: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 8337b90f0f..ac790ef928 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -1,4 +1,4 @@ -import { UmbBlockTypeBase, UmbBlockTypeGroup, UmbBlockTypeWithGroupKey } from '../../types.js'; +import { UmbBlockTypeBase, UmbBlockTypeWithGroupKey } from '../../types.js'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT_TOKEN, @@ -9,7 +9,6 @@ import '../block-type-card/index.js'; import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UmbBlockGridType } from '@umbraco-cms/backoffice/block'; @@ -25,12 +24,6 @@ export class UmbInputBlockTypeElement< this._items = items ?? []; } - @property() - groupKey?: string; - - @property() - groupName?: string; - @property({ type: String, attribute: 'entity-type' }) public get entityType() { return this.#entityType; @@ -67,16 +60,12 @@ export class UmbInputBlockTypeElement< >; #datasetContext?: UmbPropertyDatasetContext; - #blockGroups: Array = []; - #filter?: any; + #filter: Array = []; constructor() { super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { this.#datasetContext = instance; - this.observe(await this.#datasetContext?.propertyValueByAlias('blockGroups'), (value) => { - this.#blockGroups = value as Array; - }); this.observe(await this.#datasetContext?.propertyValueByAlias('blocks'), (value) => { this.#filter = value as Array; }); @@ -120,10 +109,9 @@ export class UmbInputBlockTypeElement< } render() { - return html`${this.#renderGroupInput()} -
- ${repeat(this.value, (block) => block.contentElementTypeKey, this.#renderItem)} ${this.#renderButton()} -
`; + return html`
+ ${repeat(this.value, (block) => block.contentElementTypeKey, this.#renderItem)} ${this.#renderButton()} +
`; } #renderItem = (item: BlockType) => { @@ -145,37 +133,6 @@ export class UmbInputBlockTypeElement< `; } - //Group renders (if exists) - - #renderGroupInput() { - if (!this.groupKey) return; - return html` - - - - `; - } - - #changeGroupName(e: UUIInputEvent) { - if (!this.groupKey) return; - - const groupName = e.target.value as string; - this.#datasetContext?.setPropertyValue( - 'blockGroups', - this.#blockGroups.map((group) => ({ ...group, groupName: this.groupKey === group.key ? groupName : group.name })), - ); - } - - #deleteGroup() { - if (!this.groupKey) return; - this.#datasetContext?.setPropertyValue( - 'blockGroups', - this.#blockGroups.filter((group) => group.key !== this.groupKey), - ); - this.value = this._items.filter((block) => block.groupKey !== this.groupKey); - this.dispatchEvent(new UmbChangeEvent()); - } - static styles = [ css` div { From 5411d0e872d4eed944eeea74dda161d139e4f21d Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Sun, 21 Jan 2024 15:38:27 +0100 Subject: [PATCH 12/81] remove events --- ...i-block-grid-type-configuration.element.ts | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index e74c52cce4..d7aed09461 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -52,10 +52,8 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement } #mapValuesToBlockGroups() { - const valuesWithNoGroup = this.value.filter( - // Look for values without a group, or with a group that is non existent. - (value) => !value.groupKey || this._blockGroups.find((group) => group.key !== value.groupKey), - ); + // What if a block is in a group that does not exist in the block groups? Should it be removed? (Right now they will never be rendered) + const valuesWithNoGroup = this.value.filter((value) => !value.groupKey); const valuesWithGroup = this._blockGroups.map((group) => { return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; @@ -64,30 +62,13 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup]; } - #onChange(e: Event, groupKey?: string) { - const newValues = (e.target as UmbInputBlockTypeElement).value; - - // remove all values that are in the group, or have a group that does not exist in the block groups. - let values = this.value.filter((b) => b.groupKey !== groupKey); - if (!groupKey) { - values = values.filter((b) => this._blockGroups.find((group) => group.key === b.groupKey)); - } - this.value = [...values, ...newValues]; - this.dispatchEvent(new CustomEvent('property-value-change')); - } - render() { return html`${repeat( this._mappedValuesAndGroups, (group) => group.key, (group) => html`${group.key ? this.#renderGroupInput(group.key, group.name) : nothing} - this.#onChange(e, group.key)}>`, + `, )}`; } From 100ac1284024c6ff45d6251dfe23fdc1ba3122a2 Mon Sep 17 00:00:00 2001 From: Markus Johansson Date: Mon, 22 Jan 2024 00:01:55 +0100 Subject: [PATCH 13/81] #1136 update rte when value changes --- .../input-tiny-mce/input-tiny-mce.element.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts index 7ef6f439f7..656bbd7b52 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts @@ -42,6 +42,19 @@ export class UmbInputTinyMceElement extends FormControlMixin(UmbLitElement) { return this._editorElement?.querySelector('iframe') ?? undefined; } + set value(newValue: FormDataEntryValue | FormData) { + this._value = newValue; + const newContent = newValue?.toString() ?? ''; + + if(this.#editorRef && this.#editorRef.getContent() != newContent) { + this.#editorRef.setContent(newContent); + } + } + + get value(): FormDataEntryValue | FormData { + return this._value; + } + @query('#editor', true) private _editorElement?: HTMLElement; From 1e5d751d59ffcc91b05ec5b5787a7cf4e7e8e7bb Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 23 Jan 2024 13:42:21 +0100 Subject: [PATCH 14/81] save grouping --- ...ui-block-grid-type-configuration.element.ts | 18 ++++++++++++------ .../input-block-type.element.ts | 4 +++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 32e9dc2de4..f63568ff1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -19,8 +19,14 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement { #datasetContext?: UmbPropertyDatasetContext; + private _value: Array = []; @property({ attribute: false }) - value: UmbBlockTypeWithGroupKey[] = []; + get value() { + return this._value; + } + set value(value: Array) { + this._value = value ?? []; + } @property({ type: Object, attribute: false }) public config?: UmbPropertyEditorConfigCollection; @@ -43,7 +49,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement if (!this.#datasetContext) return; this.observe(await this.#datasetContext.propertyValueByAlias('blockGroups'), (value) => { - this._blockGroups = value as Array; + this._blockGroups = (value as Array) ?? []; this.#mapValuesToBlockGroups(); }); this.observe(await this.#datasetContext.propertyValueByAlias('blocks'), () => { @@ -53,10 +59,10 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement #mapValuesToBlockGroups() { // What if a block is in a group that does not exist in the block groups? Should it be removed? (Right now they will never be rendered) - const valuesWithNoGroup = this.value.filter((value) => !value.groupKey); + const valuesWithNoGroup = this._value.filter((value) => !value.groupKey); const valuesWithGroup = this._blockGroups.map((group) => { - return { name: group.name, key: group.key, blocks: this.value.filter((value) => value.groupKey === group.key) }; + return { name: group.name, key: group.key, blocks: this._value.filter((value) => value.groupKey === group.key) }; }); this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup]; @@ -76,7 +82,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement const groupName = e.target.value as string; this.#datasetContext?.setPropertyValue( 'blockGroups', - this._blockGroups.map((group) => ({ ...group, groupName: groupKey === group.key ? groupName : group.name })), + this._blockGroups.map((group) => (group.key === groupKey ? { ...group, name: groupName } : group)), ); } @@ -87,7 +93,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement ); // Should blocks that belonged to the removed group be deleted as well? - this.value = this.value.filter((block) => block.groupKey !== groupKey); + this.value = this._value.filter((block) => block.groupKey !== groupKey); } #renderGroupInput(groupKey: string, groupName?: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 2a3721f41a..186f9b8079 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -59,6 +59,7 @@ export class UmbInputBlockTypeElement< typeof UMB_WORKSPACE_MODAL.VALUE >; + /* #datasetContext?: UmbPropertyDatasetContext; #filter: Array = []; @@ -71,6 +72,7 @@ export class UmbInputBlockTypeElement< }); }); } + */ create() { this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, async (modalManager) => { @@ -84,7 +86,7 @@ export class UmbInputBlockTypeElement< // Only pick elements: docType.isElement && // Prevent picking the an already used element type: - this.#filter.find((x) => x.contentElementTypeKey === docType.unique) === undefined, + this._items.find((x) => x.contentElementTypeKey === docType.unique) === undefined, }, }); From 0712399676f72984d0719b5ee884214105eaf8b7 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:48:59 +0100 Subject: [PATCH 15/81] filter --- .../components/input-block-type/input-block-type.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 186f9b8079..2a3721f41a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -59,7 +59,6 @@ export class UmbInputBlockTypeElement< typeof UMB_WORKSPACE_MODAL.VALUE >; - /* #datasetContext?: UmbPropertyDatasetContext; #filter: Array = []; @@ -72,7 +71,6 @@ export class UmbInputBlockTypeElement< }); }); } - */ create() { this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, async (modalManager) => { @@ -86,7 +84,7 @@ export class UmbInputBlockTypeElement< // Only pick elements: docType.isElement && // Prevent picking the an already used element type: - this._items.find((x) => x.contentElementTypeKey === docType.unique) === undefined, + this.#filter.find((x) => x.contentElementTypeKey === docType.unique) === undefined, }, }); From 3c104d7b2dcc8caa6c169b181fd8415f56a06f70 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:16:42 +0100 Subject: [PATCH 16/81] delete item --- ...or-ui-block-grid-type-configuration.element.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index f63568ff1e..354518ad8d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeWithGroupKey } from '../../../block-type/index.js'; +import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state, css, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; @@ -68,13 +68,24 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup]; } + #onChange(e: CustomEvent, group?: UmbBlockGridGroupTypeConfiguration) { + const groupValues = (e.target as UmbInputBlockTypeElement).value; + const newValues = groupValues.map((value) => ({ ...value, groupKey: group?.key })); + const filteredValues = this._value.filter((block) => block.contentElementTypeKey === group?.key); + this.value = [...filteredValues, ...newValues]; + this.dispatchEvent(new CustomEvent('property-value-change')); + } + render() { return html`${repeat( this._mappedValuesAndGroups, (group) => group.key, (group) => html`${group.key ? this.#renderGroupInput(group.key, group.name) : nothing} - `, + this.#onChange(e, group)}>`, )}`; } From dc7d2110ec9db475a7af4c0c1c9208c37c0c0700 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:36:29 +0100 Subject: [PATCH 17/81] remove build error --- .../src/mocks/data/document-type/document-type.data.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts index 2d6f01db6c..800e58907a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts @@ -1488,7 +1488,6 @@ export const data: Array = [ containers: [], }, { - type: 'document-type', allowedTemplateIds: [], defaultTemplateId: null, id: 'test-block-id', From d67f71b7ffcef5df086d355a52f1c38535d6cc62 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:36:58 +0100 Subject: [PATCH 18/81] delete event possibility --- ...editor-ui-block-grid-type-configuration.element.ts | 11 +++++++++-- .../src/packages/block/block-type/components/index.ts | 2 +- .../input-block-type/input-block-type.element.ts | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 354518ad8d..5a6c73b111 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -68,6 +68,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup]; } + /* #onChange(e: CustomEvent, group?: UmbBlockGridGroupTypeConfiguration) { const groupValues = (e.target as UmbInputBlockTypeElement).value; const newValues = groupValues.map((value) => ({ ...value, groupKey: group?.key })); @@ -75,6 +76,12 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this.value = [...filteredValues, ...newValues]; this.dispatchEvent(new CustomEvent('property-value-change')); } + */ + + #deleteItem(e: CustomEvent) { + this.value = this._value.filter((block) => block.contentElementTypeKey !== e.detail.contentElementTypeKey); + this.dispatchEvent(new CustomEvent('property-value-change')); + } render() { return html`${repeat( @@ -85,7 +92,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this.#onChange(e, group)}>`, + @delete=${this.#deleteItem}>`, )}`; } @@ -112,7 +119,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement auto-width label="Group" .value=${groupName ?? ''} - @change=${(e: UUIInputEvent) => this.#changeGroupName(e, groupKey)}> + @delete=${(e: UUIInputEvent) => this.#changeGroupName(e, groupKey)}> this.#deleteGroup(groupKey)}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/index.ts index fcdafe77a5..2ce6e9bff7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/index.ts @@ -1,2 +1,2 @@ -export * from './input-block-type/index.js'; export * from './block-type-card/index.js'; +export * from './input-block-type/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 2a3721f41a..2dc6c57e31 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -101,7 +101,8 @@ export class UmbInputBlockTypeElement< deleteItem(contentElementTypeKey: string) { this.value = this._items.filter((x) => x.contentElementTypeKey !== contentElementTypeKey); - this.dispatchEvent(new UmbChangeEvent()); + this.dispatchEvent(new CustomEvent('delete', { detail: { contentElementTypeKey } })); + //this.dispatchEvent(new UmbChangeEvent()); } protected getFormElement() { From ef942a9ee06cd7ca3d7ea2adc0d98a617a0e06d4 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:31:07 +0100 Subject: [PATCH 19/81] move grouping methods --- ...i-block-grid-type-configuration.element.ts | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 5a6c73b111..e7355d9e4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -2,7 +2,10 @@ import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../. import '../../../block-type/components/input-block-type/index.js'; import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state, css, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; -import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UmbPropertyEditorConfigCollection, + UmbPropertyValueChangeEvent, +} from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; @@ -80,7 +83,25 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement #deleteItem(e: CustomEvent) { this.value = this._value.filter((block) => block.contentElementTypeKey !== e.detail.contentElementTypeKey); - this.dispatchEvent(new CustomEvent('property-value-change')); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + + #deleteGroup(groupKey: string) { + this.#datasetContext?.setPropertyValue( + 'blockGroups', + this._blockGroups.filter((group) => group.key !== groupKey), + ); + + // Should blocks that belonged to the removed group be deleted as well? + this.value = this._value.filter((block) => block.groupKey !== groupKey); + } + + #changeGroupName(e: UUIInputEvent, groupKey: string) { + const groupName = e.target.value as string; + this.#datasetContext?.setPropertyValue( + 'blockGroups', + this._blockGroups.map((group) => (group.key === groupKey ? { ...group, name: groupName } : group)), + ); } render() { @@ -96,24 +117,6 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement )}`; } - #changeGroupName(e: UUIInputEvent, groupKey: string) { - const groupName = e.target.value as string; - this.#datasetContext?.setPropertyValue( - 'blockGroups', - this._blockGroups.map((group) => (group.key === groupKey ? { ...group, name: groupName } : group)), - ); - } - - #deleteGroup(groupKey: string) { - this.#datasetContext?.setPropertyValue( - 'blockGroups', - this._blockGroups.filter((group) => group.key !== groupKey), - ); - - // Should blocks that belonged to the removed group be deleted as well? - this.value = this._value.filter((block) => block.groupKey !== groupKey); - } - #renderGroupInput(groupKey: string, groupName?: string) { return html` Date: Wed, 24 Jan 2024 13:27:19 +0100 Subject: [PATCH 20/81] add entityType to action event and rename --- .../src/packages/core/action/action.event.ts | 24 ------------------- .../src/packages/core/action/index.ts | 1 - .../core/entity-action/entity-action.event.ts | 23 ++++++++++++++++++ .../src/packages/core/tree/event/index.ts | 1 + 4 files changed, 24 insertions(+), 25 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/action/action.event.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.event.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/action/action.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/action/action.event.ts deleted file mode 100644 index 98a6a7713b..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/action/action.event.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { UmbControllerEvent } from '@umbraco-cms/backoffice/controller-api'; - -export interface UmbActionEventArgs { - unique: string; - parentUnique: string | null; // TODO: remove this when we have endpoints to support mapping a new item without reloading the parent tree item -} - -export class UmbActionEvent extends UmbControllerEvent { - #args: UmbActionEventArgs; - - public constructor(type: string, args: UmbActionEventArgs) { - super(type); - this.#args = args; - } - - getUnique(): string { - return this.#args.unique; - } - - // TODO: this can be removed when the server supports reloading a tree item without reloading the parent - getParentUnique(): string | null { - return this.#args.parentUnique; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/action/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/action/index.ts index 05f892981b..79e8f1b8b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/action/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/action/index.ts @@ -1,4 +1,3 @@ export * from './repository-action.js'; export * from './action.interface.js'; export * from './action-event.context.js'; -export * from './action.event.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.event.ts new file mode 100644 index 0000000000..4eafc96b78 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.event.ts @@ -0,0 +1,23 @@ +import { UmbControllerEvent } from '@umbraco-cms/backoffice/controller-api'; + +export interface UmbEntityActionEventArgs { + unique: string; + entityType: string; +} + +export class UmbEntityActionEvent extends UmbControllerEvent { + #args: UmbEntityActionEventArgs; + + public constructor(type: string, args: UmbEntityActionEventArgs) { + super(type); + this.#args = args; + } + + getEntityType(): string { + return this.#args.entityType; + } + + getUnique(): string { + return this.#args.unique; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts new file mode 100644 index 0000000000..7dfd86c752 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts @@ -0,0 +1 @@ +export * from './reload-tree-item-request.event.js'; From df615d59a665165bf471c77a17cc2d4d00fb1caf Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 13:28:21 +0100 Subject: [PATCH 21/81] pass entity type to entity action --- .../entity-action-list.element.ts | 2 +- .../entity-action/entity-action.element.ts | 23 ++++++++++++++++++- .../core/entity-action/entity-action.ts | 4 +++- .../src/packages/core/entity-action/index.ts | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.element.ts index ba1ba45f2d..30321523c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.element.ts @@ -30,7 +30,7 @@ export class UmbEntityActionListElement extends UmbLitElement { type="entityAction" default-element="umb-entity-action" .filter=${this._filter} - .props=${{ unique: this.unique }}> + .props=${{ unique: this.unique, entityType: this.entityType }}> ` : ''; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts index 84656822a9..4e79806f99 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts @@ -7,6 +7,20 @@ import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; @customElement('umb-entity-action') export class UmbEntityActionElement extends UmbLitElement { + private _entityType?: string | null; + @property({ type: String }) + public get entityType() { + return this._entityType; + } + public set entityType(value: string | undefined | null) { + const oldValue = this._entityType; + this._entityType = value; + if (oldValue !== this._entityType) { + this.#createApi(); + this.requestUpdate('entityType', oldValue); + } + } + private _unique?: string | null; @property({ type: String }) public get unique() { @@ -37,10 +51,17 @@ export class UmbEntityActionElement extends UmbLitElement { } async #createApi() { + // only create the api if we have all the required properties if (!this._manifest) return; if (this._unique === undefined) return; + if (!this._entityType) return; - this.#api = await createExtensionApi(this._manifest, [this, this._manifest.meta.repositoryAlias, this.unique]); + this.#api = await createExtensionApi(this._manifest, [ + this, + this._manifest.meta.repositoryAlias, + this.unique, + this.entityType, + ]); // TODO: Fix so when we use a HREF it does not refresh the page? this._href = await this.#api.getHref?.(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.ts index 17ecb2eed6..c62a45d01b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.ts @@ -6,11 +6,13 @@ export interface UmbEntityAction extends UmbAction extends UmbActionBase { + entityType: string; unique: string; repositoryAlias: string; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { super(host, repositoryAlias); + this.entityType = entityType; this.unique = unique; this.repositoryAlias = repositoryAlias; } 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 3bc2e27029..194dedab02 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 @@ -2,3 +2,4 @@ export * from './entity-action-list.element.js'; export * from './entity-action.element.js'; export * from './entity-action.js'; export * from './common/index.js'; +export * from './entity-action.event.js'; From 801322d120c8e4eb02a89ac564b856108877e252 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 13:28:43 +0100 Subject: [PATCH 22/81] export event --- src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts index a3c11cfc66..7b0c296661 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts @@ -22,4 +22,7 @@ export * from './data-source/index.js'; // Folder export * from './folder/index.js'; +// Event +export * from './event/index.js'; + export { UmbTreeRepositoryBase } from './tree-repository-base.js'; From 12398d501b12f8b383379d2b0997ab0ba9b9cc86 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 13:29:00 +0100 Subject: [PATCH 23/81] register reload entity action --- .../packages/core/data-type/tree/manifests.ts | 3 ++- .../tree/reload-tree-item/manifests.ts | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts index bee8b4e5ec..0e25aa220c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts @@ -1,4 +1,5 @@ import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as reloadManifests } from './reload-tree-item/manifests.js'; import { UmbDataTypeTreeRepository } from './data-type-tree.repository.js'; import { UmbDataTypeTreeStore } from './data-type-tree.store.js'; import type { @@ -44,4 +45,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests, ...reloadManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts new file mode 100644 index 0000000000..c5c965fa9c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts @@ -0,0 +1,24 @@ +import { + UMB_DATA_TYPE_ENTITY_TYPE, + UMB_DATA_TYPE_FOLDER_ENTITY_TYPE, + UMB_DATA_TYPE_ROOT_ENTITY_TYPE, +} from '../../entity.js'; +import { UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js'; +import { UmbReloadTreeItemChildrenEntityAction } from './reload-tree-item-children.action.js'; +import { type ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.DataType.ReloadTreeItem', + name: 'Reload Data Type Tree Item Entity Action', + weight: 900, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload...', + repositoryAlias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS, + entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE, UMB_DATA_TYPE_ROOT_ENTITY_TYPE, UMB_DATA_TYPE_FOLDER_ENTITY_TYPE], + }, + }, +]; From 4bf35a91ba39ec3108d526f07ec8e84263bcf896 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 13:29:44 +0100 Subject: [PATCH 24/81] add reload entity action that dispatches an event on the action event context --- .../reload-tree-item-children.action.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts new file mode 100644 index 0000000000..e689c598ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts @@ -0,0 +1,27 @@ +import { type UmbCopyDataTypeRepository } from '../../repository/copy/data-type-copy.repository.js'; +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import { UMB_ACTION_EVENT_CONTEXT, UmbActionEventContext } from '@umbraco-cms/backoffice/action'; +import { UmbReloadTreeItemRequestEvent } from '@umbraco-cms/backoffice/tree'; + +export class UmbReloadTreeItemChildrenEntityAction extends UmbEntityActionBase { + #actionEventContext?: UmbActionEventContext; + + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); + + this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (instance) => { + this.#actionEventContext = instance; + }); + } + + async execute() { + if (!this.#actionEventContext) throw new Error('Action Event context is not available'); + this.#actionEventContext.dispatchEvent( + new UmbReloadTreeItemRequestEvent({ + unique: this.unique, + entityType: this.entityType, + }), + ); + } +} From b82394a7e288fe633c6c95b3141d9bf158cbd0b6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 13:30:46 +0100 Subject: [PATCH 25/81] add reload event class --- .../reload-tree-item/reload-tree-item-children.action.ts | 4 ++-- .../core/tree/event/reload-tree-item-request.event.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/tree/event/reload-tree-item-request.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts index e689c598ed..138d8a5015 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts @@ -2,7 +2,7 @@ import { type UmbCopyDataTypeRepository } from '../../repository/copy/data-type- import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UMB_ACTION_EVENT_CONTEXT, UmbActionEventContext } from '@umbraco-cms/backoffice/action'; -import { UmbReloadTreeItemRequestEvent } from '@umbraco-cms/backoffice/tree'; +import { UmbReloadTreeItemRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree'; export class UmbReloadTreeItemChildrenEntityAction extends UmbEntityActionBase { #actionEventContext?: UmbActionEventContext; @@ -18,7 +18,7 @@ export class UmbReloadTreeItemChildrenEntityAction extends UmbEntityActionBase Date: Wed, 24 Jan 2024 13:31:08 +0100 Subject: [PATCH 26/81] listen for the reload request event in a tree item context --- .../tree-item-base/tree-item-base.context.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts index 81c6d5fb4c..b6190bfb46 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts @@ -9,6 +9,9 @@ import { UmbBooleanState, UmbDeepState, UmbStringState } from '@umbraco-cms/back import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UMB_ACTION_EVENT_CONTEXT, UmbActionEventContext } from '@umbraco-cms/backoffice/action'; +import { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbReloadTreeItemRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree'; export type UmbTreeItemUniqueFunction = ( x: TreeItemType, @@ -52,6 +55,7 @@ export class UmbTreeItemContextBase treeContext?: UmbTreeContextBase; #sectionContext?: UmbSectionContext; #sectionSidebarContext?: UmbSectionSidebarContext; + #actionEventContext?: UmbActionEventContext; #getUniqueFunction: UmbTreeItemUniqueFunction; constructor(host: UmbControllerHost, getUniqueFunction: UmbTreeItemUniqueFunction) { @@ -129,6 +133,18 @@ export class UmbTreeItemContextBase this.#observeIsSelected(); this.#observeHasChildren(); }); + + this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (instance) => { + this.#actionEventContext = instance; + this.#actionEventContext.removeEventListener( + UmbReloadTreeItemRequestEntityActionEvent.TYPE, + this.#onReloadRequest as EventListener, + ); + this.#actionEventContext.addEventListener( + UmbReloadTreeItemRequestEntityActionEvent.TYPE, + this.#onReloadRequest as EventListener, + ); + }); } getTreeItem() { @@ -206,6 +222,13 @@ export class UmbTreeItemContextBase }); } + #onReloadRequest = (event: UmbEntityActionEvent) => { + if (this.unique === undefined) return; + if (event.getUnique() !== this.unique) return; + if (event.getEntityType() !== this.entityType) return; + this.requestChildren(); + }; + // TODO: use router context constructPath(pathname: string, entityType: string, unique: string | null) { return `section/${pathname}/workspace/${entityType}/edit/${unique}`; From c9cb041975727df1b87c6c78571c5d33f714dea3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 13:44:05 +0100 Subject: [PATCH 27/81] accept entityType as argument --- .../core/data-type/entity-actions/copy/copy.action.ts | 4 ++-- .../core/data-type/entity-actions/create/create.action.ts | 4 ++-- .../core/data-type/entity-actions/move/move.action.ts | 4 ++-- .../packages/core/entity-action/common/copy/copy.action.ts | 4 ++-- .../core/entity-action/common/delete/delete.action.ts | 4 ++-- .../packages/core/entity-action/common/move/move.action.ts | 4 ++-- .../core/entity-action/common/rename/rename.action.ts | 4 ++-- .../common/sort-children-of/sort-children-of.action.ts | 4 ++-- .../packages/core/entity-action/common/trash/trash.action.ts | 4 ++-- .../entity-action/create-folder/create-folder.action.ts | 4 ++-- .../entity-action/delete-folder/delete-folder.action.ts | 4 ++-- .../entity-action/folder-update/folder-update.action.ts | 4 ++-- .../dictionary/entity-actions/create/create.action.ts | 4 ++-- .../dictionary/entity-actions/export/export.action.ts | 4 ++-- .../dictionary/entity-actions/import/import.action.ts | 4 ++-- .../dictionary/dictionary/entity-actions/reload.action.ts | 4 ++-- .../document-types/entity-actions/create/create.action.ts | 4 ++-- .../documents/entity-actions/create-blueprint.action.ts | 4 ++-- .../documents/entity-actions/create/create.action.ts | 4 ++-- .../documents/entity-actions/culture-and-hostnames.action.ts | 4 ++-- .../entity-actions/permissions/permissions.action.ts | 4 ++-- .../documents/entity-actions/public-access.action.ts | 4 ++-- .../documents/documents/entity-actions/publish.action.ts | 4 ++-- .../documents/documents/entity-actions/rollback.action.ts | 4 ++-- .../documents/documents/entity-actions/unpublish.action.ts | 4 ++-- .../media/media-types/entity-actions/create/create.action.ts | 4 ++-- .../relations/relation-types/entity-actions/create.action.ts | 4 ++-- .../languages/entity-actions/language-create-entity-action.ts | 4 ++-- .../partial-views/entity-actions/create/create.action.ts | 4 ++-- .../templating/scripts/entity-actions/create/create.action.ts | 4 ++-- .../stylesheets/entity-actions/create/create.action.ts | 4 ++-- .../templates/entity-actions/create/create.action.ts | 4 ++-- .../change-password/change-user-password.action.ts | 4 ++-- .../user/user/entity-actions/disable/disable-user.action.ts | 4 ++-- .../user/user/entity-actions/enable/enable-user.action.ts | 4 ++-- .../user/user/entity-actions/unlock/unlock-user.action.ts | 4 ++-- .../entity-action/resend-invite/resend-invite.action.ts | 4 ++-- 37 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/copy/copy.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/copy/copy.action.ts index bc50ca6c71..4311e7c675 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/copy/copy.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/copy/copy.action.ts @@ -11,8 +11,8 @@ import { export class UmbCopyDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/create/create.action.ts index df5ec45503..00ae6d0f3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/create/create.action.ts @@ -7,8 +7,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/move/move.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/move/move.action.ts index 1ecd58718e..3786b8d9da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/move/move.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/entity-actions/move/move.action.ts @@ -11,8 +11,8 @@ import { export class UmbMoveDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/copy/copy.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/copy/copy.action.ts index eca7e06460..a032704347 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/copy/copy.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/copy/copy.action.ts @@ -2,8 +2,8 @@ import { UmbEntityActionBase } from '../../entity-action.js'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbCopyEntityAction }> extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.ts index 8be1c44ed9..79a93eb029 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/delete/delete.action.ts @@ -13,8 +13,8 @@ export class UmbDeleteEntityAction< > extends UmbEntityActionBase { #modalManager?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); new UmbContextConsumerController(this._host, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManager = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts index 8f7f6c49a1..feac2ed27c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/move/move.action.ts @@ -4,8 +4,8 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api // TODO: investigate what we need to finish the generic move action. We would need to open a picker, which requires a modal token, // maybe we can use kinds to make a specific manifest to the move action. export class UmbMoveEntityAction }> extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/rename/rename.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/rename/rename.action.ts index 42621775d2..7100dd50d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/rename/rename.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/rename/rename.action.ts @@ -7,8 +7,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbRenameEntityAction extends UmbEntityActionBase> { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/sort-children-of/sort-children-of.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/sort-children-of/sort-children-of.action.ts index 5170df11cf..bd658e96bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/sort-children-of/sort-children-of.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/sort-children-of/sort-children-of.action.ts @@ -4,8 +4,8 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api export class UmbSortChildrenOfEntityAction< T extends { sortChildrenOf(): Promise }, > extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts index 4b6c8bb08c..1b790bde59 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/common/trash/trash.action.ts @@ -13,8 +13,8 @@ export class UmbTrashEntityAction< > extends UmbEntityActionBase { #modalContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); new UmbContextConsumerController(this._host, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/create-folder.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/create-folder.action.ts index 28a474da8a..ea44034400 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/create-folder.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/create-folder/create-folder.action.ts @@ -7,8 +7,8 @@ import { type UmbFolderRepository, UMB_FOLDER_CREATE_MODAL } from '@umbraco-cms/ export class UmbCreateFolderEntityAction extends UmbEntityActionBase { #modalContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); new UmbContextConsumerController(this._host, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/delete-folder.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/delete-folder.action.ts index a1bc34892c..2f0d4e4798 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/delete-folder.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/delete-folder/delete-folder.action.ts @@ -11,8 +11,8 @@ import { UmbFolderRepository } from '@umbraco-cms/backoffice/tree'; export class UmbDeleteFolderEntityAction extends UmbEntityActionBase { #modalContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); new UmbContextConsumerController(this._host, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/folder-update/folder-update.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/folder-update/folder-update.action.ts index e3e2b4b78e..8d2a024a4f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/folder-update/folder-update.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/folder/entity-action/folder-update/folder-update.action.ts @@ -9,8 +9,8 @@ export class UmbFolderUpdateEntityAction< > extends UmbEntityActionBase { #modalContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); new UmbContextConsumerController(this._host, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/create/create.action.ts index 7eed91c078..461c995f75 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/create/create.action.ts @@ -6,8 +6,8 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api export default class UmbCreateDictionaryEntityAction extends UmbEntityActionBase { static styles = [UmbTextStyles]; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/export/export.action.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/export/export.action.ts index ca5eb554bf..e602e08fd0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/export/export.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/export/export.action.ts @@ -13,8 +13,8 @@ export default class UmbExportDictionaryEntityAction extends UmbEntityActionBase #modalContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/import/import.action.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/import/import.action.ts index 06cde9e29e..cf41e0a1ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/import/import.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/import/import.action.ts @@ -15,8 +15,8 @@ export default class UmbImportDictionaryEntityAction extends UmbEntityActionBase #modalContext?: UmbModalManagerContext; #treeStore?: UmbDictionaryTreeStore; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts index 95ef56cffa..316f7f1123 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts @@ -6,8 +6,8 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api export default class UmbReloadDictionaryEntityAction extends UmbEntityActionBase { static styles = [UmbTextStyles]; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts index 5c3cc0ad17..9a309fe197 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts @@ -7,8 +7,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint.action.ts index 88685471a5..5b85f28c38 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint.action.ts @@ -3,8 +3,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbCreateDocumentBlueprintEntityAction extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts index abd6f5b4cc..cb434da7a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts @@ -10,8 +10,8 @@ import { export class UmbCreateDocumentEntityAction extends UmbEntityActionBase { #modalContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames.action.ts index 01932ae60e..3e1560936d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames.action.ts @@ -3,8 +3,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbDocumentCultureAndHostnamesEntityAction extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions.action.ts index 21714c9c0d..b8e77991ab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions.action.ts @@ -10,8 +10,8 @@ import { export class UmbDocumentPermissionsEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access.action.ts index 0d4b7eafda..45b770996c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access.action.ts @@ -3,8 +3,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbDocumentPublicAccessEntityAction extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/publish.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/publish.action.ts index d00aba2a98..32a99627a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/publish.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/publish.action.ts @@ -3,8 +3,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbPublishDocumentEntityAction extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/rollback.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/rollback.action.ts index d6c8e6ff2a..e30a449a33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/rollback.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/rollback.action.ts @@ -3,8 +3,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbRollbackDocumentEntityAction extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { 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 1940fa8862..474a41f1c3 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 @@ -3,8 +3,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbUnpublishDocumentEntityAction extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts index 43565e0070..c7224b25b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts @@ -7,8 +7,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbCreateMediaTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entity-actions/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entity-actions/create.action.ts index 8a03974269..9fc883014b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entity-actions/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entity-actions/create.action.ts @@ -4,8 +4,8 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api export class UmbCreateRelationTypeEntityAction extends UmbEntityActionBase { // TODO: Could EntityActions take the manifest instead, for more flexibility? - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/entity-actions/language-create-entity-action.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/entity-actions/language-create-entity-action.ts index aae26d3732..4da1312571 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/entity-actions/language-create-entity-action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/entity-actions/language-create-entity-action.ts @@ -4,8 +4,8 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api export class UmbLanguageCreateEntityAction extends UmbEntityActionBase { // TODO: Could EntityActions take the manifest instead, for more flexibility? - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } async execute() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts index 095d522ee6..0658b065b7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts @@ -6,8 +6,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbPartialViewCreateOptionsEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts index 67e3de6dba..8e2f168865 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts @@ -6,8 +6,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbScriptCreateOptionsEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts index d6017d256b..3eb25b0620 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts @@ -6,8 +6,8 @@ import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbrac export class UmbStylesheetCreateOptionsEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManagerContext = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/create/create.action.ts index 4dc38218e1..542d05d609 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/entity-actions/create/create.action.ts @@ -2,8 +2,8 @@ import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; export class UmbCreateEntityAction }> extends UmbEntityActionBase { - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); } // TODO: can we make this a generic create action diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/change-password/change-user-password.action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/change-password/change-user-password.action.ts index 46aac1f7a9..72eeee1cd6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/change-password/change-user-password.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/change-password/change-user-password.action.ts @@ -10,8 +10,8 @@ import { export class UmbChangeUserPasswordEntityAction extends UmbEntityActionBase { #modalManager?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManager = instance; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/disable/disable-user.action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/disable/disable-user.action.ts index d5805553ee..e5c1ab5c7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/disable/disable-user.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/entity-actions/disable/disable-user.action.ts @@ -12,8 +12,8 @@ export class UmbDisableUserEntityAction extends UmbEntityActionBase { #modalManager?: UmbModalManagerContext; - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { - super(host, repositoryAlias, unique); + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { + super(host, repositoryAlias, unique, entityType); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { this.#modalManager = instance; From d0007be910c7fd4c8107a86ec33cd1111054e11b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 14:03:28 +0100 Subject: [PATCH 28/81] pass entity type to doc type folder action --- .../document-types/entity-actions/create/create.action.ts | 1 + .../create/modal/document-type-create-options-modal.element.ts | 1 + .../document-types/entity-actions/create/modal/index.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts index 9a309fe197..01a97fb6d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts @@ -22,6 +22,7 @@ export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase( From 84c46b45c5315685302cca520a0e60412ae416aa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 14:03:39 +0100 Subject: [PATCH 29/81] clean up --- .../stylesheet-create-options-modal.element.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts index 81381c1bf8..4988aeb101 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts @@ -2,11 +2,7 @@ import { UMB_STYLESHEET_FOLDER_REPOSITORY_ALIAS } from '../../../tree/folder/ind import { UmbStylesheetCreateOptionsModalData } from './index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { - UMB_MODAL_MANAGER_CONTEXT_TOKEN, - UmbModalManagerContext, - UmbModalBaseElement, -} from '@umbraco-cms/backoffice/modal'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbCreateFolderEntityAction } from '@umbraco-cms/backoffice/tree'; @customElement('umb-stylesheet-create-options-modal') @@ -14,17 +10,8 @@ export class UmbStylesheetCreateOptionsModalElement extends UmbModalBaseElement< UmbStylesheetCreateOptionsModalData, string > { - #modalManager?: UmbModalManagerContext; #createFolderAction?: UmbCreateFolderEntityAction; - constructor() { - super(); - - this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { - this.#modalManager = instance; - }); - } - connectedCallback(): void { super.connectedCallback(); From 24f1d7b1441554abc8adf7abd69f725b6e0ac4a6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 19:02:12 +0100 Subject: [PATCH 30/81] pass entity type to create options modal + create folder entity action --- .../partial-views/entity-actions/create/create.action.ts | 1 + .../partial-views/entity-actions/create/options-modal/index.ts | 1 + .../options-modal/partial-view-create-options-modal.element.ts | 1 + .../templating/scripts/entity-actions/create/create.action.ts | 1 + .../scripts/entity-actions/create/options-modal/index.ts | 1 + .../create/options-modal/script-create-options-modal.element.ts | 1 + .../stylesheets/entity-actions/create/create.action.ts | 1 + .../stylesheets/entity-actions/create/options-modal/index.ts | 1 + .../options-modal/stylesheet-create-options-modal.element.ts | 1 + 9 files changed, 9 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts index 0658b065b7..92b154e0b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/create.action.ts @@ -21,6 +21,7 @@ export class UmbPartialViewCreateOptionsEntityAction extends UmbEntityActionBase this.#modalManagerContext?.open(UMB_PARTIAL_VIEW_CREATE_OPTIONS_MODAL, { data: { parentUnique: this.unique, + entityType: this.entityType, }, }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/index.ts index eb6016ae1a..0b9c86730b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/index.ts @@ -2,6 +2,7 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbPartialViewCreateOptionsModalData { parentUnique: string | null; + entityType: string; } export const UMB_PARTIAL_VIEW_CREATE_OPTIONS_MODAL = new UmbModalToken( diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/partial-view-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/partial-view-create-options-modal.element.ts index 1f437c1c42..a0f762b79d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/partial-view-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/entity-actions/create/options-modal/partial-view-create-options-modal.element.ts @@ -38,6 +38,7 @@ export class UmbPartialViewCreateOptionsModalElement extends UmbModalBaseElement // @ts-ignore // TODO: allow null for entity actions. Some actions can be executed on the root item this.data.parentUnique, + this.data.entityType, ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts index 8e2f168865..6d3b4b1001 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/create.action.ts @@ -21,6 +21,7 @@ export class UmbScriptCreateOptionsEntityAction extends UmbEntityActionBase( diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/options-modal/script-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/options-modal/script-create-options-modal.element.ts index 582c50e29a..3accdfe3d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/options-modal/script-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/entity-actions/create/options-modal/script-create-options-modal.element.ts @@ -34,6 +34,7 @@ export class UmbScriptCreateOptionsModalElement extends UmbModalBaseElement( diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts index 4988aeb101..bb5e668bd4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/options-modal/stylesheet-create-options-modal.element.ts @@ -24,6 +24,7 @@ export class UmbStylesheetCreateOptionsModalElement extends UmbModalBaseElement< // @ts-ignore // TODO: allow null for entity actions. Some actions can be executed on the root item this.data.parentUnique, + this.data.entityType, ); } From 2610ad97cd210202179d9f1d377406dea65a2842 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 19:04:07 +0100 Subject: [PATCH 31/81] add children to label --- .../packages/core/data-type/tree/reload-tree-item/manifests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts index c5c965fa9c..c5345d22a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts @@ -16,7 +16,7 @@ export const manifests: Array = [ api: UmbReloadTreeItemChildrenEntityAction, meta: { icon: 'icon-refresh', - label: 'Reload...', + label: 'Reload children...', repositoryAlias: UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS, entityTypes: [UMB_DATA_TYPE_ENTITY_TYPE, UMB_DATA_TYPE_ROOT_ENTITY_TYPE, UMB_DATA_TYPE_FOLDER_ENTITY_TYPE], }, From e5e4ba2034f2d3d5614ba54d05f82ecdcc059987 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 19:14:14 +0100 Subject: [PATCH 32/81] move entity action to core tree module --- .../core/data-type/tree/reload-tree-item/manifests.ts | 6 +++--- .../src/packages/core/tree/event/index.ts | 1 - .../core/tree/event/reload-tree-item-request.event.ts | 9 --------- .../src/packages/core/tree/index.ts | 7 +++++-- .../core/tree/reload-tree-item-children/index.ts | 2 ++ .../reload-tree-item-children-request.event.ts | 9 +++++++++ .../reload-tree-item-children.action.ts | 6 +++--- .../core/tree/tree-item-base/tree-item-base.context.ts | 6 +++--- 8 files changed, 25 insertions(+), 21 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/tree/event/reload-tree-item-request.event.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts rename src/Umbraco.Web.UI.Client/src/packages/core/{data-type/tree/reload-tree-item => tree/reload-tree-item-children}/reload-tree-item-children.action.ts (77%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts index c5345d22a6..19c1e46657 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts @@ -4,14 +4,14 @@ import { UMB_DATA_TYPE_ROOT_ENTITY_TYPE, } from '../../entity.js'; import { UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js'; -import { UmbReloadTreeItemChildrenEntityAction } from './reload-tree-item-children.action.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; import { type ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'entityAction', - alias: 'Umb.EntityAction.DataType.ReloadTreeItem', - name: 'Reload Data Type Tree Item Entity Action', + alias: 'Umb.EntityAction.DataType.Tree.ReloadTreeItemChildren', + name: 'Reload Data Type Tree Item Children Entity Action', weight: 900, api: UmbReloadTreeItemChildrenEntityAction, meta: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts deleted file mode 100644 index 7dfd86c752..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './reload-tree-item-request.event.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/reload-tree-item-request.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/reload-tree-item-request.event.ts deleted file mode 100644 index 8e31f536be..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/event/reload-tree-item-request.event.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { UmbEntityActionEvent, UmbEntityActionEventArgs } from '@umbraco-cms/backoffice/entity-action'; - -export class UmbReloadTreeItemRequestEntityActionEvent extends UmbEntityActionEvent { - static readonly TYPE = 'reload-tree-item-request'; - - constructor(args: UmbEntityActionEventArgs) { - super(UmbReloadTreeItemRequestEntityActionEvent.TYPE, args); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts index 7b0c296661..c502da8f77 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts @@ -22,7 +22,10 @@ export * from './data-source/index.js'; // Folder export * from './folder/index.js'; -// Event -export * from './event/index.js'; +// +export { + UmbReloadTreeItemChildrenEntityAction, + UmbReloadTreeItemChildrenRequestEntityActionEvent, +} from './reload-tree-item-children/index.js'; export { UmbTreeRepositoryBase } from './tree-repository-base.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/index.ts new file mode 100644 index 0000000000..14a1621de6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/index.ts @@ -0,0 +1,2 @@ +export { UmbReloadTreeItemChildrenEntityAction } from './reload-tree-item-children.action.js'; +export { UmbReloadTreeItemChildrenRequestEntityActionEvent } from './reload-tree-item-children-request.event.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts new file mode 100644 index 0000000000..7c51f52e74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts @@ -0,0 +1,9 @@ +import { UmbEntityActionEvent, UmbEntityActionEventArgs } from '@umbraco-cms/backoffice/entity-action'; + +export class UmbReloadTreeItemChildrenRequestEntityActionEvent extends UmbEntityActionEvent { + static readonly TYPE = 'reload-tree-item-children-request'; + + constructor(args: UmbEntityActionEventArgs) { + super(UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, args); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts similarity index 77% rename from src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts index 138d8a5015..f1a5bab504 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/reload-tree-item-children.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts @@ -1,8 +1,8 @@ -import { type UmbCopyDataTypeRepository } from '../../repository/copy/data-type-copy.repository.js'; +import { type UmbCopyDataTypeRepository } from '../../data-type/repository/copy/data-type-copy.repository.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UMB_ACTION_EVENT_CONTEXT, UmbActionEventContext } from '@umbraco-cms/backoffice/action'; -import { UmbReloadTreeItemRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree'; +import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree'; export class UmbReloadTreeItemChildrenEntityAction extends UmbEntityActionBase { #actionEventContext?: UmbActionEventContext; @@ -18,7 +18,7 @@ export class UmbReloadTreeItemChildrenEntityAction extends UmbEntityActionBase = ( x: TreeItemType, @@ -137,11 +137,11 @@ export class UmbTreeItemContextBase this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (instance) => { this.#actionEventContext = instance; this.#actionEventContext.removeEventListener( - UmbReloadTreeItemRequestEntityActionEvent.TYPE, + UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, this.#onReloadRequest as EventListener, ); this.#actionEventContext.addEventListener( - UmbReloadTreeItemRequestEntityActionEvent.TYPE, + UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, this.#onReloadRequest as EventListener, ); }); From be4a284448c2bebd628488224a95aa5577b3a04a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 19:24:20 +0100 Subject: [PATCH 33/81] add reload tree item children to dictionary tree --- .../packages/core/data-type/tree/manifests.ts | 2 +- .../manifests.ts | 2 +- .../dictionary/dictionary/entities.ts | 2 -- .../dictionary/entity-actions/manifests.ts | 2 +- .../packages/dictionary/dictionary/entity.ts | 5 +++++ .../dictionary/menu-item/manifests.ts | 2 +- .../tree/dictionary-tree.repository.ts | 2 +- .../dictionary/dictionary/tree/manifests.ts | 5 +++-- .../reload-tree-item-children/manifests.ts | 20 +++++++++++++++++++ .../packages/dictionary/section.manifest.ts | 2 +- 10 files changed, 34 insertions(+), 10 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/{reload-tree-item => reload-tree-item-children}/manifests.ts (98%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entities.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts index 0e25aa220c..6ab730ac33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/manifests.ts @@ -1,5 +1,5 @@ import { manifests as folderManifests } from './folder/manifests.js'; -import { manifests as reloadManifests } from './reload-tree-item/manifests.js'; +import { manifests as reloadManifests } from './reload-tree-item-children/manifests.js'; import { UmbDataTypeTreeRepository } from './data-type-tree.repository.js'; import { UmbDataTypeTreeStore } from './data-type-tree.store.js'; import type { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item-children/manifests.ts similarity index 98% rename from src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item-children/manifests.ts index 19c1e46657..2aca5cd675 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/tree/reload-tree-item-children/manifests.ts @@ -12,7 +12,7 @@ export const manifests: Array = [ type: 'entityAction', alias: 'Umb.EntityAction.DataType.Tree.ReloadTreeItemChildren', name: 'Reload Data Type Tree Item Children Entity Action', - weight: 900, + weight: 10, api: UmbReloadTreeItemChildrenEntityAction, meta: { icon: 'icon-refresh', diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entities.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entities.ts deleted file mode 100644 index b07e1f48a9..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entities.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const UMB_DICTIONARY_ROOT_ENTITY_TYPE = 'dictionary-root'; -export const UMB_DICTIONARY_ENTITY_TYPE = 'dictionary-item'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts index c797c718e9..fc40e49434 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DICTIONARY_REPOSITORY_ALIAS } from '../repository/manifests.js'; -import { UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entities.js'; +import { UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entity.js'; import UmbReloadDictionaryEntityAction from './reload.action.js'; import UmbImportDictionaryEntityAction from './import/import.action.js'; import UmbExportDictionaryEntityAction from './export/export.action.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity.ts new file mode 100644 index 0000000000..a2c3b1a5d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity.ts @@ -0,0 +1,5 @@ +export const UMB_DICTIONARY_ROOT_ENTITY_TYPE = 'dictionary-root'; +export const UMB_DICTIONARY_ENTITY_TYPE = 'dictionary-item'; + +export type UmbDictionaryEntityType = typeof UMB_DICTIONARY_ENTITY_TYPE; +export type UmbDictionaryRootEntityType = typeof UMB_DICTIONARY_ROOT_ENTITY_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/menu-item/manifests.ts index ac644d838e..f787f054e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/menu-item/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/menu-item/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_DICTIONARY_ENTITY_TYPE } from '../entities.js'; +import { UMB_DICTIONARY_ENTITY_TYPE } from '../entity.js'; import { UMB_DICTIONARY_TREE_ALIAS } from '../tree/index.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/dictionary-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/dictionary-tree.repository.ts index 9a65449f54..20be5feebb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/dictionary-tree.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/dictionary-tree.repository.ts @@ -1,4 +1,4 @@ -import { UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entities.js'; +import { UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbDictionaryTreeServerDataSource } from './dictionary-tree.server.data-source.js'; import { UmbDictionaryTreeItemModel, UmbDictionaryTreeRootModel } from './types.js'; import { UMB_DICTIONARY_TREE_STORE_CONTEXT } from './dictionary-tree.store.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/manifests.ts index e2e0185c3c..4f0604baff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/manifests.ts @@ -1,6 +1,7 @@ -import { UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entities.js'; +import { UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbDictionaryTreeRepository } from './dictionary-tree.repository.js'; import { UmbDictionaryTreeStore } from './dictionary-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifests } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..3c39492a29 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,20 @@ +import { UMB_DICTIONARY_ROOT_ENTITY_TYPE, UMB_DICTIONARY_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DICTIONARY_REPOSITORY_ALIAS } from '../../repository/manifests.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import { type ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Dictionary.Tree.ReloadTreeItemChildren', + name: 'Reload Dictionary Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: UMB_DICTIONARY_REPOSITORY_ALIAS, + entityTypes: [UMB_DICTIONARY_ROOT_ENTITY_TYPE, UMB_DICTIONARY_ENTITY_TYPE], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/section.manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/section.manifest.ts index 9ea2fde786..c100510717 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/section.manifest.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/section.manifest.ts @@ -1,4 +1,4 @@ -import { UMB_DICTIONARY_ROOT_ENTITY_TYPE } from './dictionary/entities.js'; +import { UMB_DICTIONARY_ROOT_ENTITY_TYPE } from './dictionary/entity.js'; import type { ManifestDashboard, ManifestSection, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionAlias = 'Umb.Section.Dictionary'; From 0412a7cb2a75c4b9f8b1a84a4b2476591b573575 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 19:26:23 +0100 Subject: [PATCH 34/81] remove old reload action --- .../dictionary/entity-actions/manifests.ts | 14 -------------- .../dictionary/entity-actions/reload.action.ts | 16 ---------------- 2 files changed, 30 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts index fc40e49434..dc40b382be 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/manifests.ts @@ -1,6 +1,5 @@ import { UMB_DICTIONARY_REPOSITORY_ALIAS } from '../repository/manifests.js'; import { UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE } from '../entity.js'; -import UmbReloadDictionaryEntityAction from './reload.action.js'; import UmbImportDictionaryEntityAction from './import/import.action.js'; import UmbExportDictionaryEntityAction from './export/export.action.js'; import UmbCreateDictionaryEntityAction from './create/create.action.js'; @@ -60,19 +59,6 @@ const entityActions: Array = [ entityTypes: [UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE], }, }, - { - type: 'entityAction', - alias: 'Umb.EntityAction.Dictionary.Reload', - name: 'Reload Dictionary Entity Action', - weight: 200, - api: UmbReloadDictionaryEntityAction, - meta: { - icon: 'icon-refresh', - label: 'Reload', - repositoryAlias: UMB_DICTIONARY_REPOSITORY_ALIAS, - entityTypes: [UMB_DICTIONARY_ENTITY_TYPE, UMB_DICTIONARY_ROOT_ENTITY_TYPE], - }, - }, { type: 'entityAction', alias: 'Umb.EntityAction.Dictionary.Delete', diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts deleted file mode 100644 index 316f7f1123..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/entity-actions/reload.action.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { UmbDictionaryRepository } from '../repository/dictionary.repository.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; -import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; - -export default class UmbReloadDictionaryEntityAction extends UmbEntityActionBase { - static styles = [UmbTextStyles]; - - constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string, entityType: string) { - super(host, repositoryAlias, unique, entityType); - } - - async execute() { - alert('refresh'); - } -} From e5b166e3a0c735cdfdf01d744ca3d9c4a6b46fa9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 20:31:35 +0100 Subject: [PATCH 35/81] add reload children to document types --- .../document-types/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/manifests.ts index a4992d329c..9a9bc9e598 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/manifests.ts @@ -6,6 +6,7 @@ import { import { UmbDocumentTypeTreeRepository } from './document-type-tree.repository.js'; import { UmbDocumentTypeTreeStore } from './document-type.tree.store.js'; import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as reloadManifests } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -54,4 +55,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests, ...reloadManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..15f2a1174c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,20 @@ +import { UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/detail/manifests.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import { type ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentType.Tree.ReloadTreeItemChildren', + name: 'Reload Document Type Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, + entityTypes: [UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ENTITY_TYPE], + }, + }, +]; From 2d7a40fb0461475cb648e8de957f856fad7f3492 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 20:36:25 +0100 Subject: [PATCH 36/81] add document type mock folder handlers --- .../handlers/document-type/folder.handlers.ts | 44 +++++++++++++++++++ .../src/mocks/handlers/document-type/index.ts | 3 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/folder.handlers.ts diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/folder.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/folder.handlers.ts new file mode 100644 index 0000000000..565890e0b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/folder.handlers.ts @@ -0,0 +1,44 @@ +const { rest } = window.MockServiceWorker; +import { umbDocumentTypeMockDb } from '../../data/document-type/document-type.db.js'; +import { UMB_SLUG } from './slug.js'; +import { umbracoPath } from '@umbraco-cms/backoffice/utils'; + +export const folderHandlers = [ + rest.post(umbracoPath(`${UMB_SLUG}/folder`), async (req, res, ctx) => { + const requestBody = await req.json(); + if (!requestBody) return res(ctx.status(400, 'no body found')); + + const id = umbDocumentTypeMockDb.folder.create(requestBody); + + return res( + ctx.status(201), + ctx.set({ + Location: req.url.href + '/' + id, + 'Umb-Generated-Resource': id, + }), + ); + }), + + rest.get(umbracoPath(`${UMB_SLUG}/folder/:id`), (req, res, ctx) => { + const id = req.params.id as string; + if (!id) return res(ctx.status(400)); + const response = umbDocumentTypeMockDb.folder.read(id); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.put(umbracoPath(`${UMB_SLUG}/folder/:id`), async (req, res, ctx) => { + const id = req.params.id as string; + if (!id) return res(ctx.status(400, 'no id found')); + const requestBody = await req.json(); + if (!requestBody) return res(ctx.status(400, 'no body found')); + umbDocumentTypeMockDb.folder.update(id, requestBody); + return res(ctx.status(200)); + }), + + rest.delete(umbracoPath(`${UMB_SLUG}/folder/:id`), (req, res, ctx) => { + const id = req.params.id as string; + if (!id) return res(ctx.status(400)); + umbDocumentTypeMockDb.folder.delete(id); + return res(ctx.status(200)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/index.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/index.ts index 30239f1212..c905d34111 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/document-type/index.ts @@ -1,5 +1,6 @@ import { treeHandlers } from './tree.handlers.js'; import { detailHandlers } from './detail.handlers.js'; import { itemHandlers } from './item.handlers.js'; +import { folderHandlers } from './folder.handlers.js'; -export const handlers = [...treeHandlers, ...itemHandlers, ...detailHandlers]; +export const handlers = [...treeHandlers, ...itemHandlers, ...folderHandlers, ...detailHandlers]; From d117e130c0875277e9518d7116d92aae3c507702 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 24 Jan 2024 20:50:33 +0100 Subject: [PATCH 37/81] allow reload children for document type folders --- .../tree/reload-tree-item-children/manifests.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts index 15f2a1174c..63f50a58e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/tree/reload-tree-item-children/manifests.ts @@ -1,4 +1,8 @@ -import { UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../../entity.js'; +import { + UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, + UMB_DOCUMENT_TYPE_ENTITY_TYPE, + UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE, +} from '../../entity.js'; import { UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/detail/manifests.js'; import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; import { type ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; @@ -14,7 +18,11 @@ export const manifests: Array = [ icon: 'icon-refresh', label: 'Reload children...', repositoryAlias: UMB_DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS, - entityTypes: [UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ENTITY_TYPE], + entityTypes: [ + UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, + UMB_DOCUMENT_TYPE_ENTITY_TYPE, + UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE, + ], }, }, ]; From ec0bdebbb4c003cfa6e4671a2501a7e2a2dcd052 Mon Sep 17 00:00:00 2001 From: Markus Johansson Date: Wed, 24 Jan 2024 21:17:53 +0100 Subject: [PATCH 38/81] #1136 adjust call to set value on super --- .../core/components/input-tiny-mce/input-tiny-mce.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts index e7f94896c4..457b945401 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts @@ -44,7 +44,7 @@ export class UmbInputTinyMceElement extends FormControlMixin(UmbLitElement) { } set value(newValue: FormDataEntryValue | FormData) { - this._value = newValue; + super.value = newValue; const newContent = newValue?.toString() ?? ''; if(this.#editorRef && this.#editorRef.getContent() != newContent) { From f07ef1d6e5ca9fe3342cf1e1dbdb3787ba505043 Mon Sep 17 00:00:00 2001 From: Markus Johansson Date: Thu, 25 Jan 2024 01:45:13 +0100 Subject: [PATCH 39/81] #846 make data type picker modal medium --- .../core/modal/token/data-type-picker-flow-modal.token.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/data-type-picker-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/data-type-picker-flow-modal.token.ts index 8e9250b345..d6acec2fda 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/data-type-picker-flow-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/data-type-picker-flow-modal.token.ts @@ -14,6 +14,6 @@ export const UMB_DATA_TYPE_PICKER_FLOW_MODAL = new UmbModalToken< >('Umb.Modal.DataTypePickerFlow', { modal: { type: 'sidebar', - size: 'small', + size: 'medium', }, }); From 2eee77581689d2684763a00e644e6f6e86a7686d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 09:59:31 +0100 Subject: [PATCH 40/81] clean up when item is destroyed --- .../tree/tree-item-base/tree-item-base.context.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts index 8a089eccfe..d04e4381ff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts @@ -9,8 +9,8 @@ import { UmbBooleanState, UmbDeepState, UmbStringState } from '@umbraco-cms/back import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UMB_ACTION_EVENT_CONTEXT, UmbActionEventContext } from '@umbraco-cms/backoffice/action'; -import { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_ACTION_EVENT_CONTEXT, type UmbActionEventContext } from '@umbraco-cms/backoffice/action'; +import type { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action'; import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree'; export type UmbTreeItemUniqueFunction = ( @@ -233,6 +233,14 @@ export class UmbTreeItemContextBase constructPath(pathname: string, entityType: string, unique: string | null) { return `section/${pathname}/workspace/${entityType}/edit/${unique}`; } + + destroy(): void { + this.#actionEventContext?.removeEventListener( + UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, + this.#onReloadRequest as EventListener, + ); + super.destroy(); + } } export const UMB_TREE_ITEM_CONTEXT = new UmbContextToken>('UmbTreeItemContext'); From 1f3e7a4b9615ff55922df54dabcd02c251f34956 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 10:20:36 +0100 Subject: [PATCH 41/81] reload document tree items --- .../documents/documents/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts index cad95f0d15..7470671496 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbDocumentTreeRepository } from './document-tree.repository.js'; import { UmbDocumentTreeStore } from './document-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifests } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..dfd8b3f192 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,20 @@ +import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_REPOSITORY_ALIAS } from '../../repository/index.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Document.Tree.ReloadTreeItemChildren', + name: 'Reload Document Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: UMB_DOCUMENT_REPOSITORY_ALIAS, + entityTypes: [UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE], + }, + }, +]; From 974060cb9a7df3be92edab4b5648c77f9add45e6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 10:24:26 +0100 Subject: [PATCH 42/81] add reload to document recycle bin --- .../documents/recycle-bin/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts index 62e7712236..616228072f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbDocumentRecycleBinTreeRepository } from './document-recycle-bin-tree.repository.js'; import { UmbDocumentRecycleBinTreeStore } from './document-recycle-bin-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifests } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..2fc615bd39 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentRecycleBin.Tree.ReloadTreeItemChildren', + name: 'Reload Document Recycle Bin Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.DocumentRecycleBin.Tree', + entityTypes: [UMB_DOCUMENT_RECYCLE_BIN_ENTITY_TYPE, UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE], + }, + }, +]; From 77e2b7e9d631ee132074e65bba36cc098a96ef91 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 10:35:32 +0100 Subject: [PATCH 43/81] add reload to media tree --- .../packages/media/media/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/manifests.ts index 5ec3605b54..b6334b0d88 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_MEDIA_ENTITY_TYPE, UMB_MEDIA_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbMediaTreeRepository } from './media-tree.repository.js'; import { UmbMediaTreeStore } from './media-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifests } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..bb52bb908e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_MEDIA_ENTITY_TYPE, UMB_MEDIA_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Media.Tree.ReloadTreeItemChildren', + name: 'Reload Media Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.Media.Tree', + entityTypes: [UMB_MEDIA_ENTITY_TYPE, UMB_MEDIA_ROOT_ENTITY_TYPE], + }, + }, +]; From 7fc51aecb8f7eba75e733eb5dc7b8321a19afb91 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 10:38:21 +0100 Subject: [PATCH 44/81] add reload media type children --- .../media/media-types/tree/manifests.ts | 11 +++++++++-- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts index b53de760d7..448ac15eba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts @@ -6,7 +6,7 @@ import { import { UmbMediaTypeTreeRepository } from './media-type-tree.repository.js'; import { UmbMediaTypeTreeStore } from './media-type-tree.store.js'; import { manifests as folderManifests } from './folder/manifests.js'; - +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -51,4 +51,11 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests]; +export const manifests = [ + treeRepository, + treeStore, + tree, + treeItem, + ...folderManifests, + ...reloadTreeItemChildrenManifest, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..e53c2de2c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_MEDIA_TYPE_ENTITY_TYPE, UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.MediaType.Tree.ReloadTreeItemChildren', + name: 'Reload Media Type Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.MediaType.Tree', + entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE, UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE], + }, + }, +]; From b97ee56c670750a0e1ffa2eb8516ea437aac9a08 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 10:47:21 +0100 Subject: [PATCH 45/81] add more reload actions to trees --- .../members/member-groups/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ .../members/member-types/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ .../members/members/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ .../relation-types/{entities.ts => entity.ts} | 0 .../relations/relation-types/index.ts | 2 +- .../relation-types/tree/manifests.ts | 5 +++-- .../tree/relation-type-tree.repository.ts | 2 +- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++++++++ 11 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/reload-tree-item-children/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/reload-tree-item-children/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/members/tree/reload-tree-item-children/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/{entities.ts => entity.ts} (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/manifests.ts index 6f5490951f..7ffe0327c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_MEMBER_GROUP_ENTITY_TYPE, UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbMemberGroupTreeRepository } from './member-group-tree.repository.js'; import { UmbMemberGroupTreeStore } from './member-group-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..9bf3ee1c42 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_MEMBER_GROUP_ENTITY_TYPE, UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.MemberGroup.Tree.ReloadTreeItemChildren', + name: 'Reload Member Group Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.MemberGroup.Tree', + entityTypes: [UMB_MEMBER_GROUP_ENTITY_TYPE, UMB_MEMBER_GROUP_ROOT_ENTITY_TYPE], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/manifests.ts index 8ff56868a5..d93a6f32aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_MEMBER_TYPE_ENTITY_TYPE, UMB_MEMBER_TYPE_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbMemberTypeTreeRepository } from './member-type-tree.repository.js'; import { UmbMemberTypeTreeStore } from './member-type-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..d2929ce739 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_MEMBER_TYPE_ENTITY_TYPE, UMB_MEMBER_TYPE_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.MemberType.Tree.ReloadTreeItemChildren', + name: 'Reload Member Type Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.MemberType.Tree', + entityTypes: [UMB_MEMBER_TYPE_ENTITY_TYPE, UMB_MEMBER_TYPE_ROOT_ENTITY_TYPE], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/manifests.ts index 40fc0a89f5..fc74d4d7ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbMemberTreeRepository } from './member-tree.repository.js'; import { UmbMemberTreeStore } from './member-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..7a6db10068 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/members/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Member.Tree.ReloadTreeItemChildren', + name: 'Reload Member Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.Member.Tree', + entityTypes: [UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_ROOT_ENTITY_TYPE], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entities.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entity.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entities.ts rename to src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/entity.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/index.ts index 7bbcc83722..48e5364e41 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/index.ts @@ -1,2 +1,2 @@ export * from './repository/index.js'; -export * from './entities.js'; +export * from './entity.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/manifests.ts index fac911101f..3f3438a75d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/manifests.ts @@ -1,6 +1,7 @@ -import { UMB_RELATION_TYPE_ENTITY_TYPE, UMB_RELATION_TYPE_ROOT_ENTITY_TYPE } from '../entities.js'; +import { UMB_RELATION_TYPE_ENTITY_TYPE, UMB_RELATION_TYPE_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbRelationTypeTreeRepository } from './relation-type-tree.repository.js'; import { UmbRelationTypeTreeStore } from './relation-type-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/relation-type-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/relation-type-tree.repository.ts index 1fc833fa55..166b8b8eda 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/relation-type-tree.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/relation-type-tree.repository.ts @@ -1,4 +1,4 @@ -import { UMB_RELATION_TYPE_ROOT_ENTITY_TYPE } from '../entities.js'; +import { UMB_RELATION_TYPE_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbRelationTypeTreeServerDataSource } from './relation-type-tree.server.data-source.js'; import type { UmbRelationTypeTreeItemModel, UmbRelationTypeTreeRootModel } from './types.js'; import { UMB_RELATION_TYPE_TREE_STORE_CONTEXT } from './relation-type-tree.store.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..13db230eaf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_RELATION_TYPE_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.RelationType.Tree.ReloadTreeItemChildren', + name: 'Reload Relation Type Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.RelationType.Tree', + entityTypes: [UMB_RELATION_TYPE_ROOT_ENTITY_TYPE], + }, + }, +]; From 0d13010474e28570b60d0de8b914c10dd54485a6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 10:55:41 +0100 Subject: [PATCH 46/81] add reload for templating trees --- .../partial-views/tree/manifests.ts | 10 ++++++- .../reload-tree-item-children/manifests.ts | 27 +++++++++++++++++++ .../templating/scripts/tree/manifests.ts | 10 ++++++- .../reload-tree-item-children/manifests.ts | 19 +++++++++++++ .../templating/stylesheets/tree/manifests.ts | 10 ++++++- .../reload-tree-item-children/manifests.ts | 23 ++++++++++++++++ .../templating/templates/tree/manifests.ts | 3 ++- .../reload-tree-item-children/manifests.ts | 23 ++++++++++++++++ 8 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/reload-tree-item-children/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/reload-tree-item-children/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/reload-tree-item-children/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/reload-tree-item-children/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/manifests.ts index 6a93d9a45b..c208c9aa10 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/manifests.ts @@ -6,6 +6,7 @@ import { import { UmbPartialViewTreeRepository } from './partial-view-tree.repository.js'; import { UmbPartialViewTreeStore } from './partial-view-tree.store.js'; import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -50,4 +51,11 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests]; +export const manifests = [ + treeRepository, + treeStore, + tree, + treeItem, + ...folderManifests, + ...reloadTreeItemChildrenManifest, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..2f017d6156 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,27 @@ +import { + UMB_PARTIAL_VIEW_ROOT_ENTITY_TYPE, + UMB_PARTIAL_VIEW_ENTITY_TYPE, + UMB_PARTIAL_VIEW_FOLDER_ENTITY_TYPE, +} from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.PartialView.Tree.ReloadTreeItemChildren', + name: 'Reload Partial View Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.PartialView.Tree', + entityTypes: [ + UMB_PARTIAL_VIEW_ROOT_ENTITY_TYPE, + UMB_PARTIAL_VIEW_ENTITY_TYPE, + UMB_PARTIAL_VIEW_FOLDER_ENTITY_TYPE, + ], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/manifests.ts index 413e7b78b0..f40ed7b3f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/manifests.ts @@ -2,6 +2,7 @@ import { UMB_SCRIPT_ENTITY_TYPE, UMB_SCRIPT_FOLDER_ENTITY_TYPE, UMB_SCRIPT_ROOT_ import { UmbScriptTreeRepository } from './script-tree.repository.js'; import { UmbScriptTreeStore } from './script-tree.store.js'; import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -46,4 +47,11 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests]; +export const manifests = [ + treeRepository, + treeStore, + tree, + treeItem, + ...folderManifests, + ...reloadTreeItemChildrenManifest, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..f23c9d945d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_SCRIPT_ROOT_ENTITY_TYPE, UMB_SCRIPT_ENTITY_TYPE, UMB_SCRIPT_FOLDER_ENTITY_TYPE } from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Script.Tree.ReloadTreeItemChildren', + name: 'Reload Script Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.Script.Tree', + entityTypes: [UMB_SCRIPT_ROOT_ENTITY_TYPE, UMB_SCRIPT_ENTITY_TYPE, UMB_SCRIPT_FOLDER_ENTITY_TYPE], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts index 9b9e9a875d..43703c840f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts @@ -4,6 +4,7 @@ import { UMB_STYLESHEET_ROOT_ENTITY_TYPE, } from '../entity.js'; import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import { UmbStylesheetTreeRepository } from './stylesheet-tree.repository.js'; import { UmbStylesheetTreeStore } from './stylesheet-tree.store.js'; import type { @@ -51,4 +52,11 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests]; +export const manifests = [ + treeRepository, + treeStore, + tree, + treeItem, + ...folderManifests, + ...reloadTreeItemChildrenManifest, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..9222f8077c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,23 @@ +import { + UMB_STYLESHEET_ROOT_ENTITY_TYPE, + UMB_STYLESHEET_ENTITY_TYPE, + UMB_STYLESHEET_FOLDER_ENTITY_TYPE, +} from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Stylesheet.Tree.ReloadTreeItemChildren', + name: 'Reload Stylesheet Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.Stylesheet.Tree', + entityTypes: [UMB_STYLESHEET_ROOT_ENTITY_TYPE, UMB_STYLESHEET_ENTITY_TYPE, UMB_STYLESHEET_FOLDER_ENTITY_TYPE], + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/manifests.ts index 9c3d943c41..ca6e077e34 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/manifests.ts @@ -1,6 +1,7 @@ import { UMB_TEMPLATE_ENTITY_TYPE, UMB_TEMPLATE_ROOT_ENTITY_TYPE } from '../entity.js'; import { UmbTemplateTreeRepository } from './template-tree.repository.js'; import { UmbTemplateTreeStore } from './template-tree.store.js'; +import { manifests as reloadTreeItemChildrenManifest } from './reload-tree-item-children/manifests.js'; import type { ManifestRepository, ManifestTree, @@ -45,4 +46,4 @@ const treeItem: ManifestTreeItem = { }, }; -export const manifests = [treeRepository, treeStore, tree, treeItem]; +export const manifests = [treeRepository, treeStore, tree, treeItem, ...reloadTreeItemChildrenManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/reload-tree-item-children/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/reload-tree-item-children/manifests.ts new file mode 100644 index 0000000000..180da25ef5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/tree/reload-tree-item-children/manifests.ts @@ -0,0 +1,23 @@ +import { + UMB_TEMPLATE_ROOT_ENTITY_TYPE, + UMB_TEMPLATE_ENTITY_TYPE, + UMB_TEMPLATE_FOLDER_ENTITY_TYPE, +} from '../../entity.js'; +import { UmbReloadTreeItemChildrenEntityAction } from '@umbraco-cms/backoffice/tree'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Template.Tree.ReloadTreeItemChildren', + name: 'Reload Template Tree Item Children Entity Action', + weight: 10, + api: UmbReloadTreeItemChildrenEntityAction, + meta: { + icon: 'icon-refresh', + label: 'Reload children...', + repositoryAlias: 'Umb.Repository.Template.Tree', + entityTypes: [UMB_TEMPLATE_ROOT_ENTITY_TYPE, UMB_TEMPLATE_ENTITY_TYPE, UMB_TEMPLATE_FOLDER_ENTITY_TYPE], + }, + }, +]; From e823b9d70141bd93b38c587a3e0ab5d31d34015e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 12:23:50 +0100 Subject: [PATCH 47/81] handle root requests in tree context --- .../tree-item-base/tree-item-base.context.ts | 3 +- .../src/packages/core/tree/tree.context.ts | 51 +++++++++++++++++-- .../src/packages/core/tree/tree.element.ts | 16 +++--- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts index d04e4381ff..24ea634a98 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts @@ -223,7 +223,8 @@ export class UmbTreeItemContextBase } #onReloadRequest = (event: UmbEntityActionEvent) => { - if (this.unique === undefined) return; + // Only handle children request here. Root request is handled by the tree context + if (!this.unique) return; if (event.getUnique() !== this.unique) return; if (event.getEntityType() !== this.entityType) return; this.requestChildren(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts index 1a39bd4c2c..8702857f44 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts @@ -1,5 +1,7 @@ +import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from './reload-tree-item-children/index.js'; import type { UmbTreeItemModelBase } from './types.js'; import type { UmbTreeRepository } from './tree-repository.interface.js'; +import { type UmbActionEventContext, UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbPagedData } from '@umbraco-cms/backoffice/repository'; import { @@ -12,6 +14,8 @@ import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controlle import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import type { ProblemDetails } from '@umbraco-cms/backoffice/backend-api'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; +import type { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; // TODO: update interface export interface UmbTreeContext extends UmbBaseController { @@ -27,14 +31,16 @@ export class UmbTreeContextBase extends UmbBaseController implements UmbTreeContext { + #treeRoot = new UmbObjectState(undefined); + treeRoot = this.#treeRoot.asObservable(); + public repository?: UmbTreeRepository; public selectableFilter?: (item: TreeItemType) => boolean = () => true; - public filter?: (item: TreeItemType) => boolean = () => true; - public readonly selection = new UmbSelectionManager(this._host); #treeAlias?: string; + #actionEventContext?: UmbActionEventContext; #initResolver?: () => void; #initialized = false; @@ -46,6 +52,20 @@ export class UmbTreeContextBase constructor(host: UmbControllerHostElement) { super(host); this.provideContext('umbTreeContext', this); + + this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (instance) => { + this.#actionEventContext = instance; + this.#actionEventContext.removeEventListener( + UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, + this.#onReloadRequest as EventListener, + ); + this.#actionEventContext.addEventListener( + UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, + this.#onReloadRequest as EventListener, + ); + }); + + this.requestTreeRoot(); } // TODO: find a generic way to do this @@ -69,7 +89,13 @@ export class UmbTreeContextBase public async requestTreeRoot() { await this.#init; - return this.repository!.requestTreeRoot(); + const { data } = await this.repository!.requestTreeRoot(); + + if (data) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.#treeRoot.setValue(data); + } } public async requestRootItems() { @@ -121,4 +147,23 @@ export class UmbTreeContextBase }, ); } + + #onReloadRequest = (event: UmbEntityActionEvent) => { + // Only handle root request here. Items are handled by the tree item context + const treeRoot = this.#treeRoot.getValue(); + if (treeRoot === undefined) return; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (event.getUnique() !== treeRoot.unique) return; + if (event.getEntityType() !== treeRoot.entityType) return; + this.requestRootItems(); + }; + + destroy(): void { + this.#actionEventContext?.removeEventListener( + UmbReloadTreeItemChildrenRequestEntityActionEvent.TYPE, + this.#onReloadRequest as EventListener, + ); + super.destroy(); + } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts index 999ac69ffb..7332f200b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.element.ts @@ -79,19 +79,21 @@ export class UmbTreeElement extends UmbLitElement { private _treeRoot?: UmbTreeItemModelBase; #treeContext = new UmbTreeContextBase(this); - #rootItemsObserver?: UmbObserverController>; constructor() { super(); - this.#requestTreeRoot(); + this.#observeTreeRoot(); } - async #requestTreeRoot() { - if (!this.#treeContext?.requestTreeRoot) throw new Error('Tree does not support root'); - - const { data } = await this.#treeContext.requestTreeRoot(); - this._treeRoot = data; + #observeTreeRoot() { + this.observe( + this.#treeContext.treeRoot, + (treeRoot) => { + this._treeRoot = treeRoot; + }, + 'umbTreeRootObserver', + ); } async #observeRootItems() { From c0eb87818c9036792d87e0d27f202441643149dd Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:28:05 +0100 Subject: [PATCH 48/81] context --- ...i-block-grid-type-configuration.element.ts | 64 ++++++++++++++----- .../input-block-type.element.ts | 55 +++------------- .../workspace/block-type-workspace.context.ts | 13 ++-- .../workspace/block-type-workspace.element.ts | 10 +-- 4 files changed, 73 insertions(+), 69 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 9563e8a899..1184683ea9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -1,7 +1,16 @@ -import type { UmbBlockTypeWithGroupKey } from '../../../block-type/index.js'; +import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, property, state, repeat, nothing, css } from '@umbraco-cms/backoffice/external/lit'; +import { + html, + customElement, + property, + state, + repeat, + nothing, + css, + ifDefined, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorConfigCollection, @@ -11,6 +20,7 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { UmbBlockGridGroupType, UmbBlockGridGroupTypeConfiguration } from '@umbraco-cms/backoffice/block'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UMB_PROPERTY_DATASET_CONTEXT, type UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; /** * @element umb-property-editor-ui-block-grid-type-configuration @@ -21,6 +31,10 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement implements UmbPropertyEditorUiElement { #datasetContext?: UmbPropertyDatasetContext; + #blockTypeWorkspaceModalRegistration?: UmbModalRouteRegistrationController< + typeof UMB_WORKSPACE_MODAL.DATA, + typeof UMB_WORKSPACE_MODAL.VALUE + >; private _value: Array = []; @property({ attribute: false }) @@ -40,12 +54,29 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement @state() private _mappedValuesAndGroups: Array = []; + @state() + private _workspacePath?: string; + constructor() { super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { this.#datasetContext = instance; this.#observeProperties(); }); + + this.#blockTypeWorkspaceModalRegistration?.destroy(); + + const entityType = 'block-grid-type'; + + this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath(entityType) + .onSetup(() => { + return { data: { entityType: entityType, preset: {} }, modal: { size: 'large' } }; + }) + .observeRouteBuilder((routeBuilder) => { + const newpath = routeBuilder({}); + this._workspacePath = newpath; + }); } async #observeProperties() { @@ -71,21 +102,20 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup]; } - /* - #onChange(e: CustomEvent, group?: UmbBlockGridGroupTypeConfiguration) { - const groupValues = (e.target as UmbInputBlockTypeElement).value; - const newValues = groupValues.map((value) => ({ ...value, groupKey: group?.key })); - const filteredValues = this._value.filter((block) => block.contentElementTypeKey === group?.key); - this.value = [...filteredValues, ...newValues]; - this.dispatchEvent(new CustomEvent('property-value-change')); - } - */ - - #deleteItem(e: CustomEvent) { - this.value = this._value.filter((block) => block.contentElementTypeKey !== e.detail.contentElementTypeKey); + #onChange(e: CustomEvent, groupKey?: string) { + const updatedValues = (e.target as UmbInputBlockTypeElement).value.map((value) => ({ ...value, groupKey })); + const filteredValues = this.value.filter((value) => value.groupKey !== groupKey); + this.value = [...filteredValues, ...updatedValues]; this.dispatchEvent(new UmbPropertyValueChangeEvent()); } + #onCreate(e: CustomEvent, groupKey: string | null) { + const selectedElementType = e.detail.contentElementTypeKey; + if (selectedElementType) { + this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/' + groupKey); + } + } + #deleteGroup(groupKey: string) { this.#datasetContext?.setPropertyValue( 'blockGroups', @@ -113,7 +143,9 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement `, + .workspacePath="${this._workspacePath}" + @create=${(e: CustomEvent) => this.#onCreate(e, group.key ?? null)} + @change=${(e: CustomEvent) => this.#onChange(e, group.key)}>`, )}`; } @@ -122,7 +154,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement auto-width label="Group" .value=${groupName ?? ''} - @delete=${(e: UUIInputEvent) => this.#changeGroupName(e, groupKey)}> + @change=${(e: UUIInputEvent) => this.#changeGroupName(e, groupKey)}> this.#deleteGroup(groupKey)}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 548cd15034..982b51eb4d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -1,21 +1,16 @@ import type { UmbBlockTypeBaseModel } from '../../types.js'; -import { - UMB_DOCUMENT_TYPE_PICKER_MODAL, - UMB_MODAL_MANAGER_CONTEXT, - UMB_WORKSPACE_MODAL, - UmbModalRouteRegistrationController, -} from '@umbraco-cms/backoffice/modal'; +import { UMB_DOCUMENT_TYPE_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import '../block-type-card/index.js'; import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UMB_PROPERTY_DATASET_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; @customElement('umb-input-block-type') export class UmbInputBlockTypeElement< BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, > extends UmbLitElement { - // @property({ type: Array, attribute: false }) public get value() { return this._items; @@ -24,41 +19,12 @@ export class UmbInputBlockTypeElement< this._items = items ?? []; } - @property({ type: String, attribute: 'entity-type' }) - public get entityType() { - return this.#entityType; - } - public set entityType(entityType) { - this.#entityType = entityType; - - this.#blockTypeWorkspaceModalRegistration?.destroy(); - - if (entityType) { - // TODO: Make specific modal token that requires data. - this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) - .addAdditionalPath(entityType) - .onSetup(() => { - return { data: { entityType: entityType, preset: {} }, modal: { size: 'large' } }; - }) - .observeRouteBuilder((routeBuilder) => { - const newpath = routeBuilder({}); - this._workspacePath = newpath; - }); - } - } - #entityType?: string; + @property({ type: String }) + workspacePath?: string; @state() private _items: Array = []; - @state() - private _workspacePath?: string; - - #blockTypeWorkspaceModalRegistration?: UmbModalRouteRegistrationController< - typeof UMB_WORKSPACE_MODAL.DATA, - typeof UMB_WORKSPACE_MODAL.VALUE - >; - #datasetContext?: UmbPropertyDatasetContext; #filter: Array = []; @@ -84,25 +50,24 @@ export class UmbInputBlockTypeElement< // Only pick elements: docType.isElement && // Prevent picking the an already used element type: + this.#filter && this.#filter.find((x) => x.contentElementTypeKey === docType.unique) === undefined, }, }); const modalValue = await modalContext?.onSubmit(); const selectedElementType = modalValue.selection[0]; + if (selectedElementType) { - this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType); + this.dispatchEvent(new CustomEvent('create', { detail: { contentElementTypeKey: selectedElementType } })); } } }); - - // No need to fire a change event, as all changes are made directly to the property, via context api. } deleteItem(contentElementTypeKey: string) { this.value = this._items.filter((x) => x.contentElementTypeKey !== contentElementTypeKey); - this.dispatchEvent(new CustomEvent('delete', { detail: { contentElementTypeKey } })); - //this.dispatchEvent(new UmbChangeEvent()); + this.dispatchEvent(new UmbChangeEvent()); } protected getFormElement() { @@ -118,7 +83,7 @@ export class UmbInputBlockTypeElement< #renderItem = (item: BlockType) => { return html` this.deleteItem(item.contentElementTypeKey)}> 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 5209b21197..5883299981 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,9 +1,10 @@ -import type { UmbBlockTypeBaseModel } from '../types.js'; +import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbInvariantableWorkspaceContextInterface, - UmbWorkspaceContextInterface} from '@umbraco-cms/backoffice/workspace'; + UmbWorkspaceContextInterface, +} from '@umbraco-cms/backoffice/workspace'; import { UmbEditableWorkspaceContextBase, UmbInvariantWorkspacePropertyDatasetContext, @@ -13,7 +14,7 @@ import type { UmbControllerHost, UmbControllerHostElement } from '@umbraco-cms/b import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { ManifestWorkspace, PropertyEditorConfigProperty } from '@umbraco-cms/backoffice/extension-registry'; -export class UmbBlockTypeWorkspaceContext +export class UmbBlockTypeWorkspaceContext extends UmbEditableWorkspaceContextBase implements UmbInvariantableWorkspaceContextInterface { @@ -57,11 +58,15 @@ export class UmbBlockTypeWorkspaceContext { const elementTypeKey = info.match.params.elementTypeKey; - this.#workspaceContext!.create(elementTypeKey); + const groupKey = info.match.params.groupKey === 'null' ? null : info.match.params.groupKey; + this.#workspaceContext!.create(elementTypeKey, groupKey); new UmbWorkspaceIsNewRedirectController( this, From 025c2bf898f9428389d712330a57272df7636d04 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:33:16 +0100 Subject: [PATCH 49/81] build err --- ...operty-editor-ui-block-grid-group-configuration.element.ts | 4 ++-- ...operty-editor-ui-block-grid-group-configuration.stories.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts index ea8b94c594..333d2258ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.element.ts @@ -1,10 +1,10 @@ import { html, customElement, property, css } from '@umbraco-cms/backoffice/external/lit'; -import { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbId } from '@umbraco-cms/backoffice/id'; -import { UmbBlockGridGroupType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockGridGroupType } from '@umbraco-cms/backoffice/block'; @customElement('umb-property-editor-ui-block-grid-group-configuration') export class UmbPropertyEditorUIBlockGridGroupConfigurationElement diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts index 7e8cb00391..c001579428 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts @@ -1,4 +1,4 @@ -import { Meta, Story } from '@storybook/web-components'; +import type { Meta, Story } from '@storybook/web-components'; import type { UmbPropertyEditorUIBlockGridGroupConfigurationElement } from './property-editor-ui-block-grid-group-configuration.element.js'; import { html } from '@umbraco-cms/backoffice/external/lit'; From 316e67df7b006e4ebccf011f790398cc7975f8d6 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:40:50 +0100 Subject: [PATCH 50/81] entity type --- ...i-block-grid-type-configuration.element.ts | 28 +++++++------------ .../src/packages/block/block-grid/types.ts | 2 ++ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 1184683ea9..9714e9cd08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -1,23 +1,18 @@ import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { - html, - customElement, - property, - state, - repeat, - nothing, - css, - ifDefined, -} from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, state, repeat, nothing, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { UmbBlockGridGroupType, UmbBlockGridGroupTypeConfiguration } from '@umbraco-cms/backoffice/block'; +import { + UMB_BLOCK_GRID_TYPE, + type UmbBlockGridGroupType, + type UmbBlockGridGroupTypeConfiguration, +} from '@umbraco-cms/backoffice/block'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UMB_PROPERTY_DATASET_CONTEXT, type UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; @@ -66,12 +61,10 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this.#blockTypeWorkspaceModalRegistration?.destroy(); - const entityType = 'block-grid-type'; - this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) - .addAdditionalPath(entityType) + .addAdditionalPath(UMB_BLOCK_GRID_TYPE) .onSetup(() => { - return { data: { entityType: entityType, preset: {} }, modal: { size: 'large' } }; + return { data: { entityType: UMB_BLOCK_GRID_TYPE, preset: {} }, modal: { size: 'large' } }; }) .observeRouteBuilder((routeBuilder) => { const newpath = routeBuilder({}); @@ -141,9 +134,8 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement (group) => html`${group.key ? this.#renderGroupInput(group.key, group.name) : nothing} this.#onCreate(e, group.key ?? null)} @change=${(e: CustomEvent) => this.#onChange(e, group.key)}>`, )}`; 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 a3fb79a2f7..3a51638811 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,5 +1,7 @@ import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../block-type/index.js'; +export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; + export interface UmbBlockGridType extends UmbBlockTypeBaseModel { columnSpanOptions: Array; allowAtRoot: boolean; From 0a8d0a1c9d8b051f9218511c6a293e04cfd23805 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 13:17:07 +0100 Subject: [PATCH 51/81] remove unused state --- .../core/tree/tree-item-base/tree-item-base.element.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.element.ts index d4095549a2..ffa69d14b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.element.ts @@ -7,9 +7,6 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-tree-item-base') export class UmbTreeItemBaseElement extends UmbLitElement { - @state() - private _iconAlias?: string; - @state() private _item?: UmbTreeItemModelBase; From c641fd7d56301896ec70250fe80f73effbb04fcc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Jan 2024 13:22:16 +0100 Subject: [PATCH 52/81] fix missing type when importing --- .../reload-tree-item-children-request.event.ts | 2 +- .../reload-tree-item-children.action.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts index 7c51f52e74..999b2dd669 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children-request.event.ts @@ -1,4 +1,4 @@ -import { UmbEntityActionEvent, UmbEntityActionEventArgs } from '@umbraco-cms/backoffice/entity-action'; +import { UmbEntityActionEvent, type UmbEntityActionEventArgs } from '@umbraco-cms/backoffice/entity-action'; export class UmbReloadTreeItemChildrenRequestEntityActionEvent extends UmbEntityActionEvent { static readonly TYPE = 'reload-tree-item-children-request'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts index f1a5bab504..ba0ebe7c89 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/reload-tree-item-children/reload-tree-item-children.action.ts @@ -1,7 +1,8 @@ -import { type UmbCopyDataTypeRepository } from '../../data-type/repository/copy/data-type-copy.repository.js'; +import type { UmbCopyDataTypeRepository } from '../../data-type/repository/copy/data-type-copy.repository.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; -import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import { UMB_ACTION_EVENT_CONTEXT, UmbActionEventContext } from '@umbraco-cms/backoffice/action'; +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbActionEventContext } from '@umbraco-cms/backoffice/action'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree'; export class UmbReloadTreeItemChildrenEntityAction extends UmbEntityActionBase { From 8b4ddaa92fae35c3ddffeeb5491d28929ca3315a Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 25 Jan 2024 13:55:57 +0100 Subject: [PATCH 53/81] block list --- ...i-block-list-type-configuration.element.ts | 37 ++++++++++++++++++- .../src/packages/block/block-list/types.ts | 2 + ...shboard-localization-dictionary.element.ts | 1 + 3 files changed, 38 insertions(+), 2 deletions(-) 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 5948997fcb..57744eb391 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,10 +1,12 @@ import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; +import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; /** * @element umb-property-editor-ui-block-list-type-configuration @@ -14,16 +16,47 @@ export class UmbPropertyEditorUIBlockListBlockConfigurationElement extends UmbLitElement implements UmbPropertyEditorUiElement { + #blockTypeWorkspaceModalRegistration?: UmbModalRouteRegistrationController< + typeof UMB_WORKSPACE_MODAL.DATA, + typeof UMB_WORKSPACE_MODAL.VALUE + >; + + @state() + private _workspacePath?: string; + + constructor() { + super(); + this.#blockTypeWorkspaceModalRegistration?.destroy(); + + this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath(UMB_BLOCK_LIST_TYPE) + .onSetup(() => { + return { data: { entityType: UMB_BLOCK_LIST_TYPE, preset: {} }, modal: { size: 'large' } }; + }) + .observeRouteBuilder((routeBuilder) => { + const newpath = routeBuilder({}); + this._workspacePath = newpath; + }); + } + @property({ attribute: false }) value: UmbBlockTypeBaseModel[] = []; @property({ type: Object, attribute: false }) public config?: UmbPropertyEditorConfigCollection; + #onCreate(e: CustomEvent) { + const selectedElementType = e.detail.contentElementTypeKey; + if (selectedElementType) { + this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/null'); + } + } + render() { return html` { this.value = (e.target as UmbInputBlockTypeElement).value; }}>`; 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 dee3748bfd..bd1e8053c9 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,5 +1,7 @@ import type { UmbBlockTypeBaseModel } from '../block-type/index.js'; import type { UmbBlockLayoutBaseModel } from '../index.js'; +export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; + export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {} export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts index 6f82558c59..9f60055470 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dashboards/dictionary/dashboard-localization-dictionary.element.ts @@ -42,6 +42,7 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement { const { data } = await this.#repo.list(0, 1000); this.#dictionaryItems = data?.items ?? []; + this.#setTableColumns(); this.#setTableItems(); } From 173d4f3ed458266dcfbcdde1c01bc4dcdbb9cfb9 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:48:58 +0100 Subject: [PATCH 54/81] remove IUmbAuthContext interface since it was merely put in as a safe-guard in case we had to move the services around --- .../src/shared/auth/auth.context.interface.ts | 46 ------------------- .../src/shared/auth/auth.context.token.ts | 4 +- .../src/shared/auth/auth.context.ts | 11 +++-- .../src/shared/auth/index.ts | 1 - 4 files changed, 10 insertions(+), 52 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.interface.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.interface.ts deleted file mode 100644 index b307a4b7b9..0000000000 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.interface.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; - -export interface IUmbAuthContext { - isAuthorized: Observable; - - /** - * Initiates the login flow. - */ - login(): void; - - /** - * Initialise the auth flow. - */ - setInitialState(): Promise; - - /** - * Checks if there is a token and it is still valid. - */ - getIsAuthorized(): boolean; - - /** - * Gets the latest token from the Management API. - * If the token is expired, it will be refreshed. - * - * NB! The user may experience being redirected to the login screen if the token is expired. - * - * @example - * ```js - * const token = await authContext.getLatestToken(); - * const result = await fetch('https://my-api.com', { headers: { Authorization: `Bearer ${token}` } }); - * ``` - * - * @returns The latest token from the Management API - */ - getLatestToken(): Promise; - - /** - * Clears the token storage. - */ - clearTokenStorage(): Promise; - - /** - * Signs the user out by removing any tokens from the browser. - */ - signOut(): Promise; -} diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts index b7c70219f0..4725be3acb 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts @@ -1,4 +1,4 @@ -import type { IUmbAuthContext } from './auth.context.interface.js'; +import type { UmbAuthContext } from './auth.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -export const UMB_AUTH_CONTEXT = new UmbContextToken('UmbAuthContext'); +export const UMB_AUTH_CONTEXT = new UmbContextToken('UmbAuthContext'); diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts index 8a0a298e06..49bf424100 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts @@ -1,11 +1,10 @@ -import type { IUmbAuthContext } from './auth.context.interface.js'; import { UmbAuthFlow } from './auth-flow.js'; import { UMB_AUTH_CONTEXT } from './auth.context.token.js'; import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbAuthContext extends UmbBaseController implements IUmbAuthContext { +export class UmbAuthContext extends UmbBaseController { #isAuthorized = new UmbBooleanState(false); readonly isAuthorized = this.#isAuthorized.asObservable(); @@ -59,6 +58,13 @@ export class UmbAuthContext extends UmbBaseController implements IUmbAuthContext * * NB! The user may experience being redirected to the login screen if the token is expired. * + * @example + * ```js + * const token = await authContext.getLatestToken(); + * const result = await fetch('https://my-api.com', { headers: { Authorization: `Bearer ${token}` } }); + * ``` + * + * @memberof UmbAuthContext * @returns The latest token from the Management API */ getLatestToken(): Promise { @@ -75,7 +81,6 @@ export class UmbAuthContext extends UmbBaseController implements IUmbAuthContext /** * Signs the user out by removing any tokens from the browser. - * @return {*} {Promise} * @memberof UmbAuthContext */ signOut(): Promise { diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/index.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/index.ts index f2e7f83bb1..e2633039d7 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/index.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/index.ts @@ -1,3 +1,2 @@ -export * from './auth.context.interface.js'; export * from './auth.context.js'; export * from './auth.context.token.js'; From 9baa16878530fc918a37993993e84b8871bf9469 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:52:16 +0100 Subject: [PATCH 55/81] rename 'login' to 'makeAuthorizationRequest' and add a new public method to complete a pending authorization --- src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts | 3 +-- .../src/shared/auth/auth-flow.ts | 3 --- .../src/shared/auth/auth.context.ts | 11 +++++++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts index 4786301fa7..b9bf8a3b10 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts @@ -190,8 +190,7 @@ export class UmbAppElement extends UmbLitElement { window.sessionStorage.setItem('umb:auth:redirect', location.href); // Make a request to the auth server to start the auth flow - // TODO: find better name for this method - this.#authContext.login(); + this.#authContext.makeAuthorizationRequest(); // Return false to prevent the route from being rendered return false; diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts index 0d77f7143e..7dbb62350c 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts @@ -170,9 +170,6 @@ export class UmbAuthFlow { this.#refreshToken = this.#accessTokenResponse.refreshToken; } } - - // If no token was found, or if it was invalid, check if there is a new authorization to be made - await this.completeAuthorizationIfPossible(); } /** diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts index 49bf424100..7fa2415579 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.ts @@ -25,13 +25,20 @@ export class UmbAuthContext extends UmbBaseController { /** * Initiates the login flow. */ - login(): void { + makeAuthorizationRequest() { return this.#authFlow.makeAuthorizationRequest(); } + /** + * Completes the login flow. + */ + completeAuthorizationRequest() { + return this.#authFlow.completeAuthorizationIfPossible(); + } + /** * Checks if the user is authorized. If Authorization is bypassed, the user is always authorized. - * @returns {boolean} True if the user is authorized, otherwise false. + * @returns True if the user is authorized, otherwise false. */ getIsAuthorized() { if (this.#isBypassed) { From c2738c645a2d7d5a5586362e75f610c47043ba68 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:53:30 +0100 Subject: [PATCH 56/81] make the app element wait with any redirects if there is a ?code in the url, and make sure the authorization notifier makes the final redirect after the authorization request has been completed bonus: move magic strings into constants --- .../src/apps/app/app.element.ts | 34 +++++++++++-------- .../src/shared/auth/auth-flow.ts | 29 ++++++++++------ .../src/shared/auth/auth.context.token.ts | 2 ++ 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts index b9bf8a3b10..1663dd3d26 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app.element.ts @@ -1,8 +1,8 @@ import type { UmbAppErrorElement } from './app-error.element.js'; import { UmbAppContext } from './app.context.js'; import { UmbServerConnection } from './server-connection.js'; -import type { UMB_AUTH_CONTEXT} from '@umbraco-cms/backoffice/auth'; -import { UmbAuthContext } from '@umbraco-cms/backoffice/auth'; +import type { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; +import { UMB_STORAGE_REDIRECT_URL, UmbAuthContext } from '@umbraco-cms/backoffice/auth'; import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UUIIconRegistryEssential } from '@umbraco-cms/backoffice/external/uui'; import { UmbIconRegistry } from '@umbraco-cms/backoffice/icon'; @@ -29,13 +29,12 @@ export class UmbAppElement extends UmbLitElement { * @attr */ @property({ type: String }) - // TODO: get from server config + // TODO: get from base element or maybe move to UmbAuthContext.#getRedirectUrl since it is only used there backofficePath = '/umbraco'; /** * Bypass authentication. */ - // TODO: this might not be the right solution @property({ type: Boolean }) bypassAuth = false; @@ -140,6 +139,15 @@ export class UmbAppElement extends UmbLitElement { } #redirect() { + // If there is a ?code parameter in the url, then we are in the middle of the oauth flow + // and we need to complete the login (the authorization notifier will redirect after this is done + // essentially hitting this method again) + const queryParams = new URLSearchParams(window.location.search); + if (queryParams.has('code')) { + this.#authContext?.completeAuthorizationRequest(); + return; + } + switch (this.#serverConnection?.getStatus()) { case RuntimeLevelModel.INSTALL: history.replaceState(null, '', 'install'); @@ -156,17 +164,15 @@ export class UmbAppElement extends UmbLitElement { case RuntimeLevelModel.RUN: { const pathname = pathWithoutBasePath({ start: true, end: false }); - // If we are on the installer or upgrade page, redirect to the root - // but if not, keep the current path but replace state anyway to initialize the router - let currentRoute = location.href; - const savedRoute = sessionStorage.getItem('umb:auth:redirect'); - if (savedRoute) { - sessionStorage.removeItem('umb:auth:redirect'); - currentRoute = savedRoute; + // If we are on installer or upgrade page, redirect to the root since we are in the RUN state + if (pathname === '/install' || pathname === '/upgrade') { + history.replaceState(null, '', '/'); + break; } - const finalPath = pathname === '/install' || pathname === '/upgrade' ? '/' : currentRoute; - history.replaceState(null, '', finalPath); + // Keep the current path but replace state anyway to initialize the router + // because the router will not initialize a wildcard route by itself + history.replaceState(null, '', location.href); break; } @@ -187,7 +193,7 @@ export class UmbAppElement extends UmbLitElement { } // Save location.href so we can redirect to it after login - window.sessionStorage.setItem('umb:auth:redirect', location.href); + window.sessionStorage.setItem(UMB_STORAGE_REDIRECT_URL, location.href); // Make a request to the auth server to start the auth flow this.#authContext.makeAuthorizationRequest(); diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts index 7dbb62350c..4ced20b66d 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth-flow.ts @@ -13,9 +13,8 @@ * License for the specific language governing permissions and limitations under * the License. */ -import type { - LocationLike, - StringMap} from '@umbraco-cms/backoffice/external/openid'; +import { UMB_STORAGE_REDIRECT_URL, UMB_STORAGE_TOKEN_RESPONSE_NAME } from './auth.context.token.js'; +import type { LocationLike, StringMap } from '@umbraco-cms/backoffice/external/openid'; import { BaseTokenRequestHandler, BasicQueryStringUtils, @@ -29,13 +28,11 @@ import { GRANT_TYPE_REFRESH_TOKEN, RevokeTokenRequest, TokenRequest, - TokenResponse + TokenResponse, } from '@umbraco-cms/backoffice/external/openid'; const requestor = new FetchRequestor(); -const TOKEN_RESPONSE_NAME = 'umb:userAuthTokenResponse'; - /** * This class is needed to prevent the hash from being parsed as part of the query string. */ @@ -144,6 +141,15 @@ export class UmbAuthFlow { await this.#makeRefreshTokenRequest(response.code, codeVerifier); await this.performWithFreshTokens(); await this.#saveTokenState(); + + // Redirect to the saved state or root + let currentRoute = '/'; + const savedRoute = sessionStorage.getItem(UMB_STORAGE_REDIRECT_URL); + if (savedRoute) { + sessionStorage.removeItem(UMB_STORAGE_REDIRECT_URL); + currentRoute = savedRoute; + } + history.replaceState(null, '', currentRoute); } }); } @@ -152,17 +158,15 @@ export class UmbAuthFlow { * This method will initialize all the state needed for the auth flow. * * It will: - * - Fetch the service configuration from the server * - Check if there is a token response in local storage * - If there is a token response, check if it is valid * - If it is not valid, check if there is a new authorization to be made * - If there is a new authorization to be made, complete it * - If there is no token response, check if there is a new authorization to be made * - If there is a new authorization to be made, complete it - * - If there is no new authorization to be made, do nothing */ async setInitialState() { - const tokenResponseJson = await this.#storageBackend.getItem(TOKEN_RESPONSE_NAME); + const tokenResponseJson = await this.#storageBackend.getItem(UMB_STORAGE_TOKEN_RESPONSE_NAME); if (tokenResponseJson) { const response = new TokenResponse(JSON.parse(tokenResponseJson)); if (response.isValid()) { @@ -225,7 +229,7 @@ export class UmbAuthFlow { * Forget all cached token state */ async clearTokenStorage() { - await this.#storageBackend.removeItem(TOKEN_RESPONSE_NAME); + await this.#storageBackend.removeItem(UMB_STORAGE_TOKEN_RESPONSE_NAME); // clear the internal state this.#accessTokenResponse = undefined; @@ -310,7 +314,10 @@ export class UmbAuthFlow { */ async #saveTokenState() { if (this.#accessTokenResponse) { - await this.#storageBackend.setItem(TOKEN_RESPONSE_NAME, JSON.stringify(this.#accessTokenResponse.toJson())); + await this.#storageBackend.setItem( + UMB_STORAGE_TOKEN_RESPONSE_NAME, + JSON.stringify(this.#accessTokenResponse.toJson()), + ); } } diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts index 4725be3acb..38907f35e4 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.context.token.ts @@ -2,3 +2,5 @@ import type { UmbAuthContext } from './auth.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_AUTH_CONTEXT = new UmbContextToken('UmbAuthContext'); +export const UMB_STORAGE_TOKEN_RESPONSE_NAME = 'umb:userAuthTokenResponse'; +export const UMB_STORAGE_REDIRECT_URL = 'umb:auth:redirect'; From d40be8cdd81d72c2d77571f0562133eb3c7160de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Jan 2024 13:29:02 +0100 Subject: [PATCH 57/81] refactor --- .../src/libs/element-api/element.mixin.ts | 8 +- .../registry/extension.registry.ts | 62 +++++- .../src/libs/localization-api/index.ts | 4 +- ...est.ts => localization.controller.test.ts} | 20 +- ...ntroller.ts => localization.controller.ts} | 64 +++--- .../localization-api/localization.manager.ts | 106 ++++++++++ .../src/libs/localization-api/manager.ts | 73 ------- .../localization/localize.element.test.ts | 4 +- .../registry/localization.registry.test.ts | 2 +- .../registry/localization.registry.ts | 183 +++++++++--------- .../section-sidebar.element.ts | 2 + .../tree-menu-item-default.element.ts | 5 +- .../user/current-user/current-user.context.ts | 3 +- 13 files changed, 305 insertions(+), 231 deletions(-) rename src/Umbraco.Web.UI.Client/src/libs/localization-api/{localize.controller.test.ts => localization.controller.test.ts} (91%) rename src/Umbraco.Web.UI.Client/src/libs/localization-api/{localize.controller.ts => localization.controller.ts} (72%) create mode 100644 src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/libs/localization-api/manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts index 8f3c361bbf..604601de81 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts @@ -1,4 +1,4 @@ -import { UmbLocalizeController } from '@umbraco-cms/backoffice/localization-api'; +import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/extension-api'; import { UmbControllerHostElementMixin, type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; @@ -34,14 +34,14 @@ export declare class UmbElement extends UmbControllerHostElement { ): UmbContextConsumerController; /** * Use the UmbLocalizeController to localize your element. - * @see UmbLocalizeController + * @see UmbLocalizationController */ - localize: UmbLocalizeController; + localize: UmbLocalizationController; } export const UmbElementMixin = (superClass: T) => { class UmbElementMixinClass extends UmbControllerHostElementMixin(superClass) implements UmbElement { - localize: UmbLocalizeController = new UmbLocalizeController(this); + localize: UmbLocalizationController = new UmbLocalizationController(this); /** * @description Observe a RxJS source of choice. 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 2a86b6b220..26622af8fd 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 @@ -1,15 +1,8 @@ import type { ManifestBase, ManifestKind } from '../types/index.js'; import type { ManifestTypeMap, SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { - Observable} from '@umbraco-cms/backoffice/external/rxjs'; -import { - map, - distinctUntilChanged, - combineLatest, - of, - switchMap, -} from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; function extensionArrayMemoization>( previousValue: Array, @@ -213,6 +206,7 @@ export class UmbExtensionRegistry< ) as unknown as Observable>; } + // TODO: get rid of the name get getByAlias(alias: string) { return this.extensions.pipe( map((exts) => exts.find((ext) => ext.alias === alias)), @@ -245,6 +239,7 @@ export class UmbExtensionRegistry< ) as Observable; } + // TODO: get rid of the name get getByTypeAndAlias< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, @@ -275,6 +270,7 @@ export class UmbExtensionRegistry< ) as Observable; } + // TODO: get rid of the name get getByTypeAndAliases< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, @@ -306,6 +302,49 @@ export class UmbExtensionRegistry< ) as Observable>; } + /** + * Get an observable of an extension by type and a given filter method. + * This will return the all extensions that matches the type and which filter method returns true. + * The filter method will be called for each extension manifest of the given type, and the first argument to it is the extension manifest. + * @param type {string} - The type of the extension to get + * @param filter {(ext: T): void} - The filter method to use to filter the extensions + * @returns {Observable} - An observable of the extensions that matches the type and filter method + */ + byTypeAndFilter< + Key extends keyof ManifestTypeMap | string, + T extends ManifestBase = SpecificManifestTypeOrManifestBase, + >(type: Key, filter: (ext: T) => boolean) { + return combineLatest([ + this.extensions.pipe( + map((exts) => exts.find((ext) => ext.type === type && filter(ext as unknown as T))), + distinctUntilChanged(extensionSingleMemoization), + ), + this._kindsOfType(type), + ]).pipe( + map(([ext, kinds]) => { + // TODO: share one merge function between the different methods of this class: + // Specific Extension Meta merge (does not merge conditions) + if (ext) { + const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; + if (baseManifest) { + const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; + if ((baseManifest as any).meta) { + merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; + } + return merged; + } + } + return ext; + }), + distinctUntilChanged(extensionAndKindMatchSingleMemoization), + ) as Observable; + } + + /** + * Get an observable that provides extensions matching the given type. + * @param type {string} - The type of the extensions to get. + * @returns {Observable} - An observable of the extensions that matches the type. + */ extensionsOfType< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, @@ -331,6 +370,11 @@ export class UmbExtensionRegistry< ) as Observable>; } + /** + * Get an observable that provides extensions matching given types. + * @param type {Array} - The types of the extensions to get. + * @returns {Observable} - An observable of the extensions that matches the types. + */ extensionsOfTypes( types: string[], ): Observable> { diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/index.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/index.ts index 0f691deadf..5527ef1f2d 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/index.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/index.ts @@ -1,3 +1,3 @@ -export * from './localize.controller.js'; +export * from './localization.controller.js'; export * from './types/localization.js'; -export * from './manager.js'; +export * from './localization.manager.js'; diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localize.controller.test.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts similarity index 91% rename from src/Umbraco.Web.UI.Client/src/libs/localization-api/localize.controller.test.ts rename to src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts index 4a64d36c92..3f21914a19 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localize.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts @@ -1,7 +1,7 @@ import { aTimeout, elementUpdated, expect, fixture, html } from '@open-wc/testing'; -import type { DefaultLocalizationSet, LocalizationSet} from './manager.js'; -import { registerLocalization, localizations } from './manager.js'; -import { UmbLocalizeController } from './localize.controller.js'; +import type { UmbLocalizationSet, UmbLocalizationSetBase } from './localization.manager.js'; +import { registerLocalization, localizations } from './localization.manager.js'; +import { UmbLocalizationController } from './localization.controller.js'; import { LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -11,7 +11,7 @@ class UmbLocalizeControllerHostElement extends UmbElementMixin(LitElement) { @property() lang = 'en-us'; } -interface TestLocalization extends LocalizationSet { +interface TestLocalization extends UmbLocalizationSetBase { close: string; logout: string; withInlineToken: any; @@ -36,20 +36,20 @@ const english: TestLocalization = { }, }; -const englishOverride: DefaultLocalizationSet = { +const englishOverride: UmbLocalizationSet = { $code: 'en-us', $dir: 'ltr', close: 'Close 2', }; -const danish: DefaultLocalizationSet = { +const danish: UmbLocalizationSet = { $code: 'da', $dir: 'ltr', close: 'Luk', notOnRegional: 'Not on regional', }; -const danishRegional: DefaultLocalizationSet = { +const danishRegional: UmbLocalizationSet = { $code: 'da-dk', $dir: 'ltr', close: 'Luk', @@ -57,7 +57,7 @@ const danishRegional: DefaultLocalizationSet = { //#endregion describe('UmbLocalizeController', () => { - let controller: UmbLocalizeController; + let controller: UmbLocalizationController; beforeEach(async () => { registerLocalization(english, danish, danishRegional); @@ -72,7 +72,7 @@ describe('UmbLocalizeController', () => { getControllers: () => [], removeControllerByAlias: () => {}, } satisfies UmbControllerHost; - controller = new UmbLocalizeController(host); + controller = new UmbLocalizationController(host); }); afterEach(() => { @@ -226,7 +226,7 @@ describe('UmbLocalizeController', () => { }); it('should have a localize controller', () => { - expect(element.localize).to.be.instanceOf(UmbLocalizeController); + expect(element.localize).to.be.instanceOf(UmbLocalizationController); }); it('should update the term when the language changes', async () => { diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localize.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts similarity index 72% rename from src/Umbraco.Web.UI.Client/src/libs/localization-api/localize.controller.ts rename to src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts index 09d8054575..1d428ebbe6 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localize.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.ts @@ -11,20 +11,12 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import type { - DefaultLocalizationSet, - FunctionParams, - LocalizationSet} from './manager.js'; -import { - connectedElements, - documentDirection, - documentLanguage, - fallback, - localizations, -} from './manager.js'; +import type { UmbLocalizationSet, FunctionParams, UmbLocalizationSetBase } from './localization.manager.js'; +import { umbLocalizationManager } from './localization.manager.js'; +import type { LitElement } from '@umbraco-cms/backoffice/external/lit'; import type { UmbController, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -const LocalizeControllerAlias = Symbol(); +const LocalizationControllerAlias = Symbol(); /** * The UmbLocalizeController enables localization for your element. * @@ -43,12 +35,11 @@ const LocalizeControllerAlias = Symbol(); * } * ``` */ -export class UmbLocalizeController - implements UmbController -{ +export class UmbLocalizationController implements UmbController { #host; - #hostEl; - controllerAlias = LocalizeControllerAlias; + #hostEl?: HTMLElement & Partial>; + readonly controllerAlias = LocalizationControllerAlias; + #usedKeys = new Array(); constructor(host: UmbControllerHost) { this.#host = host; @@ -57,15 +48,11 @@ export class UmbLocalizeController) { + const hasOneOfTheseKeys = this.#usedKeys.find((key) => changedKeys.has(key)); + + if (hasOneOfTheseKeys) { + this.#hostEl?.requestUpdate?.(); + } + } + /** * Gets the host element's directionality as determined by the `dir` attribute. The return value is transformed to * lowercase. */ dir() { - return `${this.#hostEl.dir || documentDirection}`.toLowerCase(); + return `${this.#hostEl?.dir || umbLocalizationManager.documentDirection}`.toLowerCase(); } /** @@ -86,21 +85,23 @@ export class UmbLocalizeControllerlocalizations.get(`${language}-${region}`); - const secondary = localizations.get(language); + const primary = umbLocalizationManager.localizations.get(`${language}-${region}`); + const secondary = umbLocalizationManager.localizations.get(language); return { locale, language, region, primary, secondary }; } /** Outputs a translated term. */ - term(key: K, ...args: FunctionParams): string { + term(key: K, ...args: FunctionParams): string { + this.#usedKeys.push(key); + const { primary, secondary } = this.getLocalizationData(this.lang()); let term: any; @@ -109,8 +110,11 @@ export class UmbLocalizeController = T extends (...args: infer U) => string ? U : []; + +export interface UmbLocalizationSetBase { + $code: string; // e.g. en, en-GB + $dir: 'ltr' | 'rtl'; +} +export interface UmbLocalizationSet extends UmbLocalizationSetBase { + [key: string]: UmbLocalizationEntry; +} + +export class UmbLocalizationManager { + connectedControllers = new Set(); + #documentElementObserver: MutationObserver; + + #changedKeys: Set = new Set(); + #requestUpdateChangedKeysId?: number = undefined; + + localizations: Map = new Map(); + documentDirection = document.documentElement.dir || 'ltr'; + documentLanguage = document.documentElement.lang || navigator.language; + fallback?: UmbLocalizationSetBase; + + constructor() { + this.#documentElementObserver = new MutationObserver(this.updateAll); + this.#documentElementObserver.observe(document.documentElement, { + attributes: true, + attributeFilter: ['dir', 'lang'], + }); + } + + appendConsumer(consumer: UmbLocalizationController) { + if (this.connectedControllers.has(consumer)) return; + this.connectedControllers.add(consumer); + } + removeConsumer(consumer: UmbLocalizationController) { + this.connectedControllers.delete(consumer); + } + + /** Registers one or more translations */ + registerLocalization(t: UmbLocalizationSetBase) { + const code = t.$code.toLowerCase(); + + if (this.localizations.has(code)) { + // Merge translations that share the same language code + this.localizations.set(code, { ...this.localizations.get(code), ...t }); + } else { + this.localizations.set(code, t); + } + + // The first translation we registerer will become the fallback + if (!this.fallback) { + this.fallback = t; + } + + this.requestChangedKeysUpdate(); + } + #registerLocalizationBind = this.registerLocalization.bind(this); + + registerManyLocalizations(translations: Array) { + translations.map(this.#registerLocalizationBind); + } + + /** Updates all localized elements that are currently connected */ + updateAll = () => { + this.documentDirection = document.documentElement.dir || 'ltr'; + this.documentLanguage = document.documentElement.lang || navigator.language; + + // Check if there was any changed. + this.connectedControllers.forEach((ctrl) => { + ctrl.documentUpdate(); + }); + + this.#changedKeys.clear(); + }; + + updateChangedKeys = () => { + this.connectedControllers.forEach((ctrl) => { + ctrl.keysChanged(this.#changedKeys); + }); + + this.#changedKeys.clear(); + }; + + requestChangedKeysUpdate() { + if (this.#requestUpdateChangedKeysId) return; + this.#requestUpdateChangedKeysId = requestAnimationFrame(this.updateChangedKeys); + } +} + +export const umbLocalizationManager = new UmbLocalizationManager(); diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/manager.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/manager.ts deleted file mode 100644 index 6148e0f52c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/manager.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* -This module is a modified copy of the original Shoelace localize package: https://github.com/shoelace-style/localize - -The original license is included below. - -Copyright (c) 2020 A Beautiful Site, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -import type { UmbLocalizationEntry } from './types/localization.js'; -import type { LitElement } from '@umbraco-cms/backoffice/external/lit'; - -export type FunctionParams = T extends (...args: infer U) => string ? U : []; - -export interface LocalizationSet { - $code: string; // e.g. en, en-GB - $dir: 'ltr' | 'rtl'; -} - -export interface DefaultLocalizationSet extends LocalizationSet { - [key: string]: UmbLocalizationEntry; -} - -export const connectedElements = new Set(); -const documentElementObserver = new MutationObserver(update); -export const localizations: Map = new Map(); -export let documentDirection = document.documentElement.dir || 'ltr'; -export let documentLanguage = document.documentElement.lang || navigator.language; -export let fallback: LocalizationSet; - -// Watch for changes on -documentElementObserver.observe(document.documentElement, { - attributes: true, - attributeFilter: ['dir', 'lang'], -}); - -/** Registers one or more translations */ -export function registerLocalization(...translation: LocalizationSet[]) { - translation.map((t) => { - const code = t.$code.toLowerCase(); - - if (localizations.has(code)) { - // Merge translations that share the same language code - localizations.set(code, { ...localizations.get(code), ...t }); - } else { - localizations.set(code, t); - } - - // The first translation that's registered is the fallback - if (!fallback) { - fallback = t; - } - }); - - update(); -} - -/** Updates all localized elements that are currently connected */ -export function update() { - documentDirection = document.documentElement.dir || 'ltr'; - documentLanguage = document.documentElement.lang || navigator.language; - - [...connectedElements.keys()].map((el) => { - if (typeof (el as LitElement).requestUpdate === 'function') { - // TODO: We might want to implement a specific Umbraco method for informing about this. and then make the default UmbLitElement call requestUpdate..? Cause then others can implement their own solution? - (el as LitElement).requestUpdate(); - } - }); -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/localize.element.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/localize.element.test.ts index 3db7df5f70..2280d2be64 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/localize.element.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/localize.element.test.ts @@ -2,7 +2,7 @@ import { aTimeout, elementUpdated, expect, fixture, html } from '@open-wc/testin import { UmbLocalizeElement } from './localize.element.js'; import { umbLocalizationRegistry } from '@umbraco-cms/backoffice/localization'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbLocalizeController } from '@umbraco-cms/backoffice/localization-api'; +import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; const english = { type: 'localization', @@ -62,7 +62,7 @@ describe('umb-localize', () => { }); it('should have a localize controller', () => { - expect(element.localize).to.be.instanceOf(UmbLocalizeController); + expect(element.localize).to.be.instanceOf(UmbLocalizationController); }); it('should localize a key', async () => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.test.ts index 10ffa5d6e1..82ba527409 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.test.ts @@ -1,6 +1,6 @@ import { aTimeout, expect } from '@open-wc/testing'; import { UmbLocalizationRegistry } from './localization.registry.js'; -import type { ManifestLocalization} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestLocalization } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; //#region Localizations diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index c123b55f54..3af9c6bc7d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -1,129 +1,122 @@ import type { + UmbLocalizationSetBase, UmbLocalizationDictionary, UmbLocalizationFlatDictionary, - LocalizationSet} from '@umbraco-cms/backoffice/localization-api'; -import { - registerLocalization, - localizations, } from '@umbraco-cms/backoffice/localization-api'; -import { hasDefaultExport, loadManifestPlainJs } from '@umbraco-cms/backoffice/extension-api'; -import type { UmbBackofficeExtensionRegistry} from '@umbraco-cms/backoffice/extension-registry'; +import { umbLocalizationManager } from '@umbraco-cms/backoffice/localization-api'; +import type { ManifestLocalization, UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { - BehaviorSubject, - Subject, - combineLatest, - map, - distinctUntilChanged, - filter, - startWith, -} from '@umbraco-cms/backoffice/external/rxjs'; +import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; +import { combineLatest } from '@umbraco-cms/backoffice/external/rxjs'; +import { hasDefaultExport, loadManifestPlainJs } from '@umbraco-cms/backoffice/extension-api'; + +function addOrUpdateDictionary( + innerDictionary: UmbLocalizationFlatDictionary, + dictionaryName: string, + dictionary: UmbLocalizationDictionary['value'], +) { + for (const [key, value] of Object.entries(dictionary)) { + innerDictionary[`${dictionaryName}_${key}`] = value; + } +} export class UmbLocalizationRegistry { + // + #isDefaultLoadedPromise?: Promise; + #isDefaultLoadedResolve?: (value: boolean) => void; + + #currentLanguage = new UmbStringState(document.documentElement.lang ?? 'en-us'); + readonly currentLanguage = this.#currentLanguage.asObservable(); + + #loadedExtAliases: Array = []; + /** * Get the current registered translations. */ get localizations() { - return localizations; + return umbLocalizationManager.localizations; } get isDefaultLoaded() { - return this.#isDefaultLoaded.asObservable(); + this.#isDefaultLoadedPromise ??= new Promise((resolve) => { + this.#isDefaultLoadedResolve = resolve; + }); + return this.#isDefaultLoadedPromise; } - #currentLanguage = new Subject(); - #isDefaultLoaded = new BehaviorSubject(false); - constructor(extensionRegistry: UmbBackofficeExtensionRegistry) { - const currentLanguage$ = this.#currentLanguage.pipe( - startWith(document.documentElement.lang || 'en-us'), - map((x) => x.toLowerCase()), - distinctUntilChanged(), - ); + combineLatest([this.currentLanguage, extensionRegistry.extensionsOfType('localization')]).subscribe( + async ([currentLanguage, extensions]) => { + const locale = new Intl.Locale(currentLanguage); + const filteredExt = extensions.filter( + (ext) => + ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() || + ext.meta.culture.toLowerCase() === locale.language.toLowerCase(), + ); - const currentExtensions$ = extensionRegistry.extensionsOfType('localization').pipe( - filter((x) => x.length > 0), - distinctUntilChanged((prev, curr) => prev.length === curr.length && prev.every((x) => curr.includes(x))), - ); + // Check if there is any difference to the cached aliases + const diff = filteredExt.filter((ext) => !this.#loadedExtAliases.includes(ext.alias)); + if (diff.length !== 0) { + // got new localizations to load: + const translations = await Promise.all(diff.map(this.#loadExtension)); - combineLatest([currentLanguage$, currentExtensions$]).subscribe(async ([userCulture, extensions]) => { - const locale = new Intl.Locale(userCulture); - const translations = await Promise.all( - extensions - .filter( - (x) => - x.meta.culture.toLowerCase() === locale.baseName.toLowerCase() || - x.meta.culture.toLowerCase() === locale.language.toLowerCase(), - ) - .map(async (extension) => { - const innerDictionary: UmbLocalizationFlatDictionary = {}; + if (translations.length) { + umbLocalizationManager.registerManyLocalizations(translations); - // If extension contains a dictionary, add it to the inner dictionary. - if (extension.meta.localizations) { - for (const [dictionaryName, dictionary] of Object.entries(extension.meta.localizations)) { - this.#addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary); - } + // Set the document language + const newLang = locale.baseName.toLowerCase(); + if (document.documentElement.lang.toLowerCase() !== newLang) { + document.documentElement.lang = newLang; } - // If extension contains a js file, load it and add the default dictionary to the inner dictionary. - if (extension.js) { - const loadedExtension = await loadManifestPlainJs(extension.js); - - if (loadedExtension && hasDefaultExport(loadedExtension)) { - for (const [dictionaryName, dictionary] of Object.entries(loadedExtension.default)) { - this.#addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary); - } - } + // Set the document direction to the direction of the primary language + const newDir = translations[0].$dir ?? 'ltr'; + if (document.documentElement.dir !== newDir) { + document.documentElement.dir = newDir; } - - // Notify subscribers that the inner dictionary has changed. - return { - $code: extension.meta.culture.toLowerCase(), - $dir: extension.meta.direction ?? 'ltr', - ...innerDictionary, - } satisfies LocalizationSet; - }), - ); - - if (translations.length) { - registerLocalization(...translations); - - // Set the document language - const newLang = locale.baseName.toLowerCase(); - if (document.documentElement.lang.toLowerCase() !== newLang) { - document.documentElement.lang = newLang; + } } - - // Set the document direction to the direction of the primary language - const newDir = translations[0].$dir ?? 'ltr'; - if (document.documentElement.dir !== newDir) { - document.documentElement.dir = newDir; - } - } - - if (!this.#isDefaultLoaded.value) { - this.#isDefaultLoaded.next(true); - this.#isDefaultLoaded.complete(); - } - }); + }, + ); } + #loadExtension = async (extension: ManifestLocalization) => { + this.#loadedExtAliases.push(extension.alias); + + const innerDictionary: UmbLocalizationFlatDictionary = {}; + + // If extension contains a dictionary, add it to the inner dictionary. + if (extension.meta.localizations) { + for (const [dictionaryName, dictionary] of Object.entries(extension.meta.localizations)) { + addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary); + } + } + + // If extension contains a js file, load it and add the default dictionary to the inner dictionary. + if (extension.js) { + const loadedExtension = await loadManifestPlainJs(extension.js); + + if (loadedExtension && hasDefaultExport(loadedExtension)) { + for (const [dictionaryName, dictionary] of Object.entries(loadedExtension.default)) { + addOrUpdateDictionary(innerDictionary, dictionaryName, dictionary); + } + } + } + + // Notify subscribers that the inner dictionary has changed. + return { + $code: extension.meta.culture.toLowerCase(), + $dir: extension.meta.direction ?? 'ltr', + ...innerDictionary, + } satisfies UmbLocalizationSetBase; + }; + /** * Load a language from the extension registry. * @param locale The locale to load. */ loadLanguage(locale: string) { - this.#currentLanguage.next(locale); - } - - #addOrUpdateDictionary( - innerDictionary: UmbLocalizationFlatDictionary, - dictionaryName: string, - dictionary: UmbLocalizationDictionary['value'], - ) { - for (const [key, value] of Object.entries(dictionary)) { - innerDictionary[`${dictionaryName}_${key}`] = value; - } + this.#currentLanguage.setValue(locale.toLowerCase()); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts index 28fa72bb14..19eeef0b32 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts @@ -13,6 +13,8 @@ export class UmbSectionSidebarElement extends UmbLitElement { } render() { + // TODO: just for testing purpose, should be removed in PR. + console.log('Render', this); return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/tree-menu-item-default.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/tree-menu-item-default.element.ts index 7d59390733..f06de51854 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/tree-menu-item-default.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-menu-item-default/tree-menu-item-default.element.ts @@ -3,10 +3,9 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { ManifestMenuItemTreeKind, UmbBackofficeManifestKind, - UmbMenuItemElement} from '@umbraco-cms/backoffice/extension-registry'; -import { - umbExtensionsRegistry, + UmbMenuItemElement, } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; // TODO: Move to separate file: const manifest: UmbBackofficeManifestKind = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts index a41700c52d..ddac865d44 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts @@ -25,8 +25,7 @@ export class UmbCurrentUserContext extends UmbBaseController { this.#observeIsAuthorized(); }); - // TODO: revisit this. It can probably be simplified - this.observe(umbLocalizationRegistry.isDefaultLoaded, (isDefaultLoaded) => { + umbLocalizationRegistry.isDefaultLoaded.then((isDefaultLoaded) => { if (!isDefaultLoaded) return; this.observe( From 83b466cacc7fa0f7e753fd2688915408b2674cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Jan 2024 14:57:04 +0100 Subject: [PATCH 58/81] only update if document lang or dir was changed --- .../localization-api/localization.manager.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts index 31bd88ce99..b5b58c0fc9 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts @@ -78,18 +78,30 @@ export class UmbLocalizationManager { /** Updates all localized elements that are currently connected */ updateAll = () => { - this.documentDirection = document.documentElement.dir || 'ltr'; - this.documentLanguage = document.documentElement.lang || navigator.language; + const newDir = document.documentElement.dir || 'ltr'; + const newLang = document.documentElement.lang || navigator.language; + + if (this.documentDirection === newDir && this.documentLanguage === newLang) return; + + // The document direction or language did changed, so lets move on: + this.documentDirection = newDir; + this.documentLanguage = newLang; // Check if there was any changed. this.connectedControllers.forEach((ctrl) => { ctrl.documentUpdate(); }); + if (this.#requestUpdateChangedKeysId) { + cancelAnimationFrame(this.#requestUpdateChangedKeysId); + this.#requestUpdateChangedKeysId = undefined; + } this.#changedKeys.clear(); }; updateChangedKeys = () => { + this.#requestUpdateChangedKeysId = undefined; + this.connectedControllers.forEach((ctrl) => { ctrl.keysChanged(this.#changedKeys); }); From 444cae8b31a712c0b9cfe27a1c3e9f6f108aa5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Jan 2024 15:15:24 +0100 Subject: [PATCH 59/81] a bit of more restructuring --- .../localization.controller.test.ts | 10 ++--- .../localization.controller.ts | 28 ++++++++------ .../localization-api/localization.manager.ts | 37 +++++++++++-------- .../registry/localization.registry.ts | 13 +------ .../section-sidebar.element.ts | 2 - .../user/current-user/current-user.context.ts | 12 +----- 6 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts index 3f21914a19..695c9b756c 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts @@ -1,6 +1,6 @@ import { aTimeout, elementUpdated, expect, fixture, html } from '@open-wc/testing'; import type { UmbLocalizationSet, UmbLocalizationSetBase } from './localization.manager.js'; -import { registerLocalization, localizations } from './localization.manager.js'; +import { umbLocalizationManager } from './localization.manager.js'; import { UmbLocalizationController } from './localization.controller.js'; import { LitElement, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; @@ -57,10 +57,10 @@ const danishRegional: UmbLocalizationSet = { //#endregion describe('UmbLocalizeController', () => { - let controller: UmbLocalizationController; + let controller: UmbLocalizationController; beforeEach(async () => { - registerLocalization(english, danish, danishRegional); + umbLocalizationManager.registerManyLocalizations([english, danish, danishRegional]); document.documentElement.lang = english.$code; document.documentElement.dir = english.$dir; await aTimeout(0); @@ -77,7 +77,7 @@ describe('UmbLocalizeController', () => { afterEach(() => { controller.destroy(); - localizations.clear(); + umbLocalizationManager.localizations.clear(); }); it('should have a default language', () => { @@ -132,7 +132,7 @@ describe('UmbLocalizeController', () => { it('should override a term if new translation is registered', () => { // Let the registry load the new extension - registerLocalization(englishOverride); + umbLocalizationManager.registerLocalization(englishOverride); expect(controller.term('close')).to.equal('Close 2'); }); 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 1d428ebbe6..dd20e23ebd 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 @@ -11,7 +11,12 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import type { UmbLocalizationSet, FunctionParams, UmbLocalizationSetBase } from './localization.manager.js'; +import type { + UmbLocalizationSet, + FunctionParams, + UmbLocalizationSetBase, + UmbLocalizationSetKey, +} from './localization.manager.js'; import { umbLocalizationManager } from './localization.manager.js'; import type { LitElement } from '@umbraco-cms/backoffice/external/lit'; import type { UmbController, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -35,11 +40,13 @@ const LocalizationControllerAlias = Symbol(); * } * ``` */ -export class UmbLocalizationController implements UmbController { +export class UmbLocalizationController + implements UmbController +{ #host; #hostEl?: HTMLElement & Partial>; readonly controllerAlias = LocalizationControllerAlias; - #usedKeys = new Array(); + #usedKeys = new Array(); constructor(host: UmbControllerHost) { this.#host = host; @@ -64,7 +71,7 @@ export class UmbLocalizationController implements UmbController { this.#hostEl?.requestUpdate?.(); } - keysChanged(changedKeys: Set) { + keysChanged(changedKeys: Set) { const hasOneOfTheseKeys = this.#usedKeys.find((key) => changedKeys.has(key)); if (hasOneOfTheseKeys) { @@ -92,14 +99,14 @@ export class UmbLocalizationController implements UmbController { const locale = new Intl.Locale(lang); const language = locale?.language.toLowerCase(); const region = locale?.region?.toLowerCase() ?? ''; - const primary = umbLocalizationManager.localizations.get(`${language}-${region}`); - const secondary = umbLocalizationManager.localizations.get(language); + const primary = umbLocalizationManager.localizations.get(`${language}-${region}`) as LocalizationSetType; + const secondary = umbLocalizationManager.localizations.get(language) as LocalizationSetType; return { locale, language, region, primary, secondary }; } /** Outputs a translated term. */ - term(key: K, ...args: FunctionParams): string { + term(key: K, ...args: FunctionParams): string { this.#usedKeys.push(key); const { primary, secondary } = this.getLocalizationData(this.lang()); @@ -110,11 +117,8 @@ export class UmbLocalizationController implements UmbController { term = primary[key]; } else if (secondary && secondary[key]) { term = secondary[key]; - } else if ( - umbLocalizationManager.fallback && - umbLocalizationManager.fallback[key as keyof UmbLocalizationSetBase] - ) { - term = umbLocalizationManager.fallback[key as keyof UmbLocalizationSetBase]; + } else if (umbLocalizationManager.fallback && umbLocalizationManager.fallback[key]) { + term = umbLocalizationManager.fallback[key]; } else { return String(key); } diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts index b5b58c0fc9..e481072374 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts @@ -20,21 +20,29 @@ export interface UmbLocalizationSetBase { $code: string; // e.g. en, en-GB $dir: 'ltr' | 'rtl'; } + +export type UmbLocalizationSetKey = string | number | symbol; + export interface UmbLocalizationSet extends UmbLocalizationSetBase { - [key: string]: UmbLocalizationEntry; + [key: UmbLocalizationSetKey]: UmbLocalizationEntry; } +export const UMB_DEFAULT_LOCALIZATION_CULTURE = 'en-us'; + export class UmbLocalizationManager { - connectedControllers = new Set(); + connectedControllers = new Set>(); #documentElementObserver: MutationObserver; - #changedKeys: Set = new Set(); + #changedKeys: Set = new Set(); #requestUpdateChangedKeysId?: number = undefined; localizations: Map = new Map(); documentDirection = document.documentElement.dir || 'ltr'; documentLanguage = document.documentElement.lang || navigator.language; - fallback?: UmbLocalizationSetBase; + + get fallback(): UmbLocalizationSet | undefined { + return this.localizations.get(UMB_DEFAULT_LOCALIZATION_CULTURE) as UmbLocalizationSet; + } constructor() { this.#documentElementObserver = new MutationObserver(this.updateAll); @@ -44,11 +52,11 @@ export class UmbLocalizationManager { }); } - appendConsumer(consumer: UmbLocalizationController) { + appendConsumer(consumer: UmbLocalizationController) { if (this.connectedControllers.has(consumer)) return; this.connectedControllers.add(consumer); } - removeConsumer(consumer: UmbLocalizationController) { + removeConsumer(consumer: UmbLocalizationController) { this.connectedControllers.delete(consumer); } @@ -63,12 +71,7 @@ export class UmbLocalizationManager { this.localizations.set(code, t); } - // The first translation we registerer will become the fallback - if (!this.fallback) { - this.fallback = t; - } - - this.requestChangedKeysUpdate(); + this.#requestChangedKeysUpdate(); } #registerLocalizationBind = this.registerLocalization.bind(this); @@ -99,7 +102,7 @@ export class UmbLocalizationManager { this.#changedKeys.clear(); }; - updateChangedKeys = () => { + #updateChangedKeys = () => { this.#requestUpdateChangedKeysId = undefined; this.connectedControllers.forEach((ctrl) => { @@ -109,9 +112,13 @@ export class UmbLocalizationManager { this.#changedKeys.clear(); }; - requestChangedKeysUpdate() { + /** + * Request an update of all consumers of the keys defined in #changedKeys. + * This waits one frame, which ensures that multiple changes are collected into one. + */ + #requestChangedKeysUpdate() { if (this.#requestUpdateChangedKeysId) return; - this.#requestUpdateChangedKeysId = requestAnimationFrame(this.updateChangedKeys); + this.#requestUpdateChangedKeysId = requestAnimationFrame(this.#updateChangedKeys); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index 3af9c6bc7d..708e437f84 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -21,10 +21,6 @@ function addOrUpdateDictionary( } export class UmbLocalizationRegistry { - // - #isDefaultLoadedPromise?: Promise; - #isDefaultLoadedResolve?: (value: boolean) => void; - #currentLanguage = new UmbStringState(document.documentElement.lang ?? 'en-us'); readonly currentLanguage = this.#currentLanguage.asObservable(); @@ -37,13 +33,6 @@ export class UmbLocalizationRegistry { return umbLocalizationManager.localizations; } - get isDefaultLoaded() { - this.#isDefaultLoadedPromise ??= new Promise((resolve) => { - this.#isDefaultLoadedResolve = resolve; - }); - return this.#isDefaultLoadedPromise; - } - constructor(extensionRegistry: UmbBackofficeExtensionRegistry) { combineLatest([this.currentLanguage, extensionRegistry.extensionsOfType('localization')]).subscribe( async ([currentLanguage, extensions]) => { @@ -54,7 +43,7 @@ export class UmbLocalizationRegistry { ext.meta.culture.toLowerCase() === locale.language.toLowerCase(), ); - // Check if there is any difference to the cached aliases + // Only get the extensions that are not already loading/loaded: const diff = filteredExt.filter((ext) => !this.#loadedExtAliases.includes(ext.alias)); if (diff.length !== 0) { // got new localizations to load: diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts index 19eeef0b32..28fa72bb14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.element.ts @@ -13,8 +13,6 @@ export class UmbSectionSidebarElement extends UmbLitElement { } render() { - // TODO: just for testing purpose, should be removed in PR. - console.log('Render', this); return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts index ddac865d44..f891318a6d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts @@ -25,16 +25,8 @@ export class UmbCurrentUserContext extends UmbBaseController { this.#observeIsAuthorized(); }); - umbLocalizationRegistry.isDefaultLoaded.then((isDefaultLoaded) => { - if (!isDefaultLoaded) return; - - this.observe( - this.languageIsoCode, - (currentLanguageIsoCode) => { - umbLocalizationRegistry.loadLanguage(currentLanguageIsoCode); - }, - 'umbCurrentUserLanguageIsoCode', - ); + this.observe(this.languageIsoCode, (currentLanguageIsoCode) => { + umbLocalizationRegistry.loadLanguage(currentLanguageIsoCode); }); this.provideContext(UMB_CURRENT_USER_CONTEXT, this); From 37a4fee6a1a045952f239c239c9b7d1fb2d640dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Jan 2024 15:50:40 +0100 Subject: [PATCH 60/81] tests --- .../localization.controller.test.ts | 53 ++++++++++++++++++- .../localization.controller.ts | 4 +- .../localization-api/localization.manager.ts | 5 ++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts index 695c9b756c..ac1ad635d2 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts @@ -11,6 +11,22 @@ class UmbLocalizeControllerHostElement extends UmbElementMixin(LitElement) { @property() lang = 'en-us'; } +@customElement('umb-localization-render-count') +class UmbLocalizationRenderCountElement extends UmbElementMixin(LitElement) { + amountOfUpdates = 0; + amountOfRenders = 0; + + requestUpdate() { + super.requestUpdate(); + this.amountOfUpdates++; + } + + render() { + this.amountOfRenders++; + return html`${this.localize.term('logout')}`; + } +} + interface TestLocalization extends UmbLocalizationSetBase { close: string; logout: string; @@ -42,6 +58,12 @@ const englishOverride: UmbLocalizationSet = { close: 'Close 2', }; +const englishOverrideLogout: UmbLocalizationSet = { + $code: 'en-us', + $dir: 'ltr', + logout: 'Log out 2', +}; + const danish: UmbLocalizationSet = { $code: 'da', $dir: 'ltr', @@ -130,7 +152,7 @@ describe('UmbLocalizeController', () => { expect(controller.term('logout')).to.equal('Log out'); // Fallback }); - it('should override a term if new translation is registered', () => { + it('should override a term if new localization is registered', () => { // Let the registry load the new extension umbLocalizationManager.registerLocalization(englishOverride); @@ -152,6 +174,35 @@ describe('UmbLocalizeController', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any expect((controller.term as any)('logout', 'Hello', 'World')).to.equal('Log out'); }); + + it('only reacts to changes of its own localization-keys', async () => { + const element: UmbLocalizationRenderCountElement = await fixture( + html``, + ); + expect(element.amountOfUpdates).to.equal(0); + expect(element.amountOfRenders).to.equal(1); + + expect(element.shadowRoot!.textContent).to.equal('Log out'); + expect(element.amountOfUpdates).to.equal(0); + + // Let the registry load the new extension + umbLocalizationManager.registerLocalization(englishOverride); + + await aTimeout(12); + + // This should still be the same (cause it should not be affected as the change did not change our localization key) + expect(element.amountOfUpdates).to.equal(0); + expect(element.shadowRoot!.textContent).to.equal('Log out'); + + // Let the registry load the new extension + umbLocalizationManager.registerLocalization(englishOverrideLogout); + + await aTimeout(12); + + // Now we should have gotten one update and the text should be different + expect(element.amountOfUpdates).to.equal(1); + expect(element.shadowRoot!.textContent).to.equal('Log out 2'); + }); }); describe('date', () => { 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 dd20e23ebd..767370df80 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 @@ -107,7 +107,9 @@ export class UmbLocalizationController(key: K, ...args: FunctionParams): string { - this.#usedKeys.push(key); + if (!this.#usedKeys.includes(key)) { + this.#usedKeys.push(key); + } const { primary, secondary } = this.getLocalizationData(this.lang()); let term: any; diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts index e481072374..226eb5f277 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.manager.ts @@ -71,6 +71,11 @@ export class UmbLocalizationManager { this.localizations.set(code, t); } + // Declare what keys have been changed: + const keys = Object.keys(t); + for (const key of keys) { + this.#changedKeys.add(key); + } this.#requestChangedKeysUpdate(); } #registerLocalizationBind = this.registerLocalization.bind(this); From 7a5d376491b4529487c6b66d623138eba8194826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 08:50:24 +0100 Subject: [PATCH 61/81] unit test --- .../localization.controller.test.ts | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts index ac1ad635d2..44f4e7235b 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts @@ -16,6 +16,9 @@ class UmbLocalizationRenderCountElement extends UmbElementMixin(LitElement) { amountOfUpdates = 0; amountOfRenders = 0; + @property({ type: Number }) + test: number = 0; + requestUpdate() { super.requestUpdate(); this.amountOfUpdates++; @@ -23,7 +26,7 @@ class UmbLocalizationRenderCountElement extends UmbElementMixin(LitElement) { render() { this.amountOfRenders++; - return html`${this.localize.term('logout')}`; + return html`${this.localize.term('logout') + '#' + this.test}`; } } @@ -177,31 +180,44 @@ describe('UmbLocalizeController', () => { it('only reacts to changes of its own localization-keys', async () => { const element: UmbLocalizationRenderCountElement = await fixture( - html``, + html``, ); + + // Something triggers multiple updates initially, and it varies how many it is. So we wait for a timeout to ensure that we have a clean slate and then reset the counter: + await aTimeout(20); + element.amountOfUpdates = 0; + expect(element.amountOfUpdates).to.equal(0); expect(element.amountOfRenders).to.equal(1); - - expect(element.shadowRoot!.textContent).to.equal('Log out'); - expect(element.amountOfUpdates).to.equal(0); + expect(element.shadowRoot!.textContent).to.equal('Log out#10'); // Let the registry load the new extension umbLocalizationManager.registerLocalization(englishOverride); - await aTimeout(12); + // Wait three frames is safe: + await new Promise((resolve) => requestAnimationFrame(resolve)); + await new Promise((resolve) => requestAnimationFrame(resolve)); + await new Promise((resolve) => requestAnimationFrame(resolve)); // This should still be the same (cause it should not be affected as the change did not change our localization key) expect(element.amountOfUpdates).to.equal(0); - expect(element.shadowRoot!.textContent).to.equal('Log out'); + expect(element.amountOfRenders).to.equal(1); + expect(element.shadowRoot!.textContent).to.equal('Log out#10'); // Let the registry load the new extension umbLocalizationManager.registerLocalization(englishOverrideLogout); - await aTimeout(12); + // Wait three frames is safe: + await new Promise((resolve) => requestAnimationFrame(resolve)); + await new Promise((resolve) => requestAnimationFrame(resolve)); + await new Promise((resolve) => requestAnimationFrame(resolve)); // Now we should have gotten one update and the text should be different expect(element.amountOfUpdates).to.equal(1); - expect(element.shadowRoot!.textContent).to.equal('Log out 2'); + expect(element.amountOfRenders).to.equal(2); + expect(element.shadowRoot!.textContent).to.equal('Log out 2#10'); + + console.log('done'); }); }); From eb49484e320473456ec2081af8ed1900a777e3ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 08:51:57 +0100 Subject: [PATCH 62/81] clean up test --- .../localization.controller.test.ts | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts index 44f4e7235b..9df2003229 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/localization-api/localization.controller.test.ts @@ -14,10 +14,6 @@ class UmbLocalizeControllerHostElement extends UmbElementMixin(LitElement) { @customElement('umb-localization-render-count') class UmbLocalizationRenderCountElement extends UmbElementMixin(LitElement) { amountOfUpdates = 0; - amountOfRenders = 0; - - @property({ type: Number }) - test: number = 0; requestUpdate() { super.requestUpdate(); @@ -25,8 +21,7 @@ class UmbLocalizationRenderCountElement extends UmbElementMixin(LitElement) { } render() { - this.amountOfRenders++; - return html`${this.localize.term('logout') + '#' + this.test}`; + return html`${this.localize.term('logout')}`; } } @@ -180,16 +175,14 @@ describe('UmbLocalizeController', () => { it('only reacts to changes of its own localization-keys', async () => { const element: UmbLocalizationRenderCountElement = await fixture( - html``, + html``, ); // Something triggers multiple updates initially, and it varies how many it is. So we wait for a timeout to ensure that we have a clean slate and then reset the counter: await aTimeout(20); element.amountOfUpdates = 0; - expect(element.amountOfUpdates).to.equal(0); - expect(element.amountOfRenders).to.equal(1); - expect(element.shadowRoot!.textContent).to.equal('Log out#10'); + expect(element.shadowRoot!.textContent).to.equal('Log out'); // Let the registry load the new extension umbLocalizationManager.registerLocalization(englishOverride); @@ -201,8 +194,7 @@ describe('UmbLocalizeController', () => { // This should still be the same (cause it should not be affected as the change did not change our localization key) expect(element.amountOfUpdates).to.equal(0); - expect(element.amountOfRenders).to.equal(1); - expect(element.shadowRoot!.textContent).to.equal('Log out#10'); + expect(element.shadowRoot!.textContent).to.equal('Log out'); // Let the registry load the new extension umbLocalizationManager.registerLocalization(englishOverrideLogout); @@ -214,10 +206,7 @@ describe('UmbLocalizeController', () => { // Now we should have gotten one update and the text should be different expect(element.amountOfUpdates).to.equal(1); - expect(element.amountOfRenders).to.equal(2); - expect(element.shadowRoot!.textContent).to.equal('Log out 2#10'); - - console.log('done'); + expect(element.shadowRoot!.textContent).to.equal('Log out 2'); }); }); From 1ec7129a630020acd7454ad4fa270b30321d5ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 09:14:57 +0100 Subject: [PATCH 63/81] remove comment --- .../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 e205abc1a3..7fe74f0be1 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,6 @@ export class UmbBlockWorkspaceContext< readonly name = this.#label.asObservable(); constructor(host: UmbControllerHost, workspaceArgs: { manifest: ManifestWorkspace }) { - // TODO: We don't need a repo here, so maybe we should not require this of the UmbEditableWorkspaceContextBase super(host, workspaceArgs.manifest.alias); this.#entityType = workspaceArgs.manifest.meta?.entityType; this.workspaceAlias = workspaceArgs.manifest.alias; From e35911cbc47ecaee47e7cec025847701f9bdd075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 09:18:28 +0100 Subject: [PATCH 64/81] order imports --- .../property-editor-ui-block-list-type-configuration.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 57744eb391..a1a1c7de07 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,12 +1,12 @@ import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; +import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; -import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; /** * @element umb-property-editor-ui-block-list-type-configuration From 686f9b6a419667a9723283e891398cb39ebe753b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 09:54:58 +0100 Subject: [PATCH 65/81] fix js issue --- ...property-editor-ui-block-grid-type-configuration.element.ts | 2 +- ...property-editor-ui-block-list-type-configuration.element.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 9714e9cd08..10a4d4c3f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -105,7 +105,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement #onCreate(e: CustomEvent, groupKey: string | null) { const selectedElementType = e.detail.contentElementTypeKey; if (selectedElementType) { - this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/' + groupKey); + this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + groupKey + '/' + selectedElementType); } } 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 a1a1c7de07..b8941ca8b1 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 @@ -48,7 +48,8 @@ export class UmbPropertyEditorUIBlockListBlockConfigurationElement #onCreate(e: CustomEvent) { const selectedElementType = e.detail.contentElementTypeKey; if (selectedElementType) { - this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/null'); + // We do not have any groups here, which is why we pass null as the groupKey. + this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/null/' + selectedElementType); } } From 3a28c13e46a34f04790ec2a3662d541c63b98db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 09:55:10 +0100 Subject: [PATCH 66/81] remove space --- .../components/input-block-type/input-block-type.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 982b51eb4d..1dcad5fdf3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -75,7 +75,7 @@ export class UmbInputBlockTypeElement< } render() { - return html`
+ return html`
${repeat(this.value, (block) => block.contentElementTypeKey, this.#renderItem)} ${this.#renderButton()}
`; } From 9e282d7a310f6cc31b2cb0fae1e7532ff7a9f5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 09:55:19 +0100 Subject: [PATCH 67/81] remove log --- .../block/block-type/workspace/block-type-workspace.context.ts | 2 -- 1 file changed, 2 deletions(-) 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 5883299981..82ca7316ea 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 @@ -65,8 +65,6 @@ export class UmbBlockTypeWorkspaceContext Date: Fri, 26 Jan 2024 09:55:41 +0100 Subject: [PATCH 68/81] add () --- .../design/document-type-workspace-view-edit.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts index 9b9920205b..f6babbd0eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts @@ -11,12 +11,12 @@ import type { PropertyTypeContainerModelBaseModel, } from '@umbraco-cms/backoffice/backend-api'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import type { UmbRoute , UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router'; +import type { UmbRoute, UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbConfirmModalData } from '@umbraco-cms/backoffice/modal'; import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbSorterConfig} from '@umbraco-cms/backoffice/sorter'; +import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; const SORTER_CONFIG: UmbSorterConfig = { @@ -216,7 +216,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement extends UmbLitElement imple if (!tabId) return; this._workspaceContext?.structure.removeContainer(null, tabId); this._tabsStructureHelper?.isOwnerContainer(tabId) - ? window.history.replaceState(null, '', this._routerPath + this._routes[0]?.path ?? '/root') + ? window.history.replaceState(null, '', this._routerPath + (this._routes[0]?.path ?? '/root')) : ''; } async #addTab() { From cd9c729f33fbf58eb23be3e19da820fbc44fc3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 09:55:52 +0100 Subject: [PATCH 69/81] add () --- .../views/design/media-type-workspace-view-edit.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/design/media-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/design/media-type-workspace-view-edit.element.ts index a920094e78..cd24e5cf44 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/design/media-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/design/media-type-workspace-view-edit.element.ts @@ -11,12 +11,12 @@ import type { PropertyTypeContainerModelBaseModel, } from '@umbraco-cms/backoffice/backend-api'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import type { UmbRoute , UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router'; +import type { UmbRoute, UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbConfirmModalData } from '@umbraco-cms/backoffice/modal'; import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbSorterConfig} from '@umbraco-cms/backoffice/sorter'; +import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; const SORTER_CONFIG: UmbSorterConfig = { @@ -216,7 +216,7 @@ export class UmbMediaTypeWorkspaceViewEditElement extends UmbLitElement implemen if (!tabId) return; this._workspaceContext?.structure.removeContainer(null, tabId); this._tabsStructureHelper?.isOwnerContainer(tabId) - ? window.history.replaceState(null, '', this._routerPath + this._routes[0]?.path ?? '/root') + ? window.history.replaceState(null, '', this._routerPath + (this._routes[0]?.path ?? '/root')) : ''; } async #addTab() { From 5d25632ae6e7d5420b75e46ed4e22d8ef3b35bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 12:39:17 +0100 Subject: [PATCH 70/81] Revert "fix js issue" This reverts commit 686f9b6a419667a9723283e891398cb39ebe753b. --- ...property-editor-ui-block-grid-type-configuration.element.ts | 2 +- ...property-editor-ui-block-list-type-configuration.element.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 10a4d4c3f9..9714e9cd08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -105,7 +105,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement #onCreate(e: CustomEvent, groupKey: string | null) { const selectedElementType = e.detail.contentElementTypeKey; if (selectedElementType) { - this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + groupKey + '/' + selectedElementType); + this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/' + groupKey); } } 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 b8941ca8b1..a1a1c7de07 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 @@ -48,8 +48,7 @@ export class UmbPropertyEditorUIBlockListBlockConfigurationElement #onCreate(e: CustomEvent) { const selectedElementType = e.detail.contentElementTypeKey; if (selectedElementType) { - // We do not have any groups here, which is why we pass null as the groupKey. - this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/null/' + selectedElementType); + this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/null'); } } From cd2b75038a07db0f6537162fcac23f10e5a4bd18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:19:51 +0100 Subject: [PATCH 71/81] make private methods --- .../registry/extension.registry.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 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 26622af8fd..6764b32b97 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 @@ -177,19 +177,19 @@ export class UmbExtensionRegistry< return true; } - private _kindsOfType | string>(type: Key) { + #kindsOfType | string>(type: Key) { return this.kinds.pipe( map((kinds) => kinds.filter((kind) => kind.matchType === type)), distinctUntilChanged(extensionArrayMemoization), ); } - private _extensionsOfType | string>(type: Key) { + #extensionsOfType | string>(type: Key) { return this.extensions.pipe( map((exts) => exts.filter((ext) => ext.type === type)), distinctUntilChanged(extensionArrayMemoization), ); } - private _kindsOfTypes(types: string[]) { + #kindsOfTypes(types: string[]) { return this.kinds.pipe( map((kinds) => kinds.filter((kind) => types.indexOf(kind.matchType) !== -1)), distinctUntilChanged(extensionArrayMemoization), @@ -197,7 +197,7 @@ export class UmbExtensionRegistry< } // TODO: can we get rid of as unknown here - private _extensionsOfTypes( + #extensionsOfTypes( types: Array, ): Observable> { return this.extensions.pipe( @@ -213,7 +213,7 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionSingleMemoization), switchMap((ext) => { if (ext?.kind) { - return this._kindsOfType(ext.type).pipe( + return this.#kindsOfType(ext.type).pipe( map((kinds) => { // Specific Extension Meta merge (does not merge conditions) if (ext) { @@ -249,7 +249,7 @@ export class UmbExtensionRegistry< map((exts) => exts.find((ext) => ext.type === type && ext.alias === alias)), distinctUntilChanged(extensionSingleMemoization), ), - this._kindsOfType(type), + this.#kindsOfType(type), ]).pipe( map(([ext, kinds]) => { // TODO: share one merge function between the different methods of this class: @@ -280,7 +280,7 @@ export class UmbExtensionRegistry< map((exts) => exts.filter((ext) => ext.type === type && aliases.indexOf(ext.alias) !== -1)), distinctUntilChanged(extensionArrayMemoization), ), - this._kindsOfType(type), + this.#kindsOfType(type), ]).pipe( map(([exts, kinds]) => exts @@ -319,7 +319,7 @@ export class UmbExtensionRegistry< map((exts) => exts.find((ext) => ext.type === type && filter(ext as unknown as T))), distinctUntilChanged(extensionSingleMemoization), ), - this._kindsOfType(type), + this.#kindsOfType(type), ]).pipe( map(([ext, kinds]) => { // TODO: share one merge function between the different methods of this class: @@ -349,7 +349,7 @@ export class UmbExtensionRegistry< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, >(type: Key) { - return combineLatest([this._extensionsOfType(type), this._kindsOfType(type)]).pipe( + return combineLatest([this.#extensionsOfType(type), this.#kindsOfType(type)]).pipe( map(([exts, kinds]) => exts .map((ext) => { @@ -378,7 +378,7 @@ export class UmbExtensionRegistry< extensionsOfTypes( types: string[], ): Observable> { - return combineLatest([this._extensionsOfTypes(types), this._kindsOfTypes(types)]).pipe( + return combineLatest([this.#extensionsOfTypes(types), this.#kindsOfTypes(types)]).pipe( map(([exts, kinds]) => exts .map((ext) => { From 442446ff23fe4a87c69fc2ec49f831ce9a4cb795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:21:42 +0100 Subject: [PATCH 72/81] more clean up --- .../extension-api/registry/extension.registry.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 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 6764b32b97..611d3caf47 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 @@ -106,7 +106,7 @@ export class UmbExtensionRegistry< } register(manifest: ManifestTypes | ManifestKind): void { - const isValid = this.checkExtension(manifest); + const isValid = this.#checkExtension(manifest); if (!isValid) { return; } @@ -143,14 +143,7 @@ export class UmbExtensionRegistry< return false; } - /* - getByAlias(alias: string) { - // TODO: make pipes prettier/simpler/reuseable - return this.extensions.pipe(map((extensions) => extensions.find((extension) => extension.alias === alias) || null)); - } - */ - - private checkExtension(manifest: ManifestTypes | ManifestKind): boolean { + #checkExtension(manifest: ManifestTypes | ManifestKind): boolean { if (!manifest.type) { console.error(`Extension is missing type`, manifest); return false; @@ -345,6 +338,7 @@ export class UmbExtensionRegistry< * @param type {string} - The type of the extensions to get. * @returns {Observable} - An observable of the extensions that matches the type. */ + // TODO: get rid of the extensions name. extensionsOfType< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, @@ -375,6 +369,7 @@ export class UmbExtensionRegistry< * @param type {Array} - The types of the extensions to get. * @returns {Observable} - An observable of the extensions that matches the types. */ + // TODO: get rid of the extensions name. extensionsOfTypes( types: string[], ): Observable> { From 9054fde15e319fb6a67128264c5674cd3b82538b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:25:51 +0100 Subject: [PATCH 73/81] byType --- .../base-extensions-initializer.controller.ts | 4 ++-- .../bundle-extension-initializer.ts | 2 +- .../entry-point-extension-initializer.ts | 2 +- .../registry/extension.registry.test.ts | 12 ++++++------ .../registry/extension.registry.ts | 17 +++++++++++------ .../entity-actions-bundle.element.ts | 4 ++-- .../input-section/input-section.element.ts | 4 ++-- .../input-tiny-mce/input-tiny-mce.element.ts | 2 +- .../data-type-picker-flow-modal.element.ts | 7 ++++--- .../property-editor-ui-picker-modal.element.ts | 9 ++++----- .../ui-culture-input.element.ts | 4 ++-- .../registry/localization.registry.ts | 2 +- .../section-picker-modal.element.ts | 12 ++++-------- ...ui-tiny-mce-toolbar-configuration.element.ts | 4 ++-- .../src/packages/core/themes/theme.context.ts | 4 ++-- .../tree-item-base/tree-item-base.context.ts | 2 +- .../dashboard-health-check.element.ts | 6 +++--- .../created-packages-section-view.element.ts | 10 +++------- ...talled-packages-section-view-item.element.ts | 8 ++++---- .../user-profile-app-themes.element.ts | 6 +++--- ...roup-table-sections-column-layout.element.ts | 2 +- .../user-group-ref/user-group-ref.element.ts | 4 ++-- ...ser-group-default-permission-list.element.ts | 2 +- ...ity-user-permission-settings-list.element.ts | 6 +++--- 24 files changed, 66 insertions(+), 69 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 b962b7777b..b08e5cac83 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 @@ -56,8 +56,8 @@ export abstract class UmbBaseExtensionsInitializer< } protected _init() { let source = Array.isArray(this.#type) - ? this.#extensionRegistry.extensionsOfTypes(this.#type as string[]) - : this.#extensionRegistry.extensionsOfType(this.#type as ManifestTypeName); + ? this.#extensionRegistry.byTypes(this.#type as string[]) + : this.#extensionRegistry.byType(this.#type as ManifestTypeName); if (this.#filter) { source = source.pipe(map((extensions: Array) => extensions.filter(this.#filter!))); } diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/bundle-extension-initializer.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/bundle-extension-initializer.ts index d3af968dc7..23555f8246 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/bundle-extension-initializer.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/bundle-extension-initializer.ts @@ -11,7 +11,7 @@ export class UmbBundleExtensionInitializer extends UmbBaseController { constructor(host: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry) { super(host); this.#extensionRegistry = extensionRegistry; - this.observe(extensionRegistry.extensionsOfType('bundle'), (bundles) => { + this.observe(extensionRegistry.byType('bundle'), (bundles) => { // Unregister removed bundles: this.#bundleMap.forEach((existingBundle) => { if (!bundles.find((b) => b.alias === existingBundle.alias)) { diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/entry-point-extension-initializer.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/entry-point-extension-initializer.ts index 6ff6c69576..5823bc9c59 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/entry-point-extension-initializer.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/initializers/entry-point-extension-initializer.ts @@ -13,7 +13,7 @@ export class UmbEntryPointExtensionInitializer extends UmbBaseController { super(host); this.#host = host; this.#extensionRegistry = extensionRegistry; - this.observe(extensionRegistry.extensionsOfType('entryPoint'), (entryPoints) => { + this.observe(extensionRegistry.byType('entryPoint'), (entryPoints) => { entryPoints.forEach((entryPoint) => { if (this.#entryPointMap.has(entryPoint.alias)) return; this.#entryPointMap.set(entryPoint.alias, entryPoint); 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 b0492dc21c..20ae4ae57f 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 @@ -94,7 +94,7 @@ describe('UmbExtensionRegistry', () => { it('should get all extensions by type', (done) => { extensionRegistry - .extensionsOfType(type) + .byType(type) .subscribe((extensions) => { expect(extensions).to.have.lengthOf(3); expect(extensions?.[0]?.type).to.eq(type); @@ -106,7 +106,7 @@ describe('UmbExtensionRegistry', () => { it('should return extensions ordered by weight', (done) => { extensionRegistry - .extensionsOfType(type) + .byType(type) .subscribe((extensions) => { expect(extensions?.[0]?.weight).to.eq(200); expect(extensions?.[1]?.weight).to.eq(25); @@ -121,7 +121,7 @@ describe('UmbExtensionRegistry', () => { let lastAmount = 0; extensionRegistry - .extensionsOfType('section') + .byType('section') .subscribe((extensions) => { amountOfTimesTriggered++; const newAmount = extensions?.length ?? 0; @@ -244,7 +244,7 @@ describe('UmbExtensionRegistry with kinds', () => { it('should merge with kinds', (done) => { extensionRegistry - .extensionsOfType('section') + .byType('section') .subscribe((extensions) => { expect(extensions).to.have.lengthOf(3); expect(extensions?.[0]?.elementName).to.not.eq('my-kind-element'); @@ -265,7 +265,7 @@ describe('UmbExtensionRegistry with kinds', () => { extensionRegistry.unregister('Umb.Test.Kind'); extensionRegistry - .extensionsOfType('section') + .byType('section') .subscribe((extensions) => { amountOfTimesTriggered++; expect(extensions).to.have.lengthOf(3); @@ -287,7 +287,7 @@ describe('UmbExtensionRegistry with kinds', () => { let amountOfTimesTriggered = -1; extensionRegistry - .extensionsOfType('section') + .byType('section') .subscribe((extensions) => { amountOfTimesTriggered++; expect(extensions).to.have.lengthOf(3); 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 611d3caf47..2f527db29e 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 @@ -338,8 +338,7 @@ export class UmbExtensionRegistry< * @param type {string} - The type of the extensions to get. * @returns {Observable} - An observable of the extensions that matches the type. */ - // TODO: get rid of the extensions name. - extensionsOfType< + byType< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, >(type: Key) { @@ -363,16 +362,17 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } + /** + * @deprecated Use `byType` instead. + */ + extensionsOfType = this.byType.bind(this); /** * Get an observable that provides extensions matching given types. * @param type {Array} - The types of the extensions to get. * @returns {Observable} - An observable of the extensions that matches the types. */ - // TODO: get rid of the extensions name. - extensionsOfTypes( - types: string[], - ): Observable> { + byTypes(types: string[]): Observable> { return combineLatest([this.#extensionsOfTypes(types), this.#kindsOfTypes(types)]).pipe( map(([exts, kinds]) => exts @@ -395,4 +395,9 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } + + /** + * @deprecated Use `byTypes` instead. + */ + extensionsOfTypes = this.byTypes.bind(this); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index 5666bc542c..3de9b99748 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -1,7 +1,7 @@ import { css, html, nothing, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { map } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbSectionSidebarContext} from '@umbraco-cms/backoffice/section'; +import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; @@ -44,7 +44,7 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { #observeEntityActions() { this.observe( umbExtensionsRegistry - .extensionsOfType('entityAction') + .byType('entityAction') .pipe(map((actions) => actions.filter((action) => action.meta.entityTypes.includes(this.entityType!)))), (actions) => { this._hasActions = actions.length > 0; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-section/input-section.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-section/input-section.element.ts index 13cd0d0827..1e1743c1ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-section/input-section.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-section/input-section.element.ts @@ -2,7 +2,7 @@ import { UmbInputListBaseElement } from '../input-list-base/input-list-base.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UMB_SECTION_PICKER_MODAL } from '@umbraco-cms/backoffice/modal'; -import type { ManifestSection} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestSection } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; @customElement('umb-input-section') @@ -18,7 +18,7 @@ export class UmbInputSectionElement extends UmbInputListBaseElement { private _observeSections() { if (this.value.length > 0) { - this.observe(umbExtensionsRegistry.extensionsOfType('section'), (sections: Array) => { + this.observe(umbExtensionsRegistry.byType('section'), (sections: Array) => { this._sections = sections.filter((section) => this.value.includes(section.alias)); }); } else { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts index 190c92d443..0ef9d7db16 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts @@ -78,7 +78,7 @@ export class UmbInputTinyMceElement extends FormControlMixin(UmbLitElement) { * the plugins are ready and so are not associated with the editor. */ async #loadPlugins() { - const observable = umbExtensionsRegistry?.extensionsOfType('tinyMcePlugin'); + const observable = umbExtensionsRegistry?.byType('tinyMcePlugin'); const manifests = (await firstValueFrom(observable)) as ManifestTinyMcePlugin[]; const promises = []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index 279baa268f..dffe289872 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -5,13 +5,14 @@ import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import type { UmbDataTypePickerFlowModalData, UmbDataTypePickerFlowModalValue, - UmbModalRouteBuilder} from '@umbraco-cms/backoffice/modal'; + UmbModalRouteBuilder, +} from '@umbraco-cms/backoffice/modal'; import { UMB_DATA_TYPE_PICKER_FLOW_DATA_TYPE_PICKER_MODAL, UmbModalBaseElement, UmbModalRouteRegistrationController, } from '@umbraco-cms/backoffice/modal'; -import type { ManifestPropertyEditorUi} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbEntityTreeItemModel } from '@umbraco-cms/backoffice/tree'; import { UMB_DATATYPE_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/data-type'; @@ -107,7 +108,7 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< '_repositoryItemsObserver', ); - this.observe(umbExtensionsRegistry.extensionsOfType('propertyEditorUi'), (propertyEditorUIs) => { + this.observe(umbExtensionsRegistry.byType('propertyEditorUi'), (propertyEditorUIs) => { // Only include Property Editor UIs which has Property Editor Schema Alias this.#propertyEditorUIs = propertyEditorUIs.filter( (propertyEditorUi) => !!propertyEditorUi.meta.propertyEditorSchemaAlias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts index 010eb6ffee..2a32afa768 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts @@ -3,11 +3,10 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import type { UmbPropertyEditorUIPickerModalData, - UmbPropertyEditorUIPickerModalValue} from '@umbraco-cms/backoffice/modal'; -import { - UmbModalBaseElement, + UmbPropertyEditorUIPickerModalValue, } from '@umbraco-cms/backoffice/modal'; -import type { ManifestPropertyEditorUi} from '@umbraco-cms/backoffice/extension-registry'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; interface GroupedPropertyEditorUIs { @@ -38,7 +37,7 @@ export class UmbPropertyEditorUIPickerModalElement extends UmbModalBaseElement< #usePropertyEditorUIs() { if (!this.data) return; - this.observe(umbExtensionsRegistry.extensionsOfType('propertyEditorUi'), (propertyEditorUIs) => { + this.observe(umbExtensionsRegistry.byType('propertyEditorUi'), (propertyEditorUIs) => { // Only include Property Editor UIs which has Property Editor Schema Alias this._propertyEditorUIs = propertyEditorUIs.filter( (propertyEditorUi) => !!propertyEditorUi.meta.propertyEditorSchemaAlias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/components/ui-culture-input/ui-culture-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/components/ui-culture-input/ui-culture-input.element.ts index 6e607850c6..5d49ac03fd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/components/ui-culture-input/ui-culture-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/components/ui-culture-input/ui-culture-input.element.ts @@ -3,7 +3,7 @@ import { css, html, customElement, query, state, property } from '@umbraco-cms/b import type { UUIComboboxElement, UUIComboboxEvent } from '@umbraco-cms/backoffice/external/uui'; import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { ManifestLocalization} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestLocalization } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; interface UmbCultureInputOption { @@ -38,7 +38,7 @@ export class UmbUiCultureInputElement extends FormControlMixin(UmbLitElement) { #observeTranslations() { this.observe( - umbExtensionsRegistry.extensionsOfType('localization'), + umbExtensionsRegistry.byType('localization'), (localizationManifests) => { this.#mapToOptions(localizationManifests); }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index 708e437f84..f2b5e98a4e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -34,7 +34,7 @@ export class UmbLocalizationRegistry { } constructor(extensionRegistry: UmbBackofficeExtensionRegistry) { - combineLatest([this.currentLanguage, extensionRegistry.extensionsOfType('localization')]).subscribe( + combineLatest([this.currentLanguage, extensionRegistry.byType('localization')]).subscribe( async ([currentLanguage, extensions]) => { const locale = new Intl.Locale(currentLanguage); const filteredExt = extensions.filter( diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/section-picker/section-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/section-picker/section-picker-modal.element.ts index c72ad04237..909bf12c1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/section-picker/section-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/section-picker/section-picker-modal.element.ts @@ -1,14 +1,10 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; -import type { ManifestSection} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestSection } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import type { - UmbSectionPickerModalData, - UmbSectionPickerModalValue} from '@umbraco-cms/backoffice/modal'; -import { - UmbModalBaseElement, -} from '@umbraco-cms/backoffice/modal'; +import type { UmbSectionPickerModalData, UmbSectionPickerModalValue } from '@umbraco-cms/backoffice/modal'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @customElement('umb-section-picker-modal') export class UmbSectionPickerModalElement extends UmbModalBaseElement< @@ -28,7 +24,7 @@ export class UmbSectionPickerModalElement extends UmbModalBaseElement< this.#selectionManager.setSelection(this.data?.selection ?? []); this.observe( - umbExtensionsRegistry.extensionsOfType('section'), + umbExtensionsRegistry.byType('section'), (sections: Array) => (this._sections = sections), ), 'umbSectionsObserver'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tiny-mce/config/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tiny-mce/config/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts index 3df001a360..5c3f7306cd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tiny-mce/config/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tiny-mce/config/toolbar/property-editor-ui-tiny-mce-toolbar-configuration.element.ts @@ -2,7 +2,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import { customElement, css, html, property, map, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { UmbPropertyEditorUiElement} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @@ -78,7 +78,7 @@ export class UmbPropertyEditorUITinyMceToolbarConfigurationElement private async getToolbarPlugins(): Promise { // Get all the toolbar plugins - const plugin$ = umbExtensionsRegistry.extensionsOfType('tinyMcePlugin'); + const plugin$ = umbExtensionsRegistry.byType('tinyMcePlugin'); const plugins = await firstValueFrom(plugin$); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts index 120b241c2b..f069308ec8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts @@ -4,7 +4,7 @@ import type { UmbObserverController } from '@umbraco-cms/backoffice/observable-a import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; -import type { ManifestTheme} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTheme } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { loadManifestPlainCss } from '@umbraco-cms/backoffice/extension-api'; @@ -37,7 +37,7 @@ export class UmbThemeContext extends UmbBaseController { localStorage.setItem(LOCAL_STORAGE_KEY, themeAlias); this.#themeObserver = this.observe( umbExtensionsRegistry - .extensionsOfType('theme') + .byType('theme') .pipe(map((extensions) => extensions.filter((extension) => extension.alias === themeAlias))), async (themes) => { this.#styleElement?.remove(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts index a01ef5721f..d329e17fa9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item-base/tree-item-base.context.ts @@ -181,7 +181,7 @@ export class UmbTreeItemContextBase #observeActions() { this.observe( umbExtensionsRegistry - .extensionsOfType('entityAction') + .byType('entityAction') .pipe(map((actions) => actions.filter((action) => action.meta.entityTypes.includes(this.entityType!)))), (actions) => { this.#hasActions.setValue(actions.length > 0); diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts index af642d87b4..183ff898d5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts @@ -2,11 +2,11 @@ import type { UmbDashboardHealthCheckGroupElement } from './views/health-check-g import { UmbHealthCheckDashboardContext, UMB_HEALTHCHECK_DASHBOARD_CONTEXT } from './health-check-dashboard.context.js'; import { UmbHealthCheckContext } from './health-check.context.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import type { HealthCheckGroupResponseModel} from '@umbraco-cms/backoffice/backend-api'; +import type { HealthCheckGroupResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { HealthCheckResource } from '@umbraco-cms/backoffice/backend-api'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { ManifestHealthCheck} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestHealthCheck } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -34,7 +34,7 @@ export class UmbDashboardHealthCheckElement extends UmbLitElement { super(); this.provideContext(UMB_HEALTHCHECK_DASHBOARD_CONTEXT, this._healthCheckDashboardContext); - this.observe(umbExtensionsRegistry.extensionsOfType('healthCheck'), (healthCheckManifests) => { + this.observe(umbExtensionsRegistry.byType('healthCheck'), (healthCheckManifests) => { this._healthCheckDashboardContext.manifests = healthCheckManifests; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts index 502bd8285a..02f21e2016 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts @@ -1,11 +1,7 @@ import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import type { - ManifestWorkspace, - UmbSectionViewElement} from '@umbraco-cms/backoffice/extension-registry'; -import { - umbExtensionsRegistry, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestWorkspace, UmbSectionViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -19,7 +15,7 @@ export class UmbCreatedPackagesSectionViewElement extends UmbLitElement implemen constructor() { super(); // TODO: Do not implement all workspaces at this point. We should only implement the 'package-builder' workspace. - this.observe(umbExtensionsRegistry?.extensionsOfType('workspace'), (workspaceExtensions) => { + this.observe(umbExtensionsRegistry?.byType('workspace'), (workspaceExtensions) => { this._workspaces = workspaceExtensions; this._createRoutes(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/installed/installed-packages-section-view-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/installed/installed-packages-section-view-item.element.ts index fc0859b2e1..dafcfa1760 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/installed/installed-packages-section-view-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/installed/installed-packages-section-view-item.element.ts @@ -1,15 +1,15 @@ import { html, css, nothing, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import { map } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbModalManagerContext} from '@umbraco-cms/backoffice/modal'; +import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT, UMB_CONFIRM_MODAL } from '@umbraco-cms/backoffice/modal'; import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api'; -import type { ManifestPackageView} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestPackageView } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { PackageResource } from '@umbraco-cms/backoffice/backend-api'; -import type { UmbNotificationContext} from '@umbraco-cms/backoffice/notification'; +import type { UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; @customElement('umb-installed-packages-section-view-item') @@ -58,7 +58,7 @@ export class UmbInstalledPackagesSectionViewItemElement extends UmbLitElement { #observePackageView() { this.observe( - umbExtensionsRegistry.extensionsOfType('packageView').pipe( + umbExtensionsRegistry.byType('packageView').pipe( map((extensions) => { return extensions.filter((extension) => extension.meta.packageName === this.#name); }), diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/user-profile-apps/user-profile-app-themes.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/user-profile-apps/user-profile-app-themes.element.ts index e4708f1d0e..f38d8a247f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/user-profile-apps/user-profile-app-themes.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/user-profile-apps/user-profile-app-themes.element.ts @@ -1,9 +1,9 @@ -import type { UmbThemeContext} from '@umbraco-cms/backoffice/themes'; +import type { UmbThemeContext } from '@umbraco-cms/backoffice/themes'; import { UMB_THEME_CONTEXT } from '@umbraco-cms/backoffice/themes'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { ManifestTheme} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTheme } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; @customElement('umb-user-profile-app-themes') @@ -29,7 +29,7 @@ export class UmbUserProfileAppThemesElement extends UmbLitElement { ); this.observe( - umbExtensionsRegistry.extensionsOfType('theme'), + umbExtensionsRegistry.byType('theme'), (themes) => { this._themes = themes; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-sections-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-sections-column-layout.element.ts index b49b2f22a8..d39ed9f6c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-sections-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/collection/components/user-group-table-sections-column-layout.element.ts @@ -22,7 +22,7 @@ export class UmbUserGroupTableSectionsColumnLayoutElement extends UmbLitElement private observeSectionNames() { this.observe( - umbExtensionsRegistry.extensionsOfType('section'), + umbExtensionsRegistry.byType('section'), (sections) => { this._sectionsNames = sections.filter((x) => this.value.includes(x.alias)).map((x) => x.meta.label || x.name); }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.element.ts index d9be491df6..ad89f8484d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.element.ts @@ -1,7 +1,7 @@ import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui'; import { customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; -import type { ManifestUserPermission} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestUserPermission } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { map } from '@umbraco-cms/backoffice/external/rxjs'; @@ -25,7 +25,7 @@ export class UmbUserGroupRefElement extends UmbElementMixin(UUIRefNodeElement) { async #observeUserPermissions(value: Array) { if (value) { this.observe( - umbExtensionsRegistry.extensionsOfType('userPermission').pipe( + umbExtensionsRegistry.byType('userPermission').pipe( map((manifests) => { return manifests.filter((manifest) => manifest.alias && value.includes(manifest.alias)); }), diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/components/user-group-default-permission-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/components/user-group-default-permission-list.element.ts index 12315424f7..53643bcfc4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/components/user-group-default-permission-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/components/user-group-default-permission-list.element.ts @@ -32,7 +32,7 @@ export class UmbUserGroupDefaultPermissionListElement extends UmbLitElement { #observeUserPermissions() { this.observe( - umbExtensionsRegistry.extensionsOfType('userPermission'), + umbExtensionsRegistry.byType('userPermission'), (userPermissionManifests) => { this._entityTypes = [...new Set(userPermissionManifests.map((manifest) => manifest.meta.entityType))]; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/components/entity-user-permission-settings-list/entity-user-permission-settings-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/components/entity-user-permission-settings-list/entity-user-permission-settings-list.element.ts index 475cbf6db6..fcf0879a5f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/components/entity-user-permission-settings-list/entity-user-permission-settings-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/components/entity-user-permission-settings-list/entity-user-permission-settings-list.element.ts @@ -1,6 +1,6 @@ -import type { UmbChangeEvent} from '@umbraco-cms/backoffice/event'; +import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; -import type { ManifestUserPermission} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestUserPermission } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { css, html, customElement, property, state, nothing, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; @@ -36,7 +36,7 @@ export class UmbEntityUserPermissionSettingsListElement extends UmbLitElement { this.#manifestObserver?.destroy(); this.#manifestObserver = this.observe( - umbExtensionsRegistry.extensionsOfType('userPermission'), + umbExtensionsRegistry.byType('userPermission'), (userPermissionManifests) => { this._manifests = userPermissionManifests.filter((manifest) => manifest.meta.entityType === this.entityType); }, From a07e656b925d6eced623860584dccf5e94242871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:26:29 +0100 Subject: [PATCH 74/81] byTypeAndAliases --- .../controller/base-extension-initializer.controller.ts | 2 +- .../libs/extension-api/registry/extension.registry.test.ts | 2 +- .../src/libs/extension-api/registry/extension.registry.ts | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts index 7d689422ed..d8deb6cded 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts @@ -143,7 +143,7 @@ export abstract class UmbBaseExtensionInitializer< if (conditionConfigs.length > 0) { // Observes the conditions and initialize as they come in. this.observe( - this.#extensionRegistry.getByTypeAndAliases('condition', conditionAliases), + this.#extensionRegistry.byTypeAndAliases('condition', conditionAliases), this.#gotConditions, '_observeConditions', ); 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 20ae4ae57f..bd58bdb34d 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 @@ -80,7 +80,7 @@ describe('UmbExtensionRegistry', () => { it('should get an extension by aliases', (done) => { const aliases = ['Umb.Test.Section.1', 'Umb.Test.Section.2']; extensionRegistry - .getByTypeAndAliases('section', aliases) + .byTypeAndAliases('section', aliases) .subscribe((extensions) => { expect(extensions[0]?.alias).to.eq(aliases[1]); expect(extensions[1]?.alias).to.eq(aliases[0]); 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 2f527db29e..c0be272240 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 @@ -263,8 +263,7 @@ export class UmbExtensionRegistry< ) as Observable; } - // TODO: get rid of the name get - getByTypeAndAliases< + byTypeAndAliases< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, >(type: Key, aliases: Array) { @@ -294,6 +293,10 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } + /** + * @deprecated Use `byTypeAndAliases` instead. + */ + getByTypeAndAliases = this.byTypeAndAliases.bind(this); /** * Get an observable of an extension by type and a given filter method. From 4ae6fd049e0d1067a695d621eb79d6183a5e5cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:27:11 +0100 Subject: [PATCH 75/81] byTypeAndAlias --- .../src/libs/extension-api/registry/extension.registry.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 c0be272240..0cf95d96d0 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 @@ -233,7 +233,7 @@ export class UmbExtensionRegistry< } // TODO: get rid of the name get - getByTypeAndAlias< + byTypeAndAlias< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, >(type: Key, alias: string) { @@ -262,6 +262,10 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchSingleMemoization), ) as Observable; } + /** + * @deprecated Use `byTypeAndAlias` instead. + */ + getByTypeAndAlias = this.byTypeAndAlias.bind(this); byTypeAndAliases< Key extends keyof ManifestTypeMap | string, From 1ac5b51715fed3531fae52bba01fd4c74cf0bc6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:28:37 +0100 Subject: [PATCH 76/81] byAlias --- .../controller/base-extension-initializer.controller.ts | 2 +- .../src/libs/extension-api/registry/extension.registry.ts | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts index d8deb6cded..816a32e4a0 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts @@ -73,7 +73,7 @@ export abstract class UmbBaseExtensionInitializer< } protected _init() { this.#manifestObserver = this.observe( - this.#extensionRegistry.getByAlias(this.#alias), + this.#extensionRegistry.byAlias(this.#alias), async (extensionManifest) => { this.#clearPermittedState(); this.#manifest = extensionManifest; 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 0cf95d96d0..44966aeac2 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 @@ -199,8 +199,7 @@ export class UmbExtensionRegistry< ) as unknown as Observable>; } - // TODO: get rid of the name get - getByAlias(alias: string) { + byAlias(alias: string) { return this.extensions.pipe( map((exts) => exts.find((ext) => ext.alias === alias)), distinctUntilChanged(extensionSingleMemoization), @@ -231,8 +230,11 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchSingleMemoization), ) as Observable; } + /** + * @deprecated Use `byAlias` instead. + */ + getByAlias = this.byAlias.bind(this); - // TODO: get rid of the name get byTypeAndAlias< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, From 79a9642282e9e06e7d252e2b175f8f01bf8b7f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:42:33 +0100 Subject: [PATCH 77/81] reuse code of mergeExtensionsWithKinds --- .../registry/extension.registry.ts | 138 +++++------------- 1 file changed, 40 insertions(+), 98 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 44966aeac2..6bba87eb9f 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 @@ -199,30 +199,47 @@ export class UmbExtensionRegistry< ) as unknown as Observable>; } + #mergeExtensionWithKinds([ext, kinds]) { + // Specific Extension Meta merge (does not merge conditions) + if (ext) { + // Since we don't have the type up front in this request, we will just get all kinds here and find the matching one: + const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; + // TODO: This check can go away when making a find kind based on type and kind. + if (baseManifest) { + const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; + if ((baseManifest as any).meta) { + merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; + } + return merged; + } + } + return ext; + } + + #mergeExtensionsWithKinds([exts, kinds]) { + exts + .map((ext) => { + // Specific Extension Meta merge (does not merge conditions) + const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; + if (baseManifest) { + const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; + if ((baseManifest as any).meta) { + merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; + } + return merged; + } + return ext; + }) + .sort(sortExtensions); + } + byAlias(alias: string) { return this.extensions.pipe( map((exts) => exts.find((ext) => ext.alias === alias)), distinctUntilChanged(extensionSingleMemoization), switchMap((ext) => { if (ext?.kind) { - return this.#kindsOfType(ext.type).pipe( - map((kinds) => { - // Specific Extension Meta merge (does not merge conditions) - if (ext) { - // Since we dont have the type up front in this request, we will just get all kinds here and find the matching one: - const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; - // TODO: This check can go away when making a find kind based on type and kind. - if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; - if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; - } - return merged; - } - } - return ext; - }), - ); + return this.#kindsOfType(ext.type).pipe(map((kinds) => this.#mergeExtensionWithKinds([ext, kinds]))); } return of(ext); }), @@ -246,21 +263,7 @@ export class UmbExtensionRegistry< ), this.#kindsOfType(type), ]).pipe( - map(([ext, kinds]) => { - // TODO: share one merge function between the different methods of this class: - // Specific Extension Meta merge (does not merge conditions) - if (ext) { - const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; - if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; - if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; - } - return merged; - } - } - return ext; - }), + map(this.#mergeExtensionWithKinds), distinctUntilChanged(extensionAndKindMatchSingleMemoization), ) as Observable; } @@ -280,22 +283,7 @@ export class UmbExtensionRegistry< ), this.#kindsOfType(type), ]).pipe( - map(([exts, kinds]) => - exts - .map((ext) => { - // Specific Extension Meta merge (does not merge conditions) - const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; - if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; - if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; - } - return merged; - } - return ext; - }) - .sort(sortExtensions), - ), + map(this.#mergeExtensionsWithKinds), distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } @@ -323,21 +311,7 @@ export class UmbExtensionRegistry< ), this.#kindsOfType(type), ]).pipe( - map(([ext, kinds]) => { - // TODO: share one merge function between the different methods of this class: - // Specific Extension Meta merge (does not merge conditions) - if (ext) { - const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; - if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; - if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; - } - return merged; - } - } - return ext; - }), + map(this.#mergeExtensionsWithKinds), distinctUntilChanged(extensionAndKindMatchSingleMemoization), ) as Observable; } @@ -352,22 +326,7 @@ export class UmbExtensionRegistry< T extends ManifestBase = SpecificManifestTypeOrManifestBase, >(type: Key) { return combineLatest([this.#extensionsOfType(type), this.#kindsOfType(type)]).pipe( - map(([exts, kinds]) => - exts - .map((ext) => { - // Specific Extension Meta merge (does not merge conditions) - const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; - if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; - if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; - } - return merged; - } - return ext; - }) - .sort(sortExtensions), - ), + map(this.#mergeExtensionsWithKinds), distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } @@ -383,24 +342,7 @@ export class UmbExtensionRegistry< */ byTypes(types: string[]): Observable> { return combineLatest([this.#extensionsOfTypes(types), this.#kindsOfTypes(types)]).pipe( - map(([exts, kinds]) => - exts - .map((ext) => { - // Specific Extension Meta merge (does not merge conditions) - if (ext) { - const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; - if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; - if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; - } - return merged; - } - } - return ext; - }) - .sort(sortExtensions), - ), + map(this.#mergeExtensionsWithKinds), distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } From 234884638bd3c50dbc34cb80a8667922b593dbd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 13:50:21 +0100 Subject: [PATCH 78/81] JSDocs --- .../registry/extension.registry.ts | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 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 6bba87eb9f..ff27dad3cc 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 @@ -233,6 +233,11 @@ export class UmbExtensionRegistry< .sort(sortExtensions); } + /** + * Get an observable that provides extensions matching the given alias. + * @param alias {string} - The alias of the extensions to get. + * @returns {Observable} - An observable of the extension that matches the alias. + */ byAlias(alias: string) { return this.extensions.pipe( map((exts) => exts.find((ext) => ext.alias === alias)), @@ -252,6 +257,12 @@ export class UmbExtensionRegistry< */ getByAlias = this.byAlias.bind(this); + /** + * Get an observable that provides extensions matching the given type and alias. + * @param type {string} - The type of the extensions to get. + * @param alias {string} - The alias of the extensions to get. + * @returns {Observable} - An observable of the extensions that matches the type and alias. + */ byTypeAndAlias< Key extends keyof ManifestTypeMap | string, T extends ManifestBase = SpecificManifestTypeOrManifestBase, @@ -293,12 +304,12 @@ export class UmbExtensionRegistry< getByTypeAndAliases = this.byTypeAndAliases.bind(this); /** - * Get an observable of an extension by type and a given filter method. + * Get an observable of extensions by type and a given filter method. * This will return the all extensions that matches the type and which filter method returns true. * The filter method will be called for each extension manifest of the given type, and the first argument to it is the extension manifest. * @param type {string} - The type of the extension to get * @param filter {(ext: T): void} - The filter method to use to filter the extensions - * @returns {Observable} - An observable of the extensions that matches the type and filter method + * @returns {Observable>} - An observable of the extensions that matches the type and filter method */ byTypeAndFilter< Key extends keyof ManifestTypeMap | string, @@ -307,13 +318,13 @@ export class UmbExtensionRegistry< return combineLatest([ this.extensions.pipe( map((exts) => exts.find((ext) => ext.type === type && filter(ext as unknown as T))), - distinctUntilChanged(extensionSingleMemoization), + distinctUntilChanged(extensionArrayMemoization), ), this.#kindsOfType(type), ]).pipe( map(this.#mergeExtensionsWithKinds), - distinctUntilChanged(extensionAndKindMatchSingleMemoization), - ) as Observable; + distinctUntilChanged(extensionAndKindMatchArrayMemoization), + ) as Observable>; } /** From 9d98d172649e8ff37fca158848c1395ed7643429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 14:34:53 +0100 Subject: [PATCH 79/81] mega fix of types and test --- .../registry/extension.registry.test.ts | 25 +++++++++++- .../registry/extension.registry.ts | 40 ++++++++++++------- 2 files changed, 48 insertions(+), 17 deletions(-) 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 bd58bdb34d..3e542380fc 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 @@ -66,10 +66,20 @@ describe('UmbExtensionRegistry', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; }); + it('should get several extensions by type', (done) => { + extensionRegistry + .byType('section') + .subscribe((extensions) => { + expect(extensions.length).to.eq(3); + done(); + }) + .unsubscribe(); + }); + it('should get an extension by alias', (done) => { const alias = 'Umb.Test.Section.1'; extensionRegistry - .getByTypeAndAlias('section', alias) + .byTypeAndAlias('section', alias) .subscribe((extension) => { expect(extension?.alias).to.eq(alias); done(); @@ -77,6 +87,17 @@ describe('UmbExtensionRegistry', () => { .unsubscribe(); }); + it('should get an extension by type and filter', (done) => { + extensionRegistry + .byTypeAndFilter('section', (ext) => ext.weight === 25) + .subscribe((extensions) => { + expect(extensions.length).to.eq(1); + expect(extensions[0].alias).to.eq('Umb.Test.Section.3'); + done(); + }) + .unsubscribe(); + }); + it('should get an extension by aliases', (done) => { const aliases = ['Umb.Test.Section.1', 'Umb.Test.Section.2']; extensionRegistry @@ -89,7 +110,7 @@ describe('UmbExtensionRegistry', () => { .unsubscribe(); }); - describe('getByType', () => { + describe('byType', () => { const type = 'section'; it('should get all extensions by type', (done) => { 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 ff27dad3cc..4729708047 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 @@ -176,9 +176,13 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionArrayMemoization), ); } - #extensionsOfType | string>(type: Key) { + + #extensionsOfType< + Key extends keyof ManifestTypeMap | string, + T extends ManifestBase = SpecificManifestTypeOrManifestBase, + >(type: Key) { return this.extensions.pipe( - map((exts) => exts.filter((ext) => ext.type === type)), + map((exts) => exts.filter((ext) => ext.type === type) as unknown as T[]), distinctUntilChanged(extensionArrayMemoization), ); } @@ -194,30 +198,36 @@ export class UmbExtensionRegistry< types: Array, ): Observable> { return this.extensions.pipe( - map((exts) => exts.filter((ext) => types.indexOf(ext.type) !== -1)), + map((exts) => exts.filter((ext) => types.indexOf(ext.type) !== -1) as unknown as Array), distinctUntilChanged(extensionArrayMemoization), - ) as unknown as Observable>; + ); } - #mergeExtensionWithKinds([ext, kinds]) { + #mergeExtensionWithKinds>([ + ext, + kinds, + ]: [ExtensionType | undefined, Array]): ExtensionType | undefined { // Specific Extension Meta merge (does not merge conditions) if (ext) { // Since we don't have the type up front in this request, we will just get all kinds here and find the matching one: const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; // TODO: This check can go away when making a find kind based on type and kind. if (baseManifest) { - const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext } as any; + const merged = { __isMatchedWithKind: true, ...baseManifest, ...ext }; if ((baseManifest as any).meta) { - merged.meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; + (merged as any).meta = { ...(baseManifest as any).meta, ...(ext as any).meta }; } - return merged; + return merged as ExtensionType; } } return ext; } - #mergeExtensionsWithKinds([exts, kinds]) { - exts + #mergeExtensionsWithKinds>([ + exts, + kinds, + ]: [Array, Array]): ExtensionType[] { + return exts .map((ext) => { // Specific Extension Meta merge (does not merge conditions) const baseManifest = kinds.find((kind) => kind.matchKind === ext.kind)?.manifest; @@ -289,7 +299,7 @@ export class UmbExtensionRegistry< >(type: Key, aliases: Array) { return combineLatest([ this.extensions.pipe( - map((exts) => exts.filter((ext) => ext.type === type && aliases.indexOf(ext.alias) !== -1)), + map((exts) => exts.filter((ext) => ext.type === type && aliases.indexOf(ext.alias) !== -1) as unknown as T[]), distinctUntilChanged(extensionArrayMemoization), ), this.#kindsOfType(type), @@ -309,7 +319,7 @@ export class UmbExtensionRegistry< * The filter method will be called for each extension manifest of the given type, and the first argument to it is the extension manifest. * @param type {string} - The type of the extension to get * @param filter {(ext: T): void} - The filter method to use to filter the extensions - * @returns {Observable>} - An observable of the extensions that matches the type and filter method + * @returns {Observable>} - An observable of the extensions that matches the type and filter method */ byTypeAndFilter< Key extends keyof ManifestTypeMap | string, @@ -317,14 +327,14 @@ export class UmbExtensionRegistry< >(type: Key, filter: (ext: T) => boolean) { return combineLatest([ this.extensions.pipe( - map((exts) => exts.find((ext) => ext.type === type && filter(ext as unknown as T))), + map((exts) => exts.filter((ext) => ext.type === type && filter(ext as unknown as T)) as unknown as T[]), distinctUntilChanged(extensionArrayMemoization), ), this.#kindsOfType(type), ]).pipe( map(this.#mergeExtensionsWithKinds), distinctUntilChanged(extensionAndKindMatchArrayMemoization), - ) as Observable>; + ) as Observable>; } /** @@ -352,7 +362,7 @@ export class UmbExtensionRegistry< * @returns {Observable} - An observable of the extensions that matches the types. */ byTypes(types: string[]): Observable> { - return combineLatest([this.#extensionsOfTypes(types), this.#kindsOfTypes(types)]).pipe( + return combineLatest([this.#extensionsOfTypes(types), this.#kindsOfTypes(types)]).pipe( map(this.#mergeExtensionsWithKinds), distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; From da21654f2de5742dfdbaa30516619df6e4136556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 26 Jan 2024 14:39:11 +0100 Subject: [PATCH 80/81] more test --- .../registry/extension.registry.test.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) 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 3e542380fc..68e00ddbd7 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 @@ -47,6 +47,7 @@ describe('UmbExtensionRegistry', () => { type: 'workspace', name: 'test-editor-1', alias: 'Umb.Test.Editor.1', + weight: 2, meta: { entityType: 'testEntity', }, @@ -77,6 +78,17 @@ describe('UmbExtensionRegistry', () => { }); it('should get an extension by alias', (done) => { + const alias = 'Umb.Test.Section.1'; + extensionRegistry + .byAlias(alias) + .subscribe((extension) => { + expect(extension?.alias).to.eq(alias); + done(); + }) + .unsubscribe(); + }); + + it('should get an extension by type and alias', (done) => { const alias = 'Umb.Test.Section.1'; extensionRegistry .byTypeAndAlias('section', alias) @@ -190,6 +202,37 @@ describe('UmbExtensionRegistry', () => { .unsubscribe(); }); }); + + describe('byTypes', () => { + const types = ['section', 'workspace']; + + it('should get all extensions of the given types', (done) => { + extensionRegistry + .byTypes(types) + .subscribe((extensions) => { + expect(extensions).to.have.lengthOf(4); + expect(extensions?.[0]?.type).to.eq('section'); + expect(extensions?.[1]?.type).to.eq('section'); + expect(extensions?.[2]?.type).to.eq('workspace'); + expect(extensions?.[3]?.type).to.eq('section'); + done(); + }) + .unsubscribe(); + }); + + it('should return extensions ordered by weight', (done) => { + extensionRegistry + .byTypes(types) + .subscribe((extensions) => { + expect(extensions?.[0]?.weight).to.eq(200); + expect(extensions?.[1]?.weight).to.eq(25); + expect(extensions?.[2]?.weight).to.eq(2); + expect(extensions?.[3]?.weight).to.eq(1); + done(); + }) + .unsubscribe(); + }); + }); }); describe('UmbExtensionRegistry with kinds', () => { From 5cd4080434ffadae17e26d2574a91c6dfa70a212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 29 Jan 2024 10:09:24 +0100 Subject: [PATCH 81/81] Update input-tiny-mce.element.ts Use super for the getter as well, just to ensure right separation of concerns. --- .../core/components/input-tiny-mce/input-tiny-mce.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts index 457b945401..64cb646524 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tiny-mce/input-tiny-mce.element.ts @@ -53,7 +53,7 @@ export class UmbInputTinyMceElement extends FormControlMixin(UmbLitElement) { } get value(): FormDataEntryValue | FormData { - return this._value; + return super.value; } @query('#editor', true)