Adds repository for member types (#525)

* member types repo

* fix build

---------

Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
Nathan Woulfe
2023-02-15 20:44:28 +10:00
committed by GitHub
parent 9f59c190c3
commit 4e2c399832
15 changed files with 620 additions and 173 deletions

View File

@@ -23,8 +23,8 @@ import { UmbDocumentStore } from './documents/documents/repository/document.stor
import { UmbDocumentTreeStore } from './documents/documents/repository/document.tree.store';
import { UmbMediaDetailStore } from './media/media/repository/media.detail.store';
import { UmbMediaTreeStore } from './media/media/repository/media.tree.store';
import { UmbMemberTypeDetailStore } from './members/member-types/member-type.detail.store';
import { UmbMemberTypeTreeStore } from './members/member-types/member-type.tree.store';
import { UmbMemberTypeDetailStore } from './members/member-types/repository/member-type.detail.store';
import { UmbMemberTypeTreeStore } from './members/member-types/repository/member-type.tree.store';
import { UmbMemberGroupDetailStore } from './members/member-groups/repository/member-group.detail.store';
import { UmbMemberGroupTreeStore } from './members/member-groups/repository/member-group.tree.store';
import { UmbMemberDetailStore } from './members/members/member.detail.store';

View File

@@ -0,0 +1,24 @@
import { UmbDeleteEntityAction } from '../../../../backoffice/shared/entity-actions/delete/delete.action';
import { MEMBER_TYPES_REPOSITORY_ALIAS } from '../repository/manifests';
import type { ManifestEntityAction } from '@umbraco-cms/models';
const entityType = 'member-type';
const repositoryAlias = MEMBER_TYPES_REPOSITORY_ALIAS;
const entityActions: Array<ManifestEntityAction> = [
{
type: 'entityAction',
alias: 'Umb.EntityAction.MemberType.Delete',
name: 'Delete Member Type Entity Action',
weight: 100,
meta: {
entityType,
icon: 'umb:trash',
label: 'Delete',
repositoryAlias,
api: UmbDeleteEntityAction,
},
},
];
export const manifests = [...entityActions];

View File

@@ -1,5 +1,13 @@
import { manifests as sidebarMenuItemManifests } from './sidebar-menu-item/manifests';
import { manifests as treeManifests } from './tree/manifests';
import { manifests as respositoryManifests } from './repository/manifests';
import { manifests as workspaceManifests } from './workspace/manifests';
import { manifests as entityActionManifests } from './entity-actions/manifests';
export const manifests = [...sidebarMenuItemManifests, ...treeManifests, ...workspaceManifests];
export const manifests = [
...sidebarMenuItemManifests,
...treeManifests,
...respositoryManifests,
...workspaceManifests,
...entityActionManifests,
];

View File

@@ -1,66 +0,0 @@
import type { MemberTypeDetails } from '@umbraco-cms/models';
import { UmbContextToken } from '@umbraco-cms/context-api';
import { ArrayState } from '@umbraco-cms/observable-api';
import { UmbEntityDetailStore, UmbStoreBase } from '@umbraco-cms/store';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
export const UMB_MEMBER_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbMemberTypeDetailStore>('UmbMemberTypeDetailStore');
/**
* @export
* @class UmbMemberTypeDetailStore
* @extends {UmbStoreBase}
* @description - Details Data Store for Member Types
*/
export class UmbMemberTypeDetailStore extends UmbStoreBase implements UmbEntityDetailStore<MemberTypeDetails> {
#data = new ArrayState<MemberTypeDetails>([], (x) => x.key);
constructor(host: UmbControllerHostInterface) {
super(host, UMB_MEMBER_TYPE_DETAIL_STORE_CONTEXT_TOKEN.toString());
}
getScaffold(entityType: string, parentKey: string | null) {
return {
} as MemberTypeDetails;
}
/**
* @description - Request a Data Type by key. The Data Type is added to the store and is returned as an Observable.
* @param {string} key
* @return {*} {(Observable<MemberTypeDetails | undefined>)}
* @memberof UmbMemberTypesStore
*/
getByKey(key: string) {
return null as any;
}
// TODO: make sure UI somehow can follow the status of this action.
/**
* @description - Save a Data Type.
* @param {Array<MemberTypeDetails>} memberTypes
* @memberof UmbMemberTypesStore
* @return {*} {Promise<void>}
*/
save(data: MemberTypeDetails[]) {
return null as any;
}
// TODO: How can we avoid having this in both stores?
/**
* @description - Delete a Data Type.
* @param {string[]} keys
* @memberof UmbMemberTypesStore
* @return {*} {Promise<void>}
*/
async delete(keys: string[]) {
// TODO: use backend cli when available.
return null as any;
this.#data.remove(keys);
}
}

View File

@@ -1,93 +0,0 @@
import { EntityTreeItemModel, MemberTypeResource } from '@umbraco-cms/backend-api';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
import { UmbContextToken } from '@umbraco-cms/context-api';
import { ArrayState } from '@umbraco-cms/observable-api';
import { UmbStoreBase } from '@umbraco-cms/store';
import type { UmbControllerHostInterface } from '@umbraco-cms/controller';
export const UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbMemberTypeTreeStore>(
'UmbMemberTypeTreeStore'
);
/**
* @export
* @class UmbMemberTypeTreeStore
* @extends {UmbStoreBase}
* @description - Tree Data Store for Member Types
*/
export class UmbMemberTypeTreeStore extends UmbStoreBase {
// TODO: use the right type here:
#data = new ArrayState<EntityTreeItemModel>([], (x) => x.key);
constructor(host: UmbControllerHostInterface) {
super(host, UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN.toString());
}
// TODO: How can we avoid having this in both stores?
/**
* @description - Delete a Data Type.
* @param {string[]} keys
* @memberof UmbMemberTypesStore
* @return {*} {Promise<void>}
*/
async delete(keys: string[]) {
// TODO: use backend cli when available.
await fetch('/umbraco/backoffice/member-type/delete', {
method: 'POST',
body: JSON.stringify(keys),
headers: {
'Content-Type': 'application/json',
},
});
this.#data.remove(keys);
}
getTreeRoot() {
tryExecuteAndNotify(this._host, MemberTypeResource.getTreeMemberTypeRoot({})).then(({ data }) => {
if (data) {
// TODO: how do we handle if an item has been removed during this session(like in another tab or by another user)?
this.#data.append(data.items);
}
});
// TODO: remove ignore when we know how to handle trashed items.
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === null));
}
getTreeItemChildren(key: string) {
/*
tryExecuteAndNotify(
this._host,
MemberTypeResource.getTreeMemberTypeChildren({
parentKey: key,
})
).then(({ data }) => {
if (data) {
// TODO: how do we handle if an item has been removed during this session(like in another tab or by another user)?
this.#data.append(data.items);
}
});
*/
return this.#data.getObservablePart((items) => items.filter((item) => item.parentKey === key));
}
getTreeItems(keys: Array<string>) {
if (keys?.length > 0) {
tryExecuteAndNotify(
this._host,
MemberTypeResource.getTreeMemberTypeItem({
key: keys,
})
).then(({ data }) => {
if (data) {
// TODO: how do we handle if an item has been removed during this session(like in another tab or by another user)?
this.#data.append(data);
}
});
}
return this.#data.getObservablePart((items) => items.filter((item) => keys.includes(item.key ?? '')));
}
}

