feat(dashboard): add Server Links page with all service URLs
Categorized link cards for all services across nodes + public domains. Opens in new tabs. Accessible from sidebar navigation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+101
-4
@@ -184,17 +184,34 @@ function renderGroupList() {
|
||||
}
|
||||
|
||||
function updateSidebarActive() {
|
||||
// All services link
|
||||
const allLink = $("#nav-all");
|
||||
if (allLink) {
|
||||
allLink.classList.toggle("active", currentView === "all");
|
||||
}
|
||||
const linksLink = $("#nav-links");
|
||||
if (allLink) allLink.classList.toggle("active", currentView === "all");
|
||||
if (linksLink) linksLink.classList.toggle("active", currentView === "links");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main content rendering
|
||||
// ---------------------------------------------------------------------------
|
||||
function renderMain() {
|
||||
const linksView = $("#links-view");
|
||||
const toolbar = $("#toolbar");
|
||||
const grid = $("#service-grid");
|
||||
const emptyState = $("#empty-state");
|
||||
|
||||
if (currentView === "links") {
|
||||
toolbar.style.display = "none";
|
||||
grid.style.display = "none";
|
||||
emptyState.style.display = "none";
|
||||
linksView.style.display = "block";
|
||||
renderLinksView();
|
||||
return;
|
||||
}
|
||||
|
||||
toolbar.style.display = "flex";
|
||||
grid.style.display = "grid";
|
||||
linksView.style.display = "none";
|
||||
|
||||
const filtered = getFilteredServices();
|
||||
renderToolbar(filtered);
|
||||
renderServices(filtered);
|
||||
@@ -711,6 +728,75 @@ function updateRefreshIndicator() {
|
||||
indicator.classList.toggle("paused", logPanelOpen || modalOpen);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Links page
|
||||
// ---------------------------------------------------------------------------
|
||||
const serverLinks = [
|
||||
{ category: "Public Services", links: [
|
||||
{ name: "Home Assistant", url: "https://yoda.hobbs.farm", icon: "\uD83C\uDFE0" },
|
||||
{ name: "Matrix Chat", url: "https://mess.hobbs.farm", icon: "\uD83D\uDCAC" },
|
||||
{ name: "Guacamole", url: "https://solo.hobbs.farm/guacamole/", icon: "\uD83D\uDDA5\uFE0F" },
|
||||
{ name: "Vaultwarden", url: "https://vault.hobbs.farm", icon: "\uD83D\uDD12" },
|
||||
{ name: "Gitea", url: "https://git.hobbs.farm", icon: "\uD83D\uDCE6" },
|
||||
]},
|
||||
{ category: "hf-pdocker-01 (192.168.86.192)", links: [
|
||||
{ name: "Farm Manager", url: "http://192.168.86.192:8888", icon: "\uD83C\uDF3E" },
|
||||
{ name: "Frigate NVR", url: "http://192.168.86.192:5000", icon: "\uD83D\uDCF7" },
|
||||
{ name: "Home Assistant", url: "http://192.168.86.192:8123", icon: "\uD83C\uDFE0" },
|
||||
{ name: "ESPHome", url: "http://192.168.86.192:6052", icon: "\uD83D\uDD0C" },
|
||||
{ name: "Grafana", url: "http://192.168.86.192:3001", icon: "\uD83D\uDCCA" },
|
||||
{ name: "Prometheus", url: "http://192.168.86.192:9095", icon: "\uD83D\uDD25" },
|
||||
{ name: "Alertmanager", url: "http://192.168.86.192:9093", icon: "\uD83D\uDEA8" },
|
||||
{ name: "AdGuard Home", url: "http://192.168.86.192:3000", icon: "\uD83D\uDEE1\uFE0F" },
|
||||
{ name: "Traefik Dashboard", url: "http://192.168.86.192:8090", icon: "\uD83D\uDEA6" },
|
||||
{ name: "Portainer", url: "http://192.168.86.192:9000", icon: "\uD83D\uDC33" },
|
||||
]},
|
||||
{ category: "hf-pdocker-02 (192.168.86.100)", links: [
|
||||
{ name: "Gitea", url: "http://192.168.86.100:3003", icon: "\uD83D\uDCE6" },
|
||||
{ name: "Wiki.js", url: "http://192.168.86.100:3002", icon: "\uD83D\uDCDA" },
|
||||
{ name: "Semaphore", url: "http://192.168.86.100:3004", icon: "\uD83C\uDFAF" },
|
||||
{ name: "Unifi Controller", url: "https://192.168.86.100:8443", icon: "\uD83D\uDCF6" },
|
||||
{ name: "Vaultwarden", url: "http://192.168.86.100:26226", icon: "\uD83D\uDD12" },
|
||||
{ name: "Actual Budget", url: "http://192.168.86.100:5006", icon: "\uD83D\uDCB0" },
|
||||
{ name: "MCPO", url: "http://192.168.86.100:8001", icon: "\uD83E\uDD16" },
|
||||
{ name: "Trivy", url: "http://192.168.86.100:4954", icon: "\uD83D\uDD0D" },
|
||||
]},
|
||||
{ category: "bart (192.168.86.167)", links: [
|
||||
{ name: "Jellyfin", url: "http://192.168.86.167:8096", icon: "\uD83C\uDFAC" },
|
||||
{ name: "Sonarr", url: "http://192.168.86.167:8989", icon: "\uD83D\uDCFA" },
|
||||
{ name: "Radarr", url: "http://192.168.86.167:7878", icon: "\uD83C\uDFAC" },
|
||||
{ name: "SABnzbd", url: "http://192.168.86.167:8082", icon: "\u2B07\uFE0F" },
|
||||
{ name: "NZBHydra2", url: "http://192.168.86.167:5076", icon: "\uD83D\uDD0E" },
|
||||
{ name: "Jellyseerr", url: "http://192.168.86.167:5055", icon: "\u2B50" },
|
||||
{ name: "OpenVAS", url: "http://192.168.86.167:9392", icon: "\uD83D\uDEE1\uFE0F" },
|
||||
]},
|
||||
{ category: "Infrastructure", links: [
|
||||
{ name: "Synology NAS", url: "https://192.168.86.30:5001", icon: "\uD83D\uDCBE" },
|
||||
]},
|
||||
];
|
||||
|
||||
function renderLinksView() {
|
||||
const container = $("#links-view");
|
||||
container.innerHTML = `<h2 style="margin-bottom:20px;">Server Links</h2>` +
|
||||
serverLinks.map((cat) => `
|
||||
<div class="links-category">
|
||||
<div class="links-category-title">${escHtml(cat.category)}</div>
|
||||
<div class="links-grid">
|
||||
${cat.links.map((l) => `
|
||||
<a href="${escHtml(l.url)}" target="_blank" rel="noopener" class="link-card">
|
||||
<div class="link-icon">${l.icon}</div>
|
||||
<div class="link-info">
|
||||
<div class="link-name">${escHtml(l.name)}</div>
|
||||
<div class="link-url">${escHtml(l.url)}</div>
|
||||
</div>
|
||||
<span class="link-arrow">\u203A</span>
|
||||
</a>
|
||||
`).join("")}
|
||||
</div>
|
||||
</div>
|
||||
`).join("");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Utilities
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -742,6 +828,17 @@ function bindEvents() {
|
||||
});
|
||||
}
|
||||
|
||||
// Links nav
|
||||
const linksNav = $("#nav-links");
|
||||
if (linksNav) {
|
||||
linksNav.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
currentView = "links";
|
||||
renderSidebar();
|
||||
renderMain();
|
||||
});
|
||||
}
|
||||
|
||||
// Status filter pills
|
||||
$$(".filter-pill").forEach((pill) => {
|
||||
pill.addEventListener("click", () => {
|
||||
|
||||
Reference in New Issue
Block a user