diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/index.ts new file mode 100644 index 0000000000..3d76f338dd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/index.ts @@ -0,0 +1 @@ +export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/manifests.ts new file mode 100644 index 0000000000..a8e101b348 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as repositoryManifests } from './repository/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.repository.ts new file mode 100644 index 0000000000..14c6215750 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.repository.ts @@ -0,0 +1,38 @@ +import { UmbDataTypeReferenceServerDataSource } from './data-type-reference.server.data.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { DataTypeReferenceResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export type UmbDataTypeReferenceModel = { + unique: string; + entityType: string; + properties: Array<{ name: string; alias: string }>; +}; + +export class UmbDataTypeReferenceRepository extends UmbControllerBase { + #referenceSource: UmbDataTypeReferenceServerDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#referenceSource = new UmbDataTypeReferenceServerDataSource(this); + } + + async requestReferencedBy(unique: string) { + if (!unique) throw new Error(`unique is required`); + + const { data } = await this.#referenceSource.getReferencedBy(unique); + if (!data) return; + + return data.map(mapper); + } +} + +const mapper = (item: DataTypeReferenceResponseModel): UmbDataTypeReferenceModel => { + return { + unique: item.id, + entityType: item.type, + properties: item.properties, + }; +}; + +export default UmbDataTypeReferenceRepository; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts new file mode 100644 index 0000000000..f1b6f15f43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/data-type-reference.server.data.ts @@ -0,0 +1,31 @@ +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { DataTypeService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +/** + * @export + * @class UmbDataTypeReferenceServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbDataTypeReferenceServerDataSource { + #host: UmbControllerHost; + + /** + * Creates an instance of UmbDataTypeReferenceServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbDataTypeReferenceServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + + /** + * Fetches the item for the given unique from the server + * @param {string} id + * @return {*} + * @memberof UmbDataTypeReferenceServerDataSource + */ + async getReferencedBy(id: string) { + return await tryExecuteAndNotify(this.#host, DataTypeService.getDataTypeByIdReferences({ id })); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/index.ts new file mode 100644 index 0000000000..7aedc48c92 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/index.ts @@ -0,0 +1 @@ +export * from './data-type-reference.repository.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/manifests.ts new file mode 100644 index 0000000000..4db28e40e8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/reference/repository/manifests.ts @@ -0,0 +1,12 @@ +import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_DATA_TYPE_REFERENCE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Reference'; + +const repository: ManifestRepository = { + type: 'repository', + alias: UMB_DATA_TYPE_REFERENCE_REPOSITORY_ALIAS, + name: 'Data Type Reference Repository', + api: () => import('./data-type-reference.repository.js'), +}; + +export const manifests: Array = [repository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts new file mode 100644 index 0000000000..cdda120f22 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts @@ -0,0 +1,117 @@ +import { UmbDataTypeReferenceRepository } from '../../../reference/index.js'; +import type { UmbDataTypeReferenceModel } from '../../../reference/index.js'; +import { css, html, customElement, state, repeat, property, when } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; +import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; + +const elementName = 'umb-data-type-workspace-view-info-reference'; + +@customElement(elementName) +export class UmbDataTypeWorkspaceViewInfoReferenceElement extends UmbLitElement { + #referenceRepository = new UmbDataTypeReferenceRepository(this); + + #routeBuilder?: UmbModalRouteBuilder; + + @property() + dataTypeUnique = ''; + + @state() + private _loading = true; + + @state() + private _items?: Array = []; + + constructor() { + super(); + + new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath(':entityType') + .onSetup((params) => { + return { data: { entityType: params.entityType, preset: {} } }; + }) + .observeRouteBuilder((routeBuilder) => { + this.#routeBuilder = routeBuilder; + }); + } + + protected firstUpdated() { + this.#getReferences(); + } + + async #getReferences() { + this._loading = true; + + const items = await this.#referenceRepository.requestReferencedBy(this.dataTypeUnique); + if (!items) return; + + this._items = items; + this._loading = false; + } + + render() { + return html` + + ${when( + this._loading, + () => html``, + () => this.#renderItems(), + )} + + `; + } + + #getEditPath(item: UmbDataTypeReferenceModel) { + // TODO: [LK] Ask NL for a reminder on how the route constants work. + return this.#routeBuilder ? this.#routeBuilder({ entityType: item.entityType }) + `edit/${item.unique}` : '#'; + } + + #renderItems() { + if (!this._items?.length) return html`

${this.localize.term('references_DataTypeNoReferences')}

`; + return html` + + + Name + Type + + Referenced by + + + ${repeat( + this._items, + (item) => item.unique, + (item) => html` + + + + + + + ${item.entityType} + ${item.properties.map((prop) => prop.name).join(', ')} + + `, + )} + + `; + } + + static styles = [ + UmbTextStyles, + css` + uui-table-cell { + color: var(--uui-color-text-alt); + } + `, + ]; +} + +export { UmbDataTypeWorkspaceViewInfoReferenceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbDataTypeWorkspaceViewInfoReferenceElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.element.ts index 1d8df1b8b3..90561c7203 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.element.ts @@ -4,10 +4,12 @@ import { css, html, customElement, state } from '@umbraco-cms/backoffice/externa import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import './data-type-workspace-view-info-reference.element.js'; + @customElement('umb-workspace-view-data-type-info') export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement implements UmbWorkspaceViewElement { @state() - _unique?: string; + _unique: string = ''; @state() _schemaAlias?: string; @@ -30,7 +32,7 @@ export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement implement if (!this._workspaceContext) return; this.observe(this._workspaceContext.unique, (unique) => { - this._unique = unique; + this._unique = unique!; }); this.observe(this._workspaceContext.propertyEditorSchemaAlias, (schemaAlias) => { @@ -43,36 +45,63 @@ export class UmbWorkspaceViewDataTypeInfoElement extends UmbLitElement implement } render() { - return html` ${this._renderGeneralInfo()}${this._renderReferences()} `; - } - - private _renderGeneralInfo() { return html` - - -
${this._unique}
-
- -
${this._schemaAlias}
-
- - -
${this._uiAlias}
-
-
+
+ +
+
${this.#renderGeneralInfo()}
`; } - private _renderReferences() { - return html` `; + #renderGeneralInfo() { + return html` + +
+ Id + ${this._unique} +
+
+ Property Editor Schema Alias + ${this._schemaAlias} +
+
+ Property Editor UI Alias + ${this._uiAlias} +
+
+ `; } static styles = [ UmbTextStyles, css` :host { - display: block; + display: grid; + gap: var(--uui-size-layout-1); padding: var(--uui-size-layout-1); + grid-template-columns: 1fr 350px; + } + + .container { + display: flex; + flex-direction: column; + gap: var(--uui-size-layout-1); + } + + #general-section { + display: flex; + flex-direction: column; + } + + .general-item { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-1); + } + + .general-item:not(:last-child) { + margin-bottom: var(--uui-size-space-6); } `, ];