Hotfix: unnecessary Discard Changes dialog for RTEs (#17692)
* remove code duplication * remove unused code * allow value to be undefined * dot not build model if we have no markup * do update the layout value if we don't get any layouts * reset internals if there are no value * clear value if tiny mce doesn't have any markup * clear value if tip tap doesn't have any markup * add method to check if tip tap element is empty * use method to check for empty tip tap
This commit is contained in:
@@ -10,9 +10,11 @@ import type {
|
||||
import {
|
||||
UmbBlockRteEntriesContext,
|
||||
UmbBlockRteManagerContext,
|
||||
type UmbBlockRteLayoutModel,
|
||||
type UmbBlockRteTypeModel,
|
||||
} from '@umbraco-cms/backoffice/block-rte';
|
||||
import { UMB_PROPERTY_CONTEXT, UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block';
|
||||
|
||||
// eslint-disable-next-line local-rules/enforce-element-suffix-on-element-class-name
|
||||
export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement implements UmbPropertyEditorUiElement {
|
||||
@@ -35,6 +37,16 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
|
||||
},
|
||||
})
|
||||
public set value(value: UmbPropertyEditorUiValueType | undefined) {
|
||||
if (!value) {
|
||||
this._value = undefined;
|
||||
this._markup = '';
|
||||
this.#managerContext.setLayouts([]);
|
||||
this.#managerContext.setContents([]);
|
||||
this.#managerContext.setSettings([]);
|
||||
this.#managerContext.setExposes([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const buildUpValue: Partial<UmbPropertyEditorUiValueType> = value ? { ...value } : {};
|
||||
buildUpValue.markup ??= '';
|
||||
buildUpValue.blocks ??= { layout: {}, contentData: [], settingsData: [], expose: [] };
|
||||
@@ -69,10 +81,7 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
|
||||
protected _config?: UmbPropertyEditorConfigCollection;
|
||||
|
||||
@state()
|
||||
protected _value: UmbPropertyEditorUiValueType = {
|
||||
markup: '',
|
||||
blocks: { layout: {}, contentData: [], settingsData: [], expose: [] },
|
||||
};
|
||||
protected _value?: UmbPropertyEditorUiValueType | undefined;
|
||||
|
||||
/**
|
||||
* Separate state for markup, to avoid re-rendering/re-setting the value of the Tiptap editor when the value does not really change.
|
||||
@@ -127,49 +136,30 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
|
||||
|
||||
// Observe the value of the property and update the editor value.
|
||||
this.observe(this.#managerContext.layouts, (layouts) => {
|
||||
this._value = {
|
||||
...this._value,
|
||||
blocks: { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } },
|
||||
};
|
||||
this._fireChangeEvent();
|
||||
const blocksValue =
|
||||
this._value && layouts?.length > 0
|
||||
? { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } }
|
||||
: undefined;
|
||||
|
||||
this.#setBlocksValue(blocksValue);
|
||||
});
|
||||
|
||||
this.observe(this.#managerContext.contents, (contents) => {
|
||||
this._value = { ...this._value, blocks: { ...this._value.blocks, contentData: contents } };
|
||||
this._fireChangeEvent();
|
||||
const blocksValue = this._value ? { ...this._value.blocks, contentData: contents } : undefined;
|
||||
this.#setBlocksValue(blocksValue);
|
||||
});
|
||||
|
||||
this.observe(this.#managerContext.settings, (settings) => {
|
||||
this._value = { ...this._value, blocks: { ...this._value.blocks, settingsData: settings } };
|
||||
this._fireChangeEvent();
|
||||
const blocksValue = this._value ? { ...this._value.blocks, settingsData: settings } : undefined;
|
||||
this.#setBlocksValue(blocksValue);
|
||||
});
|
||||
|
||||
this.observe(this.#managerContext.exposes, (exposes) => {
|
||||
this._value = { ...this._value, blocks: { ...this._value.blocks, expose: exposes } };
|
||||
this._fireChangeEvent();
|
||||
const blocksValue = this._value ? { ...this._value.blocks, expose: exposes } : undefined;
|
||||
this.#setBlocksValue(blocksValue);
|
||||
});
|
||||
});
|
||||
|
||||
// The above could potentially be replaced with a single observeMultiple call, but it is not done for now to avoid potential issues with the order of the updates.
|
||||
/*this.observe(
|
||||
observeMultiple([
|
||||
this.#managerContext.layouts,
|
||||
this.#managerContext.contents,
|
||||
this.#managerContext.settings,
|
||||
this.#managerContext.exposes,
|
||||
]).pipe(debounceTime(20)),
|
||||
([layouts, contents, settings, exposes]) => {
|
||||
this._value = {
|
||||
...this._value,
|
||||
blocks: {
|
||||
layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts },
|
||||
contentData: contents,
|
||||
settingsData: settings,
|
||||
expose: exposes,
|
||||
},
|
||||
};
|
||||
|
||||
this._fireChangeEvent();
|
||||
},
|
||||
'motherObserver',
|
||||
);*/
|
||||
});
|
||||
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (context) => {
|
||||
this.#managerContext.setVariantId(context.getVariantId());
|
||||
});
|
||||
@@ -191,6 +181,19 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
|
||||
});
|
||||
}
|
||||
|
||||
#setBlocksValue(blocksValue?: UmbBlockValueType<UmbBlockRteLayoutModel>) {
|
||||
if (!blocksValue || !this._value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._value = {
|
||||
...this._value,
|
||||
blocks: blocksValue,
|
||||
};
|
||||
|
||||
this._fireChangeEvent();
|
||||
}
|
||||
|
||||
protected _fireChangeEvent() {
|
||||
this.dispatchEvent(new UmbPropertyValueChangeEvent());
|
||||
}
|
||||
|
||||
@@ -12,6 +12,13 @@ export class UmbPropertyEditorUITinyMceElement extends UmbPropertyEditorUiRteEle
|
||||
#onChange(event: CustomEvent & { target: UmbInputTinyMceElement }) {
|
||||
const value = typeof event.target.value === 'string' ? event.target.value : '';
|
||||
|
||||
// If we don't get any markup clear the property editor value.
|
||||
if (value === '') {
|
||||
this.value = undefined;
|
||||
this._fireChangeEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
// Clone the DOM, to remove the classes and attributes on the original:
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = value;
|
||||
@@ -38,10 +45,12 @@ export class UmbPropertyEditorUITinyMceElement extends UmbPropertyEditorUiRteEle
|
||||
|
||||
this._latestMarkup = markup;
|
||||
|
||||
this._value = {
|
||||
this._value = this._value
|
||||
? {
|
||||
...this._value,
|
||||
markup: markup,
|
||||
};
|
||||
}
|
||||
: undefined;
|
||||
|
||||
this._fireChangeEvent();
|
||||
}
|
||||
|
||||
@@ -67,6 +67,14 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
|
||||
await Promise.all([await this.#loadExtensions(), await this.#loadEditor()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the editor is empty.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public isEmpty(): boolean {
|
||||
return this._editor.isEmpty;
|
||||
}
|
||||
|
||||
async #loadExtensions() {
|
||||
await new Promise<void>((resolve) => {
|
||||
this.observe(umbExtensionsRegistry.byType('tiptapExtension'), async (manifests) => {
|
||||
|
||||
@@ -12,7 +12,15 @@ const elementName = 'umb-property-editor-ui-tiptap';
|
||||
@customElement(elementName)
|
||||
export class UmbPropertyEditorUiTiptapElement extends UmbPropertyEditorUiRteElementBase {
|
||||
#onChange(event: CustomEvent & { target: UmbInputTiptapElement }) {
|
||||
const value = event.target.value;
|
||||
const tipTapElement = event.target;
|
||||
const value = tipTapElement.value;
|
||||
|
||||
// If we don't get any markup clear the property editor value.
|
||||
if (tipTapElement.isEmpty()) {
|
||||
this.value = undefined;
|
||||
this._fireChangeEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove unused Blocks of Blocks Layout. Leaving only the Blocks that are present in Markup.
|
||||
const usedContentKeys: string[] = [];
|
||||
@@ -32,10 +40,12 @@ export class UmbPropertyEditorUiTiptapElement extends UmbPropertyEditorUiRteElem
|
||||
|
||||
this._latestMarkup = value;
|
||||
|
||||
this._value = {
|
||||
this._value = this._value
|
||||
? {
|
||||
...this._value,
|
||||
markup: this._latestMarkup,
|
||||
};
|
||||
}
|
||||
: undefined;
|
||||
|
||||
this._fireChangeEvent();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user