Merge pull request #1238 from umbraco/feature/document-collection-ui

Document Collection UI (part 2)
This commit is contained in:
Lee Kelleher
2024-02-19 14:25:52 +00:00
committed by GitHub
19 changed files with 245 additions and 121 deletions

View File

@@ -1,9 +1,9 @@
import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbExtensionsManifestInitializer, createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
import type { ManifestCollectionView} from '@umbraco-cms/backoffice/extension-registry';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbArrayState, UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
import type { ManifestCollectionView } from '@umbraco-cms/backoffice/extension-registry';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
export interface UmbCollectionViewManagerConfig {
@@ -68,7 +68,7 @@ export class UmbCollectionViewManager extends UmbBaseController {
#createRoutes(views: ManifestCollectionView[] | null) {
let routes: Array<UmbRoute> = [];
if (views) {
if (views?.length) {
// find the default view from the config. If it doesn't exist, use the first view
const defaultView = views.find((view) => view.alias === this.#defaultViewAlias);
const fallbackView = defaultView?.meta.pathName || views[0].meta.pathName;

View File

@@ -31,6 +31,9 @@ export class UmbDefaultCollectionContext<
#filter = new UmbObjectState<FilterModelType | object>({});
public readonly filter = this.#filter.asObservable();
#userDefinedProperties = new UmbArrayState<any>([], (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) => {

View File

@@ -11,12 +11,14 @@ export interface UmbCollectionBulkActionPermissions {
}
export interface UmbCollectionConfiguration {
unique?: string;
dataTypeId?: string;
allowedEntityBulkActions?: UmbCollectionBulkActionPermissions;
includeProperties?: Array<any>;
orderBy?: string;
orderDirection?: string;
pageSize?: number;
useInfiniteEditor?: boolean;
userDefinedProperties?: Array<any>;
}
export interface UmbCollectionContext {

View File

@@ -103,7 +103,7 @@ export class UmbTableElement extends LitElement {
@property({ type: String, attribute: false })
public orderingColumn = '';
@property({ type: String, attribute: false })
@property({ type: Boolean, attribute: false })
public orderingDesc = false;
@state()

View File

@@ -9,7 +9,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
interface ColumnConfig {
alias: string;
header: string;
isSystem: boolean;
isSystem: 1 | 0;
nameTemplate?: string;
}
@@ -77,7 +77,7 @@ export class UmbPropertyEditorUICollectionViewColumnConfigurationElement
const config: ColumnConfig = {
alias: selected.value,
header: selected.name,
isSystem: selected?.group === 'System Fields',
isSystem: selected?.group === 'System Fields' ? 1 : 0,
};
this.value = [...this.value, config];
@@ -133,7 +133,7 @@ export class UmbPropertyEditorUICollectionViewColumnConfigurationElement
(configuration) =>
html`<uui-table-row>
<uui-table-cell><uui-icon name="icon-navigation"></uui-icon></uui-table-cell>
${configuration.isSystem
${configuration.isSystem === 1
? this.#renderSystemFieldRow(configuration)
: this.#renderCustomFieldRow(configuration)}
<uui-table-cell>

View File

@@ -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`<uui-loader></uui-loader>`;
return html`<umb-collection alias="Umb.Collection.Document" .config=${this._config}></umb-collection>`;
}
}

View File

@@ -28,14 +28,8 @@ export class UmbDocumentCollectionToolbarElement extends UmbLitElement {
render() {
return html`
<umb-collection-action-bundle></umb-collection-action-bundle>
${this.#renderSearch()}
<umb-collection-view-bundle></umb-collection-view-bundle>
`;
}
#renderSearch() {
return html`
<uui-input @input=${this.#updateSearch} label="Search" placeholder="Search..." id="input-search"></uui-input>
<umb-collection-view-bundle></umb-collection-view-bundle>
`;
}

View File

@@ -1,11 +1,10 @@
import type { UmbDocumentDetailModel } from '../types.js';
import type { UmbDocumentCollectionFilterModel } from './types.js';
import type { UmbDocumentCollectionFilterModel, UmbDocumentCollectionItemModel } from './types.js';
import { UMB_DOCUMENT_TABLE_COLLECTION_VIEW_ALIAS } from './views/index.js';
import { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
export class UmbDocumentCollectionContext extends UmbDefaultCollectionContext<
UmbDocumentDetailModel,
UmbDocumentCollectionItemModel,
UmbDocumentCollectionFilterModel
> {
constructor(host: UmbControllerHost) {

View File

@@ -10,8 +10,8 @@ export class UmbDocumentCollectionRepository implements UmbCollectionRepository
this.#collectionSource = new UmbDocumentCollectionServerDataSource(host);
}
async requestCollection(filter: UmbDocumentCollectionFilterModel) {
return this.#collectionSource.getCollection(filter);
async requestCollection(query: UmbDocumentCollectionFilterModel) {
return this.#collectionSource.getCollection(query);
}
destroy(): void {}

View File

@@ -1,61 +1,62 @@
import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js';
import type { UmbDocumentCollectionFilterModel } from '../types.js';
import type { UmbDocumentTreeItemModel } from '../../tree/types.js';
import { DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbDocumentCollectionFilterModel, UmbDocumentCollectionItemModel } from '../types.js';
import { DirectionModel, DocumentResource } from '@umbraco-cms/backoffice/external/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
import type { DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { DocumentCollectionResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/repository';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataSource<UmbDocumentTreeItemModel> {
export class UmbDocumentCollectionServerDataSource implements UmbCollectionDataSource<UmbDocumentCollectionItemModel> {
#host: UmbControllerHost;
constructor(host: UmbControllerHost) {
this.#host = host;
}
async getCollection(filter: UmbDocumentCollectionFilterModel) {
// TODO: [LK] Replace the Management API call with the correct endpoint once it is available.
const { data, error } = await tryExecuteAndNotify(this.#host, DocumentResource.getTreeDocumentRoot(filter));
async getCollection(query: UmbDocumentCollectionFilterModel) {
if (!query.unique) {
throw new Error('Unique 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,
dataTypeId: query.dataTypeId,
orderBy: query.orderBy ?? 'updateDate',
orderCulture: query.orderCulture ?? 'en-US',
orderDirection: query.orderDirection === 'asc' ? DirectionModel.ASCENDING : DirectionModel.DESCENDING,
filter: query.filter,
skip: query.skip ?? 0,
take: query.take ?? 100,
};
const { data, error } = await tryExecuteAndNotify(this.#host, DocumentResource.getCollectionDocumentById(params));
if (data) {
const skip = Number(filter.skip) ?? 0;
const take = Number(filter.take) ?? 100;
const items = data.items.map((item: DocumentCollectionResponseModel) => {
const items = data.items.slice(skip, skip + take).map((item) => this.#mapper(item));
// TODO: [LK] Temp solution, review how to get the name from the corresponding variant.
const variant = item.variants[0];
//console.log('UmbDocumentCollectionServerDataSource.getCollection', [data, items]);
const model: UmbDocumentCollectionItemModel = {
unique: item.id,
createDate: new Date(variant.createDate),
creator: item.creator,
icon: item.documentType.icon,
name: variant.name,
state: variant.state,
updateDate: new Date(variant.updateDate),
updater: item.updater,
values: item.values.map((item) => { return { alias: item.alias, value: item.value }; }),
};
return model;
});
return { data: { items, total: data.total } };
}
return { error };
}
// TODO: [LK] Temp solution. Copied from "src\packages\documents\documents\tree\document-tree.server.data-source.ts"
#mapper = (item: DocumentTreeItemResponseModel): UmbDocumentTreeItemModel => {
return {
unique: item.id,
parentUnique: item.parent ? item.parent.id : null,
entityType: UMB_DOCUMENT_ENTITY_TYPE,
noAccess: item.noAccess,
isTrashed: item.isTrashed,
hasChildren: item.hasChildren,
isProtected: item.isProtected,
documentType: {
unique: item.documentType.id,
icon: item.documentType.icon,
hasCollection: item.documentType.hasListView,
},
variants: item.variants.map((variant) => {
return {
name: variant.name,
culture: variant.culture || null,
state: variant.state,
};
}),
name: item.variants[0]?.name, // TODO: this is not correct. We need to get it from the variants. This is a temp solution.
isFolder: false,
};
};
}

View File

@@ -1,5 +1,22 @@
export interface UmbDocumentCollectionFilterModel {
skip?: number;
take?: number;
filter?: string;
import type { UmbCollectionFilterModel } from '@umbraco-cms/backoffice/collection';
export interface UmbDocumentCollectionFilterModel extends UmbCollectionFilterModel {
unique: string;
dataTypeId?: string;
orderBy?: string;
orderCulture?: string;
orderDirection?: 'asc' | 'desc';
userDefinedProperties: Array<{alias: string, header: string, isSystem: boolean}>;
}
export interface UmbDocumentCollectionItemModel {
unique: string;
createDate: Date;
creator?: string | null;
icon: string;
name: string;
state: string;
updateDate: Date;
updater?: string | null;
values: Array<{ alias: string; value: string }>;
}

View File

@@ -1,5 +1,4 @@
import type { UmbDocumentCollectionFilterModel } from '../../types.js';
import type { UmbDocumentTreeItemModel } from '../../../tree/types.js';
import type { UmbDocumentCollectionFilterModel, UmbDocumentCollectionItemModel } from '../../types.js';
import { css, html, nothing, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@@ -9,7 +8,7 @@ import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collec
@customElement('umb-document-grid-collection-view')
export class UmbDocumentGridCollectionViewElement extends UmbLitElement {
@state()
private _items: Array<UmbDocumentTreeItemModel> = [];
private _items: Array<UmbDocumentCollectionItemModel> = [];
@state()
private _selection: Array<string | null> = [];
@@ -17,7 +16,7 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement {
@state()
private _loading = false;
#collectionContext?: UmbDefaultCollectionContext<UmbDocumentTreeItemModel, UmbDocumentCollectionFilterModel>;
#collectionContext?: UmbDefaultCollectionContext<UmbDocumentCollectionItemModel, UmbDocumentCollectionFilterModel>;
constructor() {
super();
@@ -39,11 +38,11 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement {
history.pushState(null, '', 'section/content/workspace/document/edit/' + id);
}
#onSelect(item: UmbDocumentTreeItemModel) {
#onSelect(item: UmbDocumentCollectionItemModel) {
this.#collectionContext?.selection.select(item.unique ?? '');
}
#onDeselect(item: UmbDocumentTreeItemModel) {
#onDeselect(item: UmbDocumentCollectionItemModel) {
this.#collectionContext?.selection.deselect(item.unique ?? '');
}
@@ -60,7 +59,7 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement {
`;
}
#renderCard(item: UmbDocumentTreeItemModel) {
#renderCard(item: UmbDocumentCollectionItemModel) {
return html`
<uui-card-content-node
.name=${item.name ?? 'Unnamed Document'}
@@ -70,7 +69,7 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement {
@open=${() => this._handleOpenCard(item.unique ?? '')}
@selected=${() => this.#onSelect(item)}
@deselected=${() => this.#onDeselect(item)}>
<uui-icon slot="icon" name=${item.documentType.icon}></uui-icon>
<uui-icon slot="icon" name=${item.icon}></uui-icon>
</uui-card-content-node>
`;
}

View File

@@ -1,5 +1,4 @@
import type { UmbDocumentCollectionFilterModel } from '../../types.js';
import type { UmbDocumentTreeItemModel } from '../../../tree/types.js';
import type { UmbDocumentCollectionFilterModel, UmbDocumentCollectionItemModel } from '../../types.js';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@@ -18,7 +17,13 @@ import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collec
@customElement('umb-document-table-collection-view')
export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
@state()
private _items?: Array<UmbDocumentTreeItemModel>;
private _busy = false;
@state()
private _userDefinedProperties?: Array<any>;
@state()
private _items?: Array<UmbDocumentCollectionItemModel>;
@state()
private _tableConfig: UmbTableConfig = {
@@ -26,7 +31,9 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
};
@state()
private _tableColumns: Array<UmbTableColumn> = [
private _tableColumns: Array<UmbTableColumn> = [];
#systemColumns: Array<UmbTableColumn> = [
{
name: 'Name',
alias: 'entityName',
@@ -40,7 +47,10 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
@state()
private _selection: Array<string> = [];
private _collectionContext?: UmbDefaultCollectionContext<UmbDocumentTreeItemModel, UmbDocumentCollectionFilterModel>;
private _collectionContext?: UmbDefaultCollectionContext<
UmbDocumentCollectionItemModel,
UmbDocumentCollectionFilterModel
>;
constructor() {
super();
@@ -53,9 +63,14 @@ 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);
this.#createTableItems(this._items);
});
this.observe(this._collectionContext.selection.selection, (selection) => {
@@ -63,24 +78,55 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
});
}
private _createTableItems(items: Array<UmbDocumentTreeItemModel>) {
#createTableHeadings() {
if (this._userDefinedProperties && this._userDefinedProperties.length > 0) {
const userColumns: Array<UmbTableColumn> = this._userDefinedProperties.map((item) => {
return {
name: item.header,
alias: item.alias,
elementName: item.elementName,
allowSorting: true,
};
});
this._tableColumns = [...this.#systemColumns, ...userColumns];
}
}
#createTableItems(items: Array<UmbDocumentCollectionItemModel>) {
// 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,
icon: item.documentType.icon,
data: [
{
columnAlias: 'entityName',
value: item.name || 'Unnamed Document',
},
// {
// columnAlias: 'entityActions',
// value: {
// entityType: item.entityType,
// },
// },
],
icon: item.icon,
data: data,
};
});
}
@@ -103,10 +149,18 @@ 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() {
if (this._busy) return html`<div class="container"><uui-loader></uui-loader></div>`;
if (this._tableItems.length === 0)
return html`<div class="container"><p>${this.localize.term('content_listViewNoItems')}</p></div>`;
return html`
<umb-table
.config=${this._tableConfig}
@@ -134,6 +188,12 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement {
umb-table {
padding: 0; /* To fix the embedded padding in the table component. */
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
`,
];
}

View File

@@ -18,10 +18,14 @@ export class UmbDocumentWorkspaceHasCollectionCondition extends UmbBaseControlle
this.#onChange = args.onChange;
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => {
this.observe(context.contentTypeHasCollection, (hasCollection) => {
this.permitted = hasCollection === true;
this.#onChange();
});
this.observe(
context.contentTypeHasCollection,
(hasCollection) => {
this.permitted = hasCollection ?? false;
this.#onChange();
},
'observeCollection',
);
});
}
}

