agent icon: render on dashboard + per-agent web UI
Consumes the GET /icon endpoint from #139: - Dashboard: each container card shows the agent's icon next to its name (26px). Loaded from <agent-url>/icon; onerror hides it for a stopped container whose web server isn't answering. - Per-agent web UI: the agent's icon next to the page title (40px), and /icon as the favicon on the index, stats, and screen pages. /icon always returns an image (configured SVG or the default hyperhive logo), so no presence check is needed. Closes #140
This commit is contained in:
parent
39bd46b244
commit
62aa3bb3ec
6 changed files with 32 additions and 1 deletions
|
|
@ -36,6 +36,18 @@ h2, h3 {
|
||||||
letter-spacing: 0.15em;
|
letter-spacing: 0.15em;
|
||||||
text-shadow: 0 0 8px rgba(203, 166, 247, 0.4);
|
text-shadow: 0 0 8px rgba(203, 166, 247, 0.4);
|
||||||
}
|
}
|
||||||
|
.title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
}
|
||||||
|
.title-row h2 { margin: 0; }
|
||||||
|
.agent-icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
.meta { color: var(--muted); font-size: 0.85em; }
|
.meta { color: var(--muted); font-size: 0.85em; }
|
||||||
.status-online { color: var(--green); text-shadow: 0 0 6px rgba(166, 227, 161, 0.55); }
|
.status-online { color: var(--green); text-shadow: 0 0 6px rgba(166, 227, 161, 0.55); }
|
||||||
.status-needs-login { color: var(--amber); text-shadow: 0 0 6px rgba(250, 179, 135, 0.55); }
|
.status-needs-login { color: var(--amber); text-shadow: 0 0 6px rgba(250, 179, 135, 0.55); }
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,15 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>hyperhive agent</title>
|
<title>hyperhive agent</title>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/icon">
|
||||||
<link rel="stylesheet" href="/static/agent.css">
|
<link rel="stylesheet" href="/static/agent.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<pre class="banner" id="banner">░▒▓█▓▒░ … ░▒▓█▓▒░ hyperhive ag3nt ░▒▓█▓▒░</pre>
|
<pre class="banner" id="banner">░▒▓█▓▒░ … ░▒▓█▓▒░ hyperhive ag3nt ░▒▓█▓▒░</pre>
|
||||||
|
<div class="title-row">
|
||||||
|
<img class="agent-icon" src="/icon" alt="">
|
||||||
<h2 id="title">◆ … ◆</h2>
|
<h2 id="title">◆ … ◆</h2>
|
||||||
|
</div>
|
||||||
<p class="meta">
|
<p class="meta">
|
||||||
<a href="/stats" style="color: var(--cyan); text-decoration: none;">📊 stats →</a>
|
<a href="/stats" style="color: var(--cyan); text-decoration: none;">📊 stats →</a>
|
||||||
<a id="screen-link" href="/screen" target="_blank" rel="noopener"
|
<a id="screen-link" href="/screen" target="_blank" rel="noopener"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>screen</title>
|
<title>screen</title>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/icon">
|
||||||
<style>
|
<style>
|
||||||
/* Catppuccin Mocha palette (mirrors base.css) */
|
/* Catppuccin Mocha palette (mirrors base.css) */
|
||||||
:root {
|
:root {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>hyperhive agent — stats</title>
|
<title>hyperhive agent — stats</title>
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/icon">
|
||||||
<link rel="stylesheet" href="/static/agent.css">
|
<link rel="stylesheet" href="/static/agent.css">
|
||||||
<style>
|
<style>
|
||||||
.stats-nav { display: flex; gap: 0.75rem; align-items: baseline; margin-bottom: 0.5rem; }
|
.stats-nav { display: flex; gap: 0.75rem; align-items: baseline; margin-bottom: 0.5rem; }
|
||||||
|
|
|
||||||
|
|
@ -517,6 +517,13 @@
|
||||||
// ── line 1: identity ─────────────────────────────────────────
|
// ── line 1: identity ─────────────────────────────────────────
|
||||||
const head = el('div', { class: 'head' });
|
const head = el('div', { class: 'head' });
|
||||||
head.append(
|
head.append(
|
||||||
|
// /icon always returns an image (the agent's configured SVG or
|
||||||
|
// the default hyperhive logo). onerror hides it for a stopped
|
||||||
|
// container whose web server isn't answering.
|
||||||
|
el('img', {
|
||||||
|
class: 'container-icon', src: url + 'icon', alt: '', loading: 'lazy',
|
||||||
|
onerror: "this.style.display='none'",
|
||||||
|
}),
|
||||||
el('a', { class: 'name', href: url, target: '_blank', rel: 'noopener' }, c.name),
|
el('a', { class: 'name', href: url, target: '_blank', rel: 'noopener' }, c.name),
|
||||||
el('span', { class: c.is_manager ? 'role role-m1nd' : 'role role-ag3nt' },
|
el('span', { class: c.is_manager ? 'role role-m1nd' : 'role role-ag3nt' },
|
||||||
c.is_manager ? 'm1nd' : 'ag3nt'),
|
c.is_manager ? 'm1nd' : 'ag3nt'),
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,12 @@ a:hover {
|
||||||
font-size: 1.05em;
|
font-size: 1.05em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.container-row .head .container-icon {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 4px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
.container-row .head .meta { margin-left: auto; }
|
.container-row .head .meta { margin-left: auto; }
|
||||||
.container-row .actions {
|
.container-row .actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue