Skip to content

Commit 7df9411

Browse files
committed
feature: add support for Entity Actions
1 parent 649096d commit 7df9411

File tree

63 files changed

+811
-113
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+811
-113
lines changed
131 KB
Loading

src/Umbraco.Community.SimpleTrees.Client/src/api/sdk.gen.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// This file is auto-generated by @hey-api/openapi-ts
22

33
import type { Options as ClientOptions, TDataShape, Client } from './client';
4-
import type { GetUmbracoSimpleTreesApiV1TreeItemsData, GetUmbracoSimpleTreesApiV1TreeItemsResponses, GetUmbracoSimpleTreesApiV1TreeRenderData, GetUmbracoSimpleTreesApiV1TreeRenderResponses, GetUmbracoSimpleTreesApiV1TreeRootData, GetUmbracoSimpleTreesApiV1TreeRootResponses } from './types.gen';
4+
import type { PostUmbracoSimpleTreesApiV1EntityActionExecuteData, PostUmbracoSimpleTreesApiV1EntityActionExecuteResponses, PostUmbracoSimpleTreesApiV1EntityActionUrlData, PostUmbracoSimpleTreesApiV1EntityActionUrlResponses, GetUmbracoSimpleTreesApiV1TreeItemsData, GetUmbracoSimpleTreesApiV1TreeItemsResponses, GetUmbracoSimpleTreesApiV1TreeRenderData, GetUmbracoSimpleTreesApiV1TreeRenderResponses, GetUmbracoSimpleTreesApiV1TreeRootData, GetUmbracoSimpleTreesApiV1TreeRootResponses } from './types.gen';
55
import { client as _heyApiClient } from './client.gen';
66

77
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
@@ -19,6 +19,28 @@ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends
1919
};
2020

