lvwerra HF Staff Claude Opus 4.8 (1M context) commited on
Commit
80cde8b
·
1 Parent(s): 9c88db3

Add default-on toggle to hide empty collabs

Browse files

Collabs with no agents and no messages are hidden by default via a
checkbox above the directory table, with an "N empty hidden" note. The
filter is bypassed while stats are still loading so skeleton rows show.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files changed (1) hide show
  1. index.html +40 -1
index.html CHANGED
@@ -40,6 +40,14 @@
40
  .btn:hover { border-color: var(--muted-3); color: var(--ink); }
41
  .btn:disabled { opacity: 0.6; cursor: wait; }
42
 
 
 
 
 
 
 
 
 
43
  /* --- Table --- */
44
  .tbl { border: 1px solid var(--border); background: #fff; margin-top: 20px; overflow-x: auto; }
45
  .row, .thead {
@@ -184,6 +192,10 @@
184
  </div>
185
 
186
  <div class="tabpane" id="tab-directory">
 
 
 
 
187
  <div class="tbl" id="tbl">
188
  <div class="thead">
189
  <div class="h nosort"></div>
@@ -288,6 +300,13 @@ const rowsEl = document.getElementById("rows");
288
  const stateEl = document.getElementById("state");
289
  let ROWS = []; // [{space, st}]
290
  let sort = { col: "last", dir: -1 }; // default: most recently active first
 
 
 
 
 
 
 
291
 
292
  function rel(iso) {
293
  if (!iso) return "·";
@@ -369,7 +388,19 @@ function renderRows() {
369
  h.querySelector(".arr").textContent = active ? (sort.dir < 0 ? "▼" : "▲") : "";
370
  });
371
 
372
- rowsEl.innerHTML = sorted.map(r => {
 
 
 
 
 
 
 
 
 
 
 
 
373
  const sp = r.space, st = r.st, cd = sp.cardData || {};
374
  const title = cd.title || sp.id.split("/")[1];
375
  const desc = cd.short_description || cd.description || "";
@@ -450,8 +481,14 @@ document.querySelectorAll(".thead .h[data-sort]").forEach(h => {
450
  });
451
  });
452
 
 
 
 
 
 
453
  async function load() {
454
  const btn = document.getElementById("refresh");
 
455
  btn.disabled = true; btn.textContent = "↻ Loading…";
456
  rowsEl.innerHTML = ""; stateEl.style.display = ""; stateEl.className = "state"; stateEl.textContent = "Discovering agent collabs…";
457
  try {
@@ -469,6 +506,7 @@ async function load() {
469
  if (r.st.agents) totA += r.st.agents;
470
  if (r.st.messages) totM += r.st.messages;
471
  }));
 
472
  renderRows();
473
  finishSummary(spaces.length, totA, totM);
474
  if (new URLSearchParams(location.search).get("expand") === "1") {
@@ -477,6 +515,7 @@ async function load() {
477
  } catch (e) {
478
  stateEl.className = "state err"; stateEl.textContent = "Failed to load: " + e.message;
479
  } finally {
 
480
  btn.disabled = false; btn.textContent = "↻ Refresh";
481
  }
482
  }
 
40
  .btn:hover { border-color: var(--muted-3); color: var(--ink); }
41
  .btn:disabled { opacity: 0.6; cursor: wait; }
42
 
43
+ /* --- Filter bar --- */
44
+ .filterbar { display: flex; align-items: center; gap: 12px; margin-top: 20px; font-family: "JetBrains Mono", monospace; }
45
+ .toggle { display: inline-flex; align-items: center; gap: 7px; font-size: 10px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; color: var(--muted); cursor: pointer; user-select: none; }
46
+ .toggle:hover { color: var(--ink); }
47
+ .toggle input { width: 13px; height: 13px; cursor: pointer; accent-color: var(--accent); margin: 0; }
48
+ .filter-note { font-size: 10px; letter-spacing: 0.4px; color: var(--muted-4); font-variant-numeric: tabular-nums; }
49
+ .empty-note { padding: 30px 16px; text-align: center; font-family: "JetBrains Mono", monospace; font-size: 11px; color: var(--muted-3); line-height: 1.7; }
50
+
51
  /* --- Table --- */
52
  .tbl { border: 1px solid var(--border); background: #fff; margin-top: 20px; overflow-x: auto; }
53
  .row, .thead {
 
192
  </div>
193
 
194
  <div class="tabpane" id="tab-directory">
195
+ <div class="filterbar">
196
+ <label class="toggle"><input type="checkbox" id="hideEmpty" checked><span>Hide empty collabs</span></label>
197
+ <span class="filter-note" id="hiddenNote"></span>
198
+ </div>
199
  <div class="tbl" id="tbl">
200
  <div class="thead">
201
  <div class="h nosort"></div>
 
300
  const stateEl = document.getElementById("state");
301
  let ROWS = []; // [{space, st}]
302
  let sort = { col: "last", dir: -1 }; // default: most recently active first
303
+ let hideEmpty = true; // default on: hide collabs with no agents and no messages
304
+ let loading = false; // while true, skip the empty filter so skeleton rows show
305
+
306
+ function rowIsEmpty(r) { // empty = no agents and no messages (null/0 both count as none)
307
+ const st = r.st || {};
308
+ return !(st.agents || st.messages);
309
+ }
310
 
311
  function rel(iso) {
312
  if (!iso) return "·";
 
388
  h.querySelector(".arr").textContent = active ? (sort.dir < 0 ? "▼" : "▲") : "";
389
  });
390
 
391
+ // hide empties (skipped during load so skeleton rows still appear while stats stream in)
392
+ const applyFilter = hideEmpty && !loading;
393
+ const filtered = applyFilter ? sorted.filter(r => !rowIsEmpty(r)) : sorted;
394
+ const hidden = ROWS.length - filtered.length;
395
+ const noteEl = document.getElementById("hiddenNote");
396
+ if (noteEl) noteEl.textContent = applyFilter && hidden > 0 ? `${hidden} empty hidden` : "";
397
+
398
+ if (applyFilter && filtered.length === 0 && ROWS.length > 0) {
399
+ rowsEl.innerHTML = `<div class="empty-note">All ${ROWS.length} discovered collabs are empty (no agents or messages).<br>Turn off “Hide empty collabs” to show them.</div>`;
400
+ return;
401
+ }
402
+
403
+ rowsEl.innerHTML = filtered.map(r => {
404
  const sp = r.space, st = r.st, cd = sp.cardData || {};
405
  const title = cd.title || sp.id.split("/")[1];
406
  const desc = cd.short_description || cd.description || "";
 
481
  });
482
  });
483
 
484
+ document.getElementById("hideEmpty").addEventListener("change", function () {
485
+ hideEmpty = this.checked;
486
+ renderRows();
487
+ });
488
+
489
  async function load() {
490
  const btn = document.getElementById("refresh");
491
+ loading = true;
492
  btn.disabled = true; btn.textContent = "↻ Loading…";
493
  rowsEl.innerHTML = ""; stateEl.style.display = ""; stateEl.className = "state"; stateEl.textContent = "Discovering agent collabs…";
494
  try {
 
506
  if (r.st.agents) totA += r.st.agents;
507
  if (r.st.messages) totM += r.st.messages;
508
  }));
509
+ loading = false;
510
  renderRows();
511
  finishSummary(spaces.length, totA, totM);
512
  if (new URLSearchParams(location.search).get("expand") === "1") {
 
515
  } catch (e) {
516
  stateEl.className = "state err"; stateEl.textContent = "Failed to load: " + e.message;
517
  } finally {
518
+ loading = false;
519
  btn.disabled = false; btn.textContent = "↻ Refresh";
520
  }
521
  }