feat(update): add release policy checks and dashboard version verification
This commit is contained in:
@@ -83,20 +83,36 @@
|
||||
|
||||
<!-- License status + Reload Caddy Button - top right corner -->
|
||||
<div class="reload-caddy-container">
|
||||
<div class="theme-toggle-group">
|
||||
<button id="theme" class="theme-toggle-btn" aria-label="Cycle theme" title="Click to cycle themes">
|
||||
<span id="theme-icon">🎨</span> <span id="theme-label">Dark</span>
|
||||
<div class="reload-caddy-main">
|
||||
<div class="theme-toggle-group">
|
||||
<button id="theme" class="theme-toggle-btn" aria-label="Cycle theme" title="Click to cycle themes">
|
||||
<span id="theme-icon">🎨</span> <span id="theme-label">Dark</span>
|
||||
</button>
|
||||
<button id="theme-customize-btn" class="theme-customize-link" title="Customize theme colors">Customize Theme</button>
|
||||
</div>
|
||||
<div id="license-status-topbar" class="license-status-topbar free" title="Click to manage license">
|
||||
<span id="license-topbar-icon">☆</span>
|
||||
<span id="license-topbar-text">FREE TIER</span>
|
||||
<span id="license-topbar-time"></span>
|
||||
</div>
|
||||
<button id="reload-caddy-top" aria-label="Reload Caddy configuration" style="padding: 10px 20px; font-size: 0.95rem; font-weight: 600; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border: none; border-radius: 6px; color: white; cursor: pointer; box-shadow: 0 2px 6px rgba(52, 152, 219, 0.3); transition: all 0.2s ease;">
|
||||
🔄 Reload Caddy
|
||||
</button>
|
||||
<button id="theme-customize-btn" class="theme-customize-link" title="Customize theme colors">Customize Theme</button>
|
||||
</div>
|
||||
<div id="license-status-topbar" class="license-status-topbar free" title="Click to manage license">
|
||||
<span id="license-topbar-icon">☆</span>
|
||||
<span id="license-topbar-text">FREE TIER</span>
|
||||
<span id="license-topbar-time"></span>
|
||||
<button id="dashboard-version" class="dashboard-version" type="button" title="View DashCaddy verification info" aria-label="View DashCaddy verification info">Version —</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="version-info-modal" class="weather-modal">
|
||||
<div class="weather-modal-content version-info-modal-content">
|
||||
<h3>DashCaddy Verification Info</h3>
|
||||
<p class="version-info-subtitle">Current version details and updater verification status.</p>
|
||||
<div id="version-info-status" class="version-info-status">Loading…</div>
|
||||
<div id="version-info-grid" class="version-info-grid" style="display:none;"></div>
|
||||
<div id="version-info-history" class="version-info-history" style="display:none;"></div>
|
||||
<div class="weather-modal-buttons" style="margin-top: 16px;">
|
||||
<button id="version-info-close">Close</button>
|
||||
</div>
|
||||
<button id="reload-caddy-top" aria-label="Reload Caddy configuration" style="padding: 10px 20px; font-size: 0.95rem; font-weight: 600; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border: none; border-radius: 6px; color: white; cursor: pointer; box-shadow: 0 2px 6px rgba(52, 152, 219, 0.3); transition: all 0.2s ease;">
|
||||
🔄 Reload Caddy
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -538,6 +554,117 @@
|
||||
}
|
||||
var yr = document.getElementById('footer-year');
|
||||
if (yr) yr.textContent = new Date().getFullYear();
|
||||
|
||||
var versionEl = document.getElementById('dashboard-version');
|
||||
var versionInfoModal = document.getElementById('version-info-modal');
|
||||
var versionInfoStatus = document.getElementById('version-info-status');
|
||||
var versionInfoGrid = document.getElementById('version-info-grid');
|
||||
var versionInfoHistory = document.getElementById('version-info-history');
|
||||
var versionInfoClose = document.getElementById('version-info-close');
|
||||
|
||||
function formatValue(value) {
|
||||
if (value == null || value === '') return '—';
|
||||
if (typeof value === 'object') return JSON.stringify(value);
|
||||
return String(value);
|
||||
}
|
||||
|
||||
function renderInfoRow(label, value) {
|
||||
return '<div class="version-info-row"><span class="version-info-label">' + label + '</span><span class="version-info-value">' + formatValue(value) + '</span></div>';
|
||||
}
|
||||
|
||||
function renderHistory(history) {
|
||||
if (!Array.isArray(history) || !history.length) {
|
||||
versionInfoHistory.style.display = 'none';
|
||||
versionInfoHistory.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
versionInfoHistory.style.display = '';
|
||||
versionInfoHistory.innerHTML = '<h4>Recent Update History</h4>' + history.slice(0, 5).map(function(entry) {
|
||||
return '<div class="version-history-entry">'
|
||||
+ '<div><strong>' + formatValue(entry.version) + '</strong> <span class="version-history-status">' + formatValue(entry.status) + '</span></div>'
|
||||
+ '<div class="version-history-meta">From ' + formatValue(entry.fromVersion) + ' · ' + formatValue(entry.timestamp) + '</div>'
|
||||
+ '</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function openVersionInfo() {
|
||||
if (!versionInfoModal) return;
|
||||
versionInfoModal.classList.add('show');
|
||||
versionInfoStatus.textContent = 'Loading…';
|
||||
versionInfoGrid.style.display = 'none';
|
||||
versionInfoHistory.style.display = 'none';
|
||||
versionInfoGrid.innerHTML = '';
|
||||
versionInfoHistory.innerHTML = '';
|
||||
|
||||
Promise.all([
|
||||
fetch('/api/v1/system/version', { cache: 'no-store' }).then(function(response) {
|
||||
if (!response.ok) throw new Error('Version check failed');
|
||||
return response.json();
|
||||
}),
|
||||
fetch('/api/v1/system/update-status', { cache: 'no-store' }).then(function(response) {
|
||||
if (!response.ok) throw new Error('Update status failed');
|
||||
return response.json();
|
||||
}),
|
||||
fetch('/api/v1/system/update-history', { cache: 'no-store' }).then(function(response) {
|
||||
if (!response.ok) throw new Error('Update history failed');
|
||||
return response.json();
|
||||
})
|
||||
]).then(function(results) {
|
||||
var versionData = results[0] || {};
|
||||
var statusData = results[1] || {};
|
||||
var historyData = results[2] || {};
|
||||
var lastResult = statusData.lastResult || {};
|
||||
var lastPolicy = lastResult.policy || {};
|
||||
|
||||
versionInfoStatus.textContent = 'Verification info loaded.';
|
||||
versionInfoGrid.style.display = 'grid';
|
||||
versionInfoGrid.innerHTML = [
|
||||
renderInfoRow('Version', versionData.version),
|
||||
renderInfoRow('Commit', versionData.commit),
|
||||
renderInfoRow('Updater Status', statusData.status),
|
||||
renderInfoRow('Last Check', statusData.lastCheck ? new Date(statusData.lastCheck).toLocaleString() : 'Never'),
|
||||
renderInfoRow('Update Available', lastResult.available),
|
||||
renderInfoRow('Eligible', lastPolicy.eligible),
|
||||
renderInfoRow('Policy Reason', lastPolicy.reason),
|
||||
renderInfoRow('Channel', lastPolicy.releaseChannel || (lastResult.instance && lastResult.instance.channel)),
|
||||
renderInfoRow('Instance ID', lastResult.instance && lastResult.instance.instanceId)
|
||||
].join('');
|
||||
|
||||
renderHistory(historyData.history);
|
||||
}).catch(function(error) {
|
||||
versionInfoStatus.textContent = 'Could not load verification info: ' + error.message;
|
||||
});
|
||||
}
|
||||
|
||||
if (versionEl) {
|
||||
fetch('/api/v1/system/version', { cache: 'no-store' })
|
||||
.then(function(response) {
|
||||
if (!response.ok) throw new Error('HTTP ' + response.status);
|
||||
return response.json();
|
||||
})
|
||||
.then(function(data) {
|
||||
if (data && data.success && data.version) {
|
||||
versionEl.textContent = 'Version ' + data.version;
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
versionEl.textContent = 'Version unavailable';
|
||||
});
|
||||
|
||||
versionEl.addEventListener('click', openVersionInfo);
|
||||
}
|
||||
|
||||
if (versionInfoClose && versionInfoModal) {
|
||||
versionInfoClose.addEventListener('click', function() {
|
||||
versionInfoModal.classList.remove('show');
|
||||
});
|
||||
versionInfoModal.addEventListener('click', function(event) {
|
||||
if (event.target === versionInfoModal) {
|
||||
versionInfoModal.classList.remove('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user