feat: Add navigation bar and multi-page dashboard
- Add navigation bar with 4 main sections: Tasks, Wiki, Agents, Usage - Implement Wiki page with task documentation viewer - Implement Agents page showing workspace, tools, and current tasks - Implement Usage page displaying providers, models, and quotas - Add API endpoints: /api/agents, /api/usage, /api/wiki - Add agent heartbeat endpoint for task assignment - Update Docker compose with volume mounts for agent and config data - Add comprehensive CSS for all pages and responsive design - Add JavaScript navigation and dynamic content loading 🚀 Features: - 📋 Kanban task board (existing) - 📚 Wiki documentation viewer - 🤖 Agent fleet management dashboard - 📊 Provider usage and quota monitoring - 🔗 Real-time WebSocket updates - 📱 Responsive mobile design
This commit is contained in:
@@ -1,182 +1,531 @@
|
||||
:root {
|
||||
--bg: #0e1117;
|
||||
--panel: #161b22;
|
||||
--muted: #98a6b3;
|
||||
--text: #e6edf3;
|
||||
--border: #2d333b;
|
||||
--accent: #2f81f7;
|
||||
--critical: #f85149;
|
||||
--high: #db6d28;
|
||||
--medium: #d29922;
|
||||
--low: #238636;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--bg-primary: #0f1419;
|
||||
--bg-secondary: #1a1f2e;
|
||||
--bg-card: #242b3d;
|
||||
--text-primary: #e6edf3;
|
||||
--text-secondary: #8b949e;
|
||||
--accent: #f78166;
|
||||
--border: #30363d;
|
||||
--priority-high: #f85149;
|
||||
--priority-medium: #d29922;
|
||||
--priority-low: #3fb950;
|
||||
--priority-critical: #ff6b6b;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: radial-gradient(circle at top, #1c2431, var(--bg) 55%);
|
||||
color: var(--text);
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
padding: 1.2rem;
|
||||
/* Navigation */
|
||||
.navbar {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1rem 2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: rgba(22, 27, 34, 0.9);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.topbar h1 {
|
||||
margin: 0;
|
||||
font-size: 1.4rem;
|
||||
.nav-brand h1 {
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
background: var(--bg-card);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.nav-link.active {
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Pages */
|
||||
.page {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Dashboard */
|
||||
.topbar {
|
||||
padding: 1.5rem 2rem;
|
||||
background: var(--bg-secondary);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.topbar h2 {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.topbar p {
|
||||
margin: 0.25rem 0 0;
|
||||
color: var(--muted);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.composer {
|
||||
padding: 1rem 1.2rem;
|
||||
}
|
||||
|
||||
.composer h2 {
|
||||
margin: 0 0 0.7rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
#task-form {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
button {
|
||||
border: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
color: var(--text);
|
||||
padding: 1.5rem 2rem;
|
||||
background: var(--bg-secondary);
|
||||
margin: 1rem;
|
||||
border-radius: 8px;
|
||||
padding: 0.55rem 0.7rem;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
textarea {
|
||||
grid-column: 1 / -1;
|
||||
min-height: 70px;
|
||||
resize: vertical;
|
||||
.composer h3 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
background: linear-gradient(90deg, #1f6feb, var(--accent));
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.board {
|
||||
.composer form {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(220px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
padding: 0 1.2rem 1.2rem;
|
||||
}
|
||||
|
||||
.composer input,
|
||||
.composer select,
|
||||
.composer textarea {
|
||||
padding: 0.5rem;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-primary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.composer textarea {
|
||||
grid-column: 1 / -1;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
.composer button {
|
||||
padding: 0.5rem 1.5rem;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.composer button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* Board */
|
||||
.board {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
overflow-x: auto;
|
||||
min-height: calc(100vh - 400px);
|
||||
}
|
||||
|
||||
.column {
|
||||
background: rgba(22, 27, 34, 0.9);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
min-height: 220px;
|
||||
padding: 0.7rem;
|
||||
flex: 0 0 280px;
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 250px);
|
||||
}
|
||||
|
||||
.column h2 {
|
||||
font-size: 0.95rem;
|
||||
margin: 0 0 0.6rem;
|
||||
color: var(--muted);
|
||||
.column-header {
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.column-header h3 {
|
||||
font-size: 0.9rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.column-count {
|
||||
background: var(--bg-card);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 12px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.6rem;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #202632;
|
||||
border: 1px solid #334055;
|
||||
border-radius: 8px;
|
||||
padding: 0.6rem;
|
||||
background: var(--bg-card);
|
||||
border-radius: 6px;
|
||||
padding: 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.card-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 0.4rem;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: 10px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.priority-High {
|
||||
background: var(--priority-high);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.priority-Medium {
|
||||
background: var(--priority-medium);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.priority-Low {
|
||||
background: var(--priority-low);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.priority-Critical {
|
||||
background: var(--priority-critical);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
margin: 0.5rem 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
color: #c7d3df;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.meta {
|
||||
margin: 0.2rem 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.78rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
border-radius: 999px;
|
||||
font-size: 0.72rem;
|
||||
padding: 0.18rem 0.45rem;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
.assignee {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.priority.low {
|
||||
color: var(--low);
|
||||
border-color: var(--low);
|
||||
.tags {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.priority.medium {
|
||||
color: var(--medium);
|
||||
border-color: var(--medium);
|
||||
.tag {
|
||||
background: var(--bg-primary);
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.priority.high {
|
||||
color: var(--high);
|
||||
border-color: var(--high);
|
||||
.card label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.priority.critical {
|
||||
color: var(--critical);
|
||||
border-color: var(--critical);
|
||||
/* Wiki */
|
||||
.wiki-container {
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
min-height: calc(100vh - 200px);
|
||||
}
|
||||
|
||||
.status-select {
|
||||
width: 100%;
|
||||
margin-top: 0.2rem;
|
||||
.wiki-list {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
max-height: calc(100vh - 220px);
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.board {
|
||||
grid-template-columns: repeat(2, minmax(240px, 1fr));
|
||||
.wiki-item {
|
||||
padding: 0.75rem;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0.5rem;
|
||||
background: var(--bg-card);
|
||||
}
|
||||
|
||||
.wiki-item:hover {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.wiki-item.active {
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.wiki-title {
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.wiki-date {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.wiki-content {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
padding: 2rem;
|
||||
overflow-y: auto;
|
||||
max-height: calc(100vh - 220px);
|
||||
}
|
||||
|
||||
.wiki-content h1 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.wiki-content h2 {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.wiki-content p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.wiki-content code {
|
||||
background: var(--bg-card);
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.wiki-content pre {
|
||||
background: var(--bg-card);
|
||||
padding: 1rem;
|
||||
border-radius: 6px;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Agents */
|
||||
.agents-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.agent-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.agent-header {
|
||||
background: var(--bg-card);
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.agent-name {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.agent-status {
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
background: var(--priority-low);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.agent-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.agent-section {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.agent-section h4 {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.agent-task {
|
||||
color: var(--text-primary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.agent-tools,
|
||||
.agent-files {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.tool-tag,
|
||||
.file-tag {
|
||||
background: var(--bg-card);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* Usage */
|
||||
.usage-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.usage-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.provider-name {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.provider-models {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.model-item {
|
||||
padding: 0.5rem;
|
||||
background: var(--bg-card);
|
||||
border-radius: 4px;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.model-name {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.model-meta {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.provider-quota {
|
||||
padding: 1rem;
|
||||
background: var(--bg-card);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.quota-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.quota-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.quota-label {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.quota-value {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.quota-bar {
|
||||
height: 8px;
|
||||
background: var(--bg-primary);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.quota-fill {
|
||||
height: 100%;
|
||||
background: var(--accent);
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.navbar {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 620px) {
|
||||
.board {
|
||||
|
||||
.nav-links {
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.wiki-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.board {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.column {
|
||||
flex: 0 0 auto;
|
||||
max-height: none;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user