Commit 1dc1e3e5 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Fix Zuora frame size after client-side error

When Zuora validated the form it throws a client-side error
which we want to show. But Zuora has two types of client-side
errors: validation and validation after submit. To keep errors of
the first type validations we just update the iframe src
attribute but we have a race condition here:
- We set isLoading to true and hide the Zuora frame
- Zuora validates the form on the client and throws an error
- We update the iframe src and set isLoading to false which causes
the Zuora iframe to be displayed.
The race condition happens right after the Zuora throws an error.
Zuora always tries to resize the iframe to its container
to fit the content. In our case the Zuora iframe sets the
size to 0,0 because Vue didn't update the DOM yet due to
isLoading being false. To let the Zuora iframe to resize
to correct size let's wrap the update step with nextTick.

Changelog: fixed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64595
EE: true
parent 0a36b1ce
...@@ -43,6 +43,7 @@ export default { ...@@ -43,6 +43,7 @@ export default {
return { return {
error: null, error: null,
isLoading: true, isLoading: true,
isAlertDismissed: true,
}; };
}, },
computed: { computed: {
...@@ -54,6 +55,9 @@ export default { ...@@ -54,6 +55,9 @@ export default {
iframeHeight() { iframeHeight() {
return IFRAME_MINIMUM_HEIGHT * window.devicePixelRatio; return IFRAME_MINIMUM_HEIGHT * window.devicePixelRatio;
}, },
shouldShowAlert() {
return this.error && !this.isAlertDismissed;
},
}, },
destroyed() { destroyed() {
window.removeEventListener('message', this.handleFrameMessages, true); window.removeEventListener('message', this.handleFrameMessages, true);
...@@ -64,6 +68,7 @@ export default { ...@@ -64,6 +68,7 @@ export default {
this.error = null; this.error = null;
this.isLoading = true; this.isLoading = true;
this.isAlertDismissed = true;
this.$refs.zuora.contentWindow.postMessage('submit', this.allowedOrigin); this.$refs.zuora.contentWindow.postMessage('submit', this.allowedOrigin);
}, },
...@@ -87,10 +92,13 @@ export default { ...@@ -87,10 +92,13 @@ export default {
if (event.data.success) { if (event.data.success) {
this.$emit('success'); this.$emit('success');
} else if (parseInt(event.data.code, 10) > 6) { } else if (parseInt(event.data.code, 10) > 6) {
// 0-6 error codes mean client-side validation error, // 0-6 error codes mean client-side validation error after submit,
// no needs to reload the iframe and emit the failure event // no needs to reload the iframe and emit the failure event
this.error = event.data.msg; this.error = event.data.msg;
this.$refs.zuora.src = this.iframeSrc; this.isAlertDismissed = false;
this.nextTick(() => {
this.$refs.zuora.src = this.iframeSrc;
});
this.$emit('failure', { msg: this.error }); this.$emit('failure', { msg: this.error });
} }
...@@ -105,6 +113,9 @@ export default { ...@@ -105,6 +113,9 @@ export default {
return false; return false;
} }
}, },
handleAlertDismiss() {
this.isAlertDismissed = true;
},
}, },
i18n, i18n,
}; };
...@@ -126,7 +137,9 @@ export default { ...@@ -126,7 +137,9 @@ export default {
</gl-sprintf> </gl-sprintf>
</p> </p>
<gl-alert v-if="error" variant="danger">{{ error }}</gl-alert> <gl-alert v-if="shouldShowAlert" variant="danger" @dismiss="handleAlertDismiss">{{
error
}}</gl-alert>
<gl-loading-icon v-if="isLoading" size="lg" /> <gl-loading-icon v-if="isLoading" size="lg" />
<!-- eslint-disable @gitlab/vue-require-i18n-strings --> <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
<iframe <iframe
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment