Block Editor Custom View specific conditionals

This commit is contained in:
Niels Lyngsø
2024-07-01 09:46:42 +02:00
parent c7310c358a
commit 3c1a9eef0d
8 changed files with 108 additions and 56 deletions

View File

@@ -2,12 +2,13 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit';
import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit';
import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils';
import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js';
import type { UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid';
import { UMB_BLOCK_GRID, type UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid';
import '../block-grid-block-inline/index.js';
import '../block-grid-block/index.js';
import '../block-scale-handler/index.js';
/**
* @element umb-block-grid-entry
*/
@@ -84,7 +85,6 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
@state()
_inlineCreateAboveWidth?: string;
// TODO: use this type on the Element Interface for the Manifest.
@state()
_blockViewProps: UmbBlockEditorCustomViewProperties<UmbBlockGridLayoutModel> = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render.
@@ -99,55 +99,55 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
// Misc:
this.observe(this.#context.showContentEdit, (show) => {
this._showContentEdit = show;
});
}, null);
this.observe(this.#context.settingsElementTypeKey, (key) => {
this._hasSettings = !!key;
});
}, null);
this.observe(this.#context.canScale, (canScale) => {
this._canScale = canScale;
});
}, null);
this.observe(this.#context.label, (label) => {
this.#updateBlockViewProps({ label });
this._label = label;
});
}, null);
this.observe(this.#context.contentElementTypeIcon, (icon) => {
this.#updateBlockViewProps({ icon });
this._icon = icon;
});
}, null);
this.observe(this.#context.inlineEditingMode, (mode) => {
this._inlineEditingMode = mode;
});
}, null);
// Data:
this.observe(this.#context.layout, (layout) => {
this.#updateBlockViewProps({ layout });
});
}, null);
this.observe(this.#context.content, (content) => {
this.#updateBlockViewProps({ content });
});
}, null);
this.observe(this.#context.settings, (settings) => {
this.#updateBlockViewProps({ settings });
});
}, null);
// Paths:
this.observe(this.#context.createBeforePath, (createPath) => {
//const oldValue = this._createBeforePath;
this._createBeforePath = createPath;
//this.requestUpdate('_createPath', oldValue);
});
}, null);
this.observe(this.#context.createAfterPath, (createPath) => {
//const oldValue = this._createAfterPath;
this._createAfterPath = createPath;
//this.requestUpdate('_createPath', oldValue);
});
}, null);
this.observe(this.#context.workspaceEditContentPath, (path) => {
this._workspaceEditContentPath = path;
this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editContent: path } });
});
}, null);
this.observe(this.#context.workspaceEditSettingsPath, (path) => {
this._workspaceEditSettingsPath = path;
this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editSettings: path } });
});
}, null);
}
override connectedCallback(): void {
@@ -175,13 +175,13 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
if (contentElementTypeKey) {
this.setAttribute('data-content-element-type-key', contentElementTypeKey);
}
});
}, 'contentElementTypeKey');
this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => {
if (contentElementTypeAlias) {
this._contentTypeAlias = contentElementTypeAlias;
this.setAttribute('data-content-element-type-alias', contentElementTypeAlias);
}
});
}, 'contentElementTypeAlias');
this.#callUpdateInlineCreateButtons();
}
@@ -228,6 +228,16 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
}
};
#extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => {
if(manifest.forContentTypeAlias && !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!)) {
return false;
}
if(manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_GRID)) {
return false;
}
return true;
}
#renderInlineEditBlock() {
return html`<umb-block-grid-block-inline
.contentUdi=${this.contentUdi}
@@ -238,13 +248,6 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
return html`<umb-block-grid-block .contentUdi=${this.contentUdi} .label=${this._label}></umb-block-grid-block>`;
}
#extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => {
if(manifest.forContentTypeAlias?.indexOf(this._contentTypeAlias!) === -1) {
return false;
}
return true;
}
#renderBlock() {
return this.contentUdi && this._contentTypeAlias
? html`

View File

