Skip to content

Commit 8141b6b

Browse files
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
1 parent ceafa83 commit 8141b6b

File tree

4 files changed

+78
-48
lines changed

4 files changed

+78
-48
lines changed

src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import type {
1010
import {
1111
UmbBlockRteEntriesContext,
1212
UmbBlockRteManagerContext,
13+
type UmbBlockRteLayoutModel,
1314
type UmbBlockRteTypeModel,
1415
} from '@umbraco-cms/backoffice/block-rte';
1516
import { UMB_PROPERTY_CONTEXT, UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
17+
import type { UmbBlockValueType } from '@umbraco-cms/backoffice/block';
1618

1719
// eslint-disable-next-line local-rules/enforce-element-suffix-on-element-class-name
1820
export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement implements UmbPropertyEditorUiElement {
@@ -35,6 +37,16 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
3537
},
3638
})
3739
public set value(value: UmbPropertyEditorUiValueType | undefined) {
40+
if (!value) {
41+
this._value = undefined;
42+
this._markup = '';
43+
this.#managerContext.setLayouts([]);
44+
this.#managerContext.setContents([]);
45+
this.#managerContext.setSettings([]);
46+
this.#managerContext.setExposes([]);
47+
return;
48+
}
49+
3850
const buildUpValue: Partial<UmbPropertyEditorUiValueType> = value ? { ...value } : {};
3951
buildUpValue.markup ??= '';
4052
buildUpValue.blocks ??= { layout: {}, contentData: [], settingsData: [], expose: [] };
@@ -69,10 +81,7 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
6981
protected _config?: UmbPropertyEditorConfigCollection;
7082

7183
@state()
72-
protected _value: UmbPropertyEditorUiValueType = {
73-
markup: '',
74-
blocks: { layout: {}, contentData: [], settingsData: [], expose: [] },
75-
};
84+
protected _value?: UmbPropertyEditorUiValueType | undefined;
7685

7786
/**
7887
* 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
127136

128137
// Observe the value of the property and update the editor value.
129138
this.observe(this.#managerContext.layouts, (layouts) => {
130-
this._value = {
131-
...this._value,
132-
blocks: { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } },
133-
};
134-
this._fireChangeEvent();
139+
const blocksValue =
140+
this._value && layouts?.length > 0
141+
? { ...this._value.blocks, layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts } }
142+
: undefined;
143+
144+
this.#setBlocksValue(blocksValue);
135145
});
146+
136147
this.observe(this.#managerContext.contents, (contents) => {
137-
this._value = { ...this._value, blocks: { ...this._value.blocks, contentData: contents } };
138-
this._fireChangeEvent();
148+
const blocksValue = this._value ? { ...this._value.blocks, contentData: contents } : undefined;
149+
this.#setBlocksValue(blocksValue);
139150
});
151+
140152
this.observe(this.#managerContext.settings, (settings) => {
141-
this._value = { ...this._value, blocks: { ...this._value.blocks, settingsData: settings } };
142-
this._fireChangeEvent();
153+
const blocksValue = this._value ? { ...this._value.blocks, settingsData: settings } : undefined;
154+
this.#setBlocksValue(blocksValue);
143155
});
156+
144157
this.observe(this.#managerContext.exposes, (exposes) => {
145-
this._value = { ...this._value, blocks: { ...this._value.blocks, expose: exposes } };
146-
this._fireChangeEvent();
158+
const blocksValue = this._value ? { ...this._value.blocks, expose: exposes } : undefined;
159+
this.#setBlocksValue(blocksValue);
147160
});
148-
149-
// 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.
150-
/*this.observe(
151-
observeMultiple([
152-
this.#managerContext.layouts,
153-
this.#managerContext.contents,
154-
this.#managerContext.settings,
155-
this.#managerContext.exposes,
156-
]).pipe(debounceTime(20)),
157-
([layouts, contents, settings, exposes]) => {
158-
this._value = {
159-
...this._value,
160-
blocks: {
161-
layout: { [UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS]: layouts },
162-
contentData: contents,
163-
settingsData: settings,
164-
expose: exposes,
165-
},
166-
};
167-
168-
this._fireChangeEvent();
169-
},
170-
'motherObserver',
171-
);*/
172161
});
162+
173163
this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (context) => {
174164
this.#managerContext.setVariantId(context.getVariantId());
175165
});
@@ -191,6 +181,19 @@ export abstract class UmbPropertyEditorUiRteElementBase extends UmbLitElement im
191181
});
192182
}
193183

