diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions-modal.element.ts index e5c64d311f..f1384c9983 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/permissions/permissions-modal.element.ts @@ -1,6 +1,6 @@ import { UmbDocumentPermissionRepository } from '../../user-permissions/index.js'; import { UmbDocumentItemRepository } from '../../repository/index.js'; -import { UmbUserGroupRepository } from '@umbraco-cms/backoffice/user-group'; +import { UmbUserGroupItemRepository } from '@umbraco-cms/backoffice/user-group'; import { html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { @@ -39,7 +39,7 @@ export class UmbPermissionsModalElement extends UmbLitElement { _userGroupRefs: Array = []; #userPermissions: Array = []; - #userGroupRepository = new UmbUserGroupRepository(this); + #userGroupIemRepository = new UmbUserGroupItemRepository(this); #documentPermissionRepository = new UmbDocumentPermissionRepository(this); #documentItemRepository = new UmbDocumentItemRepository(this); #modalManagerContext?: UmbModalManagerContext; @@ -83,12 +83,12 @@ export class UmbPermissionsModalElement extends UmbLitElement { async #mapToUserGroupRefs() { const userGroupIds = [...new Set(this.#userPermissions.map((permission) => permission.target.userGroupId))]; - const { data } = await this.#userGroupRepository.requestItems(userGroupIds); + const { data } = await this.#userGroupIemRepository.requestItems(userGroupIds); const userGroups = data ?? []; this._userGroupRefs = this.#userPermissions.map((entry) => { - const userGroup = userGroups.find((userGroup) => userGroup.id == entry.target.userGroupId); + const userGroup = userGroups.find((userGroup) => userGroup.unique == entry.target.userGroupId); return { id: entry.target.userGroupId, name: userGroup?.name, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts index de473acc85..5ce04e7a9e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/repository/detail/media-detail.server.data-source.ts @@ -44,7 +44,6 @@ export class UmbMediaServerDataSource implements UmbDetailDataSource(undefined); + #currentUser = new UmbObjectState(undefined); readonly currentUser = this.#currentUser.asObservable(); - readonly languageIsoCode = this.#currentUser.asObservablePart((user) => user?.languageIsoCode ?? 'en-us'); + readonly languageIsoCode = this.#currentUser.asObservablePart((user) => user?.languageIsoCode); #authContext?: typeof UMB_AUTH_CONTEXT.TYPE; + #currentUserRepository = new UmbCurrentUserRepository(this); constructor(host: UmbControllerHost) { super(host); @@ -26,6 +26,7 @@ export class UmbCurrentUserContext extends UmbBaseController { }); this.observe(this.languageIsoCode, (currentLanguageIsoCode) => { + if (!currentLanguageIsoCode) return; umbLocalizationRegistry.loadLanguage(currentLanguageIsoCode); }); @@ -33,22 +34,23 @@ export class UmbCurrentUserContext extends UmbBaseController { } async requestCurrentUser() { - // TODO: use repository - const { data, error } = await tryExecuteAndNotify(this._host, UserResource.getUserCurrent()); - // TODO: add current user store - this.#currentUser.setValue(data); - return { data, error }; + const { data } = await this.#currentUserRepository.requestCurrentUser(); + + if (data) { + // TODO: observe current user + this.#currentUser.setValue(data); + } } /** * Checks if a user is the current user. * - * @param userId The user id to check + * @param userUnique The user id to check * @returns True if the user is the current user, otherwise false */ - async isUserCurrentUser(userId: string): Promise { + async isUserCurrentUser(userUnique: string): Promise { const currentUser = await firstValueFrom(this.currentUser); - return currentUser?.id === userId; + return currentUser?.unique === userUnique; } #observeIsAuthorized() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.repository.ts new file mode 100644 index 0000000000..3c239b15fe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.repository.ts @@ -0,0 +1,31 @@ +import { UmbCurrentUserServerDataSource } from './current-user.server.data-source.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +/** + * A repository for the current user + * @export + * @class UmbCurrentUserRepository + * @extends {UmbRepositoryBase} + */ +export class UmbCurrentUserRepository extends UmbRepositoryBase { + #currentUserSource: UmbCurrentUserServerDataSource; + + constructor(host: UmbControllerHost) { + super(host); + + this.#currentUserSource = new UmbCurrentUserServerDataSource(host); + } + + /** + * Request the current user + * @return {*} + * @memberof UmbCurrentUserRepository + */ + async requestCurrentUser() { + // TODO: add observable option + return this.#currentUserSource.getCurrentUser(); + } +} + +export default UmbCurrentUserRepository; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts new file mode 100644 index 0000000000..9613df7ffd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts @@ -0,0 +1,50 @@ +import type { UmbCurrentUserModel } from '../types.js'; +import { UserResource } from '@umbraco-cms/backoffice/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; + +/** + * A data source for the current user that fetches data from the server + * @export + * @class UmbCurrentUserServerDataSource + */ +export class UmbCurrentUserServerDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbCurrentUserServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbCurrentUserServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Get the current user + * @return {*} + * @memberof UmbCurrentUserServerDataSource + */ + async getCurrentUser() { + const { data, error } = await tryExecuteAndNotify(this.#host, UserResource.getUserCurrent()); + + if (data) { + const user: UmbCurrentUserModel = { + unique: data.id, + email: data.email, + userName: data.userName, + name: data.name, + languageIsoCode: data.languageIsoCode || 'en-us', // TODO: make global variable + documentStartNodeIds: data.documentStartNodeIds, + mediaStartNodeIds: data.mediaStartNodeIds, + avatarUrls: data.avatarUrls, + languages: data.languages, + hasAccessToAllLanguages: data.hasAccessToAllLanguages, + permissions: data.permissions, + }; + return { data: user }; + } + + return { error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/index.ts new file mode 100644 index 0000000000..a5a259f95c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbCurrentUserRepository } from './current-user.repository.js'; +export { UMB_CURRENT_USER_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/manifests.ts new file mode 100644 index 0000000000..ca6754a084 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/manifests.ts @@ -0,0 +1,13 @@ +import { UmbCurrentUserRepository } from './current-user.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_CURRENT_USER_REPOSITORY_ALIAS = 'Umb.Repository.CurrentUser'; + +const avatarRepository: ManifestRepository = { + type: 'repository', + alias: UMB_CURRENT_USER_REPOSITORY_ALIAS, + name: 'Current User Repository', + api: UmbCurrentUserRepository, +}; + +export const manifests = [avatarRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/user-create-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/user-create-modal.element.ts index 55fc354eae..418edde0e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/user-create-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/create/user-create-modal.element.ts @@ -2,12 +2,11 @@ import { UmbUserDetailRepository } from '../../repository/index.js'; import type { UmbUserGroupInputElement } from '@umbraco-cms/backoffice/user-group'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; -import type { - UmbModalManagerContext} from '@umbraco-cms/backoffice/modal'; +import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UmbModalBaseElement, UMB_MODAL_MANAGER_CONTEXT, - UMB_CREATE_USER_SUCCESS_MODAL + UMB_CREATE_USER_SUCCESS_MODAL, } from '@umbraco-cms/backoffice/modal'; @customElement('umb-user-create-modal') @@ -43,16 +42,19 @@ export class UmbUserCreateModalElement extends UmbModalBaseElement { const userGroupPicker = form.querySelector('#userGroups') as UmbUserGroupInputElement; const userGroups = userGroupPicker?.selectedIds; - // TODO: figure out when to use email or username - const { data } = await this.#userDetailRepository.create({ - name, - email, - userName: email, - userGroupIds: userGroups, - }); + const { data: userScaffold } = await this.#userDetailRepository.createScaffold(null); + if (!userScaffold) return; - if (data && data.userId && data.initialPassword) { - this.#openSuccessModal(data.userId, data.initialPassword); + userScaffold.name = name; + userScaffold.email = email; + userScaffold.userName = email; + userScaffold.userGroupIds = userGroups; + + // TODO: figure out when to use email or username + const { data } = await this.#userDetailRepository.create(userScaffold); + + if (data && data.unique && data.initialPassword) { + this.#openSuccessModal(data.unique, data.initialPassword); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/sources/user-set-group.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/sources/user-set-group.server.data-source.ts index 3eb373def2..b7630ab52c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/sources/user-set-group.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/repository/sources/user-set-group.server.data-source.ts @@ -1,4 +1,3 @@ -import type { UmbUserSetGroupDataSource } from '../../types.js'; import { UserResource } from '@umbraco-cms/backoffice/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -8,7 +7,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @export * @class UmbUserSetGroupsServerDataSource */ -export class UmbUserSetGroupsServerDataSource implements UmbUserSetGroupDataSource { +export class UmbUserSetGroupsServerDataSource { #host: UmbControllerHost; /**