aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2026-04-22 12:16:32 +0200
committerGitHub Enterprise <[email protected]>2026-04-22 12:16:32 +0200
commita2c036bcd43b7348e916af6d074b3d7be93bd58c (patch)
tree1629779b9ce7bc6d6472468efb08c47c9873d4af
parenthub provision acceptable states (#1008) (diff)
downloadarchived-zen-a2c036bcd43b7348e916af6d074b3d7be93bd58c.tar.xz
archived-zen-a2c036bcd43b7348e916af6d074b3d7be93bd58c.zip
dashboard prominent version (#1009)
- Improvement: Dashboard banner displays the zenserver version next to the wordmark
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/zenserver/frontend/html/banner.js28
-rw-r--r--src/zenserver/frontend/html/pages/page.js5
3 files changed, 32 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e7f8fb2d4..89a60eedd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
- `download`: default to `<local-path>/.zen` (no change)
- Bugfix: `zen builds ls` no longer fails against cloud build storage (`--host`/`--url`) when `--storage-path` is not supplied
+- Improvement: Dashboard banner displays the zenserver version next to the wordmark
- Bugfix: `NamedEvent` construction on Linux/macOS no longer races against a concurrent destructor's `unlink()` of the backing file; the IPC key is now derived via `fstat()` on the open fd instead of `ftok()` re-stat'ing the path
- Bugfix: Hub provision requests now return 202 Accepted when the module is `Recovering` or `Waking` instead of rejecting
diff --git a/src/zenserver/frontend/html/banner.js b/src/zenserver/frontend/html/banner.js
index 01679e621..5b54f6fb9 100644
--- a/src/zenserver/frontend/html/banner.js
+++ b/src/zenserver/frontend/html/banner.js
@@ -14,12 +14,14 @@
* load 0–100 integer, shown as a percentage (default: hidden)
* tagline custom tagline text (default: "Orchestrator Overview" / "Orchestrator")
* subtitle text after "ZEN" in the wordmark (default: "COMPUTE")
+ * logo-src URL for the logo image (default: inline SVG)
+ * version version string shown next to the wordmark (default: hidden)
*/
class ZenBanner extends HTMLElement {
static get observedAttributes() {
- return ['variant', 'cluster-status', 'load', 'tagline', 'subtitle', 'logo-src'];
+ return ['variant', 'cluster-status', 'load', 'tagline', 'subtitle', 'logo-src', 'version'];
}
attributeChangedCallback() {
@@ -41,6 +43,7 @@ class ZenBanner extends HTMLElement {
get _tagline() { return this.getAttribute('tagline'); } // null → default
get _subtitle() { return this.getAttribute('subtitle'); } // null → "COMPUTE"
get _logoSrc() { return this.getAttribute('logo-src'); } // null → inline SVG
+ get _version() { return this.getAttribute('version'); } // null → hidden
get _statusColor() {
return { nominal: '#7ecfb8', degraded: '#d4a84b', offline: '#c0504d' }[this._status] ?? '#7ecfb8';
@@ -82,6 +85,7 @@ class ZenBanner extends HTMLElement {
const divH = compact ? '32px' : '48px';
const nameSize = compact ? '15px' : '22px';
const tagSize = compact ? '9px' : '11px';
+ const verSize = compact ? '11px' : '15px';
const sc = this._statusColor;
const lc = this._loadColor;
@@ -159,6 +163,12 @@ class ZenBanner extends HTMLElement {
gap: 4px;
}
+ .wordmark-row {
+ display: flex;
+ align-items: baseline;
+ gap: 10px;
+ }
+
.wordmark {
font-weight: 700;
font-size: ${nameSize};
@@ -170,6 +180,14 @@ class ZenBanner extends HTMLElement {
.wordmark span { color: #7ecfb8; }
+ .version {
+ font-weight: 700;
+ font-size: ${verSize};
+ letter-spacing: 0.08em;
+ line-height: 1;
+ color: var(--theme_bright, #e8e4dc);
+ }
+
.tagline {
font-family: 'Noto Serif JP', serif;
font-weight: 300;
@@ -290,12 +308,18 @@ class ZenBanner extends HTMLElement {
</div>
` : '';
+ const version = this._version;
+ const versionEl = version ? `<div class="version">v${version}</div>` : '';
+
return `
<a class="banner" part="banner" href="/dashboard/">
<div class="logo-mark">${this._logoMark()}</div>
<div class="divider"></div>
<div class="text-block">
- <div class="wordmark">ZEN<span> ${this._subtitle ?? 'COMPUTE'}</span></div>
+ <div class="wordmark-row">
+ <div class="wordmark">ZEN<span> ${this._subtitle ?? 'COMPUTE'}</span></div>
+ ${versionEl}
+ </div>
<div class="tagline">${this._tagline ?? (compact ? 'Orchestrator' : 'Orchestrator Overview')}</div>
</div>
<div class="spacer"></div>
diff --git a/src/zenserver/frontend/html/pages/page.js b/src/zenserver/frontend/html/pages/page.js
index 3653abb0e..d3069f506 100644
--- a/src/zenserver/frontend/html/pages/page.js
+++ b/src/zenserver/frontend/html/pages/page.js
@@ -99,6 +99,11 @@ export class ZenPage extends PageBase
this._banner = banner;
this._poll_status();
+
+ new Fetcher().resource("/health/version").text().then((data) => {
+ const v = data ? data.trim() : "";
+ if (v) banner.attr("version", v);
+ }).catch(() => {});
}
static _mode_taglines = {