184+
#setBlocksValue(blocksValue?: UmbBlockValueType<UmbBlockRteLayoutModel>) {
185+
if (!blocksValue || !this._value) {
186+
return;
187+
}
188+
189+
this._value = {
190+
...this._value,
191+
blocks: blocksValue,
192+
};
193+
194+
this._fireChangeEvent();
195+
}
196+
194197
protected _fireChangeEvent() {
195198
this.dispatchEvent(new UmbPropertyValueChangeEvent());
196199
}

src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/tiny-mce/property-editor-ui-tiny-mce.element.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ export class UmbPropertyEditorUITinyMceElement extends UmbPropertyEditorUiRteEle
1212
#onChange(event: CustomEvent & { target: UmbInputTinyMceElement }) {
1313
const value = typeof event.target.value === 'string' ? event.target.value : '';
1414

15+
// If we don't get any markup clear the property editor value.
16+
if (value === '') {
17+
this.value = undefined;
18+
this._fireChangeEvent();
19+
return;
20+
}
21+
1522
// Clone the DOM, to remove the classes and attributes on the original:
1623
const div = document.createElement('div');
1724
div.innerHTML = value;
@@ -38,10 +45,12 @@ export class UmbPropertyEditorUITinyMceElement extends UmbPropertyEditorUiRteEle
3845

3946
this._latestMarkup = markup;
4047

41-
this._value = {
42-
...this._value,
43-
markup: markup,
44-
};
48+
this._value = this._value
49+
? {
50+
...this._value,
51+
markup: markup,
52+
}
53+
: undefined;
4554

4655
this._fireChangeEvent();
4756
}

src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ export class UmbInputTiptapElement extends UmbFormControlMixin<string, typeof Um
6767
await Promise.all([await this.#loadExtensions(), await this.#loadEditor()]);
6868
}
6969

70+
/**
71+
* Checks if the editor is empty.
72+
* @returns {boolean}
73+
*/
74+
public isEmpty(): boolean {
75+
return this._editor.isEmpty;
76+
}
77+
7078
async #loadExtensions() {
7179
await new Promise<void>((resolve) => {
7280
this.observe(umbExtensionsRegistry.byType('tiptapExtension'), async (manifests) => {

src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/property-editor-ui-tiptap.element.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ const elementName = 'umb-property-editor-ui-tiptap';
1212
@customElement(elementName)
1313
export class UmbPropertyEditorUiTiptapElement extends UmbPropertyEditorUiRteElementBase {
1414
#onChange(event: CustomEvent & { target: UmbInputTiptapElement }) {
15-
const value = event.target.value;
15+
const tipTapElement = event.target;
16+
const value = tipTapElement.value;
17+
18+
// If we don't get any markup clear the property editor value.
19+
if (tipTapElement.isEmpty()) {
20+
this.value = undefined;
21+
this._fireChangeEvent();
22+
return;
23+
}
1624

1725
// Remove unused Blocks of Blocks Layout. Leaving only the Blocks that are present in Markup.
1826
const usedContentKeys: string[] = [];
@@ -32,10 +40,12 @@ export class UmbPropertyEditorUiTiptapElement extends UmbPropertyEditorUiRteElem
3240

3341
this._latestMarkup = value;
3442

35-
this._value = {
36-
...this._value,
37-
markup: this._latestMarkup,
38-
};
43+
this._value = this._value
44+
? {
45+
...this._value,
46+
markup: this._latestMarkup,
47+
}
48+
: undefined;
3949

4050
this._fireChangeEvent();
4151
}

0 commit comments

Comments
 (0)