V15: Link Picker Modal UX Flow (#17994)
* Link Picker: reworked modal UX flow * Tweaked "Target" description * Link Picker modal tweaks * Localized "Reset URL" confirm modal * Awaits validation on picker change * Added `data-mark` attributes --------- Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
This commit is contained in:
@@ -502,9 +502,9 @@ export default {
|
|||||||
copiedItemOfItems: 'Copied %0% out of %1% items',
|
copiedItemOfItems: 'Copied %0% out of %1% items',
|
||||||
},
|
},
|
||||||
defaultdialogs: {
|
defaultdialogs: {
|
||||||
nodeNameLinkPicker: 'Link title',
|
nodeNameLinkPicker: 'Title',
|
||||||
urlLinkPicker: 'Link',
|
urlLinkPicker: 'Link',
|
||||||
anchorLinkPicker: 'Anchor / querystring',
|
anchorLinkPicker: 'Anchor or querystring',
|
||||||
anchorInsert: 'Name',
|
anchorInsert: 'Name',
|
||||||
closeThisWindow: 'Close this window',
|
closeThisWindow: 'Close this window',
|
||||||
confirmdelete: 'Are you sure you want to delete',
|
confirmdelete: 'Are you sure you want to delete',
|
||||||
@@ -563,14 +563,14 @@ export default {
|
|||||||
includeDescendants: 'Include descendants',
|
includeDescendants: 'Include descendants',
|
||||||
theFriendliestCommunity: 'The friendliest community',
|
theFriendliestCommunity: 'The friendliest community',
|
||||||
linkToPage: 'Link to document',
|
linkToPage: 'Link to document',
|
||||||
openInNewWindow: 'Opens the linked document in a new window or tab',
|
openInNewWindow: 'Opens the link in a new window or tab',
|
||||||
linkToMedia: 'Link to media',
|
linkToMedia: 'Link to media',
|
||||||
selectContentStartNode: 'Select content start node',
|
selectContentStartNode: 'Select content start node',
|
||||||
selectMedia: 'Select media',
|
selectMedia: 'Select media',
|
||||||
selectMediaType: 'Select media type',
|
selectMediaType: 'Select media type',
|
||||||
selectIcon: 'Select icon',
|
selectIcon: 'Select icon',
|
||||||
selectItem: 'Select item',
|
selectItem: 'Select item',
|
||||||
selectLink: 'Select link',
|
selectLink: 'Configure link',
|
||||||
selectMacro: 'Select macro',
|
selectMacro: 'Select macro',
|
||||||
selectContent: 'Select content',
|
selectContent: 'Select content',
|
||||||
selectContentType: 'Select content type',
|
selectContentType: 'Select content type',
|
||||||
@@ -671,7 +671,7 @@ export default {
|
|||||||
email: 'Enter your email',
|
email: 'Enter your email',
|
||||||
enterMessage: 'Enter a message...',
|
enterMessage: 'Enter a message...',
|
||||||
usernameHint: 'Your username is usually your email',
|
usernameHint: 'Your username is usually your email',
|
||||||
anchor: '#value or ?key=value',
|
anchor: 'Enter an anchor or querystring, #value or ?key=value',
|
||||||
enterAlias: 'Enter alias...',
|
enterAlias: 'Enter alias...',
|
||||||
generatingAlias: 'Generating alias...',
|
generatingAlias: 'Generating alias...',
|
||||||
a11yCreateItem: 'Create item',
|
a11yCreateItem: 'Create item',
|
||||||
|
|||||||
@@ -491,9 +491,9 @@ export default {
|
|||||||
copiedItemOfItems: 'Copied %0% out of %1% items',
|
copiedItemOfItems: 'Copied %0% out of %1% items',
|
||||||
},
|
},
|
||||||
defaultdialogs: {
|
defaultdialogs: {
|
||||||
nodeNameLinkPicker: 'Link title',
|
nodeNameLinkPicker: 'Title',
|
||||||
urlLinkPicker: 'Link',
|
urlLinkPicker: 'Link',
|
||||||
anchorLinkPicker: 'Anchor / querystring',
|
anchorLinkPicker: 'Anchor or querystring',
|
||||||
anchorInsert: 'Name',
|
anchorInsert: 'Name',
|
||||||
closeThisWindow: 'Close this window',
|
closeThisWindow: 'Close this window',
|
||||||
confirmdelete: 'Are you sure you want to delete',
|
confirmdelete: 'Are you sure you want to delete',
|
||||||
@@ -553,7 +553,7 @@ export default {
|
|||||||
includeDescendants: 'Include descendants',
|
includeDescendants: 'Include descendants',
|
||||||
theFriendliestCommunity: 'The friendliest community',
|
theFriendliestCommunity: 'The friendliest community',
|
||||||
linkToPage: 'Link to document',
|
linkToPage: 'Link to document',
|
||||||
openInNewWindow: 'Opens the linked document in a new window or tab',
|
openInNewWindow: 'Opens the link in a new window or tab',
|
||||||
linkToMedia: 'Link to media',
|
linkToMedia: 'Link to media',
|
||||||
selectContentStartNode: 'Select content start node',
|
selectContentStartNode: 'Select content start node',
|
||||||
selectEvent: 'Select event',
|
selectEvent: 'Select event',
|
||||||
@@ -561,7 +561,7 @@ export default {
|
|||||||
selectMediaType: 'Select media type',
|
selectMediaType: 'Select media type',
|
||||||
selectIcon: 'Select icon',
|
selectIcon: 'Select icon',
|
||||||
selectItem: 'Select item',
|
selectItem: 'Select item',
|
||||||
selectLink: 'Select link',
|
selectLink: 'Configure link',
|
||||||
selectMacro: 'Select macro',
|
selectMacro: 'Select macro',
|
||||||
selectContent: 'Select content',
|
selectContent: 'Select content',
|
||||||
selectContentType: 'Select content type',
|
selectContentType: 'Select content type',
|
||||||
@@ -663,7 +663,7 @@ export default {
|
|||||||
email: 'Enter your email',
|
email: 'Enter your email',
|
||||||
enterMessage: 'Enter a message...',
|
enterMessage: 'Enter a message...',
|
||||||
usernameHint: 'Your username is usually your email',
|
usernameHint: 'Your username is usually your email',
|
||||||
anchor: '#value or ?key=value',
|
anchor: 'Enter an anchor or querystring, #value or ?key=value',
|
||||||
enterAlias: 'Enter alias...',
|
enterAlias: 'Enter alias...',
|
||||||
generatingAlias: 'Generating alias...',
|
generatingAlias: 'Generating alias...',
|
||||||
a11yCreateItem: 'Create item',
|
a11yCreateItem: 'Create item',
|
||||||
@@ -671,6 +671,7 @@ export default {
|
|||||||
a11yName: 'Name',
|
a11yName: 'Name',
|
||||||
rteParagraph: 'Write something amazing...',
|
rteParagraph: 'Write something amazing...',
|
||||||
rteHeading: "What's the title?",
|
rteHeading: "What's the title?",
|
||||||
|
enterUrl: 'Enter a URL...',
|
||||||
},
|
},
|
||||||
editcontenttype: {
|
editcontenttype: {
|
||||||
createListView: 'Create custom list view',
|
createListView: 'Create custom list view',
|
||||||
@@ -798,6 +799,7 @@ export default {
|
|||||||
dictionary: 'Dictionary',
|
dictionary: 'Dictionary',
|
||||||
dimensions: 'Dimensions',
|
dimensions: 'Dimensions',
|
||||||
discard: 'Discard',
|
discard: 'Discard',
|
||||||
|
document: 'Document',
|
||||||
down: 'Down',
|
down: 'Down',
|
||||||
download: 'Download',
|
download: 'Download',
|
||||||
edit: 'Edit',
|
edit: 'Edit',
|
||||||
@@ -2671,4 +2673,13 @@ export default {
|
|||||||
toolbar_removeItem: 'Remove action',
|
toolbar_removeItem: 'Remove action',
|
||||||
toolbar_emptyGroup: 'Empty',
|
toolbar_emptyGroup: 'Empty',
|
||||||
},
|
},
|
||||||
|
linkPicker: {
|
||||||
|
modalSource: 'Source',
|
||||||
|
modalManual: 'Manual',
|
||||||
|
modalAnchorValidationMessage:
|
||||||
|
'Please enter an anchor or querystring, or select a published document or media item, or manually configure the URL.',
|
||||||
|
resetUrlHeadline: 'Reset URL?',
|
||||||
|
resetUrlMessage: 'Are you sure you want to reset this URL?',
|
||||||
|
resetUrlLabel: 'Reset',
|
||||||
|
},
|
||||||
} as UmbLocalizationDictionary;
|
} as UmbLocalizationDictionary;
|
||||||
|
|||||||
@@ -6,38 +6,67 @@ import type {
|
|||||||
} from './link-picker-modal.token.js';
|
} from './link-picker-modal.token.js';
|
||||||
import { css, customElement, html, nothing, query, state, when } from '@umbraco-cms/backoffice/external/lit';
|
import { css, customElement, html, nothing, query, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||||
import { isUmbracoFolder, UmbMediaTypeStructureRepository } from '@umbraco-cms/backoffice/media-type';
|
import { isUmbracoFolder, UmbMediaTypeStructureRepository } from '@umbraco-cms/backoffice/media-type';
|
||||||
import { umbFocus } from '@umbraco-cms/backoffice/lit-element';
|
import { umbBindToValidation, UmbValidationContext } from '@umbraco-cms/backoffice/validation';
|
||||||
|
import { umbConfirmModal, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||||
import { UmbDocumentDetailRepository } from '@umbraco-cms/backoffice/document';
|
import { UmbDocumentDetailRepository } from '@umbraco-cms/backoffice/document';
|
||||||
import { UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media';
|
import { UmbMediaDetailRepository } from '@umbraco-cms/backoffice/media';
|
||||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
|
||||||
import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document';
|
import type { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document';
|
||||||
import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media';
|
import type { UmbInputMediaElement } from '@umbraco-cms/backoffice/media';
|
||||||
import type { UUIBooleanInputEvent, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
import type { UUIBooleanInputEvent, UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||||
|
|
||||||
type UmbInputPickerEvent = CustomEvent & { target: { value?: string } };
|
type UmbInputPickerEvent = CustomEvent & { target: { value?: string } };
|
||||||
|
|
||||||
@customElement('umb-link-picker-modal')
|
@customElement('umb-link-picker-modal')
|
||||||
export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPickerModalData, UmbLinkPickerModalValue> {
|
export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPickerModalData, UmbLinkPickerModalValue> {
|
||||||
|
#propertyLayoutOrientation: 'horizontal' | 'vertical' = 'vertical';
|
||||||
|
|
||||||
|
#validationContext = new UmbValidationContext(this);
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private _allowedMediaTypeUniques?: Array<string>;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private _config: UmbLinkPickerConfig = {
|
private _config: UmbLinkPickerConfig = {
|
||||||
hideAnchor: false,
|
hideAnchor: false,
|
||||||
hideTarget: false,
|
hideTarget: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@state()
|
|
||||||
private _allowedMediaTypeUniques?: Array<string>;
|
|
||||||
|
|
||||||
@query('umb-input-document')
|
@query('umb-input-document')
|
||||||
private _documentPickerElement?: UmbInputDocumentElement;
|
private _documentPickerElement?: UmbInputDocumentElement;
|
||||||
|
|
||||||
@query('umb-input-media')
|
@query('umb-input-media')
|
||||||
private _mediaPickerElement?: UmbInputMediaElement;
|
private _mediaPickerElement?: UmbInputMediaElement;
|
||||||
|
|
||||||
override async firstUpdated() {
|
@query('#link-anchor', true)
|
||||||
|
private _linkAnchorInput?: UUIInputElement;
|
||||||
|
|
||||||
|
override connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
|
||||||
if (this.data?.config) {
|
if (this.data?.config) {
|
||||||
this._config = this.data.config;
|
this._config = this.data.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.modalContext) {
|
||||||
|
this.observe(this.modalContext.size, (size) => {
|
||||||
|
if (size === 'large' || size === 'full') {
|
||||||
|
this.#propertyLayoutOrientation = 'horizontal';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#getMediaTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override firstUpdated() {
|
||||||
|
this._linkAnchorInput?.addValidator(
|
||||||
|
'valueMissing',
|
||||||
|
() => this.localize.term('linkPicker_modalAnchorValidationMessage'),
|
||||||
|
() => !this.value.link.url && !this.value.link.queryString,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async #getMediaTypes() {
|
||||||
// Get all the media types, excluding the folders, so that files are selectable media items.
|
// Get all the media types, excluding the folders, so that files are selectable media items.
|
||||||
const mediaTypeStructureRepository = new UmbMediaTypeStructureRepository(this);
|
const mediaTypeStructureRepository = new UmbMediaTypeStructureRepository(this);
|
||||||
const { data: mediaTypes } = await mediaTypeStructureRepository.requestAllowedChildrenOf(null);
|
const { data: mediaTypes } = await mediaTypeStructureRepository.requestAllowedChildrenOf(null);
|
||||||
@@ -61,7 +90,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
} else if (query) {
|
} else if (query) {
|
||||||
this.#partialUpdateLink({ queryString: `#${query}` });
|
this.#partialUpdateLink({ queryString: `#${query}` });
|
||||||
} else {
|
} else {
|
||||||
this.#partialUpdateLink({ queryString: query });
|
this.#partialUpdateLink({ queryString: '' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,24 +129,29 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
const unique = event.target.value;
|
const unique = event.target.value;
|
||||||
|
|
||||||
if (unique) {
|
if (unique) {
|
||||||
if (type === 'document') {
|
switch (type) {
|
||||||
const documentRepository = new UmbDocumentDetailRepository(this);
|
case 'document': {
|
||||||
const { data: documentData } = await documentRepository.requestByUnique(unique);
|
const documentRepository = new UmbDocumentDetailRepository(this);
|
||||||
if (documentData) {
|
const { data: documentData } = await documentRepository.requestByUnique(unique);
|
||||||
icon = documentData.documentType.icon;
|
if (documentData) {
|
||||||
name = documentData.variants[0].name;
|
icon = documentData.documentType.icon;
|
||||||
url = documentData.urls[0].url;
|
name = documentData.variants[0].name;
|
||||||
|
url = documentData.urls[0]?.url ?? '';
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case 'media': {
|
||||||
|
const mediaRepository = new UmbMediaDetailRepository(this);
|
||||||
if (type === 'media') {
|
const { data: mediaData } = await mediaRepository.requestByUnique(unique);
|
||||||
const mediaRepository = new UmbMediaDetailRepository(this);
|
if (mediaData) {
|
||||||
const { data: mediaData } = await mediaRepository.requestByUnique(unique);
|
icon = mediaData.mediaType.icon;
|
||||||
if (mediaData) {
|
name = mediaData.variants[0].name;
|
||||||
icon = mediaData.mediaType.icon;
|
url = mediaData.urls[0].url;
|
||||||
name = mediaData.variants[0].name;
|
}
|
||||||
url = mediaData.urls[0].url;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,10 +160,30 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
name: this.value.link.name || name,
|
name: this.value.link.name || name,
|
||||||
type: unique ? type : undefined,
|
type: unique ? type : undefined,
|
||||||
unique,
|
unique,
|
||||||
url,
|
url: url ?? this.value.link.url,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.#partialUpdateLink(link);
|
this.#partialUpdateLink(link);
|
||||||
|
|
||||||
|
await this.#validationContext.validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
async #onResetUrl() {
|
||||||
|
if (this.value.link.url) {
|
||||||
|
await umbConfirmModal(this, {
|
||||||
|
color: 'danger',
|
||||||
|
headline: this.localize.term('linkPicker_resetUrlHeadline'),
|
||||||
|
content: this.localize.term('linkPicker_resetUrlMessage'),
|
||||||
|
confirmLabel: this.localize.term('linkPicker_resetUrlLabel'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#partialUpdateLink({ type: null, url: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
async #onSubmit() {
|
||||||
|
await this.#validationContext.validate();
|
||||||
|
this.modalContext?.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#triggerDocumentPicker() {
|
#triggerDocumentPicker() {
|
||||||
@@ -140,12 +194,16 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
this._mediaPickerElement?.shadowRoot?.querySelector('#btn-add')?.dispatchEvent(new Event('click'));
|
this._mediaPickerElement?.shadowRoot?.querySelector('#btn-add')?.dispatchEvent(new Event('click'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#triggerExternalUrl() {
|
||||||
|
this.#partialUpdateLink({ type: 'external' });
|
||||||
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
return html`
|
return html`
|
||||||
<umb-body-layout headline=${this.localize.term('defaultdialogs_selectLink')}>
|
<umb-body-layout headline=${this.localize.term('defaultdialogs_selectLink')}>
|
||||||
<uui-box>
|
<uui-box>
|
||||||
${this.#renderLinkUrlInput()} ${this.#renderLinkTitleInput()} ${this.#renderLinkTargetInput()}
|
${this.#renderLinkType()} ${this.#renderLinkAnchorInput()} ${this.#renderLinkTitleInput()}
|
||||||
${this.#renderInternals()}
|
${this.#renderLinkTargetInput()}
|
||||||
</uui-box>
|
</uui-box>
|
||||||
<div slot="actions">
|
<div slot="actions">
|
||||||
<uui-button label=${this.localize.term('general_close')} @click=${this._rejectModal}></uui-button>
|
<uui-button label=${this.localize.term('general_close')} @click=${this._rejectModal}></uui-button>
|
||||||
@@ -153,56 +211,134 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
color="positive"
|
color="positive"
|
||||||
look="primary"
|
look="primary"
|
||||||
label=${this.localize.term('general_submit')}
|
label=${this.localize.term('general_submit')}
|
||||||
?disabled=${!this.value.link.url && !this.value.link.queryString}
|
?disabled=${!this.value.link.type}
|
||||||
@click=${this._submitModal}></uui-button>
|
@click=${this.#onSubmit}></uui-button>
|
||||||
</div>
|
</div>
|
||||||
</umb-body-layout>
|
</umb-body-layout>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
#renderLinkUrlInput() {
|
#renderLinkType() {
|
||||||
return html`
|
return html`
|
||||||
<umb-property-layout orientation="vertical">
|
<umb-property-layout
|
||||||
<div class="side-by-side" slot="editor">
|
orientation=${this.#propertyLayoutOrientation}
|
||||||
<umb-property-layout
|
label=${this.localize.term('linkPicker_modalSource')}
|
||||||
orientation="vertical"
|
mandatory>
|
||||||
label=${this.localize.term('defaultdialogs_link')}
|
<div slot="editor">
|
||||||
style="padding:0;">
|
${this.#renderLinkTypeSelection()} ${this.#renderDocumentPicker()} ${this.#renderMediaPicker()}
|
||||||
<uui-input
|
${this.#renderLinkUrlInput()} ${this.#renderLinkUrlInputReadOnly()}
|
||||||
slot="editor"
|
|
||||||
placeholder=${this.localize.term('general_url')}
|
|
||||||
label=${this.localize.term('general_url')}
|
|
||||||
.value=${this.value.link.url ?? ''}
|
|
||||||
?disabled=${this.value.link.unique ? true : false}
|
|
||||||
@change=${this.#onLinkUrlInput}
|
|
||||||
${umbFocus()}>
|
|
||||||
</uui-input>
|
|
||||||
</umb-property-layout>
|
|
||||||
${when(
|
|
||||||
!this._config.hideAnchor,
|
|
||||||
() => html`
|
|
||||||
<umb-property-layout
|
|
||||||
orientation="vertical"
|
|
||||||
label=${this.localize.term('defaultdialogs_anchorLinkPicker')}
|
|
||||||
style="padding:0;">
|
|
||||||
<uui-input
|
|
||||||
slot="editor"
|
|
||||||
placeholder=${this.localize.term('placeholders_anchor')}
|
|
||||||
label=${this.localize.term('placeholders_anchor')}
|
|
||||||
@change=${this.#onLinkAnchorInput}
|
|
||||||
.value=${this.value.link.queryString ?? ''}></uui-input>
|
|
||||||
</umb-property-layout>
|
|
||||||
`,
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</umb-property-layout>
|
</umb-property-layout>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#renderLinkTypeSelection() {
|
||||||
|
if (this.value.link.type) return nothing;
|
||||||
|
return html`
|
||||||
|
<uui-button-group>
|
||||||
|
<uui-button
|
||||||
|
data-mark="action:document"
|
||||||
|
look="placeholder"
|
||||||
|
label=${this.localize.term('general_document')}
|
||||||
|
@click=${this.#triggerDocumentPicker}></uui-button>
|
||||||
|
<uui-button
|
||||||
|
data-mark="action:media"
|
||||||
|
look="placeholder"
|
||||||
|
label=${this.localize.term('general_media')}
|
||||||
|
@click=${this.#triggerMediaPicker}></uui-button>
|
||||||
|
<uui-button
|
||||||
|
data-mark="action:external"
|
||||||
|
look="placeholder"
|
||||||
|
label=${this.localize.term('linkPicker_modalManual')}
|
||||||
|
@click=${this.#triggerExternalUrl}></uui-button>
|
||||||
|
</uui-button-group>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderDocumentPicker() {
|
||||||
|
return html`
|
||||||
|
<umb-input-document
|
||||||
|
?hidden=${!this.value.link.unique || this.value.link.type !== 'document'}
|
||||||
|
.max=${1}
|
||||||
|
.showOpenButton=${true}
|
||||||
|
.value=${this.value.link.unique && this.value.link.type === 'document' ? this.value.link.unique : ''}
|
||||||
|
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'document')}>
|
||||||
|
</umb-input-document>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderMediaPicker() {
|
||||||
|
return html`
|
||||||
|
<umb-input-media
|
||||||
|
?hidden=${!this.value.link.unique || this.value.link.type !== 'media'}
|
||||||
|
.allowedContentTypeIds=${this._allowedMediaTypeUniques}
|
||||||
|
.max=${1}
|
||||||
|
.value=${this.value.link.unique && this.value.link.type === 'media' ? this.value.link.unique : ''}
|
||||||
|
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'media')}></umb-input-media>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderLinkUrlInput() {
|
||||||
|
if (this.value.link.type !== 'external') return nothing;
|
||||||
|
return html`
|
||||||
|
<uui-input
|
||||||
|
data-mark="input:url"
|
||||||
|
label=${this.localize.term('placeholders_enterUrl')}
|
||||||
|
placeholder=${this.localize.term('placeholders_enterUrl')}
|
||||||
|
.value=${this.value.link.url ?? ''}
|
||||||
|
?disabled=${!!this.value.link.unique}
|
||||||
|
?required=${this._config.hideAnchor}
|
||||||
|
@change=${this.#onLinkUrlInput}
|
||||||
|
${umbBindToValidation(this)}>
|
||||||
|
${when(
|
||||||
|
!this.value.link.unique,
|
||||||
|
() => html`
|
||||||
|
<div slot="append">
|
||||||
|
<uui-button
|
||||||
|
slot="append"
|
||||||
|
compact
|
||||||
|
label=${this.localize.term('general_remove')}
|
||||||
|
@click=${this.#onResetUrl}>
|
||||||
|
<uui-icon name="remove"></uui-icon>
|
||||||
|
</uui-button>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</uui-input>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderLinkUrlInputReadOnly() {
|
||||||
|
if (!this.value.link.unique || !this.value.link.url) return nothing;
|
||||||
|
return html`<uui-input readonly value=${this.value.link.url}></uui-input>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderLinkAnchorInput() {
|
||||||
|
if (this._config.hideAnchor) return nothing;
|
||||||
|
return html`
|
||||||
|
<umb-property-layout
|
||||||
|
orientation=${this.#propertyLayoutOrientation}
|
||||||
|
label=${this.localize.term('defaultdialogs_anchorLinkPicker')}>
|
||||||
|
<uui-input
|
||||||
|
data-mark="input:anchor"
|
||||||
|
slot="editor"
|
||||||
|
id="link-anchor"
|
||||||
|
label=${this.localize.term('placeholders_anchor')}
|
||||||
|
placeholder=${this.localize.term('placeholders_anchor')}
|
||||||
|
.value=${this.value.link.queryString ?? ''}
|
||||||
|
@change=${this.#onLinkAnchorInput}
|
||||||
|
${umbBindToValidation(this)}></uui-input>
|
||||||
|
</umb-property-layout>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
#renderLinkTitleInput() {
|
#renderLinkTitleInput() {
|
||||||
return html`
|
return html`
|
||||||
<umb-property-layout orientation="vertical" label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}>
|
<umb-property-layout
|
||||||
|
orientation=${this.#propertyLayoutOrientation}
|
||||||
|
label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}>
|
||||||
<uui-input
|
<uui-input
|
||||||
|
data-mark="input:title"
|
||||||
slot="editor"
|
slot="editor"
|
||||||
label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}
|
label=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}
|
||||||
placeholder=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}
|
placeholder=${this.localize.term('defaultdialogs_nodeNameLinkPicker')}
|
||||||
@@ -216,7 +352,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
#renderLinkTargetInput() {
|
#renderLinkTargetInput() {
|
||||||
if (this._config.hideTarget) return nothing;
|
if (this._config.hideTarget) return nothing;
|
||||||
return html`
|
return html`
|
||||||
<umb-property-layout orientation="vertical" label=${this.localize.term('content_target')}>
|
<umb-property-layout orientation=${this.#propertyLayoutOrientation} label=${this.localize.term('content_target')}>
|
||||||
<uui-toggle
|
<uui-toggle
|
||||||
slot="editor"
|
slot="editor"
|
||||||
label=${this.localize.term('defaultdialogs_openInNewWindow')}
|
label=${this.localize.term('defaultdialogs_openInNewWindow')}
|
||||||
@@ -228,43 +364,6 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
#renderInternals() {
|
|
||||||
return html`
|
|
||||||
<umb-property-layout orientation="vertical" label=${this.localize.term('defaultdialogs_linkinternal')}>
|
|
||||||
<div slot="editor">
|
|
||||||
${when(
|
|
||||||
!this.value.link.unique,
|
|
||||||
() => html`
|
|
||||||
<uui-button-group>
|
|
||||||
<uui-button
|
|
||||||
look="placeholder"
|
|
||||||
label=${this.localize.term('defaultdialogs_linkToPage')}
|
|
||||||
@click=${this.#triggerDocumentPicker}></uui-button>
|
|
||||||
<uui-button
|
|
||||||
look="placeholder"
|
|
||||||
label=${this.localize.term('defaultdialogs_linkToMedia')}
|
|
||||||
@click=${this.#triggerMediaPicker}></uui-button>
|
|
||||||
</uui-button-group>
|
|
||||||
`,
|
|
||||||
)}
|
|
||||||
<umb-input-document
|
|
||||||
?hidden=${!this.value.link.unique || this.value.link.type !== 'document'}
|
|
||||||
.max=${1}
|
|
||||||
.showOpenButton=${true}
|
|
||||||
.value=${this.value.link.unique && this.value.link.type === 'document' ? this.value.link.unique : ''}
|
|
||||||
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'document')}>
|
|
||||||
</umb-input-document>
|
|
||||||
<umb-input-media
|
|
||||||
?hidden=${!this.value.link.unique || this.value.link.type !== 'media'}
|
|
||||||
.allowedContentTypeIds=${this._allowedMediaTypeUniques}
|
|
||||||
.max=${1}
|
|
||||||
.value=${this.value.link.unique && this.value.link.type === 'media' ? this.value.link.unique : ''}
|
|
||||||
@change=${(e: UmbInputPickerEvent) => this.#onPickerSelection(e, 'media')}></umb-input-media>
|
|
||||||
</div>
|
|
||||||
</umb-property-layout>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static override styles = [
|
static override styles = [
|
||||||
css`
|
css`
|
||||||
uui-box {
|
uui-box {
|
||||||
@@ -277,15 +376,9 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElement<UmbLinkPicker
|
|||||||
|
|
||||||
uui-input {
|
uui-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
|
||||||
|
|
||||||
.side-by-side {
|
&[readonly] {
|
||||||
display: flex;
|
margin-top: var(--uui-size-space-2);
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: var(--uui-size-space-5);
|
|
||||||
|
|
||||||
umb-property-layout {
|
|
||||||
flex: 1 1 0px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
|||||||
Reference in New Issue
Block a user