This commit is contained in:
Mads Rasmussen
2024-02-02 13:27:30 +01:00
parent fc94bc0885
commit 738cc39da1
11 changed files with 67 additions and 67 deletions

View File

@@ -1,8 +1,8 @@
import type { UmbUserGroupCollectionFilterModel } from '../../types.js';
import type { UmbUserGroupDetailModel } from '../../types.js';
import type { UmbUserGroupStore } from '../../repository/user-group.store.js';
import { UMB_USER_GROUP_STORE_CONTEXT } from '../../repository/user-group.store.js';
import type { UmbUserGroupCollectionFilterModel } from '../types.js';
import { UmbUserGroupCollectionServerDataSource } from './user-group-collection.server.data-source.js';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import type { UmbCollectionDataSource, UmbCollectionRepository } from '@umbraco-cms/backoffice/repository';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
@@ -11,7 +11,7 @@ export class UmbUserGroupCollectionRepository extends UmbBaseController implemen
#init;
#detailStore?: UmbUserGroupStore;
#collectionSource: UmbCollectionDataSource<UserGroupResponseModel>;
#collectionSource: UmbCollectionDataSource<UmbUserGroupDetailModel>;
constructor(host: UmbControllerHost) {
super(host);

View File

@@ -1,5 +1,5 @@
import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js';
import { UMB_USER_GROUP_REPOSITORY_ALIAS } from '../repository/manifests.js';
import { UMB_USER_GROUP_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
import { UmbDeleteUserGroupEntityBulkAction } from './delete/delete.action.js';
import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection';
import type { ManifestEntityBulkAction } from '@umbraco-cms/backoffice/extension-registry';
@@ -13,7 +13,7 @@ const entityActions: Array<ManifestEntityBulkAction> = [
api: UmbDeleteUserGroupEntityBulkAction,
meta: {
label: 'Delete',
repositoryAlias: UMB_USER_GROUP_REPOSITORY_ALIAS,
repositoryAlias: UMB_USER_GROUP_DETAIL_REPOSITORY_ALIAS,
},
conditions: [
{

View File

@@ -1,26 +1,11 @@
import type { UmbUserGroupDetailModel } from '../../types.js';
import { UmbUserGroupServerDataSource } from './user-group-detail.server.data-source.js';
import type { UmbUserGroupDetailStore } from './user-group-detail.store.js';
import { UMB_USER_GROUP_DETAIL_STORE_CONTEXT } from './user-group-detail.store.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbDetailRepositoryBase } from '@umbraco-cms/backoffice/repository';
export class UmbUserGroupDetailRepository extends UmbDetailRepositoryBase<UmbUserGroupDetailModel> {
#init: Promise<unknown>;
#detailStore?: UmbUserGroupDetailStore;
export class UmbUserGroupDetailRepository extends UmbDetailRepositoryBase<UmbUserGroupDetailModel> {
constructor(host: UmbControllerHost) {
super(host, UmbUserGroupServerDataSource, UMB_USER_GROUP_DETAIL_STORE_CONTEXT);
this.#init = Promise.all([
this.consumeContext(UMB_USER_GROUP_DETAIL_STORE_CONTEXT, (instance) => {
this.#detailStore = instance;
}).asPromise(),
]);
}
async byPropertyEditorUiAlias(propertyEditorUiAlias: string) {
if (!propertyEditorUiAlias) throw new Error('propertyEditorUiAlias is missing');
await this.#init;
return this.#detailStore!.withPropertyEditorUiAlias(propertyEditorUiAlias);
}
}

View File

@@ -1,8 +1,8 @@
import type { UmbUserGroupDetailModel, UmbUserGroupPropertyModel } from '../../types.js';
import type { UmbUserGroupDetailModel } from '../../types.js';
import { UMB_USER_GROUP_ENTITY_TYPE } from '../../entity.js';
import { UmbId } from '@umbraco-cms/backoffice/id';
import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository';
import type { CreateUserGroupRequestModel, UserGroupModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import type { CreateUserGroupRequestModel, UpdateUserGroupRequestModel } from '@umbraco-cms/backoffice/backend-api';
import { UserGroupResource } from '@umbraco-cms/backoffice/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
@@ -31,15 +31,21 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource<UmbUser
* @return { CreateUserGroupRequestModel }
* @memberof UmbUserGroupServerDataSource
*/
async createScaffold(parentUnique: string | null) {
async createScaffold() {
const data: UmbUserGroupDetailModel = {
entityType: UMB_USER_GROUP_ENTITY_TYPE,
unique: UmbId.new(),
parentUnique,
isSystemGroup: false,
name: '',
editorAlias: undefined,
editorUiAlias: null,
values: [],
icon: null,
sections: [],
languages: [],
hasAccessToAllLanguages: false,
documentStartNode: null,
documentRootAccess: false,
mediaStartNode: null,
mediaRootAccess: false,
permissions: [],
};
return { data };
@@ -64,11 +70,17 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource<UmbUser
const userGroup: UmbUserGroupDetailModel = {
entityType: UMB_USER_GROUP_ENTITY_TYPE,
unique: data.id,
parentUnique: data.parent ? data.parent.id : null,
isSystemGroup: data.isSystemGroup,
name: data.name,
editorAlias: data.editorAlias,
editorUiAlias: data.editorUiAlias || null,
values: data.values as Array<UmbUserGroupPropertyModel>,
icon: data.icon || null,
sections: data.sections,
languages: data.languages,
hasAccessToAllLanguages: data.hasAccessToAllLanguages,
documentStartNode: data.documentStartNode ? { unique: data.documentStartNode.id } : null,
documentRootAccess: data.documentRootAccess,
mediaStartNode: data.mediaStartNode ? { unique: data.mediaStartNode.id } : null,
mediaRootAccess: data.mediaRootAccess,
permissions: data.permissions,
};
return { data: userGroup };
@@ -82,17 +94,19 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource<UmbUser
*/
async create(model: UmbUserGroupDetailModel) {
if (!model) throw new Error('User Group is missing');
if (!model.unique) throw new Error('User Group unique is missing');
if (!model.editorAlias) throw new Error('Property Editor Alias is missing');
// TODO: make data mapper to prevent errors
const requestBody: CreateUserGroupRequestModel = {
id: model.unique,
parent: model.parentUnique ? { id: model.parentUnique } : null,
name: model.name,
editorAlias: model.editorAlias,
editorUiAlias: model.editorUiAlias,
values: model.values,
icon: model.icon,
sections: model.sections,
languages: model.languages,
hasAccessToAllLanguages: model.hasAccessToAllLanguages,
documentStartNode: model.documentStartNode ? { id: model.documentStartNode.unique } : null,
documentRootAccess: model.documentRootAccess,
mediaStartNode: model.mediaStartNode ? { id: model.mediaStartNode.unique } : null,
mediaRootAccess: model.mediaRootAccess,
permissions: model.permissions,
};
const { data, error } = await tryExecuteAndNotify(
@@ -117,14 +131,19 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource<UmbUser
*/
async update(model: UmbUserGroupDetailModel) {
if (!model.unique) throw new Error('Unique is missing');
if (!model.editorAlias) throw new Error('Property Editor Alias is missing');
// TODO: make data mapper to prevent errors
const requestBody: UserGroupModelBaseModel = {
const requestBody: UpdateUserGroupRequestModel = {
name: model.name,
editorAlias: model.editorAlias,
editorUiAlias: model.editorUiAlias,
values: model.values,
icon: model.icon,
sections: model.sections,
languages: model.languages,
hasAccessToAllLanguages: model.hasAccessToAllLanguages,
documentStartNode: model.documentStartNode ? { id: model.documentStartNode.unique } : null,
documentRootAccess: model.documentRootAccess,
mediaStartNode: model.mediaStartNode ? { id: model.mediaStartNode.unique } : null,
mediaRootAccess: model.mediaRootAccess,
permissions: model.permissions,
};
const { data, error } = await tryExecuteAndNotify(

View File

@@ -18,11 +18,6 @@ export class UmbUserGroupDetailStore extends UmbDetailStoreBase<UmbUserGroupDeta
constructor(host: UmbControllerHostElement) {
super(host, UMB_USER_GROUP_DETAIL_STORE_CONTEXT.toString());
}
withPropertyEditorUiAlias(propertyEditorUiAlias: string) {
// TODO: Use a model for the data-type tree items: ^^Most likely it should be parsed to the UmbEntityTreeStore as a generic type.
return this._data.asObservablePart((items) => items.filter((item) => item.editorUiAlias === propertyEditorUiAlias));
}
}
export const UMB_USER_GROUP_DETAIL_STORE_CONTEXT = new UmbContextToken<UmbUserGroupDetailStore>(

View File

@@ -1,5 +1,5 @@
export interface UmbUserGroupItemModel {
unique: string;
name: string;
propertyEditorUiAlias: string;
icon: string | null;
}

View File

@@ -34,6 +34,6 @@ const mapper = (item: UserGroupItemResponseModel): UmbUserGroupItemModel => {
return {
unique: item.id,
name: item.name,
propertyEditorUiAlias: item.editorUiAlias || '', // TODO: why can this be undefined or null on the server?
icon: item.icon || null,
};
};

View File

@@ -1,4 +1,6 @@
export interface UserGroupDetailModel {
import type { UmbUserGroupEntityType } from './entity.js';
export interface UmbUserGroupDetailModel {
unique: string;
entityType: UmbUserGroupEntityType;
isSystemGroup: boolean;

View File

@@ -9,9 +9,8 @@ import { css, html, customElement, state, repeat, ifDefined } from '@umbraco-cms
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UMB_DEFAULT_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
import type { UserGroupResponseModel} from '@umbraco-cms/backoffice/backend-api';
import { UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-group';
import { UmbUserGroupCollectionRepository, UmbUserGroupDetailModel } from '@umbraco-cms/backoffice/user-group';
@customElement('umb-user-collection-header')
export class UmbUserCollectionHeaderElement extends UmbLitElement {
@@ -28,10 +27,10 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
private _orderBy?: UserOrderModel;
@state()
private _userGroups: Array<UserGroupResponseModel> = [];
private _userGroups: Array<UmbUserGroupDetailModel> = [];
@state()
private _userGroupFilterSelection: Array<UserGroupResponseModel> = [];
private _userGroupFilterSelection: Array<UmbUserGroupDetailModel> = [];
#modalContext?: UmbModalManagerContext;
#collectionContext?: UmbUserCollectionContext;

View File

@@ -5,8 +5,8 @@ import { css, html, nothing, customElement, state, repeat, ifDefined } from '@um
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UMB_DEFAULT_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UserGroupResponseModel} from '@umbraco-cms/backoffice/backend-api';
import { UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import type { UmbUserGroupDetailModel } from '@umbraco-cms/backoffice/user-group';
import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-group';
@customElement('umb-user-grid-collection-view')
@@ -20,7 +20,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement {
@state()
private _loading = false;
#userGroups: Array<UserGroupResponseModel> = [];
#userGroups: Array<UmbUserGroupDetailModel> = [];
#collectionContext?: UmbUserCollectionContext;
#userGroupCollectionRepository = new UmbUserGroupCollectionRepository(this);
@@ -55,11 +55,11 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement {
}
#onSelect(user: UmbUserDetailModel) {
this.#collectionContext?.selection.select(user.id ?? '');
this.#collectionContext?.selection.select(user.unique ?? '');
}
#onDeselect(user: UmbUserDetailModel) {
this.#collectionContext?.selection.deselect(user.id ?? '');
this.#collectionContext?.selection.deselect(user.unique ?? '');
}
render() {
@@ -68,7 +68,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement {
<div id="user-grid">
${repeat(
this._users,
(user) => user.id,
(user) => user.unique,
(user) => this.#renderUserCard(user),
)}
</div>
@@ -81,8 +81,8 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement {
.name=${user.name ?? 'Unnamed user'}
selectable
?select-only=${this._selection.length > 0}
?selected=${this.#collectionContext?.selection.isSelected(user.id ?? '')}
@open=${() => this._handleOpenCard(user.id ?? '')}
?selected=${this.#collectionContext?.selection.isSelected(user.unique)}
@open=${() => this._handleOpenCard(user.unique)}
@selected=${() => this.#onSelect(user)}
@deselected=${() => this.#onDeselect(user)}>
${this.#renderUserTag(user)} ${this.#renderUserGroupNames(user)} ${this.#renderUserLoginDate(user)}
@@ -95,19 +95,19 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement {
return nothing;
}
const statusLook = getDisplayStateFromUserStatus(user.state);
const statusLook = user.state ? getDisplayStateFromUserStatus(user.state) : undefined;
return html`<uui-tag
slot="tag"
size="s"
look="${ifDefined(statusLook?.look)}"
color="${ifDefined(statusLook?.color)}">
<umb-localize key=${'user_' + statusLook.key}></umb-localize>
<umb-localize key=${'user_' + statusLook?.key}></umb-localize>
</uui-tag>`;
}
#renderUserGroupNames(user: UmbUserDetailModel) {
const userGroupNames = this.#userGroups
.filter((userGroup) => user.userGroupIds?.includes(userGroup.id!))
.filter((userGroup) => user.userGroupIds?.includes(userGroup.unique))
.map((userGroup) => userGroup.name)
.join(', ');

View File

@@ -18,7 +18,7 @@ const userStates: UmbUserDisplayStatus[] = [
export const getDisplayStateFromUserStatus = (status: UserStateModel): UmbUserDisplayStatus =>
userStates
.filter((state) => state.key === status)!
.filter((state) => state.key === status)
.map((state) => ({
...state,
key: 'state' + state.key,