Merge branch 'feature/entity-action-kind' of https://github.com/umbraco/Umbraco.CMS.Backoffice into feature/entity-action-kind

This commit is contained in:
Niels Lyngsø
2024-03-03 23:21:03 +01:00
16 changed files with 176 additions and 63 deletions

View File

@@ -6,7 +6,7 @@ import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbr
* An action to perform on an entity
* For example for content you may wish to create a new document etc
*/
export interface ManifestEntityAction<MetaType extends MetaEntityAction>
export interface ManifestEntityAction<MetaType extends MetaEntityAction = MetaEntityAction>
extends ManifestElementAndApi<UmbControllerHostElement, UmbEntityAction<MetaType>>,
ManifestWithDynamicConditions {
type: 'entityAction';
@@ -96,3 +96,23 @@ export interface MetaEntityActionMoveKind extends MetaEntityActionDefaultKind {
itemRepositoryAlias: string;
pickerModalAlias: string;
}
// FOLDER
export interface ManifestEntityActionCreateFolderKind extends ManifestEntityAction<MetaEntityActionFolderKind> {
type: 'entityAction';
kind: 'folderCreate';
}
export interface ManifestEntityActionUpdateFolderKind extends ManifestEntityAction<MetaEntityActionFolderKind> {
type: 'entityAction';
kind: 'folderUpdate';
}
export interface ManifestEntityActionDeleteFolderKind extends ManifestEntityAction<MetaEntityActionFolderKind> {
type: 'entityAction';
kind: 'folderDelete';
}
export interface MetaEntityActionFolderKind extends MetaEntityActionDefaultKind {
folderRepositoryAlias: string;
}

View File

@@ -7,7 +7,7 @@ import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbr
* An action to perform on multiple entities
* For example for content you may wish to move one or more documents in bulk
*/
export interface ManifestEntityBulkAction<MetaType extends MetaEntityBulkAction>
export interface ManifestEntityBulkAction<MetaType extends MetaEntityBulkAction = MetaEntityBulkAction>
extends ManifestElementAndApi<UmbControllerHostElement, UmbEntityBulkActionBase<MetaType>>,
ManifestWithDynamicConditions<ConditionTypes> {
type: 'entityBulkAction';

View File

@@ -10,6 +10,9 @@ import type {
ManifestEntityActionReloadTreeItemChildrenKind,
ManifestEntityActionDuplicateKind,
ManifestEntityActionMoveKind,
ManifestEntityActionCreateFolderKind,
ManifestEntityActionUpdateFolderKind,
ManifestEntityActionDeleteFolderKind,
} from './entity-action.model.js';
import type { ManifestDynamicRootOrigin, ManifestDynamicRootQueryStep } from './dynamic-root.model.js';
import type { ManifestEntityBulkAction } from './entity-bulk-action.model.js';
@@ -106,6 +109,9 @@ export type ManifestTypes =
| ManifestEntityActionReloadTreeItemChildrenKind
| ManifestEntityActionDuplicateKind
| ManifestEntityActionMoveKind
| ManifestEntityActionCreateFolderKind
| ManifestEntityActionUpdateFolderKind
| ManifestEntityActionDeleteFolderKind
| ManifestEntityBulkAction
| ManifestEntryPoint
| ManifestExternalLoginProvider

View File

@@ -0,0 +1,20 @@
import { UmbCreateFolderEntityAction } from './create-folder.action.js';
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: UmbBackofficeManifestKind = {
type: 'kind',
alias: 'Umb.Kind.EntityAction.Folder.Create',
matchKind: 'folderCreate',
matchType: 'entityAction',
manifest: {
type: 'entityAction',
kind: 'folderCreate',
api: UmbCreateFolderEntityAction,
weight: 900,
forEntityTypes: [],
meta: {
icon: 'icon-add',
label: 'Create folder...',
},
},
};

View File

@@ -1,30 +1,27 @@
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
import { type UmbFolderRepository } from '@umbraco-cms/backoffice/tree';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UMB_FOLDER_CREATE_MODAL } from '@umbraco-cms/backoffice/tree';
export class UmbCreateFolderEntityAction<T extends UmbFolderRepository> extends UmbEntityActionBase<T> {
constructor(host: UmbControllerHost, args: any) {
export class UmbCreateFolderEntityAction extends UmbEntityActionBase<never> {
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<never>) {
super(host, args);
}
async execute() {
/*
if (!this.repository) return;
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const modalContext = modalManager.open(this, UMB_FOLDER_CREATE_MODAL, {
data: {
folderRepositoryAlias: this.repositoryAlias,
folderRepositoryAlias: this.args.meta.folderRepositoryAlias,
parent: {
unique: this.unique,
entityType: this.entityType,
unique: this.args.unique,
entityType: this.args.entityType,
},
},
});
await modalContext.onSubmit();
*/
console.log(`execute create-folder for: ${this.args.unique}`);
}
destroy(): void {}

View File

@@ -0,0 +1,20 @@
import { UmbDeleteFolderEntityAction } from './delete-folder.action.js';
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: UmbBackofficeManifestKind = {
type: 'kind',
alias: 'Umb.Kind.EntityAction.Folder.Delete',
matchKind: 'folderDelete',
matchType: 'entityAction',
manifest: {
type: 'entityAction',
kind: 'folderDelete',
api: UmbDeleteFolderEntityAction,
weight: 700,
forEntityTypes: [],
meta: {
icon: 'icon-trash',
label: 'Delete Folder...',
},
},
};

View File

@@ -1,24 +1,50 @@
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import type { UmbFolderRepository } from '@umbraco-cms/backoffice/tree';
export class UmbDeleteFolderEntityAction<T extends UmbFolderRepository> extends UmbEntityActionBase<T> {
async execute() {
if (!this.unique) throw new Error('Unique is not available');
if (!this.repository) return;
export class UmbDeleteFolderEntityAction extends UmbEntityActionBase<never> {
// TODO: make base type for item and detail models
#folderRepository?: UmbFolderRepository;
#init: Promise<unknown>;
const { data: folder } = await this.repository.request(this.unique);
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<MetaEntityActionDeleteKind>) {
super(host, args);
// TODO: We should properly look into how we can simplify the one time usage of a extension api, as its a bit of overkill to take conditions/overwrites and observation of extensions into play here: [NL]
// But since this happens when we execute an action, it does most likely not hurt any users, but it is a bit of a overkill to do this for every action: [NL]
this.#init = Promise.all([
new UmbExtensionApiInitializer(
this._host,
umbExtensionsRegistry,
this.args.meta.folderRepositoryAlias,
[this._host],
(permitted, ctrl) => {
this.#folderRepository = permitted ? (ctrl.api as UmbFolderRepository) : undefined;
},
).asPromise(),
]);
}
async execute() {
if (!this.args.unique) throw new Error('Unique is not available');
await this.#init;
const { data: folder } = await this.#folderRepository!.request(this.args.unique);
if (folder) {
// TODO: maybe we can show something about how many items are part of the folder?
await umbConfirmModal(this._host, {
headline: `Delete folder ${folder.name}`,
content: 'Are you sure you want to delete this folder?',
color: 'danger',
confirmLabel: 'Delete',
});
await this.repository?.delete(this.unique);
await this.#folderRepository?.delete(this.args.unique);
}
}
}

View File

@@ -1,22 +0,0 @@
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { type UmbFolderRepository, UMB_FOLDER_UPDATE_MODAL } from '@umbraco-cms/backoffice/tree';
export class UmbFolderUpdateEntityAction<
T extends UmbFolderRepository = UmbFolderRepository,
> extends UmbEntityActionBase<T> {
async execute() {
if (!this.unique) throw new Error('Unique is not available');
if (!this.repository) return;
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const modalContext = modalManager.open(this, UMB_FOLDER_UPDATE_MODAL, {
data: {
folderRepositoryAlias: this.repositoryAlias,
unique: this.unique,
},
});
await modalContext.onSubmit();
}
}

View File

@@ -1,3 +1,3 @@
export * from './delete-folder/delete-folder.action.js';
export * from './folder-update/folder-update.action.js';
export * from './update-folder/update-folder.action.js';
export * from './create-folder/create-folder.action.js';

View File

@@ -0,0 +1,5 @@
import { manifest as createKindManifest } from './create-folder/create-folder.action.kind.js';
import { manifest as deleteKindManifest } from './delete-folder/delete-folder.action.kind.js';
import { manifest as updateKindManifest } from './update-folder/update-folder.action.kind.js';
export const manifests = [createKindManifest, deleteKindManifest, updateKindManifest];

View File

@@ -0,0 +1,20 @@
import { UmbUpdateFolderEntityAction } from './update-folder.action.js';
import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry';
export const manifest: UmbBackofficeManifestKind = {
type: 'kind',
alias: 'Umb.Kind.EntityAction.Folder.Update',
matchKind: 'folderUpdate',
matchType: 'entityAction',
manifest: {
type: 'entityAction',
kind: 'folderUpdate',
api: UmbUpdateFolderEntityAction,
weight: 700,
forEntityTypes: [],
meta: {
icon: 'icon-edit',
label: 'Rename Folder...',
},
},
};

View File

@@ -0,0 +1,27 @@
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UMB_FOLDER_UPDATE_MODAL } from '@umbraco-cms/backoffice/tree';
export class UmbUpdateFolderEntityAction extends UmbEntityActionBase<never> {
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<never>) {
super(host, args);
}
async execute() {
if (!this.args.unique) throw new Error('Unique is not available');
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const modalContext = modalManager.open(this, UMB_FOLDER_UPDATE_MODAL, {
data: {
folderRepositoryAlias: this.args.meta.folderRepositoryAlias,
unique: this.args.unique,
},
});
await modalContext.onSubmit();
}
destroy(): void {}
}

