Some recent versions of the patches
Dashboard_cache_patch1
--- /usr/local/www/guiconfig.inc
+++ /usr/local/www/guiconfig.inc
@@ -31,6 +31,26 @@
header("X-Frame-Options: SAMEORIGIN");
include_once('phpsessionmanager.inc');
include_once("util.inc");
+
+// --- FAST DASHBOARD: BACKGROUND SAVER (SMART) ---
+function save_dashboard_snapshot() {
+ if (strpos($_SERVER['SCRIPT_NAME'], 'index.php') !== false && empty($_POST) && !isset($_GET['get_updates_only'])) {
+ $html = ob_get_contents();
+ $is_syncing = (function_exists('is_subsystem_dirty') && is_subsystem_dirty('packagelock')) || file_exists('/conf/needs_package_sync');
+ $has_errors = (function_exists('system_has_crash_data') && system_has_crash_data()) || (function_exists('system_has_php_errors') && system_has_php_errors());
+ // SECURITY CHECK: Ensure it's a dashboard, logged in, and no critical tasks/errors
+ if (!empty($html) && strlen($html) > 5000 && strpos($html, 'widgetSequence') !== false && !empty($_SESSION['Username']) && !$is_syncing && !$has_errors) {
+ @file_put_contents("/tmp/dashboard.cache", $html);
+ }
+ }
+}
+
+// Start output buffering and register the shutdown function
+if (strpos($_SERVER['SCRIPT_NAME'], 'index.php') !== false && !isset($_GET['get_updates_only'])) {
+ ob_start();
+ register_shutdown_function('save_dashboard_snapshot');
+}
+// --- END FAST DASHBOARD ---
function pfSense_csrf_callback() {
include "csrf_error.php";
Dashboard_cache_patch2
--- /usr/local/www/index.php
+++ /usr/local/www/index.php
@@ -96,6 +96,51 @@
## Include each widget php include file.
-## These define vars that specify the widget title and title link.
-
-$directory = "/usr/local/www/widgets/include/";
+## These define vars that specify the widget title and title link.
+
+// --- FAST DASHBOARD: SMART CACHE LOGIC WITH REFRESH OVERLAY ---
+$is_valid_cache = false;
+
+// 1. Check for critical system alerts before considering cache
+$is_syncing = (function_exists('is_subsystem_dirty') && is_subsystem_dirty('packagelock')) || file_exists('/conf/needs_package_sync');
+$has_critical_alerts = (system_has_crash_data() || system_has_php_errors() || $is_syncing);
+
+// 2. Determine if we should serve the cache (strictly on clean login)
+if (!$has_critical_alerts && empty($_POST) && !isset($_GET['get_updates_only']) && !isset($_GET['logout'])) {
+ if (!empty($_SESSION['Username']) && empty($_SESSION['dashboard_cache_shown'])) {
+ $is_valid_cache = true;
+ }
+}
+
+// 3. CACHE KILLER: If saving settings (POST), destroy the old RAM cache
+if (!empty($_POST) && !isset($_POST['login'])) {
+ @unlink("/tmp/dashboard.cache");
+ $_SESSION['dashboard_cache_shown'] = true;
+}
+
+// 4. SERVE CACHE
+if ($is_valid_cache && file_exists("/tmp/dashboard.cache")) {
+ $_SESSION['dashboard_cache_shown'] = true;
+
+ // STRICT ANTI-CACHE HEADERS: Prevent browser from caching this output locally
+ header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
+ header("Cache-Control: post-check=0, pre-check=0", false);
+ header("Pragma: no-cache");
+
+ // Output the static snapshot from RAM
+ readfile("/tmp/dashboard.cache");
+
+ // Inject CSS and Debounced JS Tracker
+ echo "<style id=\"fast-dashboard-css\">\n\t\tbody.fast-dashboard-loading .panel-heading, body.fast-dashboard-loading .panel-body, body.fast-dashboard-loading .panel-footer { filter: blur(4px); opacity: 0.5; pointer-events: none; transition: all 0.4s ease; }\n\t\tbody.fast-dashboard-loading .panel { position: relative; }\n\t\tbody.fast-dashboard-loading .panel::after { content: 'Refreshing...'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-weight: bold; color: #fff; background: rgba(0,0,0,0.6); padding: 5px 12px; border-radius: 4px; z-index: 10; pointer-events: none; transition: opacity 0.4s ease; }\n\t</style>\n\t<script>\n\t\tdocument.body.classList.add('fast-dashboard-loading');\n\t\tsetTimeout(function(){ if (typeof(ajax_update) === 'function') ajax_update(); }, 200);\n\t\tvar removeBlur = function() { document.body.classList.remove('fast-dashboard-loading'); setTimeout(function(){ var el = document.getElementById('fast-dashboard-css'); if(el) el.remove(); }, 500); };\n\t\tvar blurFallback = setTimeout(removeBlur, 5000);\n\t\tdocument.addEventListener('DOMContentLoaded', function() { if (typeof jQuery !== 'undefined') { var ajaxTimer; jQuery(document).ajaxComplete(function() { clearTimeout(ajaxTimer); ajaxTimer = setTimeout(function() { clearTimeout(blurFallback); removeBlur(); }, 400); }); } });\n\t</script>";
+ exit;
+} else {
+ // 5. LIVE MODE FALLBACK: Guarantee live mode for normal browsing
+ if (!empty($_SESSION['Username'])) {
+ $_SESSION['dashboard_cache_shown'] = true;
+ }
+}
+// --- END FAST DASHBOARD ---
+
+$directory = "/usr/local/www/widgets/include/";
$dirhandle = opendir($directory);
$filename = "";
Widgets patches:
NTP widget patch
--- /usr/local/www/widgets/widgets/ntp_status.widget.php
+++ /usr/local/www/widgets/widgets/ntp_status.widget.php
@@ -162,9 +162,18 @@
// --------------------- Centralized widget refresh system ------------------------------
// Callback function called by refresh system when data is retrieved
- function ntp_callback(s) {
- $('[id="ntpstatus"]').prop('innerHTML', s);
- }
+ function ntp_callback(s) {
+ $('[id="ntpstatus"]').prop('innerHTML', s);
+ // --- FAST DASHBOARD: NTP CLOCK CACHE FIX ---
+ jQuery.ajax({
+ type: 'HEAD', url: '/index.php',
+ success: function(d, st, xhr) {
+ if (typeof ntp_d !== 'undefined') {
+ ntp_d = convertDateToUTC(new Date(xhr.getResponseHeader('Date')), '<?=date('Z')?>');
+ }
+ }
+ });
+ }
// POST data to send via AJAX
var postdata = {
CARP STATUS widget
--- /usr/local/www/widgets/widgets/carp_status.widget.php
+++ /usr/local/www/widgets/widgets/carp_status.widget.php
@@ -25,12 +25,18 @@
require_once("guiconfig.inc");
require_once("pfsense-utils.inc");
require_once("functions.inc");
require_once("/usr/local/www/widgets/include/carp_status.inc");
-$carp_enabled = get_carp_status();
+$carp_enabled = get_carp_status();
+// --- FAST DASHBOARD: NATIVE CARP AJAX UPDATE ---
+if (isset($_REQUEST['updateme'])) {
+ $carp_enabled = true; // FIX: get_carp_status() returns false during direct AJAX
+} else {
+ echo "<script>\nevents.push(function(){\n\tvar o = new Object();\n\to.name = 'CARP';\n\to.url = '/widgets/widgets/carp_status.widget.php';\n\to.callback = function(s) { jQuery('[id^=\"widget-carp_status\"] .panel-body').html(s); };\n\to.parms = { ajax: 'ajax', updateme: 'yes' };\n\to.freq = 1;\n\tregister_ajax(o);\n});\n</script>";
+}
?>
<div class="content">
<table class="table table-striped table-hover">
<thead>
<tr>
<th><?=gettext("CARP Interface")?></th>