PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.8.0
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.8.0
8.8.0 8.7.9 8.7.8 8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 8.5.5 All 536 releases
← All changes | includes/admin/templates/wizard-popup.php +784 -784 8.5.9 → 8.8.0 View file →
@@ -1,784 +1,784 @@
1 -<?php
2 -/**
3 - * AI Setup Wizard Popup Template
4 - * Scoped styling and JS to avoid collision.
5 - */
6 -if ( ! defined( 'ABSPATH' ) ) {
7 - exit;
8 -}
9 -
10 -// Get all custom post types for Step 7
11 -$custom_post_types = get_post_types( array( 'public' => true, '_builtin' => false ), 'objects' );
12 -$show_wizard_automatically = isset( $show_wizard_automatically ) ? $show_wizard_automatically : false;
13 -?>
14 -<div id="wpbot-wizard-overlay" class="wpbot-wizard-overlay">
15 - <div class="wpbot-wizard-modal">
16 - <!-- Progress Bar -->
17 - <div class="wpbot-wizard-progress-container">
18 - <div id="wpbot-wizard-progress-bar" class="wpbot-wizard-progress-bar" style="width: 25%;"></div>
19 - </div>
20 -
21 - <div class="wpbot-wizard-header">
22 - <h2 class="wpbot-wizard-title">AI Setup Wizard</h2>
23 - <p class="wpbot-wizard-subtitle">Quickly configure your AI Chatbot in a few steps</p>
24 - <button type="button" class="wpbot-wizard-close-btn" id="wpbot-wizard-close">&times;</button>
25 - </div>
26 -
27 - <div class="wpbot-wizard-body">
28 - <form id="wpbot-wizard-form">
29 - <!-- Step 1: Select AI Service -->
30 - <div class="wpbot-wizard-step active" data-step="1">
31 - <h3>Step 1: Choose your AI Service</h3>
32 - <p class="wpbot-step-desc">Select which artificial intelligence provider you want to power your chatbot responses.</p>
33 - <div class="wpbot-wizard-field">
34 - <label for="wizard_ai_provider">AI Provider</label>
35 - <select id="wizard_ai_provider" name="ai_provider" class="wpbot-wizard-select">
36 - <option value="openai">OpenAI</option>
37 - <option value="gemini">Gemini</option>
38 - <option value="grok">Grok</option>
39 - <option value="openrouter">OpenRouter</option>
40 - </select>
41 - </div>
42 - </div>
43 -
44 - <!-- Step 2: Setup API Key -->
45 - <div class="wpbot-wizard-step" data-step="2">
46 - <h3>Step 2: API Credentials</h3>
47 - <p class="wpbot-step-desc" id="wizard_credentials_desc">Configure the connection credentials for your selected AI service.</p>
48 -
49 - <!-- API Key Input (for standard providers) -->
50 - <div class="wpbot-wizard-field" id="wizard_api_key_container">
51 - <label for="wizard_api_key" id="wizard_api_key_label">API Key</label>
52 - <input type="password" id="wizard_api_key" name="api_key" class="wpbot-wizard-input" placeholder="sk-..." />
53 - <p class="wpbot-field-help" id="wizard_api_key_help">Requires an active key from your provider.</p>
54 - <p class="wpbot-field-help" id="wizard_api_key_paid_note" style="color: #ef4444; font-weight: 600; margin-top: 8px;">Note: A Paid API key is required.</p>
55 - </div>
56 -
57 - <!-- API verification status elements -->
58 - <div id="wizard-api-loader" style="display: none; margin-top: 15px; text-align: center; color: #ffffff;">
59 - <div class="wpbot-spinner" style="display: inline-block; width: 24px; height: 24px; border: 3px solid rgba(255,255,255,0.1); border-radius: 50%; border-top-color: #6366f1; animation: wpbotSpin 1s ease-in-out infinite; margin-right: 8px; vertical-align: middle;"></div>
60 - <span style="font-size: 14px; font-weight: 500; vertical-align: middle;">Verifying API Connection...</span>
61 - </div>
62 - <div id="wizard-api-error" style="display: none; margin-top: 15px; padding: 12px; background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.3); border-radius: 8px; color: #f87171; font-size: 13px; line-height: 1.4;">
63 - </div>
64 - </div>
65 -
66 - <!-- Step 3: Content Sources for Vector Embedding -->
67 - <div class="wpbot-wizard-step" data-step="3">
68 - <h3>Step 3: Content Sources for Vector Embedding</h3>
69 - <p class="wpbot-step-desc">Select which content types should be automatically prepared for the RAG search database.</p>
70 -
71 - <div class="wpbot-wizard-field checkbox-inline-field">
72 - <label class="wpbot-checkbox-container">
73 - <input type="checkbox" name="rag_embed_pages" value="1" checked />
74 - <span class="wpbot-checkmark"></span>
75 - Pages
76 - </label>
77 - </div>
78 -
79 - <div class="wpbot-wizard-field checkbox-inline-field">
80 - <label class="wpbot-checkbox-container">
81 - <input type="checkbox" name="rag_embed_posts" value="1" checked />
82 - <span class="wpbot-checkmark"></span>
83 - Posts
84 - </label>
85 - </div>
86 -
87 - <?php if ( ! empty( $custom_post_types ) ) : ?>
88 - <div class="wpbot-wizard-field">
89 - <label style="margin-bottom: 8px; display: block; font-weight: 500; color: #e2e8f0;">Custom Post Types</label>
90 - <div class="wpbot-wizard-cpt-list">
91 - <?php foreach ( $custom_post_types as $cpt ) : ?>
92 - <label class="wpbot-checkbox-container">
93 - <input type="checkbox" name="rag_embed_cpts[]" value="<?php echo esc_attr( $cpt->name ); ?>" />
94 - <span class="wpbot-checkmark"></span>
95 - <?php echo esc_html( $cpt->label ); ?>
96 - </label>
97 - <?php endforeach; ?>
98 - </div>
99 - </div>
100 - <?php endif; ?>
101 -
102 - <!-- Preloader for Embedding -->
103 - <div id="wizard-embed-preloader" style="display: none; margin-top: 24px; padding: 20px; background: rgba(15, 23, 42, 0.4); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 12px;">
104 - <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
105 - <span style="font-weight: 600; color: #ffffff;">Vectorizing Content...</span>
106 - <span id="wizard-embed-percent" style="font-weight: 600; color: #a855f7;">0%</span>
107 - </div>
108 - <div style="height: 8px; background: rgba(255,255,255,0.05); border-radius: 4px; overflow: hidden; margin-bottom: 12px;">
109 - <div id="wizard-embed-progress-bar" style="width: 0%; height: 100%; background: linear-gradient(90deg, #6366f1, #a855f7); transition: width 0.2s ease;"></div>
110 - </div>
111 - <div style="display: flex; align-items: center; color: #cbd5e1; font-size: 13px;">
112 - <div class="wpbot-spinner" style="display: inline-block; width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.1); border-radius: 50%; border-top-color: #a855f7; animation: wpbotSpin 1s ease-in-out infinite; margin-right: 8px; flex-shrink: 0; vertical-align: middle;"></div>
113 - <span id="wizard-embed-status" style="vertical-align: middle;">Preparing queue...</span>
114 - </div>
115 - </div>
116 - </div>
117 -
118 - <!-- Step 4: Completion Screen -->
119 - <div class="wpbot-wizard-step" data-step="4">
120 - <div style="text-align: center; padding: 20px 0;">
121 - <div style="font-size: 60px; line-height: 1; margin-bottom: 20px; color: #10b981;">🎉</div>
122 - <h3 style="color: #ffffff; font-size: 22px; font-weight: 600; margin-bottom: 12px;">Congratulations!</h3>
123 - <p id="wizard-embed-success-msg" style="color: #10b981; font-weight: 600; font-size: 16px; margin-top: 10px; margin-bottom: 20px; display: none;">
124 - We have Embedded <span id="wizard-embed-count">0</span> post types successfully
125 - </p>
126 - <p class="wpbot-step-desc" style="font-size: 15px; line-height: 1.6; color: #cbd5e1; max-width: 480px; margin: 0 auto 20px;">
127 - Now your Chatbot is trained with your website data. You can upload additional training documents from AI Settings -> Knowledge base.
128 - </p>
129 - </div>
130 - </div>
131 - </form>
132 - </div>
133 -
134 - <div class="wpbot-wizard-footer">
135 - <button type="button" class="wpbot-wizard-btn wpbot-wizard-btn-skip" id="wpbot-wizard-skip">Skip Setup</button>
136 - <div class="wpbot-wizard-nav-btns">
137 - <button type="button" class="wpbot-wizard-btn wpbot-wizard-btn-back" id="wpbot-wizard-back" disabled>Back</button>
138 - <button type="button" class="wpbot-wizard-btn wpbot-wizard-btn-next" id="wpbot-wizard-next">Next</button>
139 - </div>
140 - </div>
141 - </div>
142 -</div>
143 -
144 -<style>
145 -/* Premium Dark Glassmorphism Styling */
146 -.wpbot-wizard-overlay {
147 - position: fixed;
148 - top: 0;
149 - left: 0;
150 - width: 100vw;
151 - height: 100vh;
152 - background: rgba(15, 23, 42, 0.75);
153 - backdrop-filter: blur(12px);
154 - -webkit-backdrop-filter: blur(12px);
155 - z-index: 999999;
156 - display: none;
157 - align-items: center;
158 - justify-content: center;
159 - color: #f8fafc;
160 - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
161 - animation: wpbotFadeIn 0.3s ease forwards;
162 -}
163 -
164 -.wpbot-wizard-modal {
165 - background: rgba(30, 41, 59, 0.95);
166 - border: 1px solid rgba(255, 255, 255, 0.1);
167 - border-radius: 20px;
168 - width: 90%;
169 - max-width: 600px;
170 - box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
171 - overflow: hidden;
172 - position: relative;
173 - display: flex;
174 - flex-direction: column;
175 - max-height: 85vh;
176 - animation: wpbotScaleIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
177 -}
178 -
179 -/* Progress bar styling */
180 -.wpbot-wizard-progress-container {
181 - height: 6px;
182 - background: rgba(255, 255, 255, 0.05);
183 - width: 100%;
184 -}
185 -.wpbot-wizard-progress-bar {
186 - height: 100%;
187 - background: linear-gradient(90deg, #6366f1, #a855f7);
188 - transition: width 0.3s ease;
189 -}
190 -
191 -/* Header */
192 -.wpbot-wizard-header {
193 - padding: 28px 36px 20px;
194 - border-bottom: 1px solid rgba(255, 255, 255, 0.08);
195 - position: relative;
196 -}
197 -.wpbot-wizard-title {
198 - font-size: 24px;
199 - font-weight: 700;
200 - margin: 0 0 6px;
201 - color: #ffffff;
202 - background: linear-gradient(to right, #6366f1, #a855f7);
203 - -webkit-background-clip: text;
204 - -webkit-text-fill-color: transparent;
205 - display: inline-block;
206 -}
207 -.wpbot-wizard-subtitle {
208 - font-size: 14px;
209 - color: #94a3b8;
210 - margin: 0;
211 -}
212 -.wpbot-wizard-close-btn {
213 - position: absolute;
214 - top: 28px;
215 - right: 36px;
216 - background: none;
217 - border: none;
218 - color: #94a3b8;
219 - font-size: 28px;
220 - cursor: pointer;
221 - line-height: 1;
222 - padding: 0;
223 - transition: color 0.2s, transform 0.2s;
224 -}
225 -.wpbot-wizard-close-btn:hover {
226 - color: #ffffff;
227 - transform: scale(1.1);
228 -}
229 -
230 -/* Body and Steps */
231 -.wpbot-wizard-body {
232 - padding: 36px;
233 - overflow-y: auto;
234 - flex: 1;
235 -}
236 -.wpbot-wizard-step {
237 - display: none;
238 - animation: wpbotSlideIn 0.3s ease forwards;
239 -}
240 -.wpbot-wizard-step.active {
241 - display: block;
242 -}
243 -.wpbot-wizard-step h3 {
244 - font-size: 20px;
245 - color: #ffffff;
246 - margin: 0 0 10px;
247 - font-weight: 600;
248 -}
249 -.wpbot-step-desc {
250 - font-size: 14px;
251 - color: #94a3b8;
252 - margin: 0 0 28px;
253 - line-height: 1.6;
254 -}
255 -
256 -/* Form Fields */
257 -.wpbot-wizard-field {
258 - margin-bottom: 20px;
259 -}
260 -.wpbot-wizard-field label {
261 - display: block;
262 - font-size: 14px;
263 - color: #e2e8f0;
264 - margin-bottom: 8px;
265 - font-weight: 500;
266 -}
267 -.wpbot-wizard-input,
268 -.wpbot-wizard-select {
269 - width: 100%;
270 - background: rgba(15, 23, 42, 0.6);
271 - border: 1px solid rgba(255, 255, 255, 0.1);
272 - border-radius: 10px;
273 - padding: 12px 16px;
274 - color: #ffffff;
275 - font-size: 14px;
276 - box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
277 - box-sizing: border-box;
278 - transition: border-color 0.2s, box-shadow 0.2s;
279 -}
280 -.wpbot-wizard-input:focus,
281 -.wpbot-wizard-select:focus {
282 - border-color: #6366f1;
283 - outline: none;
284 - box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.35);
285 -}
286 -.wpbot-wizard-select option {
287 - background: #1e293b;
288 - color: #ffffff;
289 -}
290 -.wpbot-field-help {
291 - font-size: 12px;
292 - color: #94a3b8;
293 - margin: 6px 0 0;
294 -}
295 -
296 -/* Custom Checkbox Container */
297 -.wpbot-checkbox-container {
298 - display: inline-flex;
299 - align-items: center;
300 - position: relative;
301 - padding-left: 28px;
302 - cursor: pointer;
303 - font-size: 14px;
304 - user-select: none;
305 - color: #cbd5e1;
306 -}
307 -.wpbot-checkbox-container input {
308 - position: absolute;
309 - opacity: 0;
310 - cursor: pointer;
311 - height: 0;
312 - width: 0;
313 -}
314 -.wpbot-checkmark {
315 - position: absolute;
316 - top: 50%;
317 - left: 0;
318 - transform: translateY(-50%);
319 - height: 18px;
320 - width: 18px;
321 - background-color: rgba(255, 255, 255, 0.1);
322 - border: 1px solid rgba(255, 255, 255, 0.15);
323 - border-radius: 4px;
324 - transition: all 0.2s;
325 -}
326 -.wpbot-checkbox-container:hover input ~ .wpbot-checkmark {
327 - background-color: rgba(255, 255, 255, 0.15);
328 -}
329 -.wpbot-checkbox-container input:checked ~ .wpbot-checkmark {
330 - background-color: #6366f1;
331 - border-color: #6366f1;
332 -}
333 -.wpbot-checkmark:after {
334 - content: "";
335 - position: absolute;
336 - display: none;
337 -}
338 -.wpbot-checkbox-container input:checked ~ .wpbot-checkmark:after {
339 - display: block;
340 -}
341 -.wpbot-checkbox-container .wpbot-checkmark:after {
342 - left: 5px;
343 - top: 2px;
344 - width: 5px;
345 - height: 9px;
346 - border: solid white;
347 - border-width: 0 2px 2px 0;
348 - transform: rotate(45deg);
349 -}
350 -
351 -.wpbot-wizard-cpt-list {
352 - display: grid;
353 - grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
354 - gap: 12px;
355 - background: rgba(0, 0, 0, 0.2);
356 - border-radius: 8px;
357 - padding: 16px;
358 - margin-top: 8px;
359 -}
360 -
361 -/* Footer & Buttons */
362 -.wpbot-wizard-footer {
363 - padding: 24px 36px;
364 - border-top: 1px solid rgba(255, 255, 255, 0.08);
365 - display: flex;
366 - justify-content: space-between;
367 - align-items: center;
368 - background: rgba(15, 23, 42, 0.4);
369 -}
370 -.wpbot-wizard-btn {
371 - border: none;
372 - border-radius: 8px;
373 - padding: 10px 20px;
374 - font-size: 14px;
375 - font-weight: 500;
376 - cursor: pointer;
377 - transition: all 0.2s;
378 -}
379 -.wpbot-wizard-btn-skip {
380 - background: transparent;
381 - color: #94a3b8;
382 -}
383 -.wpbot-wizard-btn-skip:hover {
384 - color: #ffffff;
385 -}
386 -.wpbot-wizard-nav-btns {
387 - display: flex;
388 - gap: 12px;
389 -}
390 -.wpbot-wizard-btn-back {
391 - background: rgba(255, 255, 255, 0.05);
392 - color: #e2e8f0;
393 - border: 1px solid rgba(255, 255, 255, 0.08);
394 -}
395 -.wpbot-wizard-btn-back:hover:not(:disabled) {
396 - background: rgba(255, 255, 255, 0.1);
397 -}
398 -.wpbot-wizard-btn-back:disabled {
399 - opacity: 0.5;
400 - cursor: not-allowed;
401 -}
402 -.wpbot-wizard-btn-next {
403 - background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
404 - color: #ffffff;
405 - box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
406 -}
407 -.wpbot-wizard-btn-next:hover {
408 - transform: translateY(-1px);
409 - box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);
410 -}
411 -
412 -/* Animations */
413 -@keyframes wpbotFadeIn {
414 - from { opacity: 0; }
415 - to { opacity: 1; }
416 -}
417 -@keyframes wpbotScaleIn {
418 - from { transform: scale(0.95); opacity: 0; }
419 - to { transform: scale(1); opacity: 1; }
420 -}
421 -@keyframes wpbotSlideIn {
422 - from { transform: translateY(10px); opacity: 0; }
423 - to { transform: translateY(0); opacity: 1; }
424 -}
425 -@keyframes wpbotSpin {
426 - to { transform: rotate(360deg); }
427 -}
428 -</style>
429 -
430 -<script>
431 -jQuery(document).ready(function($) {
432 - // Move overlay to body to prevent viewport container centering bugs in WP Admin
433 - $('body').append($('#wpbot-wizard-overlay'));
434 -
435 - var currentStep = 1;
436 - var totalSteps = 4;
437 -
438 - // Auto open wizard logic
439 - var wpbot_auto_open_wizard = <?php echo $show_wizard_automatically ? 'true' : 'false'; ?>;
440 - if (wpbot_auto_open_wizard && sessionStorage.getItem('wpbot_wizard_skipped') !== '1') {
441 - $('#wpbot-wizard-overlay').css({ display: 'flex', opacity: 1 });
442 - }
443 -
444 - // Trigger wizard from settings page button
445 - $(document).on('click', '#wpbot-trigger-wizard', function(e) {
446 - e.preventDefault();
447 - goToStep(1);
448 - $('#wpbot-wizard-overlay')
449 - .css({ display: 'flex', opacity: 0 })
450 - .animate({ opacity: 1 }, 300);
451 - });
452 -
453 - // Provider detail configuration
454 - var providerConfig = {
455 - openai: {
456 - label: "OpenAI API Key",
457 - placeholder: "sk-...",
458 - help: "Requires an active key from https://platform.openai.com/settings/organization/api-keys."
459 - },
460 - gemini: {
461 - label: "Gemini API Key",
462 - placeholder: "Enter Gemini API Key",
463 - help: "Requires an active key from https://aistudio.google.com/app/api-keys."
464 - },
465 - grok: {
466 - label: "Grok API Key",
467 - placeholder: "xai-...",
468 - help: "Requires an API key from https://console.x.ai/"
469 - },
470 - openrouter: {
471 - label: "OpenRouter API Key",
472 - placeholder: "sk-or-v1-...",
473 - help: "Requires an API key from https://openrouter.ai/workspaces/default/keys."
474 - }
475 - };
476 -
477 - // Handle Provider change to adjust step 2 credentials UI
478 - $('#wizard_ai_provider').on('change', function() {
479 - var selected = $(this).val();
480 - $('#wizard_credentials_desc').text("Configure the API connection credentials for " + $(this).find('option:selected').text() + ".");
481 -
482 - var config = providerConfig[selected];
483 - if (config) {
484 - $('#wizard_api_key_label').text(config.label);
485 - $('#wizard_api_key').attr('placeholder', config.placeholder);
486 - $('#wizard_api_key_help').text(config.help);
487 - }
488 - }).trigger('change');
489 -
490 - // Dismiss wizard logic
491 - function dismissWizard() {
492 - $('#wpbot-wizard-overlay').animate({ opacity: 0 }, 300, function() {
493 - $(this).css('display', 'none');
494 - });
495 - }
496 -
497 - // Go to step helper function
498 - function goToStep(step) {
499 - $('.wpbot-wizard-step').removeClass('active');
500 - currentStep = step;
501 - $('.wpbot-wizard-step[data-step="' + currentStep + '"]').addClass('active');
502 -
503 - // Progress bar animation
504 - var pct = (currentStep / totalSteps) * 100;
505 - $('#wpbot-wizard-progress-bar').css('width', pct + '%');
506 -
507 - // Enable/disable back button
508 - if (currentStep === 1) {
509 - $('#wpbot-wizard-back').prop('disabled', true);
510 - } else {
511 - $('#wpbot-wizard-back').prop('disabled', false);
512 - }
513 -
514 - // Button texts & visibility adjustments
515 - if (currentStep === 3) {
516 - $('#wpbot-wizard-next').text('Finish');
517 - $('#wpbot-wizard-skip').show();
518 - $('#wpbot-wizard-back').show();
519 - } else if (currentStep === 4) {
520 - $('#wpbot-wizard-next').text('Finish Setup');
521 - $('#wpbot-wizard-back').hide();
522 - $('#wpbot-wizard-skip').hide();
523 - // Auto-disable Site Search when wizard completes
524 - $('#disable_wp_chatbot_site_search').prop('checked', true);
525 - } else {
526 - $('#wpbot-wizard-next').text('Next');
527 - $('#wpbot-wizard-skip').show();
528 - $('#wpbot-wizard-back').show();
529 - }
530 - }
531 -
532 - // Save options via AJAX
533 - function saveWizardData(isSkipped) {
534 - var formData = {
535 - action: 'wpbot_wizard_save',
536 - nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>',
537 - is_skipped: isSkipped ? 1 : 0
538 - };
539 -
540 - if (!isSkipped) {
541 - // Serialize form data
542 - var serialized = $('#wpbot-wizard-form').serializeArray();
543 - $.each(serialized, function(i, field) {
544 - if (field.name.endsWith('[]')) {
545 - var cleanName = field.name.slice(0, -2);
546 - if (!formData[cleanName]) {
547 - formData[cleanName] = [];
548 - }
549 - formData[cleanName].push(field.value);
550 - } else {
551 - formData[field.name] = field.value;
552 - }
553 - });
554 -
555 - // Handle checkbox values explicitly
556 - formData.rag_embed_pages = $('input[name="rag_embed_pages"]').is(':checked') ? 1 : 0;
557 - formData.rag_embed_posts = $('input[name="rag_embed_posts"]').is(':checked') ? 1 : 0;
558 - }
559 -
560 - // Disable all buttons in footer during save
561 - $('.wpbot-wizard-footer button').prop('disabled', true);
562 - if (!isSkipped) {
563 - $('#wpbot-wizard-next').text('Saving...');
564 - }
565 -
566 - $.ajax({
567 - url: ajaxurl,
568 - type: 'POST',
569 - data: formData,
570 - success: function(response) {
571 - if (response.success) {
572 - if (isSkipped) {
573 - dismissWizard();
574 - location.reload();
575 - } else {
576 - startWizardEmbedding();
577 - }
578 - } else {
579 - alert(response.data || 'Failed to save settings. Please try again.');
580 - $('.wpbot-wizard-footer button').prop('disabled', false);
581 - $('#wpbot-wizard-next').text('Finish');
582 - }
583 - },
584 - error: function() {
585 - alert('An error occurred. Please try again.');
586 - $('.wpbot-wizard-footer button').prop('disabled', false);
587 - $('#wpbot-wizard-next').text('Finish');
588 - }
589 - });
590 - }
591 -
592 - function startWizardEmbedding() {
593 - // Show preloader
594 - $('#wizard-embed-preloader').slideDown();
595 -
596 - // Disable all controls
597 - $('.wpbot-wizard-footer button').prop('disabled', true);
598 - $('#wpbot-wizard-close').prop('disabled', true);
599 - $('#wpbot-wizard-next').text('Embedding...');
600 -
601 - $('#wizard-embed-percent').text('0%');
602 - $('#wizard-embed-progress-bar').css('width', '0%');
603 - $('#wizard-embed-status').text('Preparing embedding queue...');
604 -
605 - // Fetch the queue of items to embed
606 - $.ajax({
607 - url: ajaxurl,
608 - type: 'POST',
609 - data: {
610 - action: 'qcld_rag_get_embed_queue',
611 - nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>'
612 - },
613 - success: function(response) {
614 - if (response.success) {
615 - var queue = response.data;
616 - if (!queue || queue.length === 0) {
617 - // No items to embed
618 - $('#wizard-embed-status').text('No items found to embed.');
619 - setTimeout(function() {
620 - $('#wizard-embed-count').text('0');
621 - $('#wizard-embed-success-msg').show();
622 - goToStep(4);
623 - $('.wpbot-wizard-footer button').prop('disabled', false);
624 - $('#wpbot-wizard-close').prop('disabled', false);
625 - }, 1000);
626 - return;
627 - }
628 -
629 - $('#wizard-embed-status').text('Processing 0 / ' + queue.length + ' items...');
630 - processWizardEmbedQueue(queue, 0, 0);
631 - } else {
632 - alert('Failed to fetch the embedding queue. Moving to next step.');
633 - $('#wizard-embed-count').text('0');
634 - $('#wizard-embed-success-msg').show();
635 - goToStep(4);
636 - $('.wpbot-wizard-footer button').prop('disabled', false);
637 - $('#wpbot-wizard-close').prop('disabled', false);
638 - }
639 - },
640 - error: function() {
641 - alert('An error occurred while fetching the embedding queue. Moving to next step.');
642 - $('#wizard-embed-count').text('0');
643 - $('#wizard-embed-success-msg').show();
644 - goToStep(4);
645 - $('.wpbot-wizard-footer button').prop('disabled', false);
646 - $('#wpbot-wizard-close').prop('disabled', false);
647 - }
648 - });
649 - }
650 -
651 - function processWizardEmbedQueue(queue, index, successCount) {
652 - if (index >= queue.length) {
653 - $('#wizard-embed-status').text('Embedding complete! Total processed: ' + successCount + ' / ' + queue.length);
654 - setTimeout(function() {
655 - $('#wizard-embed-count').text(successCount);
656 - $('#wizard-embed-success-msg').show();
657 - goToStep(4);
658 - $('.wpbot-wizard-footer button').prop('disabled', false);
659 - $('#wpbot-wizard-close').prop('disabled', false);
660 - }, 1000);
661 - return;
662 - }
663 -
664 - var item = queue[index];
665 - var progress = Math.round(((index + 1) / queue.length) * 100);
666 -
667 - $('#wizard-embed-status').text('Embedding document (' + (index + 1) + ' / ' + queue.length + ')...');
668 - $('#wizard-embed-progress-bar').css('width', progress + '%');
669 - $('#wizard-embed-percent').text(progress + '%');
670 -
671 - $.ajax({
672 - url: ajaxurl,
673 - type: 'POST',
674 - data: {
675 - action: 'qcld_rag_process_item',
676 - nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>',
677 - item_id: item.id,
678 - item_type: item.type
679 - },
680 - success: function(response) {
681 - // We consider either a successful return or skip as a processed item
682 - var increment = 0;
683 - if (response.success) {
684 - increment = 1;
685 - }
686 - processWizardEmbedQueue(queue, index + 1, successCount + increment);
687 - },
688 - error: function() {
689 - // Continue to next item on failure, so wizard doesn't hang
690 - processWizardEmbedQueue(queue, index + 1, successCount);
691 - }
692 - });
693 - }
694 -
695 - // Skip Button Click
696 - $('#wpbot-wizard-skip, #wpbot-wizard-close').on('click', function(e) {
697 - e.preventDefault();
698 - if (currentStep === 4) {
699 - dismissWizard();
700 - location.reload();
701 - return;
702 - }
703 - if (confirm('Are you sure you want to skip the setup wizard? you can set up these configurations manually inside the settings panel.')) {
704 - sessionStorage.setItem('wpbot_wizard_skipped', '1');
705 - dismissWizard();
706 - }
707 - });
708 -
709 - // Next Button Click
710 - $('#wpbot-wizard-next').on('click', function(e) {
711 - e.preventDefault();
712 -
713 - // If we are on Step 4 (Congratulations), clicking Next should close and reload.
714 - if (currentStep === 4) {
715 - // Ensure Site Search is disabled before closing
716 - $('#disable_wp_chatbot_site_search').prop('checked', true);
717 - dismissWizard();
718 - location.reload();
719 - return;
720 - }
721 -
722 - // Basic Validation for credentials step (Step 2) and AJAX verification
723 - if (currentStep === 2) {
724 - var provider = $('#wizard_ai_provider').val();
725 - var apiKey = $('#wizard_api_key').val().trim();
726 -
727 - if (apiKey === '') {
728 - alert('Please enter your API Key before continuing.');
729 - return;
730 - }
731 -
732 - // Show loader and hide old error
733 - $('#wizard-api-loader').show();
734 - $('#wizard-api-error').hide();
735 - $('.wpbot-wizard-footer button').prop('disabled', true);
736 -
737 - $.ajax({
738 - url: ajaxurl,
739 - type: 'POST',
740 - data: {
741 - action: 'wpbot_wizard_verify_key',
742 - nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>',
743 - ai_provider: provider,
744 - api_key: apiKey
745 - },
746 - success: function(response) {
747 - $('#wizard-api-loader').hide();
748 - $('.wpbot-wizard-footer button').prop('disabled', false);
749 -
750 - if (response.success) {
751 - goToStep(3);
752 - } else {
753 - $('#wizard-api-error').text(response.data || 'Failed to verify API key. Please check your credentials.').show();
754 - }
755 - },
756 - error: function(xhr, status, error) {
757 - $('#wizard-api-loader').hide();
758 - $('.wpbot-wizard-footer button').prop('disabled', false);
759 - $('#wizard-api-error').text('An error occurred during verification: ' + error).show();
760 - }
761 - });
762 - return;
763 - }
764 -
765 - if (currentStep === 3) {
766 - // Save wizard data and transition to Step 4 on success
767 - saveWizardData(false);
768 - return;
769 - }
770 -
771 - if (currentStep < totalSteps) {
772 - goToStep(currentStep + 1);
773 - }
774 - });
775 -
776 - // Back Button Click
777 - $('#wpbot-wizard-back').on('click', function(e) {
778 - e.preventDefault();
779 - if (currentStep > 1 && currentStep < 4) {
780 - goToStep(currentStep - 1);
781 - }
782 - });
783 -});
784 -</script>
1 +<?php
2 +/**
3 + * AI Setup Wizard Popup Template
4 + * Scoped styling and JS to avoid collision.
5 + */
6 +if ( ! defined( 'ABSPATH' ) ) {
7 + exit;
8 +}
9 +
10 +// Get all custom post types for Step 7
11 +$custom_post_types = get_post_types( array( 'public' => true, '_builtin' => false ), 'objects' );
12 +$show_wizard_automatically = isset( $show_wizard_automatically ) ? $show_wizard_automatically : false;
13 +?>
14 +<div id="wpbot-wizard-overlay" class="wpbot-wizard-overlay">
15 + <div class="wpbot-wizard-modal">
16 + <!-- Progress Bar -->
17 + <div class="wpbot-wizard-progress-container">
18 + <div id="wpbot-wizard-progress-bar" class="wpbot-wizard-progress-bar" style="width: 25%;"></div>
19 + </div>
20 +
21 + <div class="wpbot-wizard-header">
22 + <h2 class="wpbot-wizard-title">AI Setup Wizard</h2>
23 + <p class="wpbot-wizard-subtitle">Quickly configure your AI Chatbot in a few steps</p>
24 + <button type="button" class="wpbot-wizard-close-btn" id="wpbot-wizard-close">&times;</button>
25 + </div>
26 +
27 + <div class="wpbot-wizard-body">
28 + <form id="wpbot-wizard-form">
29 + <!-- Step 1: Select AI Service -->
30 + <div class="wpbot-wizard-step active" data-step="1">
31 + <h3>Step 1: Choose your AI Service</h3>
32 + <p class="wpbot-step-desc">Select which artificial intelligence provider you want to power your chatbot responses.</p>
33 + <div class="wpbot-wizard-field">
34 + <label for="wizard_ai_provider">AI Provider</label>
35 + <select id="wizard_ai_provider" name="ai_provider" class="wpbot-wizard-select">
36 + <option value="openai">OpenAI</option>
37 + <option value="gemini">Gemini</option>
38 + <option value="grok">Grok</option>
39 + <option value="openrouter">OpenRouter</option>
40 + </select>
41 + </div>
42 + </div>
43 +
44 + <!-- Step 2: Setup API Key -->
45 + <div class="wpbot-wizard-step" data-step="2">
46 + <h3>Step 2: API Credentials</h3>
47 + <p class="wpbot-step-desc" id="wizard_credentials_desc">Configure the connection credentials for your selected AI service.</p>
48 +
49 + <!-- API Key Input (for standard providers) -->
50 + <div class="wpbot-wizard-field" id="wizard_api_key_container">
51 + <label for="wizard_api_key" id="wizard_api_key_label">API Key</label>
52 + <input type="password" id="wizard_api_key" name="api_key" class="wpbot-wizard-input" placeholder="sk-..." />
53 + <p class="wpbot-field-help" id="wizard_api_key_help">Requires an active key from your provider.</p>
54 + <p class="wpbot-field-help" id="wizard_api_key_paid_note" style="color: #ef4444; font-weight: 600; margin-top: 8px;">Note: A Paid API key is required.</p>
55 + </div>
56 +
57 + <!-- API verification status elements -->
58 + <div id="wizard-api-loader" style="display: none; margin-top: 15px; text-align: center; color: #ffffff;">
59 + <div class="wpbot-spinner" style="display: inline-block; width: 24px; height: 24px; border: 3px solid rgba(255,255,255,0.1); border-radius: 50%; border-top-color: #6366f1; animation: wpbotSpin 1s ease-in-out infinite; margin-right: 8px; vertical-align: middle;"></div>
60 + <span style="font-size: 14px; font-weight: 500; vertical-align: middle;">Verifying API Connection...</span>
61 + </div>
62 + <div id="wizard-api-error" style="display: none; margin-top: 15px; padding: 12px; background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.3); border-radius: 8px; color: #f87171; font-size: 13px; line-height: 1.4;">
63 + </div>
64 + </div>
65 +
66 + <!-- Step 3: Content Sources for Vector Embedding -->
67 + <div class="wpbot-wizard-step" data-step="3">
68 + <h3>Step 3: Content Sources for Vector Embedding</h3>
69 + <p class="wpbot-step-desc">Select which content types should be automatically prepared for the RAG search database.</p>
70 +
71 + <div class="wpbot-wizard-field checkbox-inline-field">
72 + <label class="wpbot-checkbox-container">
73 + <input type="checkbox" name="rag_embed_pages" value="1" checked />
74 + <span class="wpbot-checkmark"></span>
75 + Pages
76 + </label>
77 + </div>
78 +
79 + <div class="wpbot-wizard-field checkbox-inline-field">
80 + <label class="wpbot-checkbox-container">
81 + <input type="checkbox" name="rag_embed_posts" value="1" checked />
82 + <span class="wpbot-checkmark"></span>
83 + Posts
84 + </label>
85 + </div>
86 +
87 + <?php if ( ! empty( $custom_post_types ) ) : ?>
88 + <div class="wpbot-wizard-field">
89 + <label style="margin-bottom: 8px; display: block; font-weight: 500; color: #e2e8f0;">Custom Post Types</label>
90 + <div class="wpbot-wizard-cpt-list">
91 + <?php foreach ( $custom_post_types as $cpt ) : ?>
92 + <label class="wpbot-checkbox-container">
93 + <input type="checkbox" name="rag_embed_cpts[]" value="<?php echo esc_attr( $cpt->name ); ?>" />
94 + <span class="wpbot-checkmark"></span>
95 + <?php echo esc_html( $cpt->label ); ?>
96 + </label>
97 + <?php endforeach; ?>
98 + </div>
99 + </div>
100 + <?php endif; ?>
101 +
102 + <!-- Preloader for Embedding -->
103 + <div id="wizard-embed-preloader" style="display: none; margin-top: 24px; padding: 20px; background: rgba(15, 23, 42, 0.4); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 12px;">
104 + <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
105 + <span style="font-weight: 600; color: #ffffff;">Vectorizing Content...</span>
106 + <span id="wizard-embed-percent" style="font-weight: 600; color: #a855f7;">0%</span>
107 + </div>
108 + <div style="height: 8px; background: rgba(255,255,255,0.05); border-radius: 4px; overflow: hidden; margin-bottom: 12px;">
109 + <div id="wizard-embed-progress-bar" style="width: 0%; height: 100%; background: linear-gradient(90deg, #6366f1, #a855f7); transition: width 0.2s ease;"></div>
110 + </div>
111 + <div style="display: flex; align-items: center; color: #cbd5e1; font-size: 13px;">
112 + <div class="wpbot-spinner" style="display: inline-block; width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.1); border-radius: 50%; border-top-color: #a855f7; animation: wpbotSpin 1s ease-in-out infinite; margin-right: 8px; flex-shrink: 0; vertical-align: middle;"></div>
113 + <span id="wizard-embed-status" style="vertical-align: middle;">Preparing queue...</span>
114 + </div>
115 + </div>
116 + </div>
117 +
118 + <!-- Step 4: Completion Screen -->
119 + <div class="wpbot-wizard-step" data-step="4">
120 + <div style="text-align: center; padding: 20px 0;">
121 + <div style="font-size: 60px; line-height: 1; margin-bottom: 20px; color: #10b981;">🎉</div>
122 + <h3 style="color: #ffffff; font-size: 22px; font-weight: 600; margin-bottom: 12px;">Congratulations!</h3>
123 + <p id="wizard-embed-success-msg" style="color: #10b981; font-weight: 600; font-size: 16px; margin-top: 10px; margin-bottom: 20px; display: none;">
124 + We have Embedded <span id="wizard-embed-count">0</span> post types successfully
125 + </p>
126 + <p class="wpbot-step-desc" style="font-size: 15px; line-height: 1.6; color: #cbd5e1; max-width: 480px; margin: 0 auto 20px;">
127 + Now your Chatbot is trained with your website data. You can upload additional training documents from AI Settings -> Knowledge base.
128 + </p>
129 + </div>
130 + </div>
131 + </form>
132 + </div>
133 +
134 + <div class="wpbot-wizard-footer">
135 + <button type="button" class="wpbot-wizard-btn wpbot-wizard-btn-skip" id="wpbot-wizard-skip">Skip Setup</button>
136 + <div class="wpbot-wizard-nav-btns">
137 + <button type="button" class="wpbot-wizard-btn wpbot-wizard-btn-back" id="wpbot-wizard-back" disabled>Back</button>
138 + <button type="button" class="wpbot-wizard-btn wpbot-wizard-btn-next" id="wpbot-wizard-next">Next</button>
139 + </div>
140 + </div>
141 + </div>
142 +</div>
143 +
144 +<style>
145 +/* Premium Dark Glassmorphism Styling */
146 +.wpbot-wizard-overlay {
147 + position: fixed;
148 + top: 0;
149 + left: 0;
150 + width: 100vw;
151 + height: 100vh;
152 + background: rgba(15, 23, 42, 0.75);
153 + backdrop-filter: blur(12px);
154 + -webkit-backdrop-filter: blur(12px);
155 + z-index: 999999;
156 + display: none;
157 + align-items: center;
158 + justify-content: center;
159 + color: #f8fafc;
160 + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
161 + animation: wpbotFadeIn 0.3s ease forwards;
162 +}
163 +
164 +.wpbot-wizard-modal {
165 + background: rgba(30, 41, 59, 0.95);
166 + border: 1px solid rgba(255, 255, 255, 0.1);
167 + border-radius: 20px;
168 + width: 90%;
169 + max-width: 600px;
170 + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
171 + overflow: hidden;
172 + position: relative;
173 + display: flex;
174 + flex-direction: column;
175 + max-height: 85vh;
176 + animation: wpbotScaleIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
177 +}
178 +
179 +/* Progress bar styling */
180 +.wpbot-wizard-progress-container {
181 + height: 6px;
182 + background: rgba(255, 255, 255, 0.05);
183 + width: 100%;
184 +}
185 +.wpbot-wizard-progress-bar {
186 + height: 100%;
187 + background: linear-gradient(90deg, #6366f1, #a855f7);
188 + transition: width 0.3s ease;
189 +}
190 +
191 +/* Header */
192 +.wpbot-wizard-header {
193 + padding: 28px 36px 20px;
194 + border-bottom: 1px solid rgba(255, 255, 255, 0.08);
195 + position: relative;
196 +}
197 +.wpbot-wizard-title {
198 + font-size: 24px;
199 + font-weight: 700;
200 + margin: 0 0 6px;
201 + color: #ffffff;
202 + background: linear-gradient(to right, #6366f1, #a855f7);
203 + -webkit-background-clip: text;
204 + -webkit-text-fill-color: transparent;
205 + display: inline-block;
206 +}
207 +.wpbot-wizard-subtitle {
208 + font-size: 14px;
209 + color: #94a3b8;
210 + margin: 0;
211 +}
212 +.wpbot-wizard-close-btn {
213 + position: absolute;
214 + top: 28px;
215 + right: 36px;
216 + background: none;
217 + border: none;
218 + color: #94a3b8;
219 + font-size: 28px;
220 + cursor: pointer;
221 + line-height: 1;
222 + padding: 0;
223 + transition: color 0.2s, transform 0.2s;
224 +}
225 +.wpbot-wizard-close-btn:hover {
226 + color: #ffffff;
227 + transform: scale(1.1);
228 +}
229 +
230 +/* Body and Steps */
231 +.wpbot-wizard-body {
232 + padding: 36px;
233 + overflow-y: auto;
234 + flex: 1;
235 +}
236 +.wpbot-wizard-step {
237 + display: none;
238 + animation: wpbotSlideIn 0.3s ease forwards;
239 +}
240 +.wpbot-wizard-step.active {
241 + display: block;
242 +}
243 +.wpbot-wizard-step h3 {
244 + font-size: 20px;
245 + color: #ffffff;
246 + margin: 0 0 10px;
247 + font-weight: 600;
248 +}
249 +.wpbot-step-desc {
250 + font-size: 14px;
251 + color: #94a3b8;
252 + margin: 0 0 28px;
253 + line-height: 1.6;
254 +}
255 +
256 +/* Form Fields */
257 +.wpbot-wizard-field {
258 + margin-bottom: 20px;
259 +}
260 +.wpbot-wizard-field label {
261 + display: block;
262 + font-size: 14px;
263 + color: #e2e8f0;
264 + margin-bottom: 8px;
265 + font-weight: 500;
266 +}
267 +.wpbot-wizard-input,
268 +.wpbot-wizard-select {
269 + width: 100%;
270 + background: rgba(15, 23, 42, 0.6);
271 + border: 1px solid rgba(255, 255, 255, 0.1);
272 + border-radius: 10px;
273 + padding: 12px 16px;
274 + color: #ffffff;
275 + font-size: 14px;
276 + box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
277 + box-sizing: border-box;
278 + transition: border-color 0.2s, box-shadow 0.2s;
279 +}
280 +.wpbot-wizard-input:focus,
281 +.wpbot-wizard-select:focus {
282 + border-color: #6366f1;
283 + outline: none;
284 + box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.35);
285 +}
286 +.wpbot-wizard-select option {
287 + background: #1e293b;
288 + color: #ffffff;
289 +}
290 +.wpbot-field-help {
291 + font-size: 12px;
292 + color: #94a3b8;
293 + margin: 6px 0 0;
294 +}
295 +
296 +/* Custom Checkbox Container */
297 +.wpbot-checkbox-container {
298 + display: inline-flex;
299 + align-items: center;
300 + position: relative;
301 + padding-left: 28px;
302 + cursor: pointer;
303 + font-size: 14px;
304 + user-select: none;
305 + color: #cbd5e1;
306 +}
307 +.wpbot-checkbox-container input {
308 + position: absolute;
309 + opacity: 0;
310 + cursor: pointer;
311 + height: 0;
312 + width: 0;
313 +}
314 +.wpbot-checkmark {
315 + position: absolute;
316 + top: 50%;
317 + left: 0;
318 + transform: translateY(-50%);
319 + height: 18px;
320 + width: 18px;
321 + background-color: rgba(255, 255, 255, 0.1);
322 + border: 1px solid rgba(255, 255, 255, 0.15);
323 + border-radius: 4px;
324 + transition: all 0.2s;
325 +}
326 +.wpbot-checkbox-container:hover input ~ .wpbot-checkmark {
327 + background-color: rgba(255, 255, 255, 0.15);
328 +}
329 +.wpbot-checkbox-container input:checked ~ .wpbot-checkmark {
330 + background-color: #6366f1;
331 + border-color: #6366f1;
332 +}
333 +.wpbot-checkmark:after {
334 + content: "";
335 + position: absolute;
336 + display: none;
337 +}
338 +.wpbot-checkbox-container input:checked ~ .wpbot-checkmark:after {
339 + display: block;
340 +}
341 +.wpbot-checkbox-container .wpbot-checkmark:after {
342 + left: 5px;
343 + top: 2px;
344 + width: 5px;
345 + height: 9px;
346 + border: solid white;
347 + border-width: 0 2px 2px 0;
348 + transform: rotate(45deg);
349 +}
350 +
351 +.wpbot-wizard-cpt-list {
352 + display: grid;
353 + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
354 + gap: 12px;
355 + background: rgba(0, 0, 0, 0.2);
356 + border-radius: 8px;
357 + padding: 16px;
358 + margin-top: 8px;
359 +}
360 +
361 +/* Footer & Buttons */
362 +.wpbot-wizard-footer {
363 + padding: 24px 36px;
364 + border-top: 1px solid rgba(255, 255, 255, 0.08);
365 + display: flex;
366 + justify-content: space-between;
367 + align-items: center;
368 + background: rgba(15, 23, 42, 0.4);
369 +}
370 +.wpbot-wizard-btn {
371 + border: none;
372 + border-radius: 8px;
373 + padding: 10px 20px;
374 + font-size: 14px;
375 + font-weight: 500;
376 + cursor: pointer;
377 + transition: all 0.2s;
378 +}
379 +.wpbot-wizard-btn-skip {
380 + background: transparent;
381 + color: #94a3b8;
382 +}
383 +.wpbot-wizard-btn-skip:hover {
384 + color: #ffffff;
385 +}
386 +.wpbot-wizard-nav-btns {
387 + display: flex;
388 + gap: 12px;
389 +}
390 +.wpbot-wizard-btn-back {
391 + background: rgba(255, 255, 255, 0.05);
392 + color: #e2e8f0;
393 + border: 1px solid rgba(255, 255, 255, 0.08);
394 +}
395 +.wpbot-wizard-btn-back:hover:not(:disabled) {
396 + background: rgba(255, 255, 255, 0.1);
397 +}
398 +.wpbot-wizard-btn-back:disabled {
399 + opacity: 0.5;
400 + cursor: not-allowed;
401 +}
402 +.wpbot-wizard-btn-next {
403 + background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
404 + color: #ffffff;
405 + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
406 +}
407 +.wpbot-wizard-btn-next:hover {
408 + transform: translateY(-1px);
409 + box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);
410 +}
411 +
412 +/* Animations */
413 +@keyframes wpbotFadeIn {
414 + from { opacity: 0; }
415 + to { opacity: 1; }
416 +}
417 +@keyframes wpbotScaleIn {
418 + from { transform: scale(0.95); opacity: 0; }
419 + to { transform: scale(1); opacity: 1; }
420 +}
421 +@keyframes wpbotSlideIn {
422 + from { transform: translateY(10px); opacity: 0; }
423 + to { transform: translateY(0); opacity: 1; }
424 +}
425 +@keyframes wpbotSpin {
426 + to { transform: rotate(360deg); }
427 +}
428 +</style>
429 +
430 +<script>
431 +jQuery(document).ready(function($) {
432 + // Move overlay to body to prevent viewport container centering bugs in WP Admin
433 + $('body').append($('#wpbot-wizard-overlay'));
434 +
435 + var currentStep = 1;
436 + var totalSteps = 4;
437 +
438 + // Auto open wizard logic
439 + var wpbot_auto_open_wizard = <?php echo $show_wizard_automatically ? 'true' : 'false'; ?>;
440 + if (wpbot_auto_open_wizard && sessionStorage.getItem('wpbot_wizard_skipped') !== '1') {
441 + $('#wpbot-wizard-overlay').css({ display: 'flex', opacity: 1 });
442 + }
443 +
444 + // Trigger wizard from settings page button
445 + $(document).on('click', '#wpbot-trigger-wizard', function(e) {
446 + e.preventDefault();
447 + goToStep(1);
448 + $('#wpbot-wizard-overlay')
449 + .css({ display: 'flex', opacity: 0 })
450 + .animate({ opacity: 1 }, 300);
451 + });
452 +
453 + // Provider detail configuration
454 + var providerConfig = {
455 + openai: {
456 + label: "OpenAI API Key",
457 + placeholder: "sk-...",
458 + help: "Requires an active key from https://platform.openai.com/settings/organization/api-keys."
459 + },
460 + gemini: {
461 + label: "Gemini API Key",
462 + placeholder: "Enter Gemini API Key",
463 + help: "Requires an active key from https://aistudio.google.com/app/api-keys."
464 + },
465 + grok: {
466 + label: "Grok API Key",
467 + placeholder: "xai-...",
468 + help: "Requires an API key from https://console.x.ai/"
469 + },
470 + openrouter: {
471 + label: "OpenRouter API Key",
472 + placeholder: "sk-or-v1-...",
473 + help: "Requires an API key from https://openrouter.ai/workspaces/default/keys."
474 + }
475 + };
476 +
477 + // Handle Provider change to adjust step 2 credentials UI
478 + $('#wizard_ai_provider').on('change', function() {
479 + var selected = $(this).val();
480 + $('#wizard_credentials_desc').text("Configure the API connection credentials for " + $(this).find('option:selected').text() + ".");
481 +
482 + var config = providerConfig[selected];
483 + if (config) {
484 + $('#wizard_api_key_label').text(config.label);
485 + $('#wizard_api_key').attr('placeholder', config.placeholder);
486 + $('#wizard_api_key_help').text(config.help);
487 + }
488 + }).trigger('change');
489 +
490 + // Dismiss wizard logic
491 + function dismissWizard() {
492 + $('#wpbot-wizard-overlay').animate({ opacity: 0 }, 300, function() {
493 + $(this).css('display', 'none');
494 + });
495 + }
496 +
497 + // Go to step helper function
498 + function goToStep(step) {
499 + $('.wpbot-wizard-step').removeClass('active');
500 + currentStep = step;
501 + $('.wpbot-wizard-step[data-step="' + currentStep + '"]').addClass('active');
502 +
503 + // Progress bar animation
504 + var pct = (currentStep / totalSteps) * 100;
505 + $('#wpbot-wizard-progress-bar').css('width', pct + '%');
506 +
507 + // Enable/disable back button
508 + if (currentStep === 1) {
509 + $('#wpbot-wizard-back').prop('disabled', true);
510 + } else {
511 + $('#wpbot-wizard-back').prop('disabled', false);
512 + }
513 +
514 + // Button texts & visibility adjustments
515 + if (currentStep === 3) {
516 + $('#wpbot-wizard-next').text('Finish');
517 + $('#wpbot-wizard-skip').show();
518 + $('#wpbot-wizard-back').show();
519 + } else if (currentStep === 4) {
520 + $('#wpbot-wizard-next').text('Finish Setup');
521 + $('#wpbot-wizard-back').hide();
522 + $('#wpbot-wizard-skip').hide();
523 + // Auto-disable Site Search when wizard completes
524 + $('#disable_wp_chatbot_site_search').prop('checked', true);
525 + } else {
526 + $('#wpbot-wizard-next').text('Next');
527 + $('#wpbot-wizard-skip').show();
528 + $('#wpbot-wizard-back').show();
529 + }
530 + }
531 +
532 + // Save options via AJAX
533 + function saveWizardData(isSkipped) {
534 + var formData = {
535 + action: 'wpbot_wizard_save',
536 + nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>',
537 + is_skipped: isSkipped ? 1 : 0
538 + };
539 +
540 + if (!isSkipped) {
541 + // Serialize form data
542 + var serialized = $('#wpbot-wizard-form').serializeArray();
543 + $.each(serialized, function(i, field) {
544 + if (field.name.endsWith('[]')) {
545 + var cleanName = field.name.slice(0, -2);
546 + if (!formData[cleanName]) {
547 + formData[cleanName] = [];
548 + }
549 + formData[cleanName].push(field.value);
550 + } else {
551 + formData[field.name] = field.value;
552 + }
553 + });
554 +
555 + // Handle checkbox values explicitly
556 + formData.rag_embed_pages = $('input[name="rag_embed_pages"]').is(':checked') ? 1 : 0;
557 + formData.rag_embed_posts = $('input[name="rag_embed_posts"]').is(':checked') ? 1 : 0;
558 + }
559 +
560 + // Disable all buttons in footer during save
561 + $('.wpbot-wizard-footer button').prop('disabled', true);
562 + if (!isSkipped) {
563 + $('#wpbot-wizard-next').text('Saving...');
564 + }
565 +
566 + $.ajax({
567 + url: ajaxurl,
568 + type: 'POST',
569 + data: formData,
570 + success: function(response) {
571 + if (response.success) {
572 + if (isSkipped) {
573 + dismissWizard();
574 + location.reload();
575 + } else {
576 + startWizardEmbedding();
577 + }
578 + } else {
579 + alert(response.data || 'Failed to save settings. Please try again.');
580 + $('.wpbot-wizard-footer button').prop('disabled', false);
581 + $('#wpbot-wizard-next').text('Finish');
582 + }
583 + },
584 + error: function() {
585 + alert('An error occurred. Please try again.');
586 + $('.wpbot-wizard-footer button').prop('disabled', false);
587 + $('#wpbot-wizard-next').text('Finish');
588 + }
589 + });
590 + }
591 +
592 + function startWizardEmbedding() {
593 + // Show preloader
594 + $('#wizard-embed-preloader').slideDown();
595 +
596 + // Disable all controls
597 + $('.wpbot-wizard-footer button').prop('disabled', true);
598 + $('#wpbot-wizard-close').prop('disabled', true);
599 + $('#wpbot-wizard-next').text('Embedding...');
600 +
601 + $('#wizard-embed-percent').text('0%');
602 + $('#wizard-embed-progress-bar').css('width', '0%');
603 + $('#wizard-embed-status').text('Preparing embedding queue...');
604 +
605 + // Fetch the queue of items to embed
606 + $.ajax({
607 + url: ajaxurl,
608 + type: 'POST',
609 + data: {
610 + action: 'qcld_rag_get_embed_queue',
611 + nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>'
612 + },
613 + success: function(response) {
614 + if (response.success) {
615 + var queue = response.data;
616 + if (!queue || queue.length === 0) {
617 + // No items to embed
618 + $('#wizard-embed-status').text('No items found to embed.');
619 + setTimeout(function() {
620 + $('#wizard-embed-count').text('0');
621 + $('#wizard-embed-success-msg').show();
622 + goToStep(4);
623 + $('.wpbot-wizard-footer button').prop('disabled', false);
624 + $('#wpbot-wizard-close').prop('disabled', false);
625 + }, 1000);
626 + return;
627 + }
628 +
629 + $('#wizard-embed-status').text('Processing 0 / ' + queue.length + ' items...');
630 + processWizardEmbedQueue(queue, 0, 0);
631 + } else {
632 + alert('Failed to fetch the embedding queue. Moving to next step.');
633 + $('#wizard-embed-count').text('0');
634 + $('#wizard-embed-success-msg').show();
635 + goToStep(4);
636 + $('.wpbot-wizard-footer button').prop('disabled', false);
637 + $('#wpbot-wizard-close').prop('disabled', false);
638 + }
639 + },
640 + error: function() {
641 + alert('An error occurred while fetching the embedding queue. Moving to next step.');
642 + $('#wizard-embed-count').text('0');
643 + $('#wizard-embed-success-msg').show();
644 + goToStep(4);
645 + $('.wpbot-wizard-footer button').prop('disabled', false);
646 + $('#wpbot-wizard-close').prop('disabled', false);
647 + }
648 + });
649 + }
650 +
651 + function processWizardEmbedQueue(queue, index, successCount) {
652 + if (index >= queue.length) {
653 + $('#wizard-embed-status').text('Embedding complete! Total processed: ' + successCount + ' / ' + queue.length);
654 + setTimeout(function() {
655 + $('#wizard-embed-count').text(successCount);
656 + $('#wizard-embed-success-msg').show();
657 + goToStep(4);
658 + $('.wpbot-wizard-footer button').prop('disabled', false);
659 + $('#wpbot-wizard-close').prop('disabled', false);
660 + }, 1000);
661 + return;
662 + }
663 +
664 + var item = queue[index];
665 + var progress = Math.round(((index + 1) / queue.length) * 100);
666 +
667 + $('#wizard-embed-status').text('Embedding document (' + (index + 1) + ' / ' + queue.length + ')...');
668 + $('#wizard-embed-progress-bar').css('width', progress + '%');
669 + $('#wizard-embed-percent').text(progress + '%');
670 +
671 + $.ajax({
672 + url: ajaxurl,
673 + type: 'POST',
674 + data: {
675 + action: 'qcld_rag_process_item',
676 + nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>',
677 + item_id: item.id,
678 + item_type: item.type
679 + },
680 + success: function(response) {
681 + // We consider either a successful return or skip as a processed item
682 + var increment = 0;
683 + if (response.success) {
684 + increment = 1;
685 + }
686 + processWizardEmbedQueue(queue, index + 1, successCount + increment);
687 + },
688 + error: function() {
689 + // Continue to next item on failure, so wizard doesn't hang
690 + processWizardEmbedQueue(queue, index + 1, successCount);
691 + }
692 + });
693 + }
694 +
695 + // Skip Button Click
696 + $('#wpbot-wizard-skip, #wpbot-wizard-close').on('click', function(e) {
697 + e.preventDefault();
698 + if (currentStep === 4) {
699 + dismissWizard();
700 + location.reload();
701 + return;
702 + }
703 + // if (confirm('Are you sure you want to skip the setup wizard? you can set up these configurations manually inside the settings panel.')) {
704 + sessionStorage.setItem('wpbot_wizard_skipped', '1');
705 + dismissWizard();
706 + // }
707 + });
708 +
709 + // Next Button Click
710 + $('#wpbot-wizard-next').on('click', function(e) {
711 + e.preventDefault();
712 +
713 + // If we are on Step 4 (Congratulations), clicking Next should close and reload.
714 + if (currentStep === 4) {
715 + // Ensure Site Search is disabled before closing
716 + $('#disable_wp_chatbot_site_search').prop('checked', true);
717 + dismissWizard();
718 + location.reload();
719 + return;
720 + }
721 +
722 + // Basic Validation for credentials step (Step 2) and AJAX verification
723 + if (currentStep === 2) {
724 + var provider = $('#wizard_ai_provider').val();
725 + var apiKey = $('#wizard_api_key').val().trim();
726 +
727 + if (apiKey === '') {
728 + alert('Please enter your API Key before continuing.');
729 + return;
730 + }
731 +
732 + // Show loader and hide old error
733 + $('#wizard-api-loader').show();
734 + $('#wizard-api-error').hide();
735 + $('.wpbot-wizard-footer button').prop('disabled', true);
736 +
737 + $.ajax({
738 + url: ajaxurl,
739 + type: 'POST',
740 + data: {
741 + action: 'wpbot_wizard_verify_key',
742 + nonce: '<?php echo esc_attr( wp_create_nonce("wp_chatbot") ); ?>',
743 + ai_provider: provider,
744 + api_key: apiKey
745 + },
746 + success: function(response) {
747 + $('#wizard-api-loader').hide();
748 + $('.wpbot-wizard-footer button').prop('disabled', false);
749 +
750 + if (response.success) {
751 + goToStep(3);
752 + } else {
753 + $('#wizard-api-error').text(response.data || 'Failed to verify API key. Please check your credentials.').show();
754 + }
755 + },
756 + error: function(xhr, status, error) {
757 + $('#wizard-api-loader').hide();
758 + $('.wpbot-wizard-footer button').prop('disabled', false);
759 + $('#wizard-api-error').text('An error occurred during verification: ' + error).show();
760 + }
761 + });
762 + return;
763 + }
764 +
765 + if (currentStep === 3) {
766 + // Save wizard data and transition to Step 4 on success
767 + saveWizardData(false);
768 + return;
769 + }
770 +
771 + if (currentStep < totalSteps) {
772 + goToStep(currentStep + 1);
773 + }
774 + });
775 +
776 + // Back Button Click
777 + $('#wpbot-wizard-back').on('click', function(e) {
778 + e.preventDefault();
779 + if (currentStep > 1 && currentStep < 4) {
780 + goToStep(currentStep - 1);
781 + }
782 + });
783 +});
784 +</script>