fix: brought back postgress that we removed in the last commit, and added persistent folder for it

This commit is contained in:
2026-04-19 20:10:40 +03:00
parent d8b0b9ce28
commit 9a213e93f8
8 changed files with 3412 additions and 0 deletions

View File

@@ -0,0 +1,362 @@
<!doctype html>
<meta charset="utf-8">
<title>Provisioning Wizard — Mode · Bellsystems Console</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&amp;family=JetBrains+Mono:wght@400;500;600;700&amp;display=swap" rel="stylesheet">
<link rel="stylesheet" href="wizard.css">
<style>
/* Page-specific: Mode select */
.mode-wrap{
max-width:980px;margin:0 auto;
display:flex;flex-direction:column;gap:28px;
}
.mode-head{
text-align:center;margin-top:12px;
}
.mode-head .eyebrow{
font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
color:var(--text-3);text-transform:uppercase;
}
.mode-head h2{
margin:10px 0 6px;font-size:28px;font-weight:600;letter-spacing:-0.01em;
}
.mode-head p{
margin:0;color:var(--text-2);font-size:14px;
}
.mode-grid{
display:grid;grid-template-columns:1fr 1fr;gap:16px;
}
.mode-card{
position:relative;
background:linear-gradient(180deg, var(--bg-1), var(--bg-2) 60%);
border:1px solid var(--line);
border-radius:var(--radius);
padding:28px 26px 24px;
cursor:pointer;
transition:.18s;
overflow:hidden;
display:flex;flex-direction:column;gap:20px;
min-height:340px;
text-align:left;
}
.mode-card::before{
content:"";position:absolute;inset:0 0 auto 0;height:1px;
background:linear-gradient(90deg, transparent, rgba(255,255,255,.06), transparent);
}
.mode-card::after{
content:"";position:absolute;inset:auto 0 0 0;height:2px;
background:transparent;transition:.18s;
}
.mode-card:hover{
border-color:var(--line-strong);
transform:translateY(-2px);
box-shadow:0 20px 50px -20px rgba(0,0,0,.6);
}
.mode-card.selected{
border-color:rgba(34,224,122,.35);
background:linear-gradient(180deg, rgba(34,224,122,.04), var(--bg-2) 60%);
}
.mode-card.selected::after{background:var(--accent);box-shadow:0 0 18px rgba(34,224,122,.5)}
.mode-card .icon-wrap{
width:52px;height:52px;border-radius:12px;
display:grid;place-items:center;
background:var(--bg-3);border:1px solid var(--line-strong);
color:var(--text-1);
}
.mode-card.selected .icon-wrap{
background:rgba(34,224,122,.1);
border-color:rgba(34,224,122,.35);
color:var(--accent);
}
.mode-card .icon-wrap svg{width:26px;height:26px}
.mode-card h3{
margin:0;font-size:20px;font-weight:600;letter-spacing:-0.005em;
}
.mode-card .desc{
margin:0;color:var(--text-2);font-size:13.5px;line-height:1.55;
}
.mode-card .points{
display:flex;flex-direction:column;gap:8px;
padding-top:16px;margin-top:auto;
border-top:1px solid var(--line);
}
.mode-card .points .pt{
display:flex;align-items:center;gap:10px;
font-size:12.5px;color:var(--text-2);
font-family:var(--mono);
}
.mode-card .points .pt svg{width:13px;height:13px;color:var(--text-3);flex-shrink:0}
.mode-card.selected .points .pt svg{color:var(--accent)}
.mode-card .radio{
position:absolute;top:20px;right:20px;
width:22px;height:22px;border-radius:50%;
border:1.5px solid var(--line-strong);
background:var(--bg-3);
display:grid;place-items:center;
transition:.18s;
}
.mode-card .radio::after{
content:"";width:10px;height:10px;border-radius:50%;
background:transparent;transition:.18s;
}
.mode-card.selected .radio{border-color:var(--accent);background:rgba(34,224,122,.1)}
.mode-card.selected .radio::after{background:var(--accent);box-shadow:0 0 10px var(--accent)}
.mode-card .badge-count{
display:inline-flex;align-items:center;gap:6px;
font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;
padding:4px 8px;border-radius:999px;
background:var(--bg-3);border:1px solid var(--line);
color:var(--text-2);text-transform:uppercase;
width:fit-content;
}
.mode-card.selected .badge-count{
background:rgba(34,224,122,.08);color:var(--accent);
border-color:rgba(34,224,122,.25);
}
.mode-footer{
display:flex;align-items:center;justify-content:space-between;
padding:14px 4px 0;
}
.mode-footer .hint{
font-family:var(--mono);font-size:11px;color:var(--text-3);
letter-spacing:.04em;
}
.mode-footer .hint kbd{
font-family:var(--mono);font-size:10px;padding:2px 6px;border-radius:4px;
background:var(--bg-3);border:1px solid var(--line-strong);color:var(--text-1);
margin:0 2px;
}
</style>
</head>
<body class="layout-split">
<div class="shell">
<!-- TOP BAR -->
<div class="topbar">
<div class="brand">
<div class="logo" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="#22e07a" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 3h8l4 4v14H6z"></path>
<path d="M14 3v4h4"></path>
<path d="M10 12l-2 3h3l-1 3 3-4h-2l1-2z" fill="#22e07a" stroke="none"></path>
</svg>
</div>
<div class="title">
<h1>Provisioning Wizard</h1>
<p>Flash firmware to a Bell Systems board via WebSerial</p>
</div>
</div>
<div class="top-actions" style="margin-top:2px">
<button class="btn btn-ghost">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5"></path><path d="M12 19l-7-7 7-7"></path></svg>
Back to Inventory
</button>
</div>
</div>
<!-- STEPPER -->
<div class="stepper" role="list">
<div class="step active" role="listitem">
<div class="num">1</div>
<div class="meta"><span class="label">Mode</span><span class="sub" id="step-mode-sub">choose</span></div>
<div class="step-divider"></div>
</div>
<div class="step" role="listitem">
<div class="num">2</div>
<div class="meta"><span class="label">Device</span><span class="sub">pending</span></div>
<div class="step-divider"></div>
</div>
<div class="step" role="listitem">
<div class="num">3</div>
<div class="meta"><span class="label">Flash</span><span class="sub">pending</span></div>
<div class="step-divider"></div>
</div>
<div class="step" role="listitem">
<div class="num">4</div>
<div class="meta"><span class="label">Verify</span><span class="sub">pending</span></div>
<div class="step-divider"></div>
</div>
<div class="step" role="listitem">
<div class="num">5</div>
<div class="meta"><span class="label">Done</span><span class="sub">pending</span></div>
</div>
</div>
<!-- MAIN -->
<section class="card" aria-label="Select provisioning mode">
<div class="card-head">
<h2><span class="dot"></span> Select Mode</h2>
<div class="meta-inline" style="padding:0">
<span class="k">Step</span><span class="v">1 / 5</span>
</div>
</div>
<div style="padding:36px 28px">
<div class="mode-wrap">
<div class="mode-head">
<div class="eyebrow">Provisioning Wizard</div>
<h2>What are we doing today?</h2>
<p>Choose whether to flash a board that already exists in inventory, or generate a brand-new device record.</p>
</div>
<div class="mode-grid">
<!-- OPTION 1 -->
<div class="mode-card selected" data-mode="existing" tabindex="0" role="button" aria-pressed="true">
<span class="radio" aria-hidden="true"></span>
<div class="icon-wrap">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="7"></circle>
<path d="M21 21l-4.3-4.3"></path>
</svg>
</div>
<div>
<h3>Flash Existing Device</h3>
<p class="desc" style="margin-top:6px">Re-flash or finish provisioning a board that is already on record. Search by serial, or pick from boards not yet shipped.</p>
</div>
<span class="badge-count">
<svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
<span id="existingCount">247 eligible</span>
</span>
<div class="points">
<div class="pt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
Status: Manufactured, Flashed, or Provisioned
</div>
<div class="pt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
Preserves existing serial &amp; inventory record
</div>
<div class="pt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
Ideal for rework or returned units
</div>
</div>
</div>
<!-- OPTION 2 -->
<div class="mode-card" data-mode="new" tabindex="0" role="button" aria-pressed="false">
<span class="radio" aria-hidden="true"></span>
<div class="icon-wrap">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="3"></rect>
<path d="M12 8v8M8 12h8"></path>
</svg>
</div>
<div>
<h3>Deploy New Device</h3>
<p class="desc" style="margin-top:6px">Pick a hardware type &amp; revision. We'll mint a new serial, create the inventory record, and proceed to flash it.</p>
</div>
<span class="badge-count">
<svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"></path></svg>
7 board types · + bespoke
</span>
<div class="points">
<div class="pt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
Auto-generates next sequential serial
</div>
<div class="pt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
Creates inventory record at status <span class="tok-em" style="color:var(--text-1)">Manufactured</span>
</div>
<div class="pt">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
Ideal for fresh production runs
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Action bar -->
<div class="action-bar">
<div class="meta-inline">
<span class="k">MODE</span><span class="v" id="chosenLabel">Flash Existing Device</span>
<span class="sep">/</span>
<span class="k">NEXT</span><span class="v">Device selection</span>
</div>
<div style="display:flex;gap:10px">
<button class="btn btn-ghost" disabled style="opacity:.45;cursor:not-allowed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5"></path><path d="M12 19l-7-7 7-7"></path></svg>
Back
</button>
<a class="btn btn-primary btn-lg" id="continueBtn" href="Device Select.html?mode=existing">
Continue
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"></path><path d="M12 5l7 7-7 7"></path></svg>
<span class="kbd"></span>
</a>
</div>
</div>
</section>
</div>
<script>
const cards = document.querySelectorAll('.mode-card');
const label = document.getElementById('chosenLabel');
const subLabel = document.getElementById('step-mode-sub');
const continueBtn = document.getElementById('continueBtn');
function select(mode){
cards.forEach(c => {
const is = c.dataset.mode === mode;
c.classList.toggle('selected', is);
c.setAttribute('aria-pressed', is ? 'true' : 'false');
});
if (mode === 'existing'){
label.textContent = 'Flash Existing Device';
subLabel.textContent = 'existing';
continueBtn.href = 'Device Select.html?mode=existing';
} else {
label.textContent = 'Deploy New Device';
subLabel.textContent = 'new';
continueBtn.href = 'Device Select.html?mode=new';
}
localStorage.setItem('wizard.mode', mode);
}
cards.forEach(c => {
c.addEventListener('click', () => select(c.dataset.mode));
c.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' '){ e.preventDefault(); select(c.dataset.mode); }
});
});
// Restore
const saved = localStorage.getItem('wizard.mode');
if (saved) select(saved);
// Enter to continue
document.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.target.matches('input,textarea')){
continueBtn.click();
}
});
</script>
</body>
</html>