multiple fixes in one commit
This commit is contained in:
@@ -60,6 +60,9 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
|
||||
@state()
|
||||
_label = '';
|
||||
|
||||
@state()
|
||||
_icon?: string;
|
||||
|
||||
@state()
|
||||
_workspaceEditContentPath?: string;
|
||||
|
||||
@@ -105,6 +108,10 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper
|
||||
this.#updateBlockViewProps({ label });
|
||||
this._label = label;
|
||||
});
|
||||
this.observe(this.#context.contentElementTypeIcon, (icon) => {
|
||||
this.#updateBlockViewProps({ icon });
|
||||
this._icon = icon;
|
||||
});
|
||||
this.observe(this.#context.inlineEditingMode, (mode) => {
|
||||
this._inlineEditingMode = mode;
|
||||
});
|
||||
|
||||
@@ -42,6 +42,9 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
|
||||
@state()
|
||||
_label = '';
|
||||
|
||||
@state()
|
||||
_icon?: string;
|
||||
|
||||
@state()
|
||||
_workspaceEditContentPath?: string;
|
||||
|
||||
@@ -65,10 +68,14 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
|
||||
this._hasSettings = !!settingsElementTypeKey;
|
||||
});
|
||||
this.observe(this.#context.label, (label) => {
|
||||
const oldValue = this._label;
|
||||
this._blockViewProps.label = label;
|
||||
this._label = label;
|
||||
this.requestUpdate('label', oldValue);
|
||||
this._blockViewProps.label = label;
|
||||
this.requestUpdate('_blockViewProps');
|
||||
});
|
||||
this.observe(this.#context.contentElementTypeIcon, (icon) => {
|
||||
this._icon = icon;
|
||||
this._blockViewProps.icon = icon;
|
||||
this.requestUpdate('_blockViewProps');
|
||||
});
|
||||
this.observe(this.#context.inlineEditingMode, (inlineEditingMode) => {
|
||||
this._inlineEditingMode = inlineEditingMode;
|
||||
@@ -115,12 +122,12 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper
|
||||
${this._showContentEdit && this._workspaceEditContentPath
|
||||
? html`<uui-button label="edit" compact href=${this._workspaceEditContentPath}>
|
||||
<uui-icon name="icon-edit"></uui-icon>
|
||||
</uui-button>`
|
||||
</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-button>`
|
||||
: ''}
|
||||
<uui-button label="delete" compact @click=${() => this.#context.requestDelete()}>
|
||||
<uui-icon name="icon-remove"></uui-icon>
|
||||
|
||||
@@ -11,7 +11,7 @@ export class UmbBlockRteEntryInlineElement extends UmbBlockRteEntryElement {
|
||||
...UmbBlockRteEntryElement.styles,
|
||||
css`
|
||||
:host {
|
||||
display: inline;
|
||||
display: inline-block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js';
|
||||
import type { UmbBlockRteLayoutModel } from '../../types.js';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import '../ref-rte-block/index.js';
|
||||
import type { UmbBlockViewPropsType } from '@umbraco-cms/backoffice/block';
|
||||
import type { UmbBlockListLayoutModel } from '@umbraco-cms/backoffice/block-list';
|
||||
|
||||
/**
|
||||
* @element umb-rte-block
|
||||
@@ -34,6 +34,9 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
|
||||
@state()
|
||||
_label = '';
|
||||
|
||||
@state()
|
||||
_icon?: string;
|
||||
|
||||
@state()
|
||||
_workspaceEditContentPath?: string;
|
||||
|
||||
@@ -42,7 +45,7 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
|
||||
|
||||
// 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: UmbBlockViewPropsType<UmbBlockRteLayoutModel> = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render.
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -57,10 +60,14 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
|
||||
this._hasSettings = !!settingsElementTypeKey;
|
||||
});
|
||||
this.observe(this.#context.label, (label) => {
|
||||
const oldValue = this._label;
|
||||
this._blockViewProps.label = label;
|
||||
this._label = label;
|
||||
this.requestUpdate('label', oldValue);
|
||||
this._blockViewProps.label = label;
|
||||
this.requestUpdate('_blockViewProps');
|
||||
});
|
||||
this.observe(this.#context.contentElementTypeIcon, (icon) => {
|
||||
this._icon = icon;
|
||||
this._blockViewProps.icon = icon;
|
||||
this.requestUpdate('_blockViewProps');
|
||||
});
|
||||
// Data props:
|
||||
this.observe(this.#context.layout, (layout) => {
|
||||
@@ -84,8 +91,17 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
// eslint-disable-next-line wc/no-self-class
|
||||
this.classList.add('uui-font');
|
||||
// eslint-disable-next-line wc/no-self-class
|
||||
this.classList.add('uui-text');
|
||||
}
|
||||
|
||||
#renderRefBlock() {
|
||||
return html`<umb-ref-rte-block .label=${this._label}></umb-ref-rte-block>`;
|
||||
return html`<umb-ref-rte-block .label=${this._label} .icon=${this._icon}></umb-ref-rte-block>`;
|
||||
}
|
||||
|
||||
#renderBlock() {
|
||||
@@ -123,6 +139,8 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
|
||||
:host {
|
||||
position: relative;
|
||||
display: block;
|
||||
user-select: none;
|
||||
user-drag: auto;
|
||||
}
|
||||
uui-action-bar {
|
||||
position: absolute;
|
||||
|
||||
@@ -11,6 +11,9 @@ export class UmbRefRteBlockElement extends UmbLitElement {
|
||||
@property({ type: String })
|
||||
label?: string;
|
||||
|
||||
@property({ type: String })
|
||||
icon?: string;
|
||||
|
||||
@state()
|
||||
_workspaceEditPath?: string;
|
||||
|
||||
@@ -29,10 +32,9 @@ export class UmbRefRteBlockElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<uui-ref-node
|
||||
standalone
|
||||
.name=${this.label ?? ''}
|
||||
href=${this._workspaceEditPath ?? '#'}></uui-ref-node>`;
|
||||
return html`<uui-ref-node standalone .name=${this.label ?? ''} href=${this._workspaceEditPath ?? '#'}
|
||||
><uui-icon slot="icon" .name=${this.icon ?? null}></uui-icon
|
||||
></uui-ref-node>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
|
||||
@@ -19,7 +19,7 @@ export class UmbBlockRteEntryContext extends UmbBlockEntryContext<
|
||||
(x) => !!x?.forceHideContentEditorInOverlay,
|
||||
);
|
||||
|
||||
readonly showContentEdit = this.forceHideContentEditorInOverlay;
|
||||
readonly showContentEdit = this._blockType.asObservablePart((x) => !x?.forceHideContentEditorInOverlay);
|
||||
|
||||
constructor(host: UmbControllerHost) {
|
||||
super(host, UMB_BLOCK_RTE_MANAGER_CONTEXT, UMB_BLOCK_RTE_ENTRIES_CONTEXT);
|
||||
|
||||
@@ -24,7 +24,19 @@ export class UmbBlockRteManagerContext<
|
||||
partialLayoutEntry?: Omit<BlockLayoutType, 'contentUdi'>,
|
||||
modalData?: UmbBlockRteWorkspaceData,
|
||||
) {
|
||||
return super.createBlockData(contentElementTypeKey, partialLayoutEntry);
|
||||
const data = super.createBlockData(contentElementTypeKey, partialLayoutEntry);
|
||||
|
||||
// Find block type.
|
||||
const blockType = this.getBlockTypes().find((x) => x.contentElementTypeKey === contentElementTypeKey);
|
||||
if (!blockType) {
|
||||
throw new Error(`Cannot create block, missing block type for ${contentElementTypeKey}`);
|
||||
}
|
||||
|
||||
if (blockType.displayInline) {
|
||||
data.layout.displayInline = true;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
insert(
|
||||
@@ -35,6 +47,10 @@ export class UmbBlockRteManagerContext<
|
||||
) {
|
||||
if (!this.#editor) return false;
|
||||
|
||||
this._layouts.appendOne(layoutEntry);
|
||||
|
||||
this.insertBlockData(layoutEntry, content, settings, modalData);
|
||||
|
||||
if (layoutEntry.displayInline) {
|
||||
this.#editor.selection.setContent(
|
||||
`<umb-rte-block-inline data-content-udi="${layoutEntry.contentUdi}"><!--Umbraco-Block--></umb-rte-block-inline>`,
|
||||
@@ -45,9 +61,7 @@ export class UmbBlockRteManagerContext<
|
||||
);
|
||||
}
|
||||
|
||||
this._layouts.appendOne(layoutEntry);
|
||||
|
||||
this.insertBlockData(layoutEntry, content, settings, modalData);
|
||||
this.#editor.fire('change');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,10 +67,11 @@ export abstract class UmbBlockEntryContext<
|
||||
#createAfterPath = new UmbStringState(undefined);
|
||||
readonly createAfterPath = this.#createAfterPath.asObservable();
|
||||
|
||||
#contentElementTypeName = new UmbStringState(undefined);
|
||||
public readonly contentElementTypeName = this.#contentElementTypeName.asObservable();
|
||||
#contentElementTypeAlias = new UmbStringState(undefined);
|
||||
public readonly contentElementTypeAlias = this.#contentElementTypeAlias.asObservable();
|
||||
#contentElementType = new UmbObjectState<UmbContentTypeModel | undefined>(undefined);
|
||||
public readonly contentElementType = this.#contentElementType.asObservable();
|
||||
public readonly contentElementTypeName = this.#contentElementType.asObservablePart((x) => x?.name);
|
||||
public readonly contentElementTypeAlias = this.#contentElementType.asObservablePart((x) => x?.alias);
|
||||
public readonly contentElementTypeIcon = this.#contentElementType.asObservablePart((x) => x?.icon);
|
||||
|
||||
_blockType = new UmbObjectState<BlockType | undefined>(undefined);
|
||||
public readonly blockType = this._blockType.asObservable();
|
||||
@@ -301,8 +302,9 @@ export abstract class UmbBlockEntryContext<
|
||||
this.observe(
|
||||
this._manager.contentTypeOf(contentTypeKey),
|
||||
(contentType) => {
|
||||
this.#contentElementTypeAlias.setValue(contentType?.alias);
|
||||
this.#contentElementTypeName.setValue(contentType?.name);
|
||||
//this.#contentElementTypeAlias.setValue(contentType?.alias);
|
||||
//this.#contentElementTypeName.setValue(contentType?.name);
|
||||
this.#contentElementType.setValue(contentType);
|
||||
this._gotContentType(contentType);
|
||||
},
|
||||
'observeContentElementType',
|
||||
|
||||
@@ -22,6 +22,7 @@ export interface UmbBlockViewUrlsPropType {
|
||||
|
||||
export interface UmbBlockViewPropsType<BlockLayoutType extends UmbBlockLayoutBaseModel> {
|
||||
label?: string;
|
||||
icon?: string;
|
||||
contentUdi: string;
|
||||
layout?: BlockLayoutType;
|
||||
content?: UmbBlockDataType;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UMB_CONTENT_REQUEST_EVENT_TYPE, type UmbContextRequestEvent } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { RawEditorOptions } from '@umbraco-cms/backoffice/external/tinymce';
|
||||
import { UUIIconRequestEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
|
||||
//export const UMB_BLOCK_ENTRY_WEB_COMPONENTS_ABSOLUTE_PATH = '/umbraco/backoffice/packages/block/block-rte/index.js';
|
||||
export const UMB_BLOCK_ENTRY_WEB_COMPONENTS_ABSOLUTE_PATH = '@umbraco-cms/backoffice/block-rte';
|
||||
@@ -13,6 +14,7 @@ export const defaultFallbackConfig: RawEditorOptions = {
|
||||
invalid_elements: 'font',
|
||||
extended_valid_elements:
|
||||
'@[id|class|style],umb-rte-block[!data-content-udi],-umb-rte-block-inline[!data-content-udi],-div[id|dir|class|align|style],ins[datetime|cite],-ul[class|style],-li[class|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align],span[id|class|style|lang],figure,figcaption',
|
||||
custom_elements: 'umb-rte-block[!data-content-udi],~umb-rte-block-inline[!data-content-udi]',
|
||||
toolbar: [
|
||||
'styles',
|
||||
'bold',
|
||||
@@ -30,7 +32,7 @@ export const defaultFallbackConfig: RawEditorOptions = {
|
||||
],
|
||||
|
||||
init_instance_callback: function (editor) {
|
||||
// The following code is the context api proxy.
|
||||
// The following code is the context api proxy. [NL]
|
||||
// It re-dispatches the context api request event to the origin target of this modal, in other words the element that initiated the modal. [NL]
|
||||
editor.dom.doc.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, ((event: UmbContextRequestEvent) => {
|
||||
if (!editor.iframeElement) return;
|
||||
@@ -39,6 +41,19 @@ export const defaultFallbackConfig: RawEditorOptions = {
|
||||
editor.iframeElement.dispatchEvent(event.clone());
|
||||
}) as EventListener);
|
||||
|
||||
// Proxy for retrieving icons from outside the iframe [NL]
|
||||
editor.dom.doc.addEventListener(UUIIconRequestEvent.ICON_REQUEST, ((event: UUIIconRequestEvent) => {
|
||||
if (!editor.iframeElement) return;
|
||||
|
||||
const newEvent = new UUIIconRequestEvent(UUIIconRequestEvent.ICON_REQUEST, {
|
||||
detail: event.detail,
|
||||
});
|
||||
editor.iframeElement.dispatchEvent(newEvent);
|
||||
if (newEvent.icon !== null) {
|
||||
event.acceptRequest(newEvent.icon);
|
||||
}
|
||||
}) as EventListener);
|
||||
|
||||
// Transfer our import-map to the iframe: [NL]
|
||||
const importMapTag = document.head.querySelector('script[type="importmap"]');
|
||||
if (importMapTag) {
|
||||
@@ -48,8 +63,17 @@ export const defaultFallbackConfig: RawEditorOptions = {
|
||||
editor.dom.doc.head.appendChild(importMap);
|
||||
}
|
||||
|
||||
// Transfer our stylesheets to the iframe: [NL]
|
||||
const stylesheetTags = document.head.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]');
|
||||
stylesheetTags.forEach((stylesheetTag) => {
|
||||
const stylesheet = document.createElement('link');
|
||||
stylesheet.rel = 'stylesheet';
|
||||
stylesheet.href = stylesheetTag.href;
|
||||
editor.dom.doc.head.appendChild(stylesheet);
|
||||
});
|
||||
|
||||
// TODO: Lets use/adapt the router-slot logic so we do not need to add this here [NL]
|
||||
// TODO: When transfering this code, make sure that we check for target='_parent' or target='top' if its happening within a iframe. [NL]
|
||||
// TODO: When transferring this code, make sure that we check for target='_parent' or target='top' if its happening within a iframe. [NL]
|
||||
editor.dom.doc.addEventListener('click', (e: MouseEvent) => {
|
||||
// If we try to open link in a new tab, then we want to skip skip:
|
||||
//if ((isWindows && e.ctrlKey) || (!isWindows && e.metaKey)) return;
|
||||
@@ -92,17 +116,14 @@ export const defaultFallbackConfig: RawEditorOptions = {
|
||||
window.history.pushState(null, '', path);
|
||||
});
|
||||
|
||||
function appendScript(path: string) {
|
||||
const script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.setAttribute('type', 'module');
|
||||
script.text = `import "${path}";`;
|
||||
editor.dom.doc.head.appendChild(script);
|
||||
}
|
||||
|
||||
// Load the umb-rte-block component inside the iframe [NL]
|
||||
appendScript('@umbraco-cms/backoffice/extension-registry');
|
||||
appendScript(UMB_BLOCK_ENTRY_WEB_COMPONENTS_ABSOLUTE_PATH);
|
||||
// Load backoffice JS so we can get the umb-rte-block component registered inside the iframe [NL]
|
||||
const script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.setAttribute('type', 'module');
|
||||
// TODO: Check that we actually get the same extension registry, or find a way so we can make it do so. — It could be some kind of iframe detection? [NL]
|
||||
script.text = `import "@umbraco-cms/backoffice/extension-registry";`;
|
||||
script.text = `import "${UMB_BLOCK_ENTRY_WEB_COMPONENTS_ABSOLUTE_PATH}";`;
|
||||
editor.dom.doc.head.appendChild(script);
|
||||
},
|
||||
|
||||
style_formats: [
|
||||
|
||||
Reference in New Issue
Block a user