diff options
| author | Stefan Boberg <[email protected]> | 2026-04-11 13:37:19 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-04-11 13:37:19 +0200 |
| commit | b481ba4cb40e8c8e1781d1fa74b2fc5c89564a0f (patch) | |
| tree | 21860bcdc05665e2a9b2ef50b911156cbc0fe4db /src/zenserver/frontend/html/pages/hub.js | |
| parent | Separate action and worker chunk stores for compute service (diff) | |
| parent | hub deprovision all (#938) (diff) | |
| download | zen-sb/memory-cid-store.tar.xz zen-sb/memory-cid-store.zip | |
Merge branch 'main' into sb/memory-cid-storesb/memory-cid-store
Diffstat (limited to 'src/zenserver/frontend/html/pages/hub.js')
| -rw-r--r-- | src/zenserver/frontend/html/pages/hub.js | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/src/zenserver/frontend/html/pages/hub.js b/src/zenserver/frontend/html/pages/hub.js index 7ae1deb5c..3cbfe6092 100644 --- a/src/zenserver/frontend/html/pages/hub.js +++ b/src/zenserver/frontend/html/pages/hub.js @@ -6,6 +6,7 @@ import { ZenPage } from "./page.js" import { Fetcher } from "../util/fetcher.js" import { Friendly } from "../util/friendly.js" import { Modal } from "../util/modal.js" +import { flash_highlight } from "../util/widgets.js" //////////////////////////////////////////////////////////////////////////////// const STABLE_STATES = new Set(["provisioned", "hibernated", "crashed"]); @@ -159,8 +160,36 @@ export class Page extends ZenPage this._btn_next.addEventListener("click", () => this._go_page(this._page + 1)); this._btn_provision = _make_bulk_btn("+", "Provision", () => this._show_provision_modal()); this._btn_obliterate = _make_bulk_btn("\uD83D\uDD25", "Obliterate", () => this._show_obliterate_modal()); + this._search_input = document.createElement("input"); + this._search_input.type = "text"; + this._search_input.className = "module-pager-search"; + this._search_input.placeholder = "Search module\u2026"; + this._search_input.addEventListener("keydown", (e) => + { + if (e.key === "Enter") + { + const term = this._search_input.value.trim().toLowerCase(); + if (!term) { return; } + const idx = this._modules_data.findIndex(m => + (m.moduleId || "").toLowerCase().includes(term) + ); + if (idx >= 0) + { + const id = this._modules_data[idx].moduleId; + this._navigate_to_module(id); + this._flash_module(id); + } + else + { + this._search_input.style.outline = "2px solid var(--theme_fail)"; + setTimeout(() => { this._search_input.style.outline = ""; }, 1000); + } + } + }); + pager.appendChild(this._btn_provision); pager.appendChild(this._btn_obliterate); + pager.appendChild(this._search_input); pager.appendChild(this._btn_prev); pager.appendChild(this._pager_label); pager.appendChild(this._btn_next); @@ -173,8 +202,11 @@ export class Page extends ZenPage this._row_cache = new Map(); // moduleId → row refs, for in-place DOM updates this._updating = false; this._page = 0; - this._page_size = 50; + this._page_size = 25; this._expanded = new Set(); // moduleIds with open metrics panel + this._pending_highlight = null; // moduleId to navigate+flash after next poll + this._pending_highlight_timer = null; + this._loading = mod_section.tag().classify("pager-loading").text("Loading\u2026").inner(); await this._update(); this._poll_timer = setInterval(() => this._update(), 2000); @@ -193,6 +225,15 @@ export class Page extends ZenPage this._render_capacity(stats); this._render_modules(status); + if (this._loading) { this._loading.remove(); this._loading = null; } + if (this._pending_highlight && this._module_map.has(this._pending_highlight)) + { + const id = this._pending_highlight; + this._pending_highlight = null; + clearTimeout(this._pending_highlight_timer); + this._navigate_to_module(id); + this._flash_module(id); + } } catch (e) { /* service unavailable */ } finally { this._updating = false; } @@ -844,14 +885,19 @@ export class Page extends ZenPage submit_label: "Provision", on_submit: async (moduleId) => { const resp = await fetch(`/hub/modules/${encodeURIComponent(moduleId)}/provision`, { method: "POST" }); - if (resp.ok) + if (!resp.ok) { - this._navigate_to_module(moduleId); - return true; + const msg = await resp.text(); + error_div.textContent = msg || ("HTTP " + resp.status); + return false; } - const msg = await resp.text(); - error_div.textContent = msg || ("HTTP " + resp.status); - return false; + // Endpoint returns compact binary (CbObjectWriter), not text + if (resp.status === 200 || resp.status === 202) + { + this._pending_highlight = moduleId; + this._pending_highlight_timer = setTimeout(() => { this._pending_highlight = null; }, 5000); + } + return true; } }); } @@ -885,4 +931,10 @@ export class Page extends ZenPage } } + _flash_module(id) + { + const cached = this._row_cache.get(id); + if (cached) { flash_highlight(cached.tr); } + } + } |