implement expose button for rte block

This commit is contained in:
Niels Lyngsø
2024-10-16 12:03:35 +02:00
parent 0bb54c6af6
commit 5493c0a2a1

View File

@@ -1,7 +1,7 @@
import { UMB_BLOCK_RTE, type UmbBlockRteLayoutModel } from '../../types.js';
import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit';
import { html, css, property, state, customElement, nothing } from '@umbraco-cms/backoffice/external/lit';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type {
@@ -11,6 +11,8 @@ import type {
import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils';
import '../ref-rte-block/index.js';
import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation';
import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block';
/**
* @class UmbBlockRteEntryElement
@@ -26,6 +28,16 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
if (!value) return;
this._contentKey = value;
this.#context.setContentKey(value);
new UmbObserveValidationStateController(
this,
`$.contentData[${UmbDataPathBlockElementDataQuery({ key: value })}]`,
(hasMessages) => {
this._contentInvalid = hasMessages;
this._blockViewProps.contentInvalid = hasMessages;
},
'observeMessagesForContent',
);
}
private _contentKey?: string | undefined;
@@ -55,12 +67,23 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
@state()
_contentElementTypeAlias?: string;
@state()
_contentTypeName?: string;
@state()
_blockViewProps: UmbBlockEditorCustomViewProperties<UmbBlockRteLayoutModel> = {
contentKey: undefined!,
config: { showContentEdit: false, showSettingsEdit: false },
}; // Set to undefined cause it will be set before we render.
// 'content-invalid' attribute is used for styling purpose.
@property({ type: Boolean, attribute: 'content-invalid', reflect: true })
_contentInvalid?: boolean;
// 'settings-invalid' attribute is used for styling purpose.
@property({ type: Boolean, attribute: 'settings-invalid', reflect: true })
_settingsInvalid?: boolean;
#updateBlockViewProps(incoming: Partial<UmbBlockEditorCustomViewProperties<UmbBlockRteLayoutModel>>) {
this._blockViewProps = { ...this._blockViewProps, ...incoming };
this.requestUpdate('_blockViewProps');
@@ -72,17 +95,36 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
// We do not have index for RTE Blocks at the moment.
this.#context.setIndex(0);
this.observe(this.#context.showContentEdit, (showContentEdit) => {
this._showContentEdit = showContentEdit;
this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showContentEdit } });
});
this.observe(this.#context.settingsElementTypeKey, (key) => {
this._hasSettings = !!key;
this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showSettingsEdit: !!key } });
});
this.observe(this.#context.contentElementTypeAlias, (alias) => {
this._contentElementTypeAlias = alias;
});
this.observe(
this.#context.showContentEdit,
(showContentEdit) => {
this._showContentEdit = showContentEdit;
this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showContentEdit } });
},
null,
);
this.observe(
this.#context.settingsElementTypeKey,
(key) => {
this._hasSettings = !!key;
this.#updateBlockViewProps({ config: { ...this._blockViewProps.config!, showSettingsEdit: !!key } });
},
null,
);
this.observe(
this.#context.contentElementTypeAlias,
(alias) => {
this._contentElementTypeAlias = alias;
},
null,
);
this.observe(
this.#context.contentElementTypeName,
(contentElementTypeName) => {
this._contentTypeName = contentElementTypeName;
},
null,
);
this.observe(
this.#context.blockType,
(blockType) => {
@@ -126,8 +168,6 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
this.#observeData();
// TODO: Implement validation for RTE Blocks: [NL]
/*
this.observe(
this.#context.settingsKey,
(settingsKey) => {
@@ -147,7 +187,7 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
},
null,
);
*/
this.observe(
this.#context.workspaceEditContentPath,
(path) => {
@@ -188,15 +228,6 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
this.setAttribute('contenteditable', 'false');
}
#renderRefBlock() {
return html`<umb-ref-rte-block
.label=${this._label}
.icon=${this._icon}
.unpublished=${!this._exposed}
.content=${this._blockViewProps.content}
.settings=${this._blockViewProps.settings}></umb-ref-rte-block>`;
}
readonly #filterBlockCustomViews = (manifest: ManifestBlockEditorCustomView) => {
const elementTypeAlias = this._contentElementTypeAlias ?? '';
const isForBlockEditor =
@@ -206,6 +237,10 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
return isForBlockEditor && isForContentTypeAlias;
};
#expose = () => {
this.#context.expose();
};
#renderBlock() {
return html`
<div class="uui-text uui-font">
@@ -217,22 +252,62 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
single>
${this.#renderRefBlock()}
</umb-extension-slot>
<uui-action-bar>
${this._showContentEdit && this._workspaceEditContentPath
? html`<uui-button label="edit" compact href=${this._workspaceEditContentPath}>
<uui-icon name="icon-edit"></uui-icon>
</uui-button>`
: ''}
${this._hasSettings && this._workspaceEditSettingsPath
? html`<uui-button label="Edit settings" compact href=${this._workspaceEditSettingsPath}>
<uui-icon name="icon-settings"></uui-icon>
</uui-button>`
: ''}
</uui-action-bar>
<uui-action-bar> ${this.#renderEditAction()} ${this.#renderEditSettingsAction()} </uui-action-bar>
${!this._showContentEdit && this._contentInvalid
? html`<uui-badge attention color="danger" label="Invalid content">!</uui-badge>`
: nothing}
</div>
`;
}
#renderRefBlock() {
return html`<umb-ref-rte-block
.label=${this._label}
.icon=${this._icon}
.unpublished=${!this._exposed}
.content=${this._blockViewProps.content}
.settings=${this._blockViewProps.settings}></umb-ref-rte-block>`;
}
#renderEditAction() {
return this._showContentEdit && this._workspaceEditContentPath
? html`<uui-button
label="edit"
look="secondary"
color=${this._contentInvalid ? 'danger' : ''}
href=${this._workspaceEditContentPath}>
<uui-icon name="icon-edit"></uui-icon>
${this._contentInvalid
? html`<uui-badge attention color="danger" label="Invalid content">!</uui-badge>`
: nothing}
</uui-button>`
: this._showContentEdit === false && this._exposed === false
? html`<uui-button
@click=${this.#expose}
label=${this.localize.term('blockEditor_createThisFor', this._contentTypeName)}
look="secondary"
><uui-icon name="icon-add"></uui-icon
></uui-button>`
: nothing;
}
#renderEditSettingsAction() {
return html`
${this._hasSettings && this._workspaceEditSettingsPath
? html`<uui-button
label="Edit settings"
look="secondary"
color=${this._settingsInvalid ? 'danger' : ''}
href=${this._workspaceEditSettingsPath}>
<uui-icon name="icon-settings"></uui-icon>
${this._settingsInvalid
? html`<uui-badge attention color="danger" label="Invalid settings">!</uui-badge>`
: nothing}
</uui-button>`
: nothing}
`;
}
override render() {
return this.#renderBlock();
}