diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts index c6dd9ce6f5..558131b3e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/collection/repository/data-type-collection.server.data-source.ts @@ -5,6 +5,7 @@ import { DataTypeResource } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbCollectionDataSource } from '@umbraco-cms/backoffice/collection'; import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { type ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; /** * A data source that fetches the data-type collection data from the server. @@ -14,6 +15,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; */ export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataSource { #host: UmbControllerHost; + #manifestPropertyEditorUis: Array = []; /** * Creates an instance of UmbDataTypeCollectionServerDataSource. @@ -22,6 +24,12 @@ export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataS */ constructor(host: UmbControllerHost) { this.#host = host; + umbExtensionsRegistry + .byType('propertyEditorUi') + .subscribe((manifestPropertyEditorUIs) => { + this.#manifestPropertyEditorUis = manifestPropertyEditorUIs; + }) + .unsubscribe(); } /** @@ -48,6 +56,7 @@ export class UmbDataTypeCollectionServerDataSource implements UmbCollectionDataS unique: item.id, name: item.name, propertyEditorUiAlias: item.editorUiAlias!, + icon: this.#manifestPropertyEditorUis.find((ui) => ui.alias === item.editorUiAlias!)?.meta.icon, }; return dataTypeDetail; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts index 2f888c4a5b..d89712a6da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts @@ -78,8 +78,6 @@ export class UmbInputDataTypeElement extends FormControlMixin(UmbLitElement) { this.#editDataTypeModal?.open({}, 'edit/' + this._ids![0]); }} standalone> - - diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.element.ts index 4af4380ec5..e144ad4b2e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.element.ts @@ -1,7 +1,8 @@ import { UmbDataTypeDetailRepository } from '../../repository/detail/data-type-detail.repository.js'; -import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui'; +import { UUIIconRequestEvent, UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui'; import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; /** * @element umb-ref-data-type @@ -10,8 +11,10 @@ import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; */ @customElement('umb-ref-data-type') export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) { + @state() protected fallbackIcon = - ''; + ``; + //icon-circle-dotted.svg @property({ type: String, attribute: 'data-type-id' }) public get dataTypeId(): string | undefined { @@ -28,8 +31,11 @@ export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) { (dataType) => { if (dataType) { this.name = dataType.name ?? ''; - this.propertyEditorUiAlias = dataType.editorUiAlias ?? ''; this.propertyEditorSchemaAlias = dataType.editorAlias ?? ''; + if (dataType.editorUiAlias ?? '' !== this.propertyEditorUiAlias) { + this.propertyEditorUiAlias = dataType.editorUiAlias ?? ''; + this.#getIconFromUiAlias(); + } } }, 'dataType', @@ -53,6 +59,37 @@ export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) { @state() propertyEditorSchemaAlias = ''; + async #getIconFromUiAlias() { + if (!this.propertyEditorUiAlias) return; + this.observe( + umbExtensionsRegistry.byTypeAndAlias('propertyEditorUi', this.propertyEditorUiAlias), + async (manifestPropertyEditorUi) => { + const icon = manifestPropertyEditorUi?.meta.icon; + /** [LI] We have the icon name now, but because this element extends from uui-ref-node, it wants the icon via the icon slot. + * From what I can see, this is not possible via this file, but this is the file that have the datatype data.... + * Instead, overwriting the fallbackIcon property which requires a SVG... */ + if (icon) { + this.#requestIconSVG(icon); + } + }, + ), + '_observeIcon'; + } + + #requestIconSVG(iconName: string) { + if (iconName !== '' && iconName !== null) { + const event = new UUIIconRequestEvent(UUIIconRequestEvent.ICON_REQUEST, { + detail: { iconName: iconName }, + }); + this.dispatchEvent(event); + if (event.icon !== null) { + event.icon.then((iconSvg: string) => { + this.fallbackIcon = iconSvg; + }); + } + } + } + protected renderDetail() { const details: string[] = []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts index 9df268dfcf..23d0012b14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts @@ -86,7 +86,7 @@ export class UmbDataTypePickerFlowDataTypePickerModalElement extends UmbModalBas ? html`
  • - + ${dataType.name}
    diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index af03a97473..d0d634e4e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -1,4 +1,3 @@ -import { UmbDataTypeTreeRepository } from '../../tree/data-type-tree.repository.js'; import { UMB_DATATYPE_WORKSPACE_MODAL } from '../../workspace/data-type-workspace.modal-token.js'; import { UMB_DATA_TYPE_ENTITY_TYPE } from '../../entity.js'; import { UmbDataTypeCollectionRepository } from '../../collection/index.js'; @@ -275,10 +274,10 @@ export class UmbDataTypePickerFlowModalElement extends UmbModalBaseElement< dataTypes, (dataType) => dataType.unique, (dataType) => - html`
  • + html`
  • - + ${dataType.name}
    diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/data-type-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/data-type-item.server.data-source.ts index d2963a59c1..6e5faabc94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/data-type-item.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/data-type-item.server.data-source.ts @@ -3,6 +3,9 @@ import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository' import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { DataTypeResource } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { type ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; + +let manifestPropertyEditorUis: Array = []; /** * A server data source for Data Type items @@ -19,11 +22,19 @@ export class UmbDataTypeItemServerDataSource extends UmbItemServerDataSourceBase * @param {UmbControllerHost} host * @memberof UmbDataTypeItemServerDataSource */ + constructor(host: UmbControllerHost) { super(host, { getItems, mapper, }); + + umbExtensionsRegistry + .byType('propertyEditorUi') + .subscribe((manifestPropertyEditorUIs) => { + manifestPropertyEditorUis = manifestPropertyEditorUIs; + }) + .unsubscribe(); } } @@ -35,5 +46,6 @@ const mapper = (item: DataTypeItemResponseModel): UmbDataTypeItemModel => { unique: item.id, name: item.name, propertyEditorUiAlias: item.editorUiAlias || '', // TODO: why can this be undefined or null on the server? + icon: manifestPropertyEditorUis.find((ui) => ui.alias === item.editorUiAlias)?.meta.icon, }; }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/types.ts index d798ac80cc..185aa5cba4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/repository/item/types.ts @@ -2,4 +2,5 @@ export interface UmbDataTypeItemModel { unique: string; name: string; propertyEditorUiAlias: string; + icon?: string; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/data-type-tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/data-type-tree.server.data-source.ts index d4fda7664a..7f0af01905 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/data-type-tree.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/tree/data-type-tree.server.data-source.ts @@ -4,6 +4,9 @@ import { UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree'; import type { DataTypeTreeItemResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { DataTypeResource } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { type ManifestPropertyEditorUi, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; + +let manifestPropertyEditorUis: Array = []; /** * A data source for a data type tree that fetches data from the server @@ -26,12 +29,19 @@ export class UmbDataTypeTreeServerDataSource extends UmbTreeServerDataSourceBase getChildrenOf, mapper, }); + umbExtensionsRegistry + .byType('propertyEditorUi') + .subscribe((manifestPropertyEditorUIs) => { + manifestPropertyEditorUis = manifestPropertyEditorUIs; + }) + .unsubscribe(); } } -const getRootItems = (args: UmbTreeRootItemsRequestArgs) => +const getRootItems = async (args: UmbTreeRootItemsRequestArgs) => { // eslint-disable-next-line local-rules/no-direct-api-import - DataTypeResource.getTreeDataTypeRoot({ skip: args.skip, take: args.take }); + return DataTypeResource.getTreeDataTypeRoot({ skip: args.skip, take: args.take }); +}; const getChildrenOf = (args: UmbTreeChildrenOfRequestArgs) => { if (args.parentUnique === null) { @@ -48,6 +58,7 @@ const mapper = (item: DataTypeTreeItemResponseModel): UmbDataTypeTreeItemModel = return { unique: item.id, parentUnique: item.parent?.id || null, + icon: manifestPropertyEditorUis.find((ui) => ui.alias === item.editorUiAlias)?.meta.icon, name: item.name, entityType: item.isFolder ? 'data-type-folder' : 'data-type', isFolder: item.isFolder,