From a3912d1ace18731e9383a528e1b382c220ffda57 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 2 Feb 2023 13:12:52 +0100 Subject: [PATCH 1/8] init --- .../src/backoffice/shared/components/index.ts | 2 + .../input-document-picker.element.ts | 12 +- .../input-media-picker.element.ts | 194 ++++++++++++++++++ ...perty-editor-ui-document-picker.element.ts | 3 +- ...property-editor-ui-media-picker.element.ts | 44 +++- 5 files changed, 245 insertions(+), 10 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index d4aaf7fac5..717317aa34 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -14,3 +14,5 @@ import './section/section-sidebar/section-sidebar.element'; import './section/section.element'; import './tree/tree.element'; import './workspace/workspace-content/workspace-content.element'; +import './input-media-picker/input-media-picker.element'; +import './input-document-picker/input-document-picker.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts index d02dc7ed63..9d1be7a694 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts @@ -21,6 +21,13 @@ export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElemen `, ]; + /** + * Set picker to singlemode + * @attr + */ + @property({ type: Boolean }) + singlemode?: boolean; + /** * This is a minimum amount of selected items in this input. * @type {number} @@ -122,7 +129,10 @@ export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElemen private _openPicker() { // We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data: - const modalHandler = this._modalService?.contentPicker({ multiple: true, selection: [...this._selectedKeys] }); + const modalHandler = this._modalService?.contentPicker({ + multiple: this.singlemode ? false : true, + selection: [...this._selectedKeys], + }); modalHandler?.onClose().then(({ selection }: any) => { this._setSelection(selection); }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts new file mode 100644 index 0000000000..ecf3e7d8b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts @@ -0,0 +1,194 @@ +import { css, html, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { ifDefined } from 'lit-html/directives/if-defined.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '../../../../core/modal'; +import { + MediaTreeItem, + UmbMediaTreeStore, + UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN, +} from '../../../../backoffice/media/media/media.tree.store'; +import { UmbLitElement } from '@umbraco-cms/element'; +import type { FolderTreeItem } from '@umbraco-cms/backend-api'; +import type { UmbObserverController } from '@umbraco-cms/observable-api'; + +@customElement('umb-input-media-picker') +export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) { + static styles = [ + UUITextStyles, + css` + #add-button { + width: 100%; + } + `, + ]; + + /** + * Set picker to singlemode + * @attr + */ + @property({ type: Boolean }) + singlemode?: boolean; + + /** + * This is a minimum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + min?: number; + + /** + * Min validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + minMessage = 'This field need more items'; + + /** + * This is a maximum amount of selected items in this input. + * @type {number} + * @attr + * @default undefined + */ + @property({ type: Number }) + max?: number; + + /** + * Max validation message. + * @type {boolean} + * @attr + * @default + */ + @property({ type: String, attribute: 'min-message' }) + maxMessage = 'This field exceeds the allowed amount of items'; + + // TODO: do we need both selectedKeys and value? If we just use value we follow the same pattern as native form controls. + private _selectedKeys: Array = []; + public get selectedKeys(): Array { + return this._selectedKeys; + } + public set selectedKeys(keys: Array) { + this._selectedKeys = keys; + super.value = keys.join(','); + this._observePickedMedias(); + } + + @property() + public set value(keysString: string) { + if (keysString !== this._value) { + this.selectedKeys = keysString.split(/[ ,]+/); + } + } + + @state() + private _items?: Array; + + private _modalService?: UmbModalService; + private _mediaStore?: UmbMediaTreeStore; + private _pickedItemsObserver?: UmbObserverController; + + constructor() { + super(); + + this.addValidator( + 'rangeUnderflow', + () => this.minMessage, + () => !!this.min && this._selectedKeys.length < this.min + ); + this.addValidator( + 'rangeOverflow', + () => this.maxMessage, + () => !!this.max && this._selectedKeys.length > this.max + ); + + this.consumeContext(UMB_MEDIA_TREE_STORE_CONTEXT_TOKEN, (instance) => { + this._mediaStore = instance; + this._observePickedMedias(); + }); + this.consumeContext(UMB_MODAL_SERVICE_CONTEXT_TOKEN, (instance) => { + this._modalService = instance; + }); + } + + protected getFormElement() { + return undefined; + } + + private _observePickedMedias() { + this._pickedItemsObserver?.destroy(); + + if (!this._mediaStore) return; + + // TODO: consider changing this to the list data endpoint when it is available + this._pickedItemsObserver = this.observe(this._mediaStore.getTreeItems(this._selectedKeys), (items) => { + this._items = items; + }); + } + + private _openPicker() { + // We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data: + const modalHandler = this._modalService?.mediaPicker({ + multiple: this.singlemode ? false : true, + selection: [...this._selectedKeys], + }); + modalHandler?.onClose().then(({ selection }: any) => { + this._setSelection(selection); + }); + } + + private _removeItem(item: FolderTreeItem) { + const modalHandler = this._modalService?.confirm({ + color: 'danger', + headline: `Remove ${item.name}?`, + content: 'Are you sure you want to remove this item', + confirmLabel: 'Remove', + }); + + modalHandler?.onClose().then(({ confirmed }) => { + if (confirmed) { + const newSelection = this._selectedKeys.filter((value) => value !== item.key); + this._setSelection(newSelection); + } + }); + } + + private _setSelection(newSelection: Array) { + this.selectedKeys = newSelection; + this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); + } + + render() { + return html` + ${this._items?.map((item) => this._renderItem(item))} + Add + `; + } + + private _renderItem(item: FolderTreeItem) { + // TODO: remove when we have a way to handle trashed items + const tempItem = item as FolderTreeItem & { isTrashed: boolean }; + + return html` + + ${tempItem.isTrashed ? html` Trashed ` : nothing} + + this._removeItem(item)} label="Remove media ${item.name}">Remove + + + + `; + } +} + +export default UmbInputMediaPickerElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-media-picker': UmbInputMediaPickerElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/document-picker/property-editor-ui-document-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/document-picker/property-editor-ui-document-picker.element.ts index 13254a1cf4..202b47cbef 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/document-picker/property-editor-ui-document-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/document-picker/property-editor-ui-document-picker.element.ts @@ -1,8 +1,7 @@ import { html } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; +import { UmbInputDocumentPickerElement } from '../../../components/input-document-picker/input-document-picker.element'; import { UmbLitElement } from '@umbraco-cms/element'; -import type { UmbInputDocumentPickerElement } from 'src/backoffice/shared/components/input-document-picker/input-document-picker.element'; -import '../../../components/input-document-picker/input-document-picker.element'; import type { DataTypePropertyData } from '@umbraco-cms/models'; @customElement('umb-property-editor-ui-document-picker') diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts index b7c18cd63b..e96df3ce5f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts @@ -1,23 +1,53 @@ import { html } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { UmbInputMediaPickerElement } from '../../../../../backoffice/shared/components/input-media-picker/input-media-picker.element'; import { UmbLitElement } from '@umbraco-cms/element'; +import type { DataTypePropertyData } from '@umbraco-cms/models'; /** * @element umb-property-editor-ui-media-picker */ @customElement('umb-property-editor-ui-media-picker') export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement { - static styles = [UUITextStyles]; + private _value: Array = []; - @property() - value = ''; + @property({ type: Array }) + public get value(): Array { + return this._value; + } + public set value(value: Array) { + this._value = value || []; + } @property({ type: Array, attribute: false }) - public config = []; + public set config(config: Array) { + const validationLimit = config.find((x) => x.alias === 'validationLimit'); + if (!validationLimit) return; + + this._limitMin = (validationLimit?.value as any).min; + this._limitMax = (validationLimit?.value as any).max; + } + + @state() + private _limitMin?: number; + @state() + private _limitMax?: number; + + private _onChange(event: CustomEvent) { + this.value = (event.target as UmbInputMediaPickerElement).selectedKeys; + this.dispatchEvent(new CustomEvent('property-value-change')); + } render() { - return html`
umb-property-editor-ui-media-picker
`; + return html` + Add + `; } } From b5bade0ad22e8c3d29491b5218d9a8dd904a7507 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 3 Feb 2023 10:39:26 +0100 Subject: [PATCH 2/8] single mode based on max attribute --- .../input-document-picker.element.ts | 10 +--------- .../input-media-picker/input-media-picker.element.ts | 9 +-------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts index 9d1be7a694..698c17cc11 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.element.ts @@ -20,14 +20,6 @@ export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElemen } `, ]; - - /** - * Set picker to singlemode - * @attr - */ - @property({ type: Boolean }) - singlemode?: boolean; - /** * This is a minimum amount of selected items in this input. * @type {number} @@ -130,7 +122,7 @@ export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElemen private _openPicker() { // We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data: const modalHandler = this._modalService?.contentPicker({ - multiple: this.singlemode ? false : true, + multiple: this.max === 1 ? false : true, selection: [...this._selectedKeys], }); modalHandler?.onClose().then(({ selection }: any) => { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts index ecf3e7d8b4..71927a7032 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts @@ -24,13 +24,6 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) `, ]; - /** - * Set picker to singlemode - * @attr - */ - @property({ type: Boolean }) - singlemode?: boolean; - /** * This is a minimum amount of selected items in this input. * @type {number} @@ -133,7 +126,7 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) private _openPicker() { // We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data: const modalHandler = this._modalService?.mediaPicker({ - multiple: this.singlemode ? false : true, + multiple: this.max === 1 ? false : true, selection: [...this._selectedKeys], }); modalHandler?.onClose().then(({ selection }: any) => { From 4d57a30486300f05bc06f1b846173f1f7ed11553 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 7 Feb 2023 10:10:55 +0100 Subject: [PATCH 3/8] property editor checkbox --- .../input-checkbox-list.element.ts | 81 +++++++++++++++++++ ...roperty-editor-ui-checkbox-list.element.ts | 36 +++++++-- .../src/core/mocks/data/data-type.data.ts | 10 ++- 3 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-checkbox-list/input-checkbox-list.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-checkbox-list/input-checkbox-list.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-checkbox-list/input-checkbox-list.element.ts new file mode 100644 index 0000000000..98d3dbdc59 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-checkbox-list/input-checkbox-list.element.ts @@ -0,0 +1,81 @@ +import { css, html, nothing } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { repeat } from 'lit/directives/repeat.js'; +import { UUIBooleanInputEvent } from '@umbraco-ui/uui'; +import { UmbLitElement } from '@umbraco-cms/element'; + +@customElement('umb-input-checkbox-list') +export class UmbInputCheckboxListElement extends FormControlMixin(UmbLitElement) { + static styles = [ + UUITextStyles, + css` + uui-checkbox { + width: 100%; + } + `, + ]; + + /** + * List of items. + */ + @property() + list?: []; + + private _selectedKeys: Array = []; + public get selectedKeys(): Array { + return this._selectedKeys; + } + public set selectedKeys(keys: Array) { + this._selectedKeys = keys; + super.value = keys.join(','); + } + + @property() + public set value(keysString: string) { + if (keysString !== this._value) { + this.selectedKeys = keysString.split(/[ ,]+/); + } + } + + protected getFormElement() { + return undefined; + } + + private _setSelection(e: UUIBooleanInputEvent) { + e.stopPropagation(); + if (e.target.checked) this.selectedKeys = [...this.selectedKeys, e.target.value]; + else this._removeFromSelection(this.selectedKeys.findIndex((key) => e.target.value === key)); + + this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); + } + + private _removeFromSelection(index: number) { + if (index == -1) return; + const keys = [...this.selectedKeys]; + keys.splice(index, 1); + this.selectedKeys = keys; + } + + render() { + if (!this.list) return nothing; + return html`
+ + ${repeat(this.list, (item) => item.key, this.renderCheckbox)} + +
`; + } + + renderCheckbox(item: any) { + return html``; + } +} + +export default UmbInputCheckboxListElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-checkbox-list': UmbInputCheckboxListElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/checkbox-list/property-editor-ui-checkbox-list.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/checkbox-list/property-editor-ui-checkbox-list.element.ts index 0c501fc88b..a522d15741 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/checkbox-list/property-editor-ui-checkbox-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/checkbox-list/property-editor-ui-checkbox-list.element.ts @@ -1,7 +1,10 @@ import { html } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import '../../../components/input-checkbox-list/input-checkbox-list.element'; +import { UmbInputCheckboxListElement } from '../../../components/input-checkbox-list/input-checkbox-list.element'; import { UmbLitElement } from '@umbraco-cms/element'; +import type { DataTypePropertyData } from '@umbraco-cms/models'; /** * @element umb-property-editor-ui-checkbox-list @@ -10,14 +13,37 @@ import { UmbLitElement } from '@umbraco-cms/element'; export class UmbPropertyEditorUICheckboxListElement extends UmbLitElement { static styles = [UUITextStyles]; - @property() - value = ''; + private _value: Array = []; + @property({ type: Array }) + public get value(): Array { + return this._value; + } + public set value(value: Array) { + this._value = value || []; + } @property({ type: Array, attribute: false }) - public config = []; + public set config(config: Array) { + const listData = config.find((x) => x.alias === 'itemList'); + + if (!listData) return; + this._list = listData.value; + } + + @state() + private _list: [] = []; + + private _onChange(event: CustomEvent) { + this.value = (event.target as UmbInputCheckboxListElement).selectedKeys; + this.dispatchEvent(new CustomEvent('property-value-change')); + console.log(this._value); + } render() { - return html`
umb-property-editor-ui-checkbox-list
`; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts index 6c488aca96..2a52c9dbed 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/data-type.data.ts @@ -255,7 +255,15 @@ export const data: Array = [ isFolder: false, propertyEditorModelAlias: 'Umbraco.CheckboxList', propertyEditorUIAlias: 'Umb.PropertyEditorUI.CheckboxList', - data: [], + data: [ + { + alias: 'itemList', + value: [ + { label: 'Label 1', key: '123' }, + { label: 'Label 2', key: '456' }, + ], + }, + ], }, { name: 'Block List', From 7ea1ce4f8a69fa4df5d6a96cc906efaed16cdc81 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:11:48 +0100 Subject: [PATCH 4/8] media card and grid for media --- .../input-media-picker.element.ts | 35 +++++++++++++++---- ...property-editor-ui-media-picker.element.ts | 4 +-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts index 71927a7032..8d204e0d03 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts @@ -18,8 +18,20 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) static styles = [ UUITextStyles, css` + :host { + display: grid; + gap: var(--uui-size-space-3); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + } #add-button { - width: 100%; + text-align: center; + min-height: 160px; + } + uui-icon { + display: block; + margin: 0 auto; } `, ]; @@ -153,12 +165,16 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) private _setSelection(newSelection: Array) { this.selectedKeys = newSelection; this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); + console.log(this._items); } render() { return html` ${this._items?.map((item) => this._renderItem(item))} - Add + + + Add + `; } @@ -167,13 +183,20 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) const tempItem = item as FolderTreeItem & { isTrashed: boolean }; return html` - + ${tempItem.isTrashed ? html` Trashed ` : nothing} - this._removeItem(item)} label="Remove media ${item.name}">Remove + + + + this._removeItem(item)} label="Remove media ${item.name}"> + + - - + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts index e96df3ce5f..cee50e5235 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts @@ -44,9 +44,7 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement { @change=${this._onChange} .selectedKeys=${this._value} .min=${this._limitMin} - .max=${this._limitMax} - >Add + .max=${this._limitMax}> `; } } From 09ce12c23bd24bd3f4650c47e832023b747ce342 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:12:30 +0100 Subject: [PATCH 5/8] no border --- .../components/input-media-picker/input-media-picker.element.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts index 8d204e0d03..7bec85dee6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts @@ -21,8 +21,6 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) :host { display: grid; gap: var(--uui-size-space-3); - padding: var(--uui-size-space-5); - border: 1px solid var(--uui-color-border); grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); } #add-button { From f20244c1595d4f29245ad3e922fff7b6dc37dbce Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:42:34 +0100 Subject: [PATCH 6/8] button render --- .../input-media-picker.element.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts index 7bec85dee6..2a9dad4b73 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts @@ -167,13 +167,14 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) } render() { - return html` - ${this._items?.map((item) => this._renderItem(item))} - - - Add - - `; + return html` ${this._items?.map((item) => this._renderItem(item))} ${this._renderButton()} `; + } + private _renderButton() { + if (this.max == 1 && this._items && this._items.length > 0) return; + return html` + + Add + `; } private _renderItem(item: FolderTreeItem) { From 5ab5113cf634edfc68c16b9bf62955b5e75ce3d3 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 7 Feb 2023 14:35:16 +0100 Subject: [PATCH 7/8] tests --- .../input-document-picker.test.ts | 18 ++++++++++++++++++ .../input-media-picker.element.ts | 1 + .../input-media-picker.test.ts | 18 ++++++++++++++++++ .../property-editor-ui-media-picker.element.ts | 4 +++- 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts new file mode 100644 index 0000000000..e5fc9c1382 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts @@ -0,0 +1,18 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { UmbInputDocumentPickerElement } from './input-document-picker.element'; +import { defaultA11yConfig } from '@umbraco-cms/test-utils'; +describe('UmbPropertyEditorUINumberRangeElement', () => { + let element: UmbInputDocumentPickerElement; + + beforeEach(async () => { + element = await fixture(html` `); + }); + + it('is defined with its own instance', () => { + expect(element).to.be.instanceOf(UmbInputDocumentPickerElement); + }); + + it('passes the a11y audit', async () => { + await expect(element).shadowDom.to.be.accessible(defaultA11yConfig); + }); +}); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts index 2a9dad4b73..4c2adfe105 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.element.ts @@ -197,6 +197,7 @@ export class UmbInputMediaPickerElement extends FormControlMixin(UmbLitElement) `; + //TODO: } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.test.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.test.ts new file mode 100644 index 0000000000..c101ab99ae --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-media-picker/input-media-picker.test.ts @@ -0,0 +1,18 @@ +import { expect, fixture, html } from '@open-wc/testing'; +import { UmbInputMediaPickerElement } from './input-media-picker.element'; +import { defaultA11yConfig } from '@umbraco-cms/test-utils'; +describe('UmbPropertyEditorUINumberRangeElement', () => { + let element: UmbInputMediaPickerElement; + + beforeEach(async () => { + element = await fixture(html` `); + }); + + it('is defined with its own instance', () => { + expect(element).to.be.instanceOf(UmbInputMediaPickerElement); + }); + + it('passes the a11y audit', async () => { + await expect(element).shadowDom.to.be.accessible(defaultA11yConfig); + }); +}); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts index cee50e5235..e96df3ce5f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/media-picker/property-editor-ui-media-picker.element.ts @@ -44,7 +44,9 @@ export class UmbPropertyEditorUIMediaPickerElement extends UmbLitElement { @change=${this._onChange} .selectedKeys=${this._value} .min=${this._limitMin} - .max=${this._limitMax}> + .max=${this._limitMax} + >Add `; } } From 62a86484226ac84ea5aa463be2c9bf61d438a1e0 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 8 Feb 2023 10:22:08 +0100 Subject: [PATCH 8/8] typo in document picker test --- .../input-document-picker/input-document-picker.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts index e5fc9c1382..b8841ac2db 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-document-picker/input-document-picker.test.ts @@ -5,7 +5,7 @@ describe('UmbPropertyEditorUINumberRangeElement', () => { let element: UmbInputDocumentPickerElement; beforeEach(async () => { - element = await fixture(html` `); + element = await fixture(html` `); }); it('is defined with its own instance', () => {