View File

@@ -0,0 +1,13 @@
import { UmbMemberTypeRepository } from './member-type.repository';
import { ManifestRepository } from 'libs/extensions-registry/repository.models';
export const MEMBER_TYPES_REPOSITORY_ALIAS = 'Umb.Repository.MemberTypes';
const repository: ManifestRepository = {
type: 'repository',
alias: MEMBER_TYPES_REPOSITORY_ALIAS,
name: 'Member Types Repository',
class: UmbMemberTypeRepository,
};
export const manifests = [repository];

View File

@@ -0,0 +1,33 @@
import { UmbContextToken } from '@umbraco-cms/context-api';
import { UmbStoreBase } from '@umbraco-cms/store';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
import { ArrayState } from '@umbraco-cms/observable-api';
import type { MemberTypeDetails } from '@umbraco-cms/models';
/**
* @export
* @class UmbMemberTypeDetailStore
* @extends {UmbStoreBase}
* @description - Details Data Store for Member Types
*/
export class UmbMemberTypeDetailStore
extends UmbStoreBase
{
#data = new ArrayState<MemberTypeDetails>([], (x) => x.key);
constructor(host: UmbControllerHostInterface) {
super(host, UmbMemberTypeDetailStore.name);
}
append(MemberType: MemberTypeDetails) {
this.#data.append([MemberType]);
}
remove(uniques: string[]) {
this.#data.remove(uniques);
}
}
export const UMB_MEMBER_TYPE_DETAIL_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbMemberTypeDetailStore>(
UmbMemberTypeDetailStore.name
);

