From 5e4601f75a333fba95f8cb8e9fccdd088243a50a Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 22 Feb 2024 16:00:49 +0000 Subject: [PATCH 1/4] Media section view: wired up the collection with the data-type configuration. --- .../media-collection.server.data-source.ts | 6 +- .../media-section-view.element.ts | 97 ++++++++++++------- 2 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts index 3f8b3fc203..6efc7fa75f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.server.data-source.ts @@ -13,9 +13,9 @@ export class UmbMediaCollectionServerDataSource implements UmbCollectionDataSour } async getCollection(query: UmbMediaCollectionFilterModel) { - // if (!query.dataTypeId) { - // throw new Error('Data type ID is required to fetch a collection.'); - // } + if (!query.dataTypeId) { + throw new Error('Data type ID is required to fetch a collection.'); + } const params = { id: query.unique ?? '', diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts index adc93c6514..94244fcac8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts @@ -1,48 +1,79 @@ import { UMB_MEDIA_COLLECTION_ALIAS } from '../collection/index.js'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbCollectionBulkActionPermissions, UmbCollectionConfiguration } from '../../../core/collection/types.js'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; +import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; +import type { UmbDataTypeDetailModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; +import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @customElement('umb-media-section-view') export class UmbMediaSectionViewElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { + // TODO: [LK] Check if we can get the default data-type ID (for the Media ListView) from the server. + //private readonly defaultDataTypeId: string = '3a0156c4-3b8c-4803-bdc1-6871faa83fff'; + private readonly defaultDataTypeUnique: string = 'dt-collectionView'; - // TODO: [LK] Work-in-progress. Need to get the data-type configuration for the Media Collection. - const config = { - unique: '', - dataTypeId: '', //'3a0156c4-3b8c-4803-bdc1-6871faa83fff', //'dt-collectionView', - allowedEntityBulkActions: { - allowBulkCopy: true, - allowBulkDelete: true, - allowBulkMove: true, - allowBulkPublish: false, - allowBulkUnpublish: false, + #dataTypeUnique: string = this.defaultDataTypeUnique; + + #dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); + + @state() + private _routes?: UmbRoute[]; + + constructor() { + super(); + + this.#defineRoutes(); + } + + async #defineRoutes() { + await this.#dataTypeDetailRepository.requestByUnique(this.#dataTypeUnique); + + this.observe( + await this.#dataTypeDetailRepository.byUnique(this.#dataTypeUnique), + (dataType) => { + if (!dataType) return; + + const dataTypeConfig = this.#mapDataTypeConfigToCollectionConfig(dataType); + + this._routes = [ + { + path: 'collection', + component: () => { + const element = new UmbCollectionElement(); + element.alias = UMB_MEDIA_COLLECTION_ALIAS; + element.config = dataTypeConfig; + return element; + }, }, - orderBy: 'updateDate', - orderDirection: 'asc', - pageSize: 50, - useInfiniteEditor: false, - userDefinedProperties: undefined, - }; - - const element = new UmbCollectionElement(); - element.alias = UMB_MEDIA_COLLECTION_ALIAS; - element.config = config; - return element; + { + path: '', + redirectTo: 'collection', + }, + ]; }, - }, - { - path: '', - redirectTo: 'collection', - }, - ]; + '_observeConfigDataType', + ); + } + + #mapDataTypeConfigToCollectionConfig(dataType: UmbDataTypeDetailModel): UmbCollectionConfiguration { + const config = new UmbPropertyEditorConfigCollection(dataType.values); + return { + unique: '', + 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() { - return html``; + if (!this._routes) return; + return html``; } static styles = [ From 29ed4fde69448cc1d69e129f6fa0642a05255020 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 22 Feb 2024 16:01:45 +0000 Subject: [PATCH 2/4] Media Collection Views: Added `sortOrder` support --- .../media-table-collection-view.element.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index 7955596ab7..8d093bf433 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -51,6 +51,9 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { @state() private _selection: Array = []; + @state() + private _skip: number = 0; + #collectionContext?: UmbDefaultCollectionContext; constructor() { @@ -89,6 +92,14 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { }, 'umbCollectionSelectionObserver', ); + + this.observe( + this.#collectionContext.pagination.skip, + (skip) => { + this._skip = skip; + }, + 'umbCollectionSkipObserver', + ); } #createTableHeadings() { @@ -113,14 +124,16 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { this.#createTableHeadings(); } - this._tableItems = items.map((item) => { + this._tableItems = items.map((item, rowIndex) => { if (!item.unique) throw new Error('Item id is missing.'); + const sortOrder = this._skip + rowIndex; + const data = this._tableColumns?.map((column) => { return { columnAlias: column.alias, - value: column.elementName ? item : this.#getPropertyValueByAlias(item, column.alias), + value: column.elementName ? item : this.#getPropertyValueByAlias(sortOrder, item, column.alias), }; }) ?? []; @@ -132,7 +145,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { }); } - #getPropertyValueByAlias(item: UmbMediaCollectionItemModel, alias: string) { + #getPropertyValueByAlias(sortOrder: number, item: UmbMediaCollectionItemModel, alias: string) { switch (alias) { case 'createDate': return item.createDate.toLocaleString(); @@ -140,6 +153,8 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { return item.name; case 'owner': return item.creator; + case 'sortOrder': + return sortOrder; case 'updateDate': return item.updateDate.toLocaleString(); default: From 9f2f308e43933257ac831d732bdf70b0764d1e50 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 26 Feb 2024 11:45:07 +0000 Subject: [PATCH 3/4] Adds stub for default Media Collection configuration e.g. DataType ID --- .../repository/media-collection.repository.ts | 7 +++++++ .../media-section-view.element.ts | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.repository.ts index 5b1df5cf8b..f5be70970c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/repository/media-collection.repository.ts @@ -10,6 +10,13 @@ export class UmbMediaCollectionRepository implements UmbCollectionRepository { this.#collectionSource = new UmbMediaCollectionServerDataSource(host); } + async getDefaultConfiguration() { + return { + // TODO: The default Collection data-type ID (for the Media ListView) will come from the server soon. [LK] + defaultDataTypeId: '3a0156c4-3b8c-4803-bdc1-6871faa83fff', + }; + } + async requestCollection(query: UmbMediaCollectionFilterModel) { return this.#collectionSource.getCollection(query); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts index 94244fcac8..911bbe8d44 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/section-view/media-section-view.element.ts @@ -1,22 +1,21 @@ import { UMB_MEDIA_COLLECTION_ALIAS } from '../collection/index.js'; -import type { UmbCollectionBulkActionPermissions, UmbCollectionConfiguration } from '../../../core/collection/types.js'; +import { UmbMediaCollectionRepository } from '../collection/repository/index.js'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; +import type { + UmbCollectionBulkActionPermissions, + UmbCollectionConfiguration, +} from '@umbraco-cms/backoffice/collection'; import type { UmbDataTypeDetailModel } from '@umbraco-cms/backoffice/data-type'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @customElement('umb-media-section-view') export class UmbMediaSectionViewElement extends UmbLitElement { - // TODO: [LK] Check if we can get the default data-type ID (for the Media ListView) from the server. - //private readonly defaultDataTypeId: string = '3a0156c4-3b8c-4803-bdc1-6871faa83fff'; - private readonly defaultDataTypeUnique: string = 'dt-collectionView'; - - #dataTypeUnique: string = this.defaultDataTypeUnique; - #dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); + #mediaCollectionRepository = new UmbMediaCollectionRepository(this); @state() private _routes?: UmbRoute[]; @@ -28,10 +27,12 @@ export class UmbMediaSectionViewElement extends UmbLitElement { } async #defineRoutes() { - await this.#dataTypeDetailRepository.requestByUnique(this.#dataTypeUnique); + const config = await this.#mediaCollectionRepository.getDefaultConfiguration(); + + await this.#dataTypeDetailRepository.requestByUnique(config.defaultDataTypeId); this.observe( - await this.#dataTypeDetailRepository.byUnique(this.#dataTypeUnique), + await this.#dataTypeDetailRepository.byUnique(config.defaultDataTypeId), (dataType) => { if (!dataType) return; From 8c2e17abfbc53dc45e14bce4526f9d6fd3e5eba9 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 26 Feb 2024 11:45:43 +0000 Subject: [PATCH 4/4] Adds mock data to align with the server's "ListView - Media" DataType --- .../mocks/data/data-type/data-type.data.ts | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index 74f5acfcd3..b05cea02f5 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -810,7 +810,7 @@ export const data: Array = [ isDeletable: false, canIgnoreStartNodes: false, values: [ - { alias: 'pageSize', value: 2 }, + { alias: 'pageSize', value: 25 }, { alias: 'orderDirection', value: 'desc' }, { alias: 'includeProperties', @@ -844,6 +844,51 @@ export const data: Array = [ { alias: 'useInfiniteEditor', value: true }, ], }, + { + name: 'Collection View - Media', + id: '3a0156c4-3b8c-4803-bdc1-6871faa83fff', + parent: null, + editorAlias: 'Umbraco.ListView', + editorUiAlias: 'Umb.PropertyEditorUi.CollectionView', + hasChildren: false, + isFolder: false, + isDeletable: false, + canIgnoreStartNodes: false, + values: [ + { alias: 'pageSize', value: 2 }, + { alias: 'orderDirection', value: 'desc' }, + { + alias: 'includeProperties', + value: [ + { alias: 'sortOrder', header: 'Sort order', isSystem: true, nameTemplate: '' }, + { alias: 'updateDate', header: 'Last edited', isSystem: true }, + { alias: 'owner', header: 'Created by', isSystem: true }, + ], + }, + { alias: 'orderBy', value: 'updateDate' }, + { + alias: 'bulkActionPermissions', + value: { + allowBulkPublish: false, + allowBulkUnpublish: false, + allowBulkCopy: true, + allowBulkMove: true, + allowBulkDelete: true, + }, + }, + { + alias: 'layouts', + value: [ + { icon: 'icon-grid', isSystem: true, name: 'Grid', path: '', selected: true }, + { icon: 'icon-list', isSystem: true, name: 'Table', path: '', selected: true }, + ], + }, + { alias: 'icon', value: 'icon-layers' }, + { alias: 'tabName', value: 'Items' }, + { alias: 'showContentFirst', value: false }, + { alias: 'useInfiniteEditor', value: true }, + ], + }, { name: 'Icon Picker', id: 'dt-iconPicker',