add document recycle bin

This commit is contained in:
Mads Rasmussen
2023-09-12 16:17:06 +02:00
parent f417df0af7
commit bb23126131
12 changed files with 210 additions and 1 deletions

View File

@@ -1,5 +1,6 @@
export * from './repository/index.js';
export * from './workspace/index.js';
export * from './recycle-bin/index.js';
import './components/index.js';

View File

@@ -6,6 +6,7 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js';
import { manifests as propertyEditorManifests } from './property-editors/manifests.js';
import { manifests as recycleBinManifests } from './recycle-bin/manifests.js';
export const manifests = [
...collectionManifests,
@@ -16,4 +17,5 @@ export const manifests = [
...entityActionManifests,
...entityBulkActionManifests,
...propertyEditorManifests,
...recycleBinManifests,
];

View File

@@ -4,7 +4,7 @@ const menuItem: ManifestMenuItem = {
type: 'menuItem',
alias: 'Umb.MenuItem.Documents',
name: 'Documents Menu Item',
weight: 100,
weight: 200,
loader: () => import('./document-menu-item.element.js'),
meta: {
label: 'Documents',

View File

@@ -0,0 +1 @@
export * from './repository/index.js';

View File

@@ -0,0 +1,5 @@
import { manifests as repositoryManifests } from './repository/manifests.js';
import { manifests as treeManifests } from './tree/manifests.js';
import { manifests as menuItemManifests } from './menu-item/manifests.js';
export const manifests = [...repositoryManifests, ...treeManifests, ...menuItemManifests];

View File

@@ -0,0 +1,17 @@
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@customElement('umb-document-recycle-bin-menu-item')
export class UmbDocumentRecycleMenuItemElement extends UmbLitElement {
render() {
return html`<umb-tree alias="Umb.Tree.DocumentRecycleBin"></umb-tree>`;
}
}
export default UmbDocumentRecycleMenuItemElement;
declare global {
interface HTMLElementTagNameMap {
'umb-document-recycle-bin-menu-item': UmbDocumentRecycleMenuItemElement;
}
}

View File

@@ -0,0 +1,16 @@
import type { ManifestMenuItem } from '@umbraco-cms/backoffice/extension-registry';
const menuItem: ManifestMenuItem = {
type: 'menuItem',
alias: 'Umb.MenuItem.DocumentRecycleBin',
name: 'Document Recycle Bin Menu Item',
weight: 100,
loader: () => import('./document-recycle-bin-menu-item.element.js'),
meta: {
label: 'Recycle Bin',
icon: 'umb:trash',
menus: ['Umb.Menu.Content'],
},
};
export const manifests = [menuItem];

View File

@@ -0,0 +1,77 @@
import { UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN, UmbDocumentTreeStore } from '../../repository/document.tree.store.js';
import { UmbDocumentRecycleBinTreeServerDataSource } from './sources/document-recycle-bin.tree.server.data.js';
import type { UmbTreeDataSource, UmbTreeRepository } from '@umbraco-cms/backoffice/repository';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
export class UmbDocumentRecycleBinRepository implements UmbTreeRepository<DocumentTreeItemResponseModel> {
#init!: Promise<unknown>;
#host: UmbControllerHostElement;
#treeSource: UmbTreeDataSource;
#treeStore?: UmbDocumentTreeStore;
constructor(host: UmbControllerHostElement) {
this.#host = host;
// TODO: figure out how spin up get the correct data source
this.#treeSource = new UmbDocumentRecycleBinTreeServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_DOCUMENT_TREE_STORE_CONTEXT_TOKEN, (instance) => {
this.#treeStore = instance;
}),
]);
}
async requestTreeRoot() {
await this.#init;
const data = {
id: null,
type: 'document-recycle-bin-root',
name: 'Recycle Bin',
icon: 'umb:trash',
hasChildren: true,
};
return { data };
}
async requestRootTreeItems() {
await this.#init;
const { data, error } = await this.#treeSource.getRootItems();
if (data) {
this.#treeStore?.appendItems(data.items);
}
return { data, error, asObservable: () => this.#treeStore!.rootItems };
}
async requestTreeItemsOf(parentId: string | null) {
await this.#init;
if (parentId === undefined) throw new Error('Parent id is missing');
const { data, error } = await this.#treeSource.getChildrenOf(parentId);
if (data) {
this.#treeStore?.appendItems(data.items);
}
return { data, error, asObservable: () => this.#treeStore!.childrenOf(parentId) };
}
async rootTreeItems() {
await this.#init;
return this.#treeStore!.rootItems;
}
async treeItemsOf(parentId: string | null) {
await this.#init;
return this.#treeStore!.childrenOf(parentId);
}
}

View File

@@ -0,0 +1 @@
export { UmbDocumentRecycleBinRepository } from './document-recycle-bin.repository.js';

View File

@@ -0,0 +1,13 @@
import { UmbDocumentRecycleBinRepository } from './document-recycle-bin.repository.js';
import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
export const DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS = 'Umb.Repository.DocumentRecycleBin';
const repository: ManifestRepository = {
type: 'repository',
alias: DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
name: 'Document Recycle Bin Repository',
class: UmbDocumentRecycleBinRepository,
};
export const manifests = [repository];

View File

@@ -0,0 +1,53 @@
import type { UmbTreeDataSource } from '@umbraco-cms/backoffice/repository';
import { DocumentResource } from '@umbraco-cms/backoffice/backend-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
/**
* A data source for the Document Recycle Bin tree that fetches data from the server
* @export
* @class UmbDocumentRecycleBinTreeServerDataSource
* @implements {UmbTreeDataSource}
*/
export class UmbDocumentRecycleBinTreeServerDataSource implements UmbTreeDataSource {
#host: UmbControllerHostElement;
/**
* Creates an instance of UmbDocumentRecycleBinTreeServerDataSource.
* @param {UmbControllerHostElement} host
* @memberof UmbDocumentTreeServerDataSource
*/
constructor(host: UmbControllerHostElement) {
this.#host = host;
}
/**
* Fetches the root items for the tree from the server
* @memberof UmbDocumentRecycleBinTreeServerDataSource
*/
async getRootItems() {
return tryExecuteAndNotify(this.#host, DocumentResource.getRecycleBinDocumentRoot({}));
}
/**
* Fetches the children of a given parent id from the server
* @param {(string | null)} parentId
* @memberof UmbDocumentTreeServerDataSource
*/
async getChildrenOf(parentId: string | null) {
if (parentId === undefined) throw new Error('Parent id is missing');
/* TODO: should we make getRootItems() internal
so it only is a server concern that there are two endpoints? */
if (parentId === null) {
return this.getRootItems();
} else {
return tryExecuteAndNotify(
this.#host,
DocumentResource.getRecycleBinDocumentChildren({
parentId,
}),
);
}
}
}

View File

@@ -0,0 +1,23 @@
import { DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../repository/manifests.js';
import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extension-registry';
const tree: ManifestTree = {
type: 'tree',
alias: 'Umb.Tree.DocumentRecycleBin',
name: 'Document Recycle Bin Tree',
meta: {
repositoryAlias: DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS,
},
};
const treeItem: ManifestTreeItem = {
type: 'treeItem',
kind: 'entity',
alias: 'Umb.TreeItem.DocumentRecycleBin',
name: 'Document Recycle Bin Tree Item',
meta: {
entityTypes: ['document-recycle-bin-root'],
},
};
export const manifests = [tree, treeItem];