View File

@@ -1,3 +1,4 @@
import { manifests as modalManifests } from './modal/manifests.js';
import { manifests as entityActionManifests } from './entity-action/manifests.js';
export const manifests = [...modalManifests];
export const manifests = [...modalManifests, ...entityActionManifests];

View File

@@ -1,7 +1,6 @@
import { UMB_DATA_TYPE_FOLDER_ENTITY_TYPE } from '../../entity.js';
import { UmbDataTypeFolderRepository } from './data-type-folder.repository.js';
import { UmbDeleteFolderEntityAction, UmbFolderUpdateEntityAction } from '@umbraco-cms/backoffice/tree';
import type { ManifestEntityAction, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
export const UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Folder';
@@ -12,31 +11,25 @@ const folderRepository: ManifestRepository = {
api: UmbDataTypeFolderRepository,
};
const entityActions: Array<ManifestEntityAction> = [
const entityActions: Array<ManifestTypes> = [
{
type: 'entityAction',
alias: 'Umb.EntityAction.DataType.RenameFolder',
alias: 'Umb.EntityAction.DataType.Folder.Rename',
name: 'Rename Data Type Folder Entity Action',
weight: 800,
api: UmbFolderUpdateEntityAction,
kind: 'folderRename',
forEntityTypes: [UMB_DATA_TYPE_FOLDER_ENTITY_TYPE],
meta: {
icon: 'icon-edit',
label: 'Rename Folder...',
repositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
folderRepositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
},
},
{
type: 'entityAction',
alias: 'Umb.EntityAction.DataType.DeleteFolder',
alias: 'Umb.EntityAction.DataType.Folder.Delete',
name: 'Delete Data Type Folder Entity Action',
weight: 700,
api: UmbDeleteFolderEntityAction,
kind: 'folderDelete',
forEntityTypes: [UMB_DATA_TYPE_FOLDER_ENTITY_TYPE],
meta: {
icon: 'icon-trash',
label: 'Delete Folder...',
repositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
folderRepositoryAlias: UMB_DATA_TYPE_FOLDER_REPOSITORY_ALIAS,
},
},
];

View File

@@ -1,6 +1,6 @@
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 { UmbDeleteFolderEntityAction, UmbUpdateFolderEntityAction } 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';
@@ -18,7 +18,7 @@ const entityActions: Array<ManifestEntityAction> = [
alias: 'Umb.EntityAction.DocumentType.RenameFolder',
name: 'Rename Document Type Folder Entity Action',
weight: 800,
api: UmbFolderUpdateEntityAction,
api: UmbUpdateFolderEntityAction,
forEntityTypes: [UMB_DOCUMENT_TYPE_FOLDER_ENTITY_TYPE],
meta: {
icon: 'icon-edit',

View File

@@ -1,5 +1,5 @@
import { UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE } from '../../entity.js';
import { UmbDeleteFolderEntityAction, UmbFolderUpdateEntityAction } from '@umbraco-cms/backoffice/tree';
import { UmbDeleteFolderEntityAction, UmbUpdateFolderEntityAction } from '@umbraco-cms/backoffice/tree';
import type { ManifestEntityAction, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
export const UMB_MEDIA_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Folder';
@@ -17,7 +17,7 @@ const entityActions: Array<ManifestEntityAction> = [
alias: 'Umb.EntityAction.MediaType.RenameFolder',
name: 'Rename Media Type Folder Entity Action',
weight: 800,
api: UmbFolderUpdateEntityAction,
api: UmbUpdateFolderEntityAction,
forEntityTypes: [UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE],
meta: {
icon: 'icon-edit',