View File

@@ -0,0 +1,200 @@
import { MemberTypeTreeServerDataSource } from './sources/member-type.tree.server.data';
import { UmbMemberTypeTreeStore, UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN } from './member-type.tree.store';
import { UmbMemberTypeDetailStore, UMB_MEMBER_TYPE_DETAIL_STORE_CONTEXT_TOKEN } from './member-type.detail.store';
import { UmbMemberTypeDetailServerDataSource } from './sources/member-type.detail.server.data';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
import { UmbContextConsumerController } from '@umbraco-cms/context-api';
import { RepositoryTreeDataSource, UmbDetailRepository, UmbTreeRepository } from '@umbraco-cms/repository';
import { ProblemDetailsModel } from '@umbraco-cms/backend-api';
import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification';
import type { MemberTypeDetails } from '@umbraco-cms/models';
// TODO => use correct type when available
type ItemType = any;
export class UmbMemberTypeRepository implements UmbTreeRepository, UmbDetailRepository<ItemType> {
#init!: Promise<unknown>;
#host: UmbControllerHostInterface;
#treeSource: RepositoryTreeDataSource;
#treeStore?: UmbMemberTypeTreeStore;
#detailSource: UmbMemberTypeDetailServerDataSource;
#detailStore?: UmbMemberTypeDetailStore;
#notificationService?: UmbNotificationService;
constructor(host: UmbControllerHostInterface) {
this.#host = host;
// TODO: figure out how spin up get the correct data source
this.#treeSource = new MemberTypeTreeServerDataSource(this.#host);
this.#detailSource = new UmbMemberTypeDetailServerDataSource(this.#host);
this.#init = Promise.all([
new UmbContextConsumerController(this.#host, UMB_MEMBER_TYPE_DETAIL_STORE_CONTEXT_TOKEN, (instance) => {
this.#detailStore = instance;
}),
new UmbContextConsumerController(this.#host, UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN, (instance) => {
this.#treeStore = instance;
}),
new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN, (instance) => {
this.#notificationService = instance;
}),
]);
}
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(parentKey: string | null) {
await this.#init;
if (!parentKey) {
const error: ProblemDetailsModel = { title: 'Parent key is missing' };
return { data: undefined, error };
}
const { data, error } = await this.#treeSource.getChildrenOf(parentKey);
if (data) {
this.#treeStore?.appendItems(data.items);
}
return { data, error, asObservable: () => this.#treeStore!.childrenOf(parentKey) };
}
async requestTreeItems(keys: Array<string>) {
await this.#init;
if (!keys) {
const error: ProblemDetailsModel = { title: 'Keys are missing' };
return { data: undefined, error };
}
const { data, error } = await this.#treeSource.getItems(keys);
return { data, error, asObservable: () => this.#treeStore!.items(keys) };
}
async rootTreeItems() {
await this.#init;
return this.#treeStore!.rootItems;
}
async treeItemsOf(parentKey: string | null) {
await this.#init;
return this.#treeStore!.childrenOf(parentKey);
}
async treeItems(keys: Array<string>) {
await this.#init;
return this.#treeStore!.items(keys);
}
// DETAILS
async createDetailsScaffold() {
await this.#init;
return this.#detailSource.createDetailsScaffold();
}
async requestByKey(key: string) {
await this.#init;
// TODO: should we show a notification if the key is missing?
// Investigate what is best for Acceptance testing, cause in that perspective a thrown error might be the best choice?
if (!key) {
const error: ProblemDetailsModel = { title: 'Key is missing' };
return { error };
}
const { data, error } = await this.#detailSource.requestByKey(key);
if (data) {
this.#detailStore?.append(data);
}
return { data, error };
}
async delete(key: string) {
await this.#init;
if (!key) {
const error: ProblemDetailsModel = { title: 'Key is missing' };
return { error };
}
const { error } = await this.#detailSource.delete(key);
if (!error) {
const notification = { data: { message: `Member type deleted` } };
this.#notificationService?.peek('positive', notification);
}
// TODO: we currently don't use the detail store for anything.
// Consider to look up the data before fetching from the server.
// Consider notify a workspace if a member type is deleted from the store while someone is editing it.
this.#detailStore?.remove([key]);
this.#treeStore?.removeItem(key);
// TODO: would be nice to align the stores on methods/methodNames.
return { error };
}
async saveDetail(detail: ItemType) {
await this.#init;
// TODO: should we show a notification if the MemberType is missing?
// Investigate what is best for Acceptance testing, cause in that perspective a thrown error might be the best choice?
if (!detail || !detail.key) {
const error: ProblemDetailsModel = { title: 'Member type is missing' };
return { error };
}
const { error } = await this.#detailSource.saveDetail(detail);
if (!error) {
const notification = { data: { message: `Member type '${detail.name}' saved` } };
this.#notificationService?.peek('positive', notification);
}
// TODO: we currently don't use the detail store for anything.
// Consider to look up the data before fetching from the server
// Consider notify a workspace if a member type is updated in the store while someone is editing it.
this.#detailStore?.append(detail);
this.#treeStore?.updateItem(detail.key, { name: detail.name });
// TODO: would be nice to align the stores on methods/methodNames.
return { error };
}
async createDetail(detail: MemberTypeDetails) {
await this.#init;
if (!detail.name) {
const error: ProblemDetailsModel = { title: 'Name is missing' };
return { error };
}
const { data, error } = await this.#detailSource.createDetail(detail);
if (!error) {
const notification = { data: { message: `Member type '${detail.name}' created` } };
this.#notificationService?.peek('positive', notification);
}
return { data, error };
}
}

View File

@@ -0,0 +1,20 @@
import { UmbContextToken } from '@umbraco-cms/context-api';
import { UmbTreeStoreBase } from '@umbraco-cms/store';
import type { UmbControllerHostInterface } from '@umbraco-cms/controller';
/**
* @export
* @class UmbMemberTypeTreeStore
* @extends {UmbStoreBase}
* @description - Tree Data Store for Member Types
*/
export class UmbMemberTypeTreeStore extends UmbTreeStoreBase {
constructor(host: UmbControllerHostInterface) {
super(host, UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN.toString());
}
}
export const UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken<UmbMemberTypeTreeStore>(
UmbMemberTypeTreeStore.name
);

View File

@@ -0,0 +1,116 @@
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
import { ProblemDetailsModel } from '@umbraco-cms/backend-api';
import type { MemberTypeDetails } from '@umbraco-cms/models';
import { UmbDetailRepository } from '@umbraco-cms/repository';
/**
* @description - A data source for the MemberType detail that fetches data from the server
* @export
* @class UmbMemberTypeDetailServerDataSource
* @implements {MemberTypeDetailDataSource}
*/
export class UmbMemberTypeDetailServerDataSource implements UmbDetailRepository<MemberTypeDetails> {
#host: UmbControllerHostInterface;
constructor(host: UmbControllerHostInterface) {
this.#host = host;
}
/**
* @description - Creates a new MemberType scaffold
* @return {*}
* @memberof UmbMemberTypeDetailServerDataSource
*/
async createDetailsScaffold() {
const data = {} as MemberTypeDetails;
return { data };
}
/**
* @description - Fetches a MemberType with the given key from the server
* @param {string} key
* @return {*}
* @memberof UmbMemberTypeDetailServerDataSource
*/
requestByKey(key: string) {
//return tryExecuteAndNotify(this.#host, MemberTypeResource.getMemberTypeByKey({ key }));
// TODO => use backend cli when available.
return tryExecuteAndNotify(this.#host, fetch(`/umbraco/management/api/v1/member-group/${key}`)) as any;
}
/**
* @description - Updates a MemberType on the server
* @param {MemberTypeDetails} memberType
* @return {*}
* @memberof UmbMemberTypeDetailServerDataSource
*/
async saveDetail(memberType: MemberTypeDetails) {
if (!memberType.key) {
const error: ProblemDetailsModel = { title: 'MemberType key is missing' };
return { error };
}
const payload = { key: memberType.key, requestBody: memberType };
//return tryExecuteAndNotify(this.#host, MemberTypeResource.putMemberTypeByKey(payload));
// TODO => use backend cli when available.
return tryExecuteAndNotify(
this.#host,
fetch(`/umbraco/management/api/v1/member-type/${memberType.key}`, {
method: 'PUT',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
},
})
) as any;
}
/**
* @description - Inserts a new MemberType on the server
* @param {MemberTypeDetails} data
* @return {*}
* @memberof UmbMemberTypeDetailServerDataSource
*/
async createDetail(data: MemberTypeDetails) {
const requestBody = {
name: data.name,
};
//return tryExecuteAndNotify(this.#host, MemberTypeResource.postMemberType({ requestBody }));
// TODO => use backend cli when available.
return tryExecuteAndNotify(
this.#host,
fetch(`/umbraco/management/api/v1/member-type`, {
method: 'POST',
body: JSON.stringify(requestBody),
headers: {
'Content-Type': 'application/json',
},
})
) as any;
}
/**
* @description - Deletes a MemberType on the server
* @param {string} key
* @return {*}
* @memberof UmbMemberTypeDetailServerDataSource
*/
async delete(key: string) {
if (!key) {
const error: ProblemDetailsModel = { title: 'Key is missing' };
return { error };
}
//return await tryExecuteAndNotify(this.#host, MemberTypeResource.deleteMemberTypeByKey({ key }));
// TODO => use backend cli when available.
return tryExecuteAndNotify(
this.#host,
fetch(`/umbraco/management/api/v1/member-type/${key}`, {
method: 'DELETE',
})
) as any;
}
}

View File

@@ -0,0 +1,63 @@
import { MemberTypeResource, ProblemDetailsModel } from '@umbraco-cms/backend-api';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
import { RepositoryTreeDataSource } from '@umbraco-cms/repository';
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
/**
* A data source for the MemberType tree that fetches data from the server
* @export
* @class MemberTypeTreeServerDataSource
* @implements {MemberTypeTreeDataSource}
*/
export class MemberTypeTreeServerDataSource implements RepositoryTreeDataSource {
#host: UmbControllerHostInterface;
/**
* Creates an instance of MemberTypeTreeDataSource.
* @param {UmbControllerHostInterface} host
* @memberof MemberTypeTreeDataSource
*/
constructor(host: UmbControllerHostInterface) {
this.#host = host;
}
/**
* Fetches the root items for the tree from the server
* @return {*}
* @memberof MemberTypeTreeServerDataSource
*/
async getRootItems() {
return tryExecuteAndNotify(this.#host, MemberTypeResource.getTreeMemberTypeRoot({}));
}
/**
* Fetches the children of a given parent key from the server
* @param {(string | null)} parentKey
* @return {*}
* @memberof MemberTypeTreeServerDataSource
*/
async getChildrenOf(parentKey: string | null) {
const error: ProblemDetailsModel = { title: 'Not implemented for Member Type' };
return { error };
}
/**
* Fetches the items for the given keys from the server
* @param {Array<string>} keys
* @return {*}
* @memberof MemberTypeTreeServerDataSource
*/
async getItems(keys: Array<string>) {
if (!keys || keys.length === 0) {
const error: ProblemDetailsModel = { title: 'Keys are missing' };
return { error };
}
return tryExecuteAndNotify(
this.#host,
MemberTypeResource.getTreeMemberTypeItem({
key: keys,
})
);
}
}

View File

@@ -1,4 +1,4 @@
import { UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN } from '../member-type.tree.store';
import { UmbMemberTypeRepository } from '../repository/member-type.repository';
import type { ManifestTree, ManifestTreeItemAction } from '@umbraco-cms/models';
const treeAlias = 'Umb.Tree.MemberTypes';
@@ -8,7 +8,7 @@ const tree: ManifestTree = {
alias: treeAlias,
name: 'Member Types Tree',
meta: {
storeAlias: UMB_MEMBER_TYPE_TREE_STORE_CONTEXT_TOKEN.toString(),
repository: UmbMemberTypeRepository
},
};

View File

@@ -0,0 +1,80 @@
import { UmbWorkspaceContext } from '../../../shared/components/workspace/workspace-context/workspace-context';
import { UmbWorkspaceEntityContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface';
import { UmbMemberTypeRepository } from '../repository/member-type.repository';
import { ObjectState } from '@umbraco-cms/observable-api';
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
// TODO => use correct tpye
type EntityType = any;
export class UmbWorkspaceMemberTypeContext
extends UmbWorkspaceContext
implements UmbWorkspaceEntityContextInterface<EntityType | undefined>
{
#isNew = false;
#host: UmbControllerHostInterface;
#dataTypeRepository: UmbMemberTypeRepository;
#data = new ObjectState<EntityType | undefined>(undefined);
name = this.#data.getObservablePart((data) => data?.name);
constructor(host: UmbControllerHostInterface) {
super(host);
this.#host = host;
this.#dataTypeRepository = new UmbMemberTypeRepository(this.#host);
}
async load(entityKey: string) {
const { data } = await this.#dataTypeRepository.requestByKey(entityKey);
if (data) {
this.#isNew = false;
this.#data.next(data);
}
}
async createScaffold() {
const { data } = await this.#dataTypeRepository.createDetailsScaffold();
if (!data) return;
this.#isNew = true;
this.#data.next(data);
}
getData() {
return this.#data.getValue();
}
getEntityKey() {
return this.getData()?.key || '';
}
getEntityType() {
return 'member-type';
}
setName(name: string) {
this.#data.update({ name });
}
setPropertyValue(alias: string, value: unknown) {
// Not implemented
}
async save() {
if (!this.#data.value) return;
if (this.#isNew) {
await this.#dataTypeRepository.createDetail(this.#data.value);
} else {
await this.#dataTypeRepository.saveDetail(this.#data.value);
}
// If it went well, then its not new anymore?.
this.#isNew = false;
}
async delete(key: string) {
await this.#dataTypeRepository.delete(key);
}
public destroy(): void {
this.#data.complete();
}
}

View File

@@ -1,11 +1,12 @@
import { UUIInputEvent, UUIInputElement } from '@umbraco-ui/uui';
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import '../../../shared/components/workspace/workspace-layout/workspace-layout.element';
import { css, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { UmbWorkspaceMemberTypeContext } from './member-type-workspace.context';
import { UmbLitElement } from '@umbraco-cms/element';
@customElement('umb-member-type-workspace')
export class UmbMemberTypeWorkspaceElement extends LitElement {
export class UmbMemberTypeWorkspaceElement extends UmbLitElement {
static styles = [
UUITextStyles,
css`
@@ -14,14 +15,61 @@ export class UmbMemberTypeWorkspaceElement extends LitElement {
width: 100%;
height: 100%;
}
#header {
/* TODO: can this be applied from layout slot CSS? */
margin: 0 var(--uui-size-layout-1);
flex: 1 1 auto;
}
`,
];
@property()
id!: string;
@state()
private _memberTypeName = '';
@state()
private _unique?: string;
#workspaceContext: UmbWorkspaceMemberTypeContext = new UmbWorkspaceMemberTypeContext(this);
public load(entityKey: string) {
this.#workspaceContext?.load(entityKey);
this._unique = entityKey;
}
public create() {
this.#workspaceContext.createScaffold();
}
constructor() {
super();
this.provideContext('umbWorkspaceContext', this.#workspaceContext);
this.observe(this.#workspaceContext.name, (memberTypeName) => {
if (memberTypeName !== this._memberTypeName) {
this._memberTypeName = memberTypeName ?? '';
}
});
}
// TODO. find a way where we don't have to do this for all Workspaces.
private _handleInput(event: UUIInputEvent) {
if (event instanceof UUIInputEvent) {
const target = event.composedPath()[0] as UUIInputElement;
if (typeof target?.value === 'string') {
this.#workspaceContext.setName(target.value);
}
}
}
render() {
return html` <umb-workspace-layout alias="Umb.Workspace.MemberType">Member Type Workspace</umb-workspace-layout> `;
return html`
<umb-workspace-layout alias="Umb.Workspace.MemberType">
<uui-input id="header" slot="header" .value=${this._unique} @input="${this._handleInput}"></uui-input>
</umb-workspace-layout>
`;
}
}

View File

@@ -1,5 +1,6 @@
import { UmbDeleteEntityAction } from '../../../../backoffice/shared/entity-actions/delete/delete.action';
import { UmbMoveEntityAction } from '../../../../backoffice/shared/entity-actions/move/move.action';
import { DICTIONARY_REPOSITORY_ALIAS } from '../repository/manifests';
import UmbReloadDictionaryEntityAction from './reload.action';
import UmbImportDictionaryEntityAction from './import/import.action';
import UmbExportDictionaryEntityAction from './export/export.action';
@@ -7,7 +8,7 @@ import UmbCreateDictionaryEntityAction from './create/create.action';
import type { ManifestEntityAction } from '@umbraco-cms/models';
const entityType = 'dictionary-item';
const repositoryAlias = 'Umb.Repository.Dictionary';
const repositoryAlias = DICTIONARY_REPOSITORY_ALIAS;
const entityActions: Array<ManifestEntityAction> = [
{