PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.79
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.79
51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 All 40 releases
king-addons / includes / admin / layouts / ai-settings-page.php

ai-settings-page.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.79, at includes/admin/layouts/ai-settings-page.php

400 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * AI Settings page - V3 Premium style inspired Design.
4 *
5 * @package King_Addons
6 */
7
8 if (!defined('ABSPATH')) {
9 exit;
10 }
11
12 $ka_ai_provider = \King_Addons\AI_Provider::getProvider();
13 $ka_ai_provider_label = \King_Addons\AI_Provider::getLabel($ka_ai_provider);
14
15 // Theme mode is per-user
16 $theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
17 $allowed_theme_modes = ['dark', 'light', 'auto'];
18 if (!in_array($theme_mode, $allowed_theme_modes, true)) {
19 $theme_mode = 'dark';
20 }
21
22 // Enqueue shared V3 styles
23 wp_enqueue_style(
24 'king-addons-admin-v3',
25 KING_ADDONS_URL . 'includes/admin/layouts/shared/admin-v3-styles.css',
26 [],
27 KING_ADDONS_VERSION
28 );
29 ?>
30 <script>
31 (function() {
32 document.body.classList.add('ka-admin-v3');
33
34 const mode = '<?php echo esc_js($theme_mode); ?>';
35 const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
36 const isDark = mode === 'auto' ? !!(mql && mql.matches) : mode === 'dark';
37
38 document.documentElement.classList.toggle('ka-v3-dark', isDark);
39 document.body.classList.toggle('ka-v3-dark', isDark);
40 })();
41 </script>
42
43 <style>
44 /*
45 * Rows of the provider that is not selected. The class is applied server side so
46 * there is no flash of both providers' fields, and the settings script toggles
47 * the same class when the provider changes.
48 */
49 .ka-ai-settings .ka-ai-row-hidden {
50 display: none;
51 }
52
53 /* AI Settings V3 */
54 .ka-ai-settings .form-table {
55 margin: 0;
56 width: 100%;
57 }
58
59 .ka-ai-settings .form-table th,
60 .ka-ai-settings .form-table td {
61 padding: 18px 0;
62 border-bottom: 1px solid rgba(0, 0, 0, 0.04);
63 vertical-align: top;
64 }
65
66 body.ka-v3-dark .ka-ai-settings .form-table th,
67 body.ka-v3-dark .ka-ai-settings .form-table td {
68 border-bottom-color: rgba(255, 255, 255, 0.04);
69 }
70
71 .ka-ai-settings .form-table tr:last-child th,
72 .ka-ai-settings .form-table tr:last-child td {
73 border-bottom: none;
74 }
75
76 .ka-ai-settings .form-table th {
77 width: 200px;
78 font-size: 15px;
79 font-weight: 500;
80 color: #1d1d1f;
81 padding-right: 20px;
82 }
83
84 body.ka-v3-dark .ka-ai-settings .form-table th {
85 color: #f5f5f7;
86 }
87
88 .ka-ai-settings .form-table td {
89 color: #1d1d1f;
90 }
91
92 body.ka-v3-dark .ka-ai-settings .form-table td {
93 color: #f5f5f7;
94 }
95
96 .ka-ai-settings input[type="text"],
97 .ka-ai-settings input[type="password"],
98 .ka-ai-settings input[type="number"],
99 .ka-ai-settings textarea,
100 .ka-ai-settings select {
101 width: 100%;
102 max-width: 400px;
103 padding: 12px 16px;
104 border: 1px solid rgba(0, 0, 0, 0.1);
105 border-radius: 12px;
106 font-size: 15px;
107 font-family: inherit;
108 background-color: #fff;
109 transition: border-color 0.2s, box-shadow 0.2s;
110 }
111
112 body.ka-v3-dark .ka-ai-settings input[type="text"],
113 body.ka-v3-dark .ka-ai-settings input[type="password"],
114 body.ka-v3-dark .ka-ai-settings input[type="number"],
115 body.ka-v3-dark .ka-ai-settings textarea,
116 body.ka-v3-dark .ka-ai-settings select {
117 background-color: #2c2c2e;
118 border-color: rgba(255, 255, 255, 0.1);
119 color: #f5f5f7;
120 }
121
122 .ka-ai-settings input:focus,
123 .ka-ai-settings textarea:focus,
124 .ka-ai-settings select:focus {
125 outline: none;
126 border-color: #8b5cf6;
127 box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.1);
128 }
129
130 body.ka-v3-dark .ka-ai-settings input:focus,
131 body.ka-v3-dark .ka-ai-settings textarea:focus,
132 body.ka-v3-dark .ka-ai-settings select:focus {
133 border-color: #a78bfa;
134 box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.2);
135 }
136
137 .ka-ai-settings .description {
138 font-size: 13px;
139 color: #86868b;
140 margin-top: 8px;
141 line-height: 1.5;
142 }
143
144 .ka-admin-wrap.ka-ai-settings select {
145 -webkit-appearance: none;
146 -moz-appearance: none;
147 appearance: none;
148 background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3e%3cpath fill='%2386868b' d='M6 8L0 0h12z'/%3e%3c/svg%3e");
149 background-repeat: no-repeat;
150 background-position: right 16px center;
151 background-size: 10px 6px;
152 padding-right: 44px;
153 }
154
155 body.ka-v3-dark .ka-admin-wrap.ka-ai-settings select {
156 background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3e%3cpath fill='%23a1a1a6' d='M6 8L0 0h12z'/%3e%3c/svg%3e");
157 }
158
159 /* Section titles */
160 .ka-ai-settings .ka-card-body h2 {
161 font-size: 17px;
162 font-weight: 600;
163 color: #1d1d1f;
164 margin: 24px 0 8px 0;
165 padding: 24px 0 0 0;
166 border-top: 1px solid rgba(0, 0, 0, 0.04);
167 }
168
169 body.ka-v3-dark .ka-ai-settings .ka-card-body h2 {
170 color: #f5f5f7;
171 border-top-color: rgba(255, 255, 255, 0.04);
172 }
173
174 .ka-ai-settings .ka-card-body h2:first-of-type {
175 margin-top: 0;
176 padding-top: 0;
177 border-top: none;
178 }
179
180 .ka-ai-settings .ka-card-body h2 + p {
181 color: #86868b;
182 font-size: 14px;
183 margin: 0 0 16px 0;
184 }
185
186 /* Button styles */
187 .ka-ai-settings .button {
188 padding: 10px 20px;
189 border-radius: 980px;
190 font-size: 14px;
191 font-weight: 400;
192 background: rgba(0, 0, 0, 0.06);
193 border: none;
194 color: #1d1d1f;
195 cursor: pointer;
196 transition: all 0.2s;
197 }
198
199 body.ka-v3-dark .ka-ai-settings .button {
200 background: rgba(255, 255, 255, 0.1);
201 color: #f5f5f7;
202 }
203
204 .ka-ai-settings .button:hover {
205 background: rgba(0, 0, 0, 0.1);
206 }
207
208 body.ka-v3-dark .ka-ai-settings .button:hover {
209 background: rgba(255, 255, 255, 0.15);
210 }
211 </style>
212
213 <div class="ka-admin-wrap ka-ai-settings">
214 <?php settings_errors('king_addons_ai'); ?>
215 <!-- Header -->
216 <div class="ka-admin-header">
217 <div class="ka-admin-header-left">
218 <div class="ka-admin-header-icon purple">
219 <span class="dashicons dashicons-admin-generic"></span>
220 </div>
221 <div>
222 <h1 class="ka-admin-title"><?php esc_html_e('AI Settings', 'king-addons'); ?></h1>
223 <p class="ka-admin-subtitle"><?php esc_html_e('Configure your AI provider and AI features for the Elementor editor', 'king-addons'); ?></p>
224 </div>
225 </div>
226 <div class="ka-admin-header-actions">
227 <div class="ka-v3-segmented" id="ka-v3-theme-segment" role="radiogroup" aria-label="<?php echo esc_attr(esc_html__('Theme', 'king-addons')); ?>" data-active="<?php echo esc_attr($theme_mode); ?>">
228 <span class="ka-v3-segmented-indicator" aria-hidden="true"></span>
229 <button type="button" class="ka-v3-segmented-btn" data-theme="light" aria-pressed="<?php echo $theme_mode === 'light' ? 'true' : 'false'; ?>">
230 <span class="ka-v3-segmented-icon" aria-hidden="true">☀︎</span>
231 <?php esc_html_e('Light', 'king-addons'); ?>
232 </button>
233 <button type="button" class="ka-v3-segmented-btn" data-theme="dark" aria-pressed="<?php echo $theme_mode === 'dark' ? 'true' : 'false'; ?>">
234 <span class="ka-v3-segmented-icon" aria-hidden="true">☾</span>
235 <?php esc_html_e('Dark', 'king-addons'); ?>
236 </button>
237 <button type="button" class="ka-v3-segmented-btn" data-theme="auto" aria-pressed="<?php echo $theme_mode === 'auto' ? 'true' : 'false'; ?>">
238 <span class="ka-v3-segmented-icon" aria-hidden="true">◐</span>
239 <?php esc_html_e('Auto', 'king-addons'); ?>
240 </button>
241 </div>
242 <a href="<?php echo esc_url(\King_Addons\AI_Provider::getDashboardUrl($ka_ai_provider)); ?>" target="_blank" rel="noopener noreferrer" class="ka-btn ka-btn-secondary">
243 <span class="dashicons dashicons-external"></span>
244 <?php
245 printf(
246 /* translators: %s: provider name */
247 esc_html__('%s Dashboard', 'king-addons'),
248 esc_html($ka_ai_provider_label)
249 );
250 ?>
251 </a>
252 </div>
253 </div>
254
255 <!-- Info Card -->
256 <div class="ka-card">
257 <div class="ka-card-header">
258 <span class="dashicons dashicons-info" style="color: #0071e3;"></span>
259 <h3><?php esc_html_e('How to use AI features', 'king-addons'); ?></h3>
260 </div>
261 <div class="ka-card-body">
262 <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px;">
263 <div>
264 <h4 style="margin: 0 0 8px; font-size: 15px; font-weight: 600; color: inherit;">1. <?php esc_html_e('Pick a Provider', 'king-addons'); ?></h4>
265 <p class="ka-row-desc" style="margin: 0;"><?php esc_html_e('Choose OpenAI to use the OpenAI API directly, or OpenRouter to reach models from many vendors — including free ones — with one key.', 'king-addons'); ?></p>
266 </div>
267 <div>
268 <h4 style="margin: 0 0 8px; font-size: 15px; font-weight: 600; color: inherit;">2. <?php esc_html_e('Enter Key & Test', 'king-addons'); ?></h4>
269 <p class="ka-row-desc" style="margin: 0;"><?php esc_html_e('Paste the API key in the field below, press Test Connection to verify it, then select your preferred models.', 'king-addons'); ?></p>
270 </div>
271 <div>
272 <h4 style="margin: 0 0 8px; font-size: 15px; font-weight: 600; color: inherit;">3. <?php esc_html_e('Use', 'king-addons'); ?></h4>
273 <p class="ka-row-desc" style="margin: 0;"><?php esc_html_e('AI features will be available in the Elementor editor, widgets, and other supported areas.', 'king-addons'); ?></p>
274 </div>
275 </div>
276 </div>
277 </div>
278
279 <!-- Settings Form -->
280 <div class="ka-card">
281 <div class="ka-card-header">
282 <span class="dashicons dashicons-admin-settings" style="color: #8b5cf6;"></span>
283 <h2><?php esc_html_e('AI Configuration', 'king-addons'); ?></h2>
284 </div>
285 <div class="ka-card-body">
286 <form method="post" action="options.php">
287 <?php
288 settings_fields('king_addons_ai');
289 do_settings_sections('king-addons-ai-settings');
290 ?>
291
292 <div style="margin-top: 24px; padding-top: 24px; border-top: 1px solid rgba(0,0,0,0.04);">
293 <button type="submit" class="ka-btn ka-btn-primary">
294 <?php esc_html_e('Save Settings', 'king-addons'); ?>
295 </button>
296 </div>
297 </form>
298 </div>
299 </div>
300
301 </div>
302
303 <script>
304 // Dashboard-style segmented theme control
305 (function() {
306 const segment = document.getElementById('ka-v3-theme-segment');
307 if (!segment) {
308 return;
309 }
310
311 const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
312 const nonce = '<?php echo esc_js(wp_create_nonce('king_addons_dashboard_ui')); ?>';
313 const buttons = segment.querySelectorAll('.ka-v3-segmented-btn');
314
315 const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
316 let mode = (segment.getAttribute('data-active') || 'dark').toString();
317 let mqlHandler = null;
318
319 function setPressedState(activeMode) {
320 segment.setAttribute('data-active', activeMode);
321 buttons.forEach((btn) => {
322 const theme = btn.getAttribute('data-theme');
323 btn.setAttribute('aria-pressed', theme === activeMode ? 'true' : 'false');
324 });
325 }
326
327 function saveUISetting(key, value) {
328 try {
329 const body = new URLSearchParams();
330 body.set('action', 'king_addons_save_dashboard_ui');
331 body.set('nonce', nonce);
332 body.set('key', key);
333 body.set('value', value);
334
335 fetch(ajaxUrl, {
336 method: 'POST',
337 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
338 body: body.toString(),
339 credentials: 'same-origin'
340 });
341 } catch (e) {}
342 }
343
344 function applyTheme(isDark) {
345 document.body.classList.toggle('ka-v3-dark', isDark);
346 document.documentElement.classList.toggle('ka-v3-dark', isDark);
347 }
348
349 function setThemeMode(nextMode, save) {
350 mode = nextMode;
351 setPressedState(nextMode);
352
353 if (mqlHandler && mql) {
354 if (mql.removeEventListener) {
355 mql.removeEventListener('change', mqlHandler);
356 } else if (mql.removeListener) {
357 mql.removeListener(mqlHandler);
358 }
359 mqlHandler = null;
360 }
361
362 if (nextMode === 'auto') {
363 applyTheme(!!(mql && mql.matches));
364 mqlHandler = (e) => {
365 if (mode !== 'auto') {
366 return;
367 }
368 applyTheme(!!e.matches);
369 };
370 if (mql) {
371 if (mql.addEventListener) {
372 mql.addEventListener('change', mqlHandler);
373 } else if (mql.addListener) {
374 mql.addListener(mqlHandler);
375 }
376 }
377 } else {
378 applyTheme(nextMode === 'dark');
379 }
380
381 if (save) {
382 saveUISetting('theme_mode', nextMode);
383 }
384 }
385
386 segment.addEventListener('click', (e) => {
387 const btn = e.target && e.target.closest ? e.target.closest('.ka-v3-segmented-btn') : null;
388 if (!btn) {
389 return;
390 }
391 e.preventDefault();
392 const theme = (btn.getAttribute('data-theme') || 'dark').toString();
393 setThemeMode(theme, true);
394 });
395
396 // Ensure mode applies for Auto (listener + system state)
397 setThemeMode(mode, false);
398 })();
399 </script>
400