@@ -2,6 +2,7 @@ import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/ba
import type { UmbBlockTypeWithGroupKey } from '@umbraco-cms/backoffice/block-type';
export const UMB_BLOCK_GRID_TYPE = 'block-grid-type';
export const UMB_BLOCK_GRID = 'block-grid';
// Configuration models:
export interface UmbBlockGridTypeModel extends UmbBlockTypeWithGroupKey {

View File

@@ -1,11 +1,11 @@
import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
import '../ref-list-block/index.js';
import '../inline-list-block/index.js';
import type { UmbBlockViewPropsType } from '@umbraco-cms/backoffice/block';
import type { UmbBlockListLayoutModel } from '@umbraco-cms/backoffice/block-list';
import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils';
import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js';
import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js';
/**
* @element umb-block-list-entry
@@ -34,6 +34,9 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
#context = new UmbBlockListEntryContext(this);
@state()
_contentTypeAlias?:string;
@state()
_showContentEdit = false;
@state()
@@ -54,52 +57,79 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
@state()
_inlineEditingMode?: boolean;
// TODO: use this type on the Element Interface for the Manifest.
@state()
_blockViewProps: UmbBlockViewPropsType<UmbBlockListLayoutModel> = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render.
_blockViewProps: UmbBlockEditorCustomViewProperties<UmbBlockListLayoutModel> = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render.
#updateBlockViewProps(incoming: Partial<UmbBlockEditorCustomViewProperties<UmbBlockListLayoutModel>>) {
this._blockViewProps = { ...this._blockViewProps, ...incoming };
this.requestUpdate('_blockViewProps');
}
constructor() {
super();
this.observe(this.#context.showContentEdit, (showContentEdit) => {
this._showContentEdit = showContentEdit;
});
}, null);
this.observe(this.#context.settingsElementTypeKey, (settingsElementTypeKey) => {
this._hasSettings = !!settingsElementTypeKey;
});
}, null);
this.observe(this.#context.label, (label) => {
this.#updateBlockViewProps({ label });
this._label = label;
this._blockViewProps.label = label;
this.requestUpdate('_blockViewProps');
});
}, null);
this.observe(this.#context.contentElementTypeIcon, (icon) => {
this.#updateBlockViewProps({ icon });
this._icon = icon;
this._blockViewProps.icon = icon;
this.requestUpdate('_blockViewProps');
});
}, null);
this.observe(this.#context.inlineEditingMode, (inlineEditingMode) => {
this._inlineEditingMode = inlineEditingMode;
});
}, null);
// Data props:
this.observe(this.#context.layout, (layout) => {
this._blockViewProps.layout = layout;
});
this.#updateBlockViewProps({ layout });
}, null);
this.observe(this.#context.content, (content) => {
this._blockViewProps.content = content;
});
this.#updateBlockViewProps({ content });
}, null);
this.observe(this.#context.settings, (settings) => {
this._blockViewProps.settings = settings;
});
this.#updateBlockViewProps({ settings });
}, null);
this.observe(this.#context.workspaceEditContentPath, (path) => {
this._workspaceEditContentPath = path;
this._blockViewProps.urls.editContent = path;
this.requestUpdate('_blockViewProps');
});
this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editContent: path } });
}, null);
this.observe(this.#context.workspaceEditSettingsPath, (path) => {
this._workspaceEditSettingsPath = path;
this._blockViewProps.urls.editSettings = path;
this.requestUpdate('_blockViewProps');
});
this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editSettings: path } });
}, null);
}
override connectedCallback(): void {
super.connectedCallback();
// element styling:
this.observe(this.#context.contentElementTypeKey, (contentElementTypeKey) => {
if (contentElementTypeKey) {
this.setAttribute('data-content-element-type-key', contentElementTypeKey);
}
}, 'contentElementTypeKey');
this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => {
if (contentElementTypeAlias) {
this._contentTypeAlias = contentElementTypeAlias;
this.setAttribute('data-content-element-type-alias', contentElementTypeAlias);
}
}, 'contentElementTypeAlias');
}
#extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => {
if(manifest.forContentTypeAlias && !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!)) {
return false;
}
if(manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_LIST)) {
return false;
}
return true;
}
#renderRefBlock() {
@@ -116,6 +146,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
type="blockEditorCustomView"
default-element=${this._inlineEditingMode ? 'umb-inline-list-block' : 'umb-ref-list-block'}
.props=${this._blockViewProps}
.filter=${this.#extensionSlotFilterMethod}
>${this._inlineEditingMode ? this.#renderInlineBlock() : this.#renderRefBlock()}</umb-extension-slot
>
<uui-action-bar>

View File

@@ -2,6 +2,7 @@ import type { UmbBlockTypeBaseModel } from '../block-type/index.js';
import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block';
export const UMB_BLOCK_LIST_TYPE = 'block-list-type';
export const UMB_BLOCK_LIST = 'block-list';
export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {}
export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {}

View File

@@ -5,6 +5,6 @@ export const manifest:ManifestBlockEditorCustomView = {
alias: 'Umb.blockEditorCustomView.TestView',
name: 'Block Editor Custom View Test',
element: () => import('./custom-view.element.js'),
//forContentTypeAlias: []
//forBlockType?: Array<string>;
forContentTypeAlias: 'elementTypeHeadline',
forBlockEditor: 'block-grid'
}

View File

@@ -3,6 +3,18 @@ import type { UmbBlockEditorCustomViewElement } from '../interfaces/index.js';
export interface ManifestBlockEditorCustomView extends ManifestElement<UmbBlockEditorCustomViewElement> {
type: 'blockEditorCustomView';
forContentTypeAlias?: Array<string>;
forBlockType?: Array<string>;
/**
* @property {string | Array<string> } - Declare if this Custom View only must appear at specific Content Types by Alias.
* @description Optional condition if you like this custom view to only appear at for one or more specific Content Types.
* @example 'my-element-type-alias'
* @example ['my-element-type-alias-A', 'my-element-type-alias-B']
*/
forContentTypeAlias?: string | Array<string>;
/**
* @property {string | Array<string> } - Declare if this Custom View only must appear at specific Block Editors.
* @description Optional condition if you like this custom view to only appear at a specific type of Block Editor.
* @example 'block-list'
* @example ['block-list', 'block-grid']
*/
forBlockEditor?: string | Array<string>;
}

View File

@@ -19,5 +19,6 @@ export * from './string/from-camel-case.function.js';
export * from './string/generate-umbraco-alias.function.js';
export * from './string/increment-string.function.js';
export * from './string/split-string-to-array.js';
export * from './string/string-or-string-array-contains.function.js';
export * from './string/to-camel-case/to-camel-case.function.js';
export type * from './type/index.js';

View File

@@ -0,0 +1,3 @@
export function stringOrStringArrayContains(value: string | Array<string>, search: string) {
return Array.isArray(value) ? value.indexOf(search) !== -1 : value === search;
}