From 7ee8be055e9e0eabdcbeb83e75dc791537713841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 19 Apr 2024 15:35:08 +0200 Subject: [PATCH 01/79] content type workspace getName method --- .../workspace/content-type-workspace-context.interface.ts | 1 + .../workspace/document-type-workspace.context.ts | 3 +++ .../media-types/workspace/media-type-workspace.context.ts | 3 +++ .../member-type/workspace/member-type-workspace.context.ts | 3 +++ 4 files changed, 10 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context.interface.ts index db4bbf3419..1405ff101c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context.interface.ts @@ -8,6 +8,7 @@ export interface UmbContentTypeWorkspaceContext; + getName(): string | undefined; readonly alias: Observable; readonly description: Observable; readonly icon: Observable; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 08b2610991..c5c0766105 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -41,6 +41,9 @@ export class UmbDocumentTypeWorkspaceContext //readonly data; readonly unique; readonly name; + getName(): string | undefined { + return this.structure.getOwnerContentType()?.name; + } readonly alias; readonly description; readonly icon; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts index 86e1fd5a81..6253c452d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts @@ -40,6 +40,9 @@ export class UmbMediaTypeWorkspaceContext readonly data; readonly unique; readonly name; + getName(): string | undefined { + return this.structure.getOwnerContentType()?.name; + } readonly alias; readonly description; readonly icon; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace.context.ts index 65ee4c3950..5ee915d1ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/member-type-workspace.context.ts @@ -37,6 +37,9 @@ export class UmbMemberTypeWorkspaceContext readonly data; readonly unique; readonly name; + getName(): string | undefined { + return this.structure.getOwnerContentType()?.name; + } readonly alias; readonly description; readonly icon; From 3e67d26add1876a9b591f07ad9e8ce2600a9dd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 19 Apr 2024 15:35:21 +0200 Subject: [PATCH 02/79] compose data-type name --- .../data-type-picker-flow-modal.element.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index 962abe0c73..0394356369 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -15,6 +15,8 @@ import type { UmbDataTypeItemModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/modal'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content-type'; +import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; interface GroupedItems { [key: string]: Array; @@ -78,8 +80,18 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< this._createDataTypeModal = new UmbModalRouteRegistrationController(this, UMB_DATATYPE_WORKSPACE_MODAL) .addAdditionalPath(':uiAlias') - .onSetup((params) => { - return { data: { entityType: UMB_DATA_TYPE_ENTITY_TYPE, preset: { editorUiAlias: params.uiAlias } } }; + .onSetup(async (params) => { + const contentContext = await this.getContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT); + const propContext = await this.getContext(UMB_PROPERTY_CONTEXT); + const propertyEditorName = this.#propertyEditorUIs.find((ui) => ui.alias === params.uiAlias)?.name; + const dataTypeName = `${contentContext?.getName() ?? ''} - ${propContext.getLabel() ?? ''} - ${propertyEditorName}`; + + return { + data: { + entityType: UMB_DATA_TYPE_ENTITY_TYPE, + preset: { editorUiAlias: params.uiAlias, name: dataTypeName }, + }, + }; }) .onSubmit((value) => { this._select(value?.unique); From f269c172eb4243515f68a0ce1c8f7e607a4093e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 19 Apr 2024 19:31:48 +0200 Subject: [PATCH 03/79] generate name based on data via context api --- .../property-type-settings-modal.element.ts | 3 +- .../core/content-type/workspace/index.ts | 1 + ...pe-design-editor-property.context-token.ts | 4 +++ ...ent-type-design-editor-property.context.ts | 34 +++++++++++++++++++ ...ent-type-design-editor-property.element.ts | 4 +++ .../data-type-picker-flow-modal.element.ts | 15 +++++--- 6 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts index ff53f2f34e..463ef9497e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/property-type-settings/property-type-settings-modal.element.ts @@ -64,8 +64,7 @@ export class UmbPropertyTypeSettingsModalElement extends UmbModalBaseElement< super.connectedCallback(); this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (instance) => { - if (!this.data?.contentTypeId) return; - if (instance.getUnique() !== this.data.contentTypeId) { + if (!this.data?.contentTypeId || instance.getUnique() !== this.data.contentTypeId) { // We can currently only edit properties that are part of a content type workspace, which has to be present outside of the modal. [NL] throw new Error( 'The content type workspace context does not match the content type id of the property type settings modal.', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/index.ts index 1a9af36bce..352572934d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/index.ts @@ -1,2 +1,3 @@ export type * from './content-type-workspace-context.interface.js'; export * from './content-type-workspace.context-token.js'; +export * from './views/design/content-type-design-editor-property.context-token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context-token.ts new file mode 100644 index 0000000000..931d48e3d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context-token.ts @@ -0,0 +1,4 @@ +import type { UmbPropertyTypeContext } from './content-type-design-editor-property.context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export const UMB_PROPERTY_TYPE_CONTEXT = new UmbContextToken('UmbPropertyTypeContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context.ts new file mode 100644 index 0000000000..87234ec3f7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.context.ts @@ -0,0 +1,34 @@ +import { UMB_PROPERTY_TYPE_CONTEXT } from './content-type-design-editor-property.context-token.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; + +export class UmbPropertyTypeContext extends UmbContextBase { + #alias = new UmbStringState(undefined); + public readonly alias = this.#alias.asObservable(); + #label = new UmbStringState(undefined); + public readonly label = this.#label.asObservable(); + + constructor(host: UmbControllerHost) { + super(host, UMB_PROPERTY_TYPE_CONTEXT); + } + + public setAlias(alias: string | undefined): void { + this.#alias.setValue(alias); + } + public getAlias(): string | undefined { + return this.#alias.getValue(); + } + public setLabel(label: string | undefined): void { + this.#label.setValue(label); + } + public getLabel(): string | undefined { + return this.#label.getValue(); + } + + public destroy(): void { + super.destroy(); + this.#alias.destroy(); + this.#label.destroy(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts index 389040c68b..4a2a857964 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor-property.element.ts @@ -1,3 +1,4 @@ +import { UmbPropertyTypeContext } from './content-type-design-editor-property.context.js'; import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; @@ -25,6 +26,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement { #dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); #settingsModal; #dataTypeUnique?: string; + #context = new UmbPropertyTypeContext(this); @property({ attribute: false }) public set propertyStructureHelper(value: UmbContentTypePropertyStructureHelper | undefined) { @@ -51,6 +53,8 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement { const oldValue = this._property; if (value === oldValue) return; this._property = value; + this.#context.setAlias(value?.alias); + this.#context.setLabel(value?.name); this.#checkInherited(); this.#settingsModal.setUniquePathValue('propertyId', value?.id); this.#setDataType(this._property?.dataType?.unique); diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index 0394356369..8c3c42f62b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -15,8 +15,7 @@ import type { UmbDataTypeItemModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/modal'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { umbFocus } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content-type'; -import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, UMB_PROPERTY_TYPE_CONTEXT } from '@umbraco-cms/backoffice/content-type'; interface GroupedItems { [key: string]: Array; @@ -81,8 +80,16 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< this._createDataTypeModal = new UmbModalRouteRegistrationController(this, UMB_DATATYPE_WORKSPACE_MODAL) .addAdditionalPath(':uiAlias') .onSetup(async (params) => { - const contentContext = await this.getContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT); - const propContext = await this.getContext(UMB_PROPERTY_CONTEXT); + const contentContextConsumer = this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, () => { + //this.removeUmbController(contentContextConsumer); + }).passContextAliasMatches(); + const propContextConsumer = this.consumeContext(UMB_PROPERTY_TYPE_CONTEXT, () => { + //this.removeUmbController(propContextConsumer); + }).passContextAliasMatches(); + const [contentContext, propContext] = await Promise.all([ + contentContextConsumer.asPromise(), + propContextConsumer.asPromise(), + ]); const propertyEditorName = this.#propertyEditorUIs.find((ui) => ui.alias === params.uiAlias)?.name; const dataTypeName = `${contentContext?.getName() ?? ''} - ${propContext.getLabel() ?? ''} - ${propertyEditorName}`; From 90906148953cb654c59169c59e08560995d34d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 23 Apr 2024 09:34:13 +0200 Subject: [PATCH 04/79] preparation --- .../tree-picker/tree-picker-modal.element.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index c118899df7..b093cde9da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -1,7 +1,11 @@ import type { UmbTreeSelectionConfiguration } from '../types.js'; import type { UmbTreePickerModalData, UmbTreePickerModalValue } from './tree-picker-modal.token.js'; import { html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { + UMB_WORKSPACE_MODAL, + UmbModalBaseElement, + UmbModalRouteRegistrationController, +} from '@umbraco-cms/backoffice/modal'; import { UmbDeselectedEvent, UmbSelectedEvent, UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbTreeElement, UmbTreeItemModelBase } from '@umbraco-cms/backoffice/tree'; @@ -17,17 +21,42 @@ export class UmbTreePickerModalElement { this._selectionConfiguration.selection = value?.selection ?? []; }); } + // Same here [NL] this._selectionConfiguration.multiple = this.data?.multiple ?? false; + + // TODO: If data.enableCreate is true, we should add a button to create a new item. [NL] + // Does the tree know enough about this, for us to be able to create a new item? [NL] + // I think we need to be able to get entityType and a parentId?, or do we only allow creation in the root? and then create via entity actions? [NL] + // To remove the hardcoded URLs for workspaces of entity types, we could make an create event from the tree, which either this or the sidebar impl. will pick up and react to. [NL] + // Or maybe the tree item context base can handle this? [NL] + // Maybe its a general item context problem to be solved. [NL] + if (this._createButton) { + new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath('document-type') + .onSetup(() => { + return { data: { entityType: 'document-type', preset: {} } }; + }) + .observeRouteBuilder((routeBuilder) => { + this._createPath = routeBuilder({}); + }); + } } #onSelectionChange(event: UmbSelectionChangeEvent) { From 939e92ef74d7708419b47c65478d30c695ce30c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 23 Apr 2024 11:02:45 +0200 Subject: [PATCH 05/79] update interface names for workspace modal --- ...lock-grid-area-type-workspace.modal-token.ts | 8 ++++---- .../block-grid-workspace.modal-token.ts | 6 +++--- .../block-list-workspace.modal-token.ts | 6 +++--- .../block-rte-workspace.modal-token.ts | 6 +++--- .../workspace/block-workspace.modal-token.ts | 8 ++++---- .../core/modal/token/workspace-modal.token.ts | 17 ++++++++++------- .../data-type-workspace.modal-token.ts | 8 ++++---- 7 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts index 7a2595a4e9..11e024c726 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.modal-token.ts @@ -1,11 +1,11 @@ -import type { UmbWorkspaceData, UmbWorkspaceValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -export interface UmbBlockGridAreaTypeWorkspaceData extends UmbWorkspaceData {} +export interface UmbBlockGridAreaTypeWorkspaceData extends UmbWorkspaceModalData {} export const UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_MODAL = new UmbModalToken< UmbBlockGridAreaTypeWorkspaceData, - UmbWorkspaceValue + UmbWorkspaceModalValue >('Umb.Modal.Workspace', { modal: { type: 'sidebar', @@ -13,4 +13,4 @@ export const UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_MODAL = new UmbModalToken< }, data: { entityType: 'block-grid-area-type', preset: {} }, // Recast the type, so the entityType data prop is not required: -}) as UmbModalToken, UmbWorkspaceValue>; +}) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts index 0a58a16654..bbe0f6b456 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbWorkspaceData, UmbWorkspaceValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbBlockGridWorkspaceData @@ -9,7 +9,7 @@ export interface UmbBlockGridWorkspaceData areaKey?: string; }> {} -export const UMB_BLOCK_GRID_WORKSPACE_MODAL = new UmbModalToken( +export const UMB_BLOCK_GRID_WORKSPACE_MODAL = new UmbModalToken( 'Umb.Modal.Workspace', { modal: { @@ -19,4 +19,4 @@ export const UMB_BLOCK_GRID_WORKSPACE_MODAL = new UmbModalToken, UmbWorkspaceValue>; +) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts index 091954dbe9..e86a26f97d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/workspace/block-list-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbWorkspaceData, UmbWorkspaceValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbBlockListWorkspaceData @@ -7,7 +7,7 @@ export interface UmbBlockListWorkspaceData index: number; }> {} -export const UMB_BLOCK_LIST_WORKSPACE_MODAL = new UmbModalToken( +export const UMB_BLOCK_LIST_WORKSPACE_MODAL = new UmbModalToken( 'Umb.Modal.Workspace', { modal: { @@ -17,4 +17,4 @@ export const UMB_BLOCK_LIST_WORKSPACE_MODAL = new UmbModalToken, UmbWorkspaceValue>; +) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts index cdeb480d58..da51f16a31 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/workspace/block-rte-workspace.modal-token.ts @@ -1,5 +1,5 @@ import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbWorkspaceData, UmbWorkspaceValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbBlockRTEWorkspaceData @@ -7,7 +7,7 @@ export interface UmbBlockRTEWorkspaceData index: number; }> {} -export const UMB_BLOCK_RTE_WORKSPACE_MODAL = new UmbModalToken( +export const UMB_BLOCK_RTE_WORKSPACE_MODAL = new UmbModalToken( 'Umb.Modal.Workspace', { modal: { @@ -17,4 +17,4 @@ export const UMB_BLOCK_RTE_WORKSPACE_MODAL = new UmbModalToken, UmbWorkspaceValue>; +) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts index 0a2d21ccc1..5bf06ad44f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.modal-token.ts @@ -1,11 +1,11 @@ -import type { UmbWorkspaceData, UmbWorkspaceValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -export interface UmbBlockWorkspaceData extends UmbWorkspaceData { +export interface UmbBlockWorkspaceData extends UmbWorkspaceModalData { originData: OriginDataType; } -export const UMB_BLOCK_WORKSPACE_MODAL = new UmbModalToken( +export const UMB_BLOCK_WORKSPACE_MODAL = new UmbModalToken( 'Umb.Modal.Workspace', { modal: { @@ -15,4 +15,4 @@ export const UMB_BLOCK_WORKSPACE_MODAL = new UmbModalToken, UmbWorkspaceValue>; +) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts index 7806a971be..f5b7edf84c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/workspace-modal.token.ts @@ -1,19 +1,22 @@ import { UmbModalToken } from './modal-token.js'; -export interface UmbWorkspaceData { +export interface UmbWorkspaceModalData { entityType: string; preset: Partial; } // TODO: It would be good with a WorkspaceValueBaseType, to avoid the hardcoded type for unique here: -export type UmbWorkspaceValue = +export type UmbWorkspaceModalValue = | { unique: string; } | undefined; -export const UMB_WORKSPACE_MODAL = new UmbModalToken('Umb.Modal.Workspace', { - modal: { - type: 'sidebar', - size: 'large', +export const UMB_WORKSPACE_MODAL = new UmbModalToken( + 'Umb.Modal.Workspace', + { + modal: { + type: 'sidebar', + size: 'large', + }, }, -}); +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts index d0c0d0652a..457a0f5ff4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.modal-token.ts @@ -1,10 +1,10 @@ import type { UmbDataTypeDetailModel } from '../types.js'; -import type { UmbWorkspaceData, UmbWorkspaceValue } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export const UMB_DATATYPE_WORKSPACE_MODAL = new UmbModalToken< - UmbWorkspaceData, - UmbWorkspaceValue + UmbWorkspaceModalData, + UmbWorkspaceModalValue >('Umb.Modal.Workspace', { modal: { type: 'sidebar', @@ -12,4 +12,4 @@ export const UMB_DATATYPE_WORKSPACE_MODAL = new UmbModalToken< }, data: { entityType: 'data-type', preset: {} }, // Recast the type, so the entityType data prop is not required: -}) as UmbModalToken, 'entityType'>, UmbWorkspaceValue>; +}) as UmbModalToken, 'entityType'>, UmbWorkspaceModalValue>; From acaa0685787c864fc80afacdad70a9bd1c075825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 23 Apr 2024 12:34:27 +0200 Subject: [PATCH 06/79] export entities --- .../src/packages/documents/document-types/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts index 7dafabe4cf..508c015868 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts @@ -1,5 +1,6 @@ import './components/index.js'; +export * from './entity.js'; export * from './components/index.js'; export * from './workspace/index.js'; From 0326b87cfdf9bd60ca6626a6af17aaaf5a8e6897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 23 Apr 2024 12:38:17 +0200 Subject: [PATCH 07/79] tree picker create action button --- ...i-block-grid-type-configuration.element.ts | 20 ++++- .../input-block-type.element.ts | 88 ++++++++++++------- .../tree-picker/tree-picker-modal.element.ts | 29 ++++-- .../tree-picker/tree-picker-modal.token.ts | 5 +- .../modals/workspace-modal.element.ts | 4 +- 5 files changed, 100 insertions(+), 46 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 8129fb2739..b309c9ceae 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,7 +19,11 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_BLOCK_GRID_TYPE, type UmbBlockGridTypeGroupType } from '@umbraco-cms/backoffice/block-grid'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UMB_PROPERTY_DATASET_CONTEXT, type UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import { + UMB_PROPERTY_CONTEXT, + UMB_PROPERTY_DATASET_CONTEXT, + type UmbPropertyDatasetContext, +} from '@umbraco-cms/backoffice/property'; import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; @@ -70,6 +74,9 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement this.#mapValuesToBlockGroups(); } + @state() + public _alias?: string; + @property({ type: Object, attribute: false }) public config?: UmbPropertyEditorConfigCollection; @@ -86,8 +93,13 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement constructor() { super(); - this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { - this.#datasetContext = instance; + + this.consumeContext(UMB_PROPERTY_CONTEXT, async (context) => { + this._alias = context.getAlias(); + }); + + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => { + this.#datasetContext = context; //this.#observeBlocks(); this.#observeBlockGroups(); }); @@ -203,6 +215,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement return html`
${this._notGroupedBlockTypes ? html` { + // TODO: Investigate if onEnd is called when a container move has been performed, if not then I would say it should be. [NL] this.dispatchEvent(new CustomEvent('change', { detail: { moveComplete: true } })); }, }); + #elementPickerModal; @property({ type: Array, attribute: false }) public set value(items) { @@ -42,9 +44,20 @@ export class UmbInputBlockTypeElement< return this._items; } + @property({ type: String }) + public set propertyAlias(value: string | undefined) { + this.#elementPickerModal.setUniquePathValue('propertyAlias', value); + } + public get propertyAlias(): string | undefined { + return undefined; + } + @property({ type: String }) workspacePath?: string; + @state() + private _pickerPath?: string; + @state() private _items: Array = []; @@ -60,31 +73,42 @@ export class UmbInputBlockTypeElement< this.#filter = value as Array; }); }); - } - async create() { - const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + this.#elementPickerModal = new UmbModalRouteRegistrationController(this, UMB_DOCUMENT_TYPE_PICKER_MODAL) + .addUniquePaths(['propertyAlias']) + .onSetup(() => { + return { + data: { + hideTreeRoot: true, + multiple: false, + createAction: { + entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, + preset: { isElementType: true }, + }, + pickableFilter: (docType) => + // Only pick elements: + docType.isElement && + // Prevent picking the an already used element type: + this.#filter && + this.#filter.find((x) => x.contentElementTypeKey === docType.unique) === undefined, + }, + value: { + selection: [], + }, + }; + }) + .onSubmit((value) => { + const selectedElementType = value.selection[0]; - // TODO: Make as mode for the Picker Modal, so the click to select immediately submits the modal(And in that mode we do not want to see a Submit button). - const modalContext = modalManager.open(this, UMB_DOCUMENT_TYPE_PICKER_MODAL, { - data: { - hideTreeRoot: true, - multiple: false, - pickableFilter: (docType) => - // 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.dispatchEvent(new CustomEvent('create', { detail: { contentElementTypeKey: selectedElementType } })); - } + if (selectedElementType) { + this.dispatchEvent(new CustomEvent('create', { detail: { contentElementTypeKey: selectedElementType } })); + } + }) + .observeRouteBuilder((routeBuilder) => { + const oldPath = this._pickerPath; + this._pickerPath = routeBuilder({}); + this.requestUpdate('_pickerPath', oldPath); + }); } deleteItem(contentElementTypeKey: string) { @@ -131,12 +155,14 @@ export class UmbInputBlockTypeElement< }; #renderButton() { - return html` - this.create()} label="open"> - - Add - - `; + return this._pickerPath + ? html` + + + Add + + ` + : null; } static styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index b093cde9da..47bf3661af 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -1,6 +1,6 @@ import type { UmbTreeSelectionConfiguration } from '../types.js'; import type { UmbTreePickerModalData, UmbTreePickerModalValue } from './tree-picker-modal.token.js'; -import { html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UMB_WORKSPACE_MODAL, UmbModalBaseElement, @@ -21,9 +21,6 @@ export class UmbTreePickerModalElement { - return { data: { entityType: 'document-type', preset: {} } }; + .onSetup(async () => { + return { data: createActionData }; + }) + .onSubmit((value) => { + console.log('got', value); + //this.value = value; + //this.modalContext?.dispatchEvent(new UmbSelectedEvent()); }) .observeRouteBuilder((routeBuilder) => { - this._createPath = routeBuilder({}); + const oldPath = this._createPath; + this._createPath = routeBuilder({}) + 'create'; + this.requestUpdate('_createPath', oldPath); }); } } @@ -95,6 +100,12 @@ export class UmbTreePickerModalElement
+ ${this._createPath + ? html` ` + : nothing} extends UmbPickerModalData { treeAlias?: string; + // Consider if it makes sense to move this into the UmbPickerModalData interface, but for now this is a TreePicker feature. [NL] + createAction?: UmbTreePickerModalCreateActionData; } export interface UmbTreePickerModalValue extends UmbPickerModalValue {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts index 5a9722e24d..9d702fc1d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts @@ -1,13 +1,13 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbWorkspaceData } from '@umbraco-cms/backoffice/modal'; +import type { UmbWorkspaceModalData } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-workspace-modal') export class UmbWorkspaceModalElement extends UmbLitElement { @property({ attribute: false }) - data?: UmbWorkspaceData; + data?: UmbWorkspaceModalData; /** * TODO: Consider if this binding and events integration is the right for communicating back the modal handler. Or if we should go with some Context API. like a Modal Context API. From 5c79268b6abde3a82cae6a4633e0c0583f766865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 23 Apr 2024 13:38:11 +0200 Subject: [PATCH 08/79] url-pattern-to-string function --- ...nerate-route-path-builder.function.test.ts | 16 +++++++------- .../generate-route-path-builder.function.ts | 21 ++++--------------- .../src/packages/core/router/route.context.ts | 4 ++-- .../src/packages/core/utils/index.ts | 1 + .../path/url-pattern-to-string.function.ts | 12 +++++++++++ .../workspace-is-new-redirect.controller.ts | 6 +++--- 6 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts index f6de7d9f86..b768e4d582 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts @@ -1,41 +1,41 @@ import { expect } from '@open-wc/testing'; -import { createRoutePathBuilder } from './generate-route-path-builder.function.js'; +import { umbCreateRoutePathBuilder } from './generate-route-path-builder.function.js'; describe('createRoutePathBuilder', () => { it('should return a function that builds a route path without parameters', () => { - const buildPath = createRoutePathBuilder('test/path'); + const buildPath = umbCreateRoutePathBuilder('test/path'); expect(buildPath(null)).to.eq('/test/path/'); }); it('should return a function that builds a route path with parameters', () => { - const buildPath = createRoutePathBuilder(':param0/test/:param1/path/:param2'); + const buildPath = umbCreateRoutePathBuilder(':param0/test/:param1/path/:param2'); expect(buildPath({ param0: 'value0', param1: 'value1', param2: 'value2' })).to.eq( '/value0/test/value1/path/value2/', ); }); it('should convert number parameters to strings', () => { - const buildPath = createRoutePathBuilder('test/:param1/path/:param2'); + const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2'); expect(buildPath({ param1: 123, param2: 456 })).to.eq('/test/123/path/456/'); }); it('should not consider route segments that resembles parameters as parameters', () => { - const buildPath = createRoutePathBuilder('test/uc:store/path'); + const buildPath = umbCreateRoutePathBuilder('test/uc:store/path'); expect(buildPath({ someOtherParam: 'test' })).to.eq('/test/uc:store/path/'); }); it('should support multiple parameters with the same name', () => { - const buildPath = createRoutePathBuilder('test/:param1/path/:param1'); + const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param1'); expect(buildPath({ param1: 'value1' })).to.eq('/test/value1/path/value1/'); }); it('should not consider parameters that are not in the params object', () => { - const buildPath = createRoutePathBuilder('test/:param1/path/:param2'); + const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2'); expect(buildPath({ param1: 'value1' })).to.eq('/test/value1/path/:param2/'); }); it('should support complex objects as parameters with a custom toString method', () => { - const buildPath = createRoutePathBuilder('test/:param1/path/:param2'); + const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2'); const obj = { toString() { return 'value1'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts index 115a6c3f91..181abf6abf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts @@ -1,21 +1,8 @@ -/* eslint-disable */ +import { type UrlParametersRecord, umbUrlPatternToString } from '../utils/path/url-pattern-to-string.function.js'; import { stripSlash } from '@umbraco-cms/backoffice/external/router-slot'; // This must only include the util to avoid side effects of registering the route element. -const PARAM_IDENTIFIER = /:([^\/]+)/g; - -export function createRoutePathBuilder(path: string) { - return (params: { [key: string]: string | number | { toString: () => string } } | null) => { - return ( - '/' + - stripSlash( - params - ? path.replace(PARAM_IDENTIFIER, (_substring: string, ...args: string[]) => { - // Replace the parameter with the value from the params object or the parameter name if it doesn't exist (args[0] is the parameter name without the colon) - return typeof params[args[0]] !== 'undefined' ? params[args[0]].toString() : `:${args[0]}`; - }) - : path, - ) + - '/' - ); +export function umbCreateRoutePathBuilder(path: string) { + return (params: UrlParametersRecord | null) => { + return '/' + stripSlash(umbUrlPatternToString(path, params)) + '/'; }; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts index 47576a4e0b..ee860f7d6f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts @@ -1,5 +1,5 @@ import type { UmbRoute } from './route.interface.js'; -import { createRoutePathBuilder } from './generate-route-path-builder.function.js'; +import { umbCreateRoutePathBuilder } from './generate-route-path-builder.function.js'; import type { IRoutingInfo, IRouterSlot } from '@umbraco-cms/backoffice/external/router-slot'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -147,7 +147,7 @@ export class UmbRouteContext extends UmbContextBase { : this.#routerActiveLocalPath + '/' : ''; const localPath = routeBasePath + routeActiveLocalPath + modalRegistration.generateModalPath(); - const urlBuilder = createRoutePathBuilder(localPath); + const urlBuilder = umbCreateRoutePathBuilder(localPath); modalRegistration._internal_setRouteBuilder(urlBuilder); }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index ad688e29d5..8b243bcb6c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -9,6 +9,7 @@ export * from './path/path-decode.function.js'; export * from './path/path-encode.function.js'; export * from './path/path-folder-name.function.js'; export * from './path/umbraco-path.function.js'; +export * from './path/url-pattern-to-string.function.js'; export * from './selection-manager/selection.manager.js'; export * from './string/from-camel-case.function.js'; export * from './string/generate-umbraco-alias.function.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts new file mode 100644 index 0000000000..8686c8c193 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts @@ -0,0 +1,12 @@ +export type UrlParametersRecord = Record string }>; + +const PARAM_IDENTIFIER = /:([^/]+)/g; + +export function umbUrlPatternToString(pattern: string, params: UrlParametersRecord | null): string { + return params + ? pattern.replace(PARAM_IDENTIFIER, (_substring: string, ...args: string[]) => { + // Replace the parameter with the value from the params object or the parameter name if it doesn't exist (args[0] is the parameter name without the colon) + return typeof params[args[0]] !== 'undefined' ? params[args[0]].toString() : `:${args[0]}`; + }) + : pattern; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts index fa3434a304..daabfc3140 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts @@ -1,8 +1,8 @@ import type { UmbSubmittableWorkspaceContextBase } from '../contexts/index.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import { createRoutePathBuilder, type UmbRouterSlotElement } from '@umbraco-cms/backoffice/router'; -import { ensurePathEndsWithSlash } from '@umbraco-cms/backoffice/utils'; +import type { UmbRouterSlotElement } from '@umbraco-cms/backoffice/router'; +import { ensurePathEndsWithSlash, umbUrlPatternToString } from '@umbraco-cms/backoffice/utils'; /** * Observe the workspace context to see if the entity is new or not. @@ -28,7 +28,7 @@ export class UmbWorkspaceIsNewRedirectController extends UmbControllerBase { if (router && unique) { const routerPath = router.absoluteRouterPath; if (routerPath) { - const newPath: string = createRoutePathBuilder(ensurePathEndsWithSlash(routerPath) + 'edit/:id')({ + const newPath: string = umbUrlPatternToString(ensurePathEndsWithSlash(routerPath) + 'edit/:id', { id: unique, }); this.destroy(); From abf94a94d89c2338a75eec8cf39dfcb3934bdd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 23 Apr 2024 13:38:22 +0200 Subject: [PATCH 09/79] document type paths --- .../src/packages/documents/document-types/paths.ts | 2 ++ .../workspace/document-type-workspace.context.ts | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts new file mode 100644 index 0000000000..1b3fb9a636 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts @@ -0,0 +1,2 @@ +export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH = 'create/:entityType/:parentUnique/:presetAlias'; +export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH = 'edit/:id'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 08b2610991..09781411a0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -1,6 +1,7 @@ import { UmbDocumentTypeDetailRepository } from '../repository/detail/document-type-detail.repository.js'; import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../entity.js'; import type { UmbDocumentTypeDetailModel } from '../types.js'; +import { UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH } from '../paths.js'; import { UmbDocumentTypeWorkspaceEditorElement } from './document-type-workspace-editor.element.js'; import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; @@ -89,7 +90,7 @@ export class UmbDocumentTypeWorkspaceContext this.routes.setRoutes([ { - path: 'create/:entityType/:parentUnique/:presetAlias', + path: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, component: UmbDocumentTypeWorkspaceEditorElement, setup: (_component, info) => { const parentEntityType = info.match.params.entityType; @@ -105,7 +106,7 @@ export class UmbDocumentTypeWorkspaceContext }, }, { - path: 'edit/:id', + path: UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH, component: UmbDocumentTypeWorkspaceEditorElement, setup: (_component, info) => { this.removeUmbControllerByAlias('isNewRedirectController'); From 42c62a05a297af10f357b4475caa7b43963e8349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 15:49:48 +0200 Subject: [PATCH 10/79] path consts and types for document type workspace --- .../input-block-type.element.ts | 18 ++++++++++++--- .../tree-picker/tree-picker-modal.element.ts | 20 +++++++++------- .../tree-picker/tree-picker-modal.token.ts | 16 ++++++++++--- .../path/url-pattern-to-string.function.ts | 7 +++--- .../documents/document-types/entity.ts | 5 ++++ .../documents/document-types/index.ts | 9 ++++---- .../document-type-picker-modal.token.ts | 18 +++++++++++++-- .../documents/document-types/paths.ts | 23 +++++++++++++++++++ .../document-type-workspace.context.ts | 12 +++++++--- .../document-type-workspace.modal-token.ts | 13 +++++++++++ .../document-types/workspace/index.ts | 1 + 11 files changed, 115 insertions(+), 27 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts 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 67d33fb3d9..2e5ca4ecda 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 @@ -7,7 +7,11 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import { UmbDeleteEvent } from '@umbraco-cms/backoffice/event'; -import { UMB_DOCUMENT_TYPE_PICKER_MODAL, UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '@umbraco-cms/backoffice/document-type'; +import { + UMB_DOCUMENT_TYPE_PICKER_MODAL, + UMB_DOCUMENT_TYPE_ENTITY_TYPE, + umbCreateDocumentTypeWorkspacePathGenerator, +} from '@umbraco-cms/backoffice/document-type'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; /** TODO: Look into sending a "change" event when there is a change, rather than create, delete, and change event. Make sure it doesn't break move for RTE/List/Grid. [LI] */ @@ -82,8 +86,16 @@ export class UmbInputBlockTypeElement< hideTreeRoot: true, multiple: false, createAction: { - entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, - preset: { isElementType: true }, + modalData: { + entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, + preset: { isElementType: true }, + }, + additionalPathGenerator: umbCreateDocumentTypeWorkspacePathGenerator, + additionalPathParams: { + entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, + parentUnique: null, + presetAlias: 'element', + }, }, pickableFilter: (docType) => // Only pick elements: diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index 47bf3661af..41220920d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -45,20 +45,24 @@ export class UmbTreePickerModalElement { - return { data: createActionData }; + new UmbModalRouteRegistrationController( + this, + (createActionData.modalToken as typeof UMB_WORKSPACE_MODAL) ?? UMB_WORKSPACE_MODAL, + ) + .onSetup(() => { + return { data: createActionData.modalData }; }) .onSubmit((value) => { - console.log('got', value); - //this.value = value; - //this.modalContext?.dispatchEvent(new UmbSelectedEvent()); + if (value) { + this.value = { selection: [value.unique] }; + this._submitModal(); + } }) .observeRouteBuilder((routeBuilder) => { const oldPath = this._createPath; - this._createPath = routeBuilder({}) + 'create'; + this._createPath = + routeBuilder({}) + createActionData.additionalPathGenerator(createActionData.additionalPathParams); this.requestUpdate('_createPath', oldPath); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts index 2e656d804c..a6ab0af664 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts @@ -2,11 +2,21 @@ import { UMB_TREE_PICKER_MODAL_ALIAS } from './constants.js'; import type { UmbPickerModalData, UmbPickerModalValue, UmbWorkspaceModalData } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -export interface UmbTreePickerModalCreateActionData extends UmbWorkspaceModalData {} -export interface UmbTreePickerModalData extends UmbPickerModalData { +export type UmbPathGeneratorType = (params: any) => string; +export interface UmbTreePickerModalCreateActionData { + modalData: UmbWorkspaceModalData; + modalToken?: UmbModalToken; + additionalPathGenerator: PathGeneratorType; + additionalPathParams: Parameters[0]; +} + +export interface UmbTreePickerModalData< + TreeItemType = any, + PathGeneratorType extends UmbPathGeneratorType = UmbPathGeneratorType, +> extends UmbPickerModalData { treeAlias?: string; // Consider if it makes sense to move this into the UmbPickerModalData interface, but for now this is a TreePicker feature. [NL] - createAction?: UmbTreePickerModalCreateActionData; + createAction?: UmbTreePickerModalCreateActionData; } export interface UmbTreePickerModalValue extends UmbPickerModalValue {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts index 8686c8c193..e927e3cf15 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts @@ -1,12 +1,13 @@ -export type UrlParametersRecord = Record string }>; +export type UrlParametersRecord = Record string } | null>; const PARAM_IDENTIFIER = /:([^/]+)/g; export function umbUrlPatternToString(pattern: string, params: UrlParametersRecord | null): string { return params ? pattern.replace(PARAM_IDENTIFIER, (_substring: string, ...args: string[]) => { - // Replace the parameter with the value from the params object or the parameter name if it doesn't exist (args[0] is the parameter name without the colon) - return typeof params[args[0]] !== 'undefined' ? params[args[0]].toString() : `:${args[0]}`; + const segmentName = args[0]; // (segmentName is the parameter name without the colon) + // Replace the path-segment with the value from the params object or 'null' if it doesn't exist + return params![segmentName]?.toString() ?? 'null'; }) : pattern; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity.ts index c19555dccf..7279881dac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity.ts @@ -5,3 +5,8 @@ export const UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE = 'document-type-folder'; export type UmbDocumentTypeEntityType = typeof UMB_DOCUMENT_TYPE_ENTITY_TYPE; export type UmbDocumentTypeRootEntityType = typeof UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE; export type UmbDocumentTypeFolderEntityType = typeof UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE; + +export type UmbDocumentTypeEntityTypeUnion = + | UmbDocumentTypeEntityType + | UmbDocumentTypeRootEntityType + | UmbDocumentTypeFolderEntityType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts index 508c015868..058bd6dbfe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts @@ -1,11 +1,10 @@ import './components/index.js'; -export * from './entity.js'; export * from './components/index.js'; -export * from './workspace/index.js'; - +export * from './entity.js'; +export * from './modals/index.js'; +export * from './paths.js'; export * from './repository/index.js'; export * from './tree/types.js'; export * from './types.js'; - -export * from './modals/index.js'; +export * from './workspace/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts index b9ff521986..8fc9713972 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts @@ -1,3 +1,4 @@ +import { umbCreateDocumentTypeWorkspacePathGenerator } from '../paths.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentTypeTreeItemModel } from '@umbraco-cms/backoffice/document-type'; import { @@ -6,8 +7,9 @@ import { UMB_TREE_PICKER_MODAL_ALIAS, } from '@umbraco-cms/backoffice/tree'; -export type UmbDocumentTypePickerModalData = UmbTreePickerModalData; -export type UmbDocumentTypePickerModalValue = UmbTreePickerModalValue; +export interface UmbDocumentTypePickerModalData + extends UmbTreePickerModalData {} +export interface UmbDocumentTypePickerModalValue extends UmbTreePickerModalValue {} export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< UmbDocumentTypePickerModalData, @@ -19,5 +21,17 @@ export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< }, data: { treeAlias: 'Umb.Tree.DocumentType', + createAction: { + modalData: { + entityType: 'documentType', + preset: {}, + }, + additionalPathGenerator: umbCreateDocumentTypeWorkspacePathGenerator, + additionalPathParams: { + entityType: 'documentType', + parentUnique: '', + presetAlias: '', + }, + }, }, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts index 1b3fb9a636..93b117acb3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts @@ -1,2 +1,25 @@ +import type { UmbDocumentTypeEntityTypeUnion } from './entity.js'; +import { umbUrlPatternToString } from '@umbraco-cms/backoffice/utils'; + +export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE = 'template'; +export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT = 'element'; + +export type UmbCreateDocumentTypeWorkspacePresetTemplateType = + typeof UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE; +export type UmbCreateDocumentTypeWorkspacePresetElementType = // line break thanks! + typeof UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT; + +export type UmbCreateDocumentTypeWorkspacePresetType = + | UmbCreateDocumentTypeWorkspacePresetTemplateType + | UmbCreateDocumentTypeWorkspacePresetElementType; + export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH = 'create/:entityType/:parentUnique/:presetAlias'; +export const umbCreateDocumentTypeWorkspacePathGenerator = (params: { + entityType: UmbDocumentTypeEntityTypeUnion; + parentUnique?: string | null; + presetAlias?: UmbCreateDocumentTypeWorkspacePresetType | null; +}) => umbUrlPatternToString(UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, params); + export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH = 'edit/:id'; +export const umbEditDocumentTypeWorkspacePathGenerator = (params: { id: string }) => + umbUrlPatternToString(UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, params); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 09781411a0..b5194e7080 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -1,7 +1,13 @@ import { UmbDocumentTypeDetailRepository } from '../repository/detail/document-type-detail.repository.js'; import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../entity.js'; import type { UmbDocumentTypeDetailModel } from '../types.js'; -import { UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH } from '../paths.js'; +import { + UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, + UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT, + UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE, + UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH, + type UmbCreateDocumentTypeWorkspacePresetType, +} from '../paths.js'; import { UmbDocumentTypeWorkspaceEditorElement } from './document-type-workspace-editor.element.js'; import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; @@ -199,12 +205,12 @@ export class UmbDocumentTypeWorkspaceContext if (!data) return undefined; switch (presetAlias) { - case 'template': { + case UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE satisfies UmbCreateDocumentTypeWorkspacePresetType: { this.setIcon('icon-notepad'); this.createTemplateMode = true; break; } - case 'element': { + case UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT satisfies UmbCreateDocumentTypeWorkspacePresetType: { this.setIcon('icon-plugin'); this.setIsElement(true); break; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts new file mode 100644 index 0000000000..7d26329ecc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.modal-token.ts @@ -0,0 +1,13 @@ +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import { UMB_WORKSPACE_MODAL, UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentTypeWorkspaceData extends UmbWorkspaceModalData {} + +export const UMB_DOCUMENT_TYPE_WORKSPACE_MODAL = new UmbModalToken< + UmbDocumentTypeWorkspaceData, + UmbWorkspaceModalValue +>('Umb.Modal.Workspace', { + modal: UMB_WORKSPACE_MODAL.getDefaultModal(), + data: { entityType: 'block', preset: {} }, + // Recast the type, so the entityType data prop is not required: +}) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/index.ts index b5c792e5ef..cf7ab5393f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/index.ts @@ -1 +1,2 @@ export * from './document-type-workspace.context-token.js'; +export * from './document-type-workspace.modal-token.js'; From 5bffe4366a14310504894dd32bab482ef584f457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 21:21:11 +0200 Subject: [PATCH 11/79] deep merge --- .../src/packages/core/utils/index.ts | 3 +- .../core/utils/object/deep-merge.function.ts | 22 +++++++ .../core/utils/object/deep-merge.test.ts | 61 +++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index 8b243bcb6c..09d60ef911 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -16,4 +16,5 @@ export * from './string/generate-umbraco-alias.function.js'; export * from './string/increment-string.function.js'; export * from './string/split-string-to-array.js'; export * from './string/to-camel-case/to-camel-case.function.js'; -export * from './type/diff.type.js'; +export type * from './type/deep-partial.type.js'; +export type * from './type/diff.type.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts new file mode 100644 index 0000000000..b08629cb1d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts @@ -0,0 +1,22 @@ +import type { DeepPartial } from '../type/deep-partial.type.js'; + +/** + * Deep merge two objects. + * @param target + * @param ...sources + */ +export function umbDeepMerge(source: DeepPartial, fallback: T) { + const result = { ...fallback }; + + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key) && source[key] !== undefined) { + if (source[key].constructor === Object && fallback[key].constructor === Object) { + result[key] = umbDeepMerge(source[key], fallback[key]); + } else { + result[key] = source[key] as any; + } + } + } + + return result; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.test.ts new file mode 100644 index 0000000000..61509c9162 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.test.ts @@ -0,0 +1,61 @@ +import { expect } from '@open-wc/testing'; +import { umbDeepMerge } from './deep-merge.function.js'; + +describe('UmbDeepMerge', () => { + beforeEach(() => {}); + + describe('merge just objects', () => { + it('transfers defined properties', () => { + const defaults = { + prop1: { + name: 'prop1', + value: 'value1', + }, + prop2: { + name: 'prop2', + value: 'value2', + }, + }; + const source = { + prop2: { + name: 'prop2_updatedName', + }, + }; + const result = umbDeepMerge(source, defaults); + + expect(result.prop1.name).to.equal('prop1'); + expect(result.prop2.name).to.equal('prop2_updatedName'); + }); + }); + + describe('merge objects with arrays', () => { + // The arrays should not be merged, but take the value from the main object. [NL] + it('transfers defined properties', () => { + const defaults = { + prop1: { + name: 'prop1', + value: ['entry1', 'entry2', 'entry3'], + }, + prop2: { + name: 'prop2', + value: ['entry4', 'entry4', 'entry5'], + }, + }; + const source = { + prop1: { + name: 'prop1_updatedName', + }, + prop2: { + name: 'prop2_updatedName', + value: ['entry666'], + }, + }; + const result = umbDeepMerge(source, defaults); + + expect(result.prop1.name).to.equal('prop1_updatedName'); + expect(result.prop2.value.join(',')).to.equal(defaults.prop1.value.join(',')); + expect(result.prop2.name).to.equal('prop2_updatedName'); + expect(result.prop2.value.join(',')).to.equal(source.prop2.value.join(',')); + }); + }); +}); From a3069c619545067015b5c699b01e7b5a3c3589e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 21:21:51 +0200 Subject: [PATCH 12/79] url-pattern-to-string correction --- .../core/utils/path/url-pattern-to-string.function.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts index e927e3cf15..1cd087a67e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/path/url-pattern-to-string.function.ts @@ -5,9 +5,9 @@ const PARAM_IDENTIFIER = /:([^/]+)/g; export function umbUrlPatternToString(pattern: string, params: UrlParametersRecord | null): string { return params ? pattern.replace(PARAM_IDENTIFIER, (_substring: string, ...args: string[]) => { - const segmentName = args[0]; // (segmentName is the parameter name without the colon) + const segmentValue = params![args[0]]; // (segmentValue is the value to replace the parameter) // Replace the path-segment with the value from the params object or 'null' if it doesn't exist - return params![segmentName]?.toString() ?? 'null'; + return segmentValue === undefined ? `:${args[0]}` : segmentValue === null ? 'null' : segmentValue.toString(); }) : pattern; } From e00975e64bada859f1492f138af31c3954280644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 21:25:02 +0200 Subject: [PATCH 13/79] deep-partial type --- .../src/packages/core/utils/type/deep-partial.type.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts new file mode 100644 index 0000000000..65bb71bfa0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts @@ -0,0 +1,5 @@ +export type DeepPartial = T extends object + ? { + [P in keyof T]?: DeepPartial; + } + : T; From fdbe522a8ef3460d21ca9abec17044ed1b5918dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 22:20:31 +0200 Subject: [PATCH 14/79] eport util --- src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index 09d60ef911..572569ab13 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -3,6 +3,7 @@ export * from './direction/index.js'; export * from './download/blob-download.function.js'; export * from './get-processed-image-url.function.js'; export * from './math/math.js'; +export * from './object/deep-merge.function.js'; export * from './pagination-manager/pagination.manager.js'; export * from './path/ensure-path-ends-with-slash.function.js'; export * from './path/path-decode.function.js'; From 433bdc4c74ef6a620cc9bb02d1a47e7cf9aed220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 23:42:36 +0200 Subject: [PATCH 15/79] deep partial modal data, for more fine grained definitions --- .../modal/context/modal-manager.context.ts | 2 +- .../core/modal/context/modal.context.ts | 18 +++++++++-- .../modal-route-registration.controller.ts | 19 +++++++----- .../modal-route-registration.interface.ts | 5 +++- .../packages/core/modal/token/modal-token.ts | 10 +++++-- .../tree-picker/tree-picker-modal.token.ts | 4 +-- .../src/packages/core/utils/index.ts | 2 +- .../core/utils/object/deep-merge.function.ts | 11 ++++--- .../utils/type/deep-partial-object.type.ts | 30 +++++++++++++++++++ .../core/utils/type/deep-partial.type.ts | 5 ---- 10 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial-object.type.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts index eb74e7deca..0764a232c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts @@ -38,7 +38,7 @@ export class UmbModalManagerContext extends UmbContextBase, >( diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts index 05d6220b7a..2fc6c8da0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal.context.ts @@ -6,6 +6,7 @@ import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; import { UmbId } from '@umbraco-cms/backoffice/id'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { type UmbDeepPartialObject, umbDeepMerge } from '@umbraco-cms/backoffice/utils'; export interface UmbModalRejectReason { type: string; @@ -13,7 +14,9 @@ export interface UmbModalRejectReason { export type UmbModalContextClassArgs< ModalAliasType extends string | UmbModalToken, - ModalAliasTypeAsToken extends UmbModalToken = ModalAliasType extends UmbModalToken ? ModalAliasType : UmbModalToken, + ModalAliasTypeAsToken extends UmbModalToken = ModalAliasType extends UmbModalToken + ? ModalAliasType + : UmbModalToken, > = { router?: IRouterSlot | null; data?: ModalAliasTypeAsToken['DATA']; @@ -22,7 +25,10 @@ export type UmbModalContextClassArgs< }; // TODO: consider splitting this into two separate handlers -export class UmbModalContext extends UmbControllerBase { +export class UmbModalContext< + ModalPreset extends { [key: string]: any } = { [key: string]: any }, + ModalValue = any, +> extends UmbControllerBase { // #submitPromise: Promise; #submitResolver?: (value: ModalValue) => void; @@ -60,7 +66,13 @@ export class UmbModalContext, defaultData) as ModalPreset) + : // otherwise pick one of them: + (args.data as ModalPreset) ?? defaultData, + ); const initValue = args.value ?? (this.alias instanceof UmbModalToken ? (this.alias as UmbModalToken).getDefaultValue() : undefined); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.controller.ts index b4de970109..b645cc0185 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.controller.ts @@ -1,25 +1,30 @@ import type { UmbModalToken } from '../token/index.js'; import type { UmbModalConfig, UmbModalContext, UmbModalManagerContext, UmbModalRouteRegistration } from '../index.js'; +import type { UmbModalContextClassArgs } from '../context/modal.context.js'; import { type Params, type IRouterSlot, UMB_ROUTE_CONTEXT, encodeFolderName } from '@umbraco-cms/backoffice/router'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbId } from '@umbraco-cms/backoffice/id'; +import type { UmbDeepPartialObject } from '@umbraco-cms/backoffice/utils'; export type UmbModalRouteBuilder = (params: { [key: string]: string | number } | null) => string; export type UmbModalRouteSetupReturn = UmbModalTokenValue extends undefined ? { - modal?: UmbModalConfig; - data: UmbModalTokenData; + modal?: UmbDeepPartialObject; + data: UmbDeepPartialObject; value?: UmbModalTokenValue; } : { - modal?: UmbModalConfig; - data: UmbModalTokenData; + modal?: UmbDeepPartialObject; + data: UmbDeepPartialObject; value: UmbModalTokenValue; }; -export class UmbModalRouteRegistrationController +export class UmbModalRouteRegistrationController< + UmbModalTokenData extends { [key: string]: any } = { [key: string]: any }, + UmbModalTokenValue = any, + > extends UmbControllerBase implements UmbModalRouteRegistration { @@ -293,8 +298,8 @@ export class UmbModalRouteRegistrationController>; + args.modal!.key = this.#key; this.#modalContext = modalManagerContext.open(this, this.#modalAlias, args); this.#modalContext.onSubmit().then(this.#onSubmit, this.#onReject); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.interface.ts index e4113c2408..a1af2fbcf7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/route-registration/modal-route-registration.interface.ts @@ -3,7 +3,10 @@ import type { UmbModalContext, UmbModalRouteBuilder } from '../index.js'; import type { UmbModalToken } from '../token/modal-token.js'; import type { IRouterSlot, Params } from '@umbraco-cms/backoffice/router'; -export interface UmbModalRouteRegistration { +export interface UmbModalRouteRegistration< + UmbModalTokenData extends { [key: string]: any } = { [key: string]: any }, + UmbModalTokenValue = any, +> { key: string; alias: UmbModalToken | string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/modal-token.ts index 8d45fde4b9..61d66ce63e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/modal-token.ts @@ -1,12 +1,18 @@ import type { UmbModalConfig } from '../context/modal-manager.context.js'; -export interface UmbModalTokenDefaults { +export interface UmbModalTokenDefaults< + ModalDataType extends { [key: string]: any } = { [key: string]: any }, + ModalValueType = unknown, +> { modal?: UmbModalConfig; data?: ModalDataType; value?: ModalValueType; } -export class UmbModalToken { +export class UmbModalToken< + ModalDataType extends { [key: string]: any } = { [key: string]: any }, + ModalValueType = unknown, +> { /** * Get the data type of the token's data. * diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts index a6ab0af664..d5d3affed0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts @@ -11,7 +11,7 @@ export interface UmbTreePickerModalCreateActionData extends UmbPickerModalData { treeAlias?: string; @@ -21,7 +21,7 @@ export interface UmbTreePickerModalData< export interface UmbTreePickerModalValue extends UmbPickerModalValue {} -export const UMB_TREE_PICKER_MODAL = new UmbModalToken( +export const UMB_TREE_PICKER_MODAL = new UmbModalToken, UmbTreePickerModalValue>( UMB_TREE_PICKER_MODAL_ALIAS, { modal: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index 572569ab13..6895540e28 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -17,5 +17,5 @@ export * from './string/generate-umbraco-alias.function.js'; export * from './string/increment-string.function.js'; export * from './string/split-string-to-array.js'; export * from './string/to-camel-case/to-camel-case.function.js'; -export type * from './type/deep-partial.type.js'; +export type * from './type/deep-partial-object.type.js'; export type * from './type/diff.type.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts index b08629cb1d..94b67c9b94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/object/deep-merge.function.ts @@ -1,17 +1,20 @@ -import type { DeepPartial } from '../type/deep-partial.type.js'; +import type { UmbDeepPartialObject } from '../type/deep-partial-object.type.js'; /** * Deep merge two objects. * @param target * @param ...sources */ -export function umbDeepMerge(source: DeepPartial, fallback: T) { +export function umbDeepMerge< + T extends { [key: string]: any }, + PartialType extends UmbDeepPartialObject = UmbDeepPartialObject, +>(source: PartialType, fallback: T) { const result = { ...fallback }; for (const key in source) { if (Object.prototype.hasOwnProperty.call(source, key) && source[key] !== undefined) { - if (source[key].constructor === Object && fallback[key].constructor === Object) { - result[key] = umbDeepMerge(source[key], fallback[key]); + if (source[key]?.constructor === Object && fallback[key].constructor === Object) { + result[key] = umbDeepMerge(source[key] as any, fallback[key]); } else { result[key] = source[key] as any; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial-object.type.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial-object.type.ts new file mode 100644 index 0000000000..7961caf5d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial-object.type.ts @@ -0,0 +1,30 @@ +/*export type DeepPartial = T extends { [key: string]: any } + ? { + [P in keyof T]?: DeepPartial; + } + : T; +*/ + +// Notice this can be way more complex, but in this case I just wanted to cover pure objects, to match our deep merge function [NL] +// See https://stackoverflow.com/questions/61132262/typescript-deep-partial for more extensive solutions. +/** + * Deep partial object type, making objects and their properties optional, but only until a property of a different type is encountered. + * This means if an object holds a property with an array that holds objects, the array will be made optional, but the properties of the objects inside the array will not be changed. + * @type UmbDeepPartialObject + * @generic T - The object to make partial. + * @returns A type with all properties of objects made optional. + */ +// eslint-disable-next-line @typescript-eslint/ban-types +export type UmbDeepPartialObject = T extends Function + ? T + : // Thing extends Array + // ? DeepPartialArray : + T extends { [key: string]: any } + ? UmbDeepPartialObjectProperty + : T | undefined; + +//interface DeepPartialArray extends Array> {} + +type UmbDeepPartialObjectProperty = { + [Key in keyof Thing]?: UmbDeepPartialObject; +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts deleted file mode 100644 index 65bb71bfa0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/type/deep-partial.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type DeepPartial = T extends object - ? { - [P in keyof T]?: DeepPartial; - } - : T; From 4875e1db14fed35d04d7719d1b7c01d47e84c048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 23:43:04 +0200 Subject: [PATCH 16/79] remove unnesecary modal data in implementation --- .../components/input-block-type/input-block-type.element.ts | 6 ------ 1 file changed, 6 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 2e5ca4ecda..c8a685055e 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 @@ -86,13 +86,7 @@ export class UmbInputBlockTypeElement< hideTreeRoot: true, multiple: false, createAction: { - modalData: { - entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, - preset: { isElementType: true }, - }, - additionalPathGenerator: umbCreateDocumentTypeWorkspacePathGenerator, additionalPathParams: { - entityType: UMB_DOCUMENT_TYPE_ENTITY_TYPE, parentUnique: null, presetAlias: 'element', }, From 86ddab0c37b995b88ff605b30ea7454fcf5d12db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 23:45:04 +0200 Subject: [PATCH 17/79] improed modal token --- .../modals/document-type-picker-modal.token.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts index 8fc9713972..956ae78c1d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts @@ -7,8 +7,14 @@ import { UMB_TREE_PICKER_MODAL_ALIAS, } from '@umbraco-cms/backoffice/tree'; -export interface UmbDocumentTypePickerModalData +/*export interface UmbDocumentTypePickerModalData extends UmbTreePickerModalData {} +*/ +export type UmbDocumentTypePickerModalData = UmbTreePickerModalData< + UmbDocumentTypeTreeItemModel, + typeof umbCreateDocumentTypeWorkspacePathGenerator +>; + export interface UmbDocumentTypePickerModalValue extends UmbTreePickerModalValue {} export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< @@ -23,14 +29,14 @@ export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< treeAlias: 'Umb.Tree.DocumentType', createAction: { modalData: { - entityType: 'documentType', + entityType: 'document-type', preset: {}, }, additionalPathGenerator: umbCreateDocumentTypeWorkspacePathGenerator, additionalPathParams: { - entityType: 'documentType', - parentUnique: '', - presetAlias: '', + entityType: 'document-type', + parentUnique: null, + presetAlias: null, }, }, }, From f13ab36561b281d2591e93084b174a8fd454c351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 24 Apr 2024 23:45:20 +0200 Subject: [PATCH 18/79] better rejection when failed workspace modal --- .../core/tree/tree-picker/tree-picker-modal.element.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index 41220920d7..dea4836ea8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -57,6 +57,9 @@ export class UmbTreePickerModalElement { From e58087667a6b7d6e88366cf23d596d92968a1cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Apr 2024 12:50:27 +0200 Subject: [PATCH 19/79] refactor to use umbPathPattern --- .../input-block-type.element.ts | 8 ++--- ...nerate-route-path-builder.function.test.ts | 16 ++++----- .../generate-route-path-builder.function.ts | 7 +++- .../src/packages/core/router/index.ts | 2 +- .../core/router/path-pattern.class.ts | 35 +++++++++++++++++++ .../src/packages/core/router/route.context.ts | 4 +-- .../tree-picker/tree-picker-modal.element.ts | 3 +- .../tree-picker/tree-picker-modal.token.ts | 12 +++---- .../document-type-picker-modal.token.ts | 8 ++--- .../documents/document-types/paths.ts | 11 +++--- .../document-type-workspace.context.ts | 4 +-- 11 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts 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 c8a685055e..ef77263298 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 @@ -7,11 +7,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import { UmbDeleteEvent } from '@umbraco-cms/backoffice/event'; -import { - UMB_DOCUMENT_TYPE_PICKER_MODAL, - UMB_DOCUMENT_TYPE_ENTITY_TYPE, - umbCreateDocumentTypeWorkspacePathGenerator, -} from '@umbraco-cms/backoffice/document-type'; +import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/document-type'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; /** TODO: Look into sending a "change" event when there is a change, rather than create, delete, and change event. Make sure it doesn't break move for RTE/List/Grid. [LI] */ @@ -86,7 +82,7 @@ export class UmbInputBlockTypeElement< hideTreeRoot: true, multiple: false, createAction: { - additionalPathParams: { + extendWithPathParams: { parentUnique: null, presetAlias: 'element', }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts index b768e4d582..59637c2db8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.test.ts @@ -1,41 +1,41 @@ import { expect } from '@open-wc/testing'; -import { umbCreateRoutePathBuilder } from './generate-route-path-builder.function.js'; +import { umbGenerateRoutePathBuilder } from './generate-route-path-builder.function.js'; describe('createRoutePathBuilder', () => { it('should return a function that builds a route path without parameters', () => { - const buildPath = umbCreateRoutePathBuilder('test/path'); + const buildPath = umbGenerateRoutePathBuilder('test/path'); expect(buildPath(null)).to.eq('/test/path/'); }); it('should return a function that builds a route path with parameters', () => { - const buildPath = umbCreateRoutePathBuilder(':param0/test/:param1/path/:param2'); + const buildPath = umbGenerateRoutePathBuilder(':param0/test/:param1/path/:param2'); expect(buildPath({ param0: 'value0', param1: 'value1', param2: 'value2' })).to.eq( '/value0/test/value1/path/value2/', ); }); it('should convert number parameters to strings', () => { - const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2'); + const buildPath = umbGenerateRoutePathBuilder('test/:param1/path/:param2'); expect(buildPath({ param1: 123, param2: 456 })).to.eq('/test/123/path/456/'); }); it('should not consider route segments that resembles parameters as parameters', () => { - const buildPath = umbCreateRoutePathBuilder('test/uc:store/path'); + const buildPath = umbGenerateRoutePathBuilder('test/uc:store/path'); expect(buildPath({ someOtherParam: 'test' })).to.eq('/test/uc:store/path/'); }); it('should support multiple parameters with the same name', () => { - const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param1'); + const buildPath = umbGenerateRoutePathBuilder('test/:param1/path/:param1'); expect(buildPath({ param1: 'value1' })).to.eq('/test/value1/path/value1/'); }); it('should not consider parameters that are not in the params object', () => { - const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2'); + const buildPath = umbGenerateRoutePathBuilder('test/:param1/path/:param2'); expect(buildPath({ param1: 'value1' })).to.eq('/test/value1/path/:param2/'); }); it('should support complex objects as parameters with a custom toString method', () => { - const buildPath = umbCreateRoutePathBuilder('test/:param1/path/:param2'); + const buildPath = umbGenerateRoutePathBuilder('test/:param1/path/:param2'); const obj = { toString() { return 'value1'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts index 181abf6abf..24db7b9dc6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/generate-route-path-builder.function.ts @@ -1,8 +1,13 @@ import { type UrlParametersRecord, umbUrlPatternToString } from '../utils/path/url-pattern-to-string.function.js'; import { stripSlash } from '@umbraco-cms/backoffice/external/router-slot'; // This must only include the util to avoid side effects of registering the route element. -export function umbCreateRoutePathBuilder(path: string) { +export function umbGenerateRoutePathBuilder(path: string) { return (params: UrlParametersRecord | null) => { return '/' + stripSlash(umbUrlPatternToString(path, params)) + '/'; }; } + +/** + * @deprecated Use `umbGenerateRoutePathBuilder` instead. + */ +export { umbGenerateRoutePathBuilder as umbCreateRoutePathBuilder }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/index.ts index c4b9ff29db..7aeb5ac6ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/index.ts @@ -1,8 +1,8 @@ export * from '@umbraco-cms/backoffice/external/router-slot'; export * from './encode-folder-name.function.js'; -export * from './generate-route-path-builder.function.js'; export * from './route.context.js'; export * from './route.interface.js'; export * from './router-slot-change.event.js'; export * from './router-slot-init.event.js'; export * from './router-slot.element.js'; +export * from './path-pattern.class.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts new file mode 100644 index 0000000000..31ed8b8b57 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts @@ -0,0 +1,35 @@ +import { umbUrlPatternToString } from '../utils/path/url-pattern-to-string.function.js'; + +export type UmbPathPatternParamsType = { [key: string]: any }; + +export class UmbPathPattern { + #local: string; + #base: string; + + /** + * Get the params type of the path pattern + * + * @public + * @type {T} + * @memberOf UmbPathPattern + * @example `typeof MyPathPattern.PARAMS` + * @returns undefined + */ + readonly PARAMS!: LocalParamsType; + + constructor(localPattern: string, basePath?: string) { + this.#local = localPattern; + this.#base = basePath ? (basePath.lastIndexOf('/') !== basePath.length - 1 ? basePath + '/' : basePath) : ''; + } + + generateLocal(params: LocalParamsType) { + return umbUrlPatternToString(this.#local, params); + } + generateGlobal(params: LocalParamsType) { + return this.#base + umbUrlPatternToString(this.#local, params); + } + + toString() { + return this.#local; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts index ee860f7d6f..61213982e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/route.context.ts @@ -1,5 +1,5 @@ import type { UmbRoute } from './route.interface.js'; -import { umbCreateRoutePathBuilder } from './generate-route-path-builder.function.js'; +import { umbGenerateRoutePathBuilder } from './generate-route-path-builder.function.js'; import type { IRoutingInfo, IRouterSlot } from '@umbraco-cms/backoffice/external/router-slot'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -147,7 +147,7 @@ export class UmbRouteContext extends UmbContextBase { : this.#routerActiveLocalPath + '/' : ''; const localPath = routeBasePath + routeActiveLocalPath + modalRegistration.generateModalPath(); - const urlBuilder = umbCreateRoutePathBuilder(localPath); + const urlBuilder = umbGenerateRoutePathBuilder(localPath); modalRegistration._internal_setRouteBuilder(urlBuilder); }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index dea4836ea8..dc441fe8df 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -65,7 +65,8 @@ export class UmbTreePickerModalElement { const oldPath = this._createPath; this._createPath = - routeBuilder({}) + createActionData.additionalPathGenerator(createActionData.additionalPathParams); + routeBuilder({}) + + createActionData.extendWithPathPattern.generateLocal(createActionData.extendWithPathParams); this.requestUpdate('_createPath', oldPath); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts index d5d3affed0..03f5152144 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts @@ -1,22 +1,22 @@ import { UMB_TREE_PICKER_MODAL_ALIAS } from './constants.js'; import type { UmbPickerModalData, UmbPickerModalValue, UmbWorkspaceModalData } from '@umbraco-cms/backoffice/modal'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import type { UmbPathPattern, UmbPathPatternParamsType } from '@umbraco-cms/backoffice/router'; -export type UmbPathGeneratorType = (params: any) => string; -export interface UmbTreePickerModalCreateActionData { +export interface UmbTreePickerModalCreateActionData { modalData: UmbWorkspaceModalData; modalToken?: UmbModalToken; - additionalPathGenerator: PathGeneratorType; - additionalPathParams: Parameters[0]; + extendWithPathPattern: UmbPathPattern; + extendWithPathParams: PathPatternParamsType; } export interface UmbTreePickerModalData< TreeItemType, - PathGeneratorType extends UmbPathGeneratorType = UmbPathGeneratorType, + PathPatternParamsType extends UmbPathPatternParamsType = UmbPathPatternParamsType, > extends UmbPickerModalData { treeAlias?: string; // Consider if it makes sense to move this into the UmbPickerModalData interface, but for now this is a TreePicker feature. [NL] - createAction?: UmbTreePickerModalCreateActionData; + createAction?: UmbTreePickerModalCreateActionData; } export interface UmbTreePickerModalValue extends UmbPickerModalValue {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts index 956ae78c1d..2221229a12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts @@ -1,4 +1,4 @@ -import { umbCreateDocumentTypeWorkspacePathGenerator } from '../paths.js'; +import { UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH } from '../paths.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentTypeTreeItemModel } from '@umbraco-cms/backoffice/document-type'; import { @@ -12,7 +12,7 @@ import { */ export type UmbDocumentTypePickerModalData = UmbTreePickerModalData< UmbDocumentTypeTreeItemModel, - typeof umbCreateDocumentTypeWorkspacePathGenerator + typeof UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH.PARAMS >; export interface UmbDocumentTypePickerModalValue extends UmbTreePickerModalValue {} @@ -32,8 +32,8 @@ export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< entityType: 'document-type', preset: {}, }, - additionalPathGenerator: umbCreateDocumentTypeWorkspacePathGenerator, - additionalPathParams: { + extendWithPathPattern: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, + extendWithPathParams: { entityType: 'document-type', parentUnique: null, presetAlias: null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts index 93b117acb3..c351f94b67 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts @@ -1,5 +1,5 @@ import type { UmbDocumentTypeEntityTypeUnion } from './entity.js'; -import { umbUrlPatternToString } from '@umbraco-cms/backoffice/utils'; +import { UmbPathPattern } from '@umbraco-cms/backoffice/router'; export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE = 'template'; export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT = 'element'; @@ -13,13 +13,10 @@ export type UmbCreateDocumentTypeWorkspacePresetType = | UmbCreateDocumentTypeWorkspacePresetTemplateType | UmbCreateDocumentTypeWorkspacePresetElementType; -export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH = 'create/:entityType/:parentUnique/:presetAlias'; -export const umbCreateDocumentTypeWorkspacePathGenerator = (params: { +export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH = new UmbPathPattern<{ entityType: UmbDocumentTypeEntityTypeUnion; parentUnique?: string | null; presetAlias?: UmbCreateDocumentTypeWorkspacePresetType | null; -}) => umbUrlPatternToString(UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, params); +}>('create/:entityType/:parentUnique/:presetAlias'); -export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH = 'edit/:id'; -export const umbEditDocumentTypeWorkspacePathGenerator = (params: { id: string }) => - umbUrlPatternToString(UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, params); +export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH = new UmbPathPattern<{ id: string }>('edit/:id'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index b5194e7080..578df73d21 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -96,7 +96,7 @@ export class UmbDocumentTypeWorkspaceContext this.routes.setRoutes([ { - path: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, + path: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH.toString(), component: UmbDocumentTypeWorkspaceEditorElement, setup: (_component, info) => { const parentEntityType = info.match.params.entityType; @@ -112,7 +112,7 @@ export class UmbDocumentTypeWorkspaceContext }, }, { - path: UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH, + path: UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH.toString(), component: UmbDocumentTypeWorkspaceEditorElement, setup: (_component, info) => { this.removeUmbControllerByAlias('isNewRedirectController'); From 1b0966ea61271332a0859d99d22a6ce7723f46d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Apr 2024 13:18:46 +0200 Subject: [PATCH 20/79] promise reject on create failure --- .../structure/content-type-structure-manager.class.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index a4b7176829..14f7dc9ef1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -120,18 +120,18 @@ export class UmbContentTypeStructureManager< */ public async create(parentUnique: string | null) { const contentType = this.getOwnerContentType(); - if (!contentType || !contentType.unique) return false; + if (!contentType || !contentType.unique) { + throw new Error('Could not find the Content Type to create'); + } const { data } = await this.#repository.create(contentType, parentUnique); - if (!data) return false; + if (!data) return Promise.reject(); // Update state with latest version: this.#contentTypes.updateOne(contentType.unique, data); // Start observe the new content type in the store, as we did not do that when it was a scaffold/local-version. this._observeContentType(data); - - return true; } private async _loadContentTypeCompositions(contentType: T) { From f07d8f85f989a3a130bfac39d08412da285d338b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Apr 2024 13:44:22 +0200 Subject: [PATCH 21/79] move input-tree to tree picker property editor --- src/Umbraco.Web.UI.Client/src/packages/core/tree/index.ts | 1 - .../tree => property-editors/tree-picker}/components/index.ts | 0 .../tree-picker}/components/input-tree/index.ts | 0 .../tree-picker}/components/input-tree/input-tree.element.ts | 0 .../tree-picker}/components/input-tree/input-tree.stories.ts | 0 .../tree-picker}/components/input-tree/input-tree.test.ts | 0 6 files changed, 1 deletion(-) rename src/Umbraco.Web.UI.Client/src/packages/{core/tree => property-editors/tree-picker}/components/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/{core/tree => property-editors/tree-picker}/components/input-tree/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/{core/tree => property-editors/tree-picker}/components/input-tree/input-tree.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/{core/tree => property-editors/tree-picker}/components/input-tree/input-tree.stories.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/{core/tree => property-editors/tree-picker}/components/input-tree/input-tree.test.ts (100%) 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 f12bb43497..a6376a6b04 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 @@ -1,6 +1,5 @@ import { UmbRequestReloadTreeItemChildrenEvent } from './reload-tree-item-children/index.js'; -export * from './components/index.js'; export * from './tree-item/index.js'; export * from './default/index.js'; export * from './data/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/tree/components/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.test.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.test.ts From 966245abbcf571a4d5bf1667305c4be6f525c07a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Apr 2024 13:44:32 +0200 Subject: [PATCH 22/79] relative import --- .../tree-picker/property-editor-ui-tree-picker.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts index 47261ec112..6e0b1b4a25 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts @@ -1,9 +1,9 @@ +import type { UmbInputTreeElement } from './components/input-tree/index.js'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbDynamicRootRepository } from '@umbraco-cms/backoffice/dynamic-root'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; import { UMB_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import type { UmbInputTreeElement } from '@umbraco-cms/backoffice/tree'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbTreePickerSource } from '@umbraco-cms/backoffice/components'; From 85021020ca628c0a1baf768aa0c954246bd3f99c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Apr 2024 13:44:45 +0200 Subject: [PATCH 23/79] global registration --- .../src/packages/property-editors/entry-point.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts index a6a004ace8..dc6d64c9b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts @@ -1 +1,2 @@ import './checkbox-list/components/index.js'; +import './tree-picker/components/index.js'; From 7c3ad9da5b34e578bdec4c2828302a458a47e6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Apr 2024 13:46:33 +0200 Subject: [PATCH 24/79] settings import map --- src/Umbraco.Web.UI.Client/package.json | 1 + src/Umbraco.Web.UI.Client/tsconfig.json | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index a8d5468163..c7543081eb 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -70,6 +70,7 @@ "./resources": "./dist-cms/packages/core/resources/index.js", "./router": "./dist-cms/packages/core/router/index.js", "./section": "./dist-cms/packages/core/section/index.js", + "./settings": "./dist-cms/packages/settings/index.js", "./server-file-system": "./dist-cms/packages/core/server-file-system/index.js", "./sorter": "./dist-cms/packages/core/sorter/index.js", "./static-file": "./dist-cms/packages/static-file/index.js", diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index af06940c67..579e94ca5a 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -88,6 +88,7 @@ "@umbraco-cms/backoffice/resources": ["./src/packages/core/resources/index.ts"], "@umbraco-cms/backoffice/router": ["./src/packages/core/router/index.ts"], "@umbraco-cms/backoffice/section": ["./src/packages/core/section/index.ts"], + "@umbraco-cms/backoffice/settings": ["./src/packages/settings/index.ts"], "@umbraco-cms/backoffice/server-file-system": ["./src/packages/core/server-file-system/index.ts"], "@umbraco-cms/backoffice/sorter": ["./src/packages/core/sorter/index.ts"], "@umbraco-cms/backoffice/static-file": ["./src/packages/static-file/index.ts"], From 3af29a3e697afdb488f46a3b796d5f3554d62408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 25 Apr 2024 13:47:15 +0200 Subject: [PATCH 25/79] const rework --- .../components/backoffice-main.element.ts | 9 +++++---- .../packages/core/router/path-pattern.class.ts | 7 ++++++- .../src/packages/core/section/index.ts | 1 + .../src/packages/core/section/paths.ts | 3 +++ .../tree-picker/tree-picker-modal.element.ts | 18 ++++++++++-------- .../tree-picker/tree-picker-modal.token.ts | 1 + .../modals/document-type-picker-modal.token.ts | 7 ++++--- .../packages/documents/document-types/paths.ts | 7 ++++--- .../document-type-workspace.context.ts | 8 ++++---- .../src/packages/settings/index.ts | 1 + .../src/packages/settings/paths.ts | 6 ++++++ 11 files changed, 45 insertions(+), 23 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/section/paths.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/settings/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/settings/paths.ts diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts index a04f0fad35..edd3ff21f4 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts @@ -1,7 +1,7 @@ import type { UmbBackofficeContext } from '../backoffice.context.js'; import { UMB_BACKOFFICE_CONTEXT } from '../backoffice.context.js'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbSectionContext, UMB_SECTION_CONTEXT } from '@umbraco-cms/backoffice/section'; +import { UmbSectionContext, UMB_SECTION_CONTEXT, UMB_SECTION_PATH_PATTERN } from '@umbraco-cms/backoffice/section'; import type { UmbRoute, UmbRouterSlotChangeEvent } from '@umbraco-cms/backoffice/router'; import type { ManifestSection, UmbSectionElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbExtensionManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; @@ -16,7 +16,6 @@ export class UmbBackofficeMainElement extends UmbLitElement { @state() private _sections: Array> = []; - private _routePrefix = 'section/'; private _backofficeContext?: UmbBackofficeContext; private _sectionContext?: UmbSectionContext; @@ -56,7 +55,7 @@ export class UmbBackofficeMainElement extends UmbLitElement { } else { return { alias: section.alias, - path: this._routePrefix + (section.manifest as ManifestSection).meta.pathname, + path: UMB_SECTION_PATH_PATTERN.generateLocal({ name: section.manifest!.meta.pathname }), component: () => createExtensionElement(section.manifest!, 'umb-section-default'), setup: (component) => { (component as UmbSectionElement).manifest = section.manifest as ManifestSection; @@ -78,7 +77,9 @@ export class UmbBackofficeMainElement extends UmbLitElement { private _onRouteChange = async (event: UmbRouterSlotChangeEvent) => { const currentPath = event.target.localActiveViewPath || ''; - const section = this._sections.find((s) => this._routePrefix + s.manifest?.meta.pathname === currentPath); + const section = this._sections.find( + (s) => UMB_SECTION_PATH_PATTERN.generateLocal({ name: s.manifest!.meta.pathname }) === currentPath, + ); if (!section) return; await section.asPromise(); if (section.manifest) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts index 31ed8b8b57..3463046395 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/path-pattern.class.ts @@ -25,7 +25,12 @@ export class UmbPathPattern('section/:name'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts index dc441fe8df..0ba176209b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.element.ts @@ -24,6 +24,9 @@ export class UmbTreePickerModalElement { - return { data: createActionData.modalData }; + return { data: createAction.modalData }; }) .onSubmit((value) => { if (value) { this.value = { selection: [value.unique] }; this._submitModal(); } else { - throw new Error('No value returned from workspace modal'); this._rejectModal(); } }) .observeRouteBuilder((routeBuilder) => { const oldPath = this._createPath; this._createPath = - routeBuilder({}) + - createActionData.extendWithPathPattern.generateLocal(createActionData.extendWithPathParams); + routeBuilder({}) + createAction.extendWithPathPattern.generateLocal(createAction.extendWithPathParams); this.requestUpdate('_createPath', oldPath); }); } @@ -110,7 +112,7 @@ export class UmbTreePickerModalElement ${this._createPath ? html` ` : nothing} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts index 03f5152144..0f00085f53 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-picker/tree-picker-modal.token.ts @@ -4,6 +4,7 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbPathPattern, UmbPathPatternParamsType } from '@umbraco-cms/backoffice/router'; export interface UmbTreePickerModalCreateActionData { + label: string; modalData: UmbWorkspaceModalData; modalToken?: UmbModalToken; extendWithPathPattern: UmbPathPattern; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts index 2221229a12..b0ca9278c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/modals/document-type-picker-modal.token.ts @@ -1,4 +1,4 @@ -import { UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH } from '../paths.js'; +import { UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN } from '../paths.js'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentTypeTreeItemModel } from '@umbraco-cms/backoffice/document-type'; import { @@ -12,7 +12,7 @@ import { */ export type UmbDocumentTypePickerModalData = UmbTreePickerModalData< UmbDocumentTypeTreeItemModel, - typeof UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH.PARAMS + typeof UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN.PARAMS >; export interface UmbDocumentTypePickerModalValue extends UmbTreePickerModalValue {} @@ -28,11 +28,12 @@ export const UMB_DOCUMENT_TYPE_PICKER_MODAL = new UmbModalToken< data: { treeAlias: 'Umb.Tree.DocumentType', createAction: { + label: '#content_createEmpty', modalData: { entityType: 'document-type', preset: {}, }, - extendWithPathPattern: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, + extendWithPathPattern: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN, extendWithPathParams: { entityType: 'document-type', parentUnique: null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts index c351f94b67..f96d75b927 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/paths.ts @@ -1,3 +1,4 @@ +import { UMB_SETTINGS_SECTION_PATH } from '@umbraco-cms/backoffice/settings'; import type { UmbDocumentTypeEntityTypeUnion } from './entity.js'; import { UmbPathPattern } from '@umbraco-cms/backoffice/router'; @@ -13,10 +14,10 @@ export type UmbCreateDocumentTypeWorkspacePresetType = | UmbCreateDocumentTypeWorkspacePresetTemplateType | UmbCreateDocumentTypeWorkspacePresetElementType; -export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH = new UmbPathPattern<{ +export const UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{ entityType: UmbDocumentTypeEntityTypeUnion; parentUnique?: string | null; presetAlias?: UmbCreateDocumentTypeWorkspacePresetType | null; -}>('create/:entityType/:parentUnique/:presetAlias'); +}>('create/:entityType/:parentUnique/:presetAlias', UMB_SETTINGS_SECTION_PATH); -export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH = new UmbPathPattern<{ id: string }>('edit/:id'); +export const UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{ id: string }>('edit/:id'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 578df73d21..d927e650a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -2,10 +2,10 @@ import { UmbDocumentTypeDetailRepository } from '../repository/detail/document-t import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '../entity.js'; import type { UmbDocumentTypeDetailModel } from '../types.js'; import { - UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH, + UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN, UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_ELEMENT, UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PRESET_TEMPLATE, - UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH, + UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN, type UmbCreateDocumentTypeWorkspacePresetType, } from '../paths.js'; import { UmbDocumentTypeWorkspaceEditorElement } from './document-type-workspace-editor.element.js'; @@ -96,7 +96,7 @@ export class UmbDocumentTypeWorkspaceContext this.routes.setRoutes([ { - path: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH.toString(), + path: UMB_CREATE_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN.toString(), component: UmbDocumentTypeWorkspaceEditorElement, setup: (_component, info) => { const parentEntityType = info.match.params.entityType; @@ -112,7 +112,7 @@ export class UmbDocumentTypeWorkspaceContext }, }, { - path: UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH.toString(), + path: UMB_EDIT_DOCUMENT_TYPE_WORKSPACE_PATH_PATTERN.toString(), component: UmbDocumentTypeWorkspaceEditorElement, setup: (_component, info) => { this.removeUmbControllerByAlias('isNewRedirectController'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/index.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/index.ts new file mode 100644 index 0000000000..b3031d9a5d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/index.ts @@ -0,0 +1 @@ +export * from './paths.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/paths.ts new file mode 100644 index 0000000000..775dfe38cd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/paths.ts @@ -0,0 +1,6 @@ +import { UMB_SECTION_PATH_PATTERN } from '@umbraco-cms/backoffice/section'; + +export const UMB_SETTINGS_SECTION_PATHNAME = 'settings'; +export const UMB_SETTINGS_SECTION_PATH = UMB_SECTION_PATH_PATTERN.generateAbsolute({ + name: UMB_SETTINGS_SECTION_PATHNAME, +}); From bdc80990fb0ba9b8c5eebcbfd9e40d968f365a06 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Apr 2024 14:23:23 +0200 Subject: [PATCH 26/79] move source picker from core components --- .../src/packages/core/components/index.ts | 1 - .../src/packages/property-editors/entry-point.ts | 1 - .../source-picker}/input-tree-picker-source/index.ts | 0 .../input-tree-picker-source.element.ts | 0 ...roperty-editor-ui-tree-picker-source-picker.element.ts | 8 +++++++- .../tree-picker/property-editor-ui-tree-picker.element.ts | 3 +++ 6 files changed, 10 insertions(+), 3 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/{core/components => property-editors/tree-picker/config/source-picker}/input-tree-picker-source/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/{core/components => property-editors/tree-picker/config/source-picker}/input-tree-picker-source/input-tree-picker-source.element.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts index b0bee29cb5..0846cc4cf8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/index.ts @@ -25,7 +25,6 @@ export * from './input-multi-url/index.js'; export * from './input-number-range/index.js'; export * from './input-radio-button-list/index.js'; export * from './input-slider/index.js'; -export * from './input-tree-picker-source/index.js'; export * from './input-toggle/index.js'; export * from './input-upload-field/index.js'; export * from './multiple-color-picker-input/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts index dc6d64c9b3..a6a004ace8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/entry-point.ts @@ -1,2 +1 @@ import './checkbox-list/components/index.js'; -import './tree-picker/components/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/input-tree-picker-source.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/input-tree-picker-source.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts index d8b1002fda..9a4c91db81 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts @@ -1,4 +1,7 @@ -import type { UmbInputTreePickerSourceElement, UmbTreePickerSource } from '@umbraco-cms/backoffice/components'; +import type { + UmbInputTreePickerSourceElement, + UmbTreePickerSource, +} from './input-tree-picker-source/input-tree-picker-source.element.js'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { @@ -7,6 +10,9 @@ import { } from '@umbraco-cms/backoffice/property-editor'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +// import of local component +import './input-tree-picker-source/index.js'; + /** * @element umb-property-editor-ui-tree-picker-source-picker */ diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts index 6e0b1b4a25..6cc9d17564 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts @@ -8,6 +8,9 @@ import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/ import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbTreePickerSource } from '@umbraco-cms/backoffice/components'; +// import of local component +import './components/input-tree/index.js'; + /** * @element umb-property-editor-ui-tree-picker */ From 81f0bf6c2fcf7f1b8ad1ef526757a33ea24076ae Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Apr 2024 14:24:43 +0200 Subject: [PATCH 27/79] rename to content picker --- .../Umbraco.MultiNodeTreePicker.ts | 0 .../{tree-picker => content-picker}/components/index.ts | 0 .../components/input-tree/index.ts | 0 .../components/input-tree/input-tree.element.ts | 0 .../components/input-tree/input-tree.stories.ts | 0 .../components/input-tree/input-tree.test.ts | 0 .../config/source-picker/input-tree-picker-source/index.ts | 0 .../input-tree-picker-source.element.ts | 0 .../config/source-picker/manifests.ts | 0 .../property-editor-ui-tree-picker-source-picker.element.ts | 0 .../property-editor-ui-tree-picker-source-picker.stories.ts | 0 .../property-editor-ui-tree-picker-source-picker.test.ts | 0 .../config/source-type-picker/manifests.ts | 0 ...operty-editor-ui-tree-picker-source-type-picker.element.ts | 0 .../{tree-picker => content-picker}/manifests.ts | 0 .../property-editor-ui-tree-picker.element.ts | 0 .../property-editor-ui-tree-picker.stories.ts | 0 .../property-editor-ui-tree-picker.test.ts | 0 .../src/packages/property-editors/manifests.ts | 4 ++-- 19 files changed, 2 insertions(+), 2 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/Umbraco.MultiNodeTreePicker.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/components/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/components/input-tree/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/components/input-tree/input-tree.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/components/input-tree/input-tree.stories.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/components/input-tree/input-tree.test.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-picker/input-tree-picker-source/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-picker/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-picker/property-editor-ui-tree-picker-source-picker.stories.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-picker/property-editor-ui-tree-picker-source-picker.test.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-type-picker/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/config/source-type-picker/property-editor-ui-tree-picker-source-type-picker.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/property-editor-ui-tree-picker.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/property-editor-ui-tree-picker.stories.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/{tree-picker => content-picker}/property-editor-ui-tree-picker.test.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/Umbraco.MultiNodeTreePicker.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/Umbraco.MultiNodeTreePicker.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/Umbraco.MultiNodeTreePicker.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/Umbraco.MultiNodeTreePicker.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/input-tree.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/input-tree.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/input-tree.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/input-tree.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.test.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/input-tree.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/components/input-tree/input-tree.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-tree/input-tree.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.test.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/property-editor-ui-tree-picker-source-picker.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-type-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-type-picker/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-type-picker/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-type-picker/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-type-picker/property-editor-ui-tree-picker-source-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-type-picker/property-editor-ui-tree-picker-source-type-picker.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/config/source-type-picker/property-editor-ui-tree-picker-source-type-picker.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-type-picker/property-editor-ui-tree-picker-source-type-picker.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-tree-picker.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-tree-picker.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-tree-picker.stories.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-tree-picker.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.test.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-tree-picker.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/tree-picker/property-editor-ui-tree-picker.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-tree-picker.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/manifests.ts index 7737fe3c94..b2697be517 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/manifests.ts @@ -20,7 +20,7 @@ import { manifests as sliderManifests } from './slider/manifests.js'; import { manifests as textareaManifests } from './textarea/manifests.js'; import { manifests as textBoxManifests } from './text-box/manifests.js'; import { manifests as toggleManifests } from './toggle/manifests.js'; -import { manifests as treePickerManifests } from './tree-picker/manifests.js'; +import { manifests as contentPickerManifests } from './content-picker/manifests.js'; import { manifests as uploadFieldManifests } from './upload-field/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -41,7 +41,7 @@ export const manifests: Array = [ ...textareaManifests, ...textBoxManifests, ...toggleManifests, - ...treePickerManifests, + ...contentPickerManifests, ...uploadFieldManifests, colorEditor, numberRange, From 33d57ad3651da25efc0808baefe6e4e44f881230 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 25 Apr 2024 14:28:23 +0200 Subject: [PATCH 28/79] rename interfaces --- .../input-tree-picker-source.element.ts | 24 +++++++++---------- ...or-ui-tree-picker-source-picker.element.ts | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts index be4d8e0aeb..64b642eb8c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-picker/input-tree-picker-source/input-tree-picker-source.element.ts @@ -5,21 +5,21 @@ import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -export type UmbTreePickerSource = { - type: UmbTreePickerSourceType; +export type UmbContentPickerSource = { + type: UmbContentPickerSourceType; id?: string; - dynamicRoot?: UmbTreePickerDynamicRoot; + dynamicRoot?: UmbContentPickerDynamicRoot; }; -export type UmbTreePickerSourceType = 'content' | 'member' | 'media'; +export type UmbContentPickerSourceType = 'content' | 'member' | 'media'; -export type UmbTreePickerDynamicRoot = { +export type UmbContentPickerDynamicRoot = { originAlias: string; originKey?: string; - querySteps?: Array; + querySteps?: Array; }; -export type UmbTreePickerDynamicRootQueryStep = { +export type UmbContentPickerDynamicRootQueryStep = { unique: string; alias: string; anyOfDocTypeKeys?: Array; @@ -31,10 +31,10 @@ export class UmbInputTreePickerSourceElement extends UUIFormControlMixin(UmbLitE return undefined; } - #type: UmbTreePickerSourceType = 'content'; + #type: UmbContentPickerSourceType = 'content'; @property() - public set type(value: UmbTreePickerSourceType) { + public set type(value: UmbContentPickerSourceType) { if (value === undefined) { value = this.#type; } @@ -49,7 +49,7 @@ export class UmbInputTreePickerSourceElement extends UUIFormControlMixin(UmbLitE this.requestUpdate('type', oldValue); } - public get type(): UmbTreePickerSourceType { + public get type(): UmbContentPickerSourceType { return this.#type; } @@ -57,7 +57,7 @@ export class UmbInputTreePickerSourceElement extends UUIFormControlMixin(UmbLitE nodeId?: string; @property({ attribute: false }) - dynamicRoot?: UmbTreePickerDynamicRoot | undefined; + dynamicRoot?: UmbContentPickerDynamicRoot | undefined; @state() _options: Array