[WIP] Adds Member Type picker
A placeholder component for `<umb-input-member-type>`, for use with the Multinode Treepicker property-editor. Code files were largely duplicated from `umb-document-type-input`. The modal context code hasn't been copied over as it requires substantial work with developing the Member Type repository.
This commit is contained in:
committed by
Jacob Overgaard
parent
103c5fc9d7
commit
c6c45cf6cc
@@ -0,0 +1,18 @@
|
||||
import { UmbModalToken, UmbPickerModalValue, UmbTreePickerModalData } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbEntityTreeItemModel } from '@umbraco-cms/backoffice/tree';
|
||||
|
||||
export type UmbMemberTypePickerModalData = UmbTreePickerModalData<UmbEntityTreeItemModel>;
|
||||
export type UmbMemberTypePickerModalValue = UmbPickerModalValue;
|
||||
|
||||
export const UMB_MEMBER_TYPE_PICKER_MODAL = new UmbModalToken<UmbMemberTypePickerModalData, UmbMemberTypePickerModalValue>(
|
||||
'Umb.Modal.TreePicker',
|
||||
{
|
||||
modal: {
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
},
|
||||
data: {
|
||||
treeAlias: 'Umb.Tree.MemberType',
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
import './input-member-type/input-member-type.element.js';
|
||||
@@ -0,0 +1,13 @@
|
||||
import { UMB_MEMBER_TYPE_PICKER_MODAL } from '../../../../core/modal/token/member-type-picker-modal.token.js';
|
||||
import { UMB_MEMBER_TYPE_REPOSITORY_ALIAS } from '../../repository/index.js';
|
||||
import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { MemberTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
export class UmbMemberTypePickerContext extends UmbPickerInputContext<MemberTypeItemResponseModel> {
|
||||
constructor(host: UmbControllerHostElement) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
super(host, UMB_MEMBER_TYPE_REPOSITORY_ALIAS, UMB_MEMBER_TYPE_PICKER_MODAL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
import { UmbMemberTypePickerContext } from './input-member-type.context.js';
|
||||
import { css, html, customElement, property, state, ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import type { MemberTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { splitStringToArray } from '@umbraco-cms/backoffice/utils';
|
||||
|
||||
@customElement('umb-input-member-type')
|
||||
export class UmbMemberTypeInputElement extends FormControlMixin(UmbLitElement) {
|
||||
/**
|
||||
* This is a minimum amount of selected items in this input.
|
||||
* @type {number}
|
||||
* @attr
|
||||
* @default 0
|
||||
*/
|
||||
@property({ type: Number })
|
||||
public get min(): number {
|
||||
return this.#pickerContext.min;
|
||||
}
|
||||
public set min(value: number) {
|
||||
this.#pickerContext.min = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Infinity
|
||||
*/
|
||||
@property({ type: Number })
|
||||
public get max(): number {
|
||||
return this.#pickerContext.max;
|
||||
}
|
||||
public set max(value: number) {
|
||||
this.#pickerContext.max = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Max validation message.
|
||||
* @type {boolean}
|
||||
* @attr
|
||||
* @default
|
||||
*/
|
||||
@property({ type: String, attribute: 'min-message' })
|
||||
maxMessage = 'This field exceeds the allowed amount of items';
|
||||
|
||||
public get selectedIds(): Array<string> {
|
||||
return this.#pickerContext.getSelection();
|
||||
}
|
||||
public set selectedIds(ids: Array<string>) {
|
||||
this.#pickerContext.setSelection(ids);
|
||||
}
|
||||
|
||||
@property()
|
||||
public set value(idsString: string) {
|
||||
// Its with full purpose we don't call super.value, as thats being handled by the observation of the context selection.
|
||||
this.selectedIds = splitStringToArray(idsString);
|
||||
}
|
||||
|
||||
@property()
|
||||
get pickableFilter() {
|
||||
return this.#pickerContext.pickableFilter;
|
||||
}
|
||||
set pickableFilter(newVal) {
|
||||
this.#pickerContext.pickableFilter = newVal;
|
||||
}
|
||||
|
||||
@state()
|
||||
private _items?: Array<MemberTypeItemResponseModel>;
|
||||
|
||||
#pickerContext = new UmbMemberTypePickerContext(this);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this.addValidator(
|
||||
'rangeUnderflow',
|
||||
() => this.minMessage,
|
||||
() => !!this.min && this.#pickerContext.getSelection().length < this.min,
|
||||
);
|
||||
|
||||
this.addValidator(
|
||||
'rangeOverflow',
|
||||
() => this.maxMessage,
|
||||
() => !!this.max && this.#pickerContext.getSelection().length > this.max,
|
||||
);
|
||||
|
||||
this.observe(this.#pickerContext.selection, (selection) => (super.value = selection.join(',')));
|
||||
this.observe(this.#pickerContext.selectedItems, (selectedItems) => (this._items = selectedItems));
|
||||
}
|
||||
|
||||
protected _openPicker() {
|
||||
this.#pickerContext.openPicker({
|
||||
hideTreeRoot: true,
|
||||
});
|
||||
}
|
||||
|
||||
protected getFormElement() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this.#renderItems()}
|
||||
${this.#renderAddButton()}
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItems() {
|
||||
if (!this._items) return;
|
||||
// TODO: Add sorting. [LK]
|
||||
return html`
|
||||
<uui-ref-list
|
||||
>${repeat(
|
||||
this._items,
|
||||
(item) => item.id,
|
||||
(item) => this._renderItem(item),
|
||||
)}</uui-ref-list
|
||||
>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderAddButton() {
|
||||
if (this.max > 0 && this.selectedIds.length >= this.max) return;
|
||||
return html`
|
||||
<uui-button
|
||||
id="add-button"
|
||||
look="placeholder"
|
||||
@click=${this._openPicker}
|
||||
label="${this.localize.term('general_choose')}"
|
||||
>${this.localize.term('general_choose')}</uui-button
|
||||
>
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderItem(item: MemberTypeItemResponseModel) {
|
||||
if (!item.id) return;
|
||||
return html`
|
||||
<uui-ref-node-document-type name=${ifDefined(item.name)}>
|
||||
<uui-action-bar slot="actions">
|
||||
<uui-button
|
||||
@click=${() => this.#pickerContext.requestRemoveItem(item.id!)}
|
||||
label="Remove Member Type ${item.name}"
|
||||
>${this.localize.term('general_remove')}</uui-button
|
||||
>
|
||||
</uui-action-bar>
|
||||
</uui-ref-node-document-type>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
#add-button {
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbMemberTypeInputElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-input-member-type': UmbMemberTypeInputElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import './components/index.js';
|
||||
|
||||
export * from './components/index.js';
|
||||
export * from './repository/index.js';
|
||||
export * from './entity.js';
|
||||
@@ -1,13 +1,15 @@
|
||||
import { manifests as entityActionsManifests } from './entity-actions/manifests.js';
|
||||
import { manifests as menuItemManifests } from './menu-item/manifests.js';
|
||||
import { manifests as treeManifests } from './tree/manifests.js';
|
||||
import { manifests as repositoryManifests } from './repository/manifests.js';
|
||||
import { manifests as treeManifests } from './tree/manifests.js';
|
||||
import { manifests as workspaceManifests } from './workspace/manifests.js';
|
||||
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
|
||||
|
||||
import './components/index.js';
|
||||
|
||||
export const manifests = [
|
||||
...entityActionsManifests,
|
||||
...menuItemManifests,
|
||||
...treeManifests,
|
||||
...repositoryManifests,
|
||||
...treeManifests,
|
||||
...workspaceManifests,
|
||||
...entityActionManifests,
|
||||
];
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { UmbMemberTypeRepository } from './member-type.repository.js';
|
||||
export * from './member-type.repository.js';
|
||||
export * from './manifests.js';
|
||||
|
||||
Reference in New Issue
Block a user