Docs: Collection example (#19593)
* add basic collection example * add card view example * update example readme * Add workspace view example with collection
This commit is contained in:
20
src/Umbraco.Web.UI.Client/examples/collection/README.md
Normal file
20
src/Umbraco.Web.UI.Client/examples/collection/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Collection Example
|
||||
|
||||
This example demonstrates how to register a collection with collection views.
|
||||
|
||||
The example includes:
|
||||
|
||||
- Collection Registration
|
||||
- Collection Repository
|
||||
- Collection Pagination
|
||||
- Table Collection View
|
||||
- Card Collection View
|
||||
- Collection as a Dashboard
|
||||
- Collection as a Workspace View
|
||||
|
||||
TODO: This example is not complete, it is missing the following features:
|
||||
|
||||
- Collection Action
|
||||
- Collection Filtering
|
||||
- Entity Actions
|
||||
- Selection + Bulk Actions
|
||||
@@ -0,0 +1,82 @@
|
||||
import type { ExampleCollectionItemModel } from '../repository/types.js';
|
||||
import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
|
||||
import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
|
||||
import { css, html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
|
||||
@customElement('example-card-collection-view')
|
||||
export class ExampleCardCollectionViewElement extends UmbLitElement {
|
||||
@state()
|
||||
private _items: Array<ExampleCollectionItemModel> = [];
|
||||
|
||||
#collectionContext?: UmbDefaultCollectionContext<ExampleCollectionItemModel>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_COLLECTION_CONTEXT, (instance) => {
|
||||
this.#collectionContext = instance;
|
||||
this.#observeCollectionItems();
|
||||
});
|
||||
}
|
||||
|
||||
#observeCollectionItems() {
|
||||
this.observe(this.#collectionContext?.items, (items) => (this._items = items || []), 'umbCollectionItemsObserver');
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<div id="card-grid">
|
||||
${repeat(
|
||||
this._items,
|
||||
(item) => item.unique,
|
||||
(item) =>
|
||||
html` <uui-card>
|
||||
<uui-icon name="icon-newspaper"></uui-icon>
|
||||
<div>${item.name}</div>
|
||||
</uui-card>`,
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
grid-auto-rows: 200px;
|
||||
gap: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
uui-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
|
||||
uui-icon {
|
||||
font-size: 2em;
|
||||
margin-bottom: var(--uui-size-space-4);
|
||||
}
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export { ExampleCardCollectionViewElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'example-card-collection-view': ExampleCardCollectionViewElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { UMB_LANGUAGE_TABLE_COLLECTION_VIEW_ALIAS } from './manifests.js';
|
||||
@@ -0,0 +1,23 @@
|
||||
import { EXAMPLE_COLLECTION_ALIAS } from '../constants.js';
|
||||
import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'collectionView',
|
||||
alias: 'Example.CollectionView.Card',
|
||||
name: 'Example Card Collection View',
|
||||
js: () => import('./collection-view.element.js'),
|
||||
weight: 50,
|
||||
meta: {
|
||||
label: 'Card',
|
||||
icon: 'icon-grid',
|
||||
pathName: 'card',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: UMB_COLLECTION_ALIAS_CONDITION,
|
||||
match: EXAMPLE_COLLECTION_ALIAS,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
export const EXAMPLE_COLLECTION_ALIAS = 'Example.Collection';
|
||||
@@ -0,0 +1,20 @@
|
||||
import { EXAMPLE_COLLECTION_ALIAS } from './constants.js';
|
||||
import { EXAMPLE_COLLECTION_REPOSITORY_ALIAS } from './repository/constants.js';
|
||||
import { manifests as cardViewManifests } from './card-view/manifests.js';
|
||||
import { manifests as repositoryManifests } from './repository/manifests.js';
|
||||
import { manifests as tableViewManifests } from './table-view/manifests.js';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'collection',
|
||||
kind: 'default',
|
||||
alias: EXAMPLE_COLLECTION_ALIAS,
|
||||
name: 'Example Collection',
|
||||
meta: {
|
||||
repositoryAlias: EXAMPLE_COLLECTION_REPOSITORY_ALIAS,
|
||||
},
|
||||
},
|
||||
...cardViewManifests,
|
||||
...repositoryManifests,
|
||||
...tableViewManifests,
|
||||
];
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { ExampleCollectionFilterModel, ExampleCollectionItemModel } from './types.js';
|
||||
import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository';
|
||||
import type { UmbCollectionRepository } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
export class ExampleCollectionRepository
|
||||
extends UmbRepositoryBase
|
||||
implements UmbCollectionRepository<ExampleCollectionItemModel, ExampleCollectionFilterModel>
|
||||
{
|
||||
async requestCollection(args: ExampleCollectionFilterModel) {
|
||||
const skip = args.skip || 0;
|
||||
const take = args.take || 10;
|
||||
|
||||
// Simulating a data fetch. This would in most cases be replaced with an API call.
|
||||
let items = [
|
||||
{
|
||||
unique: '3e31e9c5-7d66-4c99-a9e5-d9f2b1e2b22f',
|
||||
entityType: 'example',
|
||||
name: 'Example Item 1',
|
||||
},
|
||||
{
|
||||
unique: 'bc9b6e24-4b11-4dd6-8d4e-7c4f70e59f3c',
|
||||
entityType: 'example',
|
||||
name: 'Example Item 2',
|
||||
},
|
||||
{
|
||||
unique: '5a2f4e3a-ef7e-470e-8c3c-3d859c02ae0d',
|
||||
entityType: 'example',
|
||||
name: 'Example Item 3',
|
||||
},
|
||||
{
|
||||
unique: 'f4c3d8b8-6d79-4c87-9aa9-56b1d8fda702',
|
||||
entityType: 'example',
|
||||
name: 'Example Item 4',
|
||||
},
|
||||
{
|
||||
unique: 'c9f0a8a3-1b49-4724-bde3-70e31592eb6e',
|
||||
entityType: 'example',
|
||||
name: 'Example Item 5',
|
||||
},
|
||||
];
|
||||
|
||||
// Simulating filtering based on the args
|
||||
if (args.filter) {
|
||||
items = items.filter((item) => item.name.toLowerCase().includes(args.filter!.toLowerCase()));
|
||||
}
|
||||
|
||||
// Get the total number of items before pagination
|
||||
const totalItems = items.length;
|
||||
|
||||
// Simulating pagination
|
||||
const start = skip;
|
||||
const end = start + take;
|
||||
items = items.slice(start, end);
|
||||
|
||||
const data = {
|
||||
items,
|
||||
total: totalItems,
|
||||
};
|
||||
|
||||
return { data };
|
||||
}
|
||||
}
|
||||
|
||||
export { ExampleCollectionRepository as api };
|
||||
@@ -0,0 +1 @@
|
||||
export const EXAMPLE_COLLECTION_REPOSITORY_ALIAS = 'Example.Repository.Collection';
|
||||
@@ -0,0 +1,10 @@
|
||||
import { EXAMPLE_COLLECTION_REPOSITORY_ALIAS } from './constants.js';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'repository',
|
||||
alias: EXAMPLE_COLLECTION_REPOSITORY_ALIAS,
|
||||
name: 'Example Collection Repository',
|
||||
api: () => import('./collection.repository.js'),
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { UmbCollectionFilterModel } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
export interface ExampleCollectionItemModel {
|
||||
unique: string;
|
||||
entityType: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ExampleCollectionFilterModel extends UmbCollectionFilterModel {}
|
||||
@@ -0,0 +1,89 @@
|
||||
import type { ExampleCollectionItemModel } from '../repository/types.js';
|
||||
import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
|
||||
import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
|
||||
import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components';
|
||||
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
|
||||
@customElement('example-table-collection-view')
|
||||
export class ExampleTableCollectionViewElement extends UmbLitElement {
|
||||
@state()
|
||||
private _tableConfig: UmbTableConfig = {
|
||||
allowSelection: false,
|
||||
};
|
||||
|
||||
@state()
|
||||
private _tableColumns: Array<UmbTableColumn> = [
|
||||
{
|
||||
name: 'Name',
|
||||
alias: 'name',
|
||||
},
|
||||
];
|
||||
|
||||
@state()
|
||||
private _tableItems: Array<UmbTableItem> = [];
|
||||
|
||||
#collectionContext?: UmbDefaultCollectionContext<ExampleCollectionItemModel>;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeContext(UMB_COLLECTION_CONTEXT, (instance) => {
|
||||
this.#collectionContext = instance;
|
||||
this.#observeCollectionItems();
|
||||
});
|
||||
}
|
||||
|
||||
#observeCollectionItems() {
|
||||
this.observe(
|
||||
this.#collectionContext?.items,
|
||||
(items) => this.#createTableItems(items),
|
||||
'umbCollectionItemsObserver',
|
||||
);
|
||||
}
|
||||
|
||||
#createTableItems(items: Array<ExampleCollectionItemModel> | undefined) {
|
||||
if (!items) {
|
||||
this._tableItems = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this._tableItems = items.map((item) => {
|
||||
return {
|
||||
id: item.unique,
|
||||
icon: 'icon-newspaper',
|
||||
data: [
|
||||
{
|
||||
columnAlias: 'name',
|
||||
value: item.name,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<umb-table .config=${this._tableConfig} .columns=${this._tableColumns} .items=${this._tableItems}></umb-table>
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export { ExampleTableCollectionViewElement as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'example-table-collection-view': ExampleTableCollectionViewElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { UMB_LANGUAGE_TABLE_COLLECTION_VIEW_ALIAS } from './manifests.js';
|
||||
@@ -0,0 +1,23 @@
|
||||
import { EXAMPLE_COLLECTION_ALIAS } from '../constants.js';
|
||||
import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'collectionView',
|
||||
alias: 'Example.CollectionView.Table',
|
||||
name: 'Example Table Collection View',
|
||||
js: () => import('./collection-view.element.js'),
|
||||
weight: 100,
|
||||
meta: {
|
||||
label: 'Table',
|
||||
icon: 'icon-list',
|
||||
pathName: 'table',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: UMB_COLLECTION_ALIAS_CONDITION,
|
||||
match: EXAMPLE_COLLECTION_ALIAS,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,23 @@
|
||||
import { EXAMPLE_COLLECTION_ALIAS } from '../collection/constants.js';
|
||||
import { html, customElement, LitElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||
import type { UmbCollectionConfiguration } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
@customElement('example-dashboard-with-collection')
|
||||
export class ExampleDashboardWithCollection extends UmbElementMixin(LitElement) {
|
||||
#config: UmbCollectionConfiguration = {
|
||||
pageSize: 3,
|
||||
};
|
||||
|
||||
override render() {
|
||||
return html`<umb-collection alias=${EXAMPLE_COLLECTION_ALIAS} .config=${this.#config}></umb-collection>`;
|
||||
}
|
||||
}
|
||||
|
||||
export { ExampleDashboardWithCollection as element };
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'example-dashboard-with-collection': ExampleDashboardWithCollection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'dashboard',
|
||||
kind: 'default',
|
||||
name: 'Example Dashboard With Collection',
|
||||
alias: 'Example.Dashboard.WithCollection',
|
||||
element: () => import('./dashboard-with-collection.element.js'),
|
||||
weight: 3000,
|
||||
meta: {
|
||||
label: 'Collection Example',
|
||||
pathname: 'collection-example',
|
||||
},
|
||||
},
|
||||
];
|
||||
9
src/Umbraco.Web.UI.Client/examples/collection/index.ts
Normal file
9
src/Umbraco.Web.UI.Client/examples/collection/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { manifests as collectionManifests } from './collection/manifests.js';
|
||||
import { manifests as dashboardManifests } from './dashboard-with-collection/manifests.js';
|
||||
import { manifests as workspaceViewManifests } from './workspace-view-with-collection/manifests.js';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
...collectionManifests,
|
||||
...dashboardManifests,
|
||||
...workspaceViewManifests,
|
||||
];
|
||||
@@ -0,0 +1,25 @@
|
||||
import { EXAMPLE_COLLECTION_ALIAS } from '../collection/constants.js';
|
||||
import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace';
|
||||
import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '@umbraco-cms/backoffice/document';
|
||||
|
||||
export const manifests: Array<UmbExtensionManifest> = [
|
||||
{
|
||||
type: 'workspaceView',
|
||||
kind: 'collection',
|
||||
name: 'Example Workspace View With Collection',
|
||||
alias: 'Example.WorkspaceView.WithCollection',
|
||||
weight: 3000,
|
||||
meta: {
|
||||
label: 'Collection Example',
|
||||
pathname: 'collection-example',
|
||||
icon: 'icon-layers',
|
||||
collectionAlias: EXAMPLE_COLLECTION_ALIAS,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
alias: UMB_WORKSPACE_CONDITION_ALIAS,
|
||||
match: UMB_DOCUMENT_WORKSPACE_ALIAS,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user