PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.84
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.84
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 / dashboard-v3 / dashboard-v3.php

dashboard-v3.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.84, at includes/admin/layouts/dashboard-v3/dashboard-v3.php

1,242 lines 59.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Dashboard V3 - Premium "Pro" UI with Premium style inspired design.
4 *
5 * Modern, premium redesign inspired by high-end product pages.
6 * Features glassmorphism, bento grids, iOS-style toggles, and Titanium aesthetic.
7 *
8 * @package King_Addons
9 */
10
11 if (!defined('ABSPATH')) {
12 exit;
13 }
14
15 // Handle AJAX requests for dashboard settings
16 if (wp_doing_ajax()) {
17 return;
18 }
19
20 // Load extensions list
21 require_once __DIR__ . '/extensions-list.php';
22
23 // Get dashboard UI settings (view mode is shared, theme is per-user)
24 $dashboard_settings = get_option('king_addons_dashboard_ui', [
25 'show_descriptions' => true,
26 ]);
27 $show_descriptions = !empty($dashboard_settings['show_descriptions']);
28
29 $theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
30 $allowed_theme_modes = ['dark', 'light', 'auto'];
31 if (!in_array($theme_mode, $allowed_theme_modes, true)) {
32 $theme_mode = 'auto';
33 }
34
35 // Handle settings update
36 if (isset($_GET['settings-updated'])) {
37 add_settings_error('king_addons_messages', 'king_addons_message', esc_html__('Settings Saved', 'king-addons'), 'updated');
38 }
39 settings_errors('king_addons_messages');
40
41 $options = get_option('king_addons_options', []);
42 $modules_map = \King_Addons\ModulesMap::getModulesMapArray();
43 $widgets = $modules_map['widgets'] ?? [];
44 $features = $modules_map['features'] ?? [];
45
46 // Hide modules hard-disabled via constants (used to QA/rollout new widgets/features).
47 $ka_v3_is_hard_disabled = static function (string $prefix, string $id): bool {
48 $const = $prefix . strtoupper(str_replace('-', '_', $id));
49 return defined($const) && constant($const) === false;
50 };
51
52 if (!empty($widgets)) {
53 $widgets = array_filter(
54 $widgets,
55 static fn($widget, $widget_id) => !$ka_v3_is_hard_disabled('KING_ADDONS_WGT_', (string) $widget_id),
56 ARRAY_FILTER_USE_BOTH
57 );
58 }
59
60 if (!empty($features)) {
61 $features = array_filter(
62 $features,
63 static fn($feature, $feature_id) => !$ka_v3_is_hard_disabled('KING_ADDONS_FEAT_', (string) $feature_id),
64 ARRAY_FILTER_USE_BOTH
65 );
66 }
67
68 // Count enabled/disabled modules
69 $total_modules = count($widgets);
70 $enabled_count = 0;
71 foreach ($widgets as $widget_id => $widget) {
72 if (isset($options[$widget_id]) && $options[$widget_id] === 'enabled') {
73 $enabled_count++;
74 }
75 }
76 $disabled_count = $total_modules - $enabled_count;
77
78 // Features count (enabled by default)
79 $total_features = count($features);
80 $enabled_features = 0;
81 foreach ($features as $feature_id => $feature) {
82 $feature_enabled = !isset($options[$feature_id]) || $options[$feature_id] === 'enabled';
83 if ($feature_enabled) {
84 $enabled_features++;
85 }
86 }
87 $disabled_features = $total_features - $enabled_features;
88
89 // Get extensions list
90 $extensions = king_addons_get_extensions_list();
91
92 // Count enabled extensions (default is enabled)
93 $total_extensions = count($extensions);
94 $enabled_extensions = 0;
95 foreach ($extensions as $ext_id => $ext) {
96 $ext_enabled = !isset($options['ext_' . $ext_id]) || $options['ext_' . $ext_id] === 'enabled';
97 if ($ext_enabled) {
98 $enabled_extensions++;
99 }
100 }
101 $disabled_extensions = $total_extensions - $enabled_extensions;
102
103 // Group widgets by category
104 $categories = [
105 'content' => [
106 'title' => esc_html__('Content Elements', 'king-addons'),
107 'icon' => 'dashicons-text-page',
108 'widgets' => [],
109 ],
110 'media' => [
111 'title' => esc_html__('Media & Gallery', 'king-addons'),
112 'icon' => 'dashicons-format-gallery',
113 'widgets' => [],
114 ],
115 'woocommerce' => [
116 'title' => esc_html__('WooCommerce', 'king-addons'),
117 'icon' => 'dashicons-cart',
118 'widgets' => [],
119 ],
120 'woo-builder' => [
121 'title' => esc_html__('WooCommerce Builder', 'king-addons'),
122 'icon' => 'dashicons-store',
123 'widgets' => [],
124 ],
125 'navigation' => [
126 'title' => esc_html__('Navigation & Menus', 'king-addons'),
127 'icon' => 'dashicons-menu',
128 'widgets' => [],
129 ],
130 'creative' => [
131 'title' => esc_html__('Creative Effects', 'king-addons'),
132 'icon' => 'dashicons-art',
133 'widgets' => [],
134 ],
135 'forms' => [
136 'title' => esc_html__('Forms & Input', 'king-addons'),
137 'icon' => 'dashicons-feedback',
138 'widgets' => [],
139 ],
140 'theme-builder' => [
141 'title' => esc_html__('Theme Builder', 'king-addons'),
142 'icon' => 'dashicons-admin-appearance',
143 'widgets' => [],
144 ],
145 'other' => [
146 'title' => esc_html__('Other Widgets', 'king-addons'),
147 'icon' => 'dashicons-screenoptions',
148 'widgets' => [],
149 ],
150 ];
151
152 // Categorize widgets strictly by explicit 'category' field
153 foreach ($widgets as $widget_id => $widget) {
154 $category_id = isset($widget['category']) ? (string) $widget['category'] : '';
155 if ($category_id === '' || !isset($categories[$category_id])) {
156 $category_id = 'other';
157 }
158 $categories[$category_id]['widgets'][$widget_id] = $widget;
159 }
160
161 // Remove empty categories
162 $categories = array_filter($categories, function($cat) {
163 return !empty($cat['widgets']);
164 });
165
166 $is_pro = function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code();
167
168 // Enqueue the CSS file
169 $shared_css_url = KING_ADDONS_URL . 'includes/admin/layouts/shared/admin-v3-styles.css';
170 $shared_css_path = KING_ADDONS_PATH . 'includes/admin/layouts/shared/admin-v3-styles.css';
171 $shared_css_version = file_exists($shared_css_path) ? filemtime($shared_css_path) : KING_ADDONS_VERSION;
172
173 $css_url = KING_ADDONS_URL . 'includes/admin/layouts/dashboard-v3/dashboard-v3.css';
174 $css_path = KING_ADDONS_PATH . 'includes/admin/layouts/dashboard-v3/dashboard-v3.css';
175 $css_version = file_exists($css_path) ? filemtime($css_path) : KING_ADDONS_VERSION;
176 ?>
177
178 <link rel="stylesheet" href="<?php echo esc_url($shared_css_url); ?>?v=<?php echo esc_attr($shared_css_version); ?>">
179 <link rel="stylesheet" href="<?php echo esc_url($css_url); ?>?v=<?php echo esc_attr($css_version); ?>">
180
181 <script>
182 (function() {
183 const mode = '<?php echo esc_js($theme_mode); ?>';
184 const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
185
186 function applyThemeClasses(isDark) {
187 document.documentElement.classList.toggle('ka-v3-dark', isDark);
188 if (document.body) {
189 document.body.classList.toggle('ka-v3-dark', isDark);
190 }
191 }
192
193 function ensureBodyReady(fn) {
194 if (document.body) {
195 fn();
196 return;
197 }
198 document.addEventListener('DOMContentLoaded', fn, { once: true });
199 }
200
201 if (mode === 'auto') {
202 const isDark = !!(mql && mql.matches);
203 applyThemeClasses(isDark);
204 ensureBodyReady(function() { applyThemeClasses(isDark); });
205 } else {
206 const isDark = mode === 'dark';
207 applyThemeClasses(isDark);
208 ensureBodyReady(function() { applyThemeClasses(isDark); });
209 }
210 })();
211 </script>
212
213 <div class="ka-v3-wrap">
214 <!-- Header -->
215 <div class="ka-v3-header">
216 <div>
217 <h1 class="ka-v3-title"><?php esc_html_e('King Addons', 'king-addons'); ?> <em>for Elementor</em></h1>
218 <p class="ka-v3-subtitle"><?php esc_html_e('The ultimate toolkit for Elementor. Build faster, design better.', 'king-addons'); ?></p>
219
220 <!-- Performance Tip -->
221 <div class="ka-v3-tip">
222 <div class="ka-v3-tip-icon">
223 <span class="dashicons dashicons-performance"></span>
224 </div>
225 <div class="ka-v3-tip-content">
226 <strong><?php esc_html_e('Smart Loading', 'king-addons'); ?></strong>
227 <span><?php esc_html_e('Assets are already loaded only when a widget, feature, or extension is used on a page. Disabling items here completely hides them from Elementor and the dashboard, helping keep your workspace cleaner and your site faster.', 'king-addons'); ?></span>
228 </div>
229 </div>
230 </div>
231 <div class="ka-v3-header-actions">
232 <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); ?>">
233 <span class="ka-v3-segmented-indicator" aria-hidden="true"></span>
234 <button type="button" class="ka-v3-segmented-btn" data-theme="light" aria-pressed="<?php echo $theme_mode === 'light' ? 'true' : 'false'; ?>">
235 <span class="ka-v3-segmented-icon" aria-hidden="true">☀︎</span>
236 <?php esc_html_e('Light', 'king-addons'); ?>
237 </button>
238 <button type="button" class="ka-v3-segmented-btn" data-theme="dark" aria-pressed="<?php echo $theme_mode === 'dark' ? 'true' : 'false'; ?>">
239 <span class="ka-v3-segmented-icon" aria-hidden="true">☾</span>
240 <?php esc_html_e('Dark', 'king-addons'); ?>
241 </button>
242 <button type="button" class="ka-v3-segmented-btn" data-theme="auto" aria-pressed="<?php echo $theme_mode === 'auto' ? 'true' : 'false'; ?>">
243 <span class="ka-v3-segmented-icon" aria-hidden="true">◐</span>
244 <?php esc_html_e('Auto', 'king-addons'); ?>
245 </button>
246 </div>
247 <a href="https://www.youtube.com/@kingaddons/videos" target="_blank" class="ka-v3-btn ka-v3-btn-secondary">
248 <span class="dashicons dashicons-book"></span>
249 <?php esc_html_e('Guides', 'king-addons'); ?>
250 </a>
251 <?php if (!$is_pro): ?>
252 <a href="https://kingaddons.com/pricing/?utm_source=king-addons-dashboard" target="_blank" class="ka-v3-btn ka-v3-btn-primary">
253 <span class="dashicons dashicons-star-filled"></span>
254 <?php esc_html_e('Upgrade to Pro', 'king-addons'); ?>
255 </a>
256 <?php endif; ?>
257 </div>
258 </div>
259
260 <?php
261 // Trinity Backup Slim Banner - check if plugin is installed/active
262 $trinity_plugin_slug_slim = 'trinity-backup/trinity-backup.php';
263 $trinity_installed_slim = file_exists(WP_PLUGIN_DIR . '/' . $trinity_plugin_slug_slim);
264 $trinity_active_slim = is_plugin_active($trinity_plugin_slug_slim);
265
266 $trinity_active_slim_ENABLED = false;
267
268 // Only show banner if plugin is not active
269 if (!$trinity_active_slim && $trinity_active_slim_ENABLED):
270 ?>
271 <!-- Trinity Backup Slim Banner -->
272 <div class="ka-v3-trinity-slim" id="ka-trinity-slim">
273 <div class="ka-v3-trinity-slim-left">
274 <img src="https://ps.w.org/trinity-backup/assets/icon-256x256.png" alt="Trinity Backup" class="ka-v3-trinity-slim-icon">
275 <div class="ka-v3-trinity-slim-text">
276 <span class="ka-v3-trinity-slim-title">Trinity Backup</span>
277 <span class="ka-v3-trinity-slim-desc"><?php esc_html_e('Free one-click backups for WordPress. From the King Addons developer.', 'king-addons'); ?></span>
278 </div>
279 </div>
280 <?php if ($trinity_installed_slim): ?>
281 <button type="button" class="ka-v3-trinity-slim-btn" id="ka-trinity-slim-activate" data-action="activate">
282 <span class="ka-v3-trinity-slim-btn-text"><?php esc_html_e('Activate', 'king-addons'); ?></span>
283 <span class="ka-v3-trinity-slim-btn-loading"></span>
284 <svg class="ka-v3-trinity-slim-btn-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
285 </button>
286 <?php else: ?>
287 <button type="button" class="ka-v3-trinity-slim-btn" id="ka-trinity-slim-install" data-action="install">
288 <span class="ka-v3-trinity-slim-btn-text"><?php esc_html_e('Install Free', 'king-addons'); ?></span>
289 <span class="ka-v3-trinity-slim-btn-loading"></span>
290 <svg class="ka-v3-trinity-slim-btn-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
291 </button>
292 <?php endif; ?>
293 </div>
294 <?php endif; ?>
295
296 <!-- Bento Grid Stats -->
297 <div class="ka-v3-bento">
298 <div class="ka-v3-bento-card large">
299 <div class="ka-v3-bento-bg" style="background: #0071e3; width: 250px; height: 250px; top: -80px; right: -60px;"></div>
300 <span class="ka-v3-bento-label"><?php esc_html_e('Widget Library', 'king-addons'); ?></span>
301 <div>
302 <div class="ka-v3-bento-value"><?php echo esc_html($total_modules); ?></div>
303 <div class="ka-v3-bento-desc"><?php esc_html_e('Premium Widgets Available', 'king-addons'); ?></div>
304 </div>
305 </div>
306 <div class="ka-v3-bento-card">
307 <div class="ka-v3-bento-bg" style="background: #34c759; width: 150px; height: 150px; bottom: -40px; left: -40px;"></div>
308 <span class="ka-v3-bento-label"><?php esc_html_e('Enabled', 'king-addons'); ?></span>
309 <div>
310 <div class="ka-v3-bento-value"><?php echo esc_html($enabled_count); ?></div>
311 <div class="ka-v3-bento-desc"><?php esc_html_e('Widgets Enabled', 'king-addons'); ?></div>
312 </div>
313 </div>
314 <div class="ka-v3-bento-card">
315 <div class="ka-v3-bento-bg" style="background: #af52de; width: 150px; height: 150px; top: 0; right: -20px;"></div>
316 <span class="ka-v3-bento-label"><?php esc_html_e('Disabled', 'king-addons'); ?></span>
317 <div>
318 <div class="ka-v3-bento-value"><?php echo esc_html($disabled_count); ?></div>
319 <div class="ka-v3-bento-desc"><?php esc_html_e('Widgets Disabled', 'king-addons'); ?></div>
320 </div>
321 </div>
322 <?php
323 // Trinity Backup Promo Card - check if plugin is installed/active
324 $trinity_plugin_slug = 'trinity-backup/trinity-backup.php';
325 $trinity_installed = file_exists(WP_PLUGIN_DIR . '/' . $trinity_plugin_slug);
326 $trinity_active = is_plugin_active($trinity_plugin_slug);
327
328
329 // TEMPORARILY DISABLED
330 $trinity_PROMO = false;
331
332 // Only show promo if plugin is not active
333 if (!$trinity_active && $trinity_PROMO):
334 ?>
335 <!-- Trinity Backup Promo Card -->
336 <div class="ka-v3-bento-card ka-v3-promo-card" id="ka-trinity-promo">
337 <img src="https://ps.w.org/trinity-backup/assets/icon-256x256.png" alt="Trinity Backup" class="ka-v3-promo-icon">
338 <div class="ka-v3-promo-text">
339 <span class="ka-v3-promo-label"><?php esc_html_e('From the Developer', 'king-addons'); ?></span>
340 <span class="ka-v3-promo-title">Trinity Backup</span>
341 <span class="ka-v3-promo-desc"><?php esc_html_e('Simple & reliable backups', 'king-addons'); ?></span>
342 </div>
343 <?php if ($trinity_installed): ?>
344 <button type="button" class="ka-v3-promo-btn" id="ka-trinity-activate" data-action="activate">
345 <span class="ka-v3-promo-btn-text"><?php esc_html_e('Activate', 'king-addons'); ?></span>
346 <span class="ka-v3-promo-btn-loading"></span>
347 </button>
348 <?php else: ?>
349 <button type="button" class="ka-v3-promo-btn" id="ka-trinity-install" data-action="install">
350 <span class="ka-v3-promo-btn-text"><?php esc_html_e('Install Free', 'king-addons'); ?></span>
351 <span class="ka-v3-promo-btn-loading"></span>
352 </button>
353 <?php endif; ?>
354 </div>
355 <?php endif; ?>
356 </div>
357
358 <!-- Navigation -->
359 <div class="ka-v3-nav">
360 <button type="button" class="ka-v3-nav-item active" data-tab="widgets">
361 <?php esc_html_e('Widgets', 'king-addons'); ?>
362 <span class="ka-v3-nav-badge"><?php echo esc_html($total_modules); ?></span>
363 </button>
364 <button type="button" class="ka-v3-nav-item" data-tab="features">
365 <?php esc_html_e('Features', 'king-addons'); ?>
366 <span class="ka-v3-nav-badge"><?php echo esc_html($total_features); ?></span>
367 </button>
368 <button type="button" class="ka-v3-nav-item" data-tab="extensions">
369 <?php esc_html_e('Extensions', 'king-addons'); ?>
370 <span class="ka-v3-nav-badge"><?php echo esc_html($total_extensions); ?></span>
371 </button>
372 </div>
373
374 <!-- Single Form for all tabs -->
375 <form action="options.php" method="post" id="ka-v3-dashboard-form">
376 <?php settings_fields('king_addons'); ?>
377
378 <!-- Widgets Tab Content -->
379 <div class="ka-v3-tab-content active" id="ka-v3-tab-widgets">
380
381 <!-- Quick Actions -->
382 <div class="ka-v3-quick-actions">
383 <?php if (defined('KING_ADDONS_EXT_HEADER_FOOTER_BUILDER') && KING_ADDONS_EXT_HEADER_FOOTER_BUILDER): ?>
384 <a href="<?php echo esc_url(admin_url('admin.php?page=king-addons-el-hf')); ?>" class="ka-v3-btn ka-v3-btn-secondary">
385 <span class="dashicons dashicons-welcome-widgets-menus"></span>
386 <?php esc_html_e('Header & Footer', 'king-addons'); ?>
387 </a>
388 <?php endif; ?>
389 <?php if (defined('KING_ADDONS_EXT_POPUP_BUILDER') && KING_ADDONS_EXT_POPUP_BUILDER): ?>
390 <a href="<?php echo esc_url(admin_url('admin.php?page=king-addons-popup-builder')); ?>" class="ka-v3-btn ka-v3-btn-secondary">
391 <span class="dashicons dashicons-external"></span>
392 <?php esc_html_e('Popup Builder', 'king-addons'); ?>
393 </a>
394 <?php endif; ?>
395 <?php if (defined('KING_ADDONS_EXT_TEMPLATES_CATALOG') && KING_ADDONS_EXT_TEMPLATES_CATALOG): ?>
396 <a href="<?php echo esc_url(admin_url('admin.php?page=king-addons-templates')); ?>" class="ka-v3-btn ka-v3-btn-secondary">
397 <span class="dashicons dashicons-layout"></span>
398 <?php esc_html_e('Templates', 'king-addons'); ?>
399 </a>
400 <?php endif; ?>
401 </div>
402
403 <!-- Controls Bar -->
404 <div class="ka-v3-controls">
405 <div class="ka-v3-search">
406 <span class="dashicons dashicons-search"></span>
407 <input type="text" id="ka-v3-search" placeholder="<?php esc_attr_e('Search widgets...', 'king-addons'); ?>">
408 </div>
409 <div class="ka-v3-filters">
410 <button type="button" class="ka-v3-filter-btn active" data-filter="all"><?php esc_html_e('All', 'king-addons'); ?></button>
411 <button type="button" class="ka-v3-filter-btn" data-filter="enabled"><?php esc_html_e('Enabled', 'king-addons'); ?></button>
412 <button type="button" class="ka-v3-filter-btn" data-filter="disabled"><?php esc_html_e('Disabled', 'king-addons'); ?></button>
413 </div>
414 <div class="ka-v3-collapse-all">
415 <button type="button" class="ka-v3-filter-btn" id="ka-v3-collapse-toggle" data-state="expanded">
416 <span class="dashicons dashicons-arrow-up-alt2" aria-hidden="true"></span>
417 <span class="ka-v3-collapse-text"><?php esc_html_e('Collapse categories', 'king-addons'); ?></span>
418 </button>
419 </div>
420 </div>
421
422 <!-- Module Categories -->
423 <?php foreach ($categories as $cat_id => $category):
424 $category_enabled_count = 0;
425 foreach ($category['widgets'] as $widget_id => $widget) {
426 if (isset($options[$widget_id]) && $options[$widget_id] === 'enabled') {
427 $category_enabled_count++;
428 }
429 }
430 $category_total = count($category['widgets']);
431 $category_all_enabled = $category_enabled_count === $category_total;
432 ?>
433 <div class="ka-v3-category" data-category="<?php echo esc_attr($cat_id); ?>">
434 <div class="ka-v3-category-header">
435 <div class="ka-v3-category-title">
436 <span class="dashicons <?php echo esc_attr($category['icon']); ?>"></span>
437 <h3><?php echo esc_html($category['title']); ?></h3>
438 <span class="ka-v3-category-count"><?php echo esc_html($category_total); ?></span>
439 </div>
440 <div class="ka-v3-category-toggle">
441 <button type="button" class="ka-v3-category-collapse" aria-expanded="true" aria-label="<?php echo esc_attr(esc_html__('Collapse category', 'king-addons')); ?>">
442 <span class="dashicons dashicons-arrow-up-alt2" aria-hidden="true"></span>
443 </button>
444 <label class="ka-v3-toggle">
445 <input type="checkbox" class="ka-v3-category-toggle-input" data-category="<?php echo esc_attr($cat_id); ?>" <?php checked($category_all_enabled); ?>>
446 <span class="ka-v3-toggle-slider"></span>
447 </label>
448 </div>
449 </div>
450 <div class="ka-v3-category-body">
451 <div class="ka-v3-grid">
452 <?php foreach ($category['widgets'] as $widget_id => $widget):
453 $is_enabled = isset($options[$widget_id]) && $options[$widget_id] === 'enabled';
454 ?>
455 <div class="ka-v3-card <?php echo $is_enabled ? '' : 'disabled'; ?>" data-widget="<?php echo esc_attr($widget_id); ?>" data-enabled="<?php echo $is_enabled ? '1' : '0'; ?>">
456 <div class="ka-v3-card-header">
457 <div class="ka-v3-card-icon">
458 <?php
459 $icon_url = KING_ADDONS_URL . 'includes/admin/img/' . $widget_id . '.svg';
460 $default_icon = KING_ADDONS_URL . 'includes/admin/img/default-widget.svg';
461 ?>
462 <img src="<?php echo esc_url($icon_url); ?>?v=<?php echo esc_attr(KING_ADDONS_VERSION); ?>"
463 alt="<?php echo esc_attr($widget['title']); ?>"
464 onerror="this.onerror=null; this.src='<?php echo esc_url($default_icon); ?>';">
465 </div>
466 <label class="ka-v3-toggle">
467 <input type="hidden" name="king_addons_options[<?php echo esc_attr($widget_id); ?>]" value="disabled">
468 <input type="checkbox" name="king_addons_options[<?php echo esc_attr($widget_id); ?>]" value="enabled" <?php checked($is_enabled); ?>>
469 <span class="ka-v3-toggle-slider"></span>
470 </label>
471 </div>
472 <h4 class="ka-v3-card-title"><?php echo esc_html($widget['title']); ?></h4>
473 <?php if (!empty($widget['description'])): ?>
474 <p class="ka-v3-card-desc"><?php echo esc_html($widget['description']); ?></p>
475 <?php endif; ?>
476 <?php if (!empty($widget['demo-link'])): ?>
477 <div class="ka-v3-card-footer">
478 <a href="<?php echo esc_url($widget['demo-link']); ?>?utm_source=ka-dashboard-v3" target="_blank" class="ka-v3-card-link">
479 <?php esc_html_e('View Demo', 'king-addons'); ?>
480 <span class="dashicons dashicons-external"></span>
481 </a>
482 </div>
483 <?php endif; ?>
484 </div>
485 <?php endforeach; ?>
486 </div>
487 </div>
488 </div>
489 <?php endforeach; ?>
490 </div>
491
492 <!-- Features Tab Content -->
493 <div class="ka-v3-tab-content" id="ka-v3-tab-features">
494 <div class="ka-v3-grid">
495 <?php foreach ($features as $feature_id => $feature):
496 $feature_enabled = !isset($options[$feature_id]) || $options[$feature_id] === 'enabled';
497 ?>
498 <div class="ka-v3-card <?php echo $feature_enabled ? '' : 'disabled'; ?>" data-feature="<?php echo esc_attr($feature_id); ?>" data-enabled="<?php echo $feature_enabled ? '1' : '0'; ?>">
499 <div class="ka-v3-card-header">
500 <div class="ka-v3-card-icon">
501 <span class="dashicons dashicons-admin-settings"></span>
502 </div>
503 <label class="ka-v3-toggle">
504 <input type="hidden" name="king_addons_options[<?php echo esc_attr($feature_id); ?>]" value="disabled">
505 <input type="checkbox" name="king_addons_options[<?php echo esc_attr($feature_id); ?>]" value="enabled" <?php checked($feature_enabled); ?>>
506 <span class="ka-v3-toggle-slider"></span>
507 </label>
508 </div>
509 <h4 class="ka-v3-card-title"><?php echo esc_html($feature['title'] ?? $feature_id); ?></h4>
510 <?php if (!empty($feature['description'])): ?>
511 <p class="ka-v3-card-desc"><?php echo esc_html($feature['description']); ?></p>
512 <?php endif; ?>
513 <?php if (!empty($feature['demo-link'])): ?>
514 <div class="ka-v3-card-footer">
515 <a href="<?php echo esc_url($feature['demo-link']); ?>" target="_blank" class="ka-v3-card-link">
516 <?php esc_html_e('Learn More', 'king-addons'); ?>
517 <span class="dashicons dashicons-external"></span>
518 </a>
519 </div>
520 <?php endif; ?>
521 </div>
522 <?php endforeach; ?>
523 </div>
524 </div>
525
526 <!-- Extensions Tab Content -->
527 <div class="ka-v3-tab-content" id="ka-v3-tab-extensions">
528 <div class="ka-v3-grid">
529 <?php foreach ($extensions as $ext_id => $ext):
530 $ext_available = true;
531 $ext_requirement_msg = '';
532 $ext_requirement_url = '';
533
534 if ($ext_id === 'woo-builder' && (!class_exists('WooCommerce') || !function_exists('WC'))) {
535 $ext_available = false;
536 $ext_requirement_msg = $ext['requires']['woocommerce']['message'] ?? esc_html__('WooCommerce is required.', 'king-addons');
537 $ext_requirement_url = $ext['requires']['woocommerce']['install_url'] ?? admin_url('plugin-install.php?s=woocommerce&tab=search&type=term');
538 }
539
540 $ext_enabled = $ext_available && (!isset($options['ext_' . $ext_id]) || $options['ext_' . $ext_id] === 'enabled');
541 ?>
542 <div class="ka-v3-card <?php echo $ext_enabled ? '' : 'disabled'; ?> <?php echo $ext_available ? '' : 'ka-v3-card-unavailable'; ?>" data-ext="<?php echo esc_attr($ext_id); ?>" data-enabled="<?php echo $ext_enabled ? '1' : '0'; ?>" data-available="<?php echo $ext_available ? '1' : '0'; ?>">
543 <div class="ka-v3-card-header">
544 <div class="ka-v3-card-icon">
545 <span class="dashicons <?php echo esc_attr($ext['icon']); ?>"></span>
546 </div>
547 <label class="ka-v3-toggle">
548 <input type="hidden" name="king_addons_options[ext_<?php echo esc_attr($ext_id); ?>]" value="disabled">
549 <input type="checkbox" name="king_addons_options[ext_<?php echo esc_attr($ext_id); ?>]" value="enabled" <?php checked($ext_enabled); ?> <?php disabled(!$ext_available); ?>>
550 <span class="ka-v3-toggle-slider"></span>
551 </label>
552 </div>
553 <h4 class="ka-v3-card-title"><?php echo esc_html($ext['title']); ?></h4>
554 <p class="ka-v3-card-desc"><?php echo esc_html($ext['description']); ?></p>
555 <?php if (!$ext_available && $ext_requirement_msg !== ''): ?>
556 <p class="ka-v3-card-requirement"><?php echo esc_html($ext_requirement_msg); ?></p>
557 <?php endif; ?>
558 <div class="ka-v3-card-footer">
559 <?php if ($ext_available && empty($ext['link'])): ?>
560 <?php /* Extensions with no admin panel of their own, such as Dynamic Tags. */ ?>
561 <span class="ka-v3-card-link ka-v3-link-disabled">
562 <?php esc_html_e('No settings needed', 'king-addons'); ?>
563 </span>
564 <?php elseif ($ext_available): ?>
565 <a href="<?php echo esc_url($ext['link']); ?>" class="ka-v3-card-link <?php echo !$ext_enabled ? 'ka-v3-link-disabled' : ''; ?>">
566 <?php esc_html_e('Open Panel', 'king-addons'); ?>
567 <span class="dashicons dashicons-arrow-right-alt"></span>
568 </a>
569 <?php else: ?>
570 <a href="<?php echo esc_url($ext_requirement_url); ?>" class="ka-v3-card-link">
571 <?php esc_html_e('Install / Activate WooCommerce', 'king-addons'); ?>
572 <span class="dashicons dashicons-external"></span>
573 </a>
574 <?php endif; ?>
575 </div>
576 </div>
577 <?php endforeach; ?>
578 </div>
579 </div>
580
581 <?php
582 // Large Trinity Backup Banner
583 $trinity_plugin_slug_banner = 'trinity-backup/trinity-backup.php';
584 $trinity_installed_banner = file_exists(WP_PLUGIN_DIR . '/' . $trinity_plugin_slug_banner);
585 $trinity_active_banner = is_plugin_active($trinity_plugin_slug_banner);
586
587 // TEMPORARILY DISABLED
588 $trinity_PROMO_BANNER = false;
589
590 // Only show banner if plugin is not active
591 if (!$trinity_active_banner && $trinity_PROMO_BANNER):
592 ?>
593 <!-- Trinity Backup Large Banner -->
594 <div class="ka-v3-trinity-banner" id="ka-trinity-banner">
595 <div class="ka-v3-trinity-banner-content">
596 <div class="ka-v3-trinity-banner-left">
597 <img src="https://ps.w.org/trinity-backup/assets/icon-256x256.png" alt="Trinity Backup" class="ka-v3-trinity-banner-icon">
598 <div class="ka-v3-trinity-banner-text">
599 <span class="ka-v3-trinity-banner-label"><?php esc_html_e('From King Addons Developer', 'king-addons'); ?></span>
600 <h3 class="ka-v3-trinity-banner-title">Trinity Backup</h3>
601 <p class="ka-v3-trinity-banner-desc"><?php esc_html_e('The simplest way to backup your WordPress site. One-click backups, easy restore, and rock-solid reliability. 100% Free.', 'king-addons'); ?></p>
602 </div>
603 </div>
604 <div class="ka-v3-trinity-banner-right">
605 <div class="ka-v3-trinity-banner-features">
606 <div class="ka-v3-trinity-banner-feature">
607 <span class="dashicons dashicons-yes-alt"></span>
608 <?php esc_html_e('One-Click Backups', 'king-addons'); ?>
609 </div>
610 <div class="ka-v3-trinity-banner-feature">
611 <span class="dashicons dashicons-yes-alt"></span>
612 <?php esc_html_e('Easy Restore', 'king-addons'); ?>
613 </div>
614 <div class="ka-v3-trinity-banner-feature">
615 <span class="dashicons dashicons-yes-alt"></span>
616 <?php esc_html_e('100% Free Forever', 'king-addons'); ?>
617 </div>
618 </div>
619 <?php if ($trinity_installed_banner): ?>
620 <button type="button" class="ka-v3-trinity-banner-btn" id="ka-trinity-banner-activate" data-action="activate">
621 <span class="ka-v3-trinity-banner-btn-text"><?php esc_html_e('Activate Plugin', 'king-addons'); ?></span>
622 <span class="ka-v3-trinity-banner-btn-loading"></span>
623 </button>
624 <?php else: ?>
625 <button type="button" class="ka-v3-trinity-banner-btn" id="ka-trinity-banner-install" data-action="install">
626 <span class="ka-v3-trinity-banner-btn-text"><?php esc_html_e('Install Free Plugin', 'king-addons'); ?></span>
627 <span class="ka-v3-trinity-banner-btn-loading"></span>
628 </button>
629 <?php endif; ?>
630 </div>
631 </div>
632 <button type="button" class="ka-v3-trinity-banner-close" id="ka-trinity-banner-close" title="<?php esc_attr_e('Dismiss', 'king-addons'); ?>">
633 <span class="dashicons dashicons-no-alt"></span>
634 </button>
635 </div>
636 <?php endif; ?>
637
638 <!-- Sticky Footer -->
639 <div class="ka-v3-footer">
640 <button type="button" class="ka-v3-btn ka-v3-btn-secondary" id="ka-v3-enable-all"><?php esc_html_e('Enable All', 'king-addons'); ?></button>
641 <button type="button" class="ka-v3-btn ka-v3-btn-secondary" id="ka-v3-disable-all"><?php esc_html_e('Disable All', 'king-addons'); ?></button>
642 <button type="submit" class="ka-v3-btn ka-v3-btn-primary"><?php esc_html_e('Save Changes', 'king-addons'); ?></button>
643 </div>
644 </form>
645 </div>
646
647 <script>
648 (function($) {
649 'use strict';
650
651 $(document).ready(function() {
652 let currentFilter = 'all';
653 let searchTokens = [];
654 let currentTab = 'widgets';
655
656 // Bento stats data per tab (total / enabled / disabled)
657 const kaBentoStats = {
658 widgets: [
659 {
660 label: '<?php echo esc_js(esc_html__('Widget Library', 'king-addons')); ?>',
661 value: <?php echo (int) $total_modules; ?>,
662 desc: '<?php echo esc_js(esc_html__('Premium Widgets Available', 'king-addons')); ?>'
663 },
664 {
665 label: '<?php echo esc_js(esc_html__('Enabled', 'king-addons')); ?>',
666 value: <?php echo (int) $enabled_count; ?>,
667 desc: '<?php echo esc_js(esc_html__('Widgets Enabled', 'king-addons')); ?>'
668 },
669 {
670 label: '<?php echo esc_js(esc_html__('Disabled', 'king-addons')); ?>',
671 value: <?php echo (int) $disabled_count; ?>,
672 desc: '<?php echo esc_js(esc_html__('Widgets Disabled', 'king-addons')); ?>'
673 }
674 ],
675 features: [
676 {
677 label: '<?php echo esc_js(esc_html__('Features', 'king-addons')); ?>',
678 value: <?php echo (int) $total_features; ?>,
679 desc: '<?php echo esc_js(esc_html__('Total Features', 'king-addons')); ?>'
680 },
681 {
682 label: '<?php echo esc_js(esc_html__('Enabled', 'king-addons')); ?>',
683 value: <?php echo (int) $enabled_features; ?>,
684 desc: '<?php echo esc_js(esc_html__('Enabled', 'king-addons')); ?>'
685 },
686 {
687 label: '<?php echo esc_js(esc_html__('Disabled', 'king-addons')); ?>',
688 value: <?php echo (int) $disabled_features; ?>,
689 desc: '<?php echo esc_js(esc_html__('Disabled', 'king-addons')); ?>'
690 }
691 ],
692 extensions: [
693 {
694 label: '<?php echo esc_js(esc_html__('Extensions', 'king-addons')); ?>',
695 value: <?php echo (int) $total_extensions; ?>,
696 desc: '<?php echo esc_js(esc_html__('Total Extensions', 'king-addons')); ?>'
697 },
698 {
699 label: '<?php echo esc_js(esc_html__('Enabled', 'king-addons')); ?>',
700 value: <?php echo (int) $enabled_extensions; ?>,
701 desc: '<?php echo esc_js(esc_html__('Enabled', 'king-addons')); ?>'
702 },
703 {
704 label: '<?php echo esc_js(esc_html__('Disabled', 'king-addons')); ?>',
705 value: <?php echo (int) $disabled_extensions; ?>,
706 desc: '<?php echo esc_js(esc_html__('Disabled', 'king-addons')); ?>'
707 }
708 ]
709 };
710
711 function easeInOutQuad(t) {
712 return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
713 }
714
715 function animateTextSwap($el, nextText) {
716 const currentText = $el.text();
717 if (currentText === nextText) {
718 return;
719 }
720
721 const el = $el.get(0);
722 if (!el || !el.animate) {
723 $el.text(nextText);
724 return;
725 }
726
727 const out = el.animate(
728 [
729 { opacity: 1, transform: 'translateY(0px)' },
730 { opacity: 0, transform: 'translateY(-4px)' }
731 ],
732 { duration: 140, easing: 'ease-out', fill: 'forwards' }
733 );
734
735 out.onfinish = function() {
736 $el.text(nextText);
737 el.animate(
738 [
739 { opacity: 0, transform: 'translateY(4px)' },
740 { opacity: 1, transform: 'translateY(0px)' }
741 ],
742 { duration: 180, easing: 'ease-out', fill: 'both' }
743 );
744 };
745 }
746
747 function updateBento(tabKey) {
748 const data = kaBentoStats[tabKey];
749 if (!data) {
750 return;
751 }
752
753 const $cards = $('.ka-v3-bento .ka-v3-bento-card');
754 if ($cards.length < 3) {
755 return;
756 }
757
758 $cards.each(function(index) {
759 const cardData = data[index];
760 if (!cardData) {
761 return;
762 }
763
764 const $card = $(this);
765 const $label = $card.find('.ka-v3-bento-label').first();
766 const $value = $card.find('.ka-v3-bento-value').first();
767 const $desc = $card.find('.ka-v3-bento-desc').first();
768
769 animateTextSwap($label, cardData.label);
770 animateTextSwap($value, String(cardData.value));
771 animateTextSwap($desc, cardData.desc);
772 });
773 }
774
775 const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
776 const nonce = '<?php echo esc_js(wp_create_nonce('king_addons_dashboard_ui')); ?>';
777
778 // Save UI setting via AJAX
779 function saveUISetting(key, value) {
780 $.post(ajaxUrl, {
781 action: 'king_addons_save_dashboard_ui',
782 nonce: nonce,
783 key: key,
784 value: value
785 });
786 }
787
788 // Theme segmented control
789 const $themeSegment = $('#ka-v3-theme-segment');
790 const $themeSegmentButtons = $themeSegment.find('.ka-v3-segmented-btn');
791
792 const themeMql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
793 let themeMode = ($themeSegment.attr('data-active') || 'dark').toString();
794 let themeMqlHandler = null;
795
796 function updateSegment(mode) {
797 $themeSegment.attr('data-active', mode);
798 $themeSegmentButtons.each(function() {
799 const theme = $(this).data('theme');
800 $(this).attr('aria-pressed', theme === mode ? 'true' : 'false');
801 });
802 }
803
804 function applyThemeClass(isDark) {
805 $('body').toggleClass('ka-v3-dark', isDark);
806 document.documentElement.classList.toggle('ka-v3-dark', isDark);
807 }
808
809 function setThemeMode(mode, save) {
810 themeMode = mode;
811 updateSegment(mode);
812
813 if (themeMqlHandler && themeMql) {
814 if (themeMql.removeEventListener) {
815 themeMql.removeEventListener('change', themeMqlHandler);
816 } else if (themeMql.removeListener) {
817 themeMql.removeListener(themeMqlHandler);
818 }
819 themeMqlHandler = null;
820 }
821
822 if (mode === 'auto') {
823 applyThemeClass(!!(themeMql && themeMql.matches));
824 themeMqlHandler = function(e) {
825 if (themeMode !== 'auto') {
826 return;
827 }
828 applyThemeClass(!!e.matches);
829 };
830 if (themeMql) {
831 if (themeMql.addEventListener) {
832 themeMql.addEventListener('change', themeMqlHandler);
833 } else if (themeMql.addListener) {
834 themeMql.addListener(themeMqlHandler);
835 }
836 }
837 } else {
838 applyThemeClass(mode === 'dark');
839 }
840
841 if (save) {
842 saveUISetting('theme_mode', mode);
843 }
844 }
845
846 $themeSegment.on('click', '.ka-v3-segmented-btn', function(e) {
847 e.preventDefault();
848 const mode = ($(this).data('theme') || 'dark').toString();
849 setThemeMode(mode, true);
850 });
851
852 // Ensure mode applies for Auto (listener + system state)
853 setThemeMode(themeMode, false);
854
855 // Tab Navigation
856 $('.ka-v3-nav-item').on('click', function() {
857 const tab = $(this).data('tab');
858 currentTab = tab;
859
860 $('.ka-v3-nav-item').removeClass('active');
861 $(this).addClass('active');
862
863 $('.ka-v3-tab-content').removeClass('active');
864 $('#ka-v3-tab-' + tab).addClass('active');
865
866 // Update top bento stats for the active tab
867 updateBento(tab);
868
869 // Scroll dashboard to the top on tab switch
870 const $wrap = $('.ka-v3-wrap');
871 const targetTop = $wrap.length ? Math.max(0, Math.round($wrap.offset().top) - 20) : 0;
872 try {
873 window.scrollTo({ top: targetTop, behavior: 'smooth' });
874 } catch (e) {
875 window.scrollTo(0, targetTop);
876 }
877 });
878
879 // Initialize bento for the default tab
880 updateBento(currentTab);
881
882 function normalizeText(text) {
883 return (text || '').toString().toLowerCase();
884 }
885
886 function getQueryTokens(query) {
887 return normalizeText(query).trim().split(/\s+/).filter(Boolean);
888 }
889
890 function matchesAllTokens(haystack, tokens) {
891 if (!tokens || tokens.length === 0) {
892 return true;
893 }
894 return tokens.every(function(token) {
895 return haystack.indexOf(token) !== -1;
896 });
897 }
898
899 // Apply filters (search + filter)
900 function applyFilters() {
901 const $cards = $('#ka-v3-tab-widgets .ka-v3-card');
902
903 $cards.each(function() {
904 const $card = $(this);
905 const title = normalizeText($card.find('.ka-v3-card-title').text());
906 const widgetId = normalizeText(($card.data('widget') || '').toString());
907 const description = normalizeText($card.find('.ka-v3-card-desc').text());
908 const $category = $card.closest('.ka-v3-category');
909 const categoryId = normalizeText(($category.data('category') || '').toString());
910 const categoryTitle = normalizeText($category.find('.ka-v3-category-title h3').first().text());
911 const haystack = (title + ' ' + widgetId + ' ' + description + ' ' + categoryId + ' ' + categoryTitle).trim();
912 const isEnabled = $card.data('enabled') == 1;
913
914 let matchesSearch = matchesAllTokens(haystack, searchTokens);
915 let matchesFilter = currentFilter === 'all' ||
916 (currentFilter === 'enabled' && isEnabled) ||
917 (currentFilter === 'disabled' && !isEnabled);
918
919 if (matchesSearch && matchesFilter) {
920 $card.removeClass('ka-v3-hidden');
921 } else {
922 $card.addClass('ka-v3-hidden');
923 }
924 });
925
926 // Hide empty categories
927 $('.ka-v3-category').each(function() {
928 const $category = $(this);
929 const hasVisible = $category.find('.ka-v3-card:not(.ka-v3-hidden)').length > 0;
930 $category.toggleClass('ka-v3-hidden', !hasVisible);
931 });
932 }
933
934 // Search
935 $('#ka-v3-search').on('input', function() {
936 searchTokens = getQueryTokens($(this).val());
937 applyFilters();
938 });
939
940 // Filter buttons (widgets tab)
941 $('.ka-v3-filters .ka-v3-filter-btn').on('click', function() {
942 $('.ka-v3-filters .ka-v3-filter-btn').removeClass('active');
943 $(this).addClass('active');
944 currentFilter = $(this).data('filter');
945 applyFilters();
946 });
947
948 // Collapse / Expand categories
949 const $collapseAllBtn = $('#ka-v3-collapse-toggle');
950
951 function setCategoryCollapsed($category, collapsed) {
952 $category.toggleClass('ka-v3-collapsed', !!collapsed);
953 $category.find('.ka-v3-category-collapse').attr('aria-expanded', collapsed ? 'false' : 'true');
954 }
955
956 function updateCollapseAllButton() {
957 const $cats = $('#ka-v3-tab-widgets .ka-v3-category');
958 if (!$cats.length || !$collapseAllBtn.length) {
959 return;
960 }
961
962 const allCollapsed = $cats.filter(':not(.ka-v3-collapsed)').length === 0;
963 $collapseAllBtn.attr('data-state', allCollapsed ? 'collapsed' : 'expanded');
964 const nextText = allCollapsed ? '<?php echo esc_js(esc_html__('Expand categories', 'king-addons')); ?>' : '<?php echo esc_js(esc_html__('Collapse categories', 'king-addons')); ?>';
965 $collapseAllBtn.find('.ka-v3-collapse-text').text(nextText);
966 }
967
968 $(document).on('click', '.ka-v3-category-collapse', function(e) {
969 e.preventDefault();
970 e.stopPropagation();
971 const $category = $(this).closest('.ka-v3-category');
972 const isCollapsed = $category.hasClass('ka-v3-collapsed');
973 setCategoryCollapsed($category, !isCollapsed);
974 updateCollapseAllButton();
975 });
976
977 $collapseAllBtn.on('click', function(e) {
978 e.preventDefault();
979
980 const $cats = $('#ka-v3-tab-widgets .ka-v3-category');
981 if (!$cats.length) {
982 return;
983 }
984
985 const anyExpanded = $cats.filter(':not(.ka-v3-collapsed)').length > 0;
986 $cats.each(function() {
987 setCategoryCollapsed($(this), anyExpanded);
988 });
989 updateCollapseAllButton();
990 });
991
992 // Initialize collapse button state
993 updateCollapseAllButton();
994
995 // Center footer relative to dashboard container (WP admin menu offsets content)
996 function updateFooterCenter() {
997 const $footer = $('.ka-v3-footer');
998 const $wrap = $('.ka-v3-wrap');
999 if (!$footer.length || !$wrap.length) {
1000 return;
1001 }
1002 const wrapRect = $wrap.get(0).getBoundingClientRect();
1003 const centerX = Math.round(wrapRect.left + (wrapRect.width / 2));
1004 $footer.get(0).style.left = centerX + 'px';
1005 $footer.get(0).style.transform = 'translateX(-50%)';
1006 }
1007
1008 updateFooterCenter();
1009 $(window).on('resize', function() {
1010 updateFooterCenter();
1011 });
1012
1013 // Category toggle
1014 $('.ka-v3-category-toggle-input').on('change', function() {
1015 const isEnabled = $(this).is(':checked');
1016 const $category = $(this).closest('.ka-v3-category');
1017
1018 $category.find('.ka-v3-card').each(function() {
1019 const $card = $(this);
1020 const $checkbox = $card.find('input[type="checkbox"]');
1021
1022 $checkbox.prop('checked', isEnabled);
1023
1024 if (isEnabled) {
1025 $card.removeClass('disabled').data('enabled', 1);
1026 } else {
1027 $card.addClass('disabled').data('enabled', 0);
1028 }
1029 });
1030 });
1031
1032 // Update category toggle state when individual widgets change
1033 $(document).on('change', '.ka-v3-card input[type="checkbox"]', function() {
1034 const $card = $(this).closest('.ka-v3-card');
1035 const $category = $card.closest('.ka-v3-category');
1036
1037 if ($(this).is(':checked')) {
1038 $card.removeClass('disabled').data('enabled', 1);
1039 } else {
1040 $card.addClass('disabled').data('enabled', 0);
1041 }
1042
1043 if ($category.length) {
1044 const total = $category.find('.ka-v3-card').length;
1045 const enabled = $category.find('.ka-v3-card input[type="checkbox"]:checked').length;
1046 $category.find('.ka-v3-category-toggle-input').prop('checked', enabled === total);
1047 }
1048 });
1049
1050 // Enable/Disable All
1051 $('#ka-v3-enable-all').on('click', function() {
1052 const $activeTab = $('.ka-v3-tab-content.active');
1053 $activeTab.find('input[type="checkbox"]').prop('checked', true);
1054 $activeTab.find('.ka-v3-card').removeClass('disabled').data('enabled', 1);
1055 $activeTab.find('.ka-v3-category-toggle-input').prop('checked', true);
1056 });
1057
1058 $('#ka-v3-disable-all').on('click', function() {
1059 const $activeTab = $('.ka-v3-tab-content.active');
1060 $activeTab.find('input[type="checkbox"]').prop('checked', false);
1061 $activeTab.find('.ka-v3-card').addClass('disabled').data('enabled', 0);
1062 $activeTab.find('.ka-v3-category-toggle-input').prop('checked', false);
1063 });
1064
1065 // Trinity Backup Install/Activate (Small Promo Card)
1066 $('#ka-trinity-install, #ka-trinity-activate').on('click', function(e) {
1067 e.preventDefault();
1068 const $btn = $(this);
1069 const action = $btn.data('action');
1070
1071 if ($btn.hasClass('loading') || $btn.hasClass('success')) {
1072 return;
1073 }
1074
1075 $btn.addClass('loading');
1076
1077 $.ajax({
1078 url: ajaxUrl,
1079 type: 'POST',
1080 data: {
1081 action: 'king_addons_install_trinity_backup',
1082 nonce: '<?php echo esc_js(wp_create_nonce('king_addons_install_plugin')); ?>',
1083 plugin_action: action
1084 },
1085 success: function(response) {
1086 $btn.removeClass('loading');
1087 if (response.success) {
1088 $btn.addClass('success');
1089 var promoSuccessText = action === 'install' ? '<?php echo esc_js(__('Installed!', 'king-addons')); ?>' : '<?php echo esc_js(__('Activated!', 'king-addons')); ?>';
1090 $btn.find('.ka-v3-promo-btn-text').text(promoSuccessText);
1091 // Redirect to Trinity Backup page after 1 second
1092 setTimeout(function() {
1093 window.location.href = '<?php echo esc_url(admin_url('admin.php?page=trinity-backup')); ?>';
1094 }, 1000);
1095 } else {
1096 $btn.addClass('error');
1097 $btn.find('.ka-v3-promo-btn-text').text(response.data || '<?php echo esc_js(__('Error', 'king-addons')); ?>');
1098 setTimeout(function() {
1099 $btn.removeClass('error');
1100 $btn.find('.ka-v3-promo-btn-text').text(action === 'install' ? '<?php echo esc_js(__('Install Free', 'king-addons')); ?>' : '<?php echo esc_js(__('Activate', 'king-addons')); ?>');
1101 }, 3000);
1102 }
1103 },
1104 error: function() {
1105 $btn.removeClass('loading').addClass('error');
1106 $btn.find('.ka-v3-promo-btn-text').text('<?php echo esc_js(__('Error', 'king-addons')); ?>');
1107 setTimeout(function() {
1108 $btn.removeClass('error');
1109 $btn.find('.ka-v3-promo-btn-text').text(action === 'install' ? '<?php echo esc_js(__('Install Free', 'king-addons')); ?>' : '<?php echo esc_js(__('Activate', 'king-addons')); ?>');
1110 }, 3000);
1111 }
1112 });
1113 });
1114
1115 // Trinity Backup Large Banner Install/Activate
1116 $('#ka-trinity-banner-install, #ka-trinity-banner-activate').on('click', function(e) {
1117 e.preventDefault();
1118 const $btn = $(this);
1119 const action = $btn.data('action');
1120
1121 if ($btn.hasClass('loading') || $btn.hasClass('success')) {
1122 return;
1123 }
1124
1125 $btn.addClass('loading');
1126
1127 $.ajax({
1128 url: ajaxUrl,
1129 type: 'POST',
1130 data: {
1131 action: 'king_addons_install_trinity_backup',
1132 nonce: '<?php echo esc_js(wp_create_nonce('king_addons_install_plugin')); ?>',
1133 plugin_action: action
1134 },
1135 success: function(response) {
1136 $btn.removeClass('loading');
1137 if (response.success) {
1138 $btn.addClass('success');
1139 var bannerSuccessText = action === 'install' ? '<?php echo esc_js(__('Installed!', 'king-addons')); ?>' : '<?php echo esc_js(__('Activated!', 'king-addons')); ?>';
1140 $btn.find('.ka-v3-trinity-banner-btn-text').text(bannerSuccessText);
1141 // Redirect to Trinity Backup page after 1 second
1142 setTimeout(function() {
1143 window.location.href = '<?php echo esc_url(admin_url('admin.php?page=trinity-backup')); ?>';
1144 }, 1000);
1145 } else {
1146 $btn.addClass('error');
1147 $btn.find('.ka-v3-trinity-banner-btn-text').text(response.data || '<?php echo esc_js(__('Error', 'king-addons')); ?>');
1148 setTimeout(function() {
1149 $btn.removeClass('error');
1150 $btn.find('.ka-v3-trinity-banner-btn-text').text(action === 'install' ? '<?php echo esc_js(__('Install Free Plugin', 'king-addons')); ?>' : '<?php echo esc_js(__('Activate Plugin', 'king-addons')); ?>');
1151 }, 3000);
1152 }
1153 },
1154 error: function() {
1155 $btn.removeClass('loading').addClass('error');
1156 $btn.find('.ka-v3-trinity-banner-btn-text').text('<?php echo esc_js(__('Error', 'king-addons')); ?>');
1157 setTimeout(function() {
1158 $btn.removeClass('error');
1159 $btn.find('.ka-v3-trinity-banner-btn-text').text(action === 'install' ? '<?php echo esc_js(__('Install Free Plugin', 'king-addons')); ?>' : '<?php echo esc_js(__('Activate Plugin', 'king-addons')); ?>');
1160 }, 3000);
1161 }
1162 });
1163 });
1164
1165 // Trinity Backup Banner Close Button
1166 $('#ka-trinity-banner-close').on('click', function(e) {
1167 e.preventDefault();
1168 $('#ka-trinity-banner').fadeOut(300, function() {
1169 $(this).remove();
1170 });
1171 });
1172
1173 // Trinity Backup Slim Banner Install/Activate
1174 // Prevent closing tab during installation
1175 function preventTabClose(e) {
1176 e.preventDefault();
1177 e.returnValue = '';
1178 return '';
1179 }
1180
1181 $('#ka-trinity-slim-install, #ka-trinity-slim-activate').on('click', function(e) {
1182 e.preventDefault();
1183 const $btn = $(this);
1184 const action = $btn.data('action');
1185
1186 if ($btn.hasClass('loading') || $btn.hasClass('success')) {
1187 return;
1188 }
1189
1190 $btn.addClass('loading');
1191
1192 // Add beforeunload listener to prevent closing
1193 window.addEventListener('beforeunload', preventTabClose);
1194
1195 $.ajax({
1196 url: ajaxUrl,
1197 type: 'POST',
1198 data: {
1199 action: 'king_addons_install_trinity_backup',
1200 nonce: '<?php echo esc_js(wp_create_nonce('king_addons_install_plugin')); ?>',
1201 plugin_action: action
1202 },
1203 success: function(response) {
1204 // Remove beforeunload listener
1205 window.removeEventListener('beforeunload', preventTabClose);
1206
1207 $btn.removeClass('loading');
1208 if (response.success) {
1209 $btn.addClass('success');
1210 var successText = action === 'install' ? '<?php echo esc_js(__('Installed!', 'king-addons')); ?>' : '<?php echo esc_js(__('Activated!', 'king-addons')); ?>';
1211 $btn.find('.ka-v3-trinity-slim-btn-text').text(successText);
1212 $btn.find('.ka-v3-trinity-slim-btn-arrow').hide();
1213 // Redirect to Trinity Backup page after 1 second
1214 setTimeout(function() {
1215 window.location.href = '<?php echo esc_url(admin_url('admin.php?page=trinity-backup')); ?>';
1216 }, 1000);
1217 } else {
1218 $btn.addClass('error');
1219 $btn.find('.ka-v3-trinity-slim-btn-text').text(response.data || '<?php echo esc_js(__('Error', 'king-addons')); ?>');
1220 setTimeout(function() {
1221 $btn.removeClass('error');
1222 $btn.find('.ka-v3-trinity-slim-btn-text').text(action === 'install' ? '<?php echo esc_js(__('Install Free', 'king-addons')); ?>' : '<?php echo esc_js(__('Activate', 'king-addons')); ?>');
1223 }, 3000);
1224 }
1225 },
1226 error: function() {
1227 // Remove beforeunload listener
1228 window.removeEventListener('beforeunload', preventTabClose);
1229
1230 $btn.removeClass('loading').addClass('error');
1231 $btn.find('.ka-v3-trinity-slim-btn-text').text('<?php echo esc_js(__('Error', 'king-addons')); ?>');
1232 setTimeout(function() {
1233 $btn.removeClass('error');
1234 $btn.find('.ka-v3-trinity-slim-btn-text').text(action === 'install' ? '<?php echo esc_js(__('Install Free', 'king-addons')); ?>' : '<?php echo esc_js(__('Activate', 'king-addons')); ?>');
1235 }, 3000);
1236 }
1237 });
1238 });
1239 });
1240 })(jQuery);
1241 </script>
1242