From eee819676e50b4f8ec30f9abda3794bfd4970113 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 4 Jul 2024 16:45:12 +0100 Subject: [PATCH 1/8] Housekeeping / boilerplate Adding `elementName` constant + linting --- .../core/picker-input/picker-input.context.ts | 1 + .../form-control-validator.controller.ts | 2 +- .../input-document/input-document.element.ts | 10 +++++++--- .../input-member/input-member.element.ts | 8 +++++--- .../property-editor-ui-member-picker.element.ts | 2 +- .../input-content/input-content.element.ts | 3 ++- .../property-editor-ui-content-picker.element.ts | 14 ++++++++------ 7 files changed, 25 insertions(+), 15 deletions(-) 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 0022d3cdda..97c39f77f5 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 @@ -99,6 +99,7 @@ export class UmbPickerInputContext< content: 'Are you sure you want to remove this item', confirmLabel: 'Remove', }); + this.#removeItem(unique); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts index 662926bb38..244025e09d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts @@ -4,7 +4,7 @@ import type { UmbFormControlMixinInterface } from '../mixins/form-control.mixin. import { UmbValidationInvalidEvent } from '../events/validation-invalid.event.js'; import { UmbValidationValidEvent } from '../events/validation-valid.event.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbControllerAlias, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export class UmbFormControlValidator extends UmbControllerBase implements UmbValidator { // The path to the data that this validator is validating. 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 cddf17f5e4..68f7a1e915 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 @@ -2,15 +2,17 @@ import { UmbDocumentPickerContext } from './input-document.context.js'; import { classMap, css, customElement, html, 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 { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import type { UmbDocumentItemModel } from '@umbraco-cms/backoffice/document'; import type { UmbTreeStartNode } from '@umbraco-cms/backoffice/tree'; -import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; -@customElement('umb-input-document') +const elementName = 'umb-input-document'; + +@customElement(elementName) export class UmbInputDocumentElement extends UmbFormControlMixin( UmbLitElement, ) { @@ -243,8 +245,10 @@ export class UmbInputDocumentElement extends UmbFormControlMixin( UmbLitElement, ) { @@ -220,10 +222,10 @@ export class UmbInputMemberElement extends UmbFormControlMixin `; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts index 5396d89c1d..9b84b58c33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts @@ -11,6 +11,7 @@ import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; const elementName = 'umb-input-content'; + @customElement(elementName) export class UmbInputContentElement extends UmbFormControlMixin( UmbLitElement, @@ -156,7 +157,7 @@ export class UmbInputContentElement extends UmbFormControlMixin Date: Thu, 4 Jul 2024 16:47:45 +0100 Subject: [PATCH 2/8] Consistency across the document, media and member pickers --- .../input-document/input-document.element.ts | 20 +++++------- .../input-media/input-media.element.ts | 12 +++---- .../input-member/input-member.element.ts | 32 +++++++++---------- 3 files changed, 27 insertions(+), 37 deletions(-) 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 68f7a1e915..df5e20479a 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 @@ -75,7 +75,7 @@ export class UmbInputDocumentElement extends UmbFormControlMixin) { @@ -126,28 +126,24 @@ export class UmbInputDocumentElement extends UmbFormControlMixin this.minMessage, - () => !!this.min && this.#pickerContext.getSelection().length < this.min, + () => !!this.min && this.selection.length < this.min, ); this.addValidator( 'rangeOverflow', () => this.maxMessage, - () => !!this.max && this.#pickerContext.getSelection().length > this.max, + () => !!this.max && this.selection.length > this.max, ); this.observe(this.#pickerContext.selection, (selection) => (this.value = selection.join(',')), '_observeSelection'); this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems), '_observerItems'); } - protected override getFormElement() { - return undefined; - } - #isDraft(item: UmbDocumentItemModel) { return item.variants[0]?.state === 'Draft'; } - #pickableFilter: (item: UmbDocumentItemModel) => boolean = (item) => { + #pickableFilter = (item: UmbDocumentItemModel): boolean => { if (this.allowedContentTypeIds && this.allowedContentTypeIds.length > 0) { return this.allowedContentTypeIds.includes(item.documentType.unique); } @@ -162,7 +158,7 @@ export class UmbInputDocumentElement extends UmbFormControlMixin= this.max) return; + if (this.selection.length >= this.max) return; return html` ${this.#renderOpenButton(item)} - this.#removeItem(item)} label=${this.localize.term('general_remove')}> + this.#onRemove(item)} label=${this.localize.term('general_remove')}> `; @@ -231,7 +227,7 @@ export class UmbInputDocumentElement extends UmbFormControlMixin) { @@ -164,20 +164,16 @@ export class UmbInputMediaElement extends UmbFormControlMixin this.minMessage, - () => !!this.min && this.#pickerContext.getSelection().length < this.min, + () => !!this.min && this.selection.length < this.min, ); this.addValidator( 'rangeOverflow', () => this.maxMessage, - () => !!this.max && this.#pickerContext.getSelection().length > this.max, + () => !!this.max && this.selection.length > this.max, ); } - protected override getFormElement() { - return undefined; - } - - #pickableFilter: (item: UmbMediaItemModel) => boolean = (item) => { + #pickableFilter = (item: UmbMediaItemModel): boolean => { if (this.allowedContentTypeIds && this.allowedContentTypeIds.length > 0) { return this.allowedContentTypeIds.includes(item.mediaType.unique); } 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 db4b7e34b7..20f5188702 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 @@ -74,7 +74,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin) { @@ -125,24 +125,20 @@ export class UmbInputMemberElement extends UmbFormControlMixin this.minMessage, - () => !!this.min && this.#pickerContext.getSelection().length < this.min, + () => !!this.min && this.selection.length < this.min, ); this.addValidator( 'rangeOverflow', () => this.maxMessage, - () => !!this.max && this.#pickerContext.getSelection().length > this.max, + () => !!this.max && this.selection.length > this.max, ); this.observe(this.#pickerContext.selection, (selection) => (this.value = selection.join(',')), '_observeSelection'); this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems), '_observeItems'); } - protected override getFormElement() { - return undefined; - } - - #pickableFilter: (item: UmbMemberItemModel) => boolean = (item) => { + #pickableFilter = (item: UmbMemberItemModel): boolean => { if (this.allowedContentTypeIds && this.allowedContentTypeIds.length > 0) { return this.allowedContentTypeIds.includes(item.memberType.unique); } @@ -156,7 +152,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin= this.max) return nothing; - return html``; + if (this.selection.length >= this.max) return nothing; + return html` + + `; } #renderItem(item: UmbMemberItemModel) { @@ -192,7 +190,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin ${this.#renderOpenButton(item)} - this.#removeItem(item)} label=${this.localize.term('general_remove')}> + this.#onRemove(item)} label=${this.localize.term('general_remove')}> `; @@ -212,7 +210,7 @@ export class UmbInputMemberElement extends UmbFormControlMixin Date: Thu, 4 Jul 2024 16:48:22 +0100 Subject: [PATCH 3/8] Bugfix: `input-media` removing items --- .../media/components/input-media/input-media.element.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 b33d7a4e98..7affdb7650 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 @@ -188,8 +188,9 @@ export class UmbInputMediaElement extends UmbFormControlMixin x.unique !== item.unique); } override render() { From 5308c46378cf00eb41112bd1cfd213733599d761 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 4 Jul 2024 16:51:53 +0100 Subject: [PATCH 4/8] Refactored `input-content` to handle min/max validation - Added `minMessage` and `maxMessage` properties - Added `selection` property; deprecated `items` property - Removed the `switch` from `#onChange`, as the type can be inferred - Set the form control to be the nested picker, (document, media or member) --- .../input-content/input-content.element.ts | 136 +++++++++--------- 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts index 9b84b58c33..30c03a666d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts @@ -1,10 +1,7 @@ import type { UmbContentPickerSource } from '../../types.js'; -import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; -import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media'; -import type { UmbInputMemberElement } from '@umbraco-cms/backoffice/member'; import type { UmbReferenceByUniqueAndType } from '@umbraco-cms/backoffice/models'; import type { UmbTreeStartNode } from '@umbraco-cms/backoffice/tree'; import { splitStringToArray } from '@umbraco-cms/backoffice/utils'; @@ -16,53 +13,62 @@ const elementName = 'umb-input-content'; export class UmbInputContentElement extends UmbFormControlMixin( UmbLitElement, ) { - protected override getFormElement() { - return undefined; - } - - private _type: UmbContentPickerSource['type'] = 'content'; @property({ type: Object, attribute: false }) public set type(newType: UmbContentPickerSource['type']) { - const oldType = this._type; - if (newType?.toLowerCase() !== this._type) { - this._type = newType?.toLowerCase() as UmbContentPickerSource['type']; + const oldType = this.#type; + if (newType?.toLowerCase() !== this.#type) { + this.#type = newType?.toLowerCase() as UmbContentPickerSource['type']; this.requestUpdate('type', oldType); } } public get type(): UmbContentPickerSource['type'] { - return this._type; + return this.#type; } + #type: UmbContentPickerSource['type'] = 'content'; @property({ type: Number }) min = 0; + @property({ type: String, attribute: 'min-message' }) + minMessage = 'This field need more items'; + @property({ type: Number }) max = 0; + @property({ type: String, attribute: 'max-message' }) + maxMessage = 'This field exceeds the allowed amount of items'; + @property({ type: Object, attribute: false }) startNode?: UmbTreeStartNode; - private _allowedContentTypeIds: Array = []; @property() public set allowedContentTypeIds(value: string) { - this._allowedContentTypeIds = value ? value.split(',') : []; + this.#allowedContentTypeIds = value ? value.split(',') : []; } public get allowedContentTypeIds(): string { - return this._allowedContentTypeIds.join(','); + return this.#allowedContentTypeIds.join(','); } + #allowedContentTypeIds: Array = []; @property({ type: Boolean }) showOpenButton?: boolean; - #entityTypeLookup = { content: 'document', media: 'media', member: 'member' }; + @property({ type: Array }) + public set selection(values: Array) { + this.#selection = values?.map((item) => item.unique) ?? []; + } + public get selection(): Array { + return this.#selection.map((id) => ({ type: this.#entityTypeLookup[this.#type], unique: id })); + } - // TODO: to be consistent with other pickers, this should be named `selection` [NL] + /** @deprecated Please use `selection` instead. This property will be removed in Umbraco 15. */ @property({ type: Array }) public set items(items: Array) { - this.#selection = items?.map((item) => item.unique) ?? []; + this.selection = items; } + /** @deprecated Please use `selection` instead. This property will be removed in Umbraco 15. */ public get items(): Array { - return this.#selection.map((id) => ({ type: this.#entityTypeLookup[this._type], unique: id })); + return this.selection; } @property({ type: String }) @@ -73,38 +79,22 @@ export class UmbInputContentElement extends UmbFormControlMixin 0 ? this.#selection.join(',') : undefined; } + #entityTypeLookup = { content: 'document', media: 'media', member: 'member' }; + #selection: Array = []; - #onChange(event: CustomEvent) { - switch (this._type) { - case 'content': - { - const input = event.target as UmbInputDocumentElement; - this.#selection = input.selection; - this.value = input.selection.join(','); - } - break; - case 'media': { - const input = event.target as UmbInputMediaElement; - this.#selection = input.selection; - this.value = input.selection.join(','); - break; - } - case 'member': { - const input = event.target as UmbInputMemberElement; - this.#selection = input.selection; - this.value = input.selection.join(','); - break; - } - default: - break; - } + override firstUpdated() { + this.addFormControlElement(this.shadowRoot!.querySelector(`umb-input-${this.#entityTypeLookup[this.#type]}`)!); + } + #onChange(event: CustomEvent & { target: { selection: string[] | undefined } }) { + this.#selection = event.target.selection ?? []; + this.value = this.#selection.join(','); this.dispatchEvent(new UmbChangeEvent()); } override render() { - switch (this._type) { + switch (this.#type) { case 'content': return this.#renderDocumentPicker(); case 'media': @@ -117,34 +107,46 @@ export class UmbInputContentElement extends UmbFormControlMixin`; + return html` + + `; } #renderMediaPicker() { - return html``; + return html` + + `; } #renderMemberPicker() { - return html``; + return html` + + `; } static override styles = [ From 15d5d5e3121103a6921968bf6543f45b45b4c168 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 4 Jul 2024 16:56:36 +0100 Subject: [PATCH 5/8] MNTP: Implemented component to inherit from `UmbFormControlMixin` Sets the form control to be the nested picker `input-content`. --- ...operty-editor-ui-content-picker.element.ts | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts index 96aea0820a..5cbf24ce62 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts @@ -3,6 +3,7 @@ import type { UmbInputContentElement } from './components/input-content/index.js import type { UmbContentPickerSource, UmbContentPickerSourceType } from './types.js'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbFormControlMixin } from '@umbraco-cms/backoffice/validation'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; import { UMB_DOCUMENT_ENTITY_TYPE } from '@umbraco-cms/backoffice/document'; import { UMB_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; @@ -15,15 +16,26 @@ import type { UmbTreeStartNode } from '@umbraco-cms/backoffice/tree'; // import of local component import './components/input-content/index.js'; +type UmbContentPickerValueType = UmbInputContentElement['selection']; + const elementName = 'umb-property-editor-ui-content-picker'; /** * @element umb-property-editor-ui-content-picker */ @customElement(elementName) -export class UmbPropertyEditorUIContentPickerElement extends UmbLitElement implements UmbPropertyEditorUiElement { +export class UmbPropertyEditorUIContentPickerElement + extends UmbFormControlMixin(UmbLitElement, undefined) + implements UmbPropertyEditorUiElement +{ @property({ type: Array }) - value: UmbInputContentElement['items'] = []; + public override set value(value: UmbContentPickerValueType | undefined) { + this.#value = value; + } + public override get value(): UmbContentPickerValueType | undefined { + return this.#value; + } + #value?: UmbContentPickerValueType = []; @state() _type: UmbContentPickerSource['type'] = 'content'; @@ -73,8 +85,8 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbLitElement imple this._showOpenButton = config.getValueByAlias('showOpenButton'); } - override connectedCallback() { - super.connectedCallback(); + override firstUpdated() { + this.addFormControlElement(this.shadowRoot!.querySelector('umb-input-content')!); this.#setPickerRootUnique(); } @@ -98,7 +110,7 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbLitElement imple } #onChange(event: CustomEvent & { target: UmbInputContentElement }) { - this.value = event.target.items; + this.value = event.target.selection; this.dispatchEvent(new UmbPropertyValueChangeEvent()); } @@ -108,15 +120,19 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbLitElement imple ? { unique: this._rootUnique, entityType: this._rootEntityType } : undefined; - return html``; + return html` + + `; } } From 4811c5040e77b5dd821e0572395fa2c64343edf6 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 4 Jul 2024 16:57:20 +0100 Subject: [PATCH 6/8] MNTP: Adds `parseInt` helper for min/max config values --- .../property-editor-ui-content-picker.element.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts index 5cbf24ce62..f4fc21f7d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts @@ -78,13 +78,18 @@ export class UmbPropertyEditorUIContentPickerElement this.#dynamicRoot = startNode.dynamicRoot; } - this._min = Number(config.getValueByAlias('minNumber')) || 0; - this._max = Number(config.getValueByAlias('maxNumber')) || Infinity; + this._min = this.#parseInt(config.getValueByAlias('minNumber'), 0); + this._max = this.#parseInt(config.getValueByAlias('maxNumber'), Infinity); this._allowedContentTypeUniques = config.getValueByAlias('filter'); this._showOpenButton = config.getValueByAlias('showOpenButton'); } + #parseInt(value: unknown, fallback: number): number { + const num = Number(value); + return !isNaN(num) && num > 0 ? num : fallback; + } + override firstUpdated() { this.addFormControlElement(this.shadowRoot!.querySelector('umb-input-content')!); this.#setPickerRootUnique(); From a83dc4dbf10cc556ebdcc369c44bb241f67dfaec Mon Sep 17 00:00:00 2001 From: leekelleher Date: Thu, 4 Jul 2024 16:57:40 +0100 Subject: [PATCH 7/8] MNTP: Adds min/max validation messages --- .../property-editor-ui-content-picker.element.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts index f4fc21f7d1..c40a756769 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.element.ts @@ -43,9 +43,15 @@ export class UmbPropertyEditorUIContentPickerElement @state() _min = 0; + @state() + _minMessage = ''; + @state() _max = Infinity; + @state() + _maxMessage = ''; + @state() _allowedContentTypeUniques?: string | null; @@ -83,6 +89,14 @@ export class UmbPropertyEditorUIContentPickerElement this._allowedContentTypeUniques = config.getValueByAlias('filter'); this._showOpenButton = config.getValueByAlias('showOpenButton'); + + this._minMessage = `${this.localize.term('validation_minCount')} ${this._min} ${this.localize.term('validation_items')}`; + this._maxMessage = `${this.localize.term('validation_maxCount')} ${this._max} ${this.localize.term('validation_itemsSelected')}`; + + // NOTE: Run validation immediately, to notify if the value is outside of min/max range. [LK] + if (this._min > 0 || this._max < Infinity) { + this.checkValidity(); + } } #parseInt(value: unknown, fallback: number): number { From 8dab8e12ed1b09edd97542c5bd4d215404125a4d Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 8 Jul 2024 10:11:01 +0100 Subject: [PATCH 8/8] Fixed failing test The "document" package needed to be imported at runtime. --- .../components/input-content/input-content.element.ts | 4 ++-- .../components/input-content/input-content.test.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts index 30c03a666d..b404d9a51e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.element.ts @@ -1,5 +1,5 @@ import type { UmbContentPickerSource } from '../../types.js'; -import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbReferenceByUniqueAndType } from '@umbraco-cms/backoffice/models'; @@ -13,7 +13,7 @@ const elementName = 'umb-input-content'; export class UmbInputContentElement extends UmbFormControlMixin( UmbLitElement, ) { - @property({ type: Object, attribute: false }) + @property() public set type(newType: UmbContentPickerSource['type']) { const oldType = this.#type; if (newType?.toLowerCase() !== this.#type) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.test.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.test.ts index 619e9bb82c..a4f0bce190 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.test.ts @@ -1,11 +1,15 @@ import { UmbInputContentElement } from './input-content.element.js'; import { expect, fixture, html } from '@open-wc/testing'; -import { type UmbTestRunnerWindow, defaultA11yConfig } from '@umbraco-cms/internal/test-utils'; +import { defaultA11yConfig } from '@umbraco-cms/internal/test-utils'; +import type { UmbTestRunnerWindow } from '@umbraco-cms/internal/test-utils'; + +import '@umbraco-cms/backoffice/document'; + describe('UmbInputContentElement', () => { let element: UmbInputContentElement; beforeEach(async () => { - element = await fixture(html` `); + element = await fixture(html``); }); it('is defined with its own instance', () => {