diff --git a/src/mocks/data/user/user.db.ts b/src/mocks/data/user/user.db.ts index 813d4b695e..dad74c3e70 100644 --- a/src/mocks/data/user/user.db.ts +++ b/src/mocks/data/user/user.db.ts @@ -153,13 +153,15 @@ class UmbUserData extends UmbEntityData { * @param {InviteUserRequestModel} data * @memberof UmbUserData */ - invite(data: InviteUserRequestModel): void { + invite(data: InviteUserRequestModel) { const invitedUser = { - status: UserStateModel.INVITED, ...data, + state: UserStateModel.INVITED, }; - this.createUser(invitedUser); + const response = this.createUser(invitedUser); + + return { userId: response.userId }; } filter(options: any): PagedUserResponseModel { diff --git a/src/mocks/handlers/user/invite.handlers.ts b/src/mocks/handlers/user/invite.handlers.ts index b03239b043..42e8ba2b2c 100644 --- a/src/mocks/handlers/user/invite.handlers.ts +++ b/src/mocks/handlers/user/invite.handlers.ts @@ -4,17 +4,21 @@ import { UMB_SLUG } from './slug.js'; import { InviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; +const inviteSlug = `${UMB_SLUG}/invite`; + export const handlers = [ - rest.post(umbracoPath(`${UMB_SLUG}/invite`), async (req, res, ctx) => { + rest.post(umbracoPath(`${inviteSlug}`), async (req, res, ctx) => { const data = await req.json(); if (!data) return; - umbUsersData.invite(data); + const { userId } = umbUsersData.invite(data); - return res(ctx.status(200)); + if (!userId) return res(ctx.status(400)); + + return res(ctx.status(201), ctx.set('Location', userId)); }), - rest.post(umbracoPath(`${UMB_SLUG}/invite/resend`), async (req, res, ctx) => { + rest.post(umbracoPath(`${inviteSlug}/resend`), async (req, res, ctx) => { const data = await req.json(); if (!data) return; diff --git a/src/packages/core/modal/modal-element.element.ts b/src/packages/core/modal/modal-element.element.ts index 12c47a89c2..98a5792db3 100644 --- a/src/packages/core/modal/modal-element.element.ts +++ b/src/packages/core/modal/modal-element.element.ts @@ -27,4 +27,22 @@ export abstract class UmbModalBaseElement< public set _value(value: ModalValueType) { this.modalContext?.setValue(value); } + + /** + * Submits the modal + * @protected + * @memberof UmbModalBaseElement + */ + protected _submitModal() { + this.modalContext?.submit(this._value); + } + + /** + * Rejects the modal + * @protected + * @memberof UmbModalBaseElement + */ + protected _rejectModal() { + this.modalContext?.reject(); + } } diff --git a/src/packages/core/modal/token/index.ts b/src/packages/core/modal/token/index.ts index 0299bedaaf..85671dca66 100644 --- a/src/packages/core/modal/token/index.ts +++ b/src/packages/core/modal/token/index.ts @@ -15,7 +15,6 @@ export * from './examine-fields-settings-modal.token.js'; export * from './export-dictionary-modal.token.js'; export * from './icon-picker-modal.token.js'; export * from './import-dictionary-modal.token.js'; -export * from './invite-user-modal.token.js'; export * from './language-picker-modal.token.js'; export * from './link-picker-modal.token.js'; export * from './media-tree-picker-modal.token.js'; @@ -37,4 +36,3 @@ export * from './data-type-picker-flow-modal.token.js'; export * from './data-type-picker-flow-data-type-picker-modal.token.js'; export * from './entity-user-permission-settings-modal.token.js'; export * from './permissions-modal.token.js'; -export * from './resend-invite-to-user-modal.token.js'; diff --git a/src/packages/core/modal/token/user-picker-modal.token.ts b/src/packages/core/modal/token/user-picker-modal.token.ts index 45fb8884c3..3c96fffcd4 100644 --- a/src/packages/core/modal/token/user-picker-modal.token.ts +++ b/src/packages/core/modal/token/user-picker-modal.token.ts @@ -1,7 +1,7 @@ -import { UmbUserDetail } from '@umbraco-cms/backoffice/user'; +import { UmbUserDetailModel } from '@umbraco-cms/backoffice/user'; import { UmbModalToken, UmbPickerModalData } from '@umbraco-cms/backoffice/modal'; -export type UmbUserPickerModalData = UmbPickerModalData; +export type UmbUserPickerModalData = UmbPickerModalData; export interface UmbUserPickerModalValue { selection: Array; diff --git a/src/packages/user/user/collection/action/manifests.ts b/src/packages/user/user/collection/action/manifests.ts index 5e28e1c338..84999d72b4 100644 --- a/src/packages/user/user/collection/action/manifests.ts +++ b/src/packages/user/user/collection/action/manifests.ts @@ -1,5 +1,4 @@ import { UmbCreateUserCollectionAction } from './create-user.collection-action.js'; -import { UmbInviteUserCollectionAction } from './invite-user.collection-action.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -21,22 +20,4 @@ export const createManifest: ManifestTypes = { ], }; -export const inviteManifest: ManifestTypes = { - type: 'collectionAction', - kind: 'button', - name: 'Invite User Collection Action', - alias: 'Umb.CollectionAction.User.Invite', - api: UmbInviteUserCollectionAction, - weight: 100, - meta: { - label: 'Invite', - }, - conditions: [ - { - alias: UMB_COLLECTION_ALIAS_CONDITION, - match: 'Umb.Collection.User', - }, - ], -}; - -export const manifests = [createManifest, inviteManifest]; +export const manifests = [createManifest]; diff --git a/src/packages/user/user/collection/repository/user-collection.server.data-source.ts b/src/packages/user/user/collection/repository/user-collection.server.data-source.ts index 436fef7320..e9018635a7 100644 --- a/src/packages/user/user/collection/repository/user-collection.server.data-source.ts +++ b/src/packages/user/user/collection/repository/user-collection.server.data-source.ts @@ -1,4 +1,5 @@ -import { UMB_USER_ENTITY_TYPE, type UmbUserCollectionFilterModel, type UmbUserDetail } from '../../types.js'; +import { type UmbUserCollectionFilterModel, type UmbUserDetailModel } from '../../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import { UmbCollectionDataSource, extendDataSourcePagedResponseData } from '@umbraco-cms/backoffice/repository'; import { UserResource } from '@umbraco-cms/backoffice/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -10,7 +11,7 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * @class UmbUserCollectionServerDataSource * @implements {UmbCollectionDataSource} */ -export class UmbUserCollectionServerDataSource implements UmbCollectionDataSource { +export class UmbUserCollectionServerDataSource implements UmbCollectionDataSource { #host: UmbControllerHost; /** @@ -30,7 +31,7 @@ export class UmbUserCollectionServerDataSource implements UmbCollectionDataSourc */ async getCollection(filter: UmbUserCollectionFilterModel) { const response = await tryExecuteAndNotify(this.#host, UserResource.getUserFilter(filter)); - return extendDataSourcePagedResponseData(response, { + return extendDataSourcePagedResponseData(response, { entityType: UMB_USER_ENTITY_TYPE, }); } diff --git a/src/packages/user/user/collection/user-collection-header.element.ts b/src/packages/user/user/collection/user-collection-header.element.ts index 5e6108a011..a5bfce4cb4 100644 --- a/src/packages/user/user/collection/user-collection-header.element.ts +++ b/src/packages/user/user/collection/user-collection-header.element.ts @@ -7,14 +7,8 @@ import { } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { UmbDropdownElement } from '@umbraco-cms/backoffice/components'; import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection'; -import { - UMB_CREATE_USER_MODAL, - UMB_INVITE_USER_MODAL, - UMB_MODAL_MANAGER_CONTEXT_TOKEN, - UmbModalManagerContext, -} from '@umbraco-cms/backoffice/modal'; +import { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UserGroupResponseModel, UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-group'; @@ -72,10 +66,6 @@ export class UmbUserCollectionHeaderElement extends UmbLitElement { this.#inputTimer = setTimeout(() => this.#collectionContext?.setFilter({ filter }), this.#inputTimerAmount); } - #onInviteUserClick() { - this.#modalContext?.open(UMB_INVITE_USER_MODAL); - } - #onStateFilterChange(event: UUIBooleanInputEvent) { event.stopPropagation(); const target = event.currentTarget as UUICheckboxElement; diff --git a/src/packages/user/user/collection/user-collection.context.ts b/src/packages/user/user/collection/user-collection.context.ts index 58623f484d..b14a2521d3 100644 --- a/src/packages/user/user/collection/user-collection.context.ts +++ b/src/packages/user/user/collection/user-collection.context.ts @@ -1,9 +1,12 @@ -import { UmbUserCollectionFilterModel, UmbUserDetail } from '../types.js'; +import { UmbUserCollectionFilterModel, UmbUserDetailModel } from '../types.js'; import { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection'; import { UserOrderModel, UserStateModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -export class UmbUserCollectionContext extends UmbDefaultCollectionContext { +export class UmbUserCollectionContext extends UmbDefaultCollectionContext< + UmbUserDetailModel, + UmbUserCollectionFilterModel +> { constructor(host: UmbControllerHostElement) { super(host, { pageSize: 50 }); } diff --git a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts index 817bc7040e..d1e320feec 100644 --- a/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts +++ b/src/packages/user/user/collection/views/grid/user-grid-collection-view.element.ts @@ -1,6 +1,6 @@ import { getDisplayStateFromUserStatus } from '../../../../utils.js'; import { UmbUserCollectionContext } from '../../user-collection.context.js'; -import { type UmbUserDetail } from '../../../types.js'; +import { type UmbUserDetailModel } from '../../../types.js'; import { css, html, nothing, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection'; @@ -11,7 +11,7 @@ import { UmbUserGroupCollectionRepository } from '@umbraco-cms/backoffice/user-g @customElement('umb-user-grid-collection-view') export class UmbUserGridCollectionViewElement extends UmbLitElement { @state() - private _users: Array = []; + private _users: Array = []; @state() private _selection: Array = []; @@ -53,11 +53,11 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { history.pushState(null, '', 'section/user-management/view/users/user/' + id); //TODO Change to a tag with href and make dynamic } - #onSelect(user: UmbUserDetail) { + #onSelect(user: UmbUserDetailModel) { this.#collectionContext?.selection.select(user.id ?? ''); } - #onDeselect(user: UmbUserDetail) { + #onDeselect(user: UmbUserDetailModel) { this.#collectionContext?.selection.deselect(user.id ?? ''); } @@ -74,7 +74,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { `; } - #renderUserCard(user: UmbUserDetail) { + #renderUserCard(user: UmbUserDetailModel) { return html` `; } - #renderUserGroupNames(user: UmbUserDetail) { + #renderUserGroupNames(user: UmbUserDetailModel) { const userGroupNames = this.#userGroups .filter((userGroup) => user.userGroupIds?.includes(userGroup.id!)) .map((userGroup) => userGroup.name) @@ -113,7 +113,7 @@ export class UmbUserGridCollectionViewElement extends UmbLitElement { return html`
${userGroupNames}
`; } - #renderUserLoginDate(user: UmbUserDetail) { + #renderUserLoginDate(user: UmbUserDetailModel) { if (!user.lastLoginDate) { return html``; } diff --git a/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts b/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts index 8654d7674a..99fea4b918 100644 --- a/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts +++ b/src/packages/user/user/collection/views/table/user-table-collection-view.element.ts @@ -1,5 +1,5 @@ import { UmbUserCollectionContext } from '../../user-collection.context.js'; -import type { UmbUserDetail } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../types.js'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { @@ -57,7 +57,7 @@ export class UmbUserTableCollectionViewElement extends UmbLitElement { #UmbUserGroupRepository = new UmbUserGroupRepository(this); @state() - private _users: Array = []; + private _users: Array = []; @state() private _selection: Array = []; diff --git a/src/packages/user/user/conditions/manifests.ts b/src/packages/user/user/conditions/manifests.ts index ae62cb76a3..15d506c0c8 100644 --- a/src/packages/user/user/conditions/manifests.ts +++ b/src/packages/user/user/conditions/manifests.ts @@ -1,13 +1,11 @@ import { manifest as userAllowDisableActionManifest } from './user-allow-disable-action.condition.js'; import { manifest as userAllowEnableActionManifest } from './user-allow-enable-action.condition.js'; import { manifest as userAllowUnlockActionManifest } from './user-allow-unlock-action.condition.js'; -import { manifest as userAllowResendInviteActionManifest } from './user-allow-resend-invite-action.condition.js'; import { manifest as userAllowDeleteActionManifest } from './user-allow-delete-action.condition.js'; export const manifests = [ userAllowDisableActionManifest, userAllowEnableActionManifest, userAllowUnlockActionManifest, - userAllowResendInviteActionManifest, userAllowDeleteActionManifest, ]; diff --git a/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/packages/user/user/conditions/user-allow-action-base.condition.ts index 3955f4e1d5..d7402c1ec6 100644 --- a/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -1,4 +1,4 @@ -import { UmbUserDetail } from '../types.js'; +import { UmbUserDetailModel } from '../types.js'; import { UmbUserWorkspaceContext } from '../workspace/user-workspace.context.js'; import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; import { isCurrentUser } from '@umbraco-cms/backoffice/current-user'; @@ -13,7 +13,7 @@ export class UmbUserActionConditionBase extends UmbBaseController implements Umb config: UmbConditionConfigBase; permitted = false; #onChange: () => void; - protected userData?: UmbUserDetail; + protected userData?: UmbUserDetailModel; constructor(args: UmbConditionControllerArguments) { super(args.host); diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index d19de7414a..7722238f39 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -2,16 +2,14 @@ import { UMB_CHANGE_USER_PASSWORD_REPOSITORY_ALIAS, UMB_DISABLE_USER_REPOSITORY_ALIAS, UMB_ENABLE_USER_REPOSITORY_ALIAS, - UMB_INVITE_USER_REPOSITORY_ALIAS, UMB_UNLOCK_USER_REPOSITORY_ALIAS, UMB_USER_REPOSITORY_ALIAS, } from '../repository/manifests.js'; -import { UMB_USER_ENTITY_TYPE } from '../index.js'; +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { UmbDisableUserEntityAction } from './disable/disable-user.action.js'; import { UmbEnableUserEntityAction } from './enable/enable-user.action.js'; import { UmbChangeUserPasswordEntityAction } from './change-password/change-user-password.action.js'; import { UmbUnlockUserEntityAction } from './unlock/unlock-user.action.js'; -import { UmbResendInviteToUserEntityAction } from './resend-invite/resend-invite-to-user.action.js'; import { UmbDeleteEntityAction } from '@umbraco-cms/backoffice/entity-action'; import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -101,24 +99,6 @@ const entityActions: Array = [ }, ], }, - { - type: 'entityAction', - alias: 'Umb.EntityAction.User.ResendInvite', - name: 'Resend Invite User Entity Action', - weight: 500, - api: UmbResendInviteToUserEntityAction, - meta: { - icon: 'icon-message', - label: 'Resend Invite', - repositoryAlias: UMB_INVITE_USER_REPOSITORY_ALIAS, - entityTypes: [UMB_USER_ENTITY_TYPE], - }, - conditions: [ - { - alias: 'Umb.Condition.User.AllowResendInviteAction', - }, - ], - }, ]; export const manifests = [...entityActions]; diff --git a/src/packages/user/user/entity-bulk-actions/manifests.ts b/src/packages/user/user/entity-bulk-actions/manifests.ts index ee0b43b8f7..fd6c25e7de 100644 --- a/src/packages/user/user/entity-bulk-actions/manifests.ts +++ b/src/packages/user/user/entity-bulk-actions/manifests.ts @@ -4,7 +4,7 @@ import { UMB_UNLOCK_USER_REPOSITORY_ALIAS, UMB_USER_REPOSITORY_ALIAS, } from '../repository/manifests.js'; -import { UMB_USER_ENTITY_TYPE } from '../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { UMB_USER_COLLECTION_ALIAS } from '../collection/manifests.js'; import { UmbEnableUserEntityBulkAction } from './enable/enable.action.js'; import { UmbSetGroupUserEntityBulkAction } from './set-group/set-group.action.js'; diff --git a/src/packages/user/user/entity.ts b/src/packages/user/user/entity.ts new file mode 100644 index 0000000000..4b90173667 --- /dev/null +++ b/src/packages/user/user/entity.ts @@ -0,0 +1 @@ +export const UMB_USER_ENTITY_TYPE = 'user'; diff --git a/src/packages/user/user/index.ts b/src/packages/user/user/index.ts index 966b5e5d2d..1e0f92873c 100644 --- a/src/packages/user/user/index.ts +++ b/src/packages/user/user/index.ts @@ -1,3 +1,4 @@ export * from './components/index.js'; +export * from './invite/index.js'; export * from './repository/index.js'; export * from './types.js'; diff --git a/src/packages/user/user/collection/action/invite-user.collection-action.ts b/src/packages/user/user/invite/collection-action/invite-user.collection-action.ts similarity index 78% rename from src/packages/user/user/collection/action/invite-user.collection-action.ts rename to src/packages/user/user/invite/collection-action/invite-user.collection-action.ts index 1452f839ea..b0008ede7e 100644 --- a/src/packages/user/user/collection/action/invite-user.collection-action.ts +++ b/src/packages/user/user/invite/collection-action/invite-user.collection-action.ts @@ -1,10 +1,7 @@ +import { UMB_INVITE_USER_MODAL } from '../modal/index.js'; import { UmbCollectionActionBase } from '@umbraco-cms/backoffice/collection'; import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { - UMB_INVITE_USER_MODAL, - UMB_MODAL_MANAGER_CONTEXT_TOKEN, - UmbModalManagerContext, -} from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; export class UmbInviteUserCollectionAction extends UmbCollectionActionBase { #modalManagerContext: UmbModalManagerContext | undefined; diff --git a/src/packages/user/user/invite/collection-action/manifests.ts b/src/packages/user/user/invite/collection-action/manifests.ts new file mode 100644 index 0000000000..d414f41f07 --- /dev/null +++ b/src/packages/user/user/invite/collection-action/manifests.ts @@ -0,0 +1,23 @@ +import { UmbInviteUserCollectionAction } from './invite-user.collection-action.js'; +import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; +import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const inviteManifest: ManifestTypes = { + type: 'collectionAction', + kind: 'button', + name: 'Invite User Collection Action', + alias: 'Umb.CollectionAction.User.Invite', + api: UmbInviteUserCollectionAction, + weight: 100, + meta: { + label: 'Invite', + }, + conditions: [ + { + alias: UMB_COLLECTION_ALIAS_CONDITION, + match: 'Umb.Collection.User', + }, + ], +}; + +export const manifests = [inviteManifest]; diff --git a/src/packages/user/user/invite/entity-action/manifests.ts b/src/packages/user/user/invite/entity-action/manifests.ts new file mode 100644 index 0000000000..9175766d77 --- /dev/null +++ b/src/packages/user/user/invite/entity-action/manifests.ts @@ -0,0 +1,29 @@ +import { UMB_INVITE_USER_REPOSITORY_ALIAS } from '../repository/manifests.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UmbResendInviteToUserEntityAction } from './resend-invite/resend-invite.action.js'; +import { manifest as conditionManifest } from './resend-invite/resend-invite.action.condition.js'; +import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.User.ResendInvite', + name: 'Resend Invite User Entity Action', + weight: 500, + api: UmbResendInviteToUserEntityAction, + meta: { + icon: 'icon-message', + label: 'Resend Invite', + repositoryAlias: UMB_INVITE_USER_REPOSITORY_ALIAS, + entityTypes: [UMB_USER_ENTITY_TYPE], + }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowResendInviteAction', + }, + ], + }, + conditionManifest, +]; + +export const manifests = [...entityActions]; diff --git a/src/packages/user/user/conditions/user-allow-resend-invite-action.condition.ts b/src/packages/user/user/invite/entity-action/resend-invite/resend-invite.action.condition.ts similarity index 89% rename from src/packages/user/user/conditions/user-allow-resend-invite-action.condition.ts rename to src/packages/user/user/invite/entity-action/resend-invite/resend-invite.action.condition.ts index 8161413d59..267ae20c27 100644 --- a/src/packages/user/user/conditions/user-allow-resend-invite-action.condition.ts +++ b/src/packages/user/user/invite/entity-action/resend-invite/resend-invite.action.condition.ts @@ -1,4 +1,4 @@ -import { UmbUserActionConditionBase } from './user-allow-action-base.condition.js'; +import { UmbUserActionConditionBase } from '../../../conditions/user-allow-action-base.condition.js'; import { UserStateModel } from '@umbraco-cms/backoffice/backend-api'; import { ManifestCondition, diff --git a/src/packages/user/user/entity-actions/resend-invite/resend-invite-to-user.action.ts b/src/packages/user/user/invite/entity-action/resend-invite/resend-invite.action.ts similarity index 73% rename from src/packages/user/user/entity-actions/resend-invite/resend-invite-to-user.action.ts rename to src/packages/user/user/invite/entity-action/resend-invite/resend-invite.action.ts index 78e0f6d722..48b79bc5cb 100644 --- a/src/packages/user/user/entity-actions/resend-invite/resend-invite-to-user.action.ts +++ b/src/packages/user/user/invite/entity-action/resend-invite/resend-invite.action.ts @@ -1,11 +1,8 @@ -import { type UmbEnableUserRepository } from '../../repository/enable/enable-user.repository.js'; +import { type UmbEnableUserRepository } from '../../../repository/enable/enable-user.repository.js'; +import { UMB_RESEND_INVITE_TO_USER_MODAL } from '../../index.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import { - type UmbModalManagerContext, - UMB_MODAL_MANAGER_CONTEXT_TOKEN, - UMB_RESEND_INVITE_TO_USER_MODAL, -} from '@umbraco-cms/backoffice/modal'; +import { type UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; export class UmbResendInviteToUserEntityAction extends UmbEntityActionBase { #modalManager?: UmbModalManagerContext; diff --git a/src/packages/user/user/invite/index.ts b/src/packages/user/user/invite/index.ts new file mode 100644 index 0000000000..3e469f6465 --- /dev/null +++ b/src/packages/user/user/invite/index.ts @@ -0,0 +1,2 @@ +export { UmbInviteUserRepository, UMB_INVITE_USER_REPOSITORY_ALIAS } from './repository/index.js'; +export { UMB_INVITE_USER_MODAL, UMB_RESEND_INVITE_TO_USER_MODAL } from './modal/index.js'; diff --git a/src/packages/user/user/invite/manifests.ts b/src/packages/user/user/invite/manifests.ts new file mode 100644 index 0000000000..d798737db7 --- /dev/null +++ b/src/packages/user/user/invite/manifests.ts @@ -0,0 +1,11 @@ +import { manifests as collectionActionManifests } from './collection-action/manifests.js'; +import { manifests as modalManifests } from './modal/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as entityActionManifests } from './entity-action/manifests.js'; + +export const manifests = [ + ...collectionActionManifests, + ...modalManifests, + ...repositoryManifests, + ...entityActionManifests, +]; diff --git a/src/packages/user/user/invite/modal/index.ts b/src/packages/user/user/invite/modal/index.ts new file mode 100644 index 0000000000..08defd0e3d --- /dev/null +++ b/src/packages/user/user/invite/modal/index.ts @@ -0,0 +1,2 @@ +export { UMB_INVITE_USER_MODAL } from './invite/index.js'; +export { UMB_RESEND_INVITE_TO_USER_MODAL } from './resend-invite/index.js'; diff --git a/src/packages/user/user/invite/modal/invite/index.ts b/src/packages/user/user/invite/modal/invite/index.ts new file mode 100644 index 0000000000..0829fd1ba8 --- /dev/null +++ b/src/packages/user/user/invite/modal/invite/index.ts @@ -0,0 +1 @@ +export { UMB_INVITE_USER_MODAL } from './user-invite-modal.token.js'; diff --git a/src/packages/user/user/invite/modal/invite/user-invite-modal.element.ts b/src/packages/user/user/invite/modal/invite/user-invite-modal.element.ts new file mode 100644 index 0000000000..d24f5c77a3 --- /dev/null +++ b/src/packages/user/user/invite/modal/invite/user-invite-modal.element.ts @@ -0,0 +1,116 @@ +import { UmbUserGroupInputElement } from '../../../../user-group/components/input-user-group/user-group-input.element.js'; +import { UmbInviteUserRepository } from '../../repository/invite-user.repository.js'; +import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; + +@customElement('umb-invite-user-modal') +export class UmbInviteUserModalElement extends UmbModalBaseElement { + #inviteUserRepository = new UmbInviteUserRepository(this); + + async #onSubmit(e: Event) { + e.preventDefault(); + + const form = e.target as HTMLFormElement; + if (!form) return; + + const isValid = form.checkValidity(); + if (!isValid) return; + + const formData = new FormData(form); + + const name = formData.get('name') as string; + const email = formData.get('email') as string; + + //TODO: How should we handle pickers forms? + const userGroupPicker = form.querySelector('#userGroups') as UmbUserGroupInputElement; + const userGroupIds = userGroupPicker?.selectedIds; + + const message = formData.get('message') as string; + + // TODO: figure out when to use email or username + // TODO: invite request gives 500 error. + const { error } = await this.#inviteUserRepository.invite({ + name, + email, + userName: email, + message, + userGroupIds, + }); + + if (!error) { + this._submitModal(); + } + } + + render() { + return html` + ${this.#renderForm()} + + `; + } + + #renderForm() { + return html`

+ Invite new users to give them access to Umbraco. An invite email will be sent to the user with information on + how to log in to Umbraco. Invites last for 72 hours. +

+ +
+ + Name + + + + Email + + + + User group + Add groups to assign access and permissions + + + + Message + + +
+
`; + } + + static styles = [ + UmbTextStyles, + css` + :host { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + } + + uui-input { + width: 100%; + } + + uui-textarea { + --uui-textarea-min-height: 100px; + } + `, + ]; +} + +export default UmbInviteUserModalElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-invite-user-modal': UmbInviteUserModalElement; + } +} diff --git a/src/packages/core/modal/token/invite-user-modal.token.ts b/src/packages/user/user/invite/modal/invite/user-invite-modal.token.ts similarity index 100% rename from src/packages/core/modal/token/invite-user-modal.token.ts rename to src/packages/user/user/invite/modal/invite/user-invite-modal.token.ts diff --git a/src/packages/user/user/invite/modal/manifests.ts b/src/packages/user/user/invite/modal/manifests.ts new file mode 100644 index 0000000000..7acfa75d84 --- /dev/null +++ b/src/packages/user/user/invite/modal/manifests.ts @@ -0,0 +1,18 @@ +import type { ManifestModal } from '@umbraco-cms/backoffice/extension-registry'; + +const modals: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.User.Invite', + name: 'Invite User Modal', + js: () => import('./invite/user-invite-modal.element.js'), + }, + { + type: 'modal', + alias: 'Umb.Modal.User.Invite.Resend', + name: 'Resend Invite to User Modal', + js: () => import('./resend-invite/resend-invite-to-user-modal.element.js'), + }, +]; + +export const manifests = [...modals]; diff --git a/src/packages/user/user/invite/modal/resend-invite/index.ts b/src/packages/user/user/invite/modal/resend-invite/index.ts new file mode 100644 index 0000000000..3f90d6a99b --- /dev/null +++ b/src/packages/user/user/invite/modal/resend-invite/index.ts @@ -0,0 +1 @@ +export { UMB_RESEND_INVITE_TO_USER_MODAL } from './resend-invite-to-user-modal.token.js'; diff --git a/src/packages/user/user/modals/resend-invite/resend-invite-to-user-modal.element.ts b/src/packages/user/user/invite/modal/resend-invite/resend-invite-to-user-modal.element.ts similarity index 68% rename from src/packages/user/user/modals/resend-invite/resend-invite-to-user-modal.element.ts rename to src/packages/user/user/invite/modal/resend-invite/resend-invite-to-user-modal.element.ts index db299dcd8a..22b54d81f5 100644 --- a/src/packages/user/user/modals/resend-invite/resend-invite-to-user-modal.element.ts +++ b/src/packages/user/user/invite/modal/resend-invite/resend-invite-to-user-modal.element.ts @@ -1,18 +1,24 @@ -import { UmbInviteUserRepository } from '../../repository/invite/invite-user.repository.js'; -import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; +import { UmbInviteUserRepository } from '../../repository/invite-user.repository.js'; +import { + UmbResendInviteToUserModalData, + UmbResendInviteToUserModalValue, +} from './resend-invite-to-user-modal.token.js'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @customElement('umb-resend-invite-to-user-modal') -export class UmbResendInviteToUserModalElement extends UmbModalBaseElement { - @query('#form') - private _form!: HTMLFormElement; - - #userRepository = new UmbInviteUserRepository(this); +export class UmbResendInviteToUserModalElement extends UmbModalBaseElement< + UmbResendInviteToUserModalData, + UmbResendInviteToUserModalValue +> { + #userInviteUserRepository = new UmbInviteUserRepository(this); async #onSubmitForm(e: Event) { e.preventDefault(); + if (!this.modalContext?.data.userId) throw new Error('User id is missing'); + const form = e.target as HTMLFormElement; if (!form) return; @@ -22,28 +28,25 @@ export class UmbResendInviteToUserModalElement extends UmbModalBaseElement { const formData = new FormData(form); const message = formData.get('message') as string; - alert('implement'); - /* - const { error } = await this.#userRepository.resendInvite({ + await this.#userInviteUserRepository.resendInvite({ + userId: this.modalContext.data.userId, message, }); - */ - } - private _closeModal() { - this.modalContext?.reject(); + this._submitModal(); } render() { return html` ${this.#renderForm()} - + `; } diff --git a/src/packages/core/modal/token/resend-invite-to-user-modal.token.ts b/src/packages/user/user/invite/modal/resend-invite/resend-invite-to-user-modal.token.ts similarity index 90% rename from src/packages/core/modal/token/resend-invite-to-user-modal.token.ts rename to src/packages/user/user/invite/modal/resend-invite/resend-invite-to-user-modal.token.ts index 308c5d7cf9..a58dd10034 100644 --- a/src/packages/core/modal/token/resend-invite-to-user-modal.token.ts +++ b/src/packages/user/user/invite/modal/resend-invite/resend-invite-to-user-modal.token.ts @@ -9,7 +9,7 @@ export type UmbResendInviteToUserModalValue = undefined; export const UMB_RESEND_INVITE_TO_USER_MODAL = new UmbModalToken< UmbResendInviteToUserModalData, UmbResendInviteToUserModalValue ->('Umb.Modal.User.ResendInvite', { +>('Umb.Modal.User.Invite.Resend', { type: 'dialog', size: 'small', }); diff --git a/src/packages/user/user/invite/repository/index.ts b/src/packages/user/user/invite/repository/index.ts new file mode 100644 index 0000000000..9d8b0a75fe --- /dev/null +++ b/src/packages/user/user/invite/repository/index.ts @@ -0,0 +1,2 @@ +export { UmbInviteUserRepository } from './invite-user.repository.js'; +export { UMB_INVITE_USER_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/packages/user/user/repository/invite/invite-user.server.data-source.ts b/src/packages/user/user/invite/repository/invite-user-server.data-source.ts similarity index 62% rename from src/packages/user/user/repository/invite/invite-user.server.data-source.ts rename to src/packages/user/user/invite/repository/invite-user-server.data-source.ts index fbd717f24e..8c2e71d002 100644 --- a/src/packages/user/user/repository/invite/invite-user.server.data-source.ts +++ b/src/packages/user/user/invite/repository/invite-user-server.data-source.ts @@ -1,5 +1,10 @@ +import { UmbUserServerDataSource } from '../../repository/detail/user-detail.server.data-source.js'; import { type UmbInviteUserDataSource } from './types.js'; -import { InviteUserRequestModel, UserResource } from '@umbraco-cms/backoffice/backend-api'; +import { + InviteUserRequestModel, + ResendInviteUserRequestModel, + UserResource, +} from '@umbraco-cms/backoffice/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; @@ -10,14 +15,15 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; */ export class UmbInviteUserServerDataSource implements UmbInviteUserDataSource { #host: UmbControllerHost; + #detailSource: UmbUserServerDataSource; /** * Creates an instance of UmbInviteUserServerDataSource. - * @param {UmbControllerHost} host * @memberof UmbInviteUserServerDataSource */ constructor(host: UmbControllerHost) { this.#host = host; + this.#detailSource = new UmbUserServerDataSource(host); } /** @@ -29,41 +35,36 @@ export class UmbInviteUserServerDataSource implements UmbInviteUserDataSource { async invite(requestModel: InviteUserRequestModel) { if (!requestModel) throw new Error('Data is missing'); - return tryExecuteAndNotify( + const { data: newUserId, error } = await tryExecuteAndNotify( this.#host, UserResource.postUserInvite({ requestBody: requestModel, }), ); + + if (newUserId) { + return this.#detailSource.read(newUserId); + } + + return { error }; } /** * Resend an invite to a user - * @param {string} userId + * @param {string} userUnique * @param {InviteUserRequestModel} requestModel * @returns * @memberof UmbInviteUserServerDataSource */ - async resendInvite(userId: string, requestModel: InviteUserRequestModel) { - if (!userId) throw new Error('User id is missing'); + async resendInvite(requestModel: ResendInviteUserRequestModel) { + if (!requestModel.userId) throw new Error('User id is missing'); if (!requestModel) throw new Error('Data is missing'); - alert('End point is missing'); - - const body = JSON.stringify({ - userId, - requestModel, - }); - return tryExecuteAndNotify( this.#host, - fetch('/umbraco/management/api/v1/user/invite/resend', { - method: 'POST', - body: body, - headers: { - 'Content-Type': 'application/json', - }, - }).then((res) => res.json()), + UserResource.postUserInviteResend({ + requestBody: requestModel, + }), ); } } diff --git a/src/packages/user/user/repository/invite/invite-user.repository.ts b/src/packages/user/user/invite/repository/invite-user.repository.ts similarity index 62% rename from src/packages/user/user/repository/invite/invite-user.repository.ts rename to src/packages/user/user/invite/repository/invite-user.repository.ts index da2afa1791..7ef2325c05 100644 --- a/src/packages/user/user/repository/invite/invite-user.repository.ts +++ b/src/packages/user/user/invite/repository/invite-user.repository.ts @@ -1,11 +1,10 @@ -import { UmbUserRepositoryBase } from '../user-repository-base.js'; -import { type UmbInviteUserDataSource } from './types.js'; -import { UmbInviteUserServerDataSource } from './invite-user.server.data-source.js'; +import { UmbUserRepositoryBase } from '../../repository/user-repository-base.js'; +import { UmbInviteUserServerDataSource } from './invite-user-server.data-source.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { InviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api'; +import { InviteUserRequestModel, ResendInviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api'; export class UmbInviteUserRepository extends UmbUserRepositoryBase { - #inviteSource: UmbInviteUserDataSource; + #inviteSource: UmbInviteUserServerDataSource; constructor(host: UmbControllerHost) { super(host); @@ -22,9 +21,11 @@ export class UmbInviteUserRepository extends UmbUserRepositoryBase { if (!requestModel) throw new Error('data is missing'); await this.init; - const { error } = await this.#inviteSource.invite(requestModel); + const { data, error } = await this.#inviteSource.invite(requestModel); + + if (data) { + this.detailStore!.append(data); - if (!error) { const notification = { data: { message: `Invite sent to user` } }; this.notificationContext?.peek('positive', notification); } @@ -34,17 +35,17 @@ export class UmbInviteUserRepository extends UmbUserRepositoryBase { /** * Resend an invite to a user - * @param {string} userId + * @param {string} userUnique * @param {InviteUserRequestModel} requestModel * @return {*} * @memberof UmbInviteUserRepository */ - async resendInvite(userId: string, requestModel: any) { - if (!userId) throw new Error('User id is missing'); + async resendInvite(requestModel: ResendInviteUserRequestModel) { + if (!requestModel.userId) throw new Error('User unique is missing'); if (!requestModel) throw new Error('data is missing'); await this.init; - const { error } = await this.#inviteSource.resendInvite(userId, requestModel); + const { error } = await this.#inviteSource.resendInvite(requestModel); if (!error) { const notification = { data: { message: `Invite resent to user` } }; diff --git a/src/packages/user/user/invite/repository/manifests.ts b/src/packages/user/user/invite/repository/manifests.ts new file mode 100644 index 0000000000..218e4595c1 --- /dev/null +++ b/src/packages/user/user/invite/repository/manifests.ts @@ -0,0 +1,12 @@ +import { UmbInviteUserRepository } from './invite-user.repository.js'; +import { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_INVITE_USER_REPOSITORY_ALIAS = 'Umb.Repository.User.Invite'; +const inviteRepository: ManifestRepository = { + type: 'repository', + alias: UMB_INVITE_USER_REPOSITORY_ALIAS, + name: 'Invite User Repository', + api: UmbInviteUserRepository, +}; + +export const manifests = [inviteRepository]; diff --git a/src/packages/user/user/invite/repository/types.ts b/src/packages/user/user/invite/repository/types.ts new file mode 100644 index 0000000000..ca096d0a21 --- /dev/null +++ b/src/packages/user/user/invite/repository/types.ts @@ -0,0 +1,8 @@ +import { UmbUserDetailModel } from '../../types.js'; +import { InviteUserRequestModel, ResendInviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api'; +import { DataSourceResponse, UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository'; + +export interface UmbInviteUserDataSource { + invite(requestModel: InviteUserRequestModel): Promise>; + resendInvite(requestModel: ResendInviteUserRequestModel): Promise; +} diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index b412dc5a55..b49afe5eb4 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -1,4 +1,5 @@ import { manifests as collectionManifests } from './collection/manifests.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; @@ -9,6 +10,7 @@ import { manifests as conditionsManifests } from './conditions/manifests.js'; export const manifests = [ ...collectionManifests, + ...inviteManifests, ...repositoryManifests, ...workspaceManifests, ...modalManifests, diff --git a/src/packages/user/user/modals/invite/user-invite-modal.element.ts b/src/packages/user/user/modals/invite/user-invite-modal.element.ts deleted file mode 100644 index dc4eefe188..0000000000 --- a/src/packages/user/user/modals/invite/user-invite-modal.element.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { UmbUserGroupInputElement } from '../../../user-group/components/input-user-group/user-group-input.element.js'; -import { UmbInviteUserRepository } from '../../repository/invite/invite-user.repository.js'; -import { css, html, nothing, customElement, query, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; - -@customElement('umb-user-invite-modal') -export class UmbUserInviteModalElement extends UmbModalBaseElement { - @query('#form') - private _form!: HTMLFormElement; - - @state() - private _invitedUser?: any; - - #userRepository = new UmbInviteUserRepository(this); - - private async _handleSubmit(e: Event) { - e.preventDefault(); - - const form = e.target as HTMLFormElement; - if (!form) return; - - const isValid = form.checkValidity(); - if (!isValid) return; - - const formData = new FormData(form); - - const name = formData.get('name') as string; - const email = formData.get('email') as string; - - //TODO: How should we handle pickers forms? - const userGroupPicker = form.querySelector('#userGroups') as UmbUserGroupInputElement; - const userGroupIds = userGroupPicker?.selectedIds; - - const message = formData.get('message') as string; - - alert('implement'); - - // TODO: figure out when to use email or username - // TODO: invite request gives 500 error. - /* - const { data } = await this.#userRepository.invite({ - name, - email, - userName: email, - message, - userGroupIds, - }); - - if (data) { - this._invitedUser = data; - } - */ - } - - private _submitForm() { - this._form?.requestSubmit(); - } - - private _closeModal() { - this.modalContext?.reject(); - } - - private _resetForm() { - this._invitedUser = undefined; - } - - private _goToProfile() { - if (!this._invitedUser) return; - - this._closeModal(); - history.pushState(null, '', 'section/user-management/view/users/user/' + this._invitedUser?.id); //TODO: URL Should be dynamic - } - - private _renderForm() { - return html`

Invite user

-

- Invite new users to give them access to Umbraco. An invite email will be sent to the user with information on - how to log in to Umbraco. Invites last for 72 hours. -

- -
- - Name - - - - Email - - - - User group - Add groups to assign access and permissions - - - - Message - - -
-
`; - } - - private _renderPostInvite() { - if (!this._invitedUser) return nothing; - - return html`
-

${this._invitedUser.name} has been invited

-

An invitation has been sent to the new user with details about how to log in to Umbraco.

-
`; - } - - render() { - return html` - ${this._invitedUser ? this._renderPostInvite() : this._renderForm()} - ${this._invitedUser - ? html` - - - - ` - : html` - - - `} - `; - } - - static styles = [ - UmbTextStyles, - css` - :host { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - width: 100%; - } - uui-box { - max-width: 500px; - } - uui-form-layout-item { - display: flex; - flex-direction: column; - } - uui-input { - width: 100%; - } - form { - display: flex; - flex-direction: column; - box-sizing: border-box; - } - uui-form-layout-item { - margin-bottom: 0; - } - uui-textarea { - --uui-textarea-min-height: 100px; - } - /* TODO: Style below is to fix a11y contrast issue, find a proper solution */ - [slot='description'] { - color: black; - } - `, - ]; -} - -export default UmbUserInviteModalElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-user-invite-modal': UmbUserInviteModalElement; - } -} diff --git a/src/packages/user/user/modals/manifests.ts b/src/packages/user/user/modals/manifests.ts index b8bde4b0a9..bcb32e8211 100644 --- a/src/packages/user/user/modals/manifests.ts +++ b/src/packages/user/user/modals/manifests.ts @@ -13,18 +13,6 @@ const modals: Array = [ name: 'Create Success User Modal', js: () => import('./create/user-create-success-modal.element.js'), }, - { - type: 'modal', - alias: 'Umb.Modal.User.Invite', - name: 'Invite User Modal', - js: () => import('./invite/user-invite-modal.element.js'), - }, - { - type: 'modal', - alias: 'Umb.Modal.User.ResendInvite', - name: 'Resend Invite to User Modal', - js: () => import('./resend-invite/resend-invite-to-user-modal.element.js'), - }, { type: 'modal', alias: 'Umb.Modal.User.Picker', diff --git a/src/packages/user/user/repository/detail/user-detail.server.data-source.ts b/src/packages/user/user/repository/detail/user-detail.server.data-source.ts index 028a160401..59d4984a1c 100644 --- a/src/packages/user/user/repository/detail/user-detail.server.data-source.ts +++ b/src/packages/user/user/repository/detail/user-detail.server.data-source.ts @@ -1,4 +1,5 @@ -import { UMB_USER_ENTITY_TYPE, UmbUserDetail, UmbUserDetailDataSource } from '../../types.js'; +import { UmbUserDetailModel, UmbUserDetailDataSource } from '../../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import { DataSourceResponse, UmbDataSourceErrorResponse, @@ -45,7 +46,7 @@ export class UmbUserServerDataSource implements UmbUserDetailDataSource { async read(id: string) { if (!id) throw new Error('Id is missing'); const response = await tryExecuteAndNotify(this.#host, UserResource.getUserById({ id })); - return extendDataSourceResponseData(response, { + return extendDataSourceResponseData(response, { entityType: UMB_USER_ENTITY_TYPE, }); } diff --git a/src/packages/user/user/repository/index.ts b/src/packages/user/user/repository/index.ts index a5cf39ae66..6c538edb00 100644 --- a/src/packages/user/user/repository/index.ts +++ b/src/packages/user/user/repository/index.ts @@ -2,7 +2,6 @@ export * from './change-password/change-user-password.repository.js'; export * from './disable/disable-user.repository.js'; export * from './enable/enable-user.repository.js'; export * from './unlock/unlock-user.repository.js'; -export * from './invite/invite-user.repository.js'; export * from './user.repository.js'; export * from './item/index.js'; export * from './detail/index.js'; diff --git a/src/packages/user/user/repository/invite/types.ts b/src/packages/user/user/repository/invite/types.ts deleted file mode 100644 index cc8d5b8974..0000000000 --- a/src/packages/user/user/repository/invite/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { InviteUserRequestModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository'; - -export interface UmbInviteUserDataSource { - invite(requestModel: InviteUserRequestModel): Promise; - resendInvite(userId: string, requestModel: any): Promise; -} diff --git a/src/packages/user/user/repository/manifests.ts b/src/packages/user/user/repository/manifests.ts index ba74dac1f2..d6864f7213 100644 --- a/src/packages/user/user/repository/manifests.ts +++ b/src/packages/user/user/repository/manifests.ts @@ -4,7 +4,6 @@ import { UmbDisableUserRepository } from './disable/disable-user.repository.js'; import { UmbEnableUserRepository } from './enable/enable-user.repository.js'; import { UmbChangeUserPasswordRepository } from './change-password/change-user-password.repository.js'; import { UmbUnlockUserRepository } from './unlock/unlock-user.repository.js'; -import { UmbInviteUserRepository } from './invite/invite-user.repository.js'; import { manifests as itemManifests } from './item/manifests.js'; import type { ManifestStore, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; @@ -48,14 +47,6 @@ const unlockRepository: ManifestRepository = { api: UmbUnlockUserRepository, }; -export const UMB_INVITE_USER_REPOSITORY_ALIAS = 'Umb.Repository.User.Invite'; -const inviteRepository: ManifestRepository = { - type: 'repository', - alias: UMB_INVITE_USER_REPOSITORY_ALIAS, - name: 'Invite User Repository', - api: UmbInviteUserRepository, -}; - const store: ManifestStore = { type: 'store', alias: 'Umb.Store.User', @@ -69,7 +60,6 @@ export const manifests = [ enableRepository, changePasswordRepository, unlockRepository, - inviteRepository, store, ...itemManifests, ]; diff --git a/src/packages/user/user/repository/user.store.ts b/src/packages/user/user/repository/user.store.ts index ac0067f3ff..952fbd055d 100644 --- a/src/packages/user/user/repository/user.store.ts +++ b/src/packages/user/user/repository/user.store.ts @@ -1,4 +1,4 @@ -import { type UmbUserDetail } from '../index.js'; +import { type UmbUserDetailModel } from '../index.js'; import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; @@ -14,7 +14,7 @@ export const UMB_USER_STORE_CONTEXT_TOKEN = new UmbContextToken('U */ export class UmbUserStore extends UmbStoreBase { constructor(host: UmbControllerHostElement) { - super(host, UMB_USER_STORE_CONTEXT_TOKEN.toString(), new UmbArrayState([], (x) => x.id)); + super(host, UMB_USER_STORE_CONTEXT_TOKEN.toString(), new UmbArrayState([], (x) => x.id)); } /** @@ -22,7 +22,7 @@ export class UmbUserStore extends UmbStoreBase { * @param {id} string id. * @memberof UmbUserStore */ - byId(id: UmbUserDetail['id']) { + byId(id: UmbUserDetailModel['id']) { return this._data.asObservablePart((x) => x.find((y) => y.id === id)); } } diff --git a/src/packages/user/user/types.ts b/src/packages/user/user/types.ts index a213096de5..b57e801f0e 100644 --- a/src/packages/user/user/types.ts +++ b/src/packages/user/user/types.ts @@ -10,9 +10,7 @@ import type { import { UmbDataSource, UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository'; -export const UMB_USER_ENTITY_TYPE = 'user'; - -export type UmbUserDetail = UserResponseModel & { +export type UmbUserDetailModel = UserResponseModel & { entityType: 'user'; }; @@ -27,7 +25,7 @@ export interface UmbUserCollectionFilterModel { } export interface UmbUserDetailDataSource - extends UmbDataSource { + extends UmbDataSource { createAvatar(id: string, fileId: string): Promise; deleteAvatar(id: string): Promise; } diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts index 806023d328..c10b796dbb 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts @@ -1,6 +1,6 @@ import { getDisplayStateFromUserStatus } from '../../../../utils.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context.js'; -import { UmbUserDetail } from '../../../types.js'; +import { UmbUserDetailModel } from '../../../types.js'; import { html, customElement, @@ -20,7 +20,7 @@ type UmbUserWorkspaceInfoItem = { labelKey: string; value: string | number | und @customElement('umb-user-workspace-info') export class UmbUserWorkspaceInfoElement extends UmbLitElement { @state() - private _user?: UmbUserDetail; + private _user?: UmbUserDetailModel; @state() private _userAvatarUrls: Array<{ url: string; scale: string }> = []; @@ -56,7 +56,7 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { } // TODO: remove this when we get absolute urls from the server - #setUserAvatarUrls = async (user: UmbUserDetail | undefined) => { + #setUserAvatarUrls = async (user: UmbUserDetailModel | undefined) => { if (user?.avatarUrls?.length === 0) return; const serverUrl = (await this.#getAppContext()).getServerUrl(); @@ -98,7 +98,7 @@ export class UmbUserWorkspaceInfoElement extends UmbLitElement { } }; - #setUserInfoItems = (user: UmbUserDetail | undefined) => { + #setUserInfoItems = (user: UmbUserDetailModel | undefined) => { if (!user) { this._userInfo = []; return; diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index 841505c839..5f545057fb 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import type { ManifestWorkspace, diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index fb6dec324e..217d59907e 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -1,4 +1,5 @@ -import { UMB_USER_ENTITY_TYPE, type UmbUserDetail } from '../index.js'; +import { type UmbUserDetailModel } from '../index.js'; +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -14,7 +15,7 @@ import './components/user-workspace-info/user-workspace-info.element.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { @state() - private _user?: UmbUserDetail; + private _user?: UmbUserDetailModel; #workspaceContext?: UmbUserWorkspaceContext; diff --git a/src/packages/user/user/workspace/user-workspace.context.ts b/src/packages/user/user/workspace/user-workspace.context.ts index 4eed66cea6..e419872ac3 100644 --- a/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/packages/user/user/workspace/user-workspace.context.ts @@ -1,4 +1,5 @@ -import { UMB_USER_ENTITY_TYPE, type UmbUserDetail } from '../types.js'; +import { type UmbUserDetailModel } from '../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { UmbUserDetailRepository } from '../repository/index.js'; import { UmbSaveableWorkspaceContextInterface, @@ -12,8 +13,8 @@ import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs'; export class UmbUserWorkspaceContext - extends UmbEditableWorkspaceContextBase - implements UmbSaveableWorkspaceContextInterface + extends UmbEditableWorkspaceContextBase + implements UmbSaveableWorkspaceContextInterface { #currentUserContext?: typeof UMB_CURRENT_USER_CONTEXT.TYPE; @@ -25,7 +26,7 @@ export class UmbUserWorkspaceContext }); } - #data = new UmbObjectState(undefined); + #data = new UmbObjectState(undefined); data = this.#data.asObservable(); async load(id: string) { @@ -43,7 +44,7 @@ export class UmbUserWorkspaceContext Therefore we have to subscribe to the user store to update the state in the workspace data. There might be a less manual way to do this. */ - onUserStoreChanges(user: UmbUserDetail) { + onUserStoreChanges(user: UmbUserDetailModel) { if (!user) return; this.#data.update({ state: user.state }); } @@ -60,9 +61,9 @@ export class UmbUserWorkspaceContext return this.#data.getValue(); } - updateProperty( + updateProperty( propertyName: PropertyName, - value: UmbUserDetail[PropertyName], + value: UmbUserDetailModel[PropertyName], ) { this.#data.update({ [propertyName]: value }); }