| @@ -75,8 +75,19 @@ | ||
| 75 | 75 | }; |
| 76 | 76 | } )(); |
| 77 | 77 | |
| 78 | 78 | ( function ( $ ) { |
| 79 | + function plugin_status_event( slug, status ) { | |
| 80 | + if ( ! slug ) { | |
| 81 | + return; | |
| 82 | + } | |
| 83 | + document.dispatchEvent( | |
| 84 | + new CustomEvent( 'wcf-plugin-status-change', { | |
| 85 | + detail: { slug, status }, | |
| 86 | + } ) | |
| 87 | + ); | |
| 88 | + } | |
| 89 | + | |
| 79 | 90 | const CartFlowsOnboarding = { |
| 80 | 91 | remaining_install_plugins: 0, |
| 81 | 92 | remaining_active_plugins: 0, |
| 82 | 93 | |
| @@ -81,11 +92,71 @@ | ||
| 81 | 92 | remaining_active_plugins: 0, |
| 82 | 93 | |
| 83 | 94 | init() { |
| 84 | 95 | this._bind(); |
| 96 | + document.addEventListener( | |
| 97 | + 'wcf-plugin-retry', | |
| 98 | + CartFlowsOnboarding._retryPlugin, | |
| 99 | + false | |
| 100 | + ); | |
| 85 | 101 | }, |
| 86 | 102 | |
| 87 | 103 | /** |
| 104 | + * Retry a failed plugin: activate first, fall back to install. | |
| 105 | + * | |
| 106 | + * @param {Object} e custom event with the plugin slug. | |
| 107 | + */ | |
| 108 | + _retryPlugin( e ) { | |
| 109 | + const slug = e.detail?.slug; | |
| 110 | + | |
| 111 | + if ( ! slug ) { | |
| 112 | + return; | |
| 113 | + } | |
| 114 | + | |
| 115 | + plugin_status_event( slug, 'activating' ); | |
| 116 | + | |
| 117 | + $.ajax( { | |
| 118 | + url: ajaxurl, | |
| 119 | + type: 'POST', | |
| 120 | + data: { | |
| 121 | + action: 'cartflows_wizard_activate_plugin', | |
| 122 | + plugin_slug: slug, | |
| 123 | + plugin_init: slug + '/' + slug + '.php', | |
| 124 | + security: cartflows_onboarding.wizard_activate_plugin_nonce, | |
| 125 | + }, | |
| 126 | + } ) | |
| 127 | + .done( function ( response ) { | |
| 128 | + if ( response.success ) { | |
| 129 | + plugin_status_event( slug, 'active' ); | |
| 130 | + CartFlowsOnboarding._maybe_finish(); | |
| 131 | + } else { | |
| 132 | + plugin_status_event( slug, 'installing' ); | |
| 133 | + CartFlowsOnboarding._installPlugin( slug ); | |
| 134 | + } | |
| 135 | + } ) | |
| 136 | + .fail( function () { | |
| 137 | + plugin_status_event( slug, 'installing' ); | |
| 138 | + CartFlowsOnboarding._installPlugin( slug ); | |
| 139 | + } ); | |
| 140 | + }, | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * Settle counters after a successful retry and finish when nothing is pending. | |
| 144 | + */ | |
| 145 | + _maybe_finish() { | |
| 146 | + if ( CartFlowsOnboarding.remaining_active_plugins > 0 ) { | |
| 147 | + CartFlowsOnboarding.remaining_active_plugins--; | |
| 148 | + } | |
| 149 | + | |
| 150 | + if ( | |
| 151 | + ! CartFlowsOnboarding.remaining_active_plugins && | |
| 152 | + ! CartFlowsOnboarding.remaining_install_plugins | |
| 153 | + ) { | |
| 154 | + trigger_event(); | |
| 155 | + } | |
| 156 | + }, | |
| 157 | + | |
| 158 | + /** | |
| 88 | 159 | * Bind |
| 89 | 160 | */ |
| 90 | 161 | _bind() { |
| 91 | 162 | //Page builder installation & save option |
| @@ -262,8 +333,9 @@ | ||
| 262 | 333 | }, |
| 263 | 334 | } ) |
| 264 | 335 | .done( function ( response ) { |
| 265 | 336 | if ( response.success ) { |
| 337 | + plugin_status_event( plugin_slug, 'active' ); | |
| 266 | 338 | if ( |
| 267 | 339 | jQuery.inArray( plugin_slug, page_builder_slugs ) > |
| 268 | 340 | -1 |
| 269 | 341 | ) { |
| @@ -268,11 +340,15 @@ | ||
| 268 | 340 | -1 |
| 269 | 341 | ) { |
| 270 | 342 | save_page_builder_option( plugin_slug ); |
| 271 | 343 | } |
| 344 | + } else { | |
| 345 | + plugin_status_event( plugin_slug, 'failed' ); | |
| 272 | 346 | } |
| 273 | 347 | } ) |
| 274 | - .fail( function () {} ); | |
| 348 | + .fail( function () { | |
| 349 | + plugin_status_event( plugin_slug, 'failed' ); | |
| 350 | + } ); | |
| 275 | 351 | }, |
| 276 | 352 | |
| 277 | 353 | /** |
| 278 | 354 | * Import the store checkout template. |
| @@ -282,12 +358,18 @@ | ||
| 282 | 358 | _import_store_checkout_template( event ) { |
| 283 | 359 | event.preventDefault(); |
| 284 | 360 | // Selected Template's ID. |
| 285 | 361 | const store_template_flow = |
| 286 | - $( '#wcf-selected-store-checkout-template' ).attr( | |
| 287 | - 'data-selected-flow-info' | |
| 288 | - ) || '', | |
| 289 | - primary_color = $( 'input[name=primary_color]' ).val(), | |
| 362 | + $( '#wcf-selected-store-checkout-template' ).attr( | |
| 363 | + 'data-selected-flow-info' | |
| 364 | + ) || ''; | |
| 365 | + | |
| 366 | + // Never import when no template is selected. | |
| 367 | + if ( '' === store_template_flow ) { | |
| 368 | + return; | |
| 369 | + } | |
| 370 | + | |
| 371 | + const primary_color = $( 'input[name=primary_color]' ).val(), | |
| 290 | 372 | selected_site_logo = $( '.wcf-selected-image' ).data( |
| 291 | 373 | 'logo-data' |
| 292 | 374 | ); |
| 293 | 375 | |
| @@ -345,23 +427,29 @@ | ||
| 345 | 427 | /** |
| 346 | 428 | * Installing Plugin |
| 347 | 429 | * |
| 348 | 430 | * @param {Object} event event data. |
| 431 | + * @param {Object} args plugin data with slug. | |
| 349 | 432 | */ |
| 350 | - _pluginInstalling( event ) { | |
| 433 | + _pluginInstalling( event, args ) { | |
| 351 | 434 | event.preventDefault(); |
| 435 | + plugin_status_event( args?.slug, 'installing' ); | |
| 352 | 436 | }, |
| 353 | 437 | |
| 354 | 438 | /** |
| 355 | 439 | * Install Error |
| 356 | 440 | * |
| 357 | - * @param {Object} event event data. | |
| 441 | + * @param {Object} event event data. | |
| 442 | + * @param {Object} response error response with slug. | |
| 358 | 443 | */ |
| 359 | - _installError( event ) { | |
| 444 | + _installError( event, response ) { | |
| 360 | 445 | event.preventDefault(); |
| 361 | 446 | |
| 447 | + plugin_status_event( response?.slug, 'failed' ); | |
| 448 | + | |
| 449 | + // Stay on the step so Retry can render — attr() is undefined when the element is absent. | |
| 362 | 450 | const redirect_link = $( '.wcf-redirect-link' ).attr( 'value' ); |
| 363 | - if ( '' !== redirect_link ) { | |
| 451 | + if ( redirect_link && '' !== redirect_link ) { | |
| 364 | 452 | trigger_event(); |
| 365 | 453 | } |
| 366 | 454 | }, |
| 367 | 455 | |
| @@ -375,8 +463,10 @@ | ||
| 375 | 463 | event.preventDefault(); |
| 376 | 464 | const plugin_init = args.slug + '/' + args.slug + '.php'; |
| 377 | 465 | const plugin_slug = args.slug; |
| 378 | 466 | |
| 467 | + plugin_status_event( plugin_slug, 'activating' ); | |
| 468 | + | |
| 379 | 469 | // WordPress adds "Activate" button after waiting for 1000ms. So we will run our activation after that. |
| 380 | 470 | setTimeout( function () { |
| 381 | 471 | CartFlowsOnboarding._activatePlugin( plugin_init, plugin_slug ); |
| 382 | 472 | |
| @@ -438,9 +528,16 @@ | ||
| 438 | 528 | plugin_init, |
| 439 | 529 | security: |
| 440 | 530 | cartflows_onboarding.wizard_activate_plugin_nonce, |
| 441 | 531 | }, |
| 532 | + beforeSend() { | |
| 533 | + plugin_status_event( pluginSlug, 'activating' ); | |
| 534 | + }, | |
| 535 | + error() { | |
| 536 | + plugin_status_event( pluginSlug, 'failed' ); | |
| 537 | + }, | |
| 442 | 538 | success() { |
| 539 | + plugin_status_event( pluginSlug, 'active' ); | |
| 443 | 540 | CartFlowsOnboarding.remaining_active_plugins--; |
| 444 | 541 | |
| 445 | 542 | if ( |
| 446 | 543 | ! CartFlowsOnboarding.remaining_active_plugins && |