Skip to content

Commit 222e352

Browse files
saving actions now blocks any other action to prevent race condition and unclear ux
1 parent 448d478 commit 222e352

1 file changed

Lines changed: 39 additions & 18 deletions

File tree

assets/js/admin/components/OrderItems.js

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export default class OrderItems {
1717
this.$form = this.$card.closest('form');
1818
this.$liveComponent = this.$card.closest('[data-controller~="live"]');
1919
this.liveComponentPromise = null;
20+
this.pendingAction = false;
2021

2122
if (this.$liveComponent.length === 0) {
2223
return;
@@ -68,42 +69,39 @@ export default class OrderItems {
6869
element.dataset.orderItemsProductPickerInitialized = '1';
6970
// eslint-disable-next-line no-new
7071
new ProductPicker($(element), async productId => {
71-
const component = await this.getLiveComponent();
72-
await component.action('addProduct', { productId: Number(productId) });
73-
FormChangeInfo.showInfo();
72+
if (await this.runLiveAction('addProduct', { productId: Number(productId) })) {
73+
FormChangeInfo.showInfo();
74+
}
7475
});
7576
});
7677
}
7778

7879
async addItem(event) {
7980
event.preventDefault();
8081

81-
const component = await this.getLiveComponent();
82-
83-
await component.action('addItem');
84-
FormChangeInfo.showInfo();
82+
if (await this.runLiveAction('addItem')) {
83+
FormChangeInfo.showInfo();
84+
}
8585
}
8686

8787
async prefillTransport(event) {
88-
const component = await this.getLiveComponent();
89-
90-
await component.action('prefillTransport', { transportId: Number($(event.currentTarget).val()) });
91-
FormChangeInfo.showInfo();
88+
if (await this.runLiveAction('prefillTransport', { transportId: Number($(event.currentTarget).val()) })) {
89+
FormChangeInfo.showInfo();
90+
}
9291
}
9392

9493
async prefillPayment(event) {
95-
const component = await this.getLiveComponent();
96-
97-
await component.action('prefillPayment', { paymentId: Number($(event.currentTarget).val()) });
98-
FormChangeInfo.showInfo();
94+
if (await this.runLiveAction('prefillPayment', { paymentId: Number($(event.currentTarget).val()) })) {
95+
FormChangeInfo.showInfo();
96+
}
9997
}
10098

10199
onRemoveItemClick(event) {
102100
event.preventDefault();
103101

104102
const $removeButton = $(event.currentTarget);
105103

106-
if ($removeButton.hasClass('link-disabled')) {
104+
if (this.pendingAction || $removeButton.hasClass('link-disabled') || $removeButton.hasClass('disabled')) {
107105
return;
108106
}
109107

@@ -114,14 +112,37 @@ export default class OrderItems {
114112
itemName: itemName,
115113
}),
116114
continueEvent: async () => {
117-
const component = await this.getLiveComponent();
115+
if (
116+
!(await this.runLiveAction('removeItem', {
117+
itemIndex: $removeButton.data('order-item-index').toString(),
118+
}))
119+
) {
120+
return;
121+
}
118122

119-
await component.action('removeItem', { itemIndex: $removeButton.data('order-item-index').toString() });
120123
FormChangeInfo.showInfo();
121124
},
122125
});
123126
}
124127

128+
async runLiveAction(actionName, actionArgs = {}) {
129+
if (this.pendingAction) {
130+
return false;
131+
}
132+
133+
this.pendingAction = true;
134+
135+
try {
136+
const component = await this.getLiveComponent();
137+
138+
await component.action(actionName, actionArgs);
139+
140+
return true;
141+
} finally {
142+
this.pendingAction = false;
143+
}
144+
}
145+
125146
getLiveComponent() {
126147
if (this.liveComponentPromise === null) {
127148
this.liveComponentPromise = getComponent(this.$liveComponent[0]);

0 commit comments

Comments
 (0)