Skip to content

Commit 29fee57

Browse files
committed
add create member entity action
1 parent 5c9d834 commit 29fee57

File tree

6 files changed

+178
-4
lines changed

6 files changed

+178
-4
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { UMB_MEMBER_CREATE_OPTIONS_MODAL } from './member-create-options-modal.token.js';
2+
import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action';
3+
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
4+
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
5+
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
6+
7+
export class UmbCreateMemberEntityAction extends UmbEntityActionBase<never> {
8+
constructor(host: UmbControllerHost, args: UmbEntityActionArgs<never>) {
9+
super(host, args);
10+
}
11+
12+
override async execute() {
13+
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
14+
const modalContext = modalManager.open(this, UMB_MEMBER_CREATE_OPTIONS_MODAL);
15+
await modalContext.onSubmit();
16+
}
17+
}
18+
19+
export { UmbCreateMemberEntityAction as api };
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { UMB_MEMBER_ROOT_ENTITY_TYPE } from '../../entity.js';
2+
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
3+
4+
const entityActions: Array<ManifestTypes> = [
5+
{
6+
type: 'entityAction',
7+
kind: 'default',
8+
alias: 'Umb.EntityAction.Member.Create',
9+
name: 'Create Member Entity Action',
10+
weight: 1200,
11+
api: () => import('./create.action.js'),
12+
forEntityTypes: [UMB_MEMBER_ROOT_ENTITY_TYPE],
13+
meta: {
14+
icon: 'icon-add',
15+
label: '#actions_create',
16+
},
17+
},
18+
];
19+
20+
const modals: Array<ManifestTypes> = [
21+
{
22+
type: 'modal',
23+
alias: 'Umb.Modal.Member.CreateOptions',
24+
name: 'Member Create Options Modal',
25+
js: () => import('./member-create-options-modal.element.js'),
26+
},
27+
];
28+
29+
export const manifests: Array<ManifestTypes> = [...entityActions, ...modals];
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import type {
2+
UmbMemberCreateOptionsModalData,
3+
UmbMemberCreateOptionsModalValue,
4+
} from './member-create-options-modal.token.js';
5+
import { html, customElement, state, repeat, css } from '@umbraco-cms/backoffice/external/lit';
6+
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
7+
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
8+
9+
import { UmbMemberTypeTreeRepository } from '@umbraco-cms/backoffice/member-type';
10+
import { UMB_CREATE_MEMBER_WORKSPACE_PATH_PATTERN, UMB_MEMBER_WORKSPACE_PATH } from '../../paths.js';
11+
12+
const elementName = 'umb-member-create-options-modal';
13+
@customElement(elementName)
14+
export class UmbMemberCreateOptionsModalElement extends UmbModalBaseElement<
15+
UmbMemberCreateOptionsModalData,
16+
UmbMemberCreateOptionsModalValue
17+
> {
18+
@state()
19+
private _options: Array<{ label: string; unique: string; icon: string }> = [];
20+
21+
#memberTypeTreeRepository = new UmbMemberTypeTreeRepository(this);
22+
23+
override firstUpdated() {
24+
this.#getOptions();
25+
}
26+
27+
async #getOptions() {
28+
//TODO: Should we use the tree repository or make a collection repository?
29+
//TODO: And how would we get all the member types?
30+
//TODO: This only works because member types can't have folders.
31+
const { data } = await this.#memberTypeTreeRepository.requestTreeRootItems({});
32+
if (!data) return;
33+
34+
this._options = data.items.map((item) => {
35+
return {
36+
label: item.name,
37+
unique: item.unique,
38+
icon: item.icon || '',
39+
};
40+
});
41+
}
42+
43+
// close the modal when navigating
44+
#onOpen(event: Event, unique: string) {
45+
event?.stopPropagation();
46+
// TODO: the href does not emit an event, so we need to use the click event
47+
const path = UMB_CREATE_MEMBER_WORKSPACE_PATH_PATTERN.generateAbsolute({
48+
memberTypeUnique: unique,
49+
});
50+
history.pushState(null, '', path);
51+
this._submitModal();
52+
}
53+
54+
override render() {
55+
return html`
56+
<umb-body-layout headline=${this.localize.term('actions_create')}>
57+
${this.#renderOptions()}
58+
<uui-button
59+
slot="actions"
60+
id="cancel"
61+
label=${this.localize.term('general_cancel')}
62+
@click="${this._rejectModal}"></uui-button>
63+
</umb-body-layout>
64+
`;
65+
}
66+
67+
#renderOptions() {
68+
return html`
69+
<uui-box>
70+
${repeat(
71+
this._options,
72+
(option) => option.unique,
73+
(option) => html`
74+
<uui-ref-node
75+
.name=${this.localize.string(option.label)}
76+
@open=${(event) => this.#onOpen(event, option.unique)}>
77+
<umb-icon slot="icon" name=${option.icon || 'icon-circle-dotted'}></umb-icon>
78+
</uui-ref-node>
79+
`,
80+
)}
81+
</uui-box>
82+
`;
83+
}
84+
85+
static override styles = [
86+
UmbTextStyles,
87+
css`
88+
#blank {
89+
border-bottom: 1px solid var(--uui-color-border);
90+
}
91+
92+
#edit-permissions {
93+
margin-top: var(--uui-size-6);
94+
}
95+
`,
96+
];
97+
}
98+
99+
export { UmbMemberCreateOptionsModalElement as element };
100+
101+
declare global {
102+
interface HTMLElementTagNameMap {
103+
[elementName]: UmbMemberCreateOptionsModalElement;
104+
}
105+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
2+
3+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
4+
export interface UmbMemberCreateOptionsModalData {}
5+
6+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
7+
export interface UmbMemberCreateOptionsModalValue {}
8+
9+
export const UMB_MEMBER_CREATE_OPTIONS_MODAL = new UmbModalToken<
10+
UmbMemberCreateOptionsModalData,
11+
UmbMemberCreateOptionsModalValue
12+
>('Umb.Modal.Member.CreateOptions', {
13+
modal: {
14+
type: 'sidebar',
15+
size: 'small',
16+
},
17+
});
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { UMB_MEMBER_DETAIL_REPOSITORY_ALIAS, UMB_MEMBER_ITEM_REPOSITORY_ALIAS } from '../repository/index.js';
22
import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js';
3-
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
3+
import { manifests as createManifests } from './create/manifests.js';
44

5-
const entityActions: Array<ManifestTypes> = [
5+
export const manifests: Array<UmbExtensionManifest> = [
66
{
77
type: 'entityAction',
88
kind: 'delete',
@@ -14,6 +14,5 @@ const entityActions: Array<ManifestTypes> = [
1414
itemRepositoryAlias: UMB_MEMBER_ITEM_REPOSITORY_ALIAS,
1515
},
1616
},
17+
...createManifests,
1718
];
18-
19-
export const manifests: Array<ManifestTypes> = [...entityActions];

src/packages/members/member/paths.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { UmbPathPattern } from '@umbraco-cms/backoffice/router';
12
import { UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME } from '../section/paths.js';
23
import { UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_ROOT_ENTITY_TYPE } from './entity.js';
34
import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace';
@@ -11,3 +12,7 @@ export const UMB_MEMBER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generat
1112
sectionName: UMB_MEMBER_MANAGEMENT_SECTION_PATHNAME,
1213
entityType: UMB_MEMBER_ROOT_ENTITY_TYPE,
1314
});
15+
16+
export const UMB_CREATE_MEMBER_WORKSPACE_PATH_PATTERN = new UmbPathPattern<{
17+
memberTypeUnique: string;
18+
}>('create/:memberTypeUnique', UMB_MEMBER_WORKSPACE_PATH);

0 commit comments

Comments
 (0)