From 481759f9e9fd6ea03459d9de8a925ec2d62b9431 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 28 Feb 2024 11:05:16 +0000 Subject: [PATCH 1/6] Adds `umb-input-collection-configuration` component @nielslyngsoe may have comments on how I've reused `UMB_DATA_TYPE_PICKER_FLOW_DATA_TYPE_PICKER_MODAL`. --- src/packages/core/components/index.ts | 1 + .../input-collection-configuration/index.ts | 1 + .../input-collection-configuration.element.ts | 143 ++++++++++++++++++ src/packages/data-type/repository/index.ts | 2 + 4 files changed, 147 insertions(+) create mode 100644 src/packages/core/components/input-collection-configuration/index.ts create mode 100644 src/packages/core/components/input-collection-configuration/input-collection-configuration.element.ts diff --git a/src/packages/core/components/index.ts b/src/packages/core/components/index.ts index ea96ecaaaa..c3dee2775c 100644 --- a/src/packages/core/components/index.ts +++ b/src/packages/core/components/index.ts @@ -11,6 +11,7 @@ export * from './field-dropdown-list/index.js'; export * from './footer-layout/index.js'; export * from './header-app/index.js'; export * from './history/index.js'; +export * from './input-collection-configuration/index.js'; export * from './input-color/index.js'; export * from './input-date/index.js'; export * from './input-dropdown/index.js'; diff --git a/src/packages/core/components/input-collection-configuration/index.ts b/src/packages/core/components/input-collection-configuration/index.ts new file mode 100644 index 0000000000..08e8bcfe8f --- /dev/null +++ b/src/packages/core/components/input-collection-configuration/index.ts @@ -0,0 +1 @@ +export * from './input-collection-configuration.element.js'; diff --git a/src/packages/core/components/input-collection-configuration/input-collection-configuration.element.ts b/src/packages/core/components/input-collection-configuration/input-collection-configuration.element.ts new file mode 100644 index 0000000000..3f73467245 --- /dev/null +++ b/src/packages/core/components/input-collection-configuration/input-collection-configuration.element.ts @@ -0,0 +1,143 @@ +import { html, customElement, property, css, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; +import { UMB_DATATYPE_WORKSPACE_MODAL, UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS } from '@umbraco-cms/backoffice/data-type'; +import { + UmbModalRouteRegistrationController, + UMB_DATA_TYPE_PICKER_FLOW_DATA_TYPE_PICKER_MODAL, +} from '@umbraco-cms/backoffice/modal'; +import type { UmbDataTypeItemModel } from '@umbraco-cms/backoffice/data-type'; + +@customElement('umb-input-collection-configuration') +export class UmbInputCollectionConfigurationElement extends FormControlMixin(UmbLitElement) { + protected getFormElement() { + return undefined; + } + + #itemManager = new UmbRepositoryItemsManager( + this, + UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS, + (x) => x.unique, + ); + + #createDataTypeModal: UmbModalRouteRegistrationController; + + #propertyEditorUiAlias = 'Umb.PropertyEditorUi.CollectionView'; + + @state() + private _dataTypePickerModalPath?: string; + + @state() + private _item?: UmbDataTypeItemModel; + + @property({ attribute: 'default-value' }) + defaultValue?: string; + + #setValue(value: string) { + this.value = value; + this.#itemManager.setUniques(value ? [value] : []); + this.dispatchEvent(new UmbChangeEvent()); + } + + constructor() { + super(); + + this.observe(this.#itemManager.items, (items) => { + this._item = items[0]; + }); + + new UmbModalRouteRegistrationController(this, UMB_DATA_TYPE_PICKER_FLOW_DATA_TYPE_PICKER_MODAL) + .addAdditionalPath(':uiAlias') + .onSetup((routingInfo) => { + return { + data: { + propertyEditorUiAlias: routingInfo.uiAlias, + }, + value: undefined, + }; + }) + .onSubmit((submitData) => { + if (submitData?.createNewWithPropertyEditorUiAlias) { + this.#createDataType(); + } else { + this.#setValue(submitData?.dataTypeId ?? this.defaultValue ?? ''); + } + }) + .observeRouteBuilder((routeBuilder) => { + this._dataTypePickerModalPath = routeBuilder({ uiAlias: this.#propertyEditorUiAlias }); + }); + + this.#createDataTypeModal = new UmbModalRouteRegistrationController(this, UMB_DATATYPE_WORKSPACE_MODAL) + .addAdditionalPath(':uiAlias') + .onSetup((params) => { + return { data: { entityType: 'data-type', preset: { editorUiAlias: params.uiAlias } } }; + }) + .onSubmit((value) => { + this.#setValue(value?.unique ?? this.defaultValue ?? ''); + }); + } + + connectedCallback() { + super.connectedCallback(); + + if (this.value) { + this.#itemManager.setUniques([this.value as string]); + } + } + + #clearDataType() { + this.#setValue(''); + } + + #createDataType() { + this.#createDataTypeModal.open({ uiAlias: this.#propertyEditorUiAlias }, 'create/null'); + } + + render() { + return !this.value ? this.#renderCreate() : this.#renderConfigured(); + } + + #renderCreate() { + if (!this._dataTypePickerModalPath) return nothing; + return html``; + } + + #renderConfigured() { + if (!this._item || !this._dataTypePickerModalPath) return nothing; + return html` + + + + + + + + + `; + } + + static styles = [ + css` + #create-button { + width: 100%; + } + `, + ]; +} + +export default UmbInputCollectionConfigurationElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-collection-configuration': UmbInputCollectionConfigurationElement; + } +} diff --git a/src/packages/data-type/repository/index.ts b/src/packages/data-type/repository/index.ts index 5acdb79db9..bb1cf117cd 100644 --- a/src/packages/data-type/repository/index.ts +++ b/src/packages/data-type/repository/index.ts @@ -2,3 +2,5 @@ export { UmbCopyDataTypeRepository, COPY_DATA_TYPE_REPOSITORY_ALIAS } from './co export { UmbDataTypeDetailRepository, UMB_DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from './detail/index.js'; export { UmbDataTypeItemRepository, UMB_DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './item/index.js'; export { UmbMoveDataTypeRepository, MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './move/index.js'; + +export type { UmbDataTypeItemModel } from './item/index.js'; From ec75a9b9c364555386ea776ddc5ed184d876699e Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 28 Feb 2024 11:20:14 +0000 Subject: [PATCH 2/6] Adds `setCollection` to document-type workspace context --- src/packages/core/content-type/types.ts | 3 ++- .../workspace/document-type-workspace.context.ts | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/packages/core/content-type/types.ts b/src/packages/core/content-type/types.ts index dd28d8a300..32e61c658f 100644 --- a/src/packages/core/content-type/types.ts +++ b/src/packages/core/content-type/types.ts @@ -1,4 +1,5 @@ import type { CompositionTypeModel, PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; export type UmbPropertyContainerTypes = 'Group' | 'Tab'; export interface UmbPropertyTypeContainerModel { @@ -24,7 +25,7 @@ export interface UmbContentTypeModel { containers: Array; allowedContentTypes: Array; compositions: Array; - collection: { unique: string } | null; + collection: UmbReferenceByUnique | null; } export interface UmbPropertyTypeScaffoldModel extends Omit { diff --git a/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 9e623a9d41..5839892c6e 100644 --- a/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -1,11 +1,12 @@ import { UmbDocumentTypeDetailRepository } from '../repository/detail/document-type-detail.repository.js'; import type { UmbDocumentTypeDetailModel } from '../types.js'; -import type { UmbContentTypeCompositionModel, UmbContentTypeSortModel } from '@umbraco-cms/backoffice/content-type'; import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type'; -import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace'; import { UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace'; -import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbBooleanState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbContentTypeCompositionModel, UmbContentTypeSortModel } from '@umbraco-cms/backoffice/content-type'; +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace'; type EntityType = UmbDocumentTypeDetailModel; export class UmbDocumentTypeWorkspaceContext @@ -31,6 +32,7 @@ export class UmbDocumentTypeWorkspaceContext readonly isElement; readonly allowedContentTypes; readonly compositions; + readonly collection; // Document type specific: readonly allowedTemplateIds; @@ -57,6 +59,7 @@ export class UmbDocumentTypeWorkspaceContext this.isElement = this.structure.ownerContentTypeObservablePart((data) => data?.isElement); this.allowedContentTypes = this.structure.ownerContentTypeObservablePart((data) => data?.allowedContentTypes); this.compositions = this.structure.ownerContentTypeObservablePart((data) => data?.compositions); + this.collection = this.structure.ownerContentTypeObservablePart((data) => data?.collection); // Document type specific: this.allowedTemplateIds = this.structure.ownerContentTypeObservablePart((data) => data?.allowedTemplates); @@ -123,6 +126,9 @@ export class UmbDocumentTypeWorkspaceContext setCompositions(compositions: Array) { this.structure.updateOwnerContentType({ compositions }); } + setCollection(collection: UmbReferenceByUnique) { + this.structure.updateOwnerContentType({ collection }); + } // Document type specific: setAllowedTemplateIds(allowedTemplates: Array<{ id: string }>) { From 67bda81603739b77bd26c8aefd91ba6b7da01dac Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 28 Feb 2024 11:20:56 +0000 Subject: [PATCH 3/6] Adds `collection` to the `create` and `update` payloads --- .../detail/document-type-detail.server.data-source.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts b/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts index 5ad807ec15..54cb0f00c3 100644 --- a/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts +++ b/src/packages/documents/document-types/repository/detail/document-type-detail.server.data-source.ts @@ -186,6 +186,7 @@ export class UmbDocumentTypeDetailServerDataSource implements UmbDetailDataSourc allowedTemplates: model.allowedTemplates, defaultTemplate: model.defaultTemplate ? { id: model.defaultTemplate.id } : null, cleanup: model.cleanup, + collection: model.collection?.unique ? { id: model.collection?.unique } : null, }; const { data, error } = await tryExecuteAndNotify( @@ -252,6 +253,7 @@ export class UmbDocumentTypeDetailServerDataSource implements UmbDetailDataSourc allowedTemplates: model.allowedTemplates, defaultTemplate: model.defaultTemplate ? { id: model.defaultTemplate.id } : null, cleanup: model.cleanup, + collection: model.collection?.unique ? { id: model.collection?.unique } : null, }; const { error } = await tryExecuteAndNotify( From 0027ab9caa74fa3543945d7343c4f10ca33585b4 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 28 Feb 2024 11:21:38 +0000 Subject: [PATCH 4/6] Wires up the `umb-input-collection-configuration` in the Document Type Editor UI. --- ...t-type-workspace-view-structure.element.ts | 59 +++++++++++++++---- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts b/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts index 6cbd3433e5..e70292c346 100644 --- a/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts +++ b/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts @@ -2,11 +2,12 @@ import type { UmbDocumentTypeWorkspaceContext } from '../../document-type-worksp import type { UmbInputDocumentTypeElement } from '../../../components/input-document-type/input-document-type.element.js'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UUIToggleElement } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContentTypeSortModel } from '@umbraco-cms/backoffice/content-type'; +import type { UmbInputCollectionConfigurationElement } from '@umbraco-cms/backoffice/components'; +import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UUIToggleElement } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-document-type-workspace-view-structure') export class UmbDocumentTypeWorkspaceViewStructureElement extends UmbLitElement implements UmbWorkspaceViewElement { @@ -18,6 +19,9 @@ export class UmbDocumentTypeWorkspaceViewStructureElement extends UmbLitElement @state() private _allowedContentTypeUniques?: Array; + @state() + private _collection?: string | null; + constructor() { super(); @@ -30,14 +34,32 @@ export class UmbDocumentTypeWorkspaceViewStructureElement extends UmbLitElement private _observeDocumentType() { if (!this.#workspaceContext) return; - this.observe(this.#workspaceContext.allowedAsRoot, (allowedAsRoot) => (this._allowedAtRoot = allowedAsRoot)); - this.observe(this.#workspaceContext.allowedContentTypes, (allowedContentTypes) => { - const oldValue = this._allowedContentTypeUniques; - this._allowedContentTypeUniques = allowedContentTypes - ?.map((x) => x.contentType.unique) - .filter((x) => x !== undefined) as Array; - this.requestUpdate('_allowedContentTypeUniques', oldValue); - }); + + this.observe( + this.#workspaceContext.allowedAsRoot, + (allowedAsRoot) => (this._allowedAtRoot = allowedAsRoot), + '_allowedAsRootObserver', + ); + + this.observe( + this.#workspaceContext.allowedContentTypes, + (allowedContentTypes) => { + const oldValue = this._allowedContentTypeUniques; + this._allowedContentTypeUniques = allowedContentTypes + ?.map((x) => x.contentType.unique) + .filter((x) => x !== undefined) as Array; + this.requestUpdate('_allowedContentTypeUniques', oldValue); + }, + '_allowedContentTypesObserver', + ); + + this.observe( + this.#workspaceContext.collection, + (collection) => { + this._collection = collection?.unique; + }, + '_collectionObserver', + ); } render() { @@ -77,9 +99,20 @@ export class UmbDocumentTypeWorkspaceViewStructureElement extends UmbLitElement - -
Provides an overview of child content and hides it in the tree.
-
+ +
+ Configures the content item to show list of its children, the children will not be shown in the tree. +
+
+ { + const unique = (e.target as UmbInputCollectionConfigurationElement).value as string; + this.#workspaceContext?.setCollection({ unique }); + }}> + +
`; From 0baf4056e37f3d4d4bf316c680478db2fb7f5371 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 29 Feb 2024 08:30:34 +0000 Subject: [PATCH 5/6] Added localization keys for the Collections option Danish localization courtesy of Google Translate! :scream: --- src/assets/lang/da-dk.ts | 3 +++ src/assets/lang/en-us.ts | 3 +++ .../document-type-workspace-view-structure.element.ts | 6 ++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index 07529c2a54..89b4e7986b 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1655,6 +1655,9 @@ export default { 'NOTE! The cleanup of historically content versions are disabled globally. These settings will not take effect before it is enabled.', changeDataTypeHelpText: 'Changing a data type with stored values is disabled. To allow this you can change the Umbraco:CMS:DataTypes:CanBeChanged setting in appsettings.json.', + collections: 'Samlinger', + collectionsDescription: + 'Konfigurerer indholdselementet til at vise listen over dets børn, børnene vil ikke blive vist i træet.', }, languages: { addLanguage: 'Tilføj sprog', diff --git a/src/assets/lang/en-us.ts b/src/assets/lang/en-us.ts index 9933826ee2..f2332f75d7 100644 --- a/src/assets/lang/en-us.ts +++ b/src/assets/lang/en-us.ts @@ -1652,6 +1652,9 @@ export default { 'NOTE! The cleanup of historically content versions are disabled globally. These settings will not take effect before it is enabled.', changeDataTypeHelpText: 'Changing a data type with stored values is disabled. To allow this you can change the Umbraco:CMS:DataTypes:CanBeChanged setting in appsettings.json.', + collections: 'Collections', + collectionsDescription: + 'Configures the content item to show list of its children, the children will not be shown in the tree.', }, languages: { addLanguage: 'Add language', diff --git a/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts b/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts index e70292c346..9f8b9dc91b 100644 --- a/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts +++ b/src/packages/documents/document-types/workspace/views/structure/document-type-workspace-view-structure.element.ts @@ -99,10 +99,8 @@ export class UmbDocumentTypeWorkspaceViewStructureElement extends UmbLitElement - -
- Configures the content item to show list of its children, the children will not be shown in the tree. -
+ +
${this.localize.term('contentTypeEditor_collectionsDescription')}
Date: Thu, 29 Feb 2024 09:26:40 +0000 Subject: [PATCH 6/6] Updated Danish translation of the Collections description --- src/assets/lang/da-dk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/lang/da-dk.ts b/src/assets/lang/da-dk.ts index 89b4e7986b..68461e1e90 100644 --- a/src/assets/lang/da-dk.ts +++ b/src/assets/lang/da-dk.ts @@ -1657,7 +1657,7 @@ export default { 'Changing a data type with stored values is disabled. To allow this you can change the Umbraco:CMS:DataTypes:CanBeChanged setting in appsettings.json.', collections: 'Samlinger', collectionsDescription: - 'Konfigurerer indholdselementet til at vise listen over dets børn, børnene vil ikke blive vist i træet.', + 'Konfigurerer indholdselementet til at vise listen over dets underordnede elementer, underordnede elementer vil ikke blive vist i træet.', }, languages: { addLanguage: 'Tilføj sprog',