Merge pull request #1125 from umbraco/chore/tree-picker-source-filter

Tree Picker: Pass in "filter" to picker
This commit is contained in:
Niels Lyngsø
2024-01-24 08:47:37 +01:00
committed by GitHub
5 changed files with 125 additions and 78 deletions

View File

@@ -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}></umb-input-tree>`;

View File

@@ -35,13 +35,13 @@ export class UmbInputTreeElement extends FormControlMixin(UmbLitElement) {
@property({ type: Number })
max = 0;
private _filter: Array<string> = [];
private _allowedContentTypeIds: Array<string> = [];
@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`<umb-input-document
.selectedIds=${this.selectedIds}
.startNodeId=${this.startNodeId}
.filter=${this.filter}
.allowedContentTypeIds=${this._allowedContentTypeIds}
.min=${this.min}
.max=${this.max}
?showOpenButton=${this.showOpenButton}
@@ -115,7 +115,7 @@ export class UmbInputTreeElement extends FormControlMixin(UmbLitElement) {
#renderMediaPicker() {
return html`<umb-input-media
.selectedIds=${this.selectedIds}
.filter=${this.filter}
.allowedContentTypeIds=${this._allowedContentTypeIds}
.min=${this.min}
.max=${this.max}
?showOpenButton=${this.showOpenButton}
@@ -126,7 +126,7 @@ export class UmbInputTreeElement extends FormControlMixin(UmbLitElement) {
#renderMemberPicker() {
return html`<umb-input-member
.selectedIds=${this.selectedIds}
.filter=${this.filter}
.allowedContentTypeIds=${this._allowedContentTypeIds}
.min=${this.min}
.max=${this.max}
?showOpenButton=${this.showOpenButton}

View File

@@ -2,7 +2,7 @@ import { UmbDocumentPickerContext } from './input-document.context.js';
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 { DocumentItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
import type { DocumentItemResponseModel, DocumentTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
@customElement('umb-input-document')
@@ -63,8 +63,8 @@ export class UmbInputDocumentElement extends FormControlMixin(UmbLitElement) {
@property({ type: String })
startNodeId?: string;
@property({ type: String })
filter?: string;
@property({ type: Array })
allowedContentTypeIds?: string[] | undefined;
@property({ type: Boolean })
showOpenButton?: boolean;
@@ -106,23 +106,31 @@ export class UmbInputDocumentElement extends FormControlMixin(UmbLitElement) {
this.observe(this.#pickerContext.selectedItems, (selectedItems) => (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),
)}
</uui-ref-list>`;
}
@@ -144,17 +152,17 @@ export class UmbInputDocumentElement extends FormControlMixin(UmbLitElement) {
return html`<uui-button
id="add-button"
look="placeholder"
@click=${this._openPicker}
@click=${this.#openPicker}
label=${this.localize.term('general_choose')}></uui-button>`;
}
private _renderItem(item: DocumentItemResponseModel) {
#renderItem(item: DocumentItemResponseModel) {
if (!item.id) return;
return html`
<uui-ref-node name=${ifDefined(item.name)} detail=${ifDefined(item.id)}>
${this._renderIsTrashed(item)}
${this.#renderIsTrashed(item)}
<uui-action-bar slot="actions">
${this._renderOpenButton(item)}
${this.#renderOpenButton(item)}
<uui-button
@click=${() => 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`<uui-tag size="s" slot="tag" color="danger">Trashed</uui-tag>`;
}
private _renderOpenButton(item: DocumentItemResponseModel) {
#renderOpenButton(item: DocumentItemResponseModel) {
if (!this.showOpenButton) return;
return html`<uui-button @click=${() => this._openItem(item)} label="Open document ${item.name}"
return html`<uui-button @click=${() => this.#openItem(item)} label="Open document ${item.name}"
>${this.localize.term('general_open')}</uui-button
>`;
}

View File

@@ -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`
<uui-button
id="add-button"
look="placeholder"
@click=${this._openPicker}
@click=${this.#openPicker}
label=${this.localize.term('general_choose')}>
<uui-icon name="icon-add"></uui-icon>
${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)}
<uui-action-bar slot="actions">
<uui-button label="Copy media">
<uui-icon name="icon-documents"></uui-icon>
@@ -165,7 +182,7 @@ export class UmbInputMediaElement extends FormControlMixin(UmbLitElement) {
`;
}
private _renderIsTrashed(item: MediaItemResponseModel) {
#renderIsTrashed(item: MediaItemResponseModel) {
if (!item.isTrashed) return;
return html`<uui-tag size="s" slot="tag" color="danger">Trashed</uui-tag>`;
}

View File

@@ -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<string> {
// TODO: Uncomment, once `UmbMemberPickerContext` has been implemented. [LK]
//return this.#pickerContext.getSelection();
return [];
}
public set selectedIds(ids: Array<string>) {
// 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),
)}
</uui-ref-list>`;
}
@@ -133,19 +151,17 @@ export class UmbInputMemberElement extends FormControlMixin(UmbLitElement) {
return html`<uui-button
id="add-button"
look="placeholder"
@click=${this._openPicker}
label=${this.localize.term('general_add')}></uui-button>`;
@click=${this.#openPicker}
label=${this.localize.term('general_choose')}></uui-button>`;
}
private _renderItem(item: MemberItemResponseModel) {
#renderItem(item: MemberItemResponseModel) {
if (!item.id) return;
return html`
<uui-ref-node name=${ifDefined(item.name)} detail=${ifDefined(item.id)}>
<!-- TODO: implement is deleted <uui-tag size="s" slot="tag" color="danger">Deleted</uui-tag> -->
${this.#renderIsTrashed(item)}
<uui-action-bar slot="actions">
<uui-button
@click=${() => this._requestRemoveItem(item)}
label="Remove member ${item.name}"
<uui-button @click=${() => this.#requestRemoveItem(item)} label="Remove member ${item.name}"
>Remove</uui-button
>
</uui-action-bar>
@@ -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`<uui-tag size="s" slot="tag" color="danger">Trashed</uui-tag>`;
}
static styles = [
css`
#add-button {