Skip to content

Commit 385a091

Browse files
committed
PB-390: Nested Page Builder content can fail to save when action is performed quickly
- Add numerous rendering locks to ensure we always observe the last lock when waiting in the form mixin
1 parent dfe36e7 commit 385a091

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

app/code/Magento/PageBuilder/view/adminhtml/web/js/form/form-mixin.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ define([
4141
*/
4242
save: function (redirect, data) {
4343
var submit = this._super.bind(this, redirect, data),
44-
timeout;
44+
timeout,
45+
locks;
4546

4647
if (_.isEmpty(this.pageBuilderInstances)) {
4748
submit();
@@ -56,7 +57,9 @@ define([
5657
$.when.apply(
5758
null,
5859
this.pageBuilderInstances.map(function (instance) {
59-
return instance.stage.renderingLock;
60+
locks = instance.stage.renderingLocks;
61+
62+
return locks[locks.length - 1];
6063
})
6164
).then(function () {
6265
$('body').trigger('processStop');

app/code/Magento/PageBuilder/view/adminhtml/web/js/stage.js

Lines changed: 20 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/code/Magento/PageBuilder/view/adminhtml/web/ts/js/stage.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default class Stage {
3636
* We always complete a single render when the stage is first loaded, so we can set the lock when the stage is
3737
* created. The lock is used to halt the parent forms submission when Page Builder is rendering.
3838
*/
39-
public renderingLock: JQueryDeferred<void>;
39+
public renderingLocks: Array<JQueryDeferred<void>> = [];
4040
private template: string = "Magento_PageBuilder/content-type/preview";
4141
private render: Render;
4242
private collection: Collection = new Collection();
@@ -47,12 +47,13 @@ export default class Stage {
4747
* @type {(() => void) & _.Cancelable}
4848
*/
4949
private applyBindingsDebounce = _.debounce(() => {
50-
this.renderingLock = $.Deferred();
5150
this.render.applyBindings(this.rootContainer)
5251
.then((renderedOutput: string) => events.trigger(`stage:${ this.id }:masterFormatRenderAfter`, {
5352
value: renderedOutput,
5453
})).then(() => {
55-
this.renderingLock.resolve();
54+
this.renderingLocks.forEach((lock) => {
55+
lock.resolve();
56+
});
5657
}).catch((error: Error) => {
5758
if (error) {
5859
console.error(error);
@@ -129,6 +130,8 @@ export default class Stage {
129130
// can occur concurrently.
130131
events.on("stage:updateAfter", (args: StageUpdateAfterParamsInterface) => {
131132
if (args.stageId === this.id) {
133+
// Create the rendering lock straight away
134+
this.createLock();
132135
this.applyBindingsDebounce();
133136
}
134137
});
@@ -154,6 +157,13 @@ export default class Stage {
154157
events.on("stage:childFocusStop", () => this.focusChild(false));
155158
}
156159

160+
/**
161+
* Create a new lock for rendering
162+
*/
163+
private createLock(): void {
164+
this.renderingLocks.push($.Deferred());
165+
}
166+
157167
/**
158168
* On content type removed
159169
*

0 commit comments

Comments
 (0)