diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts index dcf199554d..96c9375d6b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts @@ -31,6 +31,9 @@ export class UmbDefaultCollectionContext< #filter = new UmbObjectState({}); public readonly filter = this.#filter.asObservable(); + #userDefinedProperties = new UmbArrayState([], (x) => x); + public readonly userDefinedProperties = this.#userDefinedProperties.asObservable(); + repository?: UmbCollectionRepository; #initResolver?: () => void; @@ -131,7 +134,13 @@ export class UmbDefaultCollectionContext< #configure() { this.selection.setMultiple(true); this.pagination.setPageSize(this.#config.pageSize!); - this.#filter.setValue({ ...this.#filter.getValue(), skip: 0, take: this.#config.pageSize }); + this.#filter.setValue({ + ...this.#config, + ...this.#filter.getValue(), + skip: 0, + take: this.#config.pageSize, + }); + this.#userDefinedProperties.setValue(this.#config.userDefinedProperties ?? []); } #onPageChange = (event: UmbChangeEvent) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts index 1a39fdb5a9..6304e5fbf5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/types.ts @@ -11,12 +11,14 @@ export interface UmbCollectionBulkActionPermissions { } export interface UmbCollectionConfiguration { + unique?: string; + dataTypeId?: string; allowedEntityBulkActions?: UmbCollectionBulkActionPermissions; - includeProperties?: Array; orderBy?: string; orderDirection?: string; pageSize?: number; useInfiniteEditor?: boolean; + userDefinedProperties?: Array; } export interface UmbCollectionContext { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/property-editor-ui-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/property-editor-ui-collection-view.element.ts index aae8535519..ec7f581a90 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/property-editor-ui-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/property-editor-ui-collection-view.element.ts @@ -3,9 +3,12 @@ import type { UmbCollectionConfiguration, } from '../../../../core/collection/types.js'; import type { UmbPropertyEditorConfigCollection } from '../../config/index.js'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/document'; /** * @element umb-property-editor-ui-collection-view @@ -23,6 +26,32 @@ export class UmbPropertyEditorUICollectionViewElement extends UmbLitElement impl this._config = this.#mapDataTypeConfigToCollectionConfig(config); } + constructor() { + super(); + + // Gets the Data Type ID for the current property. + this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { + // TODO: [LK:2024-02-01] Replace `UMB_DOCUMENT_WORKSPACE_CONTEXT` + // with an abstracted context that supports both document and media workspaces. + this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => { + this.observe(workspaceContext.unique, (unique) => { + if (this._config) { + this._config.unique = unique; + } + }); + this.observe(propertyContext.alias, async (propertyAlias) => { + if (propertyAlias) { + const property = await workspaceContext.structure.getPropertyStructureByAlias(propertyAlias); + if (property && this._config) { + this._config.dataTypeId = property.dataType.unique; + this.requestUpdate('_config'); + } + } + }); + }); + }); + } + #mapDataTypeConfigToCollectionConfig( config: UmbPropertyEditorConfigCollection | undefined, ): UmbCollectionConfiguration { @@ -32,10 +61,12 @@ export class UmbPropertyEditorUICollectionViewElement extends UmbLitElement impl orderDirection: config?.getValueByAlias('orderDirection') ?? 'asc', pageSize: Number(config?.getValueByAlias('pageSize')) ?? 50, useInfiniteEditor: config?.getValueByAlias('useInfiniteEditor') ?? false, + userDefinedProperties: config?.getValueByAlias('includeProperties'), }; } render() { + if (!this._config?.unique || !this._config?.dataTypeId) return html``; return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts index 8824d99342..8be688f611 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts @@ -21,6 +21,9 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { @state() private _busy = false; + @state() + private _userDefinedProperties?: Array; + @state() private _items?: Array; @@ -67,6 +70,11 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { private _observeCollectionContext() { if (!this._collectionContext) return; + this.observe(this._collectionContext.userDefinedProperties, (userDefinedProperties) => { + this._userDefinedProperties = userDefinedProperties; + this.#createTableHeadings(); + }); + this.observe(this._collectionContext.items, (items) => { this._items = items; this.#createTableItems(this._items); @@ -77,24 +85,55 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { }); } + #createTableHeadings() { + if (this._userDefinedProperties && this._userDefinedProperties.length > 0) { + const userColumns: Array = this._userDefinedProperties.map((item) => { + return { + name: item.header, + alias: item.alias, + elementName: item.elementName, + allowSorting: true, + }; + }); + + this._tableColumns = [...this.#systemColumns, ...userColumns]; + } + } + #createTableItems(items: Array) { + // TODO: [LK] This is a temporary solution. Let's explore a nicer way to display the values. + const getValue = (item: UmbDocumentCollectionItemModel, alias: string) => { + switch (alias) { + case 'createDate': + return item.createDate.toLocaleString(); + case 'owner': + return item.creator; + case 'published': + return item.state !== 'Draft' ? 'True' : 'False'; + case 'updateDate': + return item.updateDate.toLocaleString(); + case 'updater': + return item.updater; + default: + return item.values.find((value) => value.alias === alias)?.value ?? ''; + } + }; + this._tableItems = items.map((item) => { if (!item.unique) throw new Error('Item id is missing.'); + + const data = + this._tableColumns?.map((column) => { + return { + columnAlias: column.alias, + value: column.elementName ? item : getValue(item, column.alias), + }; + }) ?? []; + return { id: item.unique, - data: [ - { - columnAlias: 'entityName', - value: item.name || 'Unnamed Document', - }, - // { - // columnAlias: 'entityActions', - // value: { - // entityType: item.entityType, - // }, - // }, - ], icon: item.icon, + data: data, }; }); } @@ -117,7 +156,10 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { const table = event.target as UmbTableElement; const orderingColumn = table.orderingColumn; const orderingDesc = table.orderingDesc; - console.log(`fetch media items, order column: ${orderingColumn}, desc: ${orderingDesc}`); + this._collectionContext?.setFilter({ + orderBy: orderingColumn, + orderDirection: orderingDesc ? 'desc' : 'asc', + }); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/collection/document-workspace-view-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/collection/document-workspace-view-collection.element.ts index 6d34977565..ec9573543a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/collection/document-workspace-view-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/collection/document-workspace-view-collection.element.ts @@ -7,6 +7,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/document'; +import type { UmbDataTypeDetailModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; @customElement('umb-document-workspace-view-collection') @@ -14,6 +15,9 @@ export class UmbDocumentWorkspaceViewCollectionElement extends UmbLitElement imp @state() private _config?: UmbCollectionConfiguration; + @state() + private _documentUnique?: string; + #dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); constructor() { @@ -23,13 +27,16 @@ export class UmbDocumentWorkspaceViewCollectionElement extends UmbLitElement imp async #observeConfig() { this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => { + this.observe(workspaceContext.unique, (unique) => { + this._documentUnique = unique; + }); this.observe( workspaceContext.structure.ownerContentType(), async (documentType) => { if (!documentType) return; // TODO: [LK] Temp hard-coded. Once the API is ready, wire up the data-type ID from the content-type. - const dataTypeUnique = 'dt-collectionView'; + const dataTypeUnique = 'c0808dd3-8133-4e4b-8ce8-e2bea84a96a4'; // documentType.collection.dataTypeId; if (dataTypeUnique) { await this.#dataTypeDetailRepository.requestByUnique(dataTypeUnique); @@ -37,9 +44,7 @@ export class UmbDocumentWorkspaceViewCollectionElement extends UmbLitElement imp await this.#dataTypeDetailRepository.byUnique(dataTypeUnique), (dataType) => { if (!dataType) return; - this._config = this.#mapDataTypeConfigToCollectionConfig( - new UmbPropertyEditorConfigCollection(dataType.values), - ); + this._config = this.#mapDataTypeConfigToCollectionConfig(dataType); }, '#observeConfig.dataType', ); @@ -50,19 +55,22 @@ export class UmbDocumentWorkspaceViewCollectionElement extends UmbLitElement imp }); } - #mapDataTypeConfigToCollectionConfig( - config: UmbPropertyEditorConfigCollection | undefined, - ): UmbCollectionConfiguration { + #mapDataTypeConfigToCollectionConfig(dataType: UmbDataTypeDetailModel): UmbCollectionConfiguration { + const config = new UmbPropertyEditorConfigCollection(dataType.values); return { + unique: this._documentUnique, + dataTypeId: dataType.unique, allowedEntityBulkActions: config?.getValueByAlias('bulkActionPermissions'), orderBy: config?.getValueByAlias('orderBy') ?? 'updateDate', orderDirection: config?.getValueByAlias('orderDirection') ?? 'asc', pageSize: Number(config?.getValueByAlias('pageSize')) ?? 50, useInfiniteEditor: config?.getValueByAlias('useInfiniteEditor') ?? false, + userDefinedProperties: config?.getValueByAlias('includeProperties'), }; } render() { + if (!this._config?.unique || !this._config?.dataTypeId) return html``; return html``; } }