Feature: Sorter for block grid and list config editor
This commit is contained in:
committed by
Jacob Overgaard
parent
f6135adfd4
commit
467e770789
@@ -35,6 +35,7 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement
|
||||
extends UmbLitElement
|
||||
implements UmbPropertyEditorUiElement
|
||||
{
|
||||
#moveData?: Array<UmbBlockTypeWithGroupKey>;
|
||||
#sorter = new UmbSorterController<MappedGroupWithBlockTypes, HTMLElement>(this, {
|
||||
getUniqueOfElement: (element) => element.getAttribute('data-umb-group-key'),
|
||||
getUniqueOfModel: (modelEntry) => modelEntry.key!,
|
||||
@@ -128,13 +129,40 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement
|
||||
this.#sorter.setModel(this._groupsWithBlockTypes);
|
||||
}
|
||||
|
||||
#onChange(e: CustomEvent, groupKey?: string) {
|
||||
#onDelete(e: CustomEvent, groupKey?: string) {
|
||||
const updatedValues = (e.target as UmbInputBlockTypeElement).value.map((value) => ({ ...value, groupKey }));
|
||||
const filteredValues = this.value.filter((value) => value.groupKey !== groupKey);
|
||||
this.value = [...filteredValues, ...updatedValues];
|
||||
this.dispatchEvent(new UmbPropertyValueChangeEvent());
|
||||
}
|
||||
|
||||
async #onChange(e: CustomEvent) {
|
||||
e.stopPropagation();
|
||||
const element = e.target as UmbInputBlockTypeElement;
|
||||
const value = element.value;
|
||||
|
||||
if (!e.detail?.moveComplete) {
|
||||
// Container change, store data of the new group...
|
||||
const newGroupKey = element.getAttribute('data-umb-group-key');
|
||||
const movedItem = e.detail?.item as UmbBlockTypeWithGroupKey;
|
||||
// Check if item moved back to original group...
|
||||
movedItem.groupKey === newGroupKey
|
||||
? (this.#moveData = undefined)
|
||||
: (this.#moveData = value.map((block) => ({ ...block, groupKey: newGroupKey })));
|
||||
} else if (e.detail?.moveComplete) {
|
||||
// Move complete, get the blocks that were in an untouched group
|
||||
const blocks = this.value
|
||||
.filter((block) => !value.find((value) => value.contentElementTypeKey === block.contentElementTypeKey))
|
||||
.filter(
|
||||
(block) => !this.#moveData?.find((value) => value.contentElementTypeKey === block.contentElementTypeKey),
|
||||
);
|
||||
|
||||
this.value = this.#moveData ? [...blocks, ...value, ...this.#moveData] : [...blocks, ...value];
|
||||
this.dispatchEvent(new UmbPropertyValueChangeEvent());
|
||||
this.#moveData = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
#onCreate(e: CustomEvent, groupKey?: string) {
|
||||
const selectedElementType = e.detail.contentElementTypeKey;
|
||||
if (selectedElementType) {
|
||||
@@ -170,8 +198,9 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement
|
||||
? html`<umb-input-block-type
|
||||
.value=${this._notGroupedBlockTypes}
|
||||
.workspacePath=${this._workspacePath}
|
||||
@change=${this.#onChange}
|
||||
@create=${(e: CustomEvent) => this.#onCreate(e, undefined)}
|
||||
@change=${(e: CustomEvent) => this.#onChange(e, undefined)}></umb-input-block-type>`
|
||||
@delete=${(e: CustomEvent) => this.#onDelete(e, undefined)}></umb-input-block-type>`
|
||||
: ''}
|
||||
${repeat(
|
||||
this._groupsWithBlockTypes,
|
||||
@@ -180,10 +209,12 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement
|
||||
html`<div class="group" data-umb-group-key=${ifDefined(group.key)}>
|
||||
${group.key ? this.#renderGroupInput(group.key, group.name) : nothing}
|
||||
<umb-input-block-type
|
||||
data-umb-group-key=${group.key}
|
||||
.value=${group.blocks}
|
||||
.workspacePath=${this._workspacePath}
|
||||
@change=${this.#onChange}
|
||||
@create=${(e: CustomEvent) => this.#onCreate(e, group.key)}
|
||||
@change=${(e: CustomEvent) => this.#onChange(e, group.key)}></umb-input-block-type>
|
||||
@delete=${(e: CustomEvent) => this.#onDelete(e, group.key)}></umb-input-block-type>
|
||||
</div>`,
|
||||
)}
|
||||
</div>`;
|
||||
|
||||
@@ -3,7 +3,10 @@ import '../../../block-type/components/input-block-type/index.js';
|
||||
import { UMB_BLOCK_LIST_TYPE } from '../../types.js';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import {
|
||||
UmbPropertyValueChangeEvent,
|
||||
type UmbPropertyEditorConfigCollection,
|
||||
} from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
@@ -51,14 +54,19 @@ export class UmbPropertyEditorUIBlockListBlockConfigurationElement
|
||||
}
|
||||
}
|
||||
|
||||
#onChange(e: CustomEvent) {
|
||||
e.stopPropagation();
|
||||
this.value = (e.target as UmbInputBlockTypeElement).value;
|
||||
this.dispatchEvent(new UmbPropertyValueChangeEvent());
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<umb-input-block-type
|
||||
.value=${this.value}
|
||||
.workspacePath=${this._workspacePath}
|
||||
@create=${this.#onCreate}
|
||||
@change=${(e: Event) => {
|
||||
this.value = (e.target as UmbInputBlockTypeElement).value;
|
||||
}}></umb-input-block-type>`;
|
||||
@delete=${this.#onChange}
|
||||
@change=${this.#onChange}></umb-input-block-type>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,41 @@
|
||||
import type { UmbBlockTypeBaseModel } from '../../types.js';
|
||||
import type { UmbBlockTypeCardElement } from '../block-type-card/index.js';
|
||||
import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../../types.js';
|
||||
import { UMB_MODAL_MANAGER_CONTEXT, umbConfirmModal } from '@umbraco-cms/backoffice/modal';
|
||||
import '../block-type-card/index.js';
|
||||
import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UmbDeleteEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/document-type';
|
||||
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
|
||||
@customElement('umb-input-block-type')
|
||||
export class UmbInputBlockTypeElement<
|
||||
BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel,
|
||||
BlockType extends UmbBlockTypeWithGroupKey = UmbBlockTypeWithGroupKey,
|
||||
> extends UmbLitElement {
|
||||
#sorter = new UmbSorterController<BlockType, UmbBlockTypeCardElement>(this, {
|
||||
getUniqueOfElement: (element) => element.contentElementTypeKey,
|
||||
getUniqueOfModel: (modelEntry) => modelEntry.contentElementTypeKey!,
|
||||
itemSelector: 'umb-block-type-card',
|
||||
identifier: 'umb-block-type-sorter',
|
||||
containerSelector: '#blocks',
|
||||
onChange: ({ model }) => {
|
||||
this._items = model;
|
||||
},
|
||||
onContainerChange: ({ model, item }) => {
|
||||
this._items = model;
|
||||
this.dispatchEvent(new CustomEvent('change', { detail: { item } }));
|
||||
},
|
||||
onEnd: () => {
|
||||
this.dispatchEvent(new CustomEvent('change', { detail: { moveComplete: true } }));
|
||||
},
|
||||
});
|
||||
|
||||
@property({ type: Array, attribute: false })
|
||||
public set value(items) {
|
||||
this._items = items ?? [];
|
||||
this.#sorter.setModel(this._items);
|
||||
}
|
||||
public get value() {
|
||||
return this._items;
|
||||
@@ -67,7 +88,7 @@ export class UmbInputBlockTypeElement<
|
||||
|
||||
deleteItem(contentElementTypeKey: string) {
|
||||
this.value = this.value.filter((x) => x.contentElementTypeKey !== contentElementTypeKey);
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
this.dispatchEvent(new UmbDeleteEvent());
|
||||
}
|
||||
|
||||
protected getFormElement() {
|
||||
@@ -85,7 +106,7 @@ export class UmbInputBlockTypeElement<
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<div>
|
||||
return html`<div id="blocks">
|
||||
${repeat(this.value, (block) => block.contentElementTypeKey, this.#renderItem)} ${this.#renderButton()}
|
||||
</div>`;
|
||||
}
|
||||
@@ -93,6 +114,7 @@ export class UmbInputBlockTypeElement<
|
||||
#renderItem = (block: BlockType) => {
|
||||
return html`
|
||||
<umb-block-type-card
|
||||
.data-umb-content-element-key=${block.contentElementTypeKey}
|
||||
.name=${block.label}
|
||||
.iconColor=${block.iconColor}
|
||||
.backgroundColor=${block.backgroundColor}
|
||||
@@ -125,6 +147,10 @@ export class UmbInputBlockTypeElement<
|
||||
grid-template-rows: repeat(auto-fill, minmax(160px, 1fr));
|
||||
}
|
||||
|
||||
[drag-placeholder] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#add-button {
|
||||
text-align: center;
|
||||
min-height: 150px;
|
||||
|
||||
Reference in New Issue
Block a user