← back to AbramsEgo
fix: Kamatera fleet list — sort+density+infinite scroll, no silent 40-row cap
d83163b34f6ae1600824feeceb87586056cb07e3 · 2026-07-01 13:50:56 -0700 · Steve
Files touched
Diff
commit d83163b34f6ae1600824feeceb87586056cb07e3
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 1 13:50:56 2026 -0700
fix: Kamatera fleet list — sort+density+infinite scroll, no silent 40-row cap
---
public/index.html | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/public/index.html b/public/index.html
index 678c07b..e8d2703 100644
--- a/public/index.html
+++ b/public/index.html
@@ -139,6 +139,7 @@
<section class="card span4">
<h2>🛰 Fleet · Kamatera</h2>
<div class="big" id="kam-up">—</div>
+ <div id="kam-ctl"></div>
<div class="list" id="kam-list" style="margin-top:8px"></div>
</section>
<section class="card span4">
@@ -337,7 +338,7 @@ async function load(){
// ---- fleet ----
const k=d.kamatera||{}, l=d.localFleet||{};
$('kam-up').innerHTML=`<span class="${cls(100-(k.up/(k.total||1)*100),20,50)}">${k.up??'—'}</span><span class="dim" style="font-size:16px">/${k.total??'—'} up</span>`;
- $('kam-list').innerHTML=(k.procs||[]).slice(0,40).map(pr=>lrow(`${statusDot(pr.status)}${esc(pr.name)}`,`${pr.restarts??''}↺`,whenChip(pr.startedAt))).join('')|| (k.note?`<span class="muted">${esc(k.note)}</span>`:'');
+ renderKamFleet(k);
$('loc-up').innerHTML=`<span class="good">${l.up??'—'}</span><span class="dim" style="font-size:16px">/${l.total??'—'} up</span>`;
$('loc-list').innerHTML=(l.procs||[]).map(pr=>lrow(`${statusDot(pr.status)}${esc(pr.name)}`,`${pr.memMB!=null?pr.memMB+'M':''}`,whenChip(pr.startedAt))).join('')||'<span class="muted">no local pm2 procs</span>';
@@ -558,6 +559,26 @@ function renderCanaries(cans){
});
feedGrid('canaries', cans);
}
+// Kamatera fleet — 226 live procs; grid (sort + density + infinite scroll)
+// replaces the old silent slice(0,40) cap. Same lrow render, 🕓 chip kept.
+function renderKamFleet(k){
+ const srank=(pr)=> pr.status==='online'?1:0; // offline first
+ initGrid('kamfleet',{
+ controlsHost:$('kam-ctl'), host:$('kam-list'), batch:25, minCols:1, maxCols:3, defaultCols:1,
+ empty:(k.note||'kamatera unreachable'),
+ sortModes:[
+ {k:'new', label:'Newest', cmp:(a,b)=>tsOf(b.startedAt)-tsOf(a.startedAt)},
+ {k:'old', label:'Oldest', cmp:(a,b)=>tsOf(a.startedAt)-tsOf(b.startedAt)},
+ {k:'name', label:'Name A→Z', cmp:(a,b)=>(a.name||'').localeCompare(b.name||'')},
+ {k:'restarts',label:'Restarts ↓', cmp:(a,b)=>(b.restarts||0)-(a.restarts||0)},
+ {k:'status', label:'Status', cmp:(a,b)=>srank(a)-srank(b)||(a.name||'').localeCompare(b.name||'')},
+ ],
+ render:(pr)=>lrow(`${statusDot(pr.status)}${esc(pr.name)}`,`${pr.restarts??''}↺`,whenChip(pr.startedAt)),
+ });
+ // empty text can change per snapshot (unreachable note vs default)
+ GRIDS['kamfleet'].cfg.empty=(k.note||'kamatera unreachable');
+ feedGrid('kamfleet', k.procs||[]);
+}
function statusDot(st){const c=st==='online'?'var(--good)':st?'var(--bad)':'var(--dim)';return `<span class="dot" style="background:${c}"></span>`;}
function fmtDur(s){if(s==null)return null;if(s<60)return s+'s';if(s<3600)return Math.floor(s/60)+'m';return Math.floor(s/3600)+'h';}
function esc(x){return (x==null?'':String(x)).replace(/[<>&]/g,m=>({'<':'<','>':'>','&':'&'}[m]));}
← 060582a chore: replenish audit (fable) — 1 real gap: kam fleet list
·
back to AbramsEgo
·
chore: mark task 15 done (Kamatera fleet grid controls lande d3f2f9c →