2121
export class SimpleTrees {
22+
public static postUmbracoSimpleTreesApiV1EntityActionExecute<ThrowOnError extends boolean = true>(options?: Options<PostUmbracoSimpleTreesApiV1EntityActionExecuteData, ThrowOnError>) {
23+
return (options?.client ?? _heyApiClient).post<PostUmbracoSimpleTreesApiV1EntityActionExecuteResponses, unknown, ThrowOnError>({
24+
url: '/umbraco/SimpleTrees/api/v1/entity-action/execute',
25+
...options,
26+
headers: {
27+
'Content-Type': 'application/json',
28+
...options?.headers
29+
}
30+
});
31+
}
32+
33+
public static postUmbracoSimpleTreesApiV1EntityActionUrl<ThrowOnError extends boolean = true>(options?: Options<PostUmbracoSimpleTreesApiV1EntityActionUrlData, ThrowOnError>) {
34+
return (options?.client ?? _heyApiClient).post<PostUmbracoSimpleTreesApiV1EntityActionUrlResponses, unknown, ThrowOnError>({
35+
url: '/umbraco/SimpleTrees/api/v1/entity-action/url',
36+
...options,
37+
headers: {
38+
'Content-Type': 'application/json',
39+
...options?.headers
40+
}
41+
});
42+
}
43+
2244
public static getUmbracoSimpleTreesApiV1TreeItems<ThrowOnError extends boolean = true>(options?: Options<GetUmbracoSimpleTreesApiV1TreeItemsData, ThrowOnError>) {
2345
return (options?.client ?? _heyApiClient).get<GetUmbracoSimpleTreesApiV1TreeItemsResponses, unknown, ThrowOnError>({
2446
url: '/umbraco/SimpleTrees/api/v1/tree/items',

src/Umbraco.Community.SimpleTrees.Client/src/api/types.gen.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,40 @@
11
// This file is auto-generated by @hey-api/openapi-ts
22

3+
export enum EventMessageTypeModel {
4+
DEFAULT = 'Default',
5+
INFO = 'Info',
6+
ERROR = 'Error',
7+
SUCCESS = 'Success',
8+
WARNING = 'Warning'
9+
}
10+
11+
export type NotificationHeaderModel = {
12+
message: string;
13+
category: string;
14+
type: EventMessageTypeModel;
15+
};
16+
317
export type PagedISimpleTreeItemModel = {
418
total: number;
519
items: Array<SimpleTreeItem>;
620
};
721

22+
export type SimpleEntityActionExecuteResponse = {
23+
title: string;
24+
isSuccess: boolean;
25+
message: string;
26+
};
27+
28+
export type SimpleEntityActionRequest = {
29+
unique: string;
30+
entityType: string;
31+
actionAlias: string;
32+
};
33+
34+
export type SimpleEntityActionUrlResponse = {
35+
url: string;
36+
};
37+
838
export type SimpleTreeItem = {
939
hasChildren: boolean;
1040
name: string;
@@ -24,6 +54,38 @@ export type SimpleTreeRenderModel = {
2454
body: string;
2555
};
2656

57+
export type PostUmbracoSimpleTreesApiV1EntityActionExecuteData = {
58+
body?: SimpleEntityActionRequest;
59+
path?: never;
60+
query?: never;
61+
url: '/umbraco/SimpleTrees/api/v1/entity-action/execute';
62+
};
63+
64+
export type PostUmbracoSimpleTreesApiV1EntityActionExecuteResponses = {
65+
/**
66+
* OK
67+
*/
68+
200: SimpleEntityActionExecuteResponse;
69+
};
70+
71+
export type PostUmbracoSimpleTreesApiV1EntityActionExecuteResponse = PostUmbracoSimpleTreesApiV1EntityActionExecuteResponses[keyof PostUmbracoSimpleTreesApiV1EntityActionExecuteResponses];
72+
73+
export type PostUmbracoSimpleTreesApiV1EntityActionUrlData = {
74+
body?: SimpleEntityActionRequest;
75+
path?: never;
76+
query?: never;
77+
url: '/umbraco/SimpleTrees/api/v1/entity-action/url';
78+
};
79+
80+
export type PostUmbracoSimpleTreesApiV1EntityActionUrlResponses = {
81+
/**
82+
* OK
83+
*/
84+
200: SimpleEntityActionUrlResponse;
85+
};
86+
87+
export type PostUmbracoSimpleTreesApiV1EntityActionUrlResponse = PostUmbracoSimpleTreesApiV1EntityActionUrlResponses[keyof PostUmbracoSimpleTreesApiV1EntityActionUrlResponses];
88+
2789
export type GetUmbracoSimpleTreesApiV1TreeItemsData = {
2890
body?: never;
2991
path?: never;

src/Umbraco.Community.SimpleTrees.Client/src/context/simple-trees.context.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,16 @@ export class SimpleTreesContext extends UmbControllerBase {
1313
this.#repository = new SimpleTreesRepository(this);
1414
this.provideContext(SIMPLE_TREES_CONTEXT_TOKEN, this);
1515
}
16-
17-
async render(unique: string, entityType: string){
16+
17+
async runEntityExecuteAction(unique: string, entityType: string, actionAlias: string) {
18+
return await this.#repository.runEntityExecuteAction(entityType, unique, actionAlias);
19+
}
20+
21+
async runEntityUrlAction(unique: string, entityType: string, actionAlias: string) {
22+
return await this.#repository.runEntityUrlAction(entityType, unique, actionAlias);
23+
}
24+
25+
async render(unique: string, entityType: string) {
1826
return await this.#repository.render(unique, entityType);
1927
}
2028
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {MetaEntityAction, UmbEntityActionArgs, UmbEntityActionBase} from '@umbraco-cms/backoffice/entity-action';
2+
import {UmbControllerHost} from "@umbraco-cms/backoffice/controller-api";
3+
import {SIMPLE_TREES_CONTEXT_TOKEN, SimpleTreesContext} from "../context/simple-trees.context.ts";
4+
import {UMB_NOTIFICATION_CONTEXT, UmbNotificationContext, UmbNotificationDefaultData} from '@umbraco-cms/backoffice/notification';
5+
6+
class SimpleTreesExecuteEntityAction extends UmbEntityActionBase<MetaEntityAction> {
7+
_context?: SimpleTreesContext;
8+
_notificationContext?: UmbNotificationContext;
9+
10+
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<MetaEntityAction>) {
11+
super(host, args);
12+
this.consumeContext(SIMPLE_TREES_CONTEXT_TOKEN, (context) => {
13+
this._context = context;
14+
})
15+
16+
this.consumeContext(UMB_NOTIFICATION_CONTEXT, (context) => {
17+
this._notificationContext = context;
18+
})
19+
}
20+
21+
async execute() {
22+
try {
23+
// @ts-ignore
24+
const alias = this.manifest.alias;
25+
if (!alias) {
26+
throw new Error('Alias is required to generate the URL.');
27+
}
28+
const unique = this.args.unique?.toString();
29+
if (!unique) {
30+
throw new Error('Unique identifier is required to generate the URL.');
31+
}
32+
const result = await this._context?.runEntityExecuteAction(unique, this.args.entityType, alias);
33+
const responseData = result?.data;
34+
if (responseData) {
35+
const data: UmbNotificationDefaultData = {
36+
// @ts-ignore
37+
headline: responseData.title,
38+
// @ts-ignore
39+
message: responseData.message
40+
};
41+
// @ts-ignore
42+
const style = responseData.isSuccess ? 'positive' : 'danger';
43+
this._notificationContext?.peek(style, {data});
44+
} else {
45+
throw new Error('No data returned from the action execution.');
46+
}
47+
48+
} catch (error) {
49+
console.error('Error executing entity action:', error);
50+
this._notificationContext?.peek("danger", {
51+
data: {
52+
headline: 'Error executing entity action',
53+
message: error instanceof Error ? error.message : 'An unknown error occurred.'
54+
}
55+
});
56+
}
57+
}
58+
}
59+
60+
export {SimpleTreesExecuteEntityAction as api};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {MetaEntityAction, UmbEntityActionBase, UmbEntityActionArgs} from '@umbraco-cms/backoffice/entity-action';
2+
import {SimpleTreesContext} from "../context/simple-trees.context.ts";
3+
import {UmbControllerHost} from "@umbraco-cms/backoffice/controller-api";
4+
5+
class SimpleTreesUrlEntityAction extends UmbEntityActionBase<MetaEntityAction> {
6+
_context?: SimpleTreesContext;
7+
8+
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<MetaEntityAction>) {
9+
super(host, args);
10+
this._context = new SimpleTreesContext(host);
11+
}
12+
13+
async getHref() {
14+
try {
15+
// @ts-ignore
16+
const alias = this.manifest.alias;
17+
if (!alias) {
18+
throw new Error('Alias is required to generate the URL.');
19+
}
20+
const unique = this.args.unique?.toString();
21+
if (!unique) {
22+
throw new Error('Unique identifier is required to generate the URL.');
23+
}
24+
const result = await this._context?.runEntityUrlAction(unique, this.args.entityType, alias);
25+
// @ts-ignore
26+
const href = result?.data?.url || '';
27+
return href;
28+
} catch (error) {
29+
console.error('Error getting href:', error);
30+
}
31+
}
32+
}
33+
34+
export {SimpleTreesUrlEntityAction as api};

src/Umbraco.Community.SimpleTrees.Client/src/index.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import {SimpleTreesTreeStore} from "./tree/simple-trees.tree-store.ts";
66
import {ManifestRepository, ManifestTreeStore} from "@umbraco-cms/backoffice/extension-registry";
77
import {SimpleTreesContext} from "./context/simple-trees.context.ts";
88
import {ManifestLocalizations} from "./lang/manifests.ts";
9+
import {ManifestEntityAction} from "@umbraco-cms/backoffice/entity-action";
10+
import {api as SimpleTreesExecuteEntityAction} from "./entity-action/simple-trees-execute.entity-action.ts";
11+
import {api as SimpleTreesUrlEntityAction} from "./entity-action/simple-trees-url.entity-action.ts";
912

1013
const SIMPLE_TREES_REPOSITORY_ALIAS = 'SimpleTrees.Repository';
1114
const treeRepository: ManifestRepository = {
@@ -25,10 +28,29 @@ const treeStore: ManifestTreeStore = {
2528

2629
export const manifests = [treeRepository, treeStore, ...ManifestLocalizations];
2730
export const onInit: UmbEntryPointOnInit = (_host, extensionRegistry) => {
31+
new SimpleTreesContext(_host)
32+
2833
extensionRegistry.registerMany([
2934
...manifests
3035
]);
3136

37+
const entityUrlActions: ManifestEntityAction[] = extensionRegistry.getByType("entityUrlAction");
38+
const entityExecuteActions: ManifestEntityAction[] = extensionRegistry.getByType("entityExecuteAction");
39+
40+
for (const entityActionManifest of entityUrlActions) {
41+
entityActionManifest.api = SimpleTreesUrlEntityAction;
42+
entityActionManifest.type = 'entityAction';
43+
extensionRegistry.unregister(entityActionManifest.alias);
44+
extensionRegistry.register(entityActionManifest);
45+
}
46+
47+
for (const entityActionManifest of entityExecuteActions) {
48+
entityActionManifest.api = SimpleTreesExecuteEntityAction;
49+
entityActionManifest.type = 'entityAction';
50+
extensionRegistry.unregister(entityActionManifest.alias);
51+
extensionRegistry.register(entityActionManifest);
52+
}
53+
3254
_host.consumeContext(UMB_AUTH_CONTEXT, (_auth) => {
3355
if (!_auth) {
3456
console.error('No auth context found');
@@ -48,6 +70,5 @@ export const onInit: UmbEntryPointOnInit = (_host, extensionRegistry) => {
4870
return request;
4971
});
5072

51-
new SimpleTreesContext(_host)
5273
});
5374
};

src/Umbraco.Community.SimpleTrees.Client/src/repository/simple-trees.repository.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import { UmbTreeRepositoryBase } from "@umbraco-cms/backoffice/tree";
1+
import {UmbTreeRepositoryBase} from "@umbraco-cms/backoffice/tree";
22
import {
33
SimpleTreesChildrenOfRequestArgs,
44
SimpleTreesRootItemsRequestArgs,
55
SimpleTreesAncestorsOfRequestArgs,
66
SimpleTreesTreeItemModel,
77
SimpleTreesTreeRootModel
88
} from "../tree/types.ts";
9-
import { UmbControllerHost } from "@umbraco-cms/backoffice/controller-api";
10-
import { SimpleTreesTreeServerDataSource } from "../tree/simple-trees.server-data-source.ts";
11-
import { UmbApi } from "@umbraco-cms/backoffice/extension-api";
12-
import { SIMPLE_TREES_TREE_STORE_CONTEXT } from "../tree/simple-trees.tree-store.ts";
13-
import { tryExecuteAndNotify } from "@umbraco-cms/backoffice/resources";
14-
import { SimpleTrees } from "../api";
9+
import {UmbControllerHost} from "@umbraco-cms/backoffice/controller-api";
10+
import {SimpleTreesTreeServerDataSource} from "../tree/simple-trees.server-data-source.ts";
11+
import {UmbApi} from "@umbraco-cms/backoffice/extension-api";
12+
import {SIMPLE_TREES_TREE_STORE_CONTEXT} from "../tree/simple-trees.tree-store.ts";
13+
import {tryExecuteAndNotify} from "@umbraco-cms/backoffice/resources";
14+
import {SimpleEntityActionRequest, SimpleTrees} from "../api";
1515

1616
export class SimpleTreesRepository extends UmbTreeRepositoryBase<SimpleTreesTreeItemModel, SimpleTreesTreeRootModel, SimpleTreesRootItemsRequestArgs, SimpleTreesChildrenOfRequestArgs, SimpleTreesAncestorsOfRequestArgs> implements UmbApi {
1717
_treeAlias?: string;
@@ -37,7 +37,7 @@ export class SimpleTreesRepository extends UmbTreeRepositoryBase<SimpleTreesTree
3737
const options: SimpleTreesRootItemsRequestArgs = {
3838
treeAlias: this._treeAlias,
3939
};
40-
const { data: treeRootData } = await this._treeSource.getRootItems(options);
40+
const {data: treeRootData} = await this._treeSource.getRootItems(options);
4141
const hasChildren = treeRootData ? treeRootData.total > 0 : false;
4242

4343
const data: SimpleTreesTreeRootModel = {
@@ -48,7 +48,7 @@ export class SimpleTreesRepository extends UmbTreeRepositoryBase<SimpleTreesTree
4848
isFolder: true,
4949
};
5050

51-
return { data };
51+
return {data};
5252
}
5353

5454
async render(unique: string, entityType: string) {
@@ -60,6 +60,32 @@ export class SimpleTreesRepository extends UmbTreeRepositoryBase<SimpleTreesTree
6060
};
6161
return await tryExecuteAndNotify(this._host, SimpleTrees.getUmbracoSimpleTreesApiV1TreeRender(options));
6262
}
63+
64+
async runEntityExecuteAction(entityType: string, unique: string, actionAlias: string) {
65+
const body: SimpleEntityActionRequest = {
66+
entityType: entityType,
67+
unique: unique,
68+
actionAlias: actionAlias,
69+
}
70+
const options = {
71+
body: body
72+
};
73+
74+
return await tryExecuteAndNotify(this._host, SimpleTrees.postUmbracoSimpleTreesApiV1EntityActionExecute(options));
75+
}
76+
77+
async runEntityUrlAction(entityType: string, unique: string, actionAlias: string) {
78+
const body: SimpleEntityActionRequest = {
79+
entityType: entityType,
80+
unique: unique,
81+
actionAlias: actionAlias,
82+
}
83+
const options = {
84+
body: body
85+
};
86+
87+
return await tryExecuteAndNotify(this._host, SimpleTrees.postUmbracoSimpleTreesApiV1EntityActionUrl(options));
88+
}
6389
}
6490

6591
export default SimpleTreesRepository;

src/Umbraco.Community.SimpleTrees.Client/vite.config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import {defineConfig} from "vite";
33
export default defineConfig({
44
build: {
55
lib: {
6-
entry: ["src/index.ts","src/workspace/simple-trees-workspace.context.ts"],
6+
entry: [
7+
"src/index.ts",
8+
"src/workspace/simple-trees-workspace.context.ts",
9+
"src/entity-action/simple-trees-url.entity-action.ts",
10+
"src/entity-action/simple-trees-execute.entity-action.ts"
11+
],
712
formats: ["es"],
813
},
914
outDir: "../Umbraco.Community.SimpleTrees/wwwroot/App_Plugins/SimpleTrees/dist/",

src/Umbraco.Community.SimpleTrees.TestSite/packages.lock.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@
182182
},
183183
"jcdcdev.Umbraco.Core": {
184184
"type": "Transitive",
185-
"resolved": "15.3.0",
186-
"contentHash": "CEWrBQUBkY8Mrbse7d7zUesGe3CK2dyICq+DpIeJKflweDfsh3WtK68GJ1C8CEr8QrSEka0Th8H/QpzT70fx5A==",
185+
"resolved": "15.4.0",
186+
"contentHash": "Pg1HfYKtiNWZ56+V1G0PqZxfzLHyrgduzTozSR+MuZ56M1dGQdA2Mdw87nMpv2Yg/93y3HOLigpsCE0yM3AONQ==",
187187
"dependencies": {
188188
"Umbraco.Cms.Web.Common": "[15.0.0, 16.0.0)"
189189
}
@@ -3013,7 +3013,7 @@
30133013
"Umbraco.Cms.Api.Common": "[15.0.0, 16.0.0)",
30143014
"Umbraco.Cms.Api.Management": "[15.0.0, 16.0.0)",
30153015
"Umbraco.Cms.Web.Website": "[15.0.0, 16.0.0)",
3016-
"jcdcdev.Umbraco.Core": "[15.3.0, 16.0.0)"
3016+
"jcdcdev.Umbraco.Core": "[15.4.0, 16.0.0)"
30173017
}
30183018
}
30193019
}

0 commit comments

Comments
 (0)