Merge branch 'main' into feature/reload-tree-item
This commit is contained in:
@@ -706,6 +706,13 @@ export const data: Array<UmbMockDataTypeModel> = [
|
||||
icon: 'icon-book-alt',
|
||||
groupKey: 'demo-block-group-id',
|
||||
},
|
||||
{
|
||||
label: 'Test broken group key',
|
||||
contentElementTypeKey: 'test-block-id',
|
||||
editorSize: 'medium',
|
||||
icon: 'icon-war',
|
||||
groupKey: 'group-id-that-does-not-exist',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1488,4 +1488,30 @@ export const data: Array<UmbMockDocumentTypeModel> = [
|
||||
properties: [],
|
||||
containers: [],
|
||||
},
|
||||
{
|
||||
allowedTemplateIds: [],
|
||||
defaultTemplateId: null,
|
||||
id: 'test-block-id',
|
||||
alias: 'testBlock',
|
||||
name: 'Test broken group key',
|
||||
description: null,
|
||||
icon: 'icon-war',
|
||||
allowedAsRoot: true,
|
||||
variesByCulture: false,
|
||||
variesBySegment: false,
|
||||
isElement: true,
|
||||
hasChildren: false,
|
||||
isContainer: false,
|
||||
parentId: null,
|
||||
isFolder: false,
|
||||
allowedContentTypes: [],
|
||||
compositions: [],
|
||||
cleanup: {
|
||||
preventCleanup: false,
|
||||
keepAllVersionsNewerThanDays: null,
|
||||
keepLatestVersionPerDayForDays: null,
|
||||
},
|
||||
properties: [],
|
||||
containers: [],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifest: ManifestPropertyEditorUi = {
|
||||
type: 'propertyEditorUi',
|
||||
alias: 'Umb.PropertyEditorUi.BlockTypeGroupConfiguration',
|
||||
name: 'Block Grid Group Configuration Property Editor UI',
|
||||
js: () => import('./property-editor-ui-block-grid-group-configuration.element.js'),
|
||||
meta: {
|
||||
label: '',
|
||||
icon: 'icon-box-alt',
|
||||
group: 'common',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
import { html, customElement, property, css } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbId } from '@umbraco-cms/backoffice/id';
|
||||
import type { UmbBlockGridGroupType } from '@umbraco-cms/backoffice/block';
|
||||
|
||||
@customElement('umb-property-editor-ui-block-grid-group-configuration')
|
||||
export class UmbPropertyEditorUIBlockGridGroupConfigurationElement
|
||||
extends UmbLitElement
|
||||
implements UmbPropertyEditorUiElement
|
||||
{
|
||||
private _value: Array<UmbBlockGridGroupType> = [];
|
||||
|
||||
@property({ type: Array })
|
||||
public get value(): Array<UmbBlockGridGroupType> {
|
||||
return this._value;
|
||||
}
|
||||
public set value(value: Array<UmbBlockGridGroupType>) {
|
||||
this._value = value || [];
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
public set config(config: UmbPropertyEditorConfigCollection | undefined) {}
|
||||
|
||||
#addGroup() {
|
||||
this.value = [...this._value, { name: 'Unnamed group', key: UmbId.new() }];
|
||||
this.dispatchEvent(new CustomEvent('property-value-change'));
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-button label=${this.localize.term('blockEditor_addBlockGroup')} look="placeholder" @click=${this.#addGroup}>
|
||||
${this.localize.term('blockEditor_addBlockGroup')}
|
||||
</uui-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
uui-button {
|
||||
display: block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbPropertyEditorUIBlockGridGroupConfigurationElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-property-editor-ui-block-grid-group-configuration': UmbPropertyEditorUIBlockGridGroupConfigurationElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { Meta, Story } from '@storybook/web-components';
|
||||
import type { UmbPropertyEditorUIBlockGridGroupConfigurationElement } from './property-editor-ui-block-grid-group-configuration.element.js';
|
||||
import { html } from '@umbraco-cms/backoffice/external/lit';
|
||||
|
||||
import './property-editor-ui-block-grid-group-configuration.element.js';
|
||||
|
||||
export default {
|
||||
title: 'Property Editor UIs/Block Grid Group Configuration',
|
||||
component: 'umb-property-editor-ui-block-grid-group-configuration',
|
||||
id: 'umb-property-editor-ui-block-grid-group-configuration',
|
||||
} as Meta;
|
||||
|
||||
export const AAAOverview: Story<UmbPropertyEditorUIBlockGridGroupConfigurationElement> = () =>
|
||||
html` <umb-property-editor-ui-block-grid-group-configuration></umb-property-editor-ui-block-grid-group-configuration>`;
|
||||
AAAOverview.storyName = 'Overview';
|
||||
@@ -1,10 +1,21 @@
|
||||
import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '../../../block-type/index.js';
|
||||
import type { UmbBlockTypeWithGroupKey, UmbInputBlockTypeElement } from '../../../block-type/index.js';
|
||||
import '../../../block-type/components/input-block-type/index.js';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import { html, customElement, property, state, repeat, nothing, css } from '@umbraco-cms/backoffice/external/lit';
|
||||
import {
|
||||
UmbPropertyValueChangeEvent,
|
||||
type UmbPropertyEditorConfigCollection,
|
||||
} from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import {
|
||||
UMB_BLOCK_GRID_TYPE,
|
||||
type UmbBlockGridGroupType,
|
||||
type UmbBlockGridGroupTypeConfiguration,
|
||||
} from '@umbraco-cms/backoffice/block';
|
||||
import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UMB_PROPERTY_DATASET_CONTEXT, type UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||
import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-block-grid-type-configuration
|
||||
@@ -14,22 +25,150 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement
|
||||
extends UmbLitElement
|
||||
implements UmbPropertyEditorUiElement
|
||||
{
|
||||
#datasetContext?: UmbPropertyDatasetContext;
|
||||
#blockTypeWorkspaceModalRegistration?: UmbModalRouteRegistrationController<
|
||||
typeof UMB_WORKSPACE_MODAL.DATA,
|
||||
typeof UMB_WORKSPACE_MODAL.VALUE
|
||||
>;
|
||||
|
||||
private _value: Array<UmbBlockTypeWithGroupKey> = [];
|
||||
@property({ attribute: false })
|
||||
value: UmbBlockTypeBaseModel[] = [];
|
||||
get value() {
|
||||
return this._value;
|
||||
}
|
||||
set value(value: Array<UmbBlockTypeWithGroupKey>) {
|
||||
this._value = value ?? [];
|
||||
}
|
||||
|
||||
@property({ type: Object, attribute: false })
|
||||
public config?: UmbPropertyEditorConfigCollection;
|
||||
|
||||
render() {
|
||||
return html`<umb-input-block-type
|
||||
entity-type="block-grid-type"
|
||||
.value=${this.value}
|
||||
@change=${(e: Event) => {
|
||||
this.value = (e.target as UmbInputBlockTypeElement).value;
|
||||
}}></umb-input-block-type>`;
|
||||
@state()
|
||||
private _blockGroups: Array<UmbBlockGridGroupType> = [];
|
||||
|
||||
@state()
|
||||
private _mappedValuesAndGroups: Array<UmbBlockGridGroupTypeConfiguration> = [];
|
||||
|
||||
@state()
|
||||
private _workspacePath?: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => {
|
||||
this.#datasetContext = instance;
|
||||
this.#observeProperties();
|
||||
});
|
||||
|
||||
this.#blockTypeWorkspaceModalRegistration?.destroy();
|
||||
|
||||
this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(UMB_BLOCK_GRID_TYPE)
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: UMB_BLOCK_GRID_TYPE, preset: {} }, modal: { size: 'large' } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
const newpath = routeBuilder({});
|
||||
this._workspacePath = newpath;
|
||||
});
|
||||
}
|
||||
|
||||
static styles = [UmbTextStyles];
|
||||
async #observeProperties() {
|
||||
if (!this.#datasetContext) return;
|
||||
|
||||
this.observe(await this.#datasetContext.propertyValueByAlias('blockGroups'), (value) => {
|
||||
this._blockGroups = (value as Array<UmbBlockGridGroupType>) ?? [];
|
||||
this.#mapValuesToBlockGroups();
|
||||
});
|
||||
this.observe(await this.#datasetContext.propertyValueByAlias('blocks'), () => {
|
||||
this.#mapValuesToBlockGroups();
|
||||
});
|
||||
}
|
||||
|
||||
#mapValuesToBlockGroups() {
|
||||
// What if a block is in a group that does not exist in the block groups? Should it be removed? (Right now they will never be rendered)
|
||||
const valuesWithNoGroup = this._value.filter((value) => !value.groupKey);
|
||||
|
||||
const valuesWithGroup = this._blockGroups.map((group) => {
|
||||
return { name: group.name, key: group.key, blocks: this._value.filter((value) => value.groupKey === group.key) };
|
||||
});
|
||||
|
||||
this._mappedValuesAndGroups = [{ blocks: valuesWithNoGroup }, ...valuesWithGroup];
|
||||
}
|
||||
|
||||
#onChange(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());
|
||||
}
|
||||
|
||||
#onCreate(e: CustomEvent, groupKey: string | null) {
|
||||
const selectedElementType = e.detail.contentElementTypeKey;
|
||||
if (selectedElementType) {
|
||||
this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/' + groupKey);
|
||||
}
|
||||
}
|
||||
|
||||
#deleteGroup(groupKey: string) {
|
||||
this.#datasetContext?.setPropertyValue(
|
||||
'blockGroups',
|
||||
this._blockGroups.filter((group) => group.key !== groupKey),
|
||||
);
|
||||
|
||||
// Should blocks that belonged to the removed group be deleted as well?
|
||||
this.value = this._value.filter((block) => block.groupKey !== groupKey);
|
||||
}
|
||||
|
||||
#changeGroupName(e: UUIInputEvent, groupKey: string) {
|
||||
const groupName = e.target.value as string;
|
||||
this.#datasetContext?.setPropertyValue(
|
||||
'blockGroups',
|
||||
this._blockGroups.map((group) => (group.key === groupKey ? { ...group, name: groupName } : group)),
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`${repeat(
|
||||
this._mappedValuesAndGroups,
|
||||
(group) => group.key,
|
||||
(group) =>
|
||||
html`${group.key ? this.#renderGroupInput(group.key, group.name) : nothing}
|
||||
<umb-input-block-type
|
||||
.value=${group.blocks}
|
||||
.workspacePath=${this._workspacePath}
|
||||
@create=${(e: CustomEvent) => this.#onCreate(e, group.key ?? null)}
|
||||
@change=${(e: CustomEvent) => this.#onChange(e, group.key)}></umb-input-block-type>`,
|
||||
)}`;
|
||||
}
|
||||
|
||||
#renderGroupInput(groupKey: string, groupName?: string) {
|
||||
return html`<uui-input
|
||||
auto-width
|
||||
label="Group"
|
||||
.value=${groupName ?? ''}
|
||||
@change=${(e: UUIInputEvent) => this.#changeGroupName(e, groupKey)}>
|
||||
<uui-button compact slot="append" label="delete" @click=${() => this.#deleteGroup(groupKey)}>
|
||||
<uui-icon name="icon-trash"></uui-icon>
|
||||
</uui-button>
|
||||
</uui-input>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
uui-input {
|
||||
margin-top: var(--uui-size-6);
|
||||
margin-bottom: var(--uui-size-4);
|
||||
}
|
||||
|
||||
uui-input:not(:hover, :focus) {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
uui-input:not(:hover, :focus) uui-button {
|
||||
opacity: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbPropertyEditorUIBlockGridTypeConfigurationElement;
|
||||
|
||||
@@ -2,5 +2,12 @@ import { manifest as blockGridEditor } from './block-grid-editor/manifests.js';
|
||||
import { manifest as blockGridLayoutStylesheet } from './block-grid-layout-stylesheet/manifests.js';
|
||||
import { manifest as blockGridTypeConfiguration } from './block-grid-type-configuration/manifests.js';
|
||||
import { manifest as blockGridColumnSpan } from './block-grid-column-span/manifests.js';
|
||||
import { manifest as blockGridGroupConfiguration } from './block-grid-group-configuration/manifests.js';
|
||||
|
||||
export const manifests = [blockGridTypeConfiguration, blockGridEditor, blockGridLayoutStylesheet, blockGridColumnSpan];
|
||||
export const manifests = [
|
||||
blockGridTypeConfiguration,
|
||||
blockGridEditor,
|
||||
blockGridLayoutStylesheet,
|
||||
blockGridColumnSpan,
|
||||
blockGridGroupConfiguration,
|
||||
];
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { UmbBlockTypeBaseModel } from '../block-type/index.js';
|
||||
import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../block-type/index.js';
|
||||
|
||||
export const UMB_BLOCK_GRID_TYPE = 'block-grid-type';
|
||||
|
||||
export interface UmbBlockGridType extends UmbBlockTypeBaseModel {
|
||||
columnSpanOptions: Array<number>;
|
||||
@@ -9,5 +11,13 @@ export interface UmbBlockGridType extends UmbBlockTypeBaseModel {
|
||||
thumbnail?: string;
|
||||
areaGridColumns?: number;
|
||||
areas: Array<any>;
|
||||
groupKey: null | string;
|
||||
}
|
||||
|
||||
export interface UmbBlockGridGroupType {
|
||||
name: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface UmbBlockGridGroupTypeConfiguration extends Partial<UmbBlockGridGroupType> {
|
||||
blocks: Array<UmbBlockTypeWithGroupKey>;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '../../../block-type/index.js';
|
||||
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 } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
/**
|
||||
* @element umb-property-editor-ui-block-list-type-configuration
|
||||
@@ -14,16 +16,47 @@ export class UmbPropertyEditorUIBlockListBlockConfigurationElement
|
||||
extends UmbLitElement
|
||||
implements UmbPropertyEditorUiElement
|
||||
{
|
||||
#blockTypeWorkspaceModalRegistration?: UmbModalRouteRegistrationController<
|
||||
typeof UMB_WORKSPACE_MODAL.DATA,
|
||||
typeof UMB_WORKSPACE_MODAL.VALUE
|
||||
>;
|
||||
|
||||
@state()
|
||||
private _workspacePath?: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#blockTypeWorkspaceModalRegistration?.destroy();
|
||||
|
||||
this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(UMB_BLOCK_LIST_TYPE)
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: UMB_BLOCK_LIST_TYPE, preset: {} }, modal: { size: 'large' } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
const newpath = routeBuilder({});
|
||||
this._workspacePath = newpath;
|
||||
});
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
value: UmbBlockTypeBaseModel[] = [];
|
||||
|
||||
@property({ type: Object, attribute: false })
|
||||
public config?: UmbPropertyEditorConfigCollection;
|
||||
|
||||
#onCreate(e: CustomEvent) {
|
||||
const selectedElementType = e.detail.contentElementTypeKey;
|
||||
if (selectedElementType) {
|
||||
this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType + '/null');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<umb-input-block-type
|
||||
entity-type="block-list-type"
|
||||
.value=${this.value}
|
||||
.workspacePath=${this._workspacePath}
|
||||
@create=${this.#onCreate}
|
||||
@change=${(e: Event) => {
|
||||
this.value = (e.target as UmbInputBlockTypeElement).value;
|
||||
}}></umb-input-block-type>`;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { UmbBlockTypeBaseModel } from '../block-type/index.js';
|
||||
import type { UmbBlockLayoutBaseModel } from '../index.js';
|
||||
|
||||
export const UMB_BLOCK_LIST_TYPE = 'block-list-type';
|
||||
|
||||
export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {}
|
||||
export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './input-block-type/index.js';
|
||||
export * from './block-type-card/index.js';
|
||||
export * from './input-block-type/index.js';
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
import type { UmbBlockTypeBaseModel } from '../../types.js';
|
||||
import {
|
||||
UMB_DOCUMENT_TYPE_PICKER_MODAL,
|
||||
UMB_MODAL_MANAGER_CONTEXT,
|
||||
UMB_WORKSPACE_MODAL,
|
||||
UmbModalRouteRegistrationController,
|
||||
} from '@umbraco-cms/backoffice/modal';
|
||||
import { UMB_DOCUMENT_TYPE_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } 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/internal/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';
|
||||
|
||||
@customElement('umb-input-block-type')
|
||||
export class UmbInputBlockTypeElement<
|
||||
BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel,
|
||||
> extends UmbLitElement {
|
||||
//
|
||||
@property({ type: Array, attribute: false })
|
||||
public get value() {
|
||||
return this._items;
|
||||
@@ -23,43 +19,23 @@ export class UmbInputBlockTypeElement<
|
||||
this._items = items ?? [];
|
||||
}
|
||||
|
||||
@property({ type: String, attribute: 'entity-type' })
|
||||
public get entityType() {
|
||||
return this.#entityType;
|
||||
}
|
||||
public set entityType(entityType) {
|
||||
this.#entityType = entityType;
|
||||
|
||||
this.#blockTypeWorkspaceModalRegistration?.destroy();
|
||||
|
||||
if (entityType) {
|
||||
// TODO: Make specific modal token that requires data.
|
||||
this.#blockTypeWorkspaceModalRegistration = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(entityType)
|
||||
.onSetup(() => {
|
||||
return { data: { entityType: entityType, preset: {} }, modal: { size: 'large' } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
const newpath = routeBuilder({});
|
||||
this._workspacePath = newpath;
|
||||
});
|
||||
}
|
||||
}
|
||||
#entityType?: string;
|
||||
@property({ type: String })
|
||||
workspacePath?: string;
|
||||
|
||||
@state()
|
||||
private _items: Array<BlockType> = [];
|
||||
|
||||
@state()
|
||||
private _workspacePath?: string;
|
||||
|
||||
#blockTypeWorkspaceModalRegistration?: UmbModalRouteRegistrationController<
|
||||
typeof UMB_WORKSPACE_MODAL.DATA,
|
||||
typeof UMB_WORKSPACE_MODAL.VALUE
|
||||
>;
|
||||
#datasetContext?: UmbPropertyDatasetContext;
|
||||
#filter: Array<UmbBlockTypeBaseModel> = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => {
|
||||
this.#datasetContext = instance;
|
||||
this.observe(await this.#datasetContext?.propertyValueByAlias('blocks'), (value) => {
|
||||
this.#filter = value as Array<UmbBlockTypeBaseModel>;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
create() {
|
||||
@@ -74,23 +50,23 @@ export class UmbInputBlockTypeElement<
|
||||
// Only pick elements:
|
||||
docType.isElement &&
|
||||
// Prevent picking the an already used element type:
|
||||
this._items.find((x) => x.contentElementTypeKey === docType.unique) === undefined,
|
||||
this.#filter &&
|
||||
this.#filter.find((x) => x.contentElementTypeKey === docType.unique) === undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const modalValue = await modalContext?.onSubmit();
|
||||
const selectedElementType = modalValue.selection[0];
|
||||
|
||||
if (selectedElementType) {
|
||||
this.#blockTypeWorkspaceModalRegistration?.open({}, 'create/' + selectedElementType);
|
||||
this.dispatchEvent(new CustomEvent('create', { detail: { contentElementTypeKey: selectedElementType } }));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// No need to fire a change event, as all changes are made directly to the property, via context api.
|
||||
}
|
||||
|
||||
deleteItem(contentElementTypeKey: string) {
|
||||
this._items = this._items.filter((x) => x.contentElementTypeKey !== contentElementTypeKey);
|
||||
this.value = this._items.filter((x) => x.contentElementTypeKey !== contentElementTypeKey);
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
}
|
||||
|
||||
@@ -99,12 +75,21 @@ export class UmbInputBlockTypeElement<
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this._items ? repeat(this._items, (item) => item.contentElementTypeKey, this.#renderItem) : ''}
|
||||
${this.#renderButton()}
|
||||
`;
|
||||
return html`<div>
|
||||
${repeat(this.value, (block) => block.contentElementTypeKey, this.#renderItem)} ${this.#renderButton()}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
#renderItem = (item: BlockType) => {
|
||||
return html`
|
||||
<umb-block-type-card
|
||||
.workspacePath=${this.workspacePath}
|
||||
.key=${item.contentElementTypeKey}
|
||||
@delete=${() => this.deleteItem(item.contentElementTypeKey)}>
|
||||
</umb-block-type-card>
|
||||
`;
|
||||
};
|
||||
|
||||
#renderButton() {
|
||||
return html`
|
||||
<uui-button id="add-button" look="placeholder" @click=${() => this.create()} label="open">
|
||||
@@ -114,19 +99,9 @@ export class UmbInputBlockTypeElement<
|
||||
`;
|
||||
}
|
||||
|
||||
#renderItem = (item: BlockType) => {
|
||||
return html`
|
||||
<umb-block-type-card
|
||||
.workspacePath=${this._workspacePath}
|
||||
.key=${item.contentElementTypeKey}
|
||||
@delete=${() => this.deleteItem(item.contentElementTypeKey)}>
|
||||
</umb-block-type-card>
|
||||
`;
|
||||
};
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
:host {
|
||||
div {
|
||||
display: grid;
|
||||
gap: var(--uui-size-space-3);
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
@@ -135,6 +110,7 @@ export class UmbInputBlockTypeElement<
|
||||
|
||||
#add-button {
|
||||
text-align: center;
|
||||
min-height: 150px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -142,6 +118,18 @@ export class UmbInputBlockTypeElement<
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
uui-input {
|
||||
border: none;
|
||||
margin: var(--uui-size-space-6) 0 var(--uui-size-space-4);
|
||||
}
|
||||
|
||||
uui-input:hover uui-button {
|
||||
opacity: 1;
|
||||
}
|
||||
uui-input uui-button {
|
||||
opacity: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { UmbBlockTypeBaseModel } from '../types.js';
|
||||
import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js';
|
||||
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
|
||||
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import type {
|
||||
UmbInvariantableWorkspaceContextInterface,
|
||||
UmbWorkspaceContextInterface} from '@umbraco-cms/backoffice/workspace';
|
||||
UmbWorkspaceContextInterface,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import {
|
||||
UmbEditableWorkspaceContextBase,
|
||||
UmbInvariantWorkspacePropertyDatasetContext,
|
||||
@@ -13,7 +14,7 @@ import type { UmbControllerHost, UmbControllerHostElement } from '@umbraco-cms/b
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { ManifestWorkspace, PropertyEditorConfigProperty } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel>
|
||||
export class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlockTypeWithGroupKey = UmbBlockTypeWithGroupKey>
|
||||
extends UmbEditableWorkspaceContextBase<BlockTypeData>
|
||||
implements UmbInvariantableWorkspaceContextInterface
|
||||
{
|
||||
@@ -57,9 +58,11 @@ export class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlockTypeBase
|
||||
});
|
||||
}
|
||||
|
||||
async create(contentElementTypeId: string) {
|
||||
async create(contentElementTypeId: string, groupKey?: string | null) {
|
||||
//Only set groupKey property if it exists
|
||||
const data: BlockTypeData = {
|
||||
contentElementTypeKey: contentElementTypeId,
|
||||
...(groupKey && { groupKey: groupKey }),
|
||||
} as BlockTypeData;
|
||||
|
||||
this.setIsNew(true);
|
||||
|
||||
@@ -6,9 +6,9 @@ import type { UmbRoute } from '@umbraco-cms/backoffice/router';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
|
||||
import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbApi} from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api';
|
||||
import type { ManifestWorkspace} from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@customElement('umb-block-type-workspace')
|
||||
@@ -39,11 +39,13 @@ export class UmbBlockTypeWorkspaceElement extends UmbLitElement {
|
||||
|
||||
this._routes = [
|
||||
{
|
||||
path: 'create/:elementTypeKey',
|
||||
// Would it make more sense to have groupKey before elementTypeKey?
|
||||
path: 'create/:elementTypeKey/:groupKey',
|
||||
component: this.#editorElement,
|
||||
setup: async (_component, info) => {
|
||||
const elementTypeKey = info.match.params.elementTypeKey;
|
||||
this.#workspaceContext!.create(elementTypeKey);
|
||||
const groupKey = info.match.params.groupKey === 'null' ? null : info.match.params.groupKey;
|
||||
this.#workspaceContext!.create(elementTypeKey, groupKey);
|
||||
|
||||
new UmbWorkspaceIsNewRedirectController(
|
||||
this,
|
||||
|
||||
@@ -45,7 +45,6 @@ export class UmbBlockWorkspaceContext<
|
||||
readonly name = this.#label.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHost, workspaceArgs: { manifest: ManifestWorkspace }) {
|
||||
// TODO: We don't need a repo here, so maybe we should not require this of the UmbEditableWorkspaceContextBase
|
||||
super(host, workspaceArgs.manifest.alias);
|
||||
this.#entityType = workspaceArgs.manifest.meta?.entityType;
|
||||
this.workspaceAlias = workspaceArgs.manifest.alias;
|
||||
|
||||
@@ -42,6 +42,7 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
|
||||
const { data } = await this.#repo.list(0, 1000);
|
||||
this.#dictionaryItems = data?.items ?? [];
|
||||
|
||||
this.#setTableColumns();
|
||||
this.#setTableItems();
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ import type {
|
||||
PropertyTypeContainerModelBaseModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbRoute , UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
|
||||
import type { UmbRoute, UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
|
||||
import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type { UmbConfirmModalData } from '@umbraco-cms/backoffice/modal';
|
||||
import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import type { UmbSorterConfig} from '@umbraco-cms/backoffice/sorter';
|
||||
import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter';
|
||||
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
|
||||
const SORTER_CONFIG: UmbSorterConfig<PropertyTypeContainerModelBaseModel> = {
|
||||
@@ -216,7 +216,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement extends UmbLitElement imple
|
||||
if (!tabId) return;
|
||||
this._workspaceContext?.structure.removeContainer(null, tabId);
|
||||
this._tabsStructureHelper?.isOwnerContainer(tabId)
|
||||
? window.history.replaceState(null, '', this._routerPath + this._routes[0]?.path ?? '/root')
|
||||
? window.history.replaceState(null, '', this._routerPath + (this._routes[0]?.path ?? '/root'))
|
||||
: '';
|
||||
}
|
||||
async #addTab() {
|
||||
|
||||
@@ -11,12 +11,12 @@ import type {
|
||||
PropertyTypeContainerModelBaseModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbRoute , UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
|
||||
import type { UmbRoute, UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
|
||||
import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import type { UmbConfirmModalData } from '@umbraco-cms/backoffice/modal';
|
||||
import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import type { UmbSorterConfig} from '@umbraco-cms/backoffice/sorter';
|
||||
import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter';
|
||||
import { UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
|
||||
const SORTER_CONFIG: UmbSorterConfig<PropertyTypeContainerModelBaseModel> = {
|
||||
@@ -216,7 +216,7 @@ export class UmbMediaTypeWorkspaceViewEditElement extends UmbLitElement implemen
|
||||
if (!tabId) return;
|
||||
this._workspaceContext?.structure.removeContainer(null, tabId);
|
||||
this._tabsStructureHelper?.isOwnerContainer(tabId)
|
||||
? window.history.replaceState(null, '', this._routerPath + this._routes[0]?.path ?? '/root')
|
||||
? window.history.replaceState(null, '', this._routerPath + (this._routes[0]?.path ?? '/root'))
|
||||
: '';
|
||||
}
|
||||
async #addTab() {
|
||||
|
||||
Reference in New Issue
Block a user