add data type input and picker modal

This commit is contained in:
Mads Rasmussen
2023-04-12 17:08:14 +02:00
parent 191bc18acb
commit 3b2fc0e6e4
9 changed files with 234 additions and 1 deletions

View File

@@ -259,7 +259,7 @@ export class UmbWorkspacePackageBuilderElement extends UmbLitElement {
#renderDataTypeSection() {
return html`<div slot="editor">
<umb-input-checkbox-list></umb-input-checkbox-list>
<umb-data-type-input></umb-data-type-input>
</div>`;
}

View File

@@ -0,0 +1,10 @@
import { UmbPickerContext } from '@umbraco-cms/backoffice/picker';
import { UmbDataTypeRepository } from '../../repository/data-type.repository';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
import { UMB_DATA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
export class UmbDataTypePickerContext extends UmbPickerContext<UmbDataTypeRepository> {
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Repository.DataType', UMB_DATA_TYPE_PICKER_MODAL);
}
}

View File

@@ -0,0 +1,128 @@
import { css, html } 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 { UmbDataTypePickerContext } from './data-type-input.context';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_DATA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
@customElement('umb-data-type-input')
export class UmbDataTypeInputElement extends FormControlMixin(UmbLitElement) {
static styles = [
UUITextStyles,
css`
#add-button {
width: 100%;
}
`,
];
/**
* 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';
private _selectedIds: Array<string> = [];
public get selectedIds(): Array<string> {
return this._selectedIds;
}
public set selectedIds(ids: Array<string>) {
this._selectedIds = ids;
super.value = ids.join(',');
}
@property()
public set value(idsString: string) {
if (idsString !== this._value) {
this.selectedIds = idsString.split(/[ ,]+/);
}
}
@state()
private _items?: Array<DataTypeItemResponseModel>;
#pickerContext = new UmbDataTypePickerContext(this);
constructor() {
super();
this.addValidator(
'rangeUnderflow',
() => this.minMessage,
() => !!this.min && this._selectedIds.length < this.min
);
this.addValidator(
'rangeOverflow',
() => this.maxMessage,
() => !!this.max && this._selectedIds.length > this.max
);
this.observe(this.#pickerContext.selection, (selection) => (this.selectedIds = selection));
//this.observe(this.#pickerContext.items, (items) => (this._items = items));
}
protected getFormElement() {
return undefined;
}
render() {
return html`
<uui-ref-list>${this._items?.map((item) => this._renderItem(item))}</uui-ref-list>
<uui-button id="add-button" look="placeholder" @click=${() => this.#pickerContext.openPicker()} label="open"
>Add</uui-button
>
`;
}
private _renderItem(item: DataTypeItemResponseModel) {
return html`
<uui-ref-node-data-type name=${item.name}>
<uui-action-bar slot="actions">
<uui-button @click=${() => this.#pickerContext.removeItem(item.id)} label="Remove Data Type ${item.name}"
>Remove</uui-button
>
</uui-action-bar>
</uui-ref-node-data-type>
`;
}
}
export default UmbDataTypeInputElement;
declare global {
interface HTMLElementTagNameMap {
'umb-data-type-input': UmbDataTypeInputElement;
}
}

View File

@@ -0,0 +1 @@
import './data-type-input/data-type-input.element';

View File

@@ -0,0 +1 @@
import './components';

View File

@@ -3,6 +3,7 @@ import { manifests as repositoryManifests } from './repository/manifests';
import { manifests as menuItemManifests } from './menu-item/manifests';
import { manifests as treeManifests } from './tree/manifests';
import { manifests as workspaceManifests } from './workspace/manifests';
import { manifests as modalManifests } from './modal/manifests';
export const manifests = [
...entityActions,
@@ -10,4 +11,5 @@ export const manifests = [
...menuItemManifests,
...treeManifests,
...workspaceManifests,
...modalManifests,
];

View File

@@ -0,0 +1,77 @@
import { css, html } from 'lit';
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { customElement, property, state } from 'lit/decorators.js';
import type { UmbTreeElement } from '../../../../shared/components/tree/tree.element';
import {
UmbDocumentTypePickerModalData,
UmbDocumentTypePickerModalResult,
UmbModalHandler,
} from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
// TODO: make use of UmbPickerLayoutBase
@customElement('umb-data-type-picker-modal')
export class UmbDataTypePickerModalElement extends UmbLitElement {
static styles = [UUITextStyles, css``];
@property({ attribute: false })
modalHandler?: UmbModalHandler<UmbDocumentTypePickerModalData, UmbDocumentTypePickerModalResult>;
@property({ type: Object, attribute: false })
data?: UmbDocumentTypePickerModalData;
@state()
_selection: Array<string> = [];
@state()
_multiple = true;
connectedCallback() {
super.connectedCallback();
this._selection = this.data?.selection ?? [];
this._multiple = this.data?.multiple ?? true;
}
private _handleSelectionChange(e: CustomEvent) {
e.stopPropagation();
const element = e.target as UmbTreeElement;
//TODO: Should multiple property be implemented here or be passed down into umb-tree?
this._selection = this._multiple ? element.selection : [element.selection[element.selection.length - 1]];
}
private _submit() {
this.modalHandler?.submit({ selection: this._selection });
}
private _close() {
this.modalHandler?.reject();
}
render() {
return html`
<umb-workspace-layout headline="Select">
<uui-box>
<uui-input></uui-input>
<hr />
<umb-tree
alias="Umb.Tree.DataTypes"
@selected=${this._handleSelectionChange}
.selection=${this._selection}
selectable></umb-tree>
</uui-box>
<div slot="actions">
<uui-button label="Close" @click=${this._close}></uui-button>
<uui-button label="Submit" look="primary" color="positive" @click=${this._submit}></uui-button>
</div>
</umb-workspace-layout>
`;
}
}
export default UmbDataTypePickerModalElement;
declare global {
interface HTMLElementTagNameMap {
'umb-data-type-picker-modal': UmbDataTypePickerModalElement;
}
}

View File

@@ -0,0 +1,12 @@
import type { ManifestModal } from '@umbraco-cms/backoffice/extensions-registry';
const modals: Array<ManifestModal> = [
{
type: 'modal',
alias: 'Umb.Modal.DataTypePicker',
name: 'Data Type Picker Modal',
loader: () => import('./data-type-picker/data-type-picker-modal.element'),
},
];
export const manifests = [...modals];

View File

@@ -11,6 +11,8 @@ import { manifests as logviewerManifests } from './logviewer/manifests';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api';
import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry';
import './data-types/components';
export const manifests = [
...settingsSectionManifests,
...settingsMenuManifests,