Changeset 3361418
- Timestamp:
- 09/14/2025 11:06:46 PM (7 months ago)
- Location:
- speedox
- Files:
-
- 8 edited
-
tags/1.1.2/admin-dashboard-ui.php (modified) (7 diffs)
-
tags/1.1.2/assets/css/admin-dashboard.css (modified) (1 diff)
-
tags/1.1.2/includes/dashboard.php (modified) (1 diff)
-
tags/1.1.2/speedox.php (modified) (1 diff)
-
trunk/admin-dashboard-ui.php (modified) (7 diffs)
-
trunk/assets/css/admin-dashboard.css (modified) (1 diff)
-
trunk/includes/dashboard.php (modified) (1 diff)
-
trunk/speedox.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
speedox/tags/1.1.2/admin-dashboard-ui.php
r3325637 r3361418 4 4 5 5 ?> 6 <div class="wrap ">6 <div class="wrap speedox-wrap"> 7 7 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> 8 8 <input type="hidden" name="action" value="speedox_save_settings" /> 9 9 <?php wp_nonce_field('speedox_save_action', 'speedox_save_nonce'); ?> 10 11 <?php 12 // Include hidden fields for all settings to preserve them across tabs 13 $all_options = [ 14 'speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing', 15 'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion', 16 'speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css', 17 'speedox_lazyload', 'speedox_image_optimization', 'speedox_database_optimization', 18 'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache', 19 'speedox_basic_cdn_support', 'speedox_cloudflare_bunny', 'speedox_dns_prefetch', 20 'speedox_disable_emojis_embeds_heartbeat', 'speedox_priority_support_panel' 21 ]; 22 23 foreach ($all_options as $option) { 24 $value = get_option($option, 0); 25 echo '<input type="hidden" name="' . esc_attr($option) . '_preserve" value="' . esc_attr($value) . '" />'; 26 } 27 28 // Preserve current tab 29 echo '<input type="hidden" name="current_tab" value="' . esc_attr($active_tab) . '" />'; 30 ?> 10 31 11 32 <h1>⚡ SpeedOx Optimization Dashboard</h1> … … 61 82 <td> 62 83 <?php if(!$pro): ?> 63 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>84 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 64 85 <?php else: ?> 65 86 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 99 120 <td> 100 121 <?php if(!$pro): ?> 101 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>122 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 102 123 <?php else: ?> 103 124 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 134 155 <td> 135 156 <?php if(!$pro): ?> 136 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>157 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 137 158 <?php else: ?> 138 159 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 153 174 <tr> 154 175 <th scope="row"><?php echo esc_html('Database Optimization'); ?></th> 155 <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, get_option('speedox_database_optimization')); ?>> Enable</label></td>176 <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, intval(get_option('speedox_database_optimization', 0))); ?>> Enable</label></td> 156 177 </tr> 157 178 </table> … … 186 207 <td> 187 208 <?php if(!$pro): ?> 188 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>209 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 189 210 <?php else: ?> 190 211 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 202 223 <h2 class="hndle"><span>Activity Logs</span></h2> 203 224 <div class="inside"> 204 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> 205 <input type="hidden" name="action" value="speedox_clear_logs" /> 206 <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?> 207 <textarea readonly style="width:100%;height:300px;"><?php 208 $logs = SpeedOx_Logger::get_logs(200); 225 <textarea readonly style="width:100%;height:300px;"><?php 226 $logs = SpeedOx_Logger::get_logs(200); 227 if (is_array($logs) && !empty($logs)) { 209 228 echo esc_textarea(implode("\n", $logs)); 210 ?></textarea> 211 <p><button type="submit" class="button">Clear Logs</button></p> 212 </form> 229 } else { 230 echo esc_textarea("No logs available yet. Plugin activity will be logged here."); 231 } 232 ?></textarea> 233 <p> 234 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;"> 235 <input type="hidden" name="action" value="speedox_clear_logs" /> 236 <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?> 237 <button type="submit" class="button">Clear Logs</button> 238 </form> 239 </p> 213 240 </div> 214 241 </div> -
speedox/tags/1.1.2/assets/css/admin-dashboard.css
r3325637 r3361418 1 .speedox-dashboard { 2 font-family: "Segoe UI", sans-serif; 3 padding: 20px; 4 } 5 .speedox-header { 6 background: linear-gradient(to right, #4f46e5, #6d28d9); 1 /* SpeedOx Dashboard - LiteSpeed Inspired but Better */ 2 .speedox-wrap { 3 background: #f8f9fa; 4 border-radius: 0; 5 padding: 0; 6 box-shadow: none; 7 margin-top: 0; 8 min-height: 100vh; 9 display: flex; 10 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; 11 } 12 13 /* Sidebar Navigation */ 14 .speedox-wrap::before { 15 content: ''; 16 position: fixed; 17 top: 0; 18 left: 0; 19 width: 250px; 20 height: 100vh; 21 background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%); 22 z-index: 1000; 23 box-shadow: 2px 0 10px rgba(0,0,0,0.1); 24 } 25 26 .speedox-wrap::after { 27 content: ''; 28 position: fixed; 29 top: 0; 30 left: 0; 31 width: 250px; 32 height: 100vh; 33 background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="rgba(255,255,255,0.05)"/><circle cx="75" cy="75" r="1" fill="rgba(255,255,255,0.03)"/><circle cx="50" cy="10" r="0.5" fill="rgba(255,255,255,0.04)"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>'); 34 z-index: 1001; 35 pointer-events: none; 36 } 37 38 /* Main Content Area */ 39 .speedox-wrap > * { 40 margin-left: 250px; 41 width: calc(100% - 250px); 42 background: #ffffff; 43 min-height: 100vh; 44 padding: 30px; 45 } 46 47 /* Header Section */ 48 .speedox-wrap h1 { 49 color: #2c3e50; 50 font-size: 28px; 51 margin-bottom: 30px; 52 border-bottom: none; 53 padding-bottom: 0; 54 font-weight: 700; 55 display: flex; 56 align-items: center; 57 gap: 15px; 58 } 59 60 .speedox-wrap h1::before { 61 content: '⚡'; 62 font-size: 32px; 63 background: linear-gradient(135deg, #667eea, #764ba2); 64 -webkit-background-clip: text; 65 -webkit-text-fill-color: transparent; 66 background-clip: text; 67 animation: pulse 2s infinite; 68 } 69 70 @keyframes pulse { 71 0%, 100% { transform: scale(1); } 72 50% { transform: scale(1.1); } 73 } 74 75 /* Navigation Tabs - Sidebar Style */ 76 .speedox-wrap .nav-tab-wrapper { 77 position: fixed; 78 top: 0; 79 left: 0; 80 width: 250px; 81 height: 100vh; 82 background: transparent; 83 padding: 0; 84 margin: 0; 85 z-index: 1002; 86 display: flex; 87 flex-direction: column; 88 padding-top: 80px; 89 } 90 91 .speedox-wrap .nav-tab { 92 background: transparent; 93 color: #bdc3c7; 94 border: none; 95 padding: 15px 25px; 96 text-decoration: none; 97 border-radius: 0; 98 margin: 0; 99 transition: all 0.3s ease; 100 font-weight: 500; 101 font-size: 14px; 102 display: flex; 103 align-items: center; 104 gap: 12px; 105 position: relative; 106 border-left: 3px solid transparent; 107 } 108 109 .speedox-wrap .nav-tab::before { 110 content: ''; 111 position: absolute; 112 left: 0; 113 top: 0; 114 bottom: 0; 115 width: 3px; 116 background: #667eea; 117 transform: scaleY(0); 118 transition: transform 0.3s ease; 119 } 120 121 .speedox-wrap .nav-tab:hover { 122 background: rgba(255, 255, 255, 0.1); 7 123 color: white; 8 padding: 20px; 124 transform: translateX(5px); 125 } 126 127 .speedox-wrap .nav-tab:hover::before { 128 transform: scaleY(1); 129 } 130 131 .speedox-wrap .nav-tab-active { 132 background: rgba(255, 255, 255, 0.15); 133 color: white; 134 border-left-color: #667eea; 135 } 136 137 .speedox-wrap .nav-tab-active::before { 138 transform: scaleY(1); 139 } 140 141 /* Add icons to nav tabs */ 142 .speedox-wrap .nav-tab:nth-child(1)::after { content: '🚀'; } 143 .speedox-wrap .nav-tab:nth-child(2)::after { content: '⚡'; } 144 .speedox-wrap .nav-tab:nth-child(3)::after { content: '🖼️'; } 145 .speedox-wrap .nav-tab:nth-child(4)::after { content: '🗄️'; } 146 .speedox-wrap .nav-tab:nth-child(5)::after { content: '🔧'; } 147 .speedox-wrap .nav-tab:nth-child(6)::after { content: '📊'; } 148 149 /* Content Cards */ 150 .speedox-wrap .postbox { 151 border: none; 9 152 border-radius: 12px; 10 display: flex; 11 align-items: center; 153 margin-bottom: 25px; 154 box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); 155 background: white; 156 overflow: hidden; 157 position: relative; 158 } 159 160 .speedox-wrap .postbox::before { 161 content: ''; 162 position: absolute; 163 top: 0; 164 left: 0; 165 right: 0; 166 height: 4px; 167 background: linear-gradient(135deg, #667eea, #764ba2); 168 } 169 170 .speedox-wrap .postbox .hndle { 171 background: linear-gradient(135deg, #f8fafc, #e2e8f0); 172 border-bottom: 1px solid #e5e7eb; 173 padding: 20px 25px; 174 margin: 0; 175 font-size: 18px; 176 font-weight: 700; 177 color: #1f2937; 178 position: relative; 179 } 180 181 .speedox-wrap .postbox .hndle::before { 182 content: ''; 183 position: absolute; 184 left: 0; 185 top: 0; 186 bottom: 0; 187 width: 4px; 188 background: linear-gradient(135deg, #667eea, #764ba2); 189 } 190 191 .speedox-wrap .postbox .inside { 192 padding: 25px; 193 background: #fafbfc; 194 } 195 196 /* Statistics Cards Grid */ 197 .speedox-wrap .form-table { 198 display: grid; 199 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 12 200 gap: 20px; 13 } 14 .speedox-header h1 { 15 margin: 0; 16 font-size: 26px; 17 } 18 .speedox-cards { 19 display: grid; 20 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); 21 gap: 20px; 22 margin-top: 30px; 23 } 24 .speedox-card { 201 background: transparent; 202 border: none; 203 box-shadow: none; 204 } 205 206 .speedox-wrap .form-table tr { 25 207 background: white; 26 208 border-radius: 12px; 209 box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); 210 display: flex; 211 flex-direction: column; 27 212 padding: 20px; 28 box-shadow: 0 4px 12px rgba(0,0,0,0.06); 29 text-align: center; 30 } 31 .speedox-circle { 32 width: 80px; 33 height: 80px; 213 transition: all 0.3s ease; 214 border: 1px solid #e5e7eb; 215 } 216 217 .speedox-wrap .form-table tr:hover { 218 transform: translateY(-5px); 219 box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); 220 } 221 222 .speedox-wrap .form-table th { 223 width: auto; 224 padding: 0 0 15px 0; 225 font-weight: 700; 226 color: #1f2937; 227 background: transparent; 228 border: none; 229 font-size: 16px; 230 text-align: left; 231 } 232 233 .speedox-wrap .form-table td { 234 padding: 0; 235 background: transparent; 236 border: none; 237 } 238 239 /* Feature Cards with Statistics */ 240 .speedox-wrap .form-table tr { 241 position: relative; 242 overflow: hidden; 243 } 244 245 .speedox-wrap .form-table tr::before { 246 content: ''; 247 position: absolute; 248 top: 0; 249 left: 0; 250 right: 0; 251 height: 4px; 252 background: linear-gradient(135deg, #667eea, #764ba2); 253 } 254 255 /* Enhanced Checkboxes */ 256 .speedox-wrap input[type="checkbox"] { 257 margin-right: 12px; 258 transform: scale(1.4); 259 accent-color: #667eea; 260 } 261 262 .speedox-wrap label { 263 font-weight: 600; 264 color: #374151; 265 cursor: pointer; 266 font-size: 14px; 267 transition: color 0.3s ease; 268 display: flex; 269 align-items: center; 270 } 271 272 .speedox-wrap label:hover { 273 color: #667eea; 274 } 275 276 /* Status Indicators */ 277 .speedox-wrap .form-table tr { 278 position: relative; 279 } 280 281 .speedox-wrap .form-table tr::after { 282 content: ''; 283 position: absolute; 284 top: 20px; 285 right: 20px; 286 width: 12px; 287 height: 12px; 34 288 border-radius: 50%; 35 background: #eef2ff; 36 margin: 0 auto 10px; 37 display: flex; 38 align-items: center; 39 justify-content: center; 40 font-size: 20px; 41 } 42 .speedox-circle p { 43 margin: 0; 44 font-size: 18px; 45 font-weight: bold; 46 } 289 background: #10b981; 290 box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2); 291 } 292 293 /* Buttons */ 294 .speedox-wrap .button-primary { 295 background: linear-gradient(135deg, #10b981, #059669); 296 border: none; 297 color: white; 298 padding: 12px 25px; 299 font-size: 15px; 300 font-weight: 700; 301 border-radius: 8px; 302 transition: all 0.3s ease; 303 box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3); 304 text-transform: uppercase; 305 letter-spacing: 0.5px; 306 position: fixed; 307 bottom: 30px; 308 right: 30px; 309 z-index: 1003; 310 } 311 312 .speedox-wrap .button-primary:hover { 313 background: linear-gradient(135deg, #059669, #047857); 314 transform: translateY(-2px); 315 box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4); 316 } 317 318 .speedox-wrap .button { 319 background: linear-gradient(135deg, #6b7280, #4b5563); 320 border: none; 321 color: white; 322 padding: 10px 20px; 323 font-size: 13px; 324 font-weight: 600; 325 border-radius: 6px; 326 transition: all 0.3s ease; 327 box-shadow: 0 2px 8px rgba(107, 114, 128, 0.3); 328 } 329 330 .speedox-wrap .button:hover { 331 background: linear-gradient(135deg, #4b5563, #374151); 332 transform: translateY(-1px); 333 box-shadow: 0 4px 15px rgba(107, 114, 128, 0.4); 334 } 335 336 /* Textarea */ 337 .speedox-wrap textarea { 338 border: 2px solid #e5e7eb; 339 border-radius: 8px; 340 padding: 15px; 341 font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; 342 font-size: 13px; 343 background: #1f2937; 344 color: #e5e7eb; 345 box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); 346 transition: border-color 0.3s ease; 347 width: 100%; 348 height: 300px; 349 } 350 351 .speedox-wrap textarea:focus { 352 border-color: #667eea; 353 outline: none; 354 box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); 355 } 356 357 /* Footer */ 358 .speedox-wrap .speedox-footer { 359 margin-top: 30px; 360 padding: 20px; 361 background: linear-gradient(135deg, #f8fafc, #e2e8f0); 362 border-radius: 12px; 363 border-top: 3px solid #667eea; 364 box-shadow: 0 4px 15px rgba(0,0,0,0.1); 365 } 366 367 .speedox-wrap .speedox-footer a { 368 color: #667eea; 369 text-decoration: none; 370 font-weight: 600; 371 transition: color 0.3s ease; 372 } 373 374 .speedox-wrap .speedox-footer a:hover { 375 color: #764ba2; 376 text-decoration: underline; 377 } 378 379 /* Pro badge styling */ 380 .speedox-wrap span[style*="background: #444"] { 381 background: linear-gradient(135deg, #f59e0b, #d97706) !important; 382 color: white !important; 383 padding: 4px 10px !important; 384 border-radius: 15px !important; 385 font-size: 10px !important; 386 font-weight: 800 !important; 387 text-transform: uppercase !important; 388 letter-spacing: 0.8px !important; 389 box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3) !important; 390 animation: pulse 2s infinite !important; 391 } 392 393 /* Responsive Design */ 394 @media (max-width: 768px) { 395 .speedox-wrap::before, 396 .speedox-wrap::after { 397 display: none; 398 } 399 400 .speedox-wrap > * { 401 margin-left: 0; 402 width: 100%; 403 padding: 20px; 404 } 405 406 .speedox-wrap .nav-tab-wrapper { 407 position: static; 408 width: 100%; 409 height: auto; 410 flex-direction: row; 411 padding-top: 0; 412 margin-bottom: 20px; 413 background: white; 414 border-radius: 8px; 415 box-shadow: 0 2px 10px rgba(0,0,0,0.1); 416 overflow-x: auto; 417 } 418 419 .speedox-wrap .nav-tab { 420 white-space: nowrap; 421 border-left: none; 422 border-bottom: 3px solid transparent; 423 padding: 12px 20px; 424 color: #6b7280; 425 } 426 427 .speedox-wrap .nav-tab::before { 428 display: none; 429 } 430 431 .speedox-wrap .nav-tab-active { 432 border-bottom-color: #667eea; 433 background: transparent; 434 } 435 436 .speedox-wrap .form-table { 437 grid-template-columns: 1fr; 438 } 439 440 .speedox-wrap .button-primary { 441 position: static; 442 margin-top: 20px; 443 } 444 } 445 446 @media (max-width: 480px) { 447 .speedox-wrap > * { 448 padding: 15px; 449 } 450 451 .speedox-wrap h1 { 452 font-size: 24px; 453 } 454 455 .speedox-wrap .postbox .hndle { 456 padding: 15px 20px; 457 font-size: 16px; 458 } 459 460 .speedox-wrap .postbox .inside { 461 padding: 20px; 462 } 463 } -
speedox/tags/1.1.2/includes/dashboard.php
r3325637 r3361418 8 8 wp_enqueue_style( 9 9 'speedox-dashboard-style', 10 plugin_dir_url( __FILE__) . 'assets/css/admin-dashboard.css',10 plugin_dir_url(dirname(__FILE__)) . 'assets/css/admin-dashboard.css', 11 11 [], 12 12 '1.0.0' -
speedox/tags/1.1.2/speedox.php
r3325677 r3361418 200 200 201 201 foreach ($options as $opt) { 202 $value = isset($_POST[$opt]) ? 1 : 0; 202 // Check if the option is explicitly set in the current tab 203 if (isset($_POST[$opt]) && $_POST[$opt] == '1') { 204 $value = 1; 205 } else { 206 // If not explicitly set, check if this option exists in the current tab 207 // If it exists in current tab but not in POST, it means it was unchecked (set to 0) 208 $current_tab_options = []; 209 if (isset($_POST['current_tab'])) { 210 $tab = $_POST['current_tab']; 211 switch($tab) { 212 case 'cache': 213 $current_tab_options = ['speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing', 'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion', 'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache']; 214 break; 215 case 'cssjs': 216 $current_tab_options = ['speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css']; 217 break; 218 case 'media': 219 $current_tab_options = ['speedox_lazyload']; 220 break; 221 case 'database': 222 $current_tab_options = ['speedox_database_optimization']; 223 break; 224 case 'advanced': 225 $current_tab_options = ['speedox_disable_emojis_embeds_heartbeat', 'speedox_basic_cdn_support']; 226 break; 227 } 228 } 229 230 if (in_array($opt, $current_tab_options)) { 231 // This option is in current tab but not in POST, so it was unchecked 232 $value = 0; 233 } else { 234 // This option is not in current tab, preserve its value 235 $preserved_value = isset($_POST[$opt . '_preserve']) ? intval($_POST[$opt . '_preserve']) : 0; 236 $value = $preserved_value; 237 } 238 } 203 239 update_option($opt, $value); 204 } 205 206 $tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'cache'; 240 241 // Debug: Log what's being saved 242 SpeedOx_Logger::log("Setting $opt = $value (POST: " . (isset($_POST[$opt]) ? $_POST[$opt] : 'not set') . ", Preserve: " . (isset($_POST[$opt . '_preserve']) ? $_POST[$opt . '_preserve'] : 'not set') . ")"); 243 } 244 245 // Get the current tab from POST data (preserved from the form) 246 $tab = isset($_POST['current_tab']) ? sanitize_text_field(wp_unslash($_POST['current_tab'])) : 'cache'; 247 207 248 wp_safe_redirect(admin_url('admin.php?page=speedox-dashboard&tab=' . $tab)); 208 249 exit; -
speedox/trunk/admin-dashboard-ui.php
r3325213 r3361418 4 4 5 5 ?> 6 <div class="wrap ">6 <div class="wrap speedox-wrap"> 7 7 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> 8 8 <input type="hidden" name="action" value="speedox_save_settings" /> 9 9 <?php wp_nonce_field('speedox_save_action', 'speedox_save_nonce'); ?> 10 11 <?php 12 // Include hidden fields for all settings to preserve them across tabs 13 $all_options = [ 14 'speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing', 15 'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion', 16 'speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css', 17 'speedox_lazyload', 'speedox_image_optimization', 'speedox_database_optimization', 18 'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache', 19 'speedox_basic_cdn_support', 'speedox_cloudflare_bunny', 'speedox_dns_prefetch', 20 'speedox_disable_emojis_embeds_heartbeat', 'speedox_priority_support_panel' 21 ]; 22 23 foreach ($all_options as $option) { 24 $value = get_option($option, 0); 25 echo '<input type="hidden" name="' . esc_attr($option) . '_preserve" value="' . esc_attr($value) . '" />'; 26 } 27 28 // Preserve current tab 29 echo '<input type="hidden" name="current_tab" value="' . esc_attr($active_tab) . '" />'; 30 ?> 10 31 11 32 <h1>⚡ SpeedOx Optimization Dashboard</h1> … … 61 82 <td> 62 83 <?php if(!$pro): ?> 63 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>84 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 64 85 <?php else: ?> 65 86 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 99 120 <td> 100 121 <?php if(!$pro): ?> 101 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>122 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 102 123 <?php else: ?> 103 124 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 134 155 <td> 135 156 <?php if(!$pro): ?> 136 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>157 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 137 158 <?php else: ?> 138 159 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 153 174 <tr> 154 175 <th scope="row"><?php echo esc_html('Database Optimization'); ?></th> 155 <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, get_option('speedox_database_optimization')); ?>> Enable</label></td>176 <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, intval(get_option('speedox_database_optimization', 0))); ?>> Enable</label></td> 156 177 </tr> 157 178 </table> … … 186 207 <td> 187 208 <?php if(!$pro): ?> 188 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>209 <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label> 189 210 <?php else: ?> 190 211 <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em> … … 202 223 <h2 class="hndle"><span>Activity Logs</span></h2> 203 224 <div class="inside"> 204 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> 205 <input type="hidden" name="action" value="speedox_clear_logs" /> 206 <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?> 207 <textarea readonly style="width:100%;height:300px;"><?php 208 $logs = SpeedOx_Logger::get_logs(200); 225 <textarea readonly style="width:100%;height:300px;"><?php 226 $logs = SpeedOx_Logger::get_logs(200); 227 if (is_array($logs) && !empty($logs)) { 209 228 echo esc_textarea(implode("\n", $logs)); 210 ?></textarea> 211 <p><button type="submit" class="button">Clear Logs</button></p> 212 </form> 229 } else { 230 echo esc_textarea("No logs available yet. Plugin activity will be logged here."); 231 } 232 ?></textarea> 233 <p> 234 <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;"> 235 <input type="hidden" name="action" value="speedox_clear_logs" /> 236 <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?> 237 <button type="submit" class="button">Clear Logs</button> 238 </form> 239 </p> 213 240 </div> 214 241 </div> -
speedox/trunk/assets/css/admin-dashboard.css
r3325213 r3361418 1 .speedox-dashboard { 2 font-family: "Segoe UI", sans-serif; 3 padding: 20px; 4 } 5 .speedox-header { 6 background: linear-gradient(to right, #4f46e5, #6d28d9); 1 /* SpeedOx Dashboard - LiteSpeed Inspired but Better */ 2 .speedox-wrap { 3 background: #f8f9fa; 4 border-radius: 0; 5 padding: 0; 6 box-shadow: none; 7 margin-top: 0; 8 min-height: 100vh; 9 display: flex; 10 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; 11 } 12 13 /* Sidebar Navigation */ 14 .speedox-wrap::before { 15 content: ''; 16 position: fixed; 17 top: 0; 18 left: 0; 19 width: 250px; 20 height: 100vh; 21 background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%); 22 z-index: 1000; 23 box-shadow: 2px 0 10px rgba(0,0,0,0.1); 24 } 25 26 .speedox-wrap::after { 27 content: ''; 28 position: fixed; 29 top: 0; 30 left: 0; 31 width: 250px; 32 height: 100vh; 33 background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="rgba(255,255,255,0.05)"/><circle cx="75" cy="75" r="1" fill="rgba(255,255,255,0.03)"/><circle cx="50" cy="10" r="0.5" fill="rgba(255,255,255,0.04)"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>'); 34 z-index: 1001; 35 pointer-events: none; 36 } 37 38 /* Main Content Area */ 39 .speedox-wrap > * { 40 margin-left: 250px; 41 width: calc(100% - 250px); 42 background: #ffffff; 43 min-height: 100vh; 44 padding: 30px; 45 } 46 47 /* Header Section */ 48 .speedox-wrap h1 { 49 color: #2c3e50; 50 font-size: 28px; 51 margin-bottom: 30px; 52 border-bottom: none; 53 padding-bottom: 0; 54 font-weight: 700; 55 display: flex; 56 align-items: center; 57 gap: 15px; 58 } 59 60 .speedox-wrap h1::before { 61 content: '⚡'; 62 font-size: 32px; 63 background: linear-gradient(135deg, #667eea, #764ba2); 64 -webkit-background-clip: text; 65 -webkit-text-fill-color: transparent; 66 background-clip: text; 67 animation: pulse 2s infinite; 68 } 69 70 @keyframes pulse { 71 0%, 100% { transform: scale(1); } 72 50% { transform: scale(1.1); } 73 } 74 75 /* Navigation Tabs - Sidebar Style */ 76 .speedox-wrap .nav-tab-wrapper { 77 position: fixed; 78 top: 0; 79 left: 0; 80 width: 250px; 81 height: 100vh; 82 background: transparent; 83 padding: 0; 84 margin: 0; 85 z-index: 1002; 86 display: flex; 87 flex-direction: column; 88 padding-top: 80px; 89 } 90 91 .speedox-wrap .nav-tab { 92 background: transparent; 93 color: #bdc3c7; 94 border: none; 95 padding: 15px 25px; 96 text-decoration: none; 97 border-radius: 0; 98 margin: 0; 99 transition: all 0.3s ease; 100 font-weight: 500; 101 font-size: 14px; 102 display: flex; 103 align-items: center; 104 gap: 12px; 105 position: relative; 106 border-left: 3px solid transparent; 107 } 108 109 .speedox-wrap .nav-tab::before { 110 content: ''; 111 position: absolute; 112 left: 0; 113 top: 0; 114 bottom: 0; 115 width: 3px; 116 background: #667eea; 117 transform: scaleY(0); 118 transition: transform 0.3s ease; 119 } 120 121 .speedox-wrap .nav-tab:hover { 122 background: rgba(255, 255, 255, 0.1); 7 123 color: white; 8 padding: 20px; 124 transform: translateX(5px); 125 } 126 127 .speedox-wrap .nav-tab:hover::before { 128 transform: scaleY(1); 129 } 130 131 .speedox-wrap .nav-tab-active { 132 background: rgba(255, 255, 255, 0.15); 133 color: white; 134 border-left-color: #667eea; 135 } 136 137 .speedox-wrap .nav-tab-active::before { 138 transform: scaleY(1); 139 } 140 141 /* Add icons to nav tabs */ 142 .speedox-wrap .nav-tab:nth-child(1)::after { content: '🚀'; } 143 .speedox-wrap .nav-tab:nth-child(2)::after { content: '⚡'; } 144 .speedox-wrap .nav-tab:nth-child(3)::after { content: '🖼️'; } 145 .speedox-wrap .nav-tab:nth-child(4)::after { content: '🗄️'; } 146 .speedox-wrap .nav-tab:nth-child(5)::after { content: '🔧'; } 147 .speedox-wrap .nav-tab:nth-child(6)::after { content: '📊'; } 148 149 /* Content Cards */ 150 .speedox-wrap .postbox { 151 border: none; 9 152 border-radius: 12px; 10 display: flex; 11 align-items: center; 153 margin-bottom: 25px; 154 box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); 155 background: white; 156 overflow: hidden; 157 position: relative; 158 } 159 160 .speedox-wrap .postbox::before { 161 content: ''; 162 position: absolute; 163 top: 0; 164 left: 0; 165 right: 0; 166 height: 4px; 167 background: linear-gradient(135deg, #667eea, #764ba2); 168 } 169 170 .speedox-wrap .postbox .hndle { 171 background: linear-gradient(135deg, #f8fafc, #e2e8f0); 172 border-bottom: 1px solid #e5e7eb; 173 padding: 20px 25px; 174 margin: 0; 175 font-size: 18px; 176 font-weight: 700; 177 color: #1f2937; 178 position: relative; 179 } 180 181 .speedox-wrap .postbox .hndle::before { 182 content: ''; 183 position: absolute; 184 left: 0; 185 top: 0; 186 bottom: 0; 187 width: 4px; 188 background: linear-gradient(135deg, #667eea, #764ba2); 189 } 190 191 .speedox-wrap .postbox .inside { 192 padding: 25px; 193 background: #fafbfc; 194 } 195 196 /* Statistics Cards Grid */ 197 .speedox-wrap .form-table { 198 display: grid; 199 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 12 200 gap: 20px; 13 } 14 .speedox-header h1 { 15 margin: 0; 16 font-size: 26px; 17 } 18 .speedox-cards { 19 display: grid; 20 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); 21 gap: 20px; 22 margin-top: 30px; 23 } 24 .speedox-card { 201 background: transparent; 202 border: none; 203 box-shadow: none; 204 } 205 206 .speedox-wrap .form-table tr { 25 207 background: white; 26 208 border-radius: 12px; 209 box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); 210 display: flex; 211 flex-direction: column; 27 212 padding: 20px; 28 box-shadow: 0 4px 12px rgba(0,0,0,0.06); 29 text-align: center; 30 } 31 .speedox-circle { 32 width: 80px; 33 height: 80px; 213 transition: all 0.3s ease; 214 border: 1px solid #e5e7eb; 215 } 216 217 .speedox-wrap .form-table tr:hover { 218 transform: translateY(-5px); 219 box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); 220 } 221 222 .speedox-wrap .form-table th { 223 width: auto; 224 padding: 0 0 15px 0; 225 font-weight: 700; 226 color: #1f2937; 227 background: transparent; 228 border: none; 229 font-size: 16px; 230 text-align: left; 231 } 232 233 .speedox-wrap .form-table td { 234 padding: 0; 235 background: transparent; 236 border: none; 237 } 238 239 /* Feature Cards with Statistics */ 240 .speedox-wrap .form-table tr { 241 position: relative; 242 overflow: hidden; 243 } 244 245 .speedox-wrap .form-table tr::before { 246 content: ''; 247 position: absolute; 248 top: 0; 249 left: 0; 250 right: 0; 251 height: 4px; 252 background: linear-gradient(135deg, #667eea, #764ba2); 253 } 254 255 /* Enhanced Checkboxes */ 256 .speedox-wrap input[type="checkbox"] { 257 margin-right: 12px; 258 transform: scale(1.4); 259 accent-color: #667eea; 260 } 261 262 .speedox-wrap label { 263 font-weight: 600; 264 color: #374151; 265 cursor: pointer; 266 font-size: 14px; 267 transition: color 0.3s ease; 268 display: flex; 269 align-items: center; 270 } 271 272 .speedox-wrap label:hover { 273 color: #667eea; 274 } 275 276 /* Status Indicators */ 277 .speedox-wrap .form-table tr { 278 position: relative; 279 } 280 281 .speedox-wrap .form-table tr::after { 282 content: ''; 283 position: absolute; 284 top: 20px; 285 right: 20px; 286 width: 12px; 287 height: 12px; 34 288 border-radius: 50%; 35 background: #eef2ff; 36 margin: 0 auto 10px; 37 display: flex; 38 align-items: center; 39 justify-content: center; 40 font-size: 20px; 41 } 42 .speedox-circle p { 43 margin: 0; 44 font-size: 18px; 45 font-weight: bold; 46 } 289 background: #10b981; 290 box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2); 291 } 292 293 /* Buttons */ 294 .speedox-wrap .button-primary { 295 background: linear-gradient(135deg, #10b981, #059669); 296 border: none; 297 color: white; 298 padding: 12px 25px; 299 font-size: 15px; 300 font-weight: 700; 301 border-radius: 8px; 302 transition: all 0.3s ease; 303 box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3); 304 text-transform: uppercase; 305 letter-spacing: 0.5px; 306 position: fixed; 307 bottom: 30px; 308 right: 30px; 309 z-index: 1003; 310 } 311 312 .speedox-wrap .button-primary:hover { 313 background: linear-gradient(135deg, #059669, #047857); 314 transform: translateY(-2px); 315 box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4); 316 } 317 318 .speedox-wrap .button { 319 background: linear-gradient(135deg, #6b7280, #4b5563); 320 border: none; 321 color: white; 322 padding: 10px 20px; 323 font-size: 13px; 324 font-weight: 600; 325 border-radius: 6px; 326 transition: all 0.3s ease; 327 box-shadow: 0 2px 8px rgba(107, 114, 128, 0.3); 328 } 329 330 .speedox-wrap .button:hover { 331 background: linear-gradient(135deg, #4b5563, #374151); 332 transform: translateY(-1px); 333 box-shadow: 0 4px 15px rgba(107, 114, 128, 0.4); 334 } 335 336 /* Textarea */ 337 .speedox-wrap textarea { 338 border: 2px solid #e5e7eb; 339 border-radius: 8px; 340 padding: 15px; 341 font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; 342 font-size: 13px; 343 background: #1f2937; 344 color: #e5e7eb; 345 box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); 346 transition: border-color 0.3s ease; 347 width: 100%; 348 height: 300px; 349 } 350 351 .speedox-wrap textarea:focus { 352 border-color: #667eea; 353 outline: none; 354 box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); 355 } 356 357 /* Footer */ 358 .speedox-wrap .speedox-footer { 359 margin-top: 30px; 360 padding: 20px; 361 background: linear-gradient(135deg, #f8fafc, #e2e8f0); 362 border-radius: 12px; 363 border-top: 3px solid #667eea; 364 box-shadow: 0 4px 15px rgba(0,0,0,0.1); 365 } 366 367 .speedox-wrap .speedox-footer a { 368 color: #667eea; 369 text-decoration: none; 370 font-weight: 600; 371 transition: color 0.3s ease; 372 } 373 374 .speedox-wrap .speedox-footer a:hover { 375 color: #764ba2; 376 text-decoration: underline; 377 } 378 379 /* Pro badge styling */ 380 .speedox-wrap span[style*="background: #444"] { 381 background: linear-gradient(135deg, #f59e0b, #d97706) !important; 382 color: white !important; 383 padding: 4px 10px !important; 384 border-radius: 15px !important; 385 font-size: 10px !important; 386 font-weight: 800 !important; 387 text-transform: uppercase !important; 388 letter-spacing: 0.8px !important; 389 box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3) !important; 390 animation: pulse 2s infinite !important; 391 } 392 393 /* Responsive Design */ 394 @media (max-width: 768px) { 395 .speedox-wrap::before, 396 .speedox-wrap::after { 397 display: none; 398 } 399 400 .speedox-wrap > * { 401 margin-left: 0; 402 width: 100%; 403 padding: 20px; 404 } 405 406 .speedox-wrap .nav-tab-wrapper { 407 position: static; 408 width: 100%; 409 height: auto; 410 flex-direction: row; 411 padding-top: 0; 412 margin-bottom: 20px; 413 background: white; 414 border-radius: 8px; 415 box-shadow: 0 2px 10px rgba(0,0,0,0.1); 416 overflow-x: auto; 417 } 418 419 .speedox-wrap .nav-tab { 420 white-space: nowrap; 421 border-left: none; 422 border-bottom: 3px solid transparent; 423 padding: 12px 20px; 424 color: #6b7280; 425 } 426 427 .speedox-wrap .nav-tab::before { 428 display: none; 429 } 430 431 .speedox-wrap .nav-tab-active { 432 border-bottom-color: #667eea; 433 background: transparent; 434 } 435 436 .speedox-wrap .form-table { 437 grid-template-columns: 1fr; 438 } 439 440 .speedox-wrap .button-primary { 441 position: static; 442 margin-top: 20px; 443 } 444 } 445 446 @media (max-width: 480px) { 447 .speedox-wrap > * { 448 padding: 15px; 449 } 450 451 .speedox-wrap h1 { 452 font-size: 24px; 453 } 454 455 .speedox-wrap .postbox .hndle { 456 padding: 15px 20px; 457 font-size: 16px; 458 } 459 460 .speedox-wrap .postbox .inside { 461 padding: 20px; 462 } 463 } -
speedox/trunk/includes/dashboard.php
r3325213 r3361418 8 8 wp_enqueue_style( 9 9 'speedox-dashboard-style', 10 plugin_dir_url( __FILE__) . 'assets/css/admin-dashboard.css',10 plugin_dir_url(dirname(__FILE__)) . 'assets/css/admin-dashboard.css', 11 11 [], 12 12 '1.0.0' -
speedox/trunk/speedox.php
r3325677 r3361418 200 200 201 201 foreach ($options as $opt) { 202 $value = isset($_POST[$opt]) ? 1 : 0; 202 // Check if the option is explicitly set in the current tab 203 if (isset($_POST[$opt]) && $_POST[$opt] == '1') { 204 $value = 1; 205 } else { 206 // If not explicitly set, check if this option exists in the current tab 207 // If it exists in current tab but not in POST, it means it was unchecked (set to 0) 208 $current_tab_options = []; 209 if (isset($_POST['current_tab'])) { 210 $tab = $_POST['current_tab']; 211 switch($tab) { 212 case 'cache': 213 $current_tab_options = ['speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing', 'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion', 'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache']; 214 break; 215 case 'cssjs': 216 $current_tab_options = ['speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css']; 217 break; 218 case 'media': 219 $current_tab_options = ['speedox_lazyload']; 220 break; 221 case 'database': 222 $current_tab_options = ['speedox_database_optimization']; 223 break; 224 case 'advanced': 225 $current_tab_options = ['speedox_disable_emojis_embeds_heartbeat', 'speedox_basic_cdn_support']; 226 break; 227 } 228 } 229 230 if (in_array($opt, $current_tab_options)) { 231 // This option is in current tab but not in POST, so it was unchecked 232 $value = 0; 233 } else { 234 // This option is not in current tab, preserve its value 235 $preserved_value = isset($_POST[$opt . '_preserve']) ? intval($_POST[$opt . '_preserve']) : 0; 236 $value = $preserved_value; 237 } 238 } 203 239 update_option($opt, $value); 204 } 205 206 $tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'cache'; 240 241 // Debug: Log what's being saved 242 SpeedOx_Logger::log("Setting $opt = $value (POST: " . (isset($_POST[$opt]) ? $_POST[$opt] : 'not set') . ", Preserve: " . (isset($_POST[$opt . '_preserve']) ? $_POST[$opt . '_preserve'] : 'not set') . ")"); 243 } 244 245 // Get the current tab from POST data (preserved from the form) 246 $tab = isset($_POST['current_tab']) ? sanitize_text_field(wp_unslash($_POST['current_tab'])) : 'cache'; 247 207 248 wp_safe_redirect(admin_url('admin.php?page=speedox-dashboard&tab=' . $tab)); 208 249 exit;
Note: See TracChangeset
for help on using the changeset viewer.