PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.63
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.63
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.63, at includes/admin/layouts/dashboard-v3/dashboard-v3.php

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