Add a per-project "Hide seen" checkbox to the control board page (#1503)
Each project table now has "Hide seen" beside "Hide offline", both on by default, with a note saying how many rows each one hides. The choice survives the 10-second refresh. Static test pins the markup, the filter, the persistence guard, and the change handler. Sonnet review: APPROVED. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
@@ -69,6 +69,7 @@
|
||||
.detail-list dd{margin:0;overflow-wrap:anywhere}
|
||||
.project-group{margin-bottom:20px}
|
||||
.project-group-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}
|
||||
.group-toggles{display:flex;flex-wrap:wrap;gap:14px}
|
||||
.project-group-head label{font-size:.85rem;color:var(--muted);display:flex;align-items:center;gap:6px}
|
||||
.offline-note{margin:6px 0 0;font-size:.82rem;color:var(--muted)}
|
||||
.page-footer{margin-top:24px;padding-top:12px;border-top:1px solid var(--line);color:var(--muted);font-size:.85rem}
|
||||
@@ -125,6 +126,7 @@
|
||||
var timerId = null;
|
||||
var secondsLeft = REFRESH_MS / 1000;
|
||||
var hideOfflineState = {};
|
||||
var hideSeenState = {};
|
||||
// Open detail panels survive a refresh. Keyed by section, project and agent
|
||||
// because the same agent can appear in both the waiting list and its group.
|
||||
var openDetails = {};
|
||||
@@ -279,16 +281,27 @@
|
||||
projectsBody.innerHTML = projects.map(function (project) {
|
||||
var group = byProject[project].slice().sort(function (a, b) { return a.agent.localeCompare(b.agent); });
|
||||
if (!(project in hideOfflineState)) hideOfflineState[project] = true;
|
||||
if (!(project in hideSeenState)) hideSeenState[project] = true;
|
||||
var hideOffline = hideOfflineState[project];
|
||||
var visible = group.filter(function (r) { return !(hideOffline && r.state === "offline"); });
|
||||
var hiddenCount = group.length - visible.length;
|
||||
var hideSeen = hideSeenState[project];
|
||||
var offlineHidden = 0, seenHidden = 0;
|
||||
var visible = group.filter(function (r) {
|
||||
if (hideOffline && r.state === "offline") { offlineHidden += 1; return false; }
|
||||
if (hideSeen && r.seen) { seenHidden += 1; return false; }
|
||||
return true;
|
||||
});
|
||||
var rows = visible.map(function (r) { return buildRowPair(r, false); }).join("");
|
||||
var note = hiddenCount > 0 ? '<p class="offline-note">' + hiddenCount + " offline hidden</p>" : "";
|
||||
var noteParts = [];
|
||||
if (offlineHidden > 0) noteParts.push(offlineHidden + " offline hidden");
|
||||
if (seenHidden > 0) noteParts.push(seenHidden + " seen hidden");
|
||||
var note = noteParts.length > 0 ? '<p class="offline-note">' + noteParts.join(" \u00b7 ") + "</p>" : "";
|
||||
return (
|
||||
'<div class="project-group">' +
|
||||
'<div class="project-group-head"><h3>' + esc(project) + ' <span>(' + group.length + ")</span></h3>" +
|
||||
'<div class="group-toggles">' +
|
||||
'<label><input type="checkbox" class="hide-offline-toggle" data-project="' + esc(project) + '" ' + (hideOffline ? "checked" : "") + "> Hide offline</label>" +
|
||||
"</div>" +
|
||||
'<label><input type="checkbox" class="hide-seen-toggle" data-project="' + esc(project) + '" ' + (hideSeen ? "checked" : "") + "> Hide seen</label>" +
|
||||
"</div></div>" +
|
||||
'<div class="table-wrap"><table><thead><tr>' +
|
||||
"<th scope=\"col\">Agent</th><th scope=\"col\">State</th><th scope=\"col\">Age</th><th scope=\"col\">Last message</th>" +
|
||||
"</tr></thead><tbody>" + (rows || '<tr><td colspan="4" class="empty">No agents.</td></tr>') + "</tbody></table></div>" +
|
||||
@@ -297,6 +310,7 @@
|
||||
}).join("");
|
||||
}
|
||||
|
||||
|
||||
function renderFooter(data) {
|
||||
var counts = data.counts || {};
|
||||
var parts = STATES.map(function (s) { return cap(s) + " " + (counts[s] || 0); }).join(" · ");
|
||||
@@ -420,9 +434,10 @@
|
||||
});
|
||||
|
||||
main.addEventListener("change", function (e) {
|
||||
var cb = e.target.closest(".hide-offline-toggle");
|
||||
var cb = e.target.closest(".hide-offline-toggle, .hide-seen-toggle");
|
||||
if (!cb) return;
|
||||
hideOfflineState[cb.dataset.project] = cb.checked;
|
||||
var stateMap = cb.classList.contains("hide-seen-toggle") ? hideSeenState : hideOfflineState;
|
||||
stateMap[cb.dataset.project] = cb.checked;
|
||||
renderProjects(lastData);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user