Integrate dashboard natively into Deck UI
This commit is contained in:
+4
-4
@@ -5,13 +5,13 @@ Hardware-Seite entfällt. Die Übersicht für Endpunkt und GPU-Modus bleibt als
|
||||
separater Bereich erhalten; die alten Router-, Bild- und Modus-Umschalter
|
||||
werden im Dashboard nicht eingeblendet.
|
||||
|
||||
Die Karten und Ansichten ab „Aktives Profil“ übernehmen die Struktur des alten
|
||||
Athena-Dashboards: CPU, RAM, beide GPUs mit VRAM/Temperatur/Takt/Leistung,
|
||||
Das Dashboard ist Teil des normalen Deck-DOM und nutzt dessen Navigation, Typografie,
|
||||
Karten und responsive Layoutregeln. Es übernimmt die Messwerte und Funktionen
|
||||
ab „Aktives Profil“ aus dem alten Athena-Dashboard: CPU, RAM, beide GPUs mit VRAM/Temperatur/Takt/Leistung,
|
||||
Inferenzraten, Prompt-Cache, Anfragen, Slots, Kontextfenster, MTP,
|
||||
Tokenzähler, GPU- und Slot-Verlauf, Nutzung nach Profil, Modellwechsel,
|
||||
Profile, Dienste, Host/Netzwerk, GPU-Prozesse, llama.cpp-Parameter,
|
||||
GGUF-Dateien und verschlüsselte portable Backups. Die Farbwerte sind an Deck
|
||||
angepasst. Nicht verfügbare Laufzeitwerte erscheinen als „–“; sie werden nicht
|
||||
GGUF-Dateien und verschlüsselte portable Backups. Die Anzeige ist im Deck-Design neu aufgebaut. Nicht verfügbare Laufzeitwerte erscheinen als „–“; sie werden nicht
|
||||
aus historischen Werten geschätzt. Profil und Modell beziehen sich auf Decks
|
||||
eigenen Worker, nicht auf den alten Router.
|
||||
|
||||
|
||||
+10
-10
@@ -4,14 +4,14 @@ const esc=v=>String(v??'–').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>'
|
||||
const pct=n=>n==null?'–':`${Number(n).toFixed(1)}%`;
|
||||
const gib=b=>b==null?'–':`${(Number(b)/1073741824).toFixed(1)} GiB`;
|
||||
const dur=s=>{if(s==null)return'–';let d=Math.floor(s/86400),h=Math.floor(s%86400/3600),m=Math.floor(s%3600/60);return d?`${d}d ${h}h`:`${h}h ${m}m`};
|
||||
const $=id=>root.getElementById(id);
|
||||
const $=id=>root.querySelector(`#${id}`);
|
||||
const imagePhaseLabel=p=>({'running':'Bildauftrag läuft','loading':'Bildmodell lädt','complete':'bereit','failed':'Fehler'})[p]||p||'inaktiv';
|
||||
function cleanup(){for(const timer of timers)clearInterval(timer);timers=[];controller?.abort();controller=null;host=null;root=null}
|
||||
function gpuCard(g){let total=g.memory_total_mib||0,used=g.memory_used_mib||0,p=total&&g.memory_used_mib!=null?used/total*100:0,load=Math.max(0,Math.min(100,g.gpu_percent||0)),memoryText=total&&g.memory_used_mib!=null?`${(used/1024).toFixed(1)} / ${(total/1024).toFixed(1)} GiB`:'–';return `<article class="card span6"><div class="gpu-title"><div><div class="label">GPU ${esc(g.index)}</div><div class="value">${esc(g.name)}</div></div><span class="badge">${esc(g.pstate)}</span></div><div class="metrics"><div class="metric"><b>${pct(g.gpu_percent)}</b><span>GPU-Kern</span></div><div class="metric"><b>${memoryText}</b><span>VRAM</span></div><div class="metric"><b>${esc(g.temperature_c)} °C</b><span>Temperatur</span></div><div class="metric"><b>${esc(g.power_w)} / ${esc(g.power_limit_w)} W</b><span>Leistung</span></div><div class="metric"><b>${esc(g.memory_controller_percent)} %</b><span>Speichercontroller</span></div><div class="metric"><b>${esc(g.graphics_clock_mhz)} MHz</b><span>GPU-Takt</span></div><div class="metric"><b>${esc(g.memory_clock_mhz)} MHz</b><span>Speichertakt</span></div><div class="metric"><b>${esc(g.fan_percent)} %</b><span>Lüfter</span></div></div><div class="bar-label"><span>GPU-Auslastung</span><span>${pct(load)}</span></div><div class="bar"><div class="fill gpu-load" style="width:${load}%"></div></div><div class="bar-label"><span>VRAM</span><span>${pct(p)}</span></div><div class="bar"><div class="fill" style="width:${p}%"></div></div></article>`}
|
||||
function mount(){
|
||||
controller=new AbortController();
|
||||
root=host.attachShadow({mode:'open'});
|
||||
root.innerHTML=`<link rel="stylesheet" href="/dashboard.css"><div class="dashboard-root"><main><div class="top"><div><div class="eyebrow">Athena Deck · Live Telemetry</div><h1>Dashboard</h1></div><div class="live"><span class="dot" id="dot"></span><span id="updated">verbinde …</span></div></div><section class="grid"> <article class="card span3"><div class="label">Aktives Profil</div><div class="value" id="profile">–</div><div class="sub" id="profileSub">Deck wird abgefragt</div></article>
|
||||
root=host;
|
||||
root.innerHTML=`<div class="dashboard-root"><div class="top"><div><div class="kicker">ATHENA / TELEMETRIE</div><h1>Dashboard</h1><p>System, Inferenz und Verlauf auf einen Blick.</p></div><div class="live"><span class="dot" id="dot"></span><span id="updated">verbinde …</span></div></div><section class="grid"> <article class="card span3"><div class="label">Aktives Profil</div><div class="value" id="profile">–</div><div class="sub" id="profileSub">Deck wird abgefragt</div></article>
|
||||
<article class="card span3"><div class="label">Modell</div><div class="value" id="model">–</div><div class="sub" id="modelSub">–</div></article>
|
||||
<article class="card span3"><div class="label">CPU</div><div class="value" id="cpu">–</div><div class="bar"><div class="fill" id="cpuBar"></div></div><div class="sub" id="load">–</div></article>
|
||||
<article class="card span3"><div class="label">System-RAM</div><div class="value" id="ram">–</div><div class="bar"><div class="fill" id="ramBar"></div></div><div class="sub" id="ramSub">–</div></article>
|
||||
@@ -45,8 +45,8 @@ root.innerHTML=`<link rel="stylesheet" href="/dashboard.css"><div class="dashboa
|
||||
<div class="section-title">Notfall-Backups · herunterladen</div>
|
||||
<article class="card span12"><div class="row"><div><div class="label">Verschlüsselte portable Sicherungen</div><div class="sub">Unersetzliche Daten ohne erneut ladbare Modellgewichte · maximal fünf Generationen</div></div></div><div class="scroll"><table><thead><tr><th>Erstellt</th><th>Größe</th><th>SHA256</th><th></th></tr></thead><tbody id="backupFiles"><tr><td colspan="4">Backups werden geladen …</td></tr></tbody></table></div><div class="sub" id="backupNote">Zum Wiederherstellen wird der separat verwahrte Age-Schlüssel benötigt.</div></article>
|
||||
<article class="card span12 error" id="errors" hidden></article>
|
||||
</section><div class="footer">Aktualisierung jede Sekunde · Steuerung über die Deck-Übersicht</div></main></div>`;
|
||||
root.querySelector('link').addEventListener('load',()=>{if(host?.isConnected)refreshHistory()},{once:true});
|
||||
</section><div class="footer">Aktualisierung jede Sekunde · Steuerung über die Deck-Übersicht</div></div>`;
|
||||
|
||||
|
||||
|
||||
const deNum=n=>n==null?'–':Number(n).toLocaleString('de-DE',{maximumFractionDigits:1});
|
||||
@@ -130,7 +130,7 @@ function drawHistory(points){
|
||||
const canvas=$('gpuHistoryChart'),rect=canvas.getBoundingClientRect(),ratio=window.devicePixelRatio||1;
|
||||
canvas.width=Math.max(1,Math.floor(rect.width*ratio));canvas.height=Math.max(1,Math.floor(rect.height*ratio));
|
||||
const x=canvas.getContext('2d');x.scale(ratio,ratio);const w=rect.width,h=rect.height,pad={l:42,r:44,t:16,b:28};
|
||||
x.clearRect(0,0,w,h);x.strokeStyle='#213044';x.fillStyle='#8fa1b5';x.font='11px system-ui';x.lineWidth=1;
|
||||
x.clearRect(0,0,w,h);x.strokeStyle='#303a37';x.fillStyle='#97a79e';x.font='11px system-ui';x.lineWidth=1;
|
||||
for(let i=0;i<=4;i++){let y=pad.t+(h-pad.t-pad.b)*i/4;x.beginPath();x.moveTo(pad.l,y);x.lineTo(w-pad.r,y);x.stroke();x.fillText(`${100-i*25}%`,4,y+4);x.fillText(`${100-i*25}°`,w-pad.r+7,y+4)}
|
||||
if(!points.length){x.fillText('Noch keine historischen Messwerte',pad.l+10,h/2);return}
|
||||
const min=Math.min(...points.map(p=>p.ts)),max=Math.max(...points.map(p=>p.ts));
|
||||
@@ -143,8 +143,8 @@ function drawHistory(points){
|
||||
:span<=45*86400
|
||||
?date.toLocaleString('de-DE',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'})
|
||||
:date.toLocaleDateString('de-DE',{day:'2-digit',month:'2-digit',year:'2-digit'});
|
||||
x.strokeStyle='#172538';x.beginPath();x.moveTo(xx,pad.t);x.lineTo(xx,h-pad.b);x.stroke();
|
||||
x.fillStyle='#8fa1b5';x.textAlign=i===0?'left':i===ticks-1?'right':'center';x.fillText(label,xx,h-7);
|
||||
x.strokeStyle='#2b3532';x.beginPath();x.moveTo(xx,pad.t);x.lineTo(xx,h-pad.b);x.stroke();
|
||||
x.fillStyle='#97a79e';x.textAlign=i===0?'left':i===ticks-1?'right':'center';x.fillText(label,xx,h-7);
|
||||
}
|
||||
x.textAlign='start';
|
||||
const ids=[...new Set(points.map(p=>p.gpu_index))].sort();
|
||||
@@ -157,7 +157,7 @@ function drawSlotHistory(points){
|
||||
const canvas=$('slotHistoryChart'),rect=canvas.getBoundingClientRect(),ratio=window.devicePixelRatio||1;
|
||||
canvas.width=Math.max(1,Math.floor(rect.width*ratio));canvas.height=Math.max(1,Math.floor(rect.height*ratio));
|
||||
const x=canvas.getContext('2d');x.scale(ratio,ratio);const w=rect.width,h=rect.height,pad={l:42,r:18,t:16,b:28};
|
||||
x.clearRect(0,0,w,h);x.strokeStyle='#213044';x.fillStyle='#8fa1b5';x.font='11px system-ui';x.lineWidth=1;
|
||||
x.clearRect(0,0,w,h);x.strokeStyle='#303a37';x.fillStyle='#97a79e';x.font='11px system-ui';x.lineWidth=1;
|
||||
for(let i=0;i<=4;i++){let y=pad.t+(h-pad.t-pad.b)*i/4;x.beginPath();x.moveTo(pad.l,y);x.lineTo(w-pad.r,y);x.stroke();x.fillText(`${100-i*25}%`,4,y+4)}
|
||||
if(!points.length){x.fillText('Noch keine historischen Slot-Messwerte',pad.l+10,h/2);$('slotLegend').innerHTML='';return}
|
||||
const min=Math.min(...points.map(p=>p.ts)),max=Math.max(...points.map(p=>p.ts));
|
||||
@@ -166,7 +166,7 @@ function drawSlotHistory(points){
|
||||
for(let i=0;i<ticks;i++){
|
||||
const ts=min+span*i/(ticks-1),xx=px(ts),date=new Date(ts*1000);
|
||||
const label=span<=2*86400?date.toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit'}):span<=45*86400?date.toLocaleString('de-DE',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'}):date.toLocaleDateString('de-DE',{day:'2-digit',month:'2-digit',year:'2-digit'});
|
||||
x.strokeStyle='#172538';x.beginPath();x.moveTo(xx,pad.t);x.lineTo(xx,h-pad.b);x.stroke();x.fillStyle='#8fa1b5';x.textAlign=i===0?'left':i===ticks-1?'right':'center';x.fillText(label,xx,h-7);
|
||||
x.strokeStyle='#2b3532';x.beginPath();x.moveTo(xx,pad.t);x.lineTo(xx,h-pad.b);x.stroke();x.fillStyle='#97a79e';x.textAlign=i===0?'left':i===ticks-1?'right':'center';x.fillText(label,xx,h-7);
|
||||
}
|
||||
x.textAlign='start';const ids=[...new Set(points.map(p=>p.slot_id))].sort((a,b)=>a-b);
|
||||
$('slotLegend').innerHTML=ids.map((id,idx)=>{let color=historyColors[idx%historyColors.length],key=String(id);return `<button data-slot-series="${key}" class="${hiddenSlotSeries.has(key)?'off':''}" style="--series:${color}" aria-pressed="${hiddenSlotSeries.has(key)?'false':'true'}">Slot ${id} · Kontext</button>`}).join('');
|
||||
|
||||
+63
-11
@@ -1,11 +1,63 @@
|
||||
|
||||
:host{color-scheme:dark;--bg:#101416;--panel:#181f21;--panel2:#202a25;--line:#303a37;--text:#e9edea;--muted:#97a79e;--cyan:#c5edaf;--green:#bdeba4;--amber:#ffc65c;--red:#ff8c8c}
|
||||
*{box-sizing:border-box}.dashboard-root{margin:0;background:radial-gradient(circle at 15% -10%,#183049 0,transparent 35%),var(--bg);font:14px/1.45 Inter,ui-sans-serif,system-ui;color:var(--text)}main{max-width:1450px;margin:auto;padding:0}.top{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:20px}.eyebrow{color:var(--cyan);font-weight:700;letter-spacing:.14em;text-transform:uppercase;font-size:11px}h1{margin:3px 0 0;font-size:30px}.live{display:flex;align-items:center;gap:8px;color:var(--muted)}.dot{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 14px var(--green)}.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:14px}.card{background:linear-gradient(145deg,rgba(17,27,40,.96),rgba(10,16,24,.96));border:1px solid var(--line);border-radius:14px;padding:17px;min-width:0}.span3{grid-column:span 3}.span4{grid-column:span 4}.span6{grid-column:span 6}.span12{grid-column:span 12}.label{color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.08em}.value{font-size:26px;font-weight:750;margin-top:5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sub{color:var(--muted);margin-top:4px}.bar-label{display:flex;justify-content:space-between;color:var(--muted);font-size:11px;margin-top:13px}.bar{height:9px;background:#070b11;border-radius:99px;overflow:hidden;margin-top:5px}.fill{height:100%;width:0;background:linear-gradient(90deg,var(--cyan),var(--green));transition:width .5s}.fill.gpu-load{background:linear-gradient(90deg,#8b7cff,var(--cyan))}.gpu-title{display:flex;justify-content:space-between;align-items:center;gap:12px}.badge{border:1px solid var(--line);background:#07101a;color:var(--cyan);padding:4px 8px;border-radius:99px;font-size:11px}.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-top:16px}.metric b{display:block;font-size:18px}.metric span{color:var(--muted);font-size:11px}.status{color:var(--green)}.status.bad{color:var(--red)}table{border-collapse:collapse;width:100%;margin-top:10px}th,td{text-align:left;padding:8px;border-bottom:1px solid var(--line)}th{color:var(--muted);font-weight:500}.error{color:var(--red);white-space:pre-wrap}.footer{color:var(--muted);font-size:12px;text-align:right;margin-top:14px}@media(max-width:900px){.span3,.span4,.span6{grid-column:span 12}.metrics{grid-template-columns:repeat(2,1fr)}.top{align-items:flex-start;flex-direction:column}}
|
||||
.amber{color:var(--amber)}.section-title{grid-column:span 12;margin:10px 2px -3px;color:var(--cyan);font-size:12px;font-weight:750;letter-spacing:.13em;text-transform:uppercase}.slot-list{display:grid;gap:12px;margin-top:13px}.slot{border:1px solid var(--line);border-radius:11px;padding:13px;background:#141a1c}.slot-head,.row{display:flex;justify-content:space-between;align-items:center;gap:12px}.slot-head b{font-size:16px}.profiles{display:grid;grid-template-columns:repeat(2,1fr);gap:9px;margin-top:13px}.profile-item{border:1px solid var(--line);border-radius:10px;padding:10px}.profile-item.active{border-color:var(--cyan);box-shadow:inset 0 0 0 1px #c5edaf33}.profile-item b{display:block}.profile-item span{color:var(--muted);font-size:11px}.scroll{max-height:330px;overflow:auto}.scroll th{position:sticky;top:0;background:var(--panel)}.event{padding:8px 0;border-bottom:1px solid var(--line)}.event:last-child{border:0}.event time{color:var(--muted);font-size:11px;margin-right:8px}@media(max-width:900px){.profiles{grid-template-columns:1fr}}
|
||||
.span4 .metrics{grid-template-columns:repeat(2,1fr)}
|
||||
.history-controls{display:flex;flex-wrap:wrap;gap:7px;margin:10px 0 14px}.history-controls button{border:1px solid var(--line);background:#141a1c;color:var(--muted);padding:6px 10px;border-radius:8px;cursor:pointer}.history-controls button.active{color:var(--cyan);border-color:var(--cyan)}.chart-legend{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 10px}.chart-legend button{border:1px solid var(--series);background:#141a1c;color:var(--text);padding:6px 10px;border-radius:8px;cursor:pointer}.chart-legend button::before{content:'';display:inline-block;width:10px;height:3px;background:var(--series);margin:0 7px 3px 0}.chart-legend button.off{opacity:.4;text-decoration:line-through}.chart{width:100%;height:250px;display:block}.token-total{font-size:24px;font-weight:750;margin-top:5px}.history-note{color:var(--muted);font-size:11px;margin-top:8px}
|
||||
.usage-list{display:grid;gap:13px;margin-top:8px}.usage-head{display:flex;justify-content:space-between;gap:14px;align-items:baseline}.usage-head b{font-size:16px}.usage-head span{color:var(--muted)}.usage-meta{display:flex;justify-content:space-between;gap:12px;color:var(--muted);font-size:11px;margin-top:5px}
|
||||
.mode-row{display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap}.mode-buttons,.mode-buttons span{display:flex;gap:9px;flex-wrap:wrap}.mode-buttons button,.mode-buttons a{border:1px solid var(--line);background:#141a1c;color:var(--text);padding:9px 14px;border-radius:9px;cursor:pointer;text-decoration:none;font:inherit}.mode-buttons button.active{border-color:var(--cyan);color:var(--cyan);box-shadow:inset 0 0 0 1px #c5edaf33}.mode-buttons button:disabled{opacity:.45;cursor:wait}.mode-buttons span[hidden]{display:none}.mode-buttons a.stable{border-color:#66e3a466;color:var(--green)}.mode-buttons a.experimental{border-color:#ffc65c66;color:var(--amber)}.mode-error{color:var(--red)}
|
||||
.image-controls{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px;margin-top:12px}.image-controls .mode-buttons{margin-top:8px}@media(max-width:900px){.image-controls{grid-template-columns:1fr}}
|
||||
.download{display:inline-block;border:1px solid #66e3a466;color:var(--green);padding:6px 10px;border-radius:8px;text-decoration:none}.hash{font:11px ui-monospace,SFMono-Regular,monospace;color:var(--muted);word-break:break-all}
|
||||
|
||||
/* Native Deck dashboard: one DOM, one typography and surface system. */
|
||||
#deck-dashboard-host{--db-line:#303a37;--db-muted:#97a79e;--db-accent:#c5edaf;--db-danger:#e9aaa0;min-width:0;color:#e9edea}
|
||||
#deck-dashboard-host *{box-sizing:border-box}
|
||||
#deck-dashboard-host .top{display:flex;align-items:end;justify-content:space-between;gap:22px;margin-bottom:28px}
|
||||
#deck-dashboard-host .top h1{margin:12px 0 6px}
|
||||
#deck-dashboard-host .top p{margin:0}
|
||||
#deck-dashboard-host .live{display:flex;align-items:center;gap:9px;color:var(--db-muted);font-size:12px;white-space:nowrap}
|
||||
#deck-dashboard-host .dot{width:8px;height:8px;border-radius:50%;background:#bdeba4;box-shadow:0 0 0 4px #bdeba41c}
|
||||
#deck-dashboard-host .grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:18px;margin:0}
|
||||
#deck-dashboard-host .card{background:#181f21;border:1px solid var(--db-line);border-radius:13px;padding:24px;min-width:0}
|
||||
#deck-dashboard-host .span3{grid-column:span 3}#deck-dashboard-host .span4{grid-column:span 4}#deck-dashboard-host .span6{grid-column:span 6}#deck-dashboard-host .span12{grid-column:span 12}
|
||||
#deck-dashboard-host .label{color:#95a69b;font-size:11px;letter-spacing:1px;text-transform:uppercase}
|
||||
#deck-dashboard-host .value{font-size:27px;font-weight:550;letter-spacing:-.7px;margin:14px 0 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#e4f1de}
|
||||
#deck-dashboard-host .sub{font-size:12px;line-height:1.55;color:var(--db-muted);margin-top:5px}
|
||||
#deck-dashboard-host .section-title{grid-column:1/-1;color:#c5edaf;font-size:11px;letter-spacing:2px;text-transform:uppercase;margin:20px 0 -4px;padding-bottom:12px;border-bottom:1px solid var(--db-line)}
|
||||
#deck-dashboard-host .bar-label{display:flex;justify-content:space-between;gap:10px;color:var(--db-muted);font-size:11px;margin-top:15px}
|
||||
#deck-dashboard-host .bar{height:7px;background:#101718;border-radius:20px;overflow:hidden;margin-top:7px}
|
||||
#deck-dashboard-host .fill{height:100%;width:0;background:#bdeba4;transition:width .45s}
|
||||
#deck-dashboard-host .fill.gpu-load{background:#7fc8b6}
|
||||
#deck-dashboard-host .gpu-title,#deck-dashboard-host .row,#deck-dashboard-host .slot-head{display:flex;align-items:center;justify-content:space-between;gap:16px}
|
||||
#deck-dashboard-host .gpu-title .value{font-size:19px;white-space:normal;line-height:1.35}
|
||||
#deck-dashboard-host .badge{border:1px solid #3a493f;border-radius:20px;padding:5px 9px;color:#c5edaf;font-size:11px;white-space:nowrap}
|
||||
#deck-dashboard-host .metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-top:20px}
|
||||
#deck-dashboard-host .metric{min-width:0}
|
||||
#deck-dashboard-host .metric b{display:block;font-size:17px;font-weight:550;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
#deck-dashboard-host .metric span{display:block;color:var(--db-muted);font-size:11px;line-height:1.45;margin-top:4px}
|
||||
#deck-dashboard-host .span4 .metrics{grid-template-columns:repeat(2,minmax(0,1fr))}
|
||||
#deck-dashboard-host .status{color:#bdeba4}#deck-dashboard-host .status.bad,#deck-dashboard-host .error{color:var(--db-danger)}
|
||||
#deck-dashboard-host table{border-collapse:collapse;width:100%;margin-top:15px;font-size:12px}
|
||||
#deck-dashboard-host th,#deck-dashboard-host td{text-align:left;padding:11px 8px;border-bottom:1px solid var(--db-line);vertical-align:top}
|
||||
#deck-dashboard-host th{font-weight:500;color:var(--db-muted)}
|
||||
#deck-dashboard-host .scroll{max-height:330px;overflow:auto}
|
||||
#deck-dashboard-host .scroll th{position:sticky;top:0;background:#181f21}
|
||||
#deck-dashboard-host .slot-list,#deck-dashboard-host .usage-list{display:grid;gap:12px;margin-top:17px}
|
||||
#deck-dashboard-host .slot,#deck-dashboard-host .profile-item{background:#151b1c;border:1px solid var(--db-line);border-radius:10px;padding:16px}
|
||||
#deck-dashboard-host .slot-head b,#deck-dashboard-host .usage-head b{font-size:14px;font-weight:550}
|
||||
#deck-dashboard-host .profiles{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:15px}
|
||||
#deck-dashboard-host .profile-item.active{border-color:#9acb88}
|
||||
#deck-dashboard-host .profile-item b{display:block;font-weight:550}
|
||||
#deck-dashboard-host .profile-item span{color:var(--db-muted);font-size:11px}
|
||||
#deck-dashboard-host .event{padding:10px 0;border-bottom:1px solid var(--db-line)}
|
||||
#deck-dashboard-host .event:last-child{border:0}
|
||||
#deck-dashboard-host .event time{color:var(--db-muted);font-size:11px;margin-right:8px}
|
||||
#deck-dashboard-host .history-controls{display:flex;flex-wrap:wrap;gap:6px;margin:0}
|
||||
#deck-dashboard-host .history-controls button,#deck-dashboard-host .chart-legend button{border:1px solid #3a493f;background:#151b1c;color:#c5d2c9;border-radius:7px;padding:7px 11px;font:inherit;font-size:11px;cursor:pointer}
|
||||
#deck-dashboard-host .history-controls button:hover,#deck-dashboard-host .chart-legend button:hover{background:#253229}
|
||||
#deck-dashboard-host .history-controls button.active{background:#28362b;color:#d3efc5;border-color:#668659}
|
||||
#deck-dashboard-host .chart-legend{display:flex;flex-wrap:wrap;gap:7px;margin:17px 0 6px}
|
||||
#deck-dashboard-host .chart-legend button::before{content:'';display:inline-block;width:10px;height:3px;background:var(--series);margin:0 7px 3px 0}
|
||||
#deck-dashboard-host .chart-legend button.off{opacity:.45}
|
||||
#deck-dashboard-host .chart{display:block;width:100%;height:250px}
|
||||
#deck-dashboard-host .token-total{font-size:25px;font-weight:550;color:#e4f1de;margin-top:12px}
|
||||
#deck-dashboard-host .history-note{font-size:11px;color:var(--db-muted);margin-top:9px}
|
||||
#deck-dashboard-host .usage-head,#deck-dashboard-host .usage-meta{display:flex;align-items:baseline;justify-content:space-between;gap:14px}
|
||||
#deck-dashboard-host .usage-head span,#deck-dashboard-host .usage-meta{color:var(--db-muted)}
|
||||
#deck-dashboard-host .usage-meta{font-size:11px;margin-top:7px}
|
||||
#deck-dashboard-host .download{display:inline-block;border:1px solid #668659;color:#c5edaf;border-radius:7px;padding:6px 10px;text-decoration:none}
|
||||
#deck-dashboard-host .hash{font:11px ui-monospace,SFMono-Regular,monospace;color:var(--db-muted);word-break:break-all}
|
||||
#deck-dashboard-host .footer{font-size:11px;color:var(--db-muted);margin-top:22px;text-align:right}
|
||||
#deck-dashboard-host .error{white-space:pre-wrap}
|
||||
@media(max-width:1180px){#deck-dashboard-host .span3{grid-column:span 6}#deck-dashboard-host .span4{grid-column:span 6}#deck-dashboard-host .row{align-items:flex-start;flex-direction:column}}
|
||||
@media(max-width:800px){#deck-dashboard-host .span3,#deck-dashboard-host .span4,#deck-dashboard-host .span6{grid-column:span 12}#deck-dashboard-host .top{align-items:flex-start;flex-direction:column}#deck-dashboard-host .profiles{grid-template-columns:1fr}}
|
||||
@media(max-width:500px){#deck-dashboard-host .card{padding:18px}#deck-dashboard-host .metrics{grid-template-columns:repeat(2,minmax(0,1fr))}#deck-dashboard-host .gpu-title{align-items:flex-start;flex-direction:column}#deck-dashboard-host .usage-meta{flex-direction:column;gap:3px}}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Athena Deck</title><link rel="stylesheet" href="/style.css"><script src="/network-ui.js" defer></script><script src="/access-ui.js" defer></script><script src="/catalog-ui.js" defer></script><script src="/runtime-ui.js" defer></script><script src="/profiles-ui.js" defer></script><script src="/auto-test-ui.js" defer></script><script src="/chat-test-ui.js" defer></script><script src="/image-test-ui.js" defer></script><script src="/docker-ui.js" defer></script><script src="/stt-ui.js" defer></script><script src="/tts-ui.js" defer></script><script src="/studio.js" defer></script><script src="/video-ui.js" defer></script><script src="/endpoint-ui.js" defer></script><script src="/dashboard-ui.js" defer></script><script src="/app.js" defer></script></head><body><aside><a class="brand" href="#dashboard"><span>Α</span> ATHENA <b>DECK</b></a><p class="eyebrow">WORKSPACE / ATHENA</p><nav aria-label="Hauptnavigation"><a href="#dashboard">Dashboard <span>01</span></a><a href="#home">Übersicht <span>02</span></a><a href="#chat">Sprachmodelle / Chat <span>02</span></a><a href="#image">Bildgenerierung <span>03</span></a><p class="nav-heading">AUDIO</p><a class="nav-sub" href="#audio">Text-to-Speech (TTS)</a><a class="nav-sub" href="#stt">Spracherkennung (STT)</a><a class="nav-sub" href="#music">Musik</a><a class="nav-sub" href="#voice">Stimme / Voice</a><a href="#video">Video <span>05</span></a><a href="#services">Weitere Dienste <span>06</span></a><p class="nav-heading">EINSTELLUNGEN</p><a href="#runtimes">Laufzeiten <span>↗</span></a><a class="nav-sub" href="#runtime">llama.cpp</a><a class="nav-sub" href="#image-runtime">Bildgenerierung</a><a class="nav-sub" href="#stt-runtime">Spracherkennung</a><a class="nav-sub" href="#tts-runtime">Text-to-Speech</a><a class="nav-sub" href="#docker-runtime">Docker</a><a href="#endpoint">Endpunkt & Profile <span>↗</span></a><a href="#network">Netzwerk <span>↗</span></a><a href="#access">Zugang & API <span>↗</span></a></nav><footer><i></i> Isolierte Entwicklungsumgebung<p>Eigener Modell-Router<br>Hardware · nur lesend</p></footer></aside><main><header><span>ATHENA CONTROL SURFACE</span><span class="pill">v0.7 · Router</span></header><div id="view"></div><p id="error" role="alert"></p></main></body></html>
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Athena Deck</title><link rel="stylesheet" href="/style.css"><link rel="stylesheet" href="/dashboard.css"><script src="/network-ui.js" defer></script><script src="/access-ui.js" defer></script><script src="/catalog-ui.js" defer></script><script src="/runtime-ui.js" defer></script><script src="/profiles-ui.js" defer></script><script src="/auto-test-ui.js" defer></script><script src="/chat-test-ui.js" defer></script><script src="/image-test-ui.js" defer></script><script src="/docker-ui.js" defer></script><script src="/stt-ui.js" defer></script><script src="/tts-ui.js" defer></script><script src="/studio.js" defer></script><script src="/video-ui.js" defer></script><script src="/endpoint-ui.js" defer></script><script src="/dashboard-ui.js" defer></script><script src="/app.js" defer></script></head><body><aside><a class="brand" href="#dashboard"><span>Α</span> ATHENA <b>DECK</b></a><p class="eyebrow">WORKSPACE / ATHENA</p><nav aria-label="Hauptnavigation"><a href="#dashboard">Dashboard <span>01</span></a><a href="#home">Übersicht <span>02</span></a><a href="#chat">Sprachmodelle / Chat <span>02</span></a><a href="#image">Bildgenerierung <span>03</span></a><p class="nav-heading">AUDIO</p><a class="nav-sub" href="#audio">Text-to-Speech (TTS)</a><a class="nav-sub" href="#stt">Spracherkennung (STT)</a><a class="nav-sub" href="#music">Musik</a><a class="nav-sub" href="#voice">Stimme / Voice</a><a href="#video">Video <span>05</span></a><a href="#services">Weitere Dienste <span>06</span></a><p class="nav-heading">EINSTELLUNGEN</p><a href="#runtimes">Laufzeiten <span>↗</span></a><a class="nav-sub" href="#runtime">llama.cpp</a><a class="nav-sub" href="#image-runtime">Bildgenerierung</a><a class="nav-sub" href="#stt-runtime">Spracherkennung</a><a class="nav-sub" href="#tts-runtime">Text-to-Speech</a><a class="nav-sub" href="#docker-runtime">Docker</a><a href="#endpoint">Endpunkt & Profile <span>↗</span></a><a href="#network">Netzwerk <span>↗</span></a><a href="#access">Zugang & API <span>↗</span></a></nav><footer><i></i> Isolierte Entwicklungsumgebung<p>Eigener Modell-Router<br>Hardware · nur lesend</p></footer></aside><main><header><span>ATHENA CONTROL SURFACE</span><span class="pill">v0.7 · Router</span></header><div id="view"></div><p id="error" role="alert"></p></main></body></html>
|
||||
|
||||
Reference in New Issue
Block a user