| 1 |
<?php |
| 2 |
/** |
| 3 |
* MxChat → Onboarding admin page (linear wizard). |
| 4 |
* |
| 5 |
* Plan: plan-mxchat-20260527-905439 — SUPERSEDES the 704e25 checklist UI. |
| 6 |
* |
| 7 |
* Five-step wizard: |
| 8 |
* 1. Choose chat provider + model + API key |
| 9 |
* 2. Choose embedding provider + model + API key (dedup if same as chat) |
| 10 |
* 3. Seed the knowledge base (live-poll the KB row count) |
| 11 |
* 4. Try Actions (optional) |
| 12 |
* 5. Congrats + PRO add-ons (auto-graduates the menu item) |
| 13 |
* |
| 14 |
* Preserved from plan-f7c7d4: menu item, "Onboarding" naming, dismiss button, |
| 15 |
* auto-graduate via mxchat_onboarding_dismissed, 301 from old slug, Stuck? |
| 16 |
* Get help footer URLs, brand tokens, responsive 1280x800 / 390x844 quality bar. |
| 17 |
* |
| 18 |
* State storage: |
| 19 |
* mxchat_onboarding_progress — assoc array { chat_model, embedding_model, |
| 20 |
* knowledge_base, actions } booleans. Drives |
| 21 |
* resume-where-you-left-off on reload. |
| 22 |
* mxchat_onboarding_dismissed — reused from f7c7d4. Set when the user |
| 23 |
* lands on Step 5 (auto-graduate) OR clicks |
| 24 |
* Dismiss anywhere. |
| 25 |
* mxchat_onboarding_auto_graduated — companion flag from f7c7d4; set when |
| 26 |
* graduation was automatic rather than |
| 27 |
* user-initiated. |
| 28 |
* Provider/model/key options are the SAME ones Settings already uses |
| 29 |
* (mxchat_options sub-keys: api_key for OpenAI, claude_api_key, |
| 30 |
* xai_api_key, deepseek_api_key, gemini_api_key, openrouter_api_key, |
| 31 |
* voyage_api_key, custom_provider_api_key + perplexity_api_key if/when |
| 32 |
* that provider lands). No parallel key storage. |
| 33 |
* |
| 34 |
* Admin-chrome surgery (Onboarding page only): adds body class |
| 35 |
* `mxchat-onboarding-focused` from class-mxchat-admin.php's admin_body_class |
| 36 |
* hook so admin-onboarding-wizard.css can collapse the WP admin sidebar and |
| 37 |
* suppress the bottom dashboard cards on THIS page only. |
| 38 |
* |
| 39 |
* @package MxChat |
| 40 |
* @since 3.2.7 |
| 41 |
*/ |
| 42 |
|
| 43 |
if (!defined('ABSPATH')) { |
| 44 |
exit; |
| 45 |
} |
| 46 |
|
| 47 |
/** |
| 48 |
* Read the persistent onboarding-dismissed flag. |
| 49 |
*/ |
| 50 |
function mxchat_onboarding_is_dismissed() { |
| 51 |
return (bool) get_option('mxchat_onboarding_dismissed', 0); |
| 52 |
} |
| 53 |
|
| 54 |
/** |
| 55 |
* Was the dismiss caused by auto-graduation rather than a user click? |
| 56 |
*/ |
| 57 |
function mxchat_onboarding_is_auto_graduated() { |
| 58 |
return (bool) get_option('mxchat_onboarding_auto_graduated', 0); |
| 59 |
} |
| 60 |
|
| 61 |
/** |
| 62 |
* Read the wizard progress state. Returns the four step booleans. |
| 63 |
*/ |
| 64 |
function mxchat_onboarding_get_progress() { |
| 65 |
$defaults = array( |
| 66 |
'chat_model' => false, |
| 67 |
'behavior' => false, |
| 68 |
'embedding_model' => false, |
| 69 |
'knowledge_base' => false, |
| 70 |
'actions' => false, |
| 71 |
); |
| 72 |
$stored = get_option('mxchat_onboarding_progress', array()); |
| 73 |
if (!is_array($stored)) { |
| 74 |
$stored = array(); |
| 75 |
} |
| 76 |
$out = array(); |
| 77 |
foreach ($defaults as $k => $v) { |
| 78 |
$out[$k] = isset($stored[$k]) ? (bool) $stored[$k] : $v; |
| 79 |
} |
| 80 |
return $out; |
| 81 |
} |
| 82 |
|
| 83 |
/** |
| 84 |
* Update one or more wizard progress flags. Merges into the stored array. |
| 85 |
*/ |
| 86 |
function mxchat_onboarding_set_progress($changes) { |
| 87 |
$current = mxchat_onboarding_get_progress(); |
| 88 |
foreach ((array) $changes as $k => $v) { |
| 89 |
if (array_key_exists($k, $current)) { |
| 90 |
$current[$k] = (bool) $v; |
| 91 |
} |
| 92 |
} |
| 93 |
update_option('mxchat_onboarding_progress', $current); |
| 94 |
return $current; |
| 95 |
} |
| 96 |
|
| 97 |
/** |
| 98 |
* Existing AJAX: user-initiated dismiss. Preserved verbatim from f7c7d4. |
| 99 |
*/ |
| 100 |
add_action('wp_ajax_mxchat_dismiss_onboarding', 'mxchat_handle_dismiss_onboarding'); |
| 101 |
function mxchat_handle_dismiss_onboarding() { |
| 102 |
if (!current_user_can('manage_options')) { |
| 103 |
wp_send_json_error(array('message' => __('You do not have permission to do this.', 'mxchat')), 403); |
| 104 |
} |
| 105 |
check_ajax_referer('mxchat_dismiss_onboarding', 'nonce'); |
| 106 |
|
| 107 |
update_option('mxchat_onboarding_dismissed', 1); |
| 108 |
update_option('mxchat_onboarding_auto_graduated', 0); |
| 109 |
|
| 110 |
wp_send_json_success(array('dismissed' => true)); |
| 111 |
} |
| 112 |
|
| 113 |
/** |
| 114 |
* admin_post: "Show MxChat Onboarding again" — clears both dismissed flag |
| 115 |
* AND wizard progress so the user gets a fresh wizard. Preserved from f7c7d4 |
| 116 |
* with the added progress-reset. |
| 117 |
*/ |
| 118 |
add_action('admin_post_mxchat_unhide_onboarding', 'mxchat_handle_unhide_onboarding'); |
| 119 |
function mxchat_handle_unhide_onboarding() { |
| 120 |
if (!current_user_can('manage_options')) { |
| 121 |
wp_die(esc_html__('You do not have permission to do this.', 'mxchat')); |
| 122 |
} |
| 123 |
check_admin_referer('mxchat_unhide_onboarding'); |
| 124 |
|
| 125 |
delete_option('mxchat_onboarding_dismissed'); |
| 126 |
delete_option('mxchat_onboarding_auto_graduated'); |
| 127 |
|
| 128 |
wp_safe_redirect(admin_url('admin.php?page=mxchat-onboarding')); |
| 129 |
exit; |
| 130 |
} |
| 131 |
|
| 132 |
/** |
| 133 |
* admin_init: legacy slug 301 redirect (preserved from f7c7d4). |
| 134 |
*/ |
| 135 |
add_action('admin_init', 'mxchat_onboarding_legacy_slug_redirect'); |
| 136 |
function mxchat_onboarding_legacy_slug_redirect() { |
| 137 |
if (!isset($_GET['page'])) { |
| 138 |
return; |
| 139 |
} |
| 140 |
if ($_GET['page'] !== 'mxchat-dashboard') { |
| 141 |
return; |
| 142 |
} |
| 143 |
wp_safe_redirect(admin_url('admin.php?page=mxchat-onboarding'), 301); |
| 144 |
exit; |
| 145 |
} |
| 146 |
|
| 147 |
/** |
| 148 |
* Provider catalog used by Steps 1 and 2. Wraps the canonical catalog in |
| 149 |
* includes/class-mxchat-model-catalog.php (plan-d14e89) so a single edit |
| 150 |
* there flows through to the Onboarding wizard's dropdowns. Shape preserved |
| 151 |
* for back-compat: |
| 152 |
* [ slug => [ label, key_option, chat_models{}, embedding_models{} ] ] |
| 153 |
* Plus an extra `requires_key_to_load_models` flag per provider (true for |
| 154 |
* OpenRouter) so the wizard can disable that provider in its picker. |
| 155 |
*/ |
| 156 |
function mxchat_onboarding_provider_catalog() { |
| 157 |
if (!class_exists('MxChat_Model_Catalog')) { |
| 158 |
require_once plugin_dir_path(__FILE__) . 'class-mxchat-model-catalog.php'; |
| 159 |
} |
| 160 |
$chat = MxChat_Model_Catalog::chat_models(); |
| 161 |
$emb = MxChat_Model_Catalog::embedding_models(); |
| 162 |
|
| 163 |
$out = array(); |
| 164 |
$all_slugs = array_unique(array_merge(array_keys($chat), array_keys($emb))); |
| 165 |
foreach ($all_slugs as $slug) { |
| 166 |
$chat_models = array(); |
| 167 |
$requires_key = false; |
| 168 |
$disable_onb = false; |
| 169 |
if (isset($chat[$slug])) { |
| 170 |
foreach ($chat[$slug]['models'] as $id => $entry) { |
| 171 |
$chat_models[$id] = $entry['label']; |
| 172 |
} |
| 173 |
$requires_key = !empty($chat[$slug]['requires_key_to_load_models']); |
| 174 |
$disable_onb = !empty($chat[$slug]['disable_in_onboarding']); |
| 175 |
} |
| 176 |
$embed_models = array(); |
| 177 |
if (isset($emb[$slug])) { |
| 178 |
foreach ($emb[$slug]['models'] as $id => $entry) { |
| 179 |
$embed_models[$id] = $entry['label']; |
| 180 |
} |
| 181 |
} |
| 182 |
$out[$slug] = array( |
| 183 |
'label' => MxChat_Model_Catalog::provider_label($slug), |
| 184 |
'key_option' => MxChat_Model_Catalog::key_option_for_provider($slug), |
| 185 |
'chat_models' => $chat_models, |
| 186 |
'embedding_models' => $embed_models, |
| 187 |
'requires_key_to_load_models' => $requires_key, |
| 188 |
'disable_in_onboarding' => ($disable_onb || $requires_key), |
| 189 |
); |
| 190 |
} |
| 191 |
return $out; |
| 192 |
} |
| 193 |
|
| 194 |
/** |
| 195 |
* Infer the provider slug from a chat model id, mirroring the rule of thumb |
| 196 |
* the model picker uses. Returns 'openai' / 'claude' / 'gemini' / 'xai' / |
| 197 |
* 'deepseek' / 'openrouter' / 'custom' or '' if unknown. |
| 198 |
*/ |
| 199 |
function mxchat_onboarding_provider_from_model($model_id) { |
| 200 |
$m = strtolower((string) $model_id); |
| 201 |
if ($m === '') return ''; |
| 202 |
if (strpos($m, 'gpt-') === 0 || strpos($m, 'o1-') === 0 || strpos($m, 'o3-') === 0) return 'openai'; |
| 203 |
if (strpos($m, 'claude-') === 0) return 'claude'; |
| 204 |
if (strpos($m, 'gemini-') === 0) return 'gemini'; |
| 205 |
if (strpos($m, 'grok') === 0) return 'xai'; |
| 206 |
if (strpos($m, 'deepseek') === 0) return 'deepseek'; |
| 207 |
if (strpos($m, 'sonar') === 0 || strpos($m, 'pplx-') === 0) return 'perplexity'; |
| 208 |
if ($m === 'openrouter' || strpos($m, '/') !== false) return 'openrouter'; |
| 209 |
if (strpos($m, 'custom') === 0) return 'custom'; |
| 210 |
return ''; |
| 211 |
} |
| 212 |
|
| 213 |
/** |
| 214 |
* Mirror for embedding models. |
| 215 |
*/ |
| 216 |
function mxchat_onboarding_provider_from_embedding_model($model_id) { |
| 217 |
$m = strtolower((string) $model_id); |
| 218 |
if ($m === '') return ''; |
| 219 |
if (strpos($m, 'text-embedding-') === 0) return 'openai'; |
| 220 |
if (strpos($m, 'voyage') === 0) return 'voyage'; |
| 221 |
if (strpos($m, 'gemini-embedding') === 0) return 'gemini'; |
| 222 |
return ''; |
| 223 |
} |
| 224 |
|
| 225 |
/** |
| 226 |
* Whether the given provider has a non-empty API key saved. |
| 227 |
*/ |
| 228 |
function mxchat_onboarding_provider_has_key($provider_slug) { |
| 229 |
$catalog = mxchat_onboarding_provider_catalog(); |
| 230 |
if (!isset($catalog[$provider_slug])) return false; |
| 231 |
$opts = get_option('mxchat_options', array()); |
| 232 |
if (!is_array($opts)) $opts = array(); |
| 233 |
$field = $catalog[$provider_slug]['key_option']; |
| 234 |
return !empty($opts[$field]) && trim((string) $opts[$field]) !== ''; |
| 235 |
} |
| 236 |
|
| 237 |
/** |
| 238 |
* KB row count. The canonical KB content table is |
| 239 |
* {$wpdb->prefix}mxchat_system_prompt_content — see mxchat-basic.php:716 |
| 240 |
* where the table is created. An earlier draft of this function queried |
| 241 |
* mxchat_embeddings (which doesn't exist on most installs), causing Step 3 |
| 242 |
* to always report "No knowledge base items yet" even after items had been |
| 243 |
* added. Plan-d14e89 Issue 6. |
| 244 |
*/ |
| 245 |
function mxchat_onboarding_kb_count() { |
| 246 |
global $wpdb; |
| 247 |
$table = $wpdb->prefix . 'mxchat_system_prompt_content'; |
| 248 |
$exists = (bool) $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $table)); |
| 249 |
if (!$exists) return 0; |
| 250 |
return (int) $wpdb->get_var("SELECT COUNT(*) FROM {$table}"); |
| 251 |
} |
| 252 |
|
| 253 |
/** |
| 254 |
* AJAX: live KB status poll for Step 3. Returns { count: N }. |
| 255 |
* Nonce-protected per plan spec (use per-request nonce path from 6a68c9 — |
| 256 |
* here the nonce is issued fresh in the page renderer, NOT cached, since |
| 257 |
* admin pages aren't page-cached). |
| 258 |
*/ |
| 259 |
add_action('wp_ajax_mxchat_onboarding_kb_status', 'mxchat_onboarding_ajax_kb_status'); |
| 260 |
function mxchat_onboarding_ajax_kb_status() { |
| 261 |
if (!current_user_can('manage_options')) { |
| 262 |
wp_send_json_error(array('message' => __('You do not have permission.', 'mxchat')), 403); |
| 263 |
} |
| 264 |
check_ajax_referer('mxchat_onboarding_nonce', 'nonce'); |
| 265 |
wp_send_json_success(array('count' => mxchat_onboarding_kb_count())); |
| 266 |
} |
| 267 |
|
| 268 |
/** |
| 269 |
* AJAX: save Step 1 (chat) or Step 2 (embedding) selection. Persists |
| 270 |
* provider/model/key into the SAME mxchat_options sub-keys Settings uses |
| 271 |
* (no parallel storage), then flips the corresponding progress flag. |
| 272 |
* |
| 273 |
* Expected POST: which=chat|embedding, provider=<slug>, model=<id>, |
| 274 |
* api_key=<string optional — only set if a fresh key was entered>. |
| 275 |
*/ |
| 276 |
add_action('wp_ajax_mxchat_onboarding_save_step', 'mxchat_onboarding_ajax_save_step'); |
| 277 |
function mxchat_onboarding_ajax_save_step() { |
| 278 |
if (!current_user_can('manage_options')) { |
| 279 |
wp_send_json_error(array('message' => __('You do not have permission.', 'mxchat')), 403); |
| 280 |
} |
| 281 |
check_ajax_referer('mxchat_onboarding_nonce', 'nonce'); |
| 282 |
|
| 283 |
$which = isset($_POST['which']) ? sanitize_key($_POST['which']) : ''; |
| 284 |
|
| 285 |
// Behavior step branch (plan-a2e4d6) — saves system_prompt_instructions |
| 286 |
// into the SAME mxchat_options sub-key Settings uses, no parallel storage. |
| 287 |
if ($which === 'behavior') { |
| 288 |
$instructions = isset($_POST['system_prompt_instructions']) |
| 289 |
? sanitize_textarea_field(wp_unslash($_POST['system_prompt_instructions'])) |
| 290 |
: ''; |
| 291 |
$opts = get_option('mxchat_options', array()); |
| 292 |
if (!is_array($opts)) $opts = array(); |
| 293 |
$opts['system_prompt_instructions'] = $instructions; |
| 294 |
update_option('mxchat_options', $opts); |
| 295 |
mxchat_onboarding_set_progress(array('behavior' => true)); |
| 296 |
wp_send_json_success(array( |
| 297 |
'progress' => mxchat_onboarding_get_progress(), |
| 298 |
)); |
| 299 |
} |
| 300 |
|
| 301 |
$provider = isset($_POST['provider']) ? sanitize_key($_POST['provider']) : ''; |
| 302 |
$model = isset($_POST['model']) ? sanitize_text_field(wp_unslash($_POST['model'])) : ''; |
| 303 |
$api_key = isset($_POST['api_key']) ? sanitize_text_field(wp_unslash($_POST['api_key'])) : ''; |
| 304 |
|
| 305 |
$catalog = mxchat_onboarding_provider_catalog(); |
| 306 |
if (!in_array($which, array('chat', 'embedding'), true)) { |
| 307 |
wp_send_json_error(array('message' => __('Invalid step.', 'mxchat')), 400); |
| 308 |
} |
| 309 |
if (!isset($catalog[$provider])) { |
| 310 |
wp_send_json_error(array('message' => __('Unknown provider.', 'mxchat')), 400); |
| 311 |
} |
| 312 |
$model_list = $which === 'chat' ? $catalog[$provider]['chat_models'] : $catalog[$provider]['embedding_models']; |
| 313 |
if (!isset($model_list[$model])) { |
| 314 |
wp_send_json_error(array('message' => __('Model not valid for this provider.', 'mxchat')), 400); |
| 315 |
} |
| 316 |
|
| 317 |
$opts = get_option('mxchat_options', array()); |
| 318 |
if (!is_array($opts)) $opts = array(); |
| 319 |
|
| 320 |
// Persist the key if a fresh one was sent. Empty string means "no change" |
| 321 |
// (the UI sends '' when the user is reusing an already-saved key). |
| 322 |
if ($api_key !== '') { |
| 323 |
$opts[$catalog[$provider]['key_option']] = $api_key; |
| 324 |
} |
| 325 |
|
| 326 |
if ($which === 'chat') { |
| 327 |
$opts['model'] = $model; |
| 328 |
} else { |
| 329 |
$opts['embedding_model'] = $model; |
| 330 |
} |
| 331 |
update_option('mxchat_options', $opts); |
| 332 |
|
| 333 |
$progress_key = $which === 'chat' ? 'chat_model' : 'embedding_model'; |
| 334 |
mxchat_onboarding_set_progress(array($progress_key => true)); |
| 335 |
|
| 336 |
wp_send_json_success(array( |
| 337 |
'progress' => mxchat_onboarding_get_progress(), |
| 338 |
)); |
| 339 |
} |
| 340 |
|
| 341 |
/** |
| 342 |
* AJAX: mark a step done (used by Step 4 actions Skip/Continue, and Step 3 |
| 343 |
* Continue once KB is populated). No-op if the step name is unknown. |
| 344 |
*/ |
| 345 |
add_action('wp_ajax_mxchat_onboarding_mark_step', 'mxchat_onboarding_ajax_mark_step'); |
| 346 |
function mxchat_onboarding_ajax_mark_step() { |
| 347 |
if (!current_user_can('manage_options')) { |
| 348 |
wp_send_json_error(array('message' => __('You do not have permission.', 'mxchat')), 403); |
| 349 |
} |
| 350 |
check_ajax_referer('mxchat_onboarding_nonce', 'nonce'); |
| 351 |
|
| 352 |
$step = isset($_POST['step']) ? sanitize_key($_POST['step']) : ''; |
| 353 |
$valid = array('chat_model', 'behavior', 'embedding_model', 'knowledge_base', 'actions'); |
| 354 |
if (!in_array($step, $valid, true)) { |
| 355 |
wp_send_json_error(array('message' => __('Unknown step.', 'mxchat')), 400); |
| 356 |
} |
| 357 |
mxchat_onboarding_set_progress(array($step => true)); |
| 358 |
wp_send_json_success(array('progress' => mxchat_onboarding_get_progress())); |
| 359 |
} |
| 360 |
|
| 361 |
/** |
| 362 |
* AJAX: auto-graduate on Step 5 land. Sets dismissed + auto_graduated flags |
| 363 |
* (same flags f7c7d4 used) so the menu item disappears on next admin nav. |
| 364 |
*/ |
| 365 |
add_action('wp_ajax_mxchat_onboarding_auto_graduate', 'mxchat_onboarding_ajax_auto_graduate'); |
| 366 |
function mxchat_onboarding_ajax_auto_graduate() { |
| 367 |
if (!current_user_can('manage_options')) { |
| 368 |
wp_send_json_error(array('message' => __('You do not have permission.', 'mxchat')), 403); |
| 369 |
} |
| 370 |
check_ajax_referer('mxchat_onboarding_nonce', 'nonce'); |
| 371 |
|
| 372 |
update_option('mxchat_onboarding_dismissed', 1); |
| 373 |
update_option('mxchat_onboarding_auto_graduated', 1); |
| 374 |
wp_send_json_success(array('graduated' => true)); |
| 375 |
} |
| 376 |
|
| 377 |
/** |
| 378 |
* Render the Onboarding page — wizard layout. Entry point wired from |
| 379 |
* class-mxchat-admin.php. |
| 380 |
*/ |
| 381 |
function mxchat_render_onboarding_page() { |
| 382 |
if (!current_user_can('manage_options')) { |
| 383 |
wp_die(esc_html__('You do not have permission to access this page.', 'mxchat')); |
| 384 |
} |
| 385 |
|
| 386 |
$opts = get_option('mxchat_options', array()); |
| 387 |
if (!is_array($opts)) $opts = array(); |
| 388 |
|
| 389 |
$progress = mxchat_onboarding_get_progress(); |
| 390 |
$catalog = mxchat_onboarding_provider_catalog(); |
| 391 |
|
| 392 |
// Compute saved-key state per provider so the JS can short-circuit the |
| 393 |
// API-key input to the "already saved" checkmark on initial render. |
| 394 |
$key_state = array(); |
| 395 |
foreach ($catalog as $slug => $entry) { |
| 396 |
$key_state[$slug] = mxchat_onboarding_provider_has_key($slug); |
| 397 |
} |
| 398 |
|
| 399 |
// Current selections (pre-populate the wizard if user already had values |
| 400 |
// in Settings before opening Onboarding). |
| 401 |
$current_chat_model = isset($opts['model']) ? (string) $opts['model'] : ''; |
| 402 |
$current_chat_provider = mxchat_onboarding_provider_from_model($current_chat_model); |
| 403 |
$current_embed_model = isset($opts['embedding_model']) ? (string) $opts['embedding_model'] : ''; |
| 404 |
$current_embed_provider = mxchat_onboarding_provider_from_embedding_model($current_embed_model); |
| 405 |
|
| 406 |
// Pre-credit logic — run BEFORE deciding the initial step so the landing |
| 407 |
// step reflects pre-existing Settings values. The wizard is six steps now |
| 408 |
// (plan-a2e4d6 inserted "AI Behavior" at position 2): |
| 409 |
// 1. Chat model → progress.chat_model |
| 410 |
// 2. AI Behavior → progress.behavior (NEW) |
| 411 |
// 3. Embedding → progress.embedding_model |
| 412 |
// 4. Knowledge base→ progress.knowledge_base |
| 413 |
// 5. Actions → progress.actions |
| 414 |
// 6. Congrats → no progress flag (all-five-complete view) |
| 415 |
|
| 416 |
// Pre-credit Step 1 (chat) if a chat model + key are already saved. |
| 417 |
if (!$progress['chat_model'] && $current_chat_model !== '' && $current_chat_provider !== '' && !empty($key_state[$current_chat_provider])) { |
| 418 |
mxchat_onboarding_set_progress(array('chat_model' => true)); |
| 419 |
$progress['chat_model'] = true; |
| 420 |
} |
| 421 |
// Pre-credit Step 2 (behavior) if system_prompt_instructions is non-empty |
| 422 |
// — the user already set this in Settings before opening Onboarding. |
| 423 |
$current_instructions = isset($opts['system_prompt_instructions']) ? (string) $opts['system_prompt_instructions'] : ''; |
| 424 |
if (!$progress['behavior'] && trim($current_instructions) !== '') { |
| 425 |
mxchat_onboarding_set_progress(array('behavior' => true)); |
| 426 |
$progress['behavior'] = true; |
| 427 |
} |
| 428 |
// Pre-credit Step 3 (embedding) if model + key already saved. |
| 429 |
if (!$progress['embedding_model'] && $current_embed_model !== '' && $current_embed_provider !== '' && !empty($key_state[$current_embed_provider])) { |
| 430 |
mxchat_onboarding_set_progress(array('embedding_model' => true)); |
| 431 |
$progress['embedding_model'] = true; |
| 432 |
} |
| 433 |
// Pre-credit Step 4 (KB) if rows already exist. |
| 434 |
if (!$progress['knowledge_base'] && mxchat_onboarding_kb_count() > 0) { |
| 435 |
mxchat_onboarding_set_progress(array('knowledge_base' => true)); |
| 436 |
$progress['knowledge_base'] = true; |
| 437 |
} |
| 438 |
|
| 439 |
// First-not-done step is where we land on load. With all five flags true, |
| 440 |
// we land on Step 6 (Congrats). |
| 441 |
if (!$progress['chat_model']) $initial_step = 1; |
| 442 |
elseif (!$progress['behavior']) $initial_step = 2; |
| 443 |
elseif (!$progress['embedding_model']) $initial_step = 3; |
| 444 |
elseif (!$progress['knowledge_base']) $initial_step = 4; |
| 445 |
elseif (!$progress['actions']) $initial_step = 5; |
| 446 |
else $initial_step = 6; |
| 447 |
|
| 448 |
$plugin_url = plugin_dir_url(dirname(__FILE__)); |
| 449 |
$dismiss_nonce = wp_create_nonce('mxchat_dismiss_onboarding'); |
| 450 |
$wizard_nonce = wp_create_nonce('mxchat_onboarding_nonce'); |
| 451 |
|
| 452 |
$current_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : 'mxchat-onboarding'; |
| 453 |
$nav_items = array( |
| 454 |
array('slug' => 'mxchat-onboarding', 'label' => __('Onboarding', 'mxchat'), 'svg' => '<polyline points="3 9 12 2 21 9 21 21 14 21 14 14 10 14 10 21 3 21 3 9"/>'), |
| 455 |
array('slug' => 'mxchat-settings', 'label' => __('Settings', 'mxchat'), 'svg' => '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h.01a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>'), |
| 456 |
array('slug' => 'mxchat-prompts', 'label' => __('Knowledge', 'mxchat'), 'svg' => '<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>'), |
| 457 |
array('slug' => 'mxchat-transcripts', 'label' => __('Transcripts', 'mxchat'), 'svg' => '<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>'), |
| 458 |
array('slug' => 'mxchat-actions', 'label' => __('Actions', 'mxchat'), 'svg' => '<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>'), |
| 459 |
array('slug' => 'mxchat-content', 'label' => __('Content', 'mxchat'), 'svg' => '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>'), |
| 460 |
array('slug' => 'mxchat-api-access', 'label' => __('API Access', 'mxchat'), 'svg' => '<path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3m-3.5 3.5L19 4"/>'), |
| 461 |
array('slug' => 'mxchat-activation', 'label' => __('Pro & Extensions','mxchat'), 'svg' => '<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>'), |
| 462 |
); |
| 463 |
|
| 464 |
// Build a JS-shaped catalog for the wizard's client-side step machine. |
| 465 |
$js_catalog = array(); |
| 466 |
foreach ($catalog as $slug => $entry) { |
| 467 |
$js_catalog[$slug] = array( |
| 468 |
'label' => $entry['label'], |
| 469 |
'chatModels' => $entry['chat_models'], |
| 470 |
'embeddingModels' => $entry['embedding_models'], |
| 471 |
'hasKey' => $key_state[$slug], |
| 472 |
'requiresKeyToLoadModels' => !empty($entry['requires_key_to_load_models']), |
| 473 |
); |
| 474 |
} |
| 475 |
|
| 476 |
// Step metadata for the clickable pill indicator (plan-a2e4d6). Each entry: |
| 477 |
// - id: progress flag this step gates (null for Congrats) |
| 478 |
// - label: short pill label |
| 479 |
// - title: full step heading (also exposed for the legacy "Step N of M" |
| 480 |
// text-fallback) |
| 481 |
$steps_meta = array( |
| 482 |
array('num' => 1, 'flag' => 'chat_model', 'label' => __('Chat model', 'mxchat'), 'title' => __('Choose your chat model', 'mxchat')), |
| 483 |
array('num' => 2, 'flag' => 'behavior', 'label' => __('Behavior', 'mxchat'), 'title' => __('Tell your chatbot how to behave', 'mxchat')), |
| 484 |
array('num' => 3, 'flag' => 'embedding_model', 'label' => __('Embedding', 'mxchat'), 'title' => __('Choose your embedding model', 'mxchat')), |
| 485 |
array('num' => 4, 'flag' => 'knowledge_base', 'label' => __('Knowledge', 'mxchat'), 'title' => __('Add to your knowledge base', 'mxchat')), |
| 486 |
array('num' => 5, 'flag' => 'actions', 'label' => __('Actions', 'mxchat'), 'title' => __('Try MxChat Actions', 'mxchat')), |
| 487 |
array('num' => 6, 'flag' => null, 'label' => __('Done', 'mxchat'), 'title' => __('You\'re set up', 'mxchat')), |
| 488 |
); |
| 489 |
|
| 490 |
$wizard_config = array( |
| 491 |
'ajaxUrl' => admin_url('admin-ajax.php'), |
| 492 |
'nonce' => $wizard_nonce, |
| 493 |
'catalog' => $js_catalog, |
| 494 |
'initialStep' => (int) $initial_step, |
| 495 |
'progress' => $progress, |
| 496 |
'currentChatProvider' => $current_chat_provider, |
| 497 |
'currentChatModel' => $current_chat_model, |
| 498 |
'currentEmbedProvider'=> $current_embed_provider, |
| 499 |
'currentEmbedModel' => $current_embed_model, |
| 500 |
'currentInstructions' => $current_instructions, |
| 501 |
'kbCount' => mxchat_onboarding_kb_count(), |
| 502 |
'stepsMeta' => $steps_meta, |
| 503 |
'urls' => array( |
| 504 |
'kb' => admin_url('admin.php?page=mxchat-prompts'), |
| 505 |
'actions' => admin_url('admin.php?page=mxchat-actions'), |
| 506 |
'apiKeys' => admin_url('admin.php?page=mxchat-settings&tab=api-keys'), |
| 507 |
'homepage' => home_url('/'), |
| 508 |
'proAddons' => 'https://mxchat.ai/add-ons/', |
| 509 |
'settingsTesting' => admin_url('admin.php?page=mxchat-settings#testing'), |
| 510 |
'settingsDisplay' => admin_url('admin.php?page=mxchat-settings#chatbot-display'), |
| 511 |
), |
| 512 |
'strings' => array( |
| 513 |
'keyAlreadySaved' => __('%s API key already saved.', 'mxchat'), |
| 514 |
'embedKeyReused' => __('You\'ve already added your %s API key — using it for embeddings too.', 'mxchat'), |
| 515 |
'replaceKey' => __('Replace key', 'mxchat'), |
| 516 |
'saveKey' => __('Save key', 'mxchat'), |
| 517 |
'saving' => __('Saving…', 'mxchat'), |
| 518 |
'saved' => __('Saved', 'mxchat'), |
| 519 |
'saveError' => __('Save failed. Try again or set the key in Settings → API Keys.', 'mxchat'), |
| 520 |
'kbNone' => __('No knowledge base items yet.', 'mxchat'), |
| 521 |
/* translators: %d = number of KB items */ |
| 522 |
'kbFoundOne' => __('Found 1 knowledge base item.', 'mxchat'), |
| 523 |
/* translators: %d = number of KB items */ |
| 524 |
'kbFoundMany' => __('Found %d knowledge base items.', 'mxchat'), |
| 525 |
'manageAllKeys' => __('You can also manage all your keys later in API Keys settings.', 'mxchat'), |
| 526 |
'selectProvider' => __('— Select a provider —', 'mxchat'), |
| 527 |
'selectModel' => __('— Select a model —', 'mxchat'), |
| 528 |
'disabledHintOpenrouter' => __('OpenRouter requires setup in the main Settings page — finish onboarding, then configure it there.', 'mxchat'), |
| 529 |
'disabledHintCustom' => __('Custom (OpenAI-compatible) providers need a Base URL and model configured in Settings → API Keys — finish onboarding, then set it up there.', 'mxchat'), |
| 530 |
'shortcodeCopied' => __('Copied!', 'mxchat'), |
| 531 |
'shortcodeCopy' => __('Copy', 'mxchat'), |
| 532 |
), |
| 533 |
); |
| 534 |
?> |
| 535 |
<div class="mxch-onboarding-wrapper mxch-onboarding-wizard-wrapper"> |
| 536 |
|
| 537 |
<main class="mxch-content"> |
| 538 |
|
| 539 |
<div class="mxch-section active"> |
| 540 |
<div class="mxch-content-header"> |
| 541 |
<h1 class="mxch-content-title"><?php esc_html_e('Onboarding', 'mxchat'); ?></h1> |
| 542 |
<p class="mxch-content-subtitle"> |
| 543 |
<?php esc_html_e('Six quick steps to get your MxChat chatbot live.', 'mxchat'); ?> |
| 544 |
</p> |
| 545 |
</div> |
| 546 |
|
| 547 |
<div class="mxch-card mxch-wizard-card" id="mxch-onboarding-wizard"> |
| 548 |
<div class="mxch-wizard-progress" aria-hidden="false"> |
| 549 |
<!-- Clickable pill step indicator (plan-a2e4d6). The JS attaches |
| 550 |
click handlers + sets aria-current="step" on the active pill + |
| 551 |
toggles .is-complete / .is-current / .is-future as the user |
| 552 |
advances. Future steps are non-clickable. --> |
| 553 |
<nav class="mxch-wizard-pillnav" role="tablist" aria-label="<?php esc_attr_e('Onboarding steps', 'mxchat'); ?>"> |
| 554 |
<?php foreach ($steps_meta as $sm): |
| 555 |
$is_complete = ($sm['flag'] !== null && !empty($progress[$sm['flag']])) |
| 556 |
|| ($sm['flag'] === null && (int) $initial_step >= 6); |
| 557 |
$is_current = ((int) $initial_step === (int) $sm['num']); |
| 558 |
$cls = 'mxch-wizard-pill'; |
| 559 |
if ($is_complete && !$is_current) $cls .= ' is-complete'; |
| 560 |
if ($is_current) $cls .= ' is-current'; |
| 561 |
if (!$is_complete && !$is_current) $cls .= ' is-future'; |
| 562 |
?> |
| 563 |
<button type="button" |
| 564 |
class="<?php echo esc_attr($cls); ?>" |
| 565 |
data-mxch-pill-step="<?php echo (int) $sm['num']; ?>" |
| 566 |
<?php if ($is_current) echo 'aria-current="step"'; ?> |
| 567 |
<?php if (!$is_complete && !$is_current) echo 'disabled aria-disabled="true"'; ?>> |
| 568 |
<span class="mxch-wizard-pill-num" aria-hidden="true"> |
| 569 |
<svg class="mxch-wizard-pill-check" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg> |
| 570 |
<span class="mxch-wizard-pill-num-text"><?php echo (int) $sm['num']; ?></span> |
| 571 |
</span> |
| 572 |
<span class="mxch-wizard-pill-label"><?php echo esc_html($sm['label']); ?></span> |
| 573 |
</button> |
| 574 |
<?php endforeach; ?> |
| 575 |
</nav> |
| 576 |
<div class="mxch-wizard-progress-label"> |
| 577 |
<span class="mxch-wizard-step-label"><?php esc_html_e('Step', 'mxchat'); ?> <span data-mxch-current-step>1</span> <?php esc_html_e('of', 'mxchat'); ?> 6</span> |
| 578 |
<span class="mxch-wizard-step-name" data-mxch-step-name></span> |
| 579 |
</div> |
| 580 |
<div class="mxch-wizard-progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100"> |
| 581 |
<div class="mxch-wizard-progress-fill" data-mxch-progress-fill></div> |
| 582 |
</div> |
| 583 |
</div> |
| 584 |
|
| 585 |
<!-- STEP 1 — chat provider + model + key --> |
| 586 |
<section class="mxch-wizard-step" data-step="1" hidden> |
| 587 |
<h2 class="mxch-wizard-step-title"><?php esc_html_e('Choose your chat model', 'mxchat'); ?></h2> |
| 588 |
<p class="mxch-wizard-step-explainer"> |
| 589 |
<?php esc_html_e('This is the AI that will write replies in your chatbot. Different providers have different strengths and pricing. You can change this any time.', 'mxchat'); ?> |
| 590 |
</p> |
| 591 |
|
| 592 |
<div class="mxch-field"> |
| 593 |
<label class="mxch-field-label" for="mxch-wiz-chat-provider"><?php esc_html_e('Provider', 'mxchat'); ?></label> |
| 594 |
<select class="mxch-wiz-select" id="mxch-wiz-chat-provider" data-mxch-which="chat" data-mxch-role="provider"> |
| 595 |
<option value=""><?php echo esc_html($wizard_config['strings']['selectProvider']); ?></option> |
| 596 |
<?php foreach ($catalog as $slug => $entry): |
| 597 |
if (empty($entry['chat_models'])) continue; |
| 598 |
// Plan-23987f — OpenRouter (requires-key flow) AND |
| 599 |
// Custom (needs Base URL + model id in API Keys tab) |
| 600 |
// are both disabled in the wizard's static dropdown |
| 601 |
// via the unified `disable_in_onboarding` flag. |
| 602 |
$opt_disabled = !empty($entry['disable_in_onboarding']); |
| 603 |
$opt_label = $entry['label']; |
| 604 |
if ($opt_disabled) { |
| 605 |
/* translators: %s = provider label, e.g. OpenRouter */ |
| 606 |
$opt_label = sprintf(__('%s — configure in Settings', 'mxchat'), $entry['label']); |
| 607 |
} |
| 608 |
?> |
| 609 |
<option value="<?php echo esc_attr($slug); ?>" data-mxch-disabled-onboarding="<?php echo $opt_disabled ? '1' : '0'; ?>" <?php selected($current_chat_provider, $slug); ?><?php echo $opt_disabled ? ' disabled' : ''; ?>><?php echo esc_html($opt_label); ?></option> |
| 610 |
<?php endforeach; ?> |
| 611 |
</select> |
| 612 |
<p class="mxch-field-hint mxch-wiz-disabled-provider-hint"> |
| 613 |
<?php esc_html_e('OpenRouter and Custom (OpenAI-compatible) providers need extra configuration — finish onboarding, then set them up in Settings → API Keys.', 'mxchat'); ?> |
| 614 |
</p> |
| 615 |
</div> |
| 616 |
|
| 617 |
<div class="mxch-field mxch-wiz-model-field" data-mxch-which="chat" hidden> |
| 618 |
<label class="mxch-field-label" for="mxch-wiz-chat-model"><?php esc_html_e('Model', 'mxchat'); ?></label> |
| 619 |
<select class="mxch-wiz-select" id="mxch-wiz-chat-model" data-mxch-which="chat" data-mxch-role="model"></select> |
| 620 |
</div> |
| 621 |
|
| 622 |
<div class="mxch-field mxch-wiz-key-field" data-mxch-which="chat" hidden> |
| 623 |
<label class="mxch-field-label" data-mxch-key-label></label> |
| 624 |
<p class="mxch-field-description"><?php esc_html_e('An API key is a password from your AI provider that lets MxChat talk to them.', 'mxchat'); ?></p> |
| 625 |
<div class="mxch-wiz-key-row"> |
| 626 |
<input type="password" class="mxch-wiz-key-input" data-mxch-which="chat" autocomplete="new-password" data-lpignore="true" /> |
| 627 |
<button type="button" class="mxch-btn mxch-btn-primary mxch-btn-sm mxch-wiz-key-save" data-mxch-which="chat"><?php echo esc_html($wizard_config['strings']['saveKey']); ?></button> |
| 628 |
</div> |
| 629 |
<p class="mxch-field-hint"><?php echo wp_kses_post(sprintf( |
| 630 |
/* translators: %s = link to API Keys settings */ |
| 631 |
__('You can also manage all your keys later in %s.', 'mxchat'), |
| 632 |
'<a href="' . esc_url($wizard_config['urls']['apiKeys']) . '">' . esc_html__('API Keys settings', 'mxchat') . '</a>' |
| 633 |
)); ?></p> |
| 634 |
</div> |
| 635 |
|
| 636 |
<div class="mxch-wiz-key-saved" data-mxch-which="chat" hidden> |
| 637 |
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg> |
| 638 |
<span data-mxch-key-saved-text></span> |
| 639 |
<button type="button" class="mxch-wiz-replace-key-link" data-mxch-which="chat"><?php echo esc_html($wizard_config['strings']['replaceKey']); ?></button> |
| 640 |
</div> |
| 641 |
|
| 642 |
<div class="mxch-wiz-error" data-mxch-which="chat" hidden></div> |
| 643 |
|
| 644 |
<div class="mxch-wizard-actions"> |
| 645 |
<button type="button" class="mxch-btn mxch-btn-primary mxch-wiz-continue" data-mxch-from-step="1" disabled><?php esc_html_e('Continue', 'mxchat'); ?></button> |
| 646 |
</div> |
| 647 |
</section> |
| 648 |
|
| 649 |
<!-- STEP 2 — AI Behavior (system_prompt_instructions) — plan-a2e4d6. |
| 650 |
Re-uses the SAME mxchat_options['system_prompt_instructions'] |
| 651 |
binding Settings → Behavior uses. No parallel storage. The |
| 652 |
Sample Instructions modal is rendered once at the bottom of |
| 653 |
this page (after the wizard card) and shares the same DOM |
| 654 |
ids (mxchatViewSampleBtn / mxchatSampleModal) so the existing |
| 655 |
modal CSS in admin-style.css just works. --> |
| 656 |
<section class="mxch-wizard-step" data-step="2" hidden> |
| 657 |
<h2 class="mxch-wizard-step-title"><?php esc_html_e('Tell your chatbot how to behave', 'mxchat'); ?></h2> |
| 658 |
<p class="mxch-wizard-step-explainer"> |
| 659 |
<?php esc_html_e('These are the instructions your AI follows for every reply. Think of it as the chatbot\'s job description — what role it plays, what tone it uses, what topics it stays on or avoids. You can edit this any time from Settings → Behavior.', 'mxchat'); ?> |
| 660 |
</p> |
| 661 |
|
| 662 |
<div class="mxch-field"> |
| 663 |
<label class="mxch-field-label" for="mxch-wiz-behavior-textarea"><?php esc_html_e('AI Instructions', 'mxchat'); ?></label> |
| 664 |
<textarea id="mxch-wiz-behavior-textarea" class="mxch-wiz-behavior-textarea" rows="6" placeholder="<?php esc_attr_e('Describe how your chatbot should respond — its role, tone, and topics to focus on or avoid.', 'mxchat'); ?>"><?php echo esc_textarea($current_instructions); ?></textarea> |
| 665 |
<p class="mxch-field-hint"> |
| 666 |
<?php esc_html_e('Optional — leave blank to use sensible defaults. You can refine this later.', 'mxchat'); ?> |
| 667 |
</p> |
| 668 |
</div> |
| 669 |
|
| 670 |
<div class="mxch-wiz-behavior-actions-row"> |
| 671 |
<button type="button" class="mxchat-instructions-btn" id="mxchatViewSampleBtn"> |
| 672 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 673 |
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/> |
| 674 |
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/> |
| 675 |
</svg> |
| 676 |
<?php esc_html_e('View Sample Instructions', 'mxchat'); ?> |
| 677 |
</button> |
| 678 |
</div> |
| 679 |
|
| 680 |
<p class="mxch-wiz-behavior-examples-label"> |
| 681 |
<?php esc_html_e('Or start from one of these:', 'mxchat'); ?> |
| 682 |
</p> |
| 683 |
<div class="mxch-wiz-behavior-examples"> |
| 684 |
<button type="button" class="mxch-wiz-behavior-example" data-mxch-example="helpful"> |
| 685 |
<span class="mxch-wiz-behavior-example-title"><?php esc_html_e('Helpful website assistant', 'mxchat'); ?></span> |
| 686 |
<span class="mxch-wiz-behavior-example-desc"><?php esc_html_e('General-purpose, concise, sticks to your site\'s content.', 'mxchat'); ?></span> |
| 687 |
</button> |
| 688 |
<button type="button" class="mxch-wiz-behavior-example" data-mxch-example="sales"> |
| 689 |
<span class="mxch-wiz-behavior-example-title"><?php esc_html_e('Sales-focused product expert', 'mxchat'); ?></span> |
| 690 |
<span class="mxch-wiz-behavior-example-desc"><?php esc_html_e('Highlights features, suggests products, drives toward CTAs.', 'mxchat'); ?></span> |
| 691 |
</button> |
| 692 |
<button type="button" class="mxch-wiz-behavior-example" data-mxch-example="support"> |
| 693 |
<span class="mxch-wiz-behavior-example-title"><?php esc_html_e('Friendly customer support agent', 'mxchat'); ?></span> |
| 694 |
<span class="mxch-wiz-behavior-example-desc"><?php esc_html_e('Patient, empathetic, troubleshoots, escalates when stuck.', 'mxchat'); ?></span> |
| 695 |
</button> |
| 696 |
</div> |
| 697 |
|
| 698 |
<div class="mxch-wiz-error" data-mxch-which="behavior" hidden></div> |
| 699 |
|
| 700 |
<div class="mxch-wizard-actions"> |
| 701 |
<button type="button" class="mxch-btn mxch-btn-secondary mxch-wiz-back" data-mxch-from-step="2"><?php esc_html_e('Back', 'mxchat'); ?></button> |
| 702 |
<button type="button" class="mxch-btn mxch-btn-primary mxch-wiz-continue" data-mxch-from-step="2"><?php esc_html_e('Continue', 'mxchat'); ?></button> |
| 703 |
</div> |
| 704 |
</section> |
| 705 |
|
| 706 |
<!-- STEP 3 — embedding provider + model + (maybe) key --> |
| 707 |
<section class="mxch-wizard-step" data-step="3" hidden> |
| 708 |
<h2 class="mxch-wizard-step-title"><?php esc_html_e('Choose your embedding model', 'mxchat'); ?></h2> |
| 709 |
<p class="mxch-wizard-step-explainer"> |
| 710 |
<?php esc_html_e('Embeddings turn your website content and knowledge base into a format MxChat can search through — this is what makes your chatbot "know" your stuff. You only need this if you\'ll use a knowledge base, but most users do.', 'mxchat'); ?> |
| 711 |
</p> |
| 712 |
|
| 713 |
<div class="mxch-field"> |
| 714 |
<label class="mxch-field-label" for="mxch-wiz-embed-provider"><?php esc_html_e('Provider', 'mxchat'); ?></label> |
| 715 |
<select class="mxch-wiz-select" id="mxch-wiz-embed-provider" data-mxch-which="embedding" data-mxch-role="provider"> |
| 716 |
<option value=""><?php echo esc_html($wizard_config['strings']['selectProvider']); ?></option> |
| 717 |
<?php foreach ($catalog as $slug => $entry): |
| 718 |
if (empty($entry['embedding_models'])) continue; ?> |
| 719 |
<option value="<?php echo esc_attr($slug); ?>" <?php selected($current_embed_provider, $slug); ?>><?php echo esc_html($entry['label']); ?></option> |
| 720 |
<?php endforeach; ?> |
| 721 |
</select> |
| 722 |
</div> |
| 723 |
|
| 724 |
<div class="mxch-field mxch-wiz-model-field" data-mxch-which="embedding" hidden> |
| 725 |
<label class="mxch-field-label" for="mxch-wiz-embed-model"><?php esc_html_e('Model', 'mxchat'); ?></label> |
| 726 |
<select class="mxch-wiz-select" id="mxch-wiz-embed-model" data-mxch-which="embedding" data-mxch-role="model"></select> |
| 727 |
</div> |
| 728 |
|
| 729 |
<!-- Dedup case: same provider as Step 1 + key already saved --> |
| 730 |
<div class="mxch-wiz-key-dedup" data-mxch-which="embedding" hidden> |
| 731 |
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg> |
| 732 |
<span data-mxch-dedup-text></span> |
| 733 |
</div> |
| 734 |
|
| 735 |
<div class="mxch-field mxch-wiz-key-field" data-mxch-which="embedding" hidden> |
| 736 |
<label class="mxch-field-label" data-mxch-key-label></label> |
| 737 |
<p class="mxch-field-description"><?php esc_html_e('An API key is a password from your AI provider that lets MxChat talk to them.', 'mxchat'); ?></p> |
| 738 |
<div class="mxch-wiz-key-row"> |
| 739 |
<input type="password" class="mxch-wiz-key-input" data-mxch-which="embedding" autocomplete="new-password" data-lpignore="true" /> |
| 740 |
<button type="button" class="mxch-btn mxch-btn-primary mxch-btn-sm mxch-wiz-key-save" data-mxch-which="embedding"><?php echo esc_html($wizard_config['strings']['saveKey']); ?></button> |
| 741 |
</div> |
| 742 |
<p class="mxch-field-hint"><?php echo wp_kses_post(sprintf( |
| 743 |
__('You can also manage all your keys later in %s.', 'mxchat'), |
| 744 |
'<a href="' . esc_url($wizard_config['urls']['apiKeys']) . '">' . esc_html__('API Keys settings', 'mxchat') . '</a>' |
| 745 |
)); ?></p> |
| 746 |
</div> |
| 747 |
|
| 748 |
<div class="mxch-wiz-key-saved" data-mxch-which="embedding" hidden> |
| 749 |
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg> |
| 750 |
<span data-mxch-key-saved-text></span> |
| 751 |
<button type="button" class="mxch-wiz-replace-key-link" data-mxch-which="embedding"><?php echo esc_html($wizard_config['strings']['replaceKey']); ?></button> |
| 752 |
</div> |
| 753 |
|
| 754 |
<div class="mxch-wiz-error" data-mxch-which="embedding" hidden></div> |
| 755 |
|
| 756 |
<!-- Vector-store informational note (plan-23987f). Pinecone and |
| 757 |
OpenAI Vector Store are alternative *databases* (not embedding |
| 758 |
models) — configured under Knowledge after onboarding. --> |
| 759 |
<div class="mxch-wiz-vector-store-note"> |
| 760 |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg> |
| 761 |
<span><?php echo wp_kses_post(sprintf( |
| 762 |
/* translators: %s = link to Knowledge page */ |
| 763 |
__('By default MxChat stores embeddings in your WordPress database. After onboarding you can switch to %s for larger knowledge bases.', 'mxchat'), |
| 764 |
'<a href="' . esc_url($wizard_config['urls']['kb']) . '" target="_blank" rel="noopener noreferrer">' . esc_html__('Pinecone or OpenAI Vector Store', 'mxchat') . '</a>' |
| 765 |
)); ?></span> |
| 766 |
</div> |
| 767 |
|
| 768 |
<div class="mxch-wizard-actions"> |
| 769 |
<button type="button" class="mxch-btn mxch-btn-secondary mxch-wiz-back" data-mxch-from-step="3"><?php esc_html_e('Back', 'mxchat'); ?></button> |
| 770 |
<button type="button" class="mxch-btn mxch-btn-primary mxch-wiz-continue" data-mxch-from-step="3" disabled><?php esc_html_e('Continue', 'mxchat'); ?></button> |
| 771 |
</div> |
| 772 |
</section> |
| 773 |
|
| 774 |
<!-- STEP 4 — KB seed (optional, mirrors Actions) --> |
| 775 |
<section class="mxch-wizard-step" data-step="4" hidden> |
| 776 |
<h2 class="mxch-wizard-step-title"><?php esc_html_e('Add something to your knowledge base', 'mxchat'); ?></h2> |
| 777 |
<p class="mxch-wizard-step-explainer"> |
| 778 |
<?php esc_html_e('Your knowledge base is the content MxChat uses to answer questions about your site — pages, posts, PDFs, or custom text. Add some now if you\'d like, or skip this and build it later from the Knowledge page.', 'mxchat'); ?> |
| 779 |
</p> |
| 780 |
|
| 781 |
<div class="mxch-wiz-cta-row"> |
| 782 |
<a class="mxch-btn mxch-btn-primary" href="<?php echo esc_url($wizard_config['urls']['kb']); ?>" target="_blank" rel="noopener noreferrer"> |
| 783 |
<?php esc_html_e('Open Knowledge Base', 'mxchat'); ?> |
| 784 |
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> |
| 785 |
</a> |
| 786 |
</div> |
| 787 |
|
| 788 |
<div class="mxch-wizard-actions"> |
| 789 |
<button type="button" class="mxch-btn mxch-btn-secondary mxch-wiz-back" data-mxch-from-step="4"><?php esc_html_e('Back', 'mxchat'); ?></button> |
| 790 |
<button type="button" class="mxch-btn mxch-btn-secondary mxch-wiz-continue" data-mxch-from-step="4"><?php esc_html_e('I\'ll skip this for now — Continue', 'mxchat'); ?></button> |
| 791 |
</div> |
| 792 |
</section> |
| 793 |
|
| 794 |
<!-- STEP 5 — Actions (optional) --> |
| 795 |
<section class="mxch-wizard-step" data-step="5" hidden> |
| 796 |
<h2 class="mxch-wizard-step-title"><?php esc_html_e('Try MxChat Actions', 'mxchat'); ?></h2> |
| 797 |
<p class="mxch-wizard-step-explainer"> |
| 798 |
<?php esc_html_e('Actions let your chatbot do things, not just answer. When a visitor\'s message matches phrases you choose, MxChat can capture their email to a Loops list, search the web and images with Brave, generate an image with OpenAI or Gemini, answer questions about a PDF you\'ve uploaded, or hand the conversation off to a human agent on Slack or Telegram. This step is optional — skip it now and set up Actions any time.', 'mxchat'); ?> |
| 799 |
</p> |
| 800 |
|
| 801 |
<div class="mxch-wiz-cta-row"> |
| 802 |
<a class="mxch-btn mxch-btn-primary" href="<?php echo esc_url($wizard_config['urls']['actions']); ?>" target="_blank" rel="noopener noreferrer"> |
| 803 |
<?php esc_html_e('Open Actions', 'mxchat'); ?> |
| 804 |
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left:6px;"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> |
| 805 |
</a> |
| 806 |
</div> |
| 807 |
|
| 808 |
<div class="mxch-wizard-actions"> |
| 809 |
<button type="button" class="mxch-btn mxch-btn-secondary mxch-wiz-back" data-mxch-from-step="5"><?php esc_html_e('Back', 'mxchat'); ?></button> |
| 810 |
<button type="button" class="mxch-btn mxch-btn-secondary mxch-wiz-continue" data-mxch-from-step="5"><?php esc_html_e('I\'ll skip this for now — Continue', 'mxchat'); ?></button> |
| 811 |
</div> |
| 812 |
</section> |
| 813 |
|
| 814 |
<!-- STEP 6 — Congrats (plan-23987f rebuild: 3 next-step cards) --> |
| 815 |
<section class="mxch-wizard-step mxch-wizard-step-congrats" data-step="6" hidden> |
| 816 |
<div class="mxch-wiz-congrats-icon"> |
| 817 |
<svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg> |
| 818 |
</div> |
| 819 |
<h2 class="mxch-wizard-step-title mxch-wizard-step-title-congrats">🎉 <?php esc_html_e('You\'re set up.', 'mxchat'); ?></h2> |
| 820 |
|
| 821 |
<div class="mxch-wiz-nextsteps-grid"> |
| 822 |
|
| 823 |
<!-- Card 1 — Test on Settings → Testing tab --> |
| 824 |
<a class="mxch-wiz-nextstep-card" href="<?php echo esc_url($wizard_config['urls']['settingsTesting']); ?>"> |
| 825 |
<div class="mxch-wiz-nextstep-icon"> |
| 826 |
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> |
| 827 |
</div> |
| 828 |
<h3 class="mxch-wiz-nextstep-title"><?php esc_html_e('Test your chatbot', 'mxchat'); ?></h3> |
| 829 |
<p class="mxch-wiz-nextstep-desc"><?php esc_html_e('Try it right inside your dashboard — no need to visit your site.', 'mxchat'); ?></p> |
| 830 |
<span class="mxch-wiz-nextstep-cta"><?php esc_html_e('Open Testing tab', 'mxchat'); ?> |
| 831 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> |
| 832 |
</span> |
| 833 |
</a> |
| 834 |
|
| 835 |
<!-- Card 2 — Show it on the site --> |
| 836 |
<a class="mxch-wiz-nextstep-card" href="<?php echo esc_url($wizard_config['urls']['settingsDisplay']); ?>"> |
| 837 |
<div class="mxch-wiz-nextstep-icon"> |
| 838 |
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg> |
| 839 |
</div> |
| 840 |
<h3 class="mxch-wiz-nextstep-title"><?php esc_html_e('Show it on your site', 'mxchat'); ?></h3> |
| 841 |
<p class="mxch-wiz-nextstep-desc"><?php esc_html_e('Turn the chatbot on for all pages, or hide it — your choice.', 'mxchat'); ?></p> |
| 842 |
<span class="mxch-wiz-nextstep-cta"><?php esc_html_e('Open Display settings', 'mxchat'); ?> |
| 843 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> |
| 844 |
</span> |
| 845 |
</a> |
| 846 |
|
| 847 |
<!-- Card 3 — Embed code shortcodes --> |
| 848 |
<div class="mxch-wiz-nextstep-card mxch-wiz-nextstep-card-embed"> |
| 849 |
<div class="mxch-wiz-nextstep-icon"> |
| 850 |
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg> |
| 851 |
</div> |
| 852 |
<h3 class="mxch-wiz-nextstep-title"><?php esc_html_e('Or embed it manually', 'mxchat'); ?></h3> |
| 853 |
<p class="mxch-wiz-nextstep-desc"><?php esc_html_e('Prefer to place it yourself? Paste a shortcode anywhere.', 'mxchat'); ?></p> |
| 854 |
|
| 855 |
<div class="mxch-wiz-shortcode-row"> |
| 856 |
<code class="mxch-wiz-shortcode" data-mxch-shortcode='[mxchat_chatbot floating="yes"]'>[mxchat_chatbot floating="yes"]</code> |
| 857 |
<button type="button" class="mxch-wiz-shortcode-copy" data-mxch-copy-shortcode='[mxchat_chatbot floating="yes"]' aria-label="<?php esc_attr_e('Copy floating widget shortcode', 'mxchat'); ?>"> |
| 858 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> |
| 859 |
<span class="mxch-wiz-shortcode-copy-text"><?php esc_html_e('Copy', 'mxchat'); ?></span> |
| 860 |
</button> |
| 861 |
</div> |
| 862 |
<p class="mxch-wiz-shortcode-caption"><?php esc_html_e('Floating widget (bottom corner)', 'mxchat'); ?></p> |
| 863 |
|
| 864 |
<div class="mxch-wiz-shortcode-row"> |
| 865 |
<code class="mxch-wiz-shortcode" data-mxch-shortcode='[mxchat_chatbot floating="no"]'>[mxchat_chatbot floating="no"]</code> |
| 866 |
<button type="button" class="mxch-wiz-shortcode-copy" data-mxch-copy-shortcode='[mxchat_chatbot floating="no"]' aria-label="<?php esc_attr_e('Copy inline widget shortcode', 'mxchat'); ?>"> |
| 867 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg> |
| 868 |
<span class="mxch-wiz-shortcode-copy-text"><?php esc_html_e('Copy', 'mxchat'); ?></span> |
| 869 |
</button> |
| 870 |
</div> |
| 871 |
<p class="mxch-wiz-shortcode-caption"><?php esc_html_e('Inline embedded chat', 'mxchat'); ?></p> |
| 872 |
</div> |
| 873 |
|
| 874 |
</div> |
| 875 |
|
| 876 |
<!-- PRO add-ons conversion block (plan-9451be) --> |
| 877 |
<a class="mxch-wiz-pro-promo" href="<?php echo esc_url($wizard_config['urls']['proAddons']); ?>" target="_blank" rel="noopener noreferrer"> |
| 878 |
<span class="mxch-wiz-pro-promo-badge"><?php esc_html_e('PRO add-ons', 'mxchat'); ?></span> |
| 879 |
<div class="mxch-wiz-pro-promo-body"> |
| 880 |
<h3 class="mxch-wiz-pro-promo-title"><?php esc_html_e('Do more with PRO add-ons', 'mxchat'); ?></h3> |
| 881 |
<p class="mxch-wiz-pro-promo-desc"> |
| 882 |
<?php esc_html_e('Sell directly in chat with WooCommerce, run multiple specialized bots on one site, generate full SEO-ready posts with Advanced Content, and more.', 'mxchat'); ?> |
| 883 |
</p> |
| 884 |
</div> |
| 885 |
<span class="mxch-wiz-pro-promo-cta"> |
| 886 |
<?php esc_html_e('Explore PRO add-ons', 'mxchat'); ?> |
| 887 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> |
| 888 |
</span> |
| 889 |
</a> |
| 890 |
|
| 891 |
<p class="mxch-wiz-congrats-graduated" id="mxch-wiz-graduated-line"> |
| 892 |
<?php |
| 893 |
$mxch_wiz_tutorials_url = esc_url(admin_url('admin.php?page=mxchat-settings#tutorials')); |
| 894 |
printf( |
| 895 |
/* translators: %s: bold link to "Settings → Tutorials" */ |
| 896 |
wp_kses( |
| 897 |
__('This setup guide moves out of the way once you\'re done — reopen it any time under %s.', 'mxchat'), |
| 898 |
array('strong' => array(), 'a' => array('href' => array())) |
| 899 |
), |
| 900 |
'<strong><a href="' . $mxch_wiz_tutorials_url . '">' . esc_html__('Settings → Tutorials', 'mxchat') . '</a></strong>' |
| 901 |
); |
| 902 |
?> |
| 903 |
</p> |
| 904 |
|
| 905 |
<div class="mxch-wiz-congrats-footer"> |
| 906 |
<button type="button" class="mxch-wiz-congrats-footer-link mxch-wiz-back" data-mxch-from-step="6"><?php esc_html_e('Review earlier steps', 'mxchat'); ?></button> |
| 907 |
<a class="mxch-wiz-congrats-footer-link" href="<?php echo esc_url($wizard_config['urls']['homepage']); ?>" target="_blank" rel="noopener noreferrer"><?php esc_html_e('Open my live site', 'mxchat'); ?></a> |
| 908 |
</div> |
| 909 |
</section> |
| 910 |
|
| 911 |
</div> |
| 912 |
|
| 913 |
<!-- Need help? — escape hatch (preserved from f7c7d4) --> |
| 914 |
<div class="mxch-card mxch-onboarding-help" id="mxch-onboarding-help"> |
| 915 |
<div class="mxch-card-body"> |
| 916 |
<div class="mxch-help-row"> |
| 917 |
<div> |
| 918 |
<h3 class="mxch-help-title"><?php esc_html_e('Stuck? Get help.', 'mxchat'); ?></h3> |
| 919 |
<p class="mxch-help-subtitle"><?php esc_html_e('Ask the docs bot for an answer, or open a ticket if something\'s broken.', 'mxchat'); ?></p> |
| 920 |
</div> |
| 921 |
<div class="mxch-help-buttons"> |
| 922 |
<a class="mxch-btn mxch-btn-secondary mxch-btn-sm" href="https://mxchat.ai/documentation-bot/" target="_blank" rel="noopener noreferrer"> |
| 923 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:6px;"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg> |
| 924 |
<?php esc_html_e('Ask the docs bot', 'mxchat'); ?> |
| 925 |
</a> |
| 926 |
<a class="mxch-btn mxch-btn-secondary mxch-btn-sm" href="https://wordpress.org/support/plugin/mxchat-basic/" target="_blank" rel="noopener noreferrer"> |
| 927 |
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:6px;"><path d="M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v5Z"/><path d="M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"/></svg> |
| 928 |
<?php esc_html_e('Open a support ticket', 'mxchat'); ?> |
| 929 |
</a> |
| 930 |
</div> |
| 931 |
</div> |
| 932 |
</div> |
| 933 |
</div> |
| 934 |
|
| 935 |
<!-- Dismiss onboarding — bottom of page, ghost-styled, low visual weight |
| 936 |
so users don't tap it by accident. Plan-d14e89 Issue 7. --> |
| 937 |
<p class="mxch-onboarding-dismiss-row"> |
| 938 |
<button type="button" |
| 939 |
class="mxch-onboarding-dismiss-link mxch-onboarding-dismiss" |
| 940 |
data-mxch-dismiss-nonce="<?php echo esc_attr($dismiss_nonce); ?>" |
| 941 |
aria-describedby="mxch-onboarding-dismiss-hint"> |
| 942 |
<?php esc_html_e('Dismiss onboarding', 'mxchat'); ?> |
| 943 |
</button> |
| 944 |
<span class="mxch-onboarding-dismiss-hint" id="mxch-onboarding-dismiss-hint"> |
| 945 |
<?php esc_html_e('Hide the setup guide from the menu — reopen it any time under Settings → Tutorials.', 'mxchat'); ?> |
| 946 |
</span> |
| 947 |
</p> |
| 948 |
</div> |
| 949 |
|
| 950 |
</main> |
| 951 |
</div> |
| 952 |
|
| 953 |
<?php |
| 954 |
// Render the Sample Instructions modal markup once at the end of the page, |
| 955 |
// matching the Settings modal exactly (same DOM ids → same admin-style.css |
| 956 |
// styling + same UX expectations). admin-onboarding-wizard.js wires the |
| 957 |
// show/hide handlers locally so we don't need to enqueue the heavy |
| 958 |
// mxchat-admin.js on this page just for the modal. |
| 959 |
// Content kept verbatim with class-mxchat-admin.php::render_sample_instructions_modal() |
| 960 |
// so users see the same sample no matter where they invoked the modal from. |
| 961 |
?> |
| 962 |
<div class="mxchat-instructions-modal-overlay" id="mxchatSampleModal"> |
| 963 |
<div class="mxchat-instructions-modal-content"> |
| 964 |
<div class="mxchat-instructions-modal-header"> |
| 965 |
<h3 class="mxchat-instructions-modal-title"> |
| 966 |
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 967 |
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/> |
| 968 |
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/> |
| 969 |
</svg> |
| 970 |
<?php esc_html_e('Sample AI Instructions', 'mxchat'); ?> |
| 971 |
</h3> |
| 972 |
<button type="button" class="mxchat-instructions-modal-close" id="mxchatModalClose"> |
| 973 |
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 974 |
<line x1="18" y1="6" x2="6" y2="18"/> |
| 975 |
<line x1="6" y1="6" x2="18" y2="18"/> |
| 976 |
</svg> |
| 977 |
</button> |
| 978 |
</div> |
| 979 |
<div class="mxchat-instructions-modal-body"> |
| 980 |
<div class="mxchat-instructions-content"><?php echo esc_html('You are an AI Chatbot assistant for this website. Your main goal is to assist visitors with questions and provide helpful information. Here are your key guidelines: |
| 981 |
|
| 982 |
# Response Style - CRITICALLY IMPORTANT |
| 983 |
- MAXIMUM LENGTH: 1-3 short sentences per response |
| 984 |
- Ultra-concise: Get straight to the answer with no filler |
| 985 |
- No introductions like "Sure!" or "I\'d be happy to help" |
| 986 |
- No phrases like "based on my knowledge" or "according to information" |
| 987 |
- No explanatory text before giving the answer |
| 988 |
- No summaries or repetition |
| 989 |
- Hyperlink all URLs |
| 990 |
- Respond in user\'s language |
| 991 |
- Minor chit chat or conversation is okay, but try to keep it focused on [insert topic] |
| 992 |
|
| 993 |
# Knowledge Base Requirements - PREVENT HALLUCINATIONS |
| 994 |
- ONLY answer using information explicitly provided in OFFICIAL KNOWLEDGE DATABASE CONTENT sections marked with ===== delimiters |
| 995 |
- If required information is NOT in the knowledge database: "I don\'t have enough information in my knowledge base to answer that question accurately." |
| 996 |
- NEVER invent or hallucinate URLs, links, product specs, procedures, dates, statistics, names, contacts, or company information |
| 997 |
- When knowledge base information is unclear or contradictory, acknowledge the limitation rather than guessing |
| 998 |
- Better to admit insufficient information than provide inaccurate answers'); ?></div> |
| 999 |
<button type="button" class="mxchat-instructions-copy-btn" id="mxchatCopyBtn"> |
| 1000 |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 1001 |
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/> |
| 1002 |
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/> |
| 1003 |
</svg> |
| 1004 |
<?php esc_html_e('Copy to clipboard', 'mxchat'); ?> |
| 1005 |
</button> |
| 1006 |
</div> |
| 1007 |
</div> |
| 1008 |
</div> |
| 1009 |
|
| 1010 |
<script> |
| 1011 |
window.MxChatOnboardingWizard = <?php echo wp_json_encode($wizard_config); ?>; |
| 1012 |
</script> |
| 1013 |
<?php |
| 1014 |
} |
| 1015 |
|