From c9e27de687c94bd8bbe495848f4eb6d332f9850e Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 16 Feb 2023 13:09:32 +0100 Subject: [PATCH] linkpicker --- .../input-multi-url-picker.element.ts | 140 ++++++++---------- ...property-editor-ui-color-picker.element.ts | 1 - ...erty-editor-ui-multi-url-picker.element.ts | 11 +- .../src/core/mocks/data/data-type.data.ts | 19 ++- .../modal-layout-link-picker.element.ts} | 120 +++++++++------ .../modal-layout-multi-url-picker.stories.ts | 4 +- .../src/core/modal/modal.service.ts | 12 +- 7 files changed, 161 insertions(+), 146 deletions(-) rename src/Umbraco.Web.UI.Client/src/core/modal/layouts/{multi-url-picker/modal-layout-multi-url-picker.element.ts => link-picker/modal-layout-link-picker.element.ts} (56%) rename src/Umbraco.Web.UI.Client/src/core/modal/layouts/{multi-url-picker => link-picker}/modal-layout-multi-url-picker.stories.ts (89%) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-multi-url-picker/input-multi-url-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-multi-url-picker/input-multi-url-picker.element.ts index 38bb0cb82d..6f8be61e30 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-multi-url-picker/input-multi-url-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-multi-url-picker/input-multi-url-picker.element.ts @@ -4,14 +4,19 @@ 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 { UmbLitElement } from '@umbraco-cms/element'; -import { DocumentTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api'; +import { DocumentTreeItemModel, EntityTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api'; import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/modal'; +import { UmbObserverController } from '@umbraco-cms/observable-api'; -export type OverlaySize = 'small' | 'medium' | 'large'; -export interface Url { - title: string; - href: string; - target: boolean; +export interface Link { + icon?: string; + name?: string; + published?: boolean; + queryString?: string; + target?: string; + trashed?: boolean; + udi?: string; + url?: string; } @customElement('umb-input-multi-url-picker') @@ -70,108 +75,81 @@ export class UmbInputMultiUrlPickerElement extends FormControlMixin(UmbLitElemen @property({ type: Boolean, attribute: 'hide-anchor' }) hideAnchor?: boolean; + @property() + ignoreUserStartNodes?: boolean; + /** * @type {"small" | "medium" | "large"} * @attr * @default "small" */ @property() - overlaySize: OverlaySize = 'small'; - - // 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(','); - } + overlaySize?: 'small' | 'medium' | 'large' | 'full'; @property() - public set value(keysString: string) { - if (keysString !== this._value) { - this.selectedKeys = keysString.split(/[ ,]+/); - } - } - - @property() - target = false; - - @property() - title = ''; - - @property() - url = ''; - - @state() - private _urls?: Url[] = [ - { - title: 'Cake', - href: 'google.com', - target: true, - }, - ]; - - @state() - private _items?: Array; + links: Array = []; private _modalService?: UmbModalService; + 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_MODAL_SERVICE_CONTEXT_TOKEN, (instance) => { this._modalService = instance; }); } - private _openPicker() { - const modalHandler = this._modalService?.multiUrlPicker({ treeItem: this._selectedKeys[0], target: this.target }); - modalHandler?.onClose().then(({ selection }: any) => { - this.selectedKeys[0] = selection.treeItem; - this.target = selection.target; - this.url = selection.href; + private async _observePickedDocumentsOrMedias() { + this._pickedItemsObserver?.destroy(); + } + + private _removeItem(index: number) { + this.links.splice(index, 1); + this.requestUpdate(); + } + + private _openPicker(data?: Link, index?: number) { + const modalHandler = this._modalService?.linkPicker( + { + name: data?.name || undefined, + published: data?.published || undefined, + queryString: data?.queryString || undefined, + target: data?.target || undefined, + trashed: data?.trashed || undefined, + udi: data?.udi || undefined, + url: data?.url || undefined, + }, + { + hideAnchor: this.hideAnchor, + ignoreUserStartNodes: this.ignoreUserStartNodes, + overlaySize: this.overlaySize || 'small', + } + ); + modalHandler?.onClose().then((newUrl: Link) => { + if (!newUrl) return; + + if (index !== undefined && index >= 0) this.links[index] = newUrl; + else this.links.push(newUrl); + this.requestUpdate(); }); } render() { - return html`${this._urls?.map((url) => this._renderItem(url))} + return html`${this.links?.map((link, index) => this._renderItem(link, index))} Add`; } - private _renderItem(url: Url) { - return html` - - + private _renderItem(link: Link, index: number) { + return html` + + + Remove + `; - - // TODO: remove when we have a way to handle trashed items - //const tempItem = item as FolderTreeItemModel & { isTrashed: boolean }; - - /* - return html` - - ${tempItem.isTrashed ? html` Trashed ` : nothing} - - - `; - */ - } - private _renderItemIcon(url: Url) { - if (url.href === 'key') return html``; - if (url.target === true) return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/color-picker/property-editor-ui-color-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/color-picker/property-editor-ui-color-picker.element.ts index ce6b39d155..453b358ee0 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/color-picker/property-editor-ui-color-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/color-picker/property-editor-ui-color-picker.element.ts @@ -2,7 +2,6 @@ import { html } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { UUIColorSwatchesEvent } from '@umbraco-ui/uui'; -import '../../../../shared/components/color-picker/color-picker.element'; import { UmbLitElement } from '@umbraco-cms/element'; import type { DataTypePropertyModel } from '@umbraco-cms/backend-api'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multi-url-picker/property-editor-ui-multi-url-picker.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multi-url-picker/property-editor-ui-multi-url-picker.element.ts index a6d394ba46..0bf35f6cee 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multi-url-picker/property-editor-ui-multi-url-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/property-editors/uis/multi-url-picker/property-editor-ui-multi-url-picker.element.ts @@ -3,9 +3,7 @@ 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 { UmbInputMultiUrlPickerElement } from '../../../components/input-multi-url-picker/input-multi-url-picker.element'; -import type { OverlaySize } from '../../../components/input-multi-url-picker/input-multi-url-picker.element'; import { UmbLitElement } from '@umbraco-cms/element'; -import type { DataTypePropertyData } from '@umbraco-cms/models'; /** * @element umb-property-editor-ui-multi-url-picker @@ -22,7 +20,7 @@ export class UmbPropertyEditorUIMultiUrlPickerElement extends UmbLitElement { public set value(value: string[]) { this._value = value || []; } - + /* @property({ type: Array, attribute: false }) public set config(config: DataTypePropertyData[]) { const overlaySize = config.find((x) => x.alias === 'overlaySize'); @@ -30,22 +28,19 @@ export class UmbPropertyEditorUIMultiUrlPickerElement extends UmbLitElement { const hideAnchor = config.find((x) => x.alias === 'hideAnchor'); if (hideAnchor) this._hideAnchor = hideAnchor.value; - } + }*/ - @state() - private _overlaySize?: OverlaySize; @state() private _hideAnchor?: boolean; private _onChange(event: CustomEvent) { - this._value = (event.target as UmbInputMultiUrlPickerElement).selectedKeys; + //this._value = (event.target as UmbInputMultiUrlPickerElement); this.dispatchEvent(new CustomEvent('property-value-change')); } render() { 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 1fb6462337..7cd42af884 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 @@ -119,7 +119,24 @@ export const data: Array = [ parentKey: null, propertyEditorAlias: 'Umbraco.MultiUrlPicker', propertyEditorUiAlias: 'Umb.PropertyEditorUI.MultiUrlPicker', - data: [], + data: [ + { + alias: 'hideAnchor', + value: false, + }, + { + alias: 'ignoreUserStartNodes', + value: false, + }, + { + alias: 'maxNumber', + value: null, + }, + { + alias: 'minNumber', + value: null, + }, + ], }, { type: 'data-type', diff --git a/src/Umbraco.Web.UI.Client/src/core/modal/layouts/multi-url-picker/modal-layout-multi-url-picker.element.ts b/src/Umbraco.Web.UI.Client/src/core/modal/layouts/link-picker/modal-layout-link-picker.element.ts similarity index 56% rename from src/Umbraco.Web.UI.Client/src/core/modal/layouts/multi-url-picker/modal-layout-multi-url-picker.element.ts rename to src/Umbraco.Web.UI.Client/src/core/modal/layouts/link-picker/modal-layout-link-picker.element.ts index 39a56104f1..972150db4f 100644 --- a/src/Umbraco.Web.UI.Client/src/core/modal/layouts/multi-url-picker/modal-layout-multi-url-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/modal/layouts/link-picker/modal-layout-link-picker.element.ts @@ -1,23 +1,28 @@ -import { css, html } from 'lit'; +import { css, html, nothing } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, query, state } from 'lit/decorators.js'; -import { UUIBooleanInputEvent, UUIInputElement, UUIToggleElement } from '@umbraco-ui/uui'; +import { UUIBooleanInputEvent, UUIInputElement } from '@umbraco-ui/uui'; import { UmbModalLayoutElement } from '../modal-layout.element'; - -export interface UmbModalMultiUrlPickerData { - UrlString?: string; - anchorString?: string; - linkTitle?: string; - target?: boolean; - hideAnchor?: boolean; - treeItem?: string; - ignoreUserStartNodes?: boolean; -} - import { UmbTreeElement } from '../../../../backoffice/shared/components/tree/tree.element'; +export interface LinkPickerData { + icon?: string; + name?: string; + published?: boolean; + queryString?: string; + target?: string; + trashed?: boolean; + udi?: string; + url?: string; +} + +export interface LinkPickerConfig { + hideAnchor?: boolean; + ignoreUserStartNodes?: boolean; + overlaySize?: 'small' | 'medium' | 'large' | 'full'; +} @customElement('umb-modal-layout-multi-url-picker') -export class UmbModalLayoutMultiUrlPickerElement extends UmbModalLayoutElement { +export class UmbModalLayoutMultiUrlPickerElement extends UmbModalLayoutElement { static styles = [ UUITextStyles, css` @@ -53,16 +58,19 @@ export class UmbModalLayoutMultiUrlPickerElement extends UmbModalLayoutElement + @input=${() => (this._link.name = this._linkTitleInput.value as string)} + .value="${this._link.name ?? ''}"> Target Open the link in a new tab + label="Toggle if link should open in a new tab" + .checked="${this._link.target === '_blank' ? true : false}" + @change="${(e: UUIBooleanInputEvent) => + e.target.checked ? (this._link.target = '_blank') : (this._link.target = '')}"> + Open the link in a new tab +
@@ -147,30 +167,32 @@ export class UmbModalLayoutMultiUrlPickerElement extends UmbModalLayoutElement + .value="${this._link.udi ?? this._link.url ?? ''}" + @input=${() => (this._link.url = this._linkInput.value as string)} + .disabled="${this._link.udi ? true : false}"> `; } private _renderAnchorInput() { - if (this._layout.hideAnchor) return; + if (this._layout.hideAnchor) return nothing; return html` Anchor / querystring + @input=${this._handleQueryString} + .value="${this._link.queryString ?? ''}"> `; } private _renderTrees() { return html`Link to page - +
@@ -180,7 +202,7 @@ export class UmbModalLayoutMultiUrlPickerElement extends UmbModalLayoutElement`; } } diff --git a/src/Umbraco.Web.UI.Client/src/core/modal/layouts/multi-url-picker/modal-layout-multi-url-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/core/modal/layouts/link-picker/modal-layout-multi-url-picker.stories.ts similarity index 89% rename from src/Umbraco.Web.UI.Client/src/core/modal/layouts/multi-url-picker/modal-layout-multi-url-picker.stories.ts rename to src/Umbraco.Web.UI.Client/src/core/modal/layouts/link-picker/modal-layout-multi-url-picker.stories.ts index 4bb37b0aaf..d41ed207e7 100644 --- a/src/Umbraco.Web.UI.Client/src/core/modal/layouts/multi-url-picker/modal-layout-multi-url-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/core/modal/layouts/link-picker/modal-layout-multi-url-picker.stories.ts @@ -1,5 +1,5 @@ import '../../../../backoffice/shared/components/body-layout/body-layout.element'; -import './modal-layout-multi-url-picker.element'; +import './modal-layout-link-picker.element'; import { Meta, Story } from '@storybook/web-components'; import { html } from 'lit'; @@ -7,7 +7,7 @@ import { html } from 'lit'; import type { UmbModalLayoutMultiUrlPickerElement, UmbModalMultiUrlPickerData, -} from './modal-layout-multi-url-picker.element'; +} from './modal-layout-link-picker.element'; export default { title: 'API/Modals/Layouts/Multi Url Picker', diff --git a/src/Umbraco.Web.UI.Client/src/core/modal/modal.service.ts b/src/Umbraco.Web.UI.Client/src/core/modal/modal.service.ts index 9d3debf9ef..21f790dcda 100644 --- a/src/Umbraco.Web.UI.Client/src/core/modal/modal.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/modal/modal.service.ts @@ -5,7 +5,7 @@ import './layouts/media-picker/modal-layout-media-picker.element'; import './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; import './layouts/modal-layout-current-user.element'; import './layouts/icon-picker/modal-layout-icon-picker.element'; -import './layouts/multi-url-picker/modal-layout-multi-url-picker.element'; +import './layouts/link-picker/modal-layout-link-picker.element'; import { UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar'; import { BehaviorSubject } from 'rxjs'; @@ -15,7 +15,7 @@ import type { UmbModalConfirmData } from './layouts/confirm/modal-layout-confirm import type { UmbModalContentPickerData } from './layouts/content-picker/modal-layout-content-picker.element'; import type { UmbModalPropertyEditorUIPickerData } from './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; import type { UmbModalMediaPickerData } from './layouts/media-picker/modal-layout-media-picker.element'; -import type { UmbModalMultiUrlPickerData } from './layouts/multi-url-picker/modal-layout-multi-url-picker.element'; +import type { LinkPickerConfig, LinkPickerData } from './layouts/link-picker/modal-layout-link-picker.element'; import { UmbModalHandler } from './modal-handler'; import { UmbContextToken } from '@umbraco-cms/context-api'; @@ -95,8 +95,12 @@ export class UmbModalService { * @return {*} {UmbModalHandler} * @memberof UmbModalService */ - public multiUrlPicker(data?: UmbModalMultiUrlPickerData): UmbModalHandler { - return this.open('umb-modal-layout-multi-url-picker', { data, type: 'sidebar', size: 'small' }); + public linkPicker(data?: LinkPickerData, config?: LinkPickerConfig): UmbModalHandler { + return this.open('umb-modal-layout-multi-url-picker', { + data, + type: 'sidebar', + size: config?.overlaySize || 'small', + }); } /**