diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tree-picker/property-editor-ui-tree-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tree-picker/property-editor-ui-tree-picker.element.ts index 43c5f393ee..0b6d9b8133 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tree-picker/property-editor-ui-tree-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/tree-picker/property-editor-ui-tree-picker.element.ts @@ -28,7 +28,7 @@ export class UmbPropertyEditorUITreePickerElement extends UmbLitElement implemen max = 0; @state() - filter?: string | null; + allowedContentTypeIds?: string | null; @state() showOpenButton?: boolean; @@ -47,7 +47,7 @@ export class UmbPropertyEditorUITreePickerElement extends UmbLitElement implemen this.min = Number(config?.getValueByAlias('minNumber')) || 0; this.max = Number(config?.getValueByAlias('maxNumber')) || 0; - this.filter = config?.getValueByAlias('filter'); + this.allowedContentTypeIds = config?.getValueByAlias('filter'); this.showOpenButton = config?.getValueByAlias('showOpenButton'); this.ignoreUserStartNodes = config?.getValueByAlias('ignoreUserStartNodes'); } @@ -64,7 +64,7 @@ export class UmbPropertyEditorUITreePickerElement extends UmbLitElement implemen .startNodeId=${this.startNodeId ?? ''} .min=${this.min} .max=${this.max} - .filter=${this.filter ?? ''} + .allowedContentTypeIds=${this.allowedContentTypeIds ?? ''} ?showOpenButton=${this.showOpenButton} ?ignoreUserStartNodes=${this.ignoreUserStartNodes} @change=${this.#onChange}>`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.element.ts index 234a127b12..f1d5c16f53 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/components/input-tree/input-tree.element.ts @@ -35,13 +35,13 @@ export class UmbInputTreeElement extends FormControlMixin(UmbLitElement) { @property({ type: Number }) max = 0; - private _filter: Array = []; + private _allowedContentTypeIds: Array = []; @property() - public set filter(value: string) { - this._filter = value.split(','); + public set allowedContentTypeIds(value: string) { + this._allowedContentTypeIds = value ? value.split(',') : []; } - public get filter(): string { - return this._filter.join(','); + public get allowedContentTypeIds(): string { + return this._allowedContentTypeIds.join(','); } @property({ type: Boolean }) @@ -104,7 +104,7 @@ export class UmbInputTreeElement extends FormControlMixin(UmbLitElement) { return html` (this._items = selectedItems)); } - protected _openPicker() { - // TODO: Configure the content picker, with `startNodeId`, `filter` and `ignoreUserStartNodes` [LK] - console.log("_openPicker", [this.startNodeId, this.filter, this.ignoreUserStartNodes]); + protected getFormElement() { + return undefined; + } + + #pickableFilter: (item: DocumentTreeItemResponseModel) => boolean = (item) => { + if (this.allowedContentTypeIds && this.allowedContentTypeIds.length > 0) { + return this.allowedContentTypeIds.includes(item.contentTypeId); + } + return true; + } + + #openPicker() { + // TODO: Configure the content picker, with `startNodeId` and `ignoreUserStartNodes` [LK] + console.log('_openPicker', [this.startNodeId, this.ignoreUserStartNodes]); this.#pickerContext.openPicker({ hideTreeRoot: true, + pickableFilter: this.#pickableFilter, }); } - protected _openItem(item: DocumentItemResponseModel) { + #openItem(item: DocumentItemResponseModel) { // TODO: Implement the Content editing infinity editor. [LK] console.log('TODO: _openItem', item); } - protected getFormElement() { - return undefined; - } - render() { return html` ${this.#renderItems()} ${this.#renderAddButton()} `; } @@ -134,7 +142,7 @@ export class UmbInputDocumentElement extends FormControlMixin(UmbLitElement) { >${repeat( this._items, (item) => item.id, - (item) => this._renderItem(item), + (item) => this.#renderItem(item), )} `; } @@ -144,17 +152,17 @@ export class UmbInputDocumentElement extends FormControlMixin(UmbLitElement) { return html``; } - private _renderItem(item: DocumentItemResponseModel) { + #renderItem(item: DocumentItemResponseModel) { if (!item.id) return; return html` - ${this._renderIsTrashed(item)} + ${this.#renderIsTrashed(item)} - ${this._renderOpenButton(item)} + ${this.#renderOpenButton(item)} this.#pickerContext.requestRemoveItem(item.id!)} label="Remove document ${item.name}" @@ -165,14 +173,14 @@ export class UmbInputDocumentElement extends FormControlMixin(UmbLitElement) { `; } - private _renderIsTrashed(item: DocumentItemResponseModel) { + #renderIsTrashed(item: DocumentItemResponseModel) { if (!item.isTrashed) return; return html`Trashed`; } - private _renderOpenButton(item: DocumentItemResponseModel) { + #renderOpenButton(item: DocumentItemResponseModel) { if (!this.showOpenButton) return; - return html` this._openItem(item)} label="Open document ${item.name}" + return html` this.#openItem(item)} label="Open document ${item.name}" >${this.localize.term('general_open')}`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts index 94530be00a..99723e608a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.element.ts @@ -1,8 +1,8 @@ import { UmbMediaPickerContext } from './input-media.context.js'; -import { css, html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, property, state, ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit'; import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { MediaItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import type { MediaItemResponseModel, MediaTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; @customElement('umb-input-media') @@ -60,8 +60,8 @@ export class UmbInputMediaElement extends FormControlMixin(UmbLitElement) { this.#pickerContext.setSelection(ids); } - @property({ type: String }) - filter?: string; + @property({ type: Array }) + allowedContentTypeIds?: string[] | undefined; @property({ type: Boolean }) showOpenButton?: boolean; @@ -103,40 +103,57 @@ export class UmbInputMediaElement extends FormControlMixin(UmbLitElement) { this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems)); } - protected _openPicker() { - // TODO: Configure the media picker, with `filter` and `ignoreUserStartNodes` [LK] - console.log('_openPicker', [this.filter, this.ignoreUserStartNodes]); - this.#pickerContext.openPicker({ - hideTreeRoot: true, - }); - } - - protected _openItem(item: MediaItemResponseModel) { - // TODO: Implement the Content editing infinity editor. [LK] - console.log('TODO: _openItem', item); - } - protected getFormElement() { return undefined; } + #pickableFilter: (item: MediaItemResponseModel) => boolean = (item) => { + /* TODO: Media item doesn't have the content/media-type ID available to query. + Commenting out until the Management API model is updated. [LK] + */ + // if (this.allowedContentTypeIds && this.allowedContentTypeIds.length > 0) { + // return this.allowedContentTypeIds.includes(item.contentTypeId); + // } + return true; + }; + + #openPicker() { + // TODO: Configure the media picker, with `allowedContentTypeIds` and `ignoreUserStartNodes` [LK] + console.log('#openPicker', [this.allowedContentTypeIds, this.ignoreUserStartNodes]); + this.#pickerContext.openPicker({ + hideTreeRoot: true, + pickableFilter: this.#pickableFilter, + }); + } + + #openItem(item: MediaItemResponseModel) { + // TODO: Implement the Media editing infinity editor. [LK] + console.log('TODO: _openItem', item); + } + render() { - return html` ${this.#renderItems()} ${this.#renderButton()} `; + return html` ${this.#renderItems()} ${this.#renderAddButton()} `; } #renderItems() { if (!this._items) return; // TODO: Add sorting. [LK] - return html` ${this._items?.map((item) => this.#renderItem(item))} `; + return html` + ${repeat( + this._items, + (item) => item.id, + (item) => this.#renderItem(item), + )} + `; } - #renderButton() { + #renderAddButton() { if (this._items && this.max && this._items.length >= this.max) return; return html` ${this.localize.term('general_choose')} @@ -152,7 +169,7 @@ export class UmbInputMediaElement extends FormControlMixin(UmbLitElement) { name=${ifDefined(item.name === null ? undefined : item.name)} detail=${ifDefined(item.id)} file-ext="jpg"> - ${this._renderIsTrashed(item)} + ${this.#renderIsTrashed(item)} @@ -165,7 +182,7 @@ export class UmbInputMediaElement extends FormControlMixin(UmbLitElement) { `; } - private _renderIsTrashed(item: MediaItemResponseModel) { + #renderIsTrashed(item: MediaItemResponseModel) { if (!item.isTrashed) return; return html`Trashed`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/members/components/input-member/input-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/members/components/input-member/input-member.element.ts index d1106e1f2e..6ba7bfd177 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/members/components/input-member/input-member.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/members/components/input-member/input-member.element.ts @@ -14,10 +14,12 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { */ @property({ type: Number }) public get min(): number { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] //return this.#pickerContext.min; return 0; } public set min(value: number) { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] //this.#pickerContext.min = value; } @@ -38,10 +40,12 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { */ @property({ type: Number }) public get max(): number { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] //return this.#pickerContext.max; return Infinity; } public set max(value: number) { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] //this.#pickerContext.max = value; } @@ -55,13 +59,18 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { maxMessage = 'This field exceeds the allowed amount of items'; public get selectedIds(): Array { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] //return this.#pickerContext.getSelection(); return []; } public set selectedIds(ids: Array) { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] //this.#pickerContext.setSelection(ids); } + @property({ type: Array }) + allowedContentTypeIds?: string[] | undefined; + @property() public set value(idsString: string) { // Its with full purpose we don't call super.value, as thats being handled by the observation of the context selection. @@ -77,6 +86,7 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { constructor() { super(); + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] // this.addValidator( // 'rangeUnderflow', // () => this.minMessage, @@ -92,28 +102,36 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { // this.observe(this.#pickerContext.selection, (selection) => (super.value = selection.join(','))); // this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems)); } - - protected _openPicker() { - console.log("member.openPicker"); - // this.#pickerContext.openPicker({ - // hideTreeRoot: true, - // }); - } - - protected _requestRemoveItem(item: MemberItemResponseModel){ - console.log("member.requestRemoveItem", item); - //this.#pickerContext.requestRemoveItem(item.id!); - } - protected getFormElement() { return undefined; } + #pickableFilter: (item: MemberItemResponseModel) => boolean = (item) => { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] + console.log('member.pickableFilter', item); + // if (this.allowedContentTypeIds && this.allowedContentTypeIds.length > 0) { + // return this.allowedContentTypeIds.includes(item.contentTypeId); + // } + return true; + }; + + #openPicker() { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] + console.log('member.openPicker'); + // this.#pickerContext.openPicker({ + // hideTreeRoot: true, + // pickableFilter: this.#pickableFilter, + // }); + } + + #requestRemoveItem(item: MemberItemResponseModel) { + // TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK] + console.log('member.requestRemoveItem', item); + //this.#pickerContext.requestRemoveItem(item.id!); + } + render() { - return html` - ${this.#renderItems()} - ${this.#renderAddButton()} - `; + return html` ${this.#renderItems()} ${this.#renderAddButton()} `; } #renderItems() { @@ -123,7 +141,7 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { >${repeat( this._items, (item) => item.id, - (item) => this._renderItem(item), + (item) => this.#renderItem(item), )} `; } @@ -133,19 +151,17 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { return html``; + @click=${this.#openPicker} + label=${this.localize.term('general_choose')}>`; } - private _renderItem(item: MemberItemResponseModel) { + #renderItem(item: MemberItemResponseModel) { if (!item.id) return; return html` - + ${this.#renderIsTrashed(item)} - this._requestRemoveItem(item)} - label="Remove member ${item.name}" + this.#requestRemoveItem(item)} label="Remove member ${item.name}" >Remove @@ -153,6 +169,12 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) { `; } + #renderIsTrashed(item: MemberItemResponseModel) { + // TODO: Uncomment, once the Management API model support deleted members. [LK] + //if (!item.isTrashed) return; + //return html`Trashed`; + } + static styles = [ css` #add-button {