-
-
Notifications
You must be signed in to change notification settings - Fork 78
fix(template-switch+light-ajax+stripe+settings): four follow-ups from end-to-end UX validation #1113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(template-switch+light-ajax+stripe+settings): four follow-ups from end-to-end UX validation #1113
Changes from all commits
5ffbaca
0a315e1
78e37f1
5d8b953
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,7 +52,43 @@ | |
| template_category: '', | ||
| stored_templates: {}, | ||
| confirm_switch: 0, | ||
|
|
||
| /* | ||
| * Drives visibility of the confirm panel. Set true when | ||
| * the customer picks a grid template (template_id watcher | ||
| * below) or clicks Reset (reset_template). Set false on | ||
| * Cancel and after a successful switch. We track this | ||
| * explicitly rather than deriving it from | ||
| * (template_id !== original_template_id) because the | ||
| * Reset flow needs the panel to appear *while* | ||
| * template_id equals original_template_id, which a | ||
| * derived check could not express. | ||
| */ | ||
| confirm_active: false, | ||
| ready: false, | ||
|
|
||
| /* | ||
| * Inline error surface for the confirm panel. | ||
| * | ||
| * The legacy error path called wu_ajax_error() which | ||
| * either shows a SweetAlert modal (when Swal is loaded | ||
| * — it isn't on customer-panel pages) or prepends a | ||
| * dismissible notice to the very top of #wpbody-content. | ||
| * In the customer panel the confirm panel sits well | ||
| * below the fold on the typical viewport, so a notice | ||
| * placed at the top of the page is invisible to a | ||
| * customer who has just clicked "Switch to X". They | ||
| * see the spinner clear, the panel close, and nothing | ||
| * else — looking like the action silently failed. | ||
| * | ||
| * Setting this string surfaces the error inline inside | ||
| * the confirm panel itself (see views/ui/template- | ||
| * switching-confirm.php), right where the customer's | ||
| * eye is. We keep the wu_ajax_error() call too for | ||
| * users who scroll up, plus belt-and-braces for the | ||
| * (rare) case where the panel itself fails to render. | ||
| */ | ||
| error_message: '', | ||
| }; | ||
|
|
||
| }, | ||
|
|
@@ -80,6 +116,85 @@ | |
| } // end if; | ||
|
|
||
| }, | ||
|
|
||
| /* | ||
| * Surface the confirm panel when the customer clicks a Select | ||
| * button in the grid. Grid buttons live inside the shared | ||
| * checkout/template-selection clean.php view (which we don't | ||
| * edit because signup uses it too); they only set | ||
| * template_id. Watching that change lets us inject the | ||
| * confirm_active = true behaviour without touching the | ||
| * shared view. | ||
| * | ||
| * Guard: don't flip confirm_active on the initial v-init | ||
| * assignment (which sets template_id = original_template_id | ||
| * before the page is interactive). Picking the customer's | ||
| * existing template from the grid is also a no-op — there's | ||
| * nothing to confirm. | ||
| */ | ||
| template_id(new_value, old_value) { | ||
|
|
||
| if (old_value === undefined) { | ||
|
|
||
| return; | ||
|
|
||
| } // end if; | ||
|
|
||
| if (new_value === 0 || new_value === '0') { | ||
|
|
||
| this.confirm_active = false; | ||
| return; | ||
|
|
||
| } // end if; | ||
|
|
||
| /* | ||
| * Defence in depth against directive-ordering races on | ||
| * mount. The element output co-locates | ||
| * v-init:original_template_id and v-init:template_id on | ||
| * the same hidden field, but if anything ever causes the | ||
| * template_id directive to bind first (Vue plugin order, | ||
| * future markup change, third-party Vue mixin, etc.) we | ||
| * would otherwise reach the `confirm_active = true` | ||
| * branch below with original_template_id still at its | ||
| * data() sentinel of -1. -1 is a value that no real | ||
| * template can have, so we treat it as "not yet | ||
| * initialised" and bail out — the watcher will fire | ||
| * again on the next legitimate template change. | ||
| */ | ||
| // eslint-disable-next-line eqeqeq | ||
| if (this.original_template_id == -1 || this.original_template_id <= 0) { | ||
|
|
||
| return; | ||
|
|
||
| } // end if; | ||
|
|
||
| // eslint-disable-next-line eqeqeq | ||
| if (new_value == this.original_template_id) { | ||
|
|
||
| // Picking the current template from the grid is a | ||
| // no-op; reset_template() handles the deliberate | ||
| // "Reset" path and will set confirm_active = true | ||
| // itself. | ||
| return; | ||
|
|
||
| } // end if; | ||
|
|
||
| /* | ||
| * Clear any error message left over from a previous | ||
| * failed switch attempt. If the customer picks a | ||
| * different template after seeing an error, they are | ||
| * starting a new attempt and the stale message would | ||
| * be misleading. | ||
| */ | ||
| if (this.error_message) { | ||
|
|
||
| this.error_message = ''; | ||
|
|
||
| } // end if; | ||
|
|
||
| this.confirm_active = true; | ||
|
|
||
| }, | ||
| }, | ||
| methods: { | ||
| get_template(template, data) { | ||
|
|
@@ -141,55 +256,142 @@ | |
|
|
||
| }, | ||
| /** | ||
| * Re-apply the customer's current template, refreshing | ||
| * the site from the source template. Triggered by the | ||
| * "Reset current template" link in the form. | ||
| * Show the confirm panel for re-applying the customer's | ||
| * current template. Triggered by the "Reset Current | ||
| * Template" button in the current-template card. | ||
| * | ||
| * Confirms with the customer first because this overwrites | ||
| * the site's content. Confirmation text is supplied via | ||
| * wu_template_switching_params.i18n.reset_confirm so it | ||
| * is translatable. | ||
| * Previously this used a native confirm() popup and fired | ||
| * the switch immediately. The new flow surfaces the same | ||
| * confirmation card used for switching to a different | ||
| * template — the customer sees the target thumbnail, name, | ||
| * and disclaimer before clicking Confirm. Pairing reset | ||
| * and switch under the same confirmation UI makes the | ||
| * "you are about to overwrite your site" warning feel | ||
| * consistent regardless of which path got the customer | ||
| * here. | ||
| * | ||
| * Setting ready = true triggers the existing watcher which | ||
| * calls switch_template() — the same code path used by the | ||
| * normal "Process Switch" button. | ||
| * The actual switch is then triggered from the Confirm | ||
| * button inside the panel (which sets ready = true, | ||
| * matching the grid switch flow). | ||
| */ | ||
| reset_template() { | ||
|
|
||
| const params = window.wu_template_switching_params || {}; | ||
| const message = (params.i18n && params.i18n.reset_confirm) | ||
| ? params.i18n.reset_confirm | ||
| : 'Re-apply your current template? This will overwrite your site content with a fresh copy of the template. This cannot be undone.'; | ||
|
|
||
| // Native confirm() matches the existing pattern used elsewhere | ||
| // in this codebase (edit-placeholders.js, tax-rates.js, dns-management.js) | ||
| // for destructive customer-facing actions. Avoiding the no-alert | ||
| // rule would mean introducing modal infrastructure that does not | ||
| // yet exist on this page. | ||
| // eslint-disable-next-line no-alert | ||
| if ( ! window.confirm(message)) { | ||
| if ( ! this.original_template_id || this.original_template_id <= 0) { | ||
|
|
||
| return; | ||
|
|
||
| } // end if; | ||
|
|
||
| if ( ! this.original_template_id || this.original_template_id <= 0) { | ||
| this.template_id = this.original_template_id; | ||
| this.confirm_active = true; | ||
|
|
||
|
Comment on lines
277
to
287
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clear stale inline errors when opening the reset flow. After a failed switch attempt, clicking Reset Current Template keeps the previous 💡 Suggested fix reset_template() {
if ( ! this.original_template_id || this.original_template_id <= 0) {
return;
} // end if;
+ this.error_message = '';
this.template_id = this.original_template_id;
this.confirm_active = true;🤖 Prompt for AI Agents |
||
| return; | ||
| /* | ||
| * Scroll the confirm panel into view. The current- | ||
| * template card and the panel can both fit on screen | ||
| * together for most viewports, but on shorter windows | ||
| * the panel renders below the fold; without this | ||
| * scroll, customers reported clicking Reset and seeing | ||
| * "nothing happen" until they scrolled. | ||
| */ | ||
| this.$nextTick(() => { | ||
|
|
||
| } // end if; | ||
| const panel = document.querySelector('.wu-template-switching-confirm'); | ||
|
|
||
| this.template_id = this.original_template_id; | ||
| if (panel && typeof panel.scrollIntoView === 'function') { | ||
|
|
||
| this.confirm_switch = true; | ||
| panel.scrollIntoView({ behavior: 'smooth', block: 'center' }); | ||
|
|
||
| this.ready = true; | ||
| } // end if; | ||
|
|
||
| }); | ||
|
|
||
| }, | ||
|
|
||
| /** | ||
| * Dismiss the confirm panel without performing a switch. | ||
| * Resets the queued template selection back to the | ||
| * customer's active template so the grid no longer shows | ||
| * a "Selected" highlight on a template they decided not | ||
| * to switch to. | ||
| */ | ||
| cancel_switch() { | ||
|
|
||
| this.confirm_active = false; | ||
| this.template_id = this.original_template_id; | ||
| this.error_message = ''; | ||
|
|
||
| }, | ||
|
|
||
| /** | ||
| * Surface an AJAX failure inline in the confirm panel and | ||
| * also via the global wu_ajax_error() toast/notice. | ||
| * | ||
| * Keeping the confirm panel open (confirm_active stays | ||
| * true) is deliberate: the previous behaviour closed the | ||
| * panel on failure and let wu_ajax_error() prepend a | ||
| * notice to the top of #wpbody-content. On the customer | ||
| * panel that notice is far above the fold from where the | ||
| * customer just clicked Confirm, so they saw nothing — | ||
| * the spinner cleared, the panel disappeared, and the | ||
| * action looked like a silent no-op. Now the error renders | ||
| * directly inside the panel where the click happened. | ||
| * | ||
| * @param {string|null} message Human-readable failure | ||
| * reason. Pass null to delegate copy to wu_ajax_error | ||
| * (used for network errors where we do not have a | ||
| * server-supplied string). | ||
| */ | ||
| show_error(message) { | ||
|
|
||
| this.unblock(); | ||
| this.confirm_switch = false; | ||
| this.ready = false; | ||
|
|
||
| /* | ||
| * Keep confirm_active true so the panel — which now | ||
| * carries the inline error block — stays visible. | ||
| */ | ||
| this.confirm_active = true; | ||
|
|
||
| this.error_message = message || 'An error occurred while switching templates.'; | ||
|
|
||
| /* | ||
| * Belt-and-braces: also show the global notice in case | ||
| * the panel itself fails to render (e.g. third-party | ||
| * JS error breaks the Vue update). | ||
| */ | ||
| wu_ajax_error(message); | ||
|
|
||
| /* | ||
| * Bring the panel into view if the customer scrolled | ||
| * away or it was rendered below the fold. Without | ||
| * this, an inline error placed below the visible | ||
| * region would still go unnoticed. | ||
| */ | ||
| this.$nextTick(() => { | ||
|
|
||
| const panel = document.querySelector('.wu-template-switching-confirm'); | ||
|
|
||
| if (panel && typeof panel.scrollIntoView === 'function') { | ||
|
|
||
| panel.scrollIntoView({ behavior: 'smooth', block: 'center' }); | ||
|
|
||
| } // end if; | ||
|
|
||
| }); | ||
|
|
||
| }, | ||
| switch_template() { | ||
|
|
||
| const that = this; | ||
|
|
||
| /* | ||
| * Clear any error from a previous attempt so the | ||
| * panel does not show a stale message while the new | ||
| * request is in flight. | ||
| */ | ||
| that.error_message = ''; | ||
|
|
||
| that.block(); | ||
|
|
||
| this.request('wu_switch_template', { | ||
|
|
@@ -205,13 +407,7 @@ | |
| */ | ||
| if ( ! results || typeof results !== 'object') { | ||
|
|
||
| that.unblock(); | ||
|
|
||
| that.confirm_switch = false; | ||
|
|
||
| that.ready = false; | ||
|
|
||
| wu_ajax_error('An error occurred while switching templates.'); | ||
| that.show_error('An error occurred while switching templates.'); | ||
|
|
||
| return; | ||
|
|
||
|
|
@@ -222,12 +418,6 @@ | |
| */ | ||
| if (results.success === false) { | ||
|
|
||
| that.unblock(); | ||
|
|
||
| that.confirm_switch = false; | ||
|
|
||
| that.ready = false; | ||
|
|
||
| let errorMessage = 'An error occurred while switching templates.'; | ||
|
|
||
| if (results.data && results.data.message) { | ||
|
|
@@ -240,7 +430,7 @@ | |
|
|
||
| } | ||
|
|
||
| wu_ajax_error(errorMessage); | ||
| that.show_error(errorMessage); | ||
|
|
||
| return; | ||
|
|
||
|
|
@@ -269,21 +459,19 @@ | |
| that.unblock(); | ||
|
|
||
| that.confirm_switch = false; | ||
| that.confirm_active = false; | ||
|
|
||
| that.ready = false; | ||
|
|
||
| }, function() { | ||
|
|
||
| /* | ||
| * Handle network errors. | ||
| * Handle network errors. wu_ajax_error(null) lets that | ||
| * helper fill in its own "network error" copy; mirror it | ||
| * inline in the panel so the customer sees the same | ||
| * information without scrolling. | ||
| */ | ||
| that.unblock(); | ||
|
|
||
| that.confirm_switch = false; | ||
|
|
||
| that.ready = false; | ||
|
|
||
| wu_ajax_error(null); | ||
| that.show_error('A network error occurred. Please check your connection and try again.'); | ||
|
|
||
| }); | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't suppress the confirm flow for first-time template application.
When a site has no current template,
original_template_idis0. This guard returns beforeconfirm_activeis set, so picking a template never opens the new confirm panel and there is no way to reachswitch_template()for that path. The earliernew_value === 0branch already covers the initial mount case, so the<= 0check is too broad here.💡 Suggested fix
🤖 Prompt for AI Agents