From 7572ea350b218b570f99ed188bd09acceefb7edf Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 20 May 2025 11:12:19 +0200 Subject: [PATCH] Feature: Content Workspace Icon (#19292) * add slot for icon * expose icon data * render icon * load type for scaffold * rename * render icon for media * add observable for content type icon * request data in data source * wire up document scaffolding * remove unused * export server data source * render icon for member * rename data source to align with other detail sources * rename data source * remove unused styling * remove console log Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove console log Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove console log * Update detail-repository-base.ts * Update document-workspace-split-view.element.ts --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../detail/detail-data-source.interface.ts | 3 +- .../detail/detail-repository-base.ts | 7 +- .../workspace-split-view.element.ts | 7 ++ .../core/workspace/entity-detail/types.ts | 3 +- .../document-types/repository/detail/index.ts | 1 + .../document-detail.server.data-source.ts | 74 ++++++++----------- .../document-workspace-split-view.element.ts | 20 +++-- .../workspace/document-workspace.context.ts | 3 +- .../media-types/repository/detail/index.ts | 1 + .../detail/media-type-detail.repository.ts | 4 +- .../media-type-detail.server.data-source.ts | 18 ++--- .../detail/media-detail.server.data-source.ts | 56 +++++++------- .../media-workspace-split-view.element.ts | 21 +++++- .../workspace/media-workspace.context.ts | 8 +- .../member-type/repository/detail/index.ts | 1 + .../detail/member-type-detail.repository.ts | 4 +- .../member-type-detail.server.data-source.ts | 31 ++++---- .../members/member-type/repository/index.ts | 2 +- .../member-detail.server.data-source.ts | 47 ++++++------ .../member-workspace-split-view.element.ts | 18 ++++- .../member/member-workspace.context.ts | 1 + 21 files changed, 190 insertions(+), 140 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-data-source.interface.ts index 5b92e4de68..78895a6c88 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-data-source.interface.ts @@ -1,5 +1,6 @@ import type { UmbDataSourceResponse } from '../data-source-response.interface.js'; import type { UmbReadDetailDataSource } from './read/index.js'; +import type { UmbDeepPartialObject } from '@umbraco-cms/backoffice/utils'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export interface UmbDetailDataSourceConstructor< @@ -10,7 +11,7 @@ export interface UmbDetailDataSourceConstructor< } export interface UmbDetailDataSource extends UmbReadDetailDataSource { - createScaffold(preset?: Partial): Promise>; + createScaffold(preset?: UmbDeepPartialObject): Promise>; create(data: DetailType, parentUnique: string | null): Promise>; update(data: DetailType): Promise>; delete(unique: string): Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts index cad291bbcc..c34c283613 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts @@ -7,6 +7,7 @@ import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbDetailStore } from '@umbraco-cms/backoffice/store'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import type { UmbDeepPartialObject } from '@umbraco-cms/backoffice/utils'; export abstract class UmbDetailRepositoryBase< DetailModelType extends UmbEntityModel, @@ -44,11 +45,13 @@ export abstract class UmbDetailRepositoryBase< /** * Creates a scaffold - * @param {Partial} [preset] + * @param {UmbDeepPartialObject} [preset] * @returns {*} * @memberof UmbDetailRepositoryBase */ - async createScaffold(preset?: Partial): Promise> { + async createScaffold( + preset?: UmbDeepPartialObject, + ): Promise> { return this.detailDataSource.createScaffold(preset); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.element.ts index 4deb134665..25b0c70f8d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.element.ts @@ -67,6 +67,7 @@ export class UmbWorkspaceSplitViewElement extends UmbLitElement { back-path=${ifDefined(this.backPath)} .hideNavigation=${!this.displayNavigation} .enforceNoFooter=${true}> + ${when( !this._variantSelectorSlotHasContent, @@ -106,6 +107,12 @@ export class UmbWorkspaceSplitViewElement extends UmbLitElement { flex: 1 1 auto; display: block; } + + #icon { + display: inline-block; + font-size: var(--uui-size-6); + margin-right: var(--uui-size-space-4); + } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts index 97bcf40aa5..687874140f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts @@ -1,4 +1,5 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import type { UmbDeepPartialObject } from '@umbraco-cms/backoffice/utils'; export interface UmbEntityDetailWorkspaceContextArgs { entityType: string; @@ -13,5 +14,5 @@ export type UmbEntityWorkspaceContextArgs = UmbEntityDetailWorkspaceContextArgs; export interface UmbEntityDetailWorkspaceContextCreateArgs { parent: UmbEntityModel; - preset?: Partial; + preset?: UmbDeepPartialObject; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/index.ts index 08bd0c65eb..68d24e6f3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/detail/index.ts @@ -1 +1,2 @@ export { UmbDocumentTypeDetailRepository } from './document-type-detail.repository.js'; +export * from './document-type-detail.server.data-source.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts index 2f8d9de1e7..cfe9e123f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts @@ -7,69 +7,59 @@ import type { UpdateDocumentRequestModel, } from '@umbraco-cms/backoffice/external/backend-api'; import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecute } from '@umbraco-cms/backoffice/resources'; +import { umbDeepMerge, type UmbDeepPartialObject } from '@umbraco-cms/backoffice/utils'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import { UmbDocumentTypeDetailServerDataSource } from '@umbraco-cms/backoffice/document-type'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; /** * A data source for the Document that fetches data from the server * @class UmbDocumentServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbDocumentServerDataSource implements UmbDetailDataSource { - #host: UmbControllerHost; - - /** - * Creates an instance of UmbDocumentServerDataSource. - * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbDocumentServerDataSource - */ - constructor(host: UmbControllerHost) { - this.#host = host; - } - +export class UmbDocumentServerDataSource + extends UmbControllerBase + implements UmbDetailDataSource +{ /** * Creates a new Document scaffold * @param preset * @returns { UmbDocumentDetailModel } * @memberof UmbDocumentServerDataSource */ - async createScaffold(preset: Partial = {}) { - const data: UmbDocumentDetailModel = { + async createScaffold(preset: UmbDeepPartialObject = {}) { + let documentTypeIcon: string | null = null; + let documentTypeCollection: UmbReferenceByUnique | null = null; + + const documentTypeUnique = preset.documentType?.unique; + + if (!documentTypeUnique) { + throw new Error('Document type unique is missing'); + } + + const { data } = await new UmbDocumentTypeDetailServerDataSource(this).read(documentTypeUnique); + documentTypeIcon = data?.icon ?? null; + documentTypeCollection = data?.collection ?? null; + + const defaultData: UmbDocumentDetailModel = { entityType: UMB_DOCUMENT_ENTITY_TYPE, unique: UmbId.new(), template: null, documentType: { - unique: '', - collection: null, - icon: null, + unique: documentTypeUnique, + collection: documentTypeCollection, + icon: documentTypeIcon, }, isTrashed: false, values: [], variants: [], - ...preset, }; - return { data }; - } + const scaffold = umbDeepMerge(defaultData, preset) as UmbDocumentDetailModel; - /** - * Creates a new variant scaffold. - * @returns A new variant scaffold. - */ - /* - // TDOD: remove if not used - createVariantScaffold(): UmbDocumentVariantModel { - return { - state: null, - culture: null, - segment: null, - name: '', - publishDate: null, - createDate: null, - updateDate: null, - }; + return { data: scaffold }; } - */ /** * Fetches a Document with the given id from the server @@ -80,7 +70,7 @@ export class UmbDocumentServerDataSource implements UmbDetailDataSource; + @state() + _icon?: string; + constructor() { super(); // TODO: Refactor: use a split view workspace context token: [NL] this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; - this._observeActiveVariantInfo(); + this.#observeActiveVariantInfo(); + this.#observeIcon(); }); } - private _observeActiveVariantInfo() { - if (!this._workspaceContext) return; + #observeActiveVariantInfo() { this.observe( - this._workspaceContext.splitView.activeVariantsInfo, + this._workspaceContext?.splitView.activeVariantsInfo, (variants) => { this._variants = variants; }, @@ -35,6 +38,12 @@ export class UmbDocumentWorkspaceSplitViewElement extends UmbLitElement { ); } + #observeIcon() { + this.observe(this._workspaceContext?.contentTypeIcon, (icon) => { + this._icon = icon ?? undefined; + }); + } + override render() { return this._variants ? html`
@@ -46,6 +55,7 @@ export class UmbDocumentWorkspaceSplitViewElement extends UmbLitElement { + diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index b6b0e49287..ea09e88092 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -67,6 +67,8 @@ export class UmbDocumentWorkspaceContext readonly contentTypeHasCollection = this._data.createObservablePartOfCurrent( (data) => !!data?.documentType.collection, ); + readonly contentTypeIcon = this._data.createObservablePartOfCurrent((data) => data?.documentType.icon || null); + readonly templateId = this._data.createObservablePartOfCurrent((data) => data?.template?.unique || null); #isTrashedContext = new UmbIsTrashedEntityContext(this); @@ -303,7 +305,6 @@ export class UmbDocumentWorkspaceContext preset: { documentType: { unique: documentTypeUnique, - collection: null, }, }, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts index 9284c3f2eb..8869ea1c65 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts @@ -1 +1,2 @@ export { UmbMediaTypeDetailRepository } from './media-type-detail.repository.js'; +export * from './media-type-detail.server.data-source.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts index 415b7b12f0..bf65d345f9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts @@ -1,11 +1,11 @@ import type { UmbMediaTypeDetailModel } from '../../types.js'; -import { UmbMediaTypeServerDataSource } from './media-type-detail.server.data-source.js'; +import { UmbMediaTypeDetailServerDataSource } from './media-type-detail.server.data-source.js'; import { UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT } from './media-type-detail.store.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbDetailRepositoryBase } from '@umbraco-cms/backoffice/repository'; export class UmbMediaTypeDetailRepository extends UmbDetailRepositoryBase { constructor(host: UmbControllerHost) { - super(host, UmbMediaTypeServerDataSource, UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT); + super(host, UmbMediaTypeDetailServerDataSource, UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts index 6f37542e8b..90cc2fc561 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts @@ -13,16 +13,16 @@ import type { UmbPropertyContainerTypes } from '@umbraco-cms/backoffice/content- /** * A data source for the Media Type that fetches data from the server - * @class UmbMediaTypeServerDataSource + * @class UmbMediaTypeDetailServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbMediaTypeServerDataSource implements UmbDetailDataSource { +export class UmbMediaTypeDetailServerDataSource implements UmbDetailDataSource { #host: UmbControllerHost; /** - * Creates an instance of UmbMediaTypeServerDataSource. + * Creates an instance of UmbMediaTypeDetailServerDataSource. * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbMediaTypeServerDataSource + * @memberof UmbMediaTypeDetailServerDataSource */ constructor(host: UmbControllerHost) { this.#host = host; @@ -32,7 +32,7 @@ export class UmbMediaTypeServerDataSource implements UmbDetailDataSource} [preset] * @returns { CreateMediaTypeRequestModel } - * @memberof UmbMediaTypeServerDataSource + * @memberof UmbMediaTypeDetailServerDataSource */ async createScaffold(preset: Partial = {}) { const data: UmbMediaTypeDetailModel = { @@ -61,7 +61,7 @@ export class UmbMediaTypeServerDataSource implements UmbDetailDataSource { - #host: UmbControllerHost; - - /** - * Creates an instance of UmbMediaServerDataSource. - * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbMediaServerDataSource - */ - constructor(host: UmbControllerHost) { - this.#host = host; - } - +export class UmbMediaServerDataSource extends UmbControllerBase implements UmbDetailDataSource { /** * Creates a new Media scaffold - * @param {Partial} [preset] + * @param {UmbDeepPartialObject} [preset] * @returns { UmbMediaDetailModel } * @memberof UmbMediaServerDataSource */ - async createScaffold(preset: Partial = {}) { - const data: UmbMediaDetailModel = { + async createScaffold(preset: UmbDeepPartialObject = {}) { + let mediaTypeIcon: string | null = null; + let mediaTypeCollection: UmbReferenceByUnique | null = null; + + const mediaTypeUnique = preset.mediaType?.unique; + + if (!mediaTypeUnique) { + throw new Error('Media type unique is missing'); + } + + const { data } = await new UmbMediaTypeDetailServerDataSource(this).read(mediaTypeUnique); + mediaTypeIcon = data?.icon ?? null; + mediaTypeCollection = data?.collection ?? null; + + const defaultData: UmbMediaDetailModel = { entityType: UMB_MEDIA_ENTITY_TYPE, unique: UmbId.new(), mediaType: { - unique: '', - collection: null, - icon: null, + unique: mediaTypeUnique, + collection: mediaTypeCollection, + icon: mediaTypeIcon, }, isTrashed: false, values: [], @@ -50,10 +55,11 @@ export class UmbMediaServerDataSource implements UmbDetailDataSource; + @state() + _icon?: string; + constructor() { super(); // TODO: Refactor: use a split view workspace context token: this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; - this._observeActiveVariantInfo(); + this.#observeActiveVariantInfo(); + this.#observeIcon(); }); } - private _observeActiveVariantInfo() { + #observeActiveVariantInfo() { if (!this._workspaceContext) return; this.observe( this._workspaceContext.splitView.activeVariantsInfo, @@ -33,6 +37,13 @@ export class UmbMediaWorkspaceSplitViewElement extends UmbLitElement { ); } + #observeIcon() { + if (!this._workspaceContext) return; + this.observe(this._workspaceContext.contentTypeIcon, (icon) => { + this._icon = icon ?? undefined; + }); + } + override render() { return this._variants ? html`
@@ -43,7 +54,9 @@ export class UmbMediaWorkspaceSplitViewElement extends UmbLitElement { (view) => html` + .displayNavigation=${view.index === this._variants!.length - 1}> + + `, )}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts index 5799bdf175..423d1cde14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts @@ -38,6 +38,7 @@ export class UmbMediaWorkspaceContext { readonly contentTypeUnique = this._data.createObservablePartOfCurrent((data) => data?.mediaType.unique); readonly contentTypeHasCollection = this._data.createObservablePartOfCurrent((data) => !!data?.mediaType.collection); + readonly contentTypeIcon = this._data.createObservablePartOfCurrent((data) => data?.mediaType.icon); #isTrashedContext = new UmbIsTrashedEntityContext(this); @@ -117,11 +118,10 @@ export class UmbMediaWorkspaceContext * @deprecated Use `createScaffold` instead. */ public async create(parent: { entityType: string; unique: string | null }, mediaTypeUnique: string) { - const args = { + return this.createScaffold({ parent, - preset: { mediaType: { unique: mediaTypeUnique, collection: null } }, - }; - return this.createScaffold(args); + preset: { mediaType: { unique: mediaTypeUnique } }, + }); } public getCollectionAlias() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/index.ts index 39f038ba4d..6494f6e308 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/index.ts @@ -1 +1,2 @@ export { UmbMemberTypeDetailRepository } from './member-type-detail.repository.js'; +export * from './member-type-detail.server.data-source.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.repository.ts index 478b731bbd..e70ef3b387 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.repository.ts @@ -1,5 +1,5 @@ import type { UmbMemberTypeDetailModel } from '../../types.js'; -import { UmbMemberTypeServerDataSource } from './member-type-detail.server.data-source.js'; +import { UmbMemberTypeDetailServerDataSource } from './member-type-detail.server.data-source.js'; import { UMB_MEMBER_TYPE_DETAIL_STORE_CONTEXT } from './member-type-detail.store.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbDetailRepositoryBase } from '@umbraco-cms/backoffice/repository'; @@ -16,7 +16,7 @@ export class UmbMemberTypeDetailRepository extends UmbDetailRepositoryBase} */ -export class UmbMemberTypeServerDataSource implements UmbDetailDataSource { +export class UmbMemberTypeDetailServerDataSource implements UmbDetailDataSource { #host: UmbControllerHost; /** - * Creates an instance of UmbMemberTypeServerDataSource. + * Creates an instance of UmbMemberTypeDetailServerDataSource. * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbMemberTypeServerDataSource + * @memberof UmbMemberTypeDetailServerDataSource */ constructor(host: UmbControllerHost) { this.#host = host; @@ -30,9 +30,9 @@ export class UmbMemberTypeServerDataSource implements UmbDetailDataSource} [preset] + * @param {Partial} [preset] - Optional preset data to merge with the scaffold * @returns { CreateMemberTypeRequestModel } - * @memberof UmbMemberTypeServerDataSource + * @memberof UmbMemberTypeDetailServerDataSource */ async createScaffold(preset: Partial = {}) { const data: UmbMemberTypeDetailModel = { @@ -59,9 +59,9 @@ export class UmbMemberTypeServerDataSource implements UmbDetailDataSource { - #host: UmbControllerHost; - - /** - * Creates an instance of UmbMemberServerDataSource. - * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbMemberServerDataSource - */ - constructor(host: UmbControllerHost) { - this.#host = host; - } - +export class UmbMemberServerDataSource extends UmbControllerBase implements UmbDetailDataSource { /** * Creates a new Member scaffold * @param {Partial} [preset] @@ -32,14 +23,25 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource = {}) { - const data: UmbMemberDetailModel = { + let memberTypeIcon = ''; + + const memberTypeUnique = preset.memberType?.unique; + + if (!memberTypeUnique) { + throw new Error('Document type unique is missing'); + } + + const { data } = await new UmbMemberTypeDetailServerDataSource(this).read(memberTypeUnique); + memberTypeIcon = data?.icon ?? ''; + + const defaultData: UmbMemberDetailModel = { entityType: UMB_MEMBER_ENTITY_TYPE, unique: UmbId.new(), email: '', username: '', memberType: { - unique: '', - icon: '', + unique: memberTypeUnique, + icon: memberTypeIcon, }, isApproved: false, isLockedOut: false, @@ -60,10 +62,11 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource; + @state() + _icon?: string; + constructor() { super(); // TODO: Refactor: use a split view workspace context token: this.consumeContext(UMB_MEMBER_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; - this._observeActiveVariantInfo(); + this.#observeActiveVariantInfo(); + this.#observeIcon(); }); } - private _observeActiveVariantInfo() { + #observeActiveVariantInfo() { if (!this._workspaceContext) return; this.observe( this._workspaceContext.splitView.activeVariantsInfo, @@ -34,6 +38,13 @@ export class UmbMemberWorkspaceSplitViewElement extends UmbLitElement { ); } + #observeIcon() { + if (!this._workspaceContext) return; + this.observe(this._workspaceContext.contentTypeIcon, (icon) => { + this._icon = icon ?? undefined; + }); + } + override render() { return this._variants ? html`
@@ -46,6 +57,7 @@ export class UmbMemberWorkspaceSplitViewElement extends UmbLitElement { back-path=${UMB_MEMBER_ROOT_WORKSPACE_PATH} .splitViewIndex=${view.index} .displayNavigation=${view.index === this._variants!.length - 1}> + `, )} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts index 19b0327095..ee4233573a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace.context.ts @@ -28,6 +28,7 @@ export class UmbMemberWorkspaceContext implements UmbContentWorkspaceContext { readonly contentTypeUnique = this._data.createObservablePartOfCurrent((data) => data?.memberType.unique); + readonly contentTypeIcon = this._data.createObservablePartOfCurrent((data) => data?.memberType.icon); readonly kind = this._data.createObservablePartOfCurrent((data) => data?.kind); readonly createDate = this._data.createObservablePartOfCurrent((data) => data?.variants[0].createDate); readonly updateDate = this._data.createObservablePartOfCurrent((data) => data?.variants[0].updateDate);