Refactor first-boot process to introduce ordered execution and new one-shot scripts
Revise the first-boot script to implement a structured approach with 13 numbered steps, allowing for better control over the execution order. Introduce two new one-shot scripts: `01-set-rotation-once.sh` and `02-set-wallpaper-once.sh`, replacing the previous single script approach. Update documentation to reflect these changes, including the new configuration options for enabling/disabling steps and the revised file structure for one-shot scripts. Enhance the dashboard to display first-boot progress, improving user feedback during the initial setup.
This commit is contained in:
@@ -108,6 +108,15 @@
|
||||
<div id="progressWrap" class="progress-track" style="display:none;"><div id="progressFill" class="progress-fill"></div></div>
|
||||
</div>
|
||||
|
||||
<div id="firstBootCard" class="card" style="margin-bottom: 1rem; display:none;">
|
||||
<h2 class="card-title">First-boot progress</h2>
|
||||
<div id="firstBootStatus" class="status-row">
|
||||
<span id="firstBootStep" class="status-pill idle"></span>
|
||||
<span id="firstBootMsg" class="status-msg"></span>
|
||||
</div>
|
||||
<p id="firstBootIpWrap" style="margin-top: 0.5rem; font-size: 0.9rem; display:none;"><strong>Device IP:</strong> <code id="firstBootIp" class="mono"></code></p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2 class="card-title">Capture or deploy</h2>
|
||||
<p id="dhcpNetbootWrap" class="status-row" style="margin-bottom: 0.5rem; font-size: 0.85rem;"><span class="text-dim">Network boot (DHCP):</span> <span id="dhcpNetbootState">—</span> <button type="button" id="dhcpNetbootDisableBtn" class="btn btn-outline btn-sm" style="display:none;">Disable network boot</button> <button type="button" id="dhcpNetbootEnableBtn" class="btn btn-outline btn-sm" style="display:none;">Enable network boot</button></p>
|
||||
@@ -230,6 +239,28 @@
|
||||
function fmtSize(n) { if (n >= 1e9) return (n/1e9).toFixed(1)+' GB'; if (n >= 1e6) return (n/1e6).toFixed(1)+' MB'; return (n/1e3).toFixed(0)+' KB'; }
|
||||
function fmtDate(ts) { return new Date(ts*1000).toLocaleString(); }
|
||||
function fetchStatus() { fetch('/api/status').then(function(r){ return r.json(); }).then(renderStatus).catch(function(){ renderStatus({ phase: 'error', message: 'Could not load status.' }); }); }
|
||||
function renderFirstBootStatus(data) {
|
||||
const phase = data.phase || 'idle';
|
||||
const card = document.getElementById('firstBootCard');
|
||||
if (phase === 'idle' || phase === '') { card.style.display = 'none'; return; }
|
||||
card.style.display = 'block';
|
||||
const stepEl = document.getElementById('firstBootStep');
|
||||
const msgEl = document.getElementById('firstBootMsg');
|
||||
const ipWrap = document.getElementById('firstBootIpWrap');
|
||||
const ipEl = document.getElementById('firstBootIp');
|
||||
stepEl.textContent = data.step ? 'Step ' + data.step : (phase === 'done' ? 'Done' : phase);
|
||||
stepEl.className = 'status-pill ' + (phase === 'done' ? 'done' : phase === 'error' ? 'error' : 'flashing');
|
||||
msgEl.textContent = data.message || (phase === 'done' && data.ip ? 'First-boot finished. Device IP: ' + data.ip : '');
|
||||
if (phase === 'done' && data.ip) {
|
||||
ipWrap.style.display = 'block';
|
||||
ipEl.textContent = data.ip;
|
||||
} else {
|
||||
ipWrap.style.display = 'none';
|
||||
}
|
||||
}
|
||||
function fetchFirstBootStatus() {
|
||||
fetch('/api/first-boot-status').then(function(r){ return r.json(); }).then(renderFirstBootStatus).catch(function(){});
|
||||
}
|
||||
function fetchPending() { fetch('/api/pending-devices').then(function(r){ return r.json(); }).then(function(d){ renderPending(d.usb || null, d.network || []); }).catch(function(){ renderPending(null, []); }); }
|
||||
function fetchLog() { fetch('/api/log').then(function(r){ return r.json(); }).then(function(d){ document.getElementById('log').textContent = d.log || ''; }).catch(function(){}); }
|
||||
function fetchGolden() {
|
||||
@@ -286,10 +317,11 @@
|
||||
.then(function(d){ if(d.ok) fetchDhcpNetboot(); else alert(d.error || 'Failed'); })
|
||||
.catch(function(){ alert('Request failed'); });
|
||||
});
|
||||
fetchStatus(); fetchLog(); fetchPending(); fetchGolden(); fetchDhcpNetboot(); fetchDhcpLeases();
|
||||
fetchStatus(); fetchLog(); fetchPending(); fetchGolden(); fetchDhcpNetboot(); fetchDhcpLeases(); fetchFirstBootStatus();
|
||||
setInterval(fetchStatus, 2000);
|
||||
setInterval(fetchLog, 4000);
|
||||
setInterval(fetchPending, 2000);
|
||||
setInterval(fetchFirstBootStatus, 3000);
|
||||
setInterval(fetchGolden, 10000);
|
||||
setInterval(fetchDhcpNetboot, 10000);
|
||||
setInterval(fetchDhcpLeases, 10000);
|
||||
|
||||
Reference in New Issue
Block a user