overview updates and removal of duplicate title headers
CI / Build & Test (push) Successful in 4m55s
CI / Build & Test (push) Successful in 4m55s
This commit is contained in:
+127
-129
@@ -184,14 +184,20 @@
|
||||
.topbar-title { font-size: 15px; font-weight: 600; color: var(--text); }
|
||||
.topbar-actions { display: flex; align-items: center; gap: 8px; }
|
||||
|
||||
.content { padding: 24px 28px; flex: 1; }
|
||||
.content { padding: 24px 28px; flex: 1; min-height: 0; display: flex; flex-direction: column; }
|
||||
|
||||
/* ── Page visibility ───────────────────────────── */
|
||||
.page { display: none; }
|
||||
.page.active { display: block; }
|
||||
/* Overview page: content is fixed-height (capped list cards) so the
|
||||
outer scroll area must not scroll — Quick Actions stays visible. */
|
||||
#page-dashboard.active { overflow: hidden; }
|
||||
/* Overview page fills the content area as a flex column so Quick Actions
|
||||
sticks to the bottom and the list cards share all remaining space. */
|
||||
#page-dashboard.active {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ── Cards ─────────────────────────────────────── */
|
||||
.card {
|
||||
@@ -324,13 +330,17 @@
|
||||
.ov-list-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
/* Cards fill the grid cell height set by the flex grid rows */
|
||||
height: 100%;
|
||||
}
|
||||
/* Fixed height: thead (~34px) + exactly 2 data rows (~36px each) = ~106px.
|
||||
Items 3+ scroll inside the card; the page itself never scrolls. */
|
||||
/* The scroll area grows to fill whatever height the card has after the
|
||||
header and search input. No max-height — the grid rows control height. */
|
||||
.ov-scroll-area {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 106px;
|
||||
min-height: 0;
|
||||
}
|
||||
.ov-table thead th {
|
||||
position: sticky;
|
||||
@@ -634,15 +644,6 @@
|
||||
.copy-btn.copied .copy-tooltip { opacity: 1; }
|
||||
|
||||
/* ── Page headers ──────────────────────────────── */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
gap: 12px;
|
||||
}
|
||||
.page-header h2 { font-size: 18px; font-weight: 700; color: var(--text); letter-spacing: -0.02em; }
|
||||
|
||||
/* ── Inline row layout ─────────────────────────── */
|
||||
.row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
|
||||
.row .form-group { flex: 1; min-width: 120px; }
|
||||
@@ -1017,13 +1018,12 @@
|
||||
|
||||
<!-- ── Overview page ──────────────────────────── -->
|
||||
<div class="page active" id="page-dashboard">
|
||||
<div class="page-header" style="margin-bottom:16px;">
|
||||
<h2>Overview</h2>
|
||||
<div id="overviewLastUpdated" style="font-size:11px;color:var(--text4);align-self:center;"></div>
|
||||
<div style="margin-bottom:16px;flex-shrink:0;display:flex;align-items:center;justify-content:flex-end;">
|
||||
<div id="overviewLastUpdated" style="font-size:11px;color:var(--text4);"></div>
|
||||
</div>
|
||||
|
||||
<!-- System status bar -->
|
||||
<div id="overviewStatusBar" style="display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);margin-bottom:14px;flex-wrap:wrap;">
|
||||
<div id="overviewStatusBar" style="display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);margin-bottom:14px;flex-wrap:wrap;flex-shrink:0;">
|
||||
<div style="display:flex;align-items:center;gap:7px;flex:1;min-width:160px;">
|
||||
<div class="status-dot" id="ovHostDot"></div>
|
||||
<span style="font-size:12.5px;font-weight:500;color:var(--text2);">Native Host</span>
|
||||
@@ -1050,7 +1050,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Stat cards — 6 across -->
|
||||
<div class="stats-grid" style="grid-template-columns:repeat(6,1fr);margin-bottom:14px;">
|
||||
<div class="stats-grid" style="grid-template-columns:repeat(6,1fr);margin-bottom:14px;flex-shrink:0;">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon cyan">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="2"/><circle cx="4" cy="6" r="2"/><circle cx="20" cy="6" r="2"/><line x1="6" y1="6" x2="10" y2="11"/><line x1="18" y1="6" x2="14" y2="11"/></svg>
|
||||
@@ -1095,114 +1095,121 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lists: 2-col top row, 3-col bottom row — each card has fixed height + scroll -->
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px;">
|
||||
<!-- Lists: flex column that fills all remaining space between stat cards
|
||||
and Quick Actions. Each grid row gets equal share via flex:1. -->
|
||||
<div id="ovListsWrapper" style="flex:1;min-height:0;display:flex;flex-direction:column;gap:10px;margin-bottom:10px;">
|
||||
|
||||
<!-- Virtual Hosts -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Virtual Hosts</div>
|
||||
<div class="card-subtitle" id="ovVhostSubtitle">—</div>
|
||||
<!-- Row 1: Virtual Hosts + Server Tunnels -->
|
||||
<div style="flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
||||
|
||||
<!-- Virtual Hosts -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Virtual Hosts</div>
|
||||
<div class="card-subtitle" id="ovVhostSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;flex-shrink:0;">
|
||||
<input class="input ov-search" id="ovVhostSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Hostname</th><th>State</th><th></th></tr></thead>
|
||||
<tbody id="recentConnections"></tbody>
|
||||
</table>
|
||||
<div id="ovVhostSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;">
|
||||
<input class="input ov-search" id="ovVhostSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Hostname</th><th>State</th><th></th></tr></thead>
|
||||
<tbody id="recentConnections"></tbody>
|
||||
</table>
|
||||
<div id="ovVhostSentinel" class="ov-sentinel"></div>
|
||||
|
||||
<!-- Server Tunnels -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Server Tunnels</div>
|
||||
<div class="card-subtitle" id="ovServersSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;flex-shrink:0;">
|
||||
<input class="input ov-search" id="ovServersSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Port</th><th>State</th><th>hs:// Key</th></tr></thead>
|
||||
<tbody id="ovServersBody"></tbody>
|
||||
</table>
|
||||
<div id="ovServersSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Server Tunnels -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Server Tunnels</div>
|
||||
<div class="card-subtitle" id="ovServersSubtitle">—</div>
|
||||
<!-- Row 2: Service Tunnels + SSH + Remote Desktops -->
|
||||
<div style="flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;">
|
||||
|
||||
<!-- Service Tunnels -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Service Tunnels</div>
|
||||
<div class="card-subtitle" id="ovSvcSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;flex-shrink:0;">
|
||||
<input class="input ov-search" id="ovSvcSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Label</th><th>Port</th><th>State</th></tr></thead>
|
||||
<tbody id="ovSvcBody"></tbody>
|
||||
</table>
|
||||
<div id="ovSvcSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;">
|
||||
<input class="input ov-search" id="ovServersSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Port</th><th>State</th><th>hs:// Key</th></tr></thead>
|
||||
<tbody id="ovServersBody"></tbody>
|
||||
</table>
|
||||
<div id="ovServersSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-bottom:10px;">
|
||||
|
||||
<!-- Service Tunnels -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Service Tunnels</div>
|
||||
<div class="card-subtitle" id="ovSvcSubtitle">—</div>
|
||||
<!-- SSH Connections -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">SSH Connections</div>
|
||||
<div class="card-subtitle" id="ovSshSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;flex-shrink:0;">
|
||||
<input class="input ov-search" id="ovSshSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Label</th><th>User</th></tr></thead>
|
||||
<tbody id="ovSshBody"></tbody>
|
||||
</table>
|
||||
<div id="ovSshSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;">
|
||||
<input class="input ov-search" id="ovSvcSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Label</th><th>Port</th><th>State</th></tr></thead>
|
||||
<tbody id="ovSvcBody"></tbody>
|
||||
</table>
|
||||
<div id="ovSvcSentinel" class="ov-sentinel"></div>
|
||||
|
||||
<!-- Remote Desktops -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Remote Desktops</div>
|
||||
<div class="card-subtitle" id="ovRdpSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;flex-shrink:0;">
|
||||
<input class="input ov-search" id="ovRdpSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Label</th><th>Type</th></tr></thead>
|
||||
<tbody id="ovRdpBody"></tbody>
|
||||
</table>
|
||||
<div id="ovRdpSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SSH Connections -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">SSH Connections</div>
|
||||
<div class="card-subtitle" id="ovSshSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;">
|
||||
<input class="input ov-search" id="ovSshSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Label</th><th>User</th></tr></thead>
|
||||
<tbody id="ovSshBody"></tbody>
|
||||
</table>
|
||||
<div id="ovSshSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /ovListsWrapper -->
|
||||
|
||||
<!-- Remote Desktops -->
|
||||
<div class="card ov-list-card">
|
||||
<div class="card-header" style="padding-bottom:8px;">
|
||||
<div style="min-width:0;">
|
||||
<div class="card-title">Remote Desktops</div>
|
||||
<div class="card-subtitle" id="ovRdpSubtitle">—</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:0 12px 8px;">
|
||||
<input class="input ov-search" id="ovRdpSearch" placeholder="Filter…" autocomplete="off" style="height:28px;font-size:12px;">
|
||||
</div>
|
||||
<div class="ov-scroll-area">
|
||||
<table class="table ov-table">
|
||||
<thead><tr><th>Label</th><th>Type</th></tr></thead>
|
||||
<tbody id="ovRdpBody"></tbody>
|
||||
</table>
|
||||
<div id="ovRdpSentinel" class="ov-sentinel"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick actions -->
|
||||
<!-- Quick Actions — sticky at the bottom, never pushed off screen -->
|
||||
<div class="card" style="flex-shrink:0;">
|
||||
<div class="card-header"><div class="card-title">Quick Actions</div></div>
|
||||
<div class="card-body" style="display:flex;gap:8px;flex-wrap:wrap;padding-top:10px;padding-bottom:10px;">
|
||||
@@ -1236,8 +1243,7 @@
|
||||
|
||||
<!-- ── Virtual Hosts page ──────────────────────── -->
|
||||
<div class="page" id="page-connections">
|
||||
<div class="page-header">
|
||||
<h2>Virtual Hosts</h2>
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:flex-end;">
|
||||
<button class="btn btn-primary" id="addVhostBtn">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||||
Add Host
|
||||
@@ -1265,8 +1271,7 @@
|
||||
|
||||
<!-- ── Servers page ────────────────────────────── -->
|
||||
<div class="page" id="page-swarms">
|
||||
<div class="page-header">
|
||||
<h2>Server Tunnels</h2>
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:flex-end;">
|
||||
<button class="btn btn-primary" id="startServerBtn">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||||
New Server
|
||||
@@ -1294,7 +1299,6 @@
|
||||
|
||||
<!-- ── Proxy & CA page ────────────────────────── -->
|
||||
<div class="page" id="page-tabs">
|
||||
<div class="page-header"><h2>Proxy & CA</h2></div>
|
||||
<div class="info-grid" id="proxyInfoGrid" style="margin-bottom:16px;">
|
||||
<div class="info-item">
|
||||
<div class="info-item-label">Proxy Port</div>
|
||||
@@ -1356,8 +1360,7 @@
|
||||
|
||||
<!-- ── Remote Desktop page ───────────────────── -->
|
||||
<div class="page" id="page-rdp">
|
||||
<div class="page-header">
|
||||
<h2>Remote Desktop</h2>
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:flex-end;">
|
||||
<button class="btn btn-primary" id="addRdpBtn">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||||
Add Connection
|
||||
@@ -1374,8 +1377,7 @@
|
||||
|
||||
<!-- ── Backups page ───────────────────────────── -->
|
||||
<div class="page" id="page-backups">
|
||||
<div class="page-header">
|
||||
<h2>Backups</h2>
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:flex-end;">
|
||||
<button class="btn btn-primary" id="btnTakeBackup">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17,8 12,3 7,8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
|
||||
Take Backup
|
||||
@@ -1406,7 +1408,6 @@
|
||||
|
||||
<!-- ── Settings page ──────────────────────────── -->
|
||||
<div class="page" id="page-settings">
|
||||
<div class="page-header"><h2>Settings</h2></div>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="section-heading">Notifications</div>
|
||||
@@ -1480,8 +1481,7 @@
|
||||
|
||||
<!-- ── Service Tunnels page ──────────────────────── -->
|
||||
<div class="page" id="page-service-tunnels">
|
||||
<div class="page-header">
|
||||
<h2>Service Tunnels</h2>
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:flex-end;">
|
||||
<button class="btn btn-primary" id="addServiceTunnelBtn">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||||
Add Tunnel
|
||||
@@ -1509,8 +1509,7 @@
|
||||
|
||||
<!-- ── SSH page ────────────────────────────────── -->
|
||||
<div class="page" id="page-ssh">
|
||||
<div class="page-header">
|
||||
<h2>SSH Connections</h2>
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:flex-end;">
|
||||
<button class="btn btn-primary" id="addSshBtn">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||||
Add Connection
|
||||
@@ -1527,7 +1526,6 @@
|
||||
|
||||
<!-- ── Logs page ───────────────────────────────── -->
|
||||
<div class="page" id="page-logs">
|
||||
<div class="page-header"><h2>System Logs</h2></div>
|
||||
<div class="logs-toolbar">
|
||||
<input type="text" class="input logs-filter" id="logsFilter" placeholder="Filter logs…">
|
||||
<button class="btn btn-secondary" id="btnAutoScroll">
|
||||
|
||||
Reference in New Issue
Block a user