This commit is contained in:
Mads Rasmussen
2024-02-02 14:12:39 +01:00
parent 738cc39da1
commit 5f3bd03f92
18 changed files with 124 additions and 127 deletions

View File

@@ -14,7 +14,7 @@ import {
// TODO: move to UI Library - entity actions should NOT be moved to UI Library but stay in an UmbTable element
export interface UmbTableItem {
id: string;
icon?: string;
icon?: string | null;
entityType?: string;
data: Array<UmbTableItemData>;
}

View File

@@ -1,7 +1,9 @@
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
export interface UmbChangePasswordModalData {
userId: string;
user: {
unique: string;
};
}
export interface UmbChangePasswordModalValue {

View File

@@ -1,18 +1,14 @@
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type {
UmbModalManagerContext} from '@umbraco-cms/backoffice/modal';
import {
UMB_CHANGE_PASSWORD_MODAL,
UMB_MODAL_MANAGER_CONTEXT,
} from '@umbraco-cms/backoffice/modal';
import { UMB_CURRENT_USER_CONTEXT, type UmbCurrentUser } from '@umbraco-cms/backoffice/current-user';
import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal';
import { UMB_CHANGE_PASSWORD_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { UMB_CURRENT_USER_CONTEXT, type UmbCurrentUserModel } from '@umbraco-cms/backoffice/current-user';
@customElement('umb-user-profile-app-profile')
export class UmbUserProfileAppProfileElement extends UmbLitElement {
@state()
private _currentUser?: UmbCurrentUser;
private _currentUser?: UmbCurrentUserModel;
#modalManagerContext?: UmbModalManagerContext;
#currentUserContext?: typeof UMB_CURRENT_USER_CONTEXT.TYPE;
@@ -45,15 +41,18 @@ export class UmbUserProfileAppProfileElement extends UmbLitElement {
private _edit() {
if (!this._currentUser) return;
history.pushState(null, '', 'section/user-management/view/users/user/' + this._currentUser.id); //TODO Change to a tag with href and make dynamic
history.pushState(null, '', 'section/user-management/view/users/user/' + this._currentUser.unique); //TODO Change to a tag with href and make dynamic
//TODO Implement modal routing for the current-user-modal, so that the modal closes when navigating to the edit profile page
}
private _changePassword() {
if (!this.#modalManagerContext) return;
if (!this._currentUser) throw new Error('Current User not found');
this.#modalManagerContext.open(UMB_CHANGE_PASSWORD_MODAL, {
data: {
userId: this._currentUser?.id ?? '',
user: {
unique: this._currentUser.unique,
},
},
});
}

View File

@@ -1,14 +1,10 @@
import { UmbUserItemRepository } from '../../user/repository/item/user-item.repository.js';
import { UMB_CURRENT_USER_CONTEXT } from '../../current-user/current-user.context.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { CSSResultGroup} from '@umbraco-cms/backoffice/external/lit';
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import type {
UmbChangePasswordModalData,
UmbChangePasswordModalValue} from '@umbraco-cms/backoffice/modal';
import {
UmbModalBaseElement,
} from '@umbraco-cms/backoffice/modal';
import type { UmbChangePasswordModalData, UmbChangePasswordModalValue } from '@umbraco-cms/backoffice/modal';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
@customElement('umb-change-password-modal')
export class UmbChangePasswordModalElement extends UmbModalBaseElement<
@@ -58,7 +54,7 @@ export class UmbChangePasswordModalElement extends UmbModalBaseElement<
}
async #setIsCurrentUser() {
if (!this.data?.userId) {
if (!this.data?.user.unique) {
this._isCurrentUser = false;
return;
}
@@ -68,12 +64,12 @@ export class UmbChangePasswordModalElement extends UmbModalBaseElement<
return;
}
this._isCurrentUser = await this.#currentUserContext.isUserCurrentUser(this.data.userId);
this._isCurrentUser = await this.#currentUserContext.isUserCurrentUser(this.data.user.unique);
}
protected async firstUpdated(): Promise<void> {
if (!this.data?.userId) return;
const { data } = await this.#userItemRepository.requestItems([this.data.userId]);
if (!this.data?.user.unique) return;
const { data } = await this.#userItemRepository.requestItems([this.data.user.unique]);
if (data) {
const userName = data[0].name;

View File

@@ -1,6 +1,6 @@
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 { UmbUserGroupDetailStore } from '../../repository/index.js';
import { UMB_USER_GROUP_DETAIL_STORE_CONTEXT } from '../../repository/index.js';
import type { UmbUserGroupCollectionFilterModel } from '../types.js';
import { UmbUserGroupCollectionServerDataSource } from './user-group-collection.server.data-source.js';
import type { UmbCollectionDataSource, UmbCollectionRepository } from '@umbraco-cms/backoffice/repository';
@@ -10,14 +10,14 @@ import { UmbBaseController } from '@umbraco-cms/backoffice/class-api';
export class UmbUserGroupCollectionRepository extends UmbBaseController implements UmbCollectionRepository {
#init;
#detailStore?: UmbUserGroupStore;
#detailStore?: UmbUserGroupDetailStore;
#collectionSource: UmbCollectionDataSource<UmbUserGroupDetailModel>;
constructor(host: UmbControllerHost) {
super(host);
this.#collectionSource = new UmbUserGroupCollectionServerDataSource(this._host);
this.#init = this.consumeContext(UMB_USER_GROUP_STORE_CONTEXT, (instance) => {
this.#init = this.consumeContext(UMB_USER_GROUP_DETAIL_STORE_CONTEXT, (instance) => {
this.#detailStore = instance;
}).asPromise();
}

View File

@@ -1,8 +1,8 @@
import type { UmbUserGroupCollectionFilterModel } from '../../types.js';
import type { UmbUserGroupCollectionFilterModel } from '../types.js';
import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/repository';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
import type { UserGroupResponseModel} from '@umbraco-cms/backoffice/backend-api';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UserGroupResource } from '@umbraco-cms/backoffice/backend-api';
/**
@@ -23,8 +23,20 @@ export class UmbUserGroupCollectionServerDataSource implements UmbCollectionData
this.#host = host;
}
getCollection(filter: UmbUserGroupCollectionFilterModel) {
// TODO: Switch this to the filter endpoint when available
return tryExecuteAndNotify(this.#host, UserGroupResource.getUserGroup({}));
async getCollection(filter: UmbUserGroupCollectionFilterModel) {
const { data, error } = await tryExecuteAndNotify(
this.#host,
UserGroupResource.getUserGroup({ skip: filter.skip, take: filter.take }),
);
if (data) {
const mappedItems = data.items.map((item) => {
return {
...item,
};
});
}
return { error };
}
}

View File

@@ -3,7 +3,6 @@ import { css, html, customElement, state } from '@umbraco-cms/backoffice/externa
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection';
import { UMB_DEFAULT_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import '../components/user-group-table-name-column-layout.element.js';
import '../components/user-group-table-sections-column-layout.element.js';
@@ -16,6 +15,7 @@ import type {
UmbTableItem,
UmbTableSelectedEvent,
} from '@umbraco-cms/backoffice/components';
import type { UmbUserGroupDetailModel } from '../../types.js';
@customElement('umb-user-group-collection-table-view')
export class UmbUserGroupCollectionTableViewElement extends UmbLitElement {
@@ -74,29 +74,29 @@ export class UmbUserGroupCollectionTableViewElement extends UmbLitElement {
});
}
private _createTableItems(userGroups: Array<UserGroupResponseModel>) {
private _createTableItems(userGroups: Array<UmbUserGroupDetailModel>) {
this._tableItems = userGroups.map((userGroup) => {
return {
id: userGroup.id || '',
icon: userGroup.icon || '',
id: userGroup.unique,
icon: userGroup.icon,
data: [
{
columnAlias: 'userGroupName',
value: {
name: userGroup.name || '',
name: userGroup.name,
},
},
{
columnAlias: 'userGroupSections',
value: userGroup.sections || [],
value: userGroup.sections,
},
{
columnAlias: 'userGroupContentStartNode',
value: userGroup.documentStartNode?.id || this.localize.term('content_contentRoot'),
value: userGroup.documentStartNode?.unique || this.localize.term('content_contentRoot'),
},
{
columnAlias: 'userGroupMediaStartNode',
value: userGroup.mediaStartNode?.id || this.localize.term('media_mediaRoot'),
value: userGroup.mediaStartNode?.unique || this.localize.term('media_mediaRoot'),
},
],
};

View File

@@ -1,10 +1,10 @@
import { UMB_USER_GROUP_ITEM_REPOSITORY_ALIAS, type UmbUserGroupItemModel } from '../../repository/index.js';
import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UMB_USER_GROUP_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
import type { UserGroupItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
export class UmbUserGroupPickerContext extends UmbPickerInputContext<UserGroupItemResponseModel> {
export class UmbUserGroupPickerContext extends UmbPickerInputContext<UmbUserGroupItemModel> {
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Repository.UserGroup', UMB_USER_GROUP_PICKER_MODAL);
super(host, UMB_USER_GROUP_ITEM_REPOSITORY_ALIAS, UMB_USER_GROUP_PICKER_MODAL);
}
}

View File

@@ -1,8 +1,8 @@
import type { UmbUserGroupItemModel } from '../../repository/index.js';
import { UmbUserGroupPickerContext } from './user-group-input.context.js';
import { css, html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit';
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UserGroupItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
@customElement('umb-user-group-input')
@@ -67,7 +67,7 @@ export class UmbUserGroupInputElement extends FormControlMixin(UmbLitElement) {
}
@state()
private _items?: Array<UserGroupItemResponseModel>;
private _items?: Array<UmbUserGroupItemModel>;
#pickerContext = new UmbUserGroupPickerContext(this);
@@ -111,7 +111,7 @@ export class UmbUserGroupInputElement extends FormControlMixin(UmbLitElement) {
`;
}
private _renderItem(item: UserGroupItemResponseModel) {
private _renderItem(item: UmbUserGroupItemModel) {
if (!item.id) return;
return html`
<umb-user-group-ref name="${ifDefined(item.name)}">

View File

@@ -1,10 +1,10 @@
import { UmbUserGroupCollectionRepository } from '../../collection/repository/index.js';
import type { UmbUserGroupDetailModel } from '../../types.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils';
import type { UMB_USER_GROUP_PICKER_MODAL} from '@umbraco-cms/backoffice/modal';
import type { UMB_USER_GROUP_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import type { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui';
import { UmbSelectedEvent, UmbDeselectedEvent } from '@umbraco-cms/backoffice/event';
@customElement('umb-user-group-picker-modal')
@@ -13,7 +13,7 @@ export class UmbUserGroupPickerModalElement extends UmbModalBaseElement<
(typeof UMB_USER_GROUP_PICKER_MODAL)['VALUE']
> {
@state()
private _userGroups: Array<UserGroupResponseModel> = [];
private _userGroups: Array<UmbUserGroupDetailModel> = [];
#selectionManager = new UmbSelectionManager(this);
#userGroupCollectionRepository = new UmbUserGroupCollectionRepository(this);
@@ -37,20 +37,20 @@ export class UmbUserGroupPickerModalElement extends UmbModalBaseElement<
this.observe(asObservable(), (items) => (this._userGroups = items), 'umbUserGroupsObserver');
}
#onSelected(event: UUIMenuItemEvent, item: UserGroupResponseModel) {
if (!item.id) throw new Error('User group id is required');
#onSelected(event: UUIMenuItemEvent, item: UmbUserGroupDetailModel) {
if (!item.unique) throw new Error('User group unique is required');
event.stopPropagation();
this.#selectionManager.select(item.id);
this.#selectionManager.select(item.unique);
this.requestUpdate();
this.modalContext?.dispatchEvent(new UmbSelectedEvent(item.id));
this.modalContext?.dispatchEvent(new UmbSelectedEvent(item.unique));
}
#onDeselected(event: UUIMenuItemEvent, item: UserGroupResponseModel) {
if (!item.id) throw new Error('User group id is required');
#onDeselected(event: UUIMenuItemEvent, item: UmbUserGroupDetailModel) {
if (!item.unique) throw new Error('User group unique is required');
event.stopPropagation();
this.#selectionManager.deselect(item.id);
this.#selectionManager.deselect(item.unique);
this.requestUpdate();
this.modalContext?.dispatchEvent(new UmbDeselectedEvent(item.id));
this.modalContext?.dispatchEvent(new UmbDeselectedEvent(item.unique));
}
render() {
@@ -64,7 +64,7 @@ export class UmbUserGroupPickerModalElement extends UmbModalBaseElement<
selectable
@selected=${(event: UUIMenuItemEvent) => this.#onSelected(event, item)}
@deselected=${(event: UUIMenuItemEvent) => this.#onDeselected(event, item)}
?selected=${this.#selectionManager.isSelected(item.id!)}>
?selected=${this.#selectionManager.isSelected(item.unique)}>
<uui-icon .name=${item.icon || null} slot="icon"></uui-icon>
</uui-menu-item>
`,

View File

@@ -1,2 +1,3 @@
export { UmbUserGroupDetailRepository } from './user-group-detail.repository.js';
export { UMB_USER_GROUP_DETAIL_REPOSITORY_ALIAS } from './manifests.js';
export { UMB_USER_GROUP_DETAIL_STORE_CONTEXT } from './user-group-detail.store.js';

View File

@@ -1,13 +1,13 @@
import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from '../user-group-workspace.context.js';
import type { UmbUserGroupDetailModel } from '../../types.js';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@customElement('umb-user-group-granular-permission-list')
export class UmbUserGroupGranularPermissionListElement extends UmbLitElement {
@state()
private _userGroup?: UserGroupResponseModel;
private _userGroup?: UmbUserGroupDetailModel;
#workspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE;

View File

@@ -1,3 +1,4 @@
import type { UmbUserGroupDetailModel } from '../index.js';
import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js';
import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context.js';
import type { UmbUserInputElement } from '@umbraco-cms/backoffice/user';
@@ -5,7 +6,6 @@ import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document';
import type { UmbInputSectionElement } from '@umbraco-cms/backoffice/components';
@@ -18,10 +18,10 @@ import './components/user-group-granular-permission-list.element.js';
@customElement('umb-user-group-workspace-editor')
export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
@state()
private _userGroup?: UserGroupResponseModel;
private _userGroup?: UmbUserGroupDetailModel;
@state()
private _userIds?: Array<string>;
private _userUniques?: Array<string>;
#workspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE;
@@ -31,7 +31,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
this.consumeContext(UMB_USER_GROUP_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.observe(this.#workspaceContext.data, (userGroup) => (this._userGroup = userGroup), 'umbUserGroupObserver');
this.observe(this.#workspaceContext.userIds, (userIds) => (this._userIds = userIds), 'umbUserIdsObserver');
this.observe(this.#workspaceContext.userIds, (userIds) => (this._userUniques = userIds), 'umbUserIdsObserver');
});
}
@@ -118,7 +118,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
<umb-input-document
slot="editor"
max="1"
.selectedIds=${this._userGroup.documentStartNodeId ? [this._userGroup.documentStartNodeId] : []}
.selectedIds=${this._userGroup.documentStartNode?.unique ? [this._userGroup.documentStartNode.unique] : []}
@change=${this.#onDocumentStartNodeChange}></umb-input-document>
</umb-property-layout>
<umb-property-layout
@@ -127,7 +127,7 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
<umb-input-media
slot="editor"
max="1"
.selectedIds=${this._userGroup.mediaStartNodeId ? [this._userGroup.mediaStartNodeId] : []}
.selectedIds=${this._userGroup.mediaStartNode?.unique ? [this._userGroup.mediaStartNode.unique] : []}
@change=${this.#onMediaStartNodeChange}></umb-input-media>
</umb-property-layout>
</uui-box>
@@ -149,12 +149,12 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
#renderRightColumn() {
return html`<uui-box>
<div slot="headline"><umb-localize key="sections_users"></umb-localize></div>
<umb-user-input @change=${this.#onUsersChange} .selectedIds=${this._userIds ?? []}></umb-user-input>
<umb-user-input @change=${this.#onUsersChange} .selectedIds=${this._userUniques ?? []}></umb-user-input>
</uui-box>
<uui-box headline="Actions">
<umb-entity-action-list
.entityType=${UMB_USER_GROUP_ENTITY_TYPE}
.unique=${this._userGroup?.id}></umb-entity-action-list
.unique=${this._userGroup?.unique}></umb-entity-action-list
></uui-box>`;
}

View File

@@ -1,23 +1,21 @@
import { UmbUserGroupRepository } from '../repository/user-group.repository.js';
import { UmbUserGroupDetailRepository } from '../repository/detail/index.js';
import { UmbUserRepository } from '../../user/repository/user.repository.js';
import type {
UmbSaveableWorkspaceContextInterface} from '@umbraco-cms/backoffice/workspace';
import {
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import type { UmbUserGroupDetailModel } from '../types.js';
import { UMB_USER_GROUP_ENTITY_TYPE } from '../entity.js';
import type { UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
import { UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbUserGroupWorkspaceContext
extends UmbEditableWorkspaceContextBase<UserGroupResponseModel>
extends UmbEditableWorkspaceContextBase<UmbUserGroupDetailModel>
implements UmbSaveableWorkspaceContextInterface
{
//
public readonly repository: UmbUserGroupRepository = new UmbUserGroupRepository(this);
public readonly repository: UmbUserGroupDetailRepository = new UmbUserGroupDetailRepository(this);
#data = new UmbObjectState<UserGroupResponseModel | undefined>(undefined);
#data = new UmbObjectState<UmbUserGroupDetailModel | undefined>(undefined);
data = this.#data.asObservable();
#userIds = new UmbArrayState<string>([], (x) => x);
@@ -34,43 +32,28 @@ export class UmbUserGroupWorkspaceContext
async create() {
const { data } = await this.repository.createScaffold(null);
this.setIsNew(true);
// TODO: Should the data be the base model or the presentation model?
this.#data.setValue(data as unknown as UserGroupResponseModel);
this.#data.setValue(data);
return { data };
}
async load(id: string) {
const { data } = await this.repository.requestById(id);
async load(unique: string) {
const { data } = await this.repository.requestByUnique(unique);
if (data) {
this.setIsNew(false);
this.#data.update(data);
}
/* TODO: implement user selection for a user group
const { data: users } = await this.#userRepository.filterCollection({
skip: 0,
take: 10000000,
userGroupIds: [id],
});
if (!users) return;
const ids = users.items.map((user) => user.id ?? '');
this.#userIds.next(ids);
*/
}
getEntityId(): string | undefined {
throw new Error('Method not implemented.');
getEntityId() {
return this.getData()?.unique;
}
getEntityType(): string {
return 'user-group';
return UMB_USER_GROUP_ENTITY_TYPE;
}
getData(): UserGroupResponseModel | undefined {
throw new Error('Method not implemented.');
getData() {
return this.#data.getValue();
}
async save() {
@@ -79,8 +62,8 @@ export class UmbUserGroupWorkspaceContext
//TODO: Could we clean this code up?
if (this.getIsNew()) {
await this.repository.create(this.#data.value);
} else if (this.#data.value.id) {
await this.repository.save(this.#data.value.id, this.#data.value);
} else if (this.#data.value.unique) {
await this.repository.save(this.#data.value);
} else return;
//TODO: This next user-group section kinda works. But it will overwrite the entire user-group list on the user.
@@ -89,7 +72,7 @@ export class UmbUserGroupWorkspaceContext
//TODO: or the new user-group id needs to be removed from the existing list.
const userIds = this.#userIds.getValue();
const userGroupIds = [this.#data.getValue()?.id ?? ''];
const userGroupIds = [this.#data.getValue()?.unique ?? ''];
if (userIds.length > 0 && userGroupIds.length > 0) {
await this.#userRepository.setUserGroups(userIds, userGroupIds);
@@ -107,7 +90,7 @@ export class UmbUserGroupWorkspaceContext
await this.repository.delete(id);
}
updateProperty<Alias extends keyof UserGroupResponseModel>(alias: Alias, value: UserGroupResponseModel[Alias]) {
updateProperty<Alias extends keyof UmbUserGroupDetailModel>(alias: Alias, value: UmbUserGroupDetailModel[Alias]) {
this.#data.update({ [alias]: value });
}

View File

@@ -9,8 +9,10 @@ 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 { UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbUserGroupCollectionRepository, UmbUserGroupDetailModel } from '@umbraco-cms/backoffice/user-group';
import type { UserOrderModel } 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-collection-header')
export class UmbUserCollectionHeaderElement extends UmbLitElement {
@@ -20,9 +22,6 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
@state()
private _stateFilterSelection: Array<UserStateModel> = [];
@state()
private _orderByOptions: Array<UserOrderModel> = Object.values(UserOrderModel);
@state()
private _orderBy?: UserOrderModel;
@@ -109,18 +108,18 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
#onUserGroupFilterChange(event: UUIBooleanInputEvent) {
const target = event.currentTarget as UUICheckboxElement;
const item = this._userGroups.find((group) => group.id === target.value);
const item = this._userGroups.find((group) => group.unique === target.value);
if (!item) return;
if (target.checked) {
this._userGroupFilterSelection = [...this._userGroupFilterSelection, item];
} else {
this._userGroupFilterSelection = this._userGroupFilterSelection.filter((group) => group.id !== item.id);
this._userGroupFilterSelection = this._userGroupFilterSelection.filter((group) => group.unique !== item.unique);
}
const ids = this._userGroupFilterSelection.map((group) => group.id!);
this.#collectionContext?.setUserGroupFilter(ids);
const uniques = this._userGroupFilterSelection.map((group) => group.unique);
this.#collectionContext?.setUserGroupFilter(uniques);
}
#getUserGroupFilterLabel() {
@@ -183,11 +182,11 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement {
<div class="filter-dropdown">
${repeat(
this._userGroups,
(group) => group.id,
(group) => group.unique,
(group) => html`
<uui-checkbox
label=${ifDefined(group.name)}
value=${ifDefined(group.id)}
value=${ifDefined(group.unique)}
@change=${this.#onUserGroupFilterChange}></uui-checkbox>
`,
)}

View File

@@ -13,11 +13,11 @@ import type {
} from '@umbraco-cms/backoffice/components';
import { UMB_DEFAULT_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UmbUserGroupRepository } from '@umbraco-cms/backoffice/user-group';
import type { UmbUserGroupItemModel } from '@umbraco-cms/backoffice/user-group';
import { UmbUserGroupItemRepository } from '@umbraco-cms/backoffice/user-group';
import './column-layouts/name/user-table-name-column-layout.element.js';
import './column-layouts/status/user-table-status-column-layout.element.js';
import type { UserGroupItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
@customElement('umb-user-table-collection-view')
export class UmbUserTableCollectionViewElement extends UmbLitElement {
@@ -52,9 +52,9 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement {
private _tableItems: Array<UmbTableItem> = [];
@state()
private _userGroupItems: Array<UserGroupItemResponseModel> = [];
private _userGroupItems: Array<UmbUserGroupItemModel> = [];
#UmbUserGroupRepository = new UmbUserGroupRepository(this);
#userGroupItemRepository = new UmbUserGroupItemRepository(this);
@state()
private _users: Array<UmbUserDetailModel> = [];
@@ -87,8 +87,8 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement {
async #observeUserGroups() {
if (this._users.length === 0) return;
const userGroupsIds = [...new Set(this._users.flatMap((user) => user.userGroupIds ?? []))];
const { asObservable } = await this.#UmbUserGroupRepository.requestItems(userGroupsIds);
const userGroupsIds = [...new Set(this._users.flatMap((user) => user.userGroupIds))];
const { asObservable } = await this.#userGroupItemRepository.requestItems(userGroupsIds);
this.observe(
asObservable(),
(userGroups) => {
@@ -99,10 +99,10 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement {
);
}
#getUserGroupNames(ids: Array<string>) {
return ids
.map((id: string) => {
return this._userGroupItems.find((x) => x.id === id)?.name;
#getUserGroupNames(uniques: Array<string>) {
return uniques
.map((unique: string) => {
return this._userGroupItems.find((x) => x.unique === unique)?.name;
})
.join(', ');
}

View File

@@ -23,7 +23,9 @@ export class UmbChangeUserPasswordEntityAction extends UmbEntityActionBase<UmbCh
const modalContext = this.#modalManager.open(UMB_CHANGE_PASSWORD_MODAL, {
data: {
userId: this.unique,
user: {
unique: this.unique,
},
},
});

View File

@@ -1,3 +1,6 @@
import { UmbEnableUserRepository } from './enable-user.repository.js';
import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
export const UMB_ENABLE_USER_REPOSITORY_ALIAS = 'Umb.Repository.User.Enable';
const enableRepository: ManifestRepository = {
type: 'repository',