feat(agent): v0.3.9 sync, UI details, self-update, centralized version

- Add agent/server startup sync (sync/sync_response)
- Centralize agent version in agent/VERSION + expose /api/agent/version
- Display agent version, nodeId and server version in local UI
- Add agent self-update detection/download/restart via helper scripts
- Run start/stop/delete/reset handlers in goroutines to avoid WebSocket blocking
- Update dashboard download links and SUIVI_VPN_ONDEMAND.md
- Document Podman stays installer-managed, not agent-updated
This commit is contained in:
EduBox Dev
2026-06-27 21:11:20 +00:00
parent cf8b66340a
commit e946b22a42
14 changed files with 613 additions and 59 deletions
+63
View File
@@ -479,6 +479,8 @@
<h1 id="welcome-text">Bienvenue</h1>
<p class="subtitle">État de ton poste</p>
<div id="update-banner"></div>
<div class="services">
<div class="service-item" id="svc-connection">
<div class="service-icon pending"></div>
@@ -628,6 +630,7 @@
: 'Bienvenue';
showView('dashboard');
ws.send(JSON.stringify({action: 'instances'}));
loadSettings();
break;
case 'activation_failed':
@@ -671,6 +674,18 @@
case 'config':
fillSettings(msg.config);
break;
case 'update_available':
fillSettings({
...getCurrentConfig(),
server_version: msg.version,
update_available: true
});
break;
case 'update_progress':
showUpdateProgress(msg.percent, msg.message);
break;
}
}
@@ -876,7 +891,14 @@
}
}
let currentConfig = {};
function getCurrentConfig() {
return currentConfig;
}
function fillSettings(cfg) {
currentConfig = cfg;
document.getElementById('cfg-server').value = cfg.server || '';
document.getElementById('cfg-node').value = cfg.node_id || '';
document.getElementById('cfg-headscale-url').value = cfg.headscale_url || '';
@@ -885,6 +907,46 @@
document.getElementById('detail-version').textContent = cfg.version || 'dev';
document.getElementById('detail-nodeid').textContent = cfg.node_id || '-';
document.getElementById('detail-server').textContent = cfg.server || '-';
const updateBanner = document.getElementById('update-banner');
if (cfg.update_available) {
updateBanner.innerHTML = `
<div class="service-item" style="background: var(--warning-bg); border-radius: 8px; padding: 0.75rem; margin-bottom: 0.75rem;">
<div class="service-icon" style="background: var(--warning);">⬆️</div>
<div>
<div class="service-text">Mise à jour disponible</div>
<div class="service-detail">Version ${cfg.server_version} disponible. <button class="ghost" style="padding: 0; font-weight: 600;" onclick="startAgentUpdate()">Mettre à jour maintenant</button></div>
</div>
</div>
`;
} else {
updateBanner.innerHTML = '';
}
}
function showUpdateProgress(percent, message) {
const banner = document.getElementById('update-banner');
banner.innerHTML = `
<div class="service-item" style="background: var(--info-bg); border-radius: 8px; padding: 0.75rem; margin-bottom: 0.75rem;">
<div class="service-icon" style="background: var(--info);">⬇️</div>
<div>
<div class="service-text">Mise à jour en cours</div>
<div class="service-detail">${escapeHtml(message || '')} (${percent || 0}%)</div>
</div>
</div>
`;
}
async function startAgentUpdate() {
showUpdateProgress('10', 'Préparation de la mise à jour...');
try {
const res = await fetch('/api/update', {method: 'POST'});
if (!res.ok) {
showUpdateProgress('0', 'Erreur ' + res.status);
}
} catch (err) {
showUpdateProgress('0', escapeHtml(err.message));
}
}
async function saveSettings(event) {
@@ -919,6 +981,7 @@
function showDashboard() {
showView('dashboard');
ws.send(JSON.stringify({action: 'get_status'}));
loadSettings();
}
function controlInstance(instanceId, action) {