Files
felhom-controller/controller/internal/web/templates/storage_attach.html
T
admin 7df061c00f D0 Part 4: settings visual pass + remaining pages; grep gate zero
- settings.html: Aktív/Inaktív rows -> run-blue check / neutral gray
  (Inaktív no longer red), update states -> run/crit/progress with
  sprite check/x/spinner, pencil + cancel buttons -> icons, storage
  badges -> tags, host-disk bar + JS drive capBar -> meters
  (usageColorClass -> nominal/warn/crit), state-text-* consumers on the
  new suffixes incl. JS-built class names.
- debug.html, app_info.html, storage_init/attach.html, logs.html:
  emoji -> sprite icons or plain text in templates AND JS strings.
- catchall.html (standalone, no sprite): v2 token sweep of its inline
  style, status emoji -> inline SVGs; a stopped app renders neutral,
  not red.
- login.html: two-tone H1 (last word blue-bright).
- setup_hub_versions.html: stale var(--border,#30363d) fallback -> v2.
- Test Group F grep gate: all 34 banned patterns at ZERO across
  internal/web + internal/setup; Scenario E test now asserts the
  '--bg-0: #0A1220' token literal.
2026-07-02 14:38:51 +02:00

116 lines
6.2 KiB
HTML

{{define "storage_attach"}}
{{template "layout_start" .}}
<div class="page-header">
<div style="display:flex;align-items:center;gap:.5rem">
<a href="/settings" class="btn btn-sm btn-outline">← Vissza</a>
<h2>Meglévő meghajtó csatolása</h2>
</div>
</div>
<div class="settings-card">
<h3>1. Meghajtó kiválasztása</h3>
<p class="settings-card-desc">Válassza ki a már fájlrendszerrel rendelkező meghajtót.
<strong>A meghajtón lévő adatok nem törlődnek</strong> — a csatolás csak elérhetővé teszi azokat.</p>
<div id="disk-error" class="alert alert-error" style="display:none;margin-bottom:1rem"></div>
<div id="disk-list">Betöltés…</div>
</div>
<div class="settings-card" id="cfg-card" style="display:none">
<h3>2. Konfiguráció</h3>
<form id="attach-form" onsubmit="return submitAttach(event)">
<div class="form-group">
<label>Kiválasztott eszköz</label>
<span class="settings-value mono" id="sel-device"></span>
</div>
<div class="form-group">
<label for="mount-name">Csatlakoztatási név <span class="required">*</span></label>
<div style="display:flex;align-items:center;gap:.25rem">
<span class="mono" style="opacity:.6">/mnt/</span>
<input type="text" id="mount-name" class="form-control" placeholder="hdd_1"
pattern="[a-zA-Z0-9_-]+" required style="max-width:180px">
</div>
<span class="form-hint">A meghajtó a /mnt/&lt;név&gt; útvonalra kerül.</span>
</div>
<div class="form-group">
<label for="storage-label">Megnevezés</label>
<input type="text" id="storage-label" class="form-control" placeholder="Külső HDD 1TB" maxlength="50">
</div>
<label class="toggle" style="margin-bottom:1.25rem">
<input type="checkbox" id="set-default">
<span class="toggle-label">Beállítás alapértelmezett adattárolóként új telepítéseknél</span>
</label>
<div class="form-actions" style="gap:.75rem">
<button type="submit" class="btn btn-primary" id="attach-btn">Csatolás</button>
<a href="/settings" class="btn btn-outline">Mégsem</a>
</div>
<div id="attach-result" style="margin-top:1rem"></div>
</form>
</div>
<script>
var selDevice = "", selFSType = "";
function esc(s){ return String(s==null?'':s).replace(/[&<>"]/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];}); }
function fmtSize(b){
if(!b) return '';
var g=b/1073741824;
return g>=1 ? g.toFixed(g>=10?0:1)+' GB' : Math.round(b/1048576)+' MB';
}
async function loadDisks(){
try{
// Impl-2b: the raw-device scan (agent GET /disks/candidates). `attach` = unclaimed disks already
// carrying a mountable ext4/xfs FS (mounted + bound, NO format — data preserved). The agent's filter
// excludes OS/enrolled/claimed disks, so we trust the list as-is.
var r = await fetch('/api/disks/candidates'); var j = await r.json();
if(!j.ok){ throw new Error(j.error||'Hiba'); }
var cands = (j.data&&j.data.attach)||[];
if(cands.length===0){ document.getElementById('disk-list').innerHTML='<p class="form-hint">Nincs csatolható meghajtó — a csatoláshoz olyan (még nem használt) meghajtó kell, amelyen már van fájlrendszer. Új, üres meghajtóhoz használja az „Inicializálás” lehetőséget.</p>'; return; }
var html='<div class="drive-list">';
cands.forEach(function(d,i){
var title = d.model ? esc(d.model) : esc(d.device);
var parts = [esc(d.device)];
if(d.size_bytes) parts.push(fmtSize(d.size_bytes));
if(d.fstype) parts.push(esc(d.fstype));
var sub = parts.join(' · ');
// Attach the FS-bearing node (mount_source, e.g. /dev/sdd1); the agent resolves its UUID.
var dev = d.mount_source || d.device;
html+='<label class="drive-card role-user-data is-selectable" id="dc-'+i+'">'
+'<div class="drive-card-top"><div class="drive-select"><input type="radio" name="disk" value="'+esc(dev)+'" data-fs="'+esc(d.fstype)+'" data-i="'+i+'" onchange="pickDisk(this)">'
+'<div class="drive-id"><span class="drive-name">'+title+'</span><span class="drive-sub">'+sub+'</span></div></div>'
+'<div class="drive-badges"><span class="badge badge-ok">Fájlrendszer: '+esc(d.fstype)+'</span></div></div></label>';
});
html+='</div>';
document.getElementById('disk-list').innerHTML=html;
}catch(e){ var el=document.getElementById('disk-error'); el.style.display='block'; el.textContent='Meghajtók betöltése sikertelen: '+e.message; }
}
function pickDisk(radio){
selDevice=radio.value; selFSType=radio.getAttribute('data-fs')||"";
document.getElementById('sel-device').textContent=selDevice;
document.querySelectorAll('.drive-card').forEach(function(c){c.classList.remove('is-picked');});
var card=document.getElementById('dc-'+radio.getAttribute('data-i')); if(card) card.classList.add('is-picked');
document.getElementById('cfg-card').style.display='block';
document.getElementById('cfg-card').scrollIntoView({behavior:'smooth'});
}
async function submitAttach(ev){
ev.preventDefault();
var btn=document.getElementById('attach-btn'); var out=document.getElementById('attach-result');
btn.disabled=true; out.innerHTML='<p class="form-hint">Csatlakoztatás folyamatban…</p>';
try{
var body={device:selDevice, fstype:selFSType, mount_name:document.getElementById('mount-name').value,
label:document.getElementById('storage-label').value, set_default:document.getElementById('set-default').checked};
var r=await fetch('/api/storage/attach',{method:'POST',headers:Object.assign({'Content-Type':'application/json'},csrfHeaders()),body:JSON.stringify(body)});
var j=await r.json();
if(!j.ok){ throw new Error(j.error||'Hiba'); }
out.innerHTML='<div class="alert alert-success">A meghajtó sikeresen csatolva és regisztrálva: <strong class="mono">'+(j.data.where||'')+'</strong>. <a href="/settings">Vissza a Beállításokhoz →</a></div>';
}catch(e){ out.innerHTML='<div class="alert alert-error">Hiba: '+e.message+'</div>'; btn.disabled=false; }
return false;
}
loadDisks();
</script>
{{template "layout_end" .}}
{{end}}