PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.5.5
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.5.5
4.5.6 4.5.5 4.5.4 4.2.1 4.2.2 4.2.3 4.5.0 4.5.2 4.5.3 4.2.0 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.0.9 4.1.0 4.1.1 4.1.2 All 148 releases
ultimate-post-kit / includes / setup-wizard / assets / js / setup-wizard.js

setup-wizard.js in Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets 4.5.5, at includes/setup-wizard/assets/js/setup-wizard.js

850 lines 36.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function ($) {
2 if (!$('.bdt-setup-wizard').length) {
3 return;
4 }
5
6 $(document).ready(function () {
7 const wizard = {
8 currentStep: 0,
9 steps: document.querySelectorAll('.bdt-wizard-step'),
10 nextButtons: document.querySelectorAll('.bdt-wizard-next'),
11 prevButtons: document.querySelectorAll('.bdt-wizard-prev'),
12 progressItems: document.querySelectorAll('.bdt-wizard-progress-item'),
13 progressBar: document.getElementById('plugin-install-progress'),
14 categorySelect: document.getElementById('category-select'),
15 searchInput: document.querySelector('.widget-search'),
16 activateAllButton: document.querySelector('.bulk-action.activate'),
17 deactivateAllButton: document.querySelector('.bulk-action.deactivate'),
18 saveButton: document.getElementById('save-and-continue'),
19 widgetList: document.querySelector('.widget-list'),
20 installButton: document.getElementById('upk-install-plugins-btn'),
21 filterButtons: document.querySelectorAll('.filter-button'),
22
23 init: function () {
24 this.setupStepAttributes();
25 this.showStep(this.currentStep);
26 this.updateProgress(this.currentStep);
27 this.bindEvents();
28 this.initAnimations();
29 },
30
31 setupStepAttributes: function() {
32 const stepNames = ['welcome', 'features', 'integration', 'finish'];
33 this.steps.forEach((step, index) => {
34 if (!step.hasAttribute('data-step') && index < stepNames.length) {
35 step.setAttribute('data-step', stepNames[index]);
36 }
37 });
38 },
39
40 initAnimations: function() {
41 const currentStep = this.steps[this.currentStep];
42 if (currentStep) {
43 setTimeout(() => {
44 currentStep.classList.add('active');
45 currentStep.style.display = 'block'; // Ensure display is set to block
46 }, 100);
47 }
48 },
49
50 bindEvents: function () {
51 const self = this;
52
53 this.progressItems.forEach((item, index) => {
54 item.addEventListener('click', () => {
55 const stepName = item.getAttribute('data-step');
56 if (index <= this.getCompletedStepIndex()) {
57 this.goToStep(index);
58 }
59 });
60 });
61
62 $(document).on('click', '.bdt-wizard-next', function(e) {
63 e.preventDefault();
64 const targetStep = $(this).data('step');
65
66 // No loader or timeout - immediate transition
67 if (targetStep) {
68 for (let i = 0; i < self.steps.length; i++) {
69 if ($(self.steps[i]).data('step') === targetStep) {
70 self.goToStep(i);
71 return;
72 }
73 }
74
75 const stepIndex = self.getStepIndexByName(targetStep);
76 if (stepIndex !== -1) {
77 self.goToStep(stepIndex);
78 return;
79 }
80 }
81
82 self.goToStep(self.currentStep + 1);
83 });
84
85 this.prevButtons.forEach(button => {
86 button.addEventListener('click', () => {
87 // No loader or timeout - immediate transition
88 const targetStep = button.getAttribute('data-step');
89 if (targetStep) {
90 const stepIndex = this.getStepIndexByName(targetStep);
91 if (stepIndex !== -1) {
92 this.goToStep(stepIndex);
93 }
94 } else if (this.currentStep > 0) {
95 this.goToStep(this.currentStep - 1);
96 }
97 });
98 });
99
100 if (this.filterButtons) {
101 this.filterButtons.forEach(button => {
102 button.addEventListener('click', () => {
103 this.filterButtons.forEach(btn => btn.classList.remove('active'));
104 button.classList.add('active');
105 this.filterItemsByType(button.dataset.filter);
106 });
107 });
108 }
109
110 if (this.categorySelect) {
111 this.categorySelect.addEventListener('change', this.filterWidgets.bind(this));
112 }
113
114 if (this.searchInput) {
115 this.searchInput.addEventListener('input', this.searchWidgets.bind(this));
116 }
117
118 if (this.activateAllButton) {
119 this.activateAllButton.addEventListener('click', this.activateAllWidgets.bind(this));
120 }
121 if (this.deactivateAllButton) {
122 this.deactivateAllButton.addEventListener('click', this.deactivateAllWidgets.bind(this));
123 }
124
125 this.saveSettingsSubmit();
126 this.installPlugins();
127 this.onChangedPluginSliderCheckbox();
128 this.subscribeSubmit();
129
130 const featureItems = document.querySelectorAll('.bdt-feature-item');
131 featureItems.forEach(item => {
132 item.addEventListener('mouseenter', () => {
133 item.style.transform = 'translateY(-8px)';
134 });
135 item.addEventListener('mouseleave', () => {
136 item.style.transform = 'translateY(-3px)';
137 });
138 });
139 },
140
141 getStepIndexByName: function(stepName) {
142 for (let i = 0; i < this.steps.length; i++) {
143 if (this.steps[i].getAttribute('data-step') === stepName) {
144 return i;
145 }
146 }
147
148 const stepMap = {
149 'welcome': 0,
150 'features': 1,
151 'integration': 2,
152 'finish': 3
153 };
154
155 return stepName in stepMap ? stepMap[stepName] : -1;
156 },
157
158 getCompletedStepIndex: function() {
159 return this.currentStep;
160 },
161
162 goToStep: function(stepIndex) {
163 if (stepIndex >= 0 && stepIndex < this.steps.length) {
164 this.currentStep = stepIndex;
165 this.showStep(this.currentStep);
166 this.updateProgress(this.currentStep);
167 }
168 },
169
170 pluginSliderCheckbox: function(selector){
171 const pluginSlugs = [];
172 const data = $(selector).serialize();
173 data.split('&').forEach(item => {
174 const [key, value] = item.split('=');
175 if (key.startsWith('plugins') && value === 'on') {
176 const slug = decodeURIComponent(key.split('%5B%5D')[1]);
177 if (slug) {
178 pluginSlugs.push(slug);
179 }
180 }
181 });
182
183 if(pluginSlugs.length){
184 $("#upk-install-plugins-btn").removeClass('d-none').addClass('pulse-animation');
185 }else{
186 $("#upk-install-plugins-btn").addClass('d-none').removeClass('pulse-animation');
187 }
188 },
189
190 onChangedPluginSliderCheckbox: function(){
191 const vm = this;
192 $('#upk-install-plugins').on('change', '.plugin-slider-checkbox', function (e) {
193 vm.pluginSliderCheckbox('#upk-install-plugins .plugin-slider-checkbox');
194
195 const pluginItem = $(this).closest('.plugin-item');
196 pluginItem.addClass('item-highlight');
197 setTimeout(() => {
198 pluginItem.removeClass('item-highlight');
199 }, 600);
200 });
201 },
202
203 showStep: function (step) {
204 // Hide all steps first
205 this.steps.forEach((stepElement) => {
206 stepElement.classList.remove('active');
207 stepElement.style.display = 'none'; // Ensure inactive steps are completely hidden
208 });
209
210 // Immediately show the current step without delay
211 const currentStep = this.steps[step];
212 if (currentStep) {
213 currentStep.classList.add('active');
214 currentStep.style.display = 'block'; // Make sure active step is visible
215 }
216
217 this.pluginSliderCheckbox('#upk-install-plugins .plugin-slider-checkbox');
218 },
219
220 filterItemsByType: function(type) {
221 const items = document.querySelectorAll('.feature-item, .plugin-item');
222
223 items.forEach(item => {
224 if (type === 'all' || item.dataset.type === type) {
225 item.style.display = 'flex';
226 setTimeout(() => {
227 item.style.opacity = '1';
228 item.style.transform = 'translateY(0)';
229 }, 50);
230 } else {
231 item.style.opacity = '0';
232 item.style.transform = 'translateY(10px)';
233 setTimeout(() => {
234 item.style.display = 'none';
235 }, 300);
236 }
237 });
238 },
239
240 filterWidgets: function () {
241 const selectedCategory = this.categorySelect.value;
242 const widgets = this.widgetList.querySelectorAll('li');
243
244 widgets.forEach(widget => {
245 const types = widget.dataset.type.split(/\s+/);
246 if (selectedCategory === 'all' || types.includes(selectedCategory)) {
247 widget.style.display = 'block';
248 setTimeout(() => {
249 widget.style.opacity = '1';
250 widget.style.transform = 'translateY(0)';
251 }, 50);
252 } else {
253 widget.style.opacity = '0';
254 widget.style.transform = 'translateY(10px)';
255 setTimeout(() => {
256 widget.style.display = 'none';
257 }, 300);
258 }
259 });
260 },
261
262 updateProgress: function (step) {
263 this.progressItems.forEach((item, index) => {
264 if (index < step) {
265 item.classList.remove('active');
266 item.classList.add('completed');
267 } else if (index === step) {
268 item.classList.add('active');
269 item.classList.remove('completed');
270 } else {
271 item.classList.remove('active', 'completed');
272 }
273 });
274 },
275
276 searchWidgets: function () {
277 const searchTerm = this.searchInput.value.toLowerCase();
278 const widgets = this.widgetList.querySelectorAll('li');
279
280 widgets.forEach(widget => {
281 if (widget.dataset.label.toLowerCase().includes(searchTerm)) {
282 widget.style.display = 'block';
283 setTimeout(() => {
284 widget.style.opacity = '1';
285 }, 50);
286 } else {
287 widget.style.opacity = '0';
288 setTimeout(() => {
289 widget.style.display = 'none';
290 }, 300);
291 }
292 });
293 },
294
295 activateAllWidgets: function (event) {
296 event.preventDefault();
297 const checkboxes = this.widgetList.querySelectorAll('input[type="checkbox"]');
298
299 this.activateAllButton.classList.add('button-pulse');
300 setTimeout(() => {
301 this.activateAllButton.classList.remove('button-pulse');
302 }, 500);
303
304 checkboxes.forEach(checkbox => {
305 checkbox.checked = true;
306 const widgetItem = checkbox.closest('li');
307 widgetItem.classList.add('item-highlight');
308 setTimeout(() => {
309 widgetItem.classList.remove('item-highlight');
310 }, 600);
311 });
312 },
313
314 deactivateAllWidgets: function (event) {
315 event.preventDefault();
316 const checkboxes = this.widgetList.querySelectorAll('input[type="checkbox"]');
317
318 this.deactivateAllButton.classList.add('button-pulse');
319 setTimeout(() => {
320 this.deactivateAllButton.classList.remove('button-pulse');
321 }, 500);
322
323 checkboxes.forEach(checkbox => {
324 checkbox.checked = false;
325 const widgetItem = checkbox.closest('li');
326 widgetItem.classList.add('item-highlight');
327 setTimeout(() => {
328 widgetItem.classList.remove('item-highlight');
329 }, 600);
330 });
331 },
332
333 /**
334 * The newsletter opt-in sits in the welcome step and has no submit
335 * button of its own: the choice is sent when the user moves on with
336 * "Get Started".
337 *
338 * Fire and forget — the step change is never delayed and shows no
339 * status. The box is unticked by default and gates the subscription
340 * server side; an unticked box sends nothing to the newsletter list.
341 */
342 subscribeSubmit: function () {
343 $(document).on('click', '.bdt-wizard-step[data-step="welcome"] .bdt-wizard-next', function () {
344 const $email = $('#bdt-subscribe-email');
345
346 if (!$email.length) {
347 return;
348 }
349
350 $.ajax({
351 url: UPK_SetupWizard.ajax_url,
352 type: 'POST',
353 data: {
354 action: 'ultimate_post_kit_setup_wizard_subscribe',
355 nonce: UPK_SetupWizard.nonce,
356 email: ($email.val() || '').trim(),
357 consent: $('#bdt-subscribe-consent').is(':checked') ? 'yes' : 'no'
358 }
359 });
360
361 // No preventDefault: the step change proceeds immediately.
362 });
363 },
364
365 saveSettingsSubmit: function () {
366 const vm = this;
367 $('#upk_setup_wizard_modules').submit(function (e) {
368 e.preventDefault();
369 var data = $(this).serialize();
370
371 // Get the button and store original text
372 const saveBtn = $(this).find('#save-and-continue');
373 const originalText = saveBtn.html().trim();
374
375 // Show loading state
376 saveBtn.prop('disabled', true)
377 .html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Saving...');
378
379 $.ajax({
380 url: UPK_SetupWizard.ajax_url,
381 type: 'POST',
382 data: data,
383 success: function (response) {
384 if (response.success) {
385 saveBtn.html('<i class="dashicons dashicons-yes-alt"></i> Saved!');
386 setTimeout(() => {
387 vm.goToStep(vm.currentStep + 1);
388 // Reset button state
389 saveBtn.prop('disabled', false).html(originalText);
390 }, 1000);
391 } else {
392 saveBtn.html('<i class="dashicons dashicons-no"></i> Failed');
393 setTimeout(() => {
394 saveBtn.prop('disabled', false).html(originalText);
395 }, 1000);
396 alert('Failed to save settings');
397 }
398 },
399 error: function (error) {
400 saveBtn.html('<i class="dashicons dashicons-no"></i> Error');
401 setTimeout(() => {
402 saveBtn.prop('disabled', false).html(originalText);
403 }, 1000);
404 console.error('Error:', error);
405 }
406 });
407 });
408 },
409
410 installPlugins: function () {
411 const vm = this;
412 $('#upk-install-plugins').submit(function (e) {
413 e.preventDefault();
414
415 vm.installButton.disabled = true;
416 vm.installButton.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Installing...';
417
418 const pluginSlugs = [];
419 const data = $(this).serialize();
420 data.split('&').forEach(item => {
421 const [key, value] = item.split('=');
422 if (key.startsWith('plugins') && value === 'on') {
423 const slug = decodeURIComponent(key.split('%5B%5D')[1]);
424 if (slug) {
425 pluginSlugs.push(slug);
426 }
427 }
428 });
429
430 let installedPlugins = 0;
431 const totalPluginsSlug = pluginSlugs.length;
432
433 let progressContainer = document.querySelector('.install-progress-container');
434 if (!progressContainer) {
435 progressContainer = document.createElement('div');
436 progressContainer.className = 'install-progress-container';
437 progressContainer.innerHTML = `
438 <div class="progress-bar-wrapper">
439 <div id="plugin-install-progress" class="progress-bar" style="width: 0%">0%</div>
440 </div>
441 <div class="install-status">Preparing to install plugins...</div>
442 `;
443 vm.installButton.parentNode.appendChild(progressContainer);
444 }
445
446 const progressBar = document.getElementById('plugin-install-progress');
447 const statusText = document.querySelector('.install-status');
448
449 const updateProgressBar = () => {
450 const progress = (installedPlugins / totalPluginsSlug) * 100;
451 progressBar.style.width = `${progress}%`;
452 progressBar.textContent = `${Math.round(progress)}%`;
453 statusText.textContent = `Installing plugin ${installedPlugins} of ${totalPluginsSlug}...`;
454 };
455
456 const installNextPlugin = () => {
457 if (installedPlugins < totalPluginsSlug) {
458 const slug = pluginSlugs[installedPlugins];
459 const pluginName = slug.split('/')[0].split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
460
461 statusText.textContent = `Installing ${pluginName}...`;
462
463 jQuery.ajax({
464 url: UPK_SetupWizard.ajax_url,
465 method: 'POST',
466 data: {
467 action: 'ultimate_post_kit_setup_wizard_install_plugins',
468 nonce: UPK_SetupWizard.nonce,
469 plugins: [slug]
470 },
471 success: (response) => {
472 if (response.success) {
473 installedPlugins++;
474 updateProgressBar();
475
476 statusText.innerHTML += ` <span class="success-indicator"><i class="dashicons dashicons-yes-alt"></i></span>`;
477
478 const pluginItem = document.querySelector(`[data-slug="${slug}"]`);
479 if (pluginItem) {
480 pluginItem.classList.add('plugin-installed');
481 }
482
483 setTimeout(() => {
484 installNextPlugin();
485 }, 500);
486 } else {
487 statusText.innerHTML += ` <span class="error-indicator"><i class="dashicons dashicons-no"></i> Failed</span>`;
488 installedPlugins++;
489 updateProgressBar();
490 setTimeout(() => {
491 installNextPlugin();
492 }, 500);
493 }
494 },
495 error: (error) => {
496 statusText.innerHTML += ` <span class="error-indicator"><i class="dashicons dashicons-no"></i> Error</span>`;
497 installedPlugins++;
498 updateProgressBar();
499 setTimeout(() => {
500 installNextPlugin();
501 }, 500);
502 }
503 });
504 } else {
505 statusText.textContent = 'All plugins installed successfully!';
506 statusText.innerHTML += ' <span class="success-indicator"><i class="dashicons dashicons-yes-alt"></i></span>';
507
508 setTimeout(() => {
509 vm.installButton.disabled = false;
510 vm.installButton.innerHTML = 'Installation Complete';
511 vm.goToStep(vm.currentStep + 1);
512 }, 1500);
513 }
514 };
515
516 installNextPlugin();
517 });
518 }
519 };
520
521 wizard.init();
522 });
523
524 // Handle template import button clicks
525 $('body').on('click', '.upk-setup-wizard .template-import', function (e) {
526 e.preventDefault();
527 e.stopPropagation();
528
529 const $button = $(this);
530 const $templateCard = $button.closest('.choose-template');
531 const importUrl = $templateCard.data('import-url');
532 const templateName = $templateCard.find('.template-title').text();
533
534 if (!importUrl) {
535 alert('Import URL not found');
536 return;
537 }
538
539 // Prevent multiple clicks
540 if ($button.prop('disabled')) {
541 return;
542 }
543
544 // Update button state
545 const originalButtonHtml = $button.html();
546 $button.prop('disabled', true)
547 .html('<i class="dashicons dashicons-update"></i> Importing...');
548
549 $templateCard.addClass('template-importing');
550 $templateCard.find('.template-title').html(`<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Importing ${templateName}...`);
551
552 // Determine import type based on template card classes
553 const isZipTemplate = $templateCard.hasClass('bdt-upk-import-temp-zip');
554 const isJsonTemplate = $templateCard.hasClass('bdt-upk-import-temp-json');
555
556 if (isJsonTemplate) {
557 // Handle JSON template import
558 $.ajax({
559 url: UPK_SetupWizard.ajax_url,
560 type: 'POST',
561 data: {
562 action: 'ultimate_post_kit_import_elementor_template',
563 nonce: UPK_SetupWizard.nonce,
564 import_url: importUrl
565 },
566 success: function(response) {
567 if (response.success) {
568 $button.removeClass('template-importing')
569 .addClass('template-imported')
570 .html('<i class="dashicons dashicons-yes-alt"></i> Imported');
571 $templateCard.removeClass('template-importing').addClass('template-imported');
572 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-yes-alt"></i> ${templateName} Imported`);
573 } else {
574 $button.removeClass('template-importing')
575 .addClass('template-import-failed')
576 .html('<i class="dashicons dashicons-no"></i> Failed');
577 $templateCard.removeClass('template-importing').addClass('template-import-failed');
578 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-no"></i> Import Failed`);
579
580 // Reset button after 3 seconds
581 setTimeout(() => {
582 $button.prop('disabled', false)
583 .removeClass('template-import-failed')
584 .html(originalButtonHtml);
585 }, 3000);
586 }
587 },
588 error: function() {
589 $button.removeClass('template-importing')
590 .addClass('template-import-failed')
591 .html('<i class="dashicons dashicons-no"></i> Failed');
592 $templateCard.removeClass('template-importing').addClass('template-import-failed');
593 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-no"></i> Import Failed`);
594
595 // Reset button after 3 seconds
596 setTimeout(() => {
597 $button.prop('disabled', false)
598 .removeClass('template-import-failed')
599 .html(originalButtonHtml);
600 }, 3000);
601 }
602 });
603 } else if (isZipTemplate) {
604 // Handle ZIP template import
605 $.ajax({
606 url: UPK_SetupWizard.ajax_url,
607 type: 'POST',
608 data: {
609 action: 'ultimate_post_kit_import_elementor_bundle_template',
610 nonce: UPK_SetupWizard.nonce,
611 import_url: importUrl
612 },
613 success: async function(response) {
614 if (response.success) {
615 const sessionId = response.data.session;
616 const runners = response?.data?.runners;
617 let error = '';
618
619 for (const runner of runners) {
620 const success = await importRunner(sessionId, runner);
621 if (!success) {
622 error = `❌ Failed to import: ${runner}`;
623 break;
624 }
625 }
626
627 if (error) {
628 $button.removeClass('template-importing')
629 .addClass('template-import-failed')
630 .html('<i class="dashicons dashicons-no"></i> Failed');
631 $templateCard.removeClass('template-importing').addClass('template-import-failed');
632 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-no"></i> ${error}`);
633 alert(error);
634
635 // Reset button after 3 seconds
636 setTimeout(() => {
637 $button.prop('disabled', false)
638 .removeClass('template-import-failed')
639 .html(originalButtonHtml);
640 }, 3000);
641 return;
642 }
643
644 $button.removeClass('template-importing')
645 .addClass('template-imported')
646 .html('<i class="dashicons dashicons-yes-alt"></i> Imported');
647 $templateCard.removeClass('template-importing').addClass('template-imported');
648 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-yes-alt"></i> ${templateName} Imported`);
649 } else {
650 $button.removeClass('template-importing')
651 .addClass('template-import-failed')
652 .html('<i class="dashicons dashicons-no"></i> Failed');
653 $templateCard.removeClass('template-importing').addClass('template-import-failed');
654 const missingPlugins = response?.data?.plugins;
655 if (missingPlugins) {
656 let pluginArr = [];
657 for (const plugin of missingPlugins) {
658 pluginArr.push(plugin.name);
659 }
660 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-no"></i> ${"plugins are required to import: " + pluginArr.join(', ')}`);
661 } else {
662 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-no"></i> ${response.data.message}`);
663 }
664
665 // Reset button after 3 seconds
666 setTimeout(() => {
667 $button.prop('disabled', false)
668 .removeClass('template-import-failed')
669 .html(originalButtonHtml);
670 }, 3000);
671 }
672 },
673 error: function() {
674 $button.removeClass('template-importing')
675 .addClass('template-import-failed')
676 .html('<i class="dashicons dashicons-no"></i> Failed');
677 $templateCard.removeClass('template-importing').addClass('template-import-failed');
678 $templateCard.find('.template-title').html(`<i class="dashicons dashicons-no"></i> Import Failed`);
679
680 // Reset button after 3 seconds
681 setTimeout(() => {
682 $button.prop('disabled', false)
683 .removeClass('template-import-failed')
684 .html(originalButtonHtml);
685 }, 3000);
686 }
687 });
688 } else {
689 // Unsupported template type
690 alert('Unsupported template format');
691 $button.prop('disabled', false).html(originalButtonHtml);
692 $templateCard.removeClass('template-importing');
693 }
694 });
695
696 async function importRunner(sessionId, runner) {
697 try {
698 const response = await new Promise((resolve, reject) => {
699 $.ajax({
700 url: UPK_SetupWizard.ajax_url, type: 'POST', data: {
701 action: 'ultimate_post_kit_import_elementor_bundle_runner_template',
702 nonce: UPK_SetupWizard.nonce,
703 sessionId: sessionId,
704 runner: runner,
705 }, success: resolve, error: reject
706 })
707 });
708
709 return response.success;
710 } catch (error) {
711 console.error('AJAX Error:', error);
712 return false;
713 }
714 }
715
716 })(jQuery);
717
718 document.addEventListener('DOMContentLoaded', function() {
719 const style = document.createElement('style');
720 style.textContent = `
721 .bdt-wizard-step {
722 transition: opacity 0.3s ease, transform 0.3s ease;
723 display: none; /* Hide all steps by default */
724 }
725
726 .bdt-wizard-step.active {
727 display: block; /* Show only active step */
728 opacity: 1;
729 transform: translateY(0);
730 }
731
732 .item-highlight {
733 transition: all 0.3s ease;
734 box-shadow: 0 0 0 2px var(--upk-primary);
735 transform: translateY(-3px);
736 }
737
738 .button-pulse {
739 animation: buttonPulse 0.5s ease;
740 }
741
742 .pulse-animation {
743 animation: pulse 1.5s infinite;
744 }
745
746 /* Spinner for plugin installation and template importing */
747 .spinner {
748 display: inline-block;
749 width: 16px;
750 height: 16px;
751 border: 2px solid rgba(255,255,255,0.3);
752 border-radius: 50%;
753 border-top-color: #fff;
754 animation: spin 1s linear infinite;
755 margin-right: 8px;
756 }
757
758 /* Plugin installation progress styles */
759 .install-progress-container {
760 margin-top: 20px;
761 padding: 15px;
762 background: var(--upk-gray-light);
763 border-radius: var(--upk-border-radius);
764 }
765
766 .progress-bar-wrapper {
767 height: 8px;
768 background: var(--upk-gray-medium);
769 border-radius: 4px;
770 overflow: hidden;
771 margin-bottom: 10px;
772 }
773
774 .progress-bar {
775 height: 100%;
776 background: var(--upk-primary);
777 border-radius: 4px;
778 transition: width 0.3s ease;
779 color: transparent;
780 font-size: 0;
781 }
782
783 .install-status {
784 font-size: 14px;
785 color: var(--upk-text-light);
786 }
787
788 .success-indicator {
789 color: var(--upk-success);
790 }
791
792 .error-indicator {
793 color: var(--upk-danger);
794 }
795
796 .plugin-installed {
797 border-color: var(--upk-success) !important;
798 }
799
800 /* Template import states */
801 .template-importing {
802 opacity: 0.7;
803 pointer-events: none;
804 }
805
806 .template-imported {
807 border-color: var(--upk-success) !important;
808 }
809
810 .template-import-failed {
811 border-color: var(--upk-danger) !important;
812 }
813
814 /* Template import button states */
815 .template-import:disabled {
816 cursor: not-allowed;
817 }
818
819 .template-import.template-imported {
820 background-color: #28a745;
821 border-color: #28a745;
822 color: white;
823 }
824
825 .template-import.template-import-failed {
826 background-color: #dc3545;
827 border-color: #dc3545;
828 color: white;
829 }
830
831 /* Animations */
832 @keyframes buttonPulse {
833 0%, 100% { transform: scale(1); }
834 50% { transform: scale(1.05); }
835 }
836
837 @keyframes pulse {
838 0% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0.4); }
839 70% { box-shadow: 0 0 0 10px rgba(108, 92, 231, 0); }
840 100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0); }
841 }
842
843 @keyframes spin {
844 0% { transform: rotate(0deg); }
845 100% { transform: rotate(360deg); }
846 }
847 `;
848 document.head.appendChild(style);
849 });
850