9508b73293
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>
140 lines
5.2 KiB
HTML
140 lines
5.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Farm Manager</title>
|
|
<link rel="stylesheet" href="/style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ===== Header ===== -->
|
|
<header id="header">
|
|
<h1>Farm Manager</h1>
|
|
<div class="header-right">
|
|
<span id="refresh-indicator" class="refresh-indicator" title="Auto-refreshing every 15s">
|
|
<span class="refresh-dot"></span> Auto-refresh
|
|
</span>
|
|
<span id="last-updated" class="last-updated"></span>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- ===== Sidebar ===== -->
|
|
<nav id="sidebar">
|
|
<div class="sidebar-section">
|
|
<a href="#" class="sidebar-item active" id="nav-all" data-view="all">
|
|
<span class="sidebar-icon">☰</span> All Services
|
|
</a>
|
|
<a href="#" class="sidebar-item" id="nav-links" data-view="links">
|
|
<span class="sidebar-icon">🔗</span> Server Links
|
|
</a>
|
|
</div>
|
|
|
|
<div class="sidebar-section">
|
|
<div class="sidebar-heading">Nodes</div>
|
|
<div id="node-list"></div>
|
|
</div>
|
|
|
|
<div class="sidebar-section">
|
|
<div class="sidebar-heading">
|
|
Groups
|
|
<button class="btn-icon" id="btn-add-group" title="Create group">✚</button>
|
|
</div>
|
|
<div id="group-list"></div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- ===== Main Content ===== -->
|
|
<main id="main">
|
|
<!-- Toolbar -->
|
|
<div id="toolbar" class="toolbar">
|
|
<div class="toolbar-left">
|
|
<h2 id="view-title">All Services</h2>
|
|
<span id="service-count" class="service-count"></span>
|
|
</div>
|
|
<div class="toolbar-center" id="group-actions" style="display:none;">
|
|
<button class="btn btn-success btn-sm" id="btn-group-start" title="Start all in group">▶ Start All</button>
|
|
<button class="btn btn-danger btn-sm" id="btn-group-stop" title="Stop all in group">■ Stop All</button>
|
|
<button class="btn btn-warning btn-sm" id="btn-group-restart" title="Restart all in group">↻ Restart All</button>
|
|
</div>
|
|
<div class="toolbar-filters" id="status-filters">
|
|
<button class="filter-pill active" data-filter="all">All</button>
|
|
<button class="filter-pill" data-filter="running">Running <span id="count-running" class="filter-count"></span></button>
|
|
<button class="filter-pill" data-filter="stopped">Stopped <span id="count-stopped" class="filter-count"></span></button>
|
|
</div>
|
|
<div class="toolbar-right">
|
|
<input type="text" id="search-input" class="search-input" placeholder="Search services...">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Service Grid -->
|
|
<div id="service-grid" class="service-grid"></div>
|
|
|
|
<!-- Empty state -->
|
|
<div id="empty-state" class="empty-state" style="display:none;">
|
|
<span class="empty-icon">📦</span>
|
|
<p>No services found</p>
|
|
</div>
|
|
|
|
<!-- Links view -->
|
|
<div id="links-view" style="display:none;"></div>
|
|
</main>
|
|
|
|
<!-- ===== Log Viewer (slide-out panel) ===== -->
|
|
<div id="log-overlay" class="log-overlay" style="display:none;"></div>
|
|
<div id="log-panel" class="log-panel">
|
|
<div class="log-header">
|
|
<h3 id="log-title">Container Logs</h3>
|
|
<button class="btn-icon log-close" id="btn-close-logs" title="Close">✕</button>
|
|
</div>
|
|
<pre id="log-content" class="log-content"></pre>
|
|
</div>
|
|
|
|
<!-- ===== Group Editor Modal ===== -->
|
|
<div id="group-modal" class="modal-overlay" style="display:none;">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<h3 id="group-modal-title">Create Group</h3>
|
|
<button class="btn-icon" id="btn-close-group-modal" title="Close">✕</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="group-name-input">Group Name</label>
|
|
<input type="text" id="group-name-input" class="form-input" placeholder="e.g. Media Stack">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Services</label>
|
|
<input type="text" id="group-service-search" class="form-input" placeholder="Filter services...">
|
|
<div id="group-service-list" class="group-service-list"></div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-secondary" id="btn-cancel-group">Cancel</button>
|
|
<button class="btn btn-primary" id="btn-save-group">Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ===== Confirmation Modal ===== -->
|
|
<div id="confirm-modal" class="modal-overlay" style="display:none;">
|
|
<div class="modal modal-sm">
|
|
<div class="modal-header">
|
|
<h3>Confirm Action</h3>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p id="confirm-message"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-secondary" id="btn-confirm-cancel">Cancel</button>
|
|
<button class="btn btn-danger" id="btn-confirm-ok">Confirm</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ===== Toast Container ===== -->
|
|
<div id="toast-container" class="toast-container"></div>
|
|
|
|
<script src="/app.js"></script>
|
|
</body>
|
|
</html>
|