From 7d171f3dd70539fe674717ce5477f200135a533b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 May 2023 13:13:47 +0200 Subject: [PATCH 1/4] add selectable filter on for tree element --- .../tree/tree-item-base/tree-item-base.context.ts | 8 +++++++- .../src/backoffice/shared/components/tree/tree.context.ts | 5 +++-- .../src/backoffice/shared/components/tree/tree.element.ts | 8 ++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index d3a7bafd82..b7801c151e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -138,7 +138,13 @@ export class UmbTreeItemContextBase this.#isSelectable.next(value)); + new UmbObserverController(this.host, this.treeContext.selectable, (value) => { + // If the tree is selectable, check if this item is selectable + if (value === true) { + const isSelectable = this.treeContext?.selectableFilter(this.getTreeItem()!) || false; + this.#isSelectable.next(isSelectable); + } + }); } #observeIsSelected() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts index f9102ef0bd..2d21346985 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts @@ -37,9 +37,10 @@ export class UmbTreeContextBase #selection = new UmbArrayState(>[]); public readonly selection = this.#selection.asObservable(); - #treeAlias?: string; - repository?: UmbTreeRepository; + public repository?: UmbTreeRepository; + public selectableFilter: (item: TreeItemType) => boolean = () => true; + #treeAlias?: string; #treeManifestObserver?: UmbObserverController; #initResolver?: () => void; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts index 304fc8d38e..abc7b8a871 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.element.ts @@ -61,6 +61,14 @@ export class UmbTreeElement extends UmbLitElement { this.requestUpdate('hideTreeRoot', oldVal); } + @property() + get selectableFilter() { + return this.#treeContext.selectableFilter; + } + set selectableFilter(newVal) { + this.#treeContext.selectableFilter = newVal; + } + @state() private _items: TreeItemPresentationModel[] = []; From ed4c5a26bb19c22f86a8aa4055ba2683480e6b78 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 May 2023 14:00:41 +0200 Subject: [PATCH 2/4] add pickableFilter to the modal interface + implement for data type picker --- .../libs/modal/modal.interfaces.ts | 5 +++-- .../modal/token/data-type-picker-modal.token.ts | 13 ++++--------- .../libs/picker-input/picker-input.context.ts | 6 +++--- .../data-type-picker-modal.element.ts | 1 + .../components/input-list-base/input-list-base.ts | 4 ++-- .../tree/tree-item-base/tree-item-base.context.ts | 2 +- .../shared/components/tree/tree.context.ts | 2 +- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/libs/modal/modal.interfaces.ts b/src/Umbraco.Web.UI.Client/libs/modal/modal.interfaces.ts index bcc2f9ad6d..c5bd4ad006 100644 --- a/src/Umbraco.Web.UI.Client/libs/modal/modal.interfaces.ts +++ b/src/Umbraco.Web.UI.Client/libs/modal/modal.interfaces.ts @@ -1,7 +1,8 @@ export interface UmbPickerModalData { - multiple: boolean; - selection: Array; + multiple?: boolean; + selection?: Array; filter?: (item: T) => boolean; + pickableFilter?: (item: T) => boolean; } export interface UmbPickerModalResult { diff --git a/src/Umbraco.Web.UI.Client/libs/modal/token/data-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/libs/modal/token/data-type-picker-modal.token.ts index 2297e7e023..49a3b54798 100644 --- a/src/Umbraco.Web.UI.Client/libs/modal/token/data-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/libs/modal/token/data-type-picker-modal.token.ts @@ -1,13 +1,8 @@ -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import { FolderTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbModalToken, UmbPickerModalData, UmbPickerModalResult } from '@umbraco-cms/backoffice/modal'; -export interface UmbDataTypePickerModalData { - selection?: Array; - multiple?: boolean; -} - -export interface UmbDataTypePickerModalResult { - selection: Array; -} +export type UmbDataTypePickerModalData = UmbPickerModalData; +export type UmbDataTypePickerModalResult = UmbPickerModalResult; export const UMB_DATA_TYPE_PICKER_MODAL = new UmbModalToken( 'Umb.Modal.DataTypePicker', diff --git a/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts b/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts index 3c8bae91c2..d085faddfa 100644 --- a/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts +++ b/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts @@ -7,6 +7,7 @@ import { UMB_MODAL_CONTEXT_TOKEN, UmbModalContext, UmbModalToken, + UmbPickerModalData, } from '@umbraco-cms/backoffice/modal'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ItemResponseModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -74,9 +75,8 @@ export class UmbPickerInputContext this.#selection.next(selection); } - // TODO: revisit this method. How do we best pass picker data? - // If modalAlias is a ModalToken, then via TS, we should get the correct type for pickerData. Otherwise fallback to unknown. - openPicker(pickerData?: any) { + // TODO: If modalAlias is a ModalToken, then via TS, we should get the correct type for pickerData. Otherwise fallback to unknown. + openPicker(pickerData?: UmbPickerModalData) { if (!this.modalContext) throw new Error('Modal context is not initialized'); const modalHandler = this.modalContext.open(this.modalAlias, { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/modal/data-type-picker/data-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/modal/data-type-picker/data-type-picker-modal.element.ts index 1f3f620f78..7b430b6065 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/modal/data-type-picker/data-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/modal/data-type-picker/data-type-picker-modal.element.ts @@ -53,6 +53,7 @@ export class UmbDataTypePickerModalElement extends UmbLitElement { @selected=${this.#onSelectionChange} .selection=${this._selection} selectable + .selectableFilter=${this.data?.pickableFilter} ?multiple=${this._multiple}>
diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-list-base/input-list-base.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-list-base/input-list-base.ts index 8d5208dc37..fe8713e0ab 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-list-base/input-list-base.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-list-base/input-list-base.ts @@ -6,7 +6,7 @@ import { UmbModalToken, UmbModalType, UMB_MODAL_CONTEXT_TOKEN, - UmbPickerModalData, + UmbPickerModalResult, } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -43,7 +43,7 @@ export class UmbInputListBaseElement extends UmbLitElement { selection: this.value, }); - modalHandler?.onSubmit().then((data: UmbPickerModalData) => { + modalHandler?.onSubmit().then((data: UmbPickerModalResult) => { if (data) { this.value = data.selection.filter((id) => id !== null && id !== undefined) as Array; this.selectionUpdated(); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts index b7801c151e..66c29c24c9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree-item-base/tree-item-base.context.ts @@ -141,7 +141,7 @@ export class UmbTreeItemContextBase { // If the tree is selectable, check if this item is selectable if (value === true) { - const isSelectable = this.treeContext?.selectableFilter(this.getTreeItem()!) || false; + const isSelectable = this.treeContext?.selectableFilter?.(this.getTreeItem()!) ?? true; this.#isSelectable.next(isSelectable); } }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts index 2d21346985..e5f86b694e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/tree/tree.context.ts @@ -38,7 +38,7 @@ export class UmbTreeContextBase public readonly selection = this.#selection.asObservable(); public repository?: UmbTreeRepository; - public selectableFilter: (item: TreeItemType) => boolean = () => true; + public selectableFilter?: (item: TreeItemType) => boolean = () => true; #treeAlias?: string; #treeManifestObserver?: UmbObserverController; From 283502ec85088bfd9499ed1c79231d78d266250f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 May 2023 14:27:20 +0200 Subject: [PATCH 3/4] add pickableFilter prop to picker input context --- src/Umbraco.Web.UI.Client/.vscode/settings.json | 1 + .../libs/picker-input/picker-input.context.ts | 5 ++++- .../workspace/workspace-package-builder.element.ts | 3 +-- .../data-type-input/data-type-input.element.ts | 10 +++++++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/.vscode/settings.json b/src/Umbraco.Web.UI.Client/.vscode/settings.json index 387d52b0f6..200dde453b 100644 --- a/src/Umbraco.Web.UI.Client/.vscode/settings.json +++ b/src/Umbraco.Web.UI.Client/.vscode/settings.json @@ -3,6 +3,7 @@ "cSpell.words": [ "combobox", "Elementable", + "pickable", "templating", "variantable" ], diff --git a/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts b/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts index d085faddfa..669e18d129 100644 --- a/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts +++ b/src/Umbraco.Web.UI.Client/libs/picker-input/picker-input.context.ts @@ -21,6 +21,8 @@ export class UmbPickerInputContext public modalContext?: UmbModalContext; + public pickableFilter?: (item: ItemType) => boolean = () => true; + #selection = new UmbArrayState([]); selection = this.#selection.asObservable(); @@ -76,12 +78,13 @@ export class UmbPickerInputContext } // TODO: If modalAlias is a ModalToken, then via TS, we should get the correct type for pickerData. Otherwise fallback to unknown. - openPicker(pickerData?: UmbPickerModalData) { + openPicker(pickerData?: Partial>) { if (!this.modalContext) throw new Error('Modal context is not initialized'); const modalHandler = this.modalContext.open(this.modalAlias, { multiple: this.max === 1 ? false : true, selection: [...this.getSelection()], + pickableFilter: this.pickableFilter, ...pickerData, }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts index cf6287835e..23126b76d7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts @@ -10,11 +10,10 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { PackageDefinitionResponseModel, PackageResource } from '@umbraco-cms/backoffice/backend-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; +import { itemHandlers } from 'src/core/mocks/domains/data-type/item.handlers'; @customElement('umb-workspace-package-builder') export class UmbWorkspacePackageBuilderElement extends UmbLitElement { - - @property() entityId?: string; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/components/data-type-input/data-type-input.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/components/data-type-input/data-type-input.element.ts index c8c28070e2..8a5e055745 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/components/data-type-input/data-type-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/data-types/components/data-type-input/data-type-input.element.ts @@ -4,7 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js'; import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; import { UmbDataTypePickerContext } from './data-type-input.context'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import type { DataTypeItemResponseModel, FolderTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; @customElement('umb-data-type-input') export class UmbDataTypeInputElement extends FormControlMixin(UmbLitElement) { @@ -67,6 +67,14 @@ export class UmbDataTypeInputElement extends FormControlMixin(UmbLitElement) { this.selectedIds = idsString.split(/[ ,]+/); } + @property() + get pickableFilter() { + return this.#pickerContext.pickableFilter; + } + set pickableFilter(newVal) { + this.#pickerContext.pickableFilter = newVal; + } + @state() private _items?: Array; From 12a4e93e753e9078e79aa7dbc1a73e9bee1a5fa8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 May 2023 14:41:54 +0200 Subject: [PATCH 4/4] remove import --- .../workspace/workspace-package-builder.element.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts index 23126b76d7..fce753f5ef 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/packages/package-builder/workspace/workspace-package-builder.element.ts @@ -10,7 +10,6 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { PackageDefinitionResponseModel, PackageResource } from '@umbraco-cms/backoffice/backend-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { itemHandlers } from 'src/core/mocks/domains/data-type/item.handlers'; @customElement('umb-workspace-package-builder') export class UmbWorkspacePackageBuilderElement extends UmbLitElement {