diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/default-item-ref.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/default-item-ref.element.ts new file mode 100644 index 000000000000..25c32cafd65a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/default-item-ref.element.ts @@ -0,0 +1,37 @@ +import type { UmbDefaultItemModel } from '../types.js'; +import { customElement, html, nothing, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +@customElement('umb-default-item-ref') +export class UmbDefaultItemRefElement extends UmbLitElement { + @property({ type: Object }) + item?: UmbDefaultItemModel; + + @property({ type: Boolean }) + readonly = false; + + @property({ type: Boolean }) + standalone = false; + + override render() { + if (!this.item) return nothing; + + return html` + + + ${this.#renderIcon(this.item)} + + `; + } + + #renderIcon(item: UmbDefaultItemModel) { + if (!item.icon) return; + return html``; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-default-item-ref': UmbDefaultItemRefElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/entity-item-ref.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/entity-item-ref.element.ts new file mode 100644 index 000000000000..a76e1c36c062 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/entity-item-ref.element.ts @@ -0,0 +1,124 @@ +import type { UmbEntityModel } from '../types.js'; +import type { ManifestEntityItemRef } from './entity-item-ref.extension.js'; +import { customElement, property, type PropertyValueMap, state, css, html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbExtensionsElementInitializer } from '@umbraco-cms/backoffice/extension-api'; +import { UMB_MARK_ATTRIBUTE_NAME } from '@umbraco-cms/backoffice/const'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; + +import './default-item-ref.element.js'; + +@customElement('umb-entity-item-ref') +export class UmbEntityItemRefElement extends UmbLitElement { + #extensionsController?: UmbExtensionsElementInitializer; + #item?: UmbEntityModel; + + @state() + _component?: any; // TODO: Add type + + @property({ type: Object, attribute: false }) + public get item(): UmbEntityModel | undefined { + return this.#item; + } + public set item(value: UmbEntityModel | undefined) { + const oldValue = this.#item; + this.#item = value; + + if (value === oldValue) return; + if (!value) return; + + // If the component is already created and the entity type is the same, we can just update the item. + if (this._component && value.entityType === oldValue?.entityType) { + this._component.item = value; + return; + } + + // If the component is already created, but the entity type is different, we need to destroy the component. + this.#createController(value.entityType); + } + + #readonly = false; + @property({ type: Boolean, attribute: 'readonly' }) + public get readonly() { + return this.#readonly; + } + public set readonly(value) { + this.#readonly = value; + + if (this._component) { + this._component.readonly = this.#readonly; + } + } + + #standalone = false; + @property({ type: Boolean, attribute: 'standalone' }) + public get standalone() { + return this.#standalone; + } + public set standalone(value) { + this.#standalone = value; + + if (this._component) { + this._component.standalone = this.#standalone; + } + } + + protected override firstUpdated(_changedProperties: PropertyValueMap | Map): void { + super.firstUpdated(_changedProperties); + this.setAttribute(UMB_MARK_ATTRIBUTE_NAME, 'entity-item-ref'); + } + + #createController(entityType: string) { + if (this.#extensionsController) { + this.#extensionsController.destroy(); + } + + this.#extensionsController = new UmbExtensionsElementInitializer( + this, + umbExtensionsRegistry, + 'entityItemRef', + (manifest: ManifestEntityItemRef) => manifest.forEntityTypes.includes(entityType), + (extensionControllers) => { + this._component?.remove(); + const component = extensionControllers[0]?.component || document.createElement('umb-default-item-ref'); + + // assign the properties to the component + component.item = this.#item; + component.readonly = this.readonly; + component.standalone = this.standalone; + + // Proxy the actions slot to the component + const slotElement = document.createElement('slot'); + slotElement.name = 'actions'; + slotElement.setAttribute('slot', 'actions'); + component.appendChild(slotElement); + + this._component = component; + }, + undefined, // We can leave the alias to undefined, as we destroy this our selfs. + undefined, + { single: true }, + ); + } + + override render() { + return html`${this._component}`; + } + + static override styles = [ + css` + :host { + display: block; + position: relative; + } + `, + ]; +} + +export { UmbEntityItemRefElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-entity-item-ref': UmbEntityItemRefElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/entity-item-ref.extension.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/entity-item-ref.extension.ts new file mode 100644 index 000000000000..9b4d9d43daea --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/entity-item-ref.extension.ts @@ -0,0 +1,18 @@ +import type { ManifestElement, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; + +export interface ManifestEntityItemRef + extends ManifestElement, + ManifestWithDynamicConditions { + type: 'entityItemRef'; + meta: MetaType; + forEntityTypes: Array; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface MetaEntityItemRef {} + +declare global { + interface UmbExtensionManifestMap { + umbManifestEntityItemRef: ManifestEntityItemRef; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/index.ts new file mode 100644 index 000000000000..338849e06997 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/index.ts @@ -0,0 +1,3 @@ +import './entity-item-ref.element.js'; + +export * from './entity-item-ref.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/types.ts new file mode 100644 index 000000000000..06c33f562f4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity-item-ref/types.ts @@ -0,0 +1 @@ +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts index 737d7bf4828c..7fbfc9d7f634 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/index.ts @@ -1,3 +1,4 @@ export { UMB_ENTITY_CONTEXT } from './entity.context-token.js'; export { UmbEntityContext } from './entity.context.js'; +export * from './entity-item-ref/index.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/types.ts index f2fcb7dde994..09ec5529e207 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/types.ts @@ -8,3 +8,7 @@ export interface UmbEntityModel { export interface UmbNamedEntityModel extends UmbEntityModel { name: string; } + +export interface UmbDefaultItemModel extends UmbNamedEntityModel { + icon?: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/index.ts index 5aee89bb955f..66eb8d0b6067 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/index.ts @@ -1 +1,2 @@ export * from './picker-input.context.js'; +export * from './picker-input.context-token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context-token.ts new file mode 100644 index 000000000000..e208597b4770 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context-token.ts @@ -0,0 +1,4 @@ +import type { UmbPickerInputContext } from './picker-input.context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export const UMB_PICKER_INPUT_CONTEXT = new UmbContextToken('UmbPickerInputContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts index 1a597bf8af68..057ba23d72b9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts @@ -1,5 +1,6 @@ +import { UMB_PICKER_INPUT_CONTEXT } from './picker-input.context-token.js'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; import { UMB_MODAL_MANAGER_CONTEXT, umbConfirmModal } from '@umbraco-cms/backoffice/modal'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -13,7 +14,7 @@ export class UmbPickerInputContext< PickerItemType extends PickerItemBaseType = PickedItemType, PickerModalConfigType extends UmbPickerModalData = UmbPickerModalData, PickerModalValueType extends UmbPickerModalValue = UmbPickerModalValue, -> extends UmbControllerBase { +> extends UmbContextBase { modalAlias: string | UmbModalToken, PickerModalValueType>; repository?: UmbItemRepository; #getUnique: (entry: PickedItemType) => string | undefined; @@ -59,9 +60,8 @@ export class UmbPickerInputContext< modalAlias: string | UmbModalToken, PickerModalValueType>, getUniqueMethod?: (entry: PickedItemType) => string | undefined, ) { - super(host); + super(host, UMB_PICKER_INPUT_CONTEXT); this.modalAlias = modalAlias; - this.#getUnique = getUniqueMethod || ((entry) => entry.unique); this.#getUnique = getUniqueMethod ? (entry: PickedItemType) => { @@ -74,7 +74,7 @@ export class UmbPickerInputContext< } : (entry) => entry.unique; - this.#itemManager = new UmbRepositoryItemsManager(this, repositoryAlias, this.#getUnique); + this.#itemManager = new UmbRepositoryItemsManager(this, repositoryAlias, getUniqueMethod); this.selection = this.#itemManager.uniques; this.selectedItems = this.#itemManager.items; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.context.ts index 75b2b2c42a90..6d9f07bc551a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.context.ts @@ -1,10 +1,7 @@ import type { UmbDocumentPickerModalData, UmbDocumentPickerModalValue } from '../../modals/types.js'; -import { - UMB_DOCUMENT_PICKER_MODAL, - UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS, - UMB_DOCUMENT_SEARCH_PROVIDER_ALIAS, -} from '../../constants.js'; -import type { UmbDocumentItemModel } from '../../repository/index.js'; +import { UMB_DOCUMENT_PICKER_MODAL, UMB_DOCUMENT_SEARCH_PROVIDER_ALIAS } from '../../constants.js'; +import type { UmbDocumentItemModel } from '../../item/types.js'; +import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../item/constants.js'; import type { UmbDocumentTreeItemModel } from '../../tree/types.js'; import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts index c16b2c675968..1f8b902c4521 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.element.ts @@ -1,30 +1,15 @@ import { UmbDocumentPickerInputContext } from './input-document.context.js'; -import { - classMap, - css, - customElement, - html, - ifDefined, - nothing, - property, - repeat, - state, - when, -} from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; -import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { UmbDocumentItemModel } from '@umbraco-cms/backoffice/document'; import type { UmbTreeStartNode } from '@umbraco-cms/backoffice/tree'; import { UMB_DOCUMENT_TYPE_ENTITY_TYPE } from '@umbraco-cms/backoffice/document-type'; -const elementName = 'umb-input-document'; - -@customElement(elementName) +@customElement('umb-input-document') export class UmbInputDocumentElement extends UmbFormControlMixin( UmbLitElement, ) { @@ -36,7 +21,7 @@ export class UmbInputDocumentElement extends UmbFormControlMixin { this.selection = model; @@ -136,9 +121,6 @@ export class UmbInputDocumentElement extends UmbFormControlMixin; @@ -147,15 +129,6 @@ export class UmbInputDocumentElement extends UmbFormControlMixin { - return { data: { entityType: 'document', preset: {} } }; - }) - .observeRouteBuilder((routeBuilder) => { - this._editDocumentPath = routeBuilder({}); - }); - this.addValidator( 'rangeUnderflow', () => this.minMessage, @@ -172,10 +145,6 @@ export class UmbInputDocumentElement extends UmbFormControlMixin (this._items = selectedItems), '_observerItems'); } - #isDraft(item: UmbDocumentItemModel) { - return item.variants[0]?.state === 'Draft'; - } - #openPicker() { this.#pickerContext.openPicker( { @@ -222,61 +191,37 @@ export class UmbInputDocumentElement extends UmbFormControlMixin item.unique, - (item) => this.#renderItem(item), + (item) => + html` + ${when( + !this.readonly, + () => html` + + this.#onRemove(item)}> + + `, + )} + `, )} `; } - #renderItem(item: UmbDocumentItemModel) { - if (!item.unique) return; - const href = !this.readonly && this.showOpenButton ? `${this._editDocumentPath}edit/${item.unique}` : undefined; - return html` - - ${this.#renderIcon(item)} ${this.#renderIsTrashed(item)} - ${when( - !this.readonly, - () => html` - - this.#onRemove(item)}> - - `, - )} - - `; - } - - #renderIcon(item: UmbDocumentItemModel) { - if (!item.documentType.icon) return; - return html``; - } - - #renderIsTrashed(item: UmbDocumentItemModel) { - if (!item.isTrashed) return; - return html`Trashed`; - } - static override styles = [ css` #btn-add { display: block; } - uui-ref-node[drag-placeholder] { + umb-entity-item-ref[drag-placeholder] { opacity: 0.2; } - - .draft { - opacity: 0.6; - } `, ]; } @@ -285,6 +230,6 @@ export { UmbInputDocumentElement as element }; declare global { interface HTMLElementTagNameMap { - [elementName]: UmbInputDocumentElement; + 'umb-input-document': UmbInputDocumentElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts index 456994bdd613..b0cd03a572f1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/constants.ts @@ -3,6 +3,7 @@ export { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from './entit export * from './collection/constants.js'; export * from './entity-actions/constants.js'; export * from './entity-bulk-actions/constants.js'; +export * from './item/constants.js'; export * from './modals/constants.js'; export * from './paths.js'; export * from './property-dataset-context/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts index 2bcc382622f7..af2adec3bef7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/create.action.ts @@ -1,4 +1,4 @@ -import { UmbDocumentItemRepository } from '../../repository/index.js'; +import { UmbDocumentItemRepository } from '../../item/index.js'; import { UMB_DOCUMENT_CREATE_OPTIONS_MODAL } from './document-create-options-modal.token.js'; import type { UmbEntityActionArgs } from '@umbraco-cms/backoffice/entity-action'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index 419bd85a626f..1dbf684c995d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -1,4 +1,4 @@ -import { UmbDocumentItemRepository } from '../../repository/index.js'; +import { UmbDocumentItemRepository } from '../../item/index.js'; import type { UmbDocumentCreateOptionsModalData, UmbDocumentCreateOptionsModalValue, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts index 8caa4a29f5c1..3c1a1fcd1be2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts @@ -1,4 +1,5 @@ -import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; +import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js'; +import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../item/constants.js'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; import { UMB_USER_PERMISSION_DOCUMENT_DELETE } from '../user-permissions/constants.js'; import { manifests as createBlueprintManifests } from './create-blueprint/manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/modal/document-notifications-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/modal/document-notifications-modal.element.ts index b1d9683fc1f8..061c60669c1a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/modal/document-notifications-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/modal/document-notifications-modal.element.ts @@ -1,4 +1,4 @@ -import { UmbDocumentItemRepository } from '../../../repository/index.js'; +import { UmbDocumentItemRepository } from '../../../item/index.js'; import { UmbDocumentNotificationsRepository } from '../repository/document-notifications.repository.js'; import type { UmbDocumentNotificationsModalData } from './document-notifications-modal.token.js'; import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/modal/public-access-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/modal/public-access-modal.element.ts index e246b11ae21e..90d08daedc48 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/modal/public-access-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/modal/public-access-modal.element.ts @@ -1,5 +1,5 @@ import { UmbDocumentPublicAccessRepository } from '../repository/public-access.repository.js'; -import { UmbDocumentItemRepository } from '../../../repository/index.js'; +import { UmbDocumentItemRepository } from '../../../item/index.js'; import type { UmbInputDocumentElement } from '../../../components/index.js'; import type { UmbPublicAccessModalData, UmbPublicAccessModalValue } from './public-access-modal.token.js'; import { css, customElement, html, nothing, state } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts index 41a9ecade2f0..39f00ca0f828 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js'; +import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../item/constants.js'; import { UMB_DOCUMENT_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; import { UMB_USER_PERMISSION_DOCUMENT_SORT } from '../../user-permissions/index.js'; import { UMB_SORT_CHILDREN_OF_DOCUMENT_REPOSITORY_ALIAS } from './repository/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts index fcc6565ced8d..a14bf00b99e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts @@ -5,16 +5,17 @@ export * from './components/index.js'; export * from './constants.js'; export * from './entity-actions/index.js'; export * from './global-contexts/index.js'; +export * from './item/index.js'; export * from './modals/index.js'; export * from './paths.js'; export * from './publishing/index.js'; export * from './recycle-bin/index.js'; export * from './reference/index.js'; export * from './repository/index.js'; +export * from './tree/index.js'; export * from './url/index.js'; export * from './user-permissions/index.js'; -export * from './tree/index.js'; export { UMB_CONTENT_MENU_ALIAS } from './menu/manifests.js'; export { UMB_DOCUMENT_COLLECTION_ALIAS } from './collection/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/constants.ts new file mode 100644 index 000000000000..41a409dec1f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/constants.ts @@ -0,0 +1 @@ +export * from './repository/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-ref.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-ref.element.ts new file mode 100644 index 000000000000..3b57e75ca9bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-ref.element.ts @@ -0,0 +1,115 @@ +import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; +import type { UmbDocumentItemModel } from './types.js'; +import { + classMap, + css, + customElement, + html, + ifDefined, + nothing, + property, + state, +} from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; + +@customElement('umb-document-item-ref') +export class UmbDocumentItemRefElement extends UmbLitElement { + #item?: UmbDocumentItemModel | undefined; + + @property({ type: Object }) + public get item(): UmbDocumentItemModel | undefined { + return this.#item; + } + public set item(value: UmbDocumentItemModel | undefined) { + const oldValue = this.#item; + this.#item = value; + + if (!this.#item) { + this.#modalRoute?.destroy(); + return; + } + + if (oldValue?.unique === this.#item.unique) { + return; + } + + this.#modalRoute?.setUniquePathValue('unique', this.#item.unique); + } + + @property({ type: Boolean }) + readonly = false; + + @property({ type: Boolean }) + standalone = false; + + @state() + _editPath = ''; + + #modalRoute?: any; + + constructor() { + super(); + + this.#modalRoute = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath(UMB_DOCUMENT_ENTITY_TYPE) + .addUniquePaths(['unique']) + .onSetup(() => { + return { data: { entityType: UMB_DOCUMENT_ENTITY_TYPE, preset: {} } }; + }) + .observeRouteBuilder((routeBuilder) => { + this._editPath = routeBuilder({}); + }); + } + + #isDraft(item: UmbDocumentItemModel) { + return item.variants[0]?.state === 'Draft'; + } + + #getHref(item: UmbDocumentItemModel) { + return `${this._editPath}/edit/${item.unique}`; + } + + override render() { + if (!this.item) return nothing; + + return html` + + + ${this.#renderIcon(this.item)} ${this.#renderIsTrashed(this.item)} + + `; + } + + #renderIcon(item: UmbDocumentItemModel) { + if (!item.documentType.icon) return; + return html``; + } + + #renderIsTrashed(item: UmbDocumentItemModel) { + if (!item.isTrashed) return; + return html`Trashed`; + } + + static override styles = [ + css` + .draft { + opacity: 0.6; + } + `, + ]; +} + +export { UmbDocumentItemRefElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-item-ref': UmbDocumentItemRefElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/index.ts new file mode 100644 index 000000000000..f6365499927d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/index.ts @@ -0,0 +1 @@ +export { UmbDocumentItemRepository } from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/manifests.ts new file mode 100644 index 000000000000..16a6e20374f2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/manifests.ts @@ -0,0 +1,13 @@ +import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; + +export const manifests: Array = [ + { + type: 'entityItemRef', + alias: 'Umb.EntityItemRef.Document', + name: 'Document Entity Item Reference', + element: () => import('./document-item-ref.element.js'), + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + }, + ...repositoryManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.repository.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.repository.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.server.data-source.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.server.data-source.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.server.data-source.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.store.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.store.context-token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.store.context-token.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.store.context-token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.store.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.store.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/document-item.store.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/document-item.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/item/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/repository/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/types.ts new file mode 100644 index 000000000000..281be3f829a9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/types.ts @@ -0,0 +1 @@ +export type { UmbDocumentItemModel } from './repository/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts index e744094a3c84..c7910bc1b5c3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts @@ -3,6 +3,7 @@ import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; import { manifests as globalContextManifests } from './global-contexts/manifests.js'; +import { manifests as itemManifests } from './item/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; @@ -26,6 +27,7 @@ export const manifests: Array = ...entityActionManifests, ...entityBulkActionManifests, ...globalContextManifests, + ...itemManifests, ...menuManifests, ...modalManifests, ...pickerManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts index f4d9b410dee9..bf4f63f5d34a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/manifests.ts @@ -5,7 +5,7 @@ import { UMB_USER_PERMISSION_DOCUMENT_DELETE, UMB_USER_PERMISSION_DOCUMENT_MOVE, } from '../../constants.js'; -import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../repository/constants.js'; +import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../item/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS, UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/constants.ts index 7a6c4a9d9c73..7846cdeb9a47 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/constants.ts @@ -1,3 +1,2 @@ export * from './detail/constants.js'; -export * from './item/constants.js'; export * from './validation/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts index 8059abd30dde..6025dec443a4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/index.ts @@ -1,6 +1,4 @@ export { UmbDocumentDetailRepository } from './detail/index.js'; -export { UmbDocumentItemRepository } from './item/index.js'; export { UmbDocumentPreviewRepository } from './preview/index.js'; export * from './constants.js'; -export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts index 4dfb0c911f4e..3c7f8d7aaf69 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/manifests.ts @@ -1,4 +1,3 @@ import { manifests as detailManifests } from './detail/manifests.js'; -import { manifests as itemManifests } from './item/manifests.js'; -export const manifests: Array = [...detailManifests, ...itemManifests]; +export const manifests: Array = [...detailManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts deleted file mode 100644 index 204e345ff932..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type { UmbDocumentItemModel } from './item/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts index f7907e593572..4cd8d71a5944 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts @@ -1,4 +1,4 @@ -import type { UmbDocumentItemModel, UmbDocumentItemVariantModel } from '../repository/item/types.js'; +import type { UmbDocumentItemModel, UmbDocumentItemVariantModel } from '../item/repository/types.js'; import type { UmbSearchResultItemModel } from '@umbraco-cms/backoffice/search'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts index a63f89853bd7..3b12d8b51a97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/types.ts @@ -1,4 +1,4 @@ -import type { UmbDocumentItemModel } from '../repository/index.js'; +import type { UmbDocumentItemModel } from '../item/types.js'; import type { UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; import type { UmbDocumentTypeEntityType } from '@umbraco-cms/backoffice/document-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts index a3407cf5aa4a..c6bd94ae241d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts @@ -10,15 +10,15 @@ import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/b export { UmbDocumentVariantState }; export type * from './audit-log/types.js'; -export type * from './recycle-bin/types.js'; export type * from './collection/types.js'; +export type * from './entity.js'; +export type * from './item/types.js'; export type * from './modals/types.js'; -export type * from './repository/types.js'; +export type * from './publishing/types.js'; +export type * from './recycle-bin/types.js'; export type * from './tree/types.js'; export type * from './user-permissions/types.js'; -export type * from './entity.js'; export type * from './workspace/types.js'; -export type * from './publishing/types.js'; export interface UmbDocumentDetailModel extends UmbContentDetailModel { documentType: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index c83a9975d1d2..512fc7af2a04 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -1,5 +1,6 @@ import type { UmbDocumentUserPermissionModel } from '../types.js'; -import { UmbDocumentItemRepository, type UmbDocumentItemModel } from '../../repository/index.js'; +import { UmbDocumentItemRepository } from '../../item/index.js'; +import type { UmbDocumentItemModel } from '../../item/types.js'; import { UMB_DOCUMENT_PICKER_MODAL } from '../../constants.js'; import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.context.ts index b8c77827b967..350e9b1ae4aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.context.ts @@ -1,4 +1,4 @@ -import type { UmbMemberItemModel } from '../../repository/index.js'; +import type { UmbMemberItemModel } from '../../item/types.js'; import { UMB_MEMBER_PICKER_MODAL, type UmbMemberPickerModalData, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts index fd594ad89884..0d903b5dee7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.element.ts @@ -1,14 +1,12 @@ -import type { UmbMemberItemModel } from '../../repository/index.js'; +import type { UmbMemberItemModel } from '../../item/types.js'; import { UmbMemberPickerInputContext } from './input-member.context.js'; -import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, nothing, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { UMB_MEMBER_TYPE_ENTITY_TYPE } from '@umbraco-cms/backoffice/member-type'; -import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; @customElement('umb-input-member') export class UmbInputMemberElement extends UmbFormControlMixin( @@ -22,7 +20,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin { this.selection = model; @@ -84,9 +82,6 @@ export class UmbInputMemberElement extends UmbFormControlMixin; @@ -133,15 +125,6 @@ export class UmbInputMemberElement extends UmbFormControlMixin { - return { data: { entityType: 'member', preset: {} } }; - }) - .observeRouteBuilder((routeBuilder) => { - this._editMemberPath = routeBuilder({}); - }); - this.addValidator( 'rangeUnderflow', () => this.minMessage, @@ -193,6 +176,15 @@ export class UmbInputMemberElement extends UmbFormControlMixin + ${this.#renderRemoveButton(item)} + + `; + } + #renderAddButton() { if (this.selection.length >= this.max) return nothing; if (this.readonly && this.selection.length > 0) { @@ -209,29 +201,6 @@ export class UmbInputMemberElement extends UmbFormControlMixin - ${when(item.memberType.icon, (icon) => html``)} - - ${this.#renderOpenButton(item)} ${this.#renderRemoveButton(item)} - - - `; - } - - #renderOpenButton(item: UmbMemberItemModel) { - if (!this.showOpenButton) return nothing; - return html` - - - - `; - } - #renderRemoveButton(item: UmbMemberItemModel) { if (this.readonly) return nothing; return html` @@ -245,7 +214,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin = [ + { + type: 'entityItemRef', + alias: 'Umb.EntityItemRef.Member', + name: 'Member Entity Item Reference', + element: () => import('./member-item-ref.element.js'), + forEntityTypes: [UMB_MEMBER_ENTITY_TYPE], + }, + ...repositoryManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/item/member-item-ref.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/member-item-ref.element.ts new file mode 100644 index 000000000000..2dbfb4848b5a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/member-item-ref.element.ts @@ -0,0 +1,104 @@ +import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js'; +import { UMB_MEMBER_MANAGEMENT_SECTION_ALIAS } from '../../section/constants.js'; +import type { UmbMemberItemModel } from './repository/types.js'; +import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; +import { customElement, html, ifDefined, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; +import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; + +@customElement('umb-member-item-ref') +export class UmbMemberItemRefElement extends UmbLitElement { + #item?: UmbMemberItemModel | undefined; + + @property({ type: Object }) + public get item(): UmbMemberItemModel | undefined { + return this.#item; + } + public set item(value: UmbMemberItemModel | undefined) { + const oldValue = this.#item; + this.#item = value; + + if (!this.#item) { + this.#modalRoute?.destroy(); + return; + } + if (oldValue?.unique === this.#item.unique) { + return; + } + + this.#modalRoute?.setUniquePathValue('unique', this.#item.unique); + } + + @property({ type: Boolean }) + readonly = false; + + @property({ type: Boolean }) + standalone = false; + + @state() + _editPath = ''; + + @state() + _userHasSectionAccess = false; + + #modalRoute?: any; + + constructor() { + super(); + + createExtensionApiByAlias(this, UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + match: UMB_MEMBER_MANAGEMENT_SECTION_ALIAS, + }, + onChange: (permitted: boolean) => { + this._userHasSectionAccess = permitted; + }, + }, + ]); + + this.#modalRoute = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath(UMB_MEMBER_ENTITY_TYPE) + .addUniquePaths(['unique']) + .onSetup(() => { + return { data: { entityType: UMB_MEMBER_ENTITY_TYPE, preset: {} } }; + }) + .observeRouteBuilder((routeBuilder) => { + this._editPath = routeBuilder({}); + }); + } + + #getHref(item: UmbMemberItemModel) { + return `${this._editPath}/edit/${item.unique}`; + } + + override render() { + if (!this.item) return nothing; + + return html` + + + ${this.#renderIcon(this.item)} + + `; + } + + #renderIcon(item: UmbMemberItemModel) { + if (!item.memberType.icon) return; + return html``; + } +} + +export { UmbMemberItemRefElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-member-item-ref': UmbMemberItemRefElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.repository.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.repository.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.server.data-source.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.server.data-source.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.server.data-source.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.store.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.store.context-token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.store.context-token.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.store.context-token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.store.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.store.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/member-item.store.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/member-item.store.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/members/member/repository/item/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/members/member/item/repository/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/item/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/types.ts new file mode 100644 index 000000000000..e32ac4b889fe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/item/types.ts @@ -0,0 +1 @@ +export type * from './repository/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts index 84682bbb25be..470f6503b329 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/manifests.ts @@ -1,5 +1,6 @@ import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; +import { manifests as itemManifests } from './item/manifests.js'; import { manifests as memberPickerModalManifests } from './components/member-picker-modal/manifests.js'; import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; @@ -13,6 +14,7 @@ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, + ...itemManifests, ...memberPickerModalManifests, ...menuItemManifests, ...pickerManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/constants.ts index 5409d1b6b838..0f60420161b0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/constants.ts @@ -1,2 +1 @@ export * from './detail/constants.js'; -export * from './item/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/index.ts index d54682b8ca73..f54e601fc57e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/index.ts @@ -1,3 +1,2 @@ export { UmbMemberDetailRepository } from './detail/index.js'; -export { UmbMemberItemRepository, type UmbMemberItemModel } from './item/index.js'; export * from './validation/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/manifests.ts index 74a3121896bb..b4c5404d8422 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/manifests.ts @@ -1,5 +1,4 @@ import { manifests as detailManifests } from './detail/manifests.js'; -import { manifests as itemManifests } from './item/manifests.js'; import { manifests as validationManifests } from './validation/manifests.js'; -export const manifests: Array = [...detailManifests, ...itemManifests, ...validationManifests]; +export const manifests: Array = [...detailManifests, ...validationManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/member-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/member-repository-base.ts index c8a0464f7a2f..74257955e161 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/member-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/member-repository-base.ts @@ -1,7 +1,7 @@ import type { UmbMemberDetailStore } from './detail/member-detail.store.js'; import { UMB_MEMBER_DETAIL_STORE_CONTEXT } from './detail/member-detail.store.context-token.js'; -import type { UmbMemberItemStore } from './item/member-item.store.js'; -import { UMB_MEMBER_ITEM_STORE_CONTEXT } from './item/member-item.store.context-token.js'; +import type { UmbMemberItemStore } from '../item/repository/member-item.store.js'; +import { UMB_MEMBER_ITEM_STORE_CONTEXT } from '../item/repository/member-item.store.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; import { UMB_NOTIFICATION_CONTEXT } from '@umbraco-cms/backoffice/notification'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/types.ts index 6ee8fceef593..1970d6108500 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/search/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/search/types.ts @@ -1,4 +1,4 @@ -import type { UmbMemberItemModel } from '../repository/index.js'; +import type { UmbMemberItemModel } from '../item/types.js'; import type { UmbMemberTypeEntityType } from '@umbraco-cms/backoffice/member-type'; import type { UmbSearchRequestArgs } from '@umbraco-cms/backoffice/search'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index 44fb8d298cfc..cb8c9c153dcc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -5,6 +5,8 @@ import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/b export type * from './entity.js'; export type * from './collection/types.js'; +export type * from './item/types.js'; + export interface UmbMemberDetailModel extends UmbContentDetailModel { email: string; entityType: UmbMemberEntityType; @@ -19,7 +21,7 @@ export interface UmbMemberDetailModel extends UmbContentDetailModel { lastPasswordChangeDate: string | null; memberType: { unique: string; - icon: string; + icon: string; }; newPassword?: string; oldPassword?: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts index 118cdc4a3677..f5621924100a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.element.ts @@ -18,7 +18,7 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') return modelEntry; }, identifier: 'Umb.SorterIdentifier.InputUser', - itemSelector: 'uui-ref-node-user', + itemSelector: 'umb-entity-item-ref', containerSelector: 'uui-ref-list', onChange: ({ model }) => { this.selection = model; @@ -156,16 +156,11 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') #renderItem(item: UmbUserItemModel) { if (!item.unique) return nothing; return html` - - + this.#removeItem(item)}> - + `; } @@ -174,10 +169,6 @@ export class UmbUserInputElement extends UUIFormControlMixin(UmbLitElement, '') #btn-add { width: 100%; } - - umb-user-avatar { - font-size: var(--uui-size-4); - } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/item/manifests.ts new file mode 100644 index 000000000000..460383ab2103 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/item/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; + +export const manifests: Array = [ + { + type: 'entityItemRef', + alias: 'Umb.EntityItemRef.User', + name: 'User Entity Item Reference', + element: () => import('./user-item-ref.element.js'), + forEntityTypes: [UMB_USER_ENTITY_TYPE], + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/item/user-item-ref.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/item/user-item-ref.element.ts new file mode 100644 index 000000000000..f910931ba47c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/item/user-item-ref.element.ts @@ -0,0 +1,112 @@ +import { UMB_USER_ENTITY_TYPE } from '../entity.js'; +import type { UmbUserItemModel } from '../repository/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/constants.js'; +import { css, customElement, html, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; +import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section'; +import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/workspace'; +import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; + +@customElement('umb-user-item-ref') +export class UmbUserItemRefElement extends UmbLitElement { + #item?: UmbUserItemModel | undefined; + + @property({ type: Object }) + public get item(): UmbUserItemModel | undefined { + return this.#item; + } + public set item(value: UmbUserItemModel | undefined) { + const oldValue = this.#item; + this.#item = value; + + if (!this.#item) { + this.#modalRoute?.destroy(); + return; + } + + if (oldValue?.unique === this.#item.unique) { + return; + } + + this.#modalRoute?.setUniquePathValue('unique', this.#item.unique); + } + + @property({ type: Boolean }) + readonly = false; + + @property({ type: Boolean }) + standalone = false; + + @state() + _editPath = ''; + + @state() + _userHasSectionAccess = false; + + #modalRoute?: any; + + constructor() { + super(); + + createExtensionApiByAlias(this, UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + onChange: (permitted: boolean) => { + this._userHasSectionAccess = permitted; + }, + }, + ]); + + this.#modalRoute = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath(UMB_USER_ENTITY_TYPE) + .addUniquePaths(['unique']) + .onSetup(() => { + return { data: { entityType: UMB_USER_ENTITY_TYPE, preset: {} } }; + }) + .observeRouteBuilder((routeBuilder) => { + this._editPath = routeBuilder({}); + }); + } + + #getHref(item: UmbUserItemModel) { + return `${this._editPath}/edit/${item.unique}`; + } + + override render() { + if (!this.item) return nothing; + + return html` + + + + + `; + } + + static override styles = [ + css` + umb-user-avatar { + font-size: var(--uui-size-4); + } + `, + ]; +} + +export { UmbUserItemRefElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-user-item-ref': UmbUserItemRefElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts index 29df08be7c9e..d3f0e2d96ee1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/manifests.ts @@ -4,11 +4,13 @@ import { manifests as conditionsManifests } from './conditions/manifests.js'; import { manifests as entityActionsManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; import { manifests as inviteManifests } from './invite/manifests.js'; +import { manifests as itemManifests } from './item/manifests.js'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as menuItemManifests } from './menu-item/manifests.js'; + import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -18,9 +20,10 @@ export const manifests: Array = ...entityActionsManifests, ...entityBulkActionManifests, ...inviteManifests, + ...itemManifests, + ...menuItemManifests, ...modalManifests, ...propertyEditorManifests, ...repositoryManifests, ...workspaceManifests, - ...menuItemManifests, ];