View File

@@ -38,7 +38,7 @@ const mapper = (item: DocumentItemResponseModel): UmbDocumentItemModel => {
documentType: {
unique: item.documentType.id,
icon: item.documentType.icon,
hasListView: item.documentType.hasListView,
hasCollection: item.documentType.hasListView,
},
variants: item.variants.map((variant) => {
return {

View File

@@ -8,7 +8,7 @@ export interface UmbDocumentItemModel {
documentType: {
unique: string;
icon: string;
hasListView: boolean;
hasCollection: boolean;
};
variants: Array<UmbDocumentItemVariantModel>;
}

View File

@@ -1,12 +1,13 @@
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbDocumentWorkspaceSplitViewElement } from './document-workspace-split-view.element.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from './document-workspace.context-token.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { customElement, state, css, html } from '@umbraco-cms/backoffice/external/lit';
import type { UmbVariantModel } from '@umbraco-cms/backoffice/variant';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbRoute, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
import type { ActiveVariant } from '@umbraco-cms/backoffice/workspace';
import type { UmbRoute, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
import type { UmbVariantModel } from '@umbraco-cms/backoffice/variant';
@customElement('umb-document-workspace-editor')
export class UmbDocumentWorkspaceEditorElement extends UmbLitElement {
//private _defaultVariant?: VariantViewModelBaseModel;

View File

@@ -1,15 +1,14 @@
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
import { UmbDocumentWorkspaceEditorElement } from './document-workspace-editor.element.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api';
import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
@customElement('umb-document-workspace')
export class UmbDocumentWorkspaceElement extends UmbLitElement {

View File

@@ -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,32 +44,33 @@ 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',
'_observeConfigDataType',
);
}
},
'#observeConfig.documentType',
'_observeConfigDocumentType',
);
});
}
#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<UmbCollectionBulkActionPermissions>('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`<uui-loader></uui-loader>`;
return html`<umb-collection alias="Umb.Collection.Document" .config=${this._config}></umb-collection>`;
}
}