Merge branch 'main' into feature/default-tree-icons

This commit is contained in:
Mads Rasmussen
2024-01-23 12:25:07 +01:00
11 changed files with 251 additions and 46 deletions

View File

@@ -11,8 +11,8 @@ export class UmbDataTypeFolderRepository extends UmbFolderRepositoryBase<UmbData
}
}
const folderToDataTypeTreeItemMapper = (folder: UmbFolderModel) => {
const folderTreeItem: UmbDataTypeFolderTreeItemModel = {
const folderToDataTypeTreeItemMapper = (folder: UmbFolderModel): UmbDataTypeFolderTreeItemModel => {
return {
unique: folder.unique,
parentUnique: folder.parentUnique,
name: folder.name,
@@ -21,6 +21,4 @@ const folderToDataTypeTreeItemMapper = (folder: UmbFolderModel) => {
hasChildren: false,
isFolder: true,
};
return folderTreeItem;
};

View File

@@ -21,7 +21,7 @@ export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase<UmbDocume
this.#modalManagerContext?.open(UMB_DOCUMENT_TYPE_CREATE_OPTIONS_MODAL, {
data: {
parentKey: this.unique,
parentUnique: this.unique,
},
});
}

View File

@@ -1,52 +1,43 @@
import { DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../../repository/index.js';
import { UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS } from '../../../tree/index.js';
import { UmbDocumentTypeCreateOptionsModalData } from './index.js';
import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import {
type UmbModalManagerContext,
type UmbModalContext,
UMB_MODAL_MANAGER_CONTEXT_TOKEN,
} from '@umbraco-cms/backoffice/modal';
import { UMB_FOLDER_CREATE_MODAL } from '@umbraco-cms/backoffice/tree';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import { UmbCreateFolderEntityAction } from '@umbraco-cms/backoffice/tree';
@customElement('umb-document-type-create-options-modal')
export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement {
@property({ attribute: false })
modalContext?: UmbModalContext<UmbDocumentTypeCreateOptionsModalData>;
export class UmbDataTypeCreateOptionsModalElement extends UmbModalBaseElement<UmbDocumentTypeCreateOptionsModalData> {
#createFolderAction?: UmbCreateFolderEntityAction<any>;
@property({ type: Object })
data?: UmbDocumentTypeCreateOptionsModalData;
connectedCallback(): void {
super.connectedCallback();
#modalContext?: UmbModalManagerContext;
if (this.data?.parentUnique === undefined) throw new Error('A parent unique is required to create a folder');
constructor() {
super();
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
this.#modalContext = instance;
});
this.#createFolderAction = new UmbCreateFolderEntityAction(
this,
UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// TODO: allow null for entity actions. Some actions can be executed on the root item
this.data.parentUnique,
);
}
#onClick(event: PointerEvent) {
async #onCreateFolderClick(event: PointerEvent) {
event.stopPropagation();
if (this.data?.parentKey === undefined) throw new Error('A parent unique is required to create a folder');
const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_CREATE_MODAL, {
data: {
folderRepositoryAlias: DOCUMENT_TYPE_DETAIL_REPOSITORY_ALIAS,
parentUnique: this.data?.parentKey,
},
});
folderModalHandler?.onSubmit().then(() => this.modalContext?.submit());
try {
await this.#createFolderAction?.execute();
this._submitModal();
} catch (error) {
console.error(error);
}
}
// close the modal when navigating to data type
#onNavigate() {
this.modalContext?.submit();
}
#onCancel() {
this.modalContext?.reject();
this._rejectModal();
}
render() {
@@ -55,16 +46,16 @@ export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement {
<uui-box>
<!-- TODO: construct url -->
<uui-menu-item
href=${`section/settings/workspace/document-type/create/${this.data?.parentKey || 'null'}`}
href=${`section/settings/workspace/document-type/create/${this.data?.parentUnique || 'null'}`}
label="New Document Type..."
@click=${this.#onNavigate}>
<uui-icon slot="icon" name="icon-autofill"></uui-icon>}
</uui-menu-item>
<uui-menu-item @click=${this.#onClick} label="New Folder...">
<uui-menu-item @click=${this.#onCreateFolderClick} label="New Folder...">
<uui-icon slot="icon" name="icon-folder"></uui-icon>}
</uui-menu-item>
</uui-box>
<uui-button slot="actions" id="cancel" label="Cancel" @click="${this.#onCancel}">Cancel</uui-button>
<uui-button slot="actions" id="cancel" label="Cancel" @click="${this._rejectModal}">Cancel</uui-button>
</umb-body-layout>
`;
}

View File

@@ -1,7 +1,7 @@
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
export interface UmbDocumentTypeCreateOptionsModalData {
parentKey: string | null;
parentUnique: string | null;
}
export const UMB_DOCUMENT_TYPE_CREATE_OPTIONS_MODAL = new UmbModalToken<UmbDocumentTypeCreateOptionsModalData>(

View File

@@ -0,0 +1,30 @@
import { UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE } from '../../entity.js';
import { UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT } from '../../tree/index.js';
import { UmbDocumentTypeFolderServerDataSource } from './document-type-folder.server.data-source.js';
import { UmbDocumentTypeFolderTreeItemModel } from './types.js';
import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbFolderModel, UmbFolderRepositoryBase } from '@umbraco-cms/backoffice/tree';
export class UmbDocumentTypeFolderRepository extends UmbFolderRepositoryBase<UmbDocumentTypeFolderTreeItemModel> {
constructor(host: UmbControllerHost) {
super(
host,
UmbDocumentTypeFolderServerDataSource,
UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT,
folderToDocumentTypeTreeItemMapper,
);
}
}
const folderToDocumentTypeTreeItemMapper = (folder: UmbFolderModel): UmbDocumentTypeFolderTreeItemModel => {
return {
unique: folder.unique,
parentUnique: folder.parentUnique,
name: folder.name,
entityType: UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
isContainer: false,
hasChildren: false,
isFolder: true,
isElement: false,
};
};

View File

@@ -0,0 +1,123 @@
import { UmbCreateFolderModel, UmbFolderDataSource, UmbUpdateFolderModel } from '@umbraco-cms/backoffice/tree';
import { DocumentTypeResource } from '@umbraco-cms/backoffice/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
/**
* A data source for a Document Type folder that fetches data from the server
* @export
* @class UmbDocumentTypeFolderServerDataSource
* @implements {RepositoryDetailDataSource}
*/
export class UmbDocumentTypeFolderServerDataSource implements UmbFolderDataSource {
#host: UmbControllerHost;
/**
* Creates an instance of UmbDocumentTypeFolderServerDataSource.
* @param {UmbControllerHost} host
* @memberof UmbDocumentTypeFolderServerDataSource
*/
constructor(host: UmbControllerHost) {
this.#host = host;
}
/**
* Fetches a Document Type folder from the server
* @param {string} unique
* @return {*}
* @memberof UmbDocumentTypeFolderServerDataSource
*/
async read(unique: string) {
if (!unique) throw new Error('Unique is missing');
const { data, error } = await tryExecuteAndNotify(
this.#host,
DocumentTypeResource.getDocumentTypeFolderById({
id: unique,
}),
);
if (data) {
const mappedData = {
unique: data.id,
name: data.name,
parentUnique: data.parentId || null,
};
return { data: mappedData };
}
return { error };
}
/**
* Creates a Document Type folder on the server
* @param {UmbCreateFolderModel} args
* @return {*}
* @memberof UmbDocumentTypeFolderServerDataSource
*/
async create(args: UmbCreateFolderModel) {
if (args.parentUnique === undefined) throw new Error('Parent unique is missing');
if (!args.name) throw new Error('Name is missing');
const requestBody = {
id: args.unique,
parentId: args.parentUnique,
name: args.name,
};
const { error } = await tryExecuteAndNotify(
this.#host,
DocumentTypeResource.postDocumentTypeFolder({
requestBody,
}),
);
if (!error) {
return this.read(args.unique);
}
return { error };
}
/**
* Updates a Document Type folder on the server
* @param {UmbUpdateFolderModel} args
* @return {*}
* @memberof UmbDocumentTypeFolderServerDataSource
*/
async update(args: UmbUpdateFolderModel) {
if (!args.unique) throw new Error('Unique is missing');
if (!args.name) throw new Error('Folder name is missing');
const { error } = await tryExecuteAndNotify(
this.#host,
DocumentTypeResource.putDocumentTypeFolderById({
id: args.unique,
requestBody: { name: args.name },
}),
);
if (!error) {
return this.read(args.unique);
}
return { error };
}
/**
* Deletes a Document Type folder on the server
* @param {string} unique
* @return {*}
* @memberof UmbDocumentTypeServerDataSource
*/
async delete(unique: string) {
if (!unique) throw new Error('Unique is missing');
return tryExecuteAndNotify(
this.#host,
DocumentTypeResource.deleteDocumentTypeFolderById({
id: unique,
}),
);
}
}

View File

@@ -0,0 +1,2 @@
export { UmbDocumentTypeFolderRepository } from './document-type-folder.repository.js';
export { UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS } from './manifests.js';

View File

@@ -0,0 +1,44 @@
import { UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE } from '../../entity.js';
import { UmbDocumentTypeFolderRepository } from './document-type-folder.repository.js';
import { UmbDeleteFolderEntityAction, UmbFolderUpdateEntityAction } from '@umbraco-cms/backoffice/tree';
import type { ManifestEntityAction, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
export const UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Folder';
const folderRepository: ManifestRepository = {
type: 'repository',
alias: UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS,
name: 'Document Type Folder Repository',
api: UmbDocumentTypeFolderRepository,
};
const entityActions: Array<ManifestEntityAction> = [
{
type: 'entityAction',
alias: 'Umb.EntityAction.DocumentType.DeleteFolder',
name: 'Delete Document Type Folder Entity Action',
weight: 800,
api: UmbDeleteFolderEntityAction,
meta: {
icon: 'icon-trash',
label: 'Delete Folder...',
repositoryAlias: UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS,
entityTypes: [UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE],
},
},
{
type: 'entityAction',
alias: 'Umb.EntityAction.DocumentType.RenameFolder',
name: 'Rename Document Type Folder Entity Action',
weight: 700,
api: UmbFolderUpdateEntityAction,
meta: {
icon: 'icon-edit',
label: 'Rename Folder...',
repositoryAlias: UMB_DOCUMENT_TYPE_FOLDER_REPOSITORY_ALIAS,
entityTypes: [UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE],
},
},
];
export const manifests = [folderRepository, ...entityActions];

View File

@@ -0,0 +1,6 @@
import { UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE } from '../../entity.js';
import { UmbDocumentTypeTreeItemModel } from '../types.js';
export interface UmbDocumentTypeFolderTreeItemModel extends UmbDocumentTypeTreeItemModel {
entityType: typeof UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE;
}

View File

@@ -0,0 +1,2 @@
export { UMB_DOCUMENT_TYPE_TREE_STORE_CONTEXT } from './document-type.tree.store.js';
export * from './folder/index.js';

View File

@@ -1,6 +1,11 @@
import { UMB_DOCUMENT_TYPE_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE } from '../entity.js';
import {
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
} from '../entity.js';
import { UmbDocumentTypeTreeRepository } from './document-type-tree.repository.js';
import { UmbDocumentTypeTreeStore } from './document-type.tree.store.js';
import { manifests as folderManifests } from './folder/manifests.js';
import type {
ManifestRepository,
ManifestTree,
@@ -41,8 +46,12 @@ const treeItem: ManifestTreeItem = {
alias: 'Umb.TreeItem.DocumentType',
name: 'Document Type Tree Item',
meta: {
entityTypes: [UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE, UMB_DOCUMENT_TYPE_ENTITY_TYPE],
entityTypes: [
UMB_DOCUMENT_TYPE_ROOT_ENTITY_TYPE,
UMB_DOCUMENT_TYPE_ENTITY_TYPE,
UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE,
],
},
};
export const manifests = [treeRepository, treeStore, tree, treeItem];
export const manifests = [treeRepository, treeStore, tree, treeItem, ...folderManifests];