Merge pull request #1465 from umbraco/feature/input-manifest

Feature: Manifest input
This commit is contained in:
Lee Kelleher
2024-03-22 07:50:47 +00:00
committed by GitHub
6 changed files with 202 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# Manifest Picker Example
This example demonstrates the Manifest picker input UI.

View File

@@ -0,0 +1,15 @@
import type { ManifestDashboard } from '@umbraco-cms/backoffice/extension-registry';
export const manifests: Array<ManifestDashboard> = [
{
type: 'dashboard',
name: 'Example Manifest Picker Dashboard',
alias: 'example.dashboard.manifestPicker',
element: () => import('./manifest-picker-dashboard.js'),
weight: 1000,
meta: {
label: 'Manifest Picker example',
pathname: 'example-manifest-picker',
},
},
];

View File

@@ -0,0 +1,97 @@
import { css, html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
@customElement('example-manifest-picker-dashboard')
export class ExampleManifestPickerDashboard extends UmbLitElement {
#options: Array<Option> = [];
@state()
private _selectedExtensionType: string = 'collectionView';
@state()
private _selectedManifest: string = '';
constructor() {
super();
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
const types = [...new Set(extensions.map((x) => x.type))];
this.#options = types.sort().map((x) => ({
name: x,
value: x,
selected: x === this._selectedExtensionType,
}));
});
}
#onSelect(event: UUISelectEvent) {
this._selectedManifest = '';
this._selectedExtensionType = event.target.value as string;
}
#onChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
render() {
return html`
<uui-box>
<umb-property-layout label="Select a extension type...">
<uui-select
slot="editor"
label="Select type..."
placeholder="Select type..."
.options=${this.#options}
@change=${this.#onSelect}></uui-select>
</umb-property-layout>
${when(
this._selectedExtensionType,
() => html`
<umb-property-layout label="Selected extension type" description=${this._selectedExtensionType}>
<div slot="editor">
<umb-input-manifest
.extensionType=${this._selectedExtensionType}
@change=${this.#onChange}></umb-input-manifest>
</div>
</umb-property-layout>
`,
() => nothing,
)}
${when(
this._selectedManifest,
() => html`
<umb-property-layout label="Selected manifest">
<div slot="editor">
<code>${this._selectedManifest}</code>
</div>
</umb-property-layout>
`,
() => nothing,
)}
</uui-box>
`;
}
static styles = [
UmbTextStyles,
css`
:host {
display: block;
padding: var(--uui-size-layout-1);
}
`,
];
}
export default ExampleManifestPickerDashboard;
declare global {
interface HTMLElementTagNameMap {
'example-manifest-picker-dashboard': ExampleManifestPickerDashboard;
}
}

View File

@@ -20,6 +20,7 @@ export * from './input-date/index.js';
export * from './input-dropdown/index.js';
export * from './input-eye-dropper/index.js';
export * from './input-list-base/index.js';
export * from './input-manifest/index.js';
export * from './input-multi-url/index.js';
export * from './input-number-range/index.js';
export * from './input-radio-button-list/index.js';

View File

@@ -0,0 +1 @@
export * from './input-manifest.element.js';

View File

@@ -0,0 +1,85 @@
import { html, customElement, property, css } from '@umbraco-cms/backoffice/external/lit';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_ITEM_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
@customElement('umb-input-manifest')
export class UmbInputManifestElement extends UmbLitElement {
#extensions: Array<typeof umbExtensionsRegistry.MANIFEST_TYPES> = [];
#extensionType?: string;
@property({ type: String, attribute: 'extension-type' })
public set extensionType(value: string | undefined) {
this.#extensionType = value;
this.#observeExtensions();
}
public get extensionType(): string | undefined {
return this.#extensionType;
}
@property({ attribute: false })
value?: typeof UMB_ITEM_PICKER_MODAL.VALUE;
@property({ type: Number })
max = Infinity;
#observeExtensions() {
if (!this.#extensionType) return;
this.observe(umbExtensionsRegistry.byType(this.#extensionType), (extensions) => {
this.#extensions = extensions.sort((a, b) => a.type.localeCompare(b.type) || a.alias.localeCompare(b.alias));
});
}
async #onClick() {
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
const modalContext = modalManager.open(this, UMB_ITEM_PICKER_MODAL, {
data: {
headline: `${this.localize.term('general_choose')}...`,
items: this.#extensions
.filter((ext) => ext.type === this.extensionType)
.map((ext) => ({
label: ext.name,
value: ext.alias,
description: ext.alias,
icon: (ext as any).meta?.icon, // HACK: Ugly way to get the icon. [LK]
})),
},
});
const modalValue = await modalContext.onSubmit();
if (!modalValue) return;
this.value = modalValue;
this.dispatchEvent(new UmbChangeEvent());
}
render() {
return html`
<uui-button
label=${this.localize.term('general_choose')}
look="placeholder"
color="default"
@click=${this.#onClick}></uui-button>
`;
}
static styles = [
css`
:host {
display: flex;
flex-direction: column;
}
`,
];
}
export default UmbInputManifestElement;
declare global {
interface HTMLElementTagNameMap {
'umb-input-manifest': UmbInputManifestElement;
}
}