@proletariat/cli 0.3.94 → 0.3.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent/cleanup.d.ts +3 -4
- package/dist/commands/agent/cleanup.js +5 -4
- package/dist/commands/agent/cleanup.js.map +1 -1
- package/dist/commands/agent/gc.d.ts +3 -4
- package/dist/commands/agent/gc.js +5 -4
- package/dist/commands/agent/gc.js.map +1 -1
- package/dist/commands/agent/index.d.ts +3 -4
- package/dist/commands/agent/index.js +5 -4
- package/dist/commands/agent/index.js.map +1 -1
- package/dist/commands/agent/list.d.ts +3 -4
- package/dist/commands/agent/list.js +5 -4
- package/dist/commands/agent/list.js.map +1 -1
- package/dist/commands/agent/remove.d.ts +3 -4
- package/dist/commands/agent/remove.js +5 -4
- package/dist/commands/agent/remove.js.map +1 -1
- package/dist/commands/agent/staff/index.d.ts +3 -4
- package/dist/commands/agent/staff/index.js +5 -4
- package/dist/commands/agent/staff/index.js.map +1 -1
- package/dist/commands/agent/staff/remove.d.ts +3 -4
- package/dist/commands/agent/staff/remove.js +5 -4
- package/dist/commands/agent/staff/remove.js.map +1 -1
- package/dist/commands/agent/status.d.ts +3 -4
- package/dist/commands/agent/status.js +5 -4
- package/dist/commands/agent/status.js.map +1 -1
- package/dist/commands/agent/visit.d.ts +3 -4
- package/dist/commands/agent/visit.js +5 -4
- package/dist/commands/agent/visit.js.map +1 -1
- package/dist/commands/branch/create.js +1 -12
- package/dist/commands/branch/create.js.map +1 -1
- package/dist/commands/branch/list.d.ts +3 -4
- package/dist/commands/branch/list.js +5 -4
- package/dist/commands/branch/list.js.map +1 -1
- package/dist/commands/branch/validate.d.ts +3 -4
- package/dist/commands/branch/validate.js +6 -5
- package/dist/commands/branch/validate.js.map +1 -1
- package/dist/commands/branch/where.d.ts +3 -4
- package/dist/commands/branch/where.js +5 -4
- package/dist/commands/branch/where.js.map +1 -1
- package/dist/commands/commit.js +1 -1
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/db/backup.d.ts +16 -0
- package/dist/commands/db/backup.js +125 -0
- package/dist/commands/db/backup.js.map +1 -0
- package/dist/commands/db/repair.js +8 -11
- package/dist/commands/db/repair.js.map +1 -1
- package/dist/commands/execution/config.d.ts +3 -4
- package/dist/commands/execution/config.js +5 -4
- package/dist/commands/execution/config.js.map +1 -1
- package/dist/commands/execution/index.d.ts +3 -4
- package/dist/commands/execution/index.js +5 -4
- package/dist/commands/execution/index.js.map +1 -1
- package/dist/commands/execution/list.d.ts +3 -4
- package/dist/commands/execution/list.js +5 -4
- package/dist/commands/execution/list.js.map +1 -1
- package/dist/commands/execution/logs.d.ts +3 -4
- package/dist/commands/execution/logs.js +5 -4
- package/dist/commands/execution/logs.js.map +1 -1
- package/dist/commands/execution/stop.d.ts +3 -4
- package/dist/commands/execution/stop.js +5 -4
- package/dist/commands/execution/stop.js.map +1 -1
- package/dist/commands/execution/view.d.ts +3 -4
- package/dist/commands/execution/view.js +5 -4
- package/dist/commands/execution/view.js.map +1 -1
- package/dist/commands/hook/export.d.ts +3 -4
- package/dist/commands/hook/export.js +5 -4
- package/dist/commands/hook/export.js.map +1 -1
- package/dist/commands/hook/fire.d.ts +3 -4
- package/dist/commands/hook/fire.js +5 -4
- package/dist/commands/hook/fire.js.map +1 -1
- package/dist/commands/hook/list.d.ts +3 -4
- package/dist/commands/hook/list.js +5 -4
- package/dist/commands/hook/list.js.map +1 -1
- package/dist/commands/hook/preset.d.ts +3 -4
- package/dist/commands/hook/preset.js +5 -4
- package/dist/commands/hook/preset.js.map +1 -1
- package/dist/commands/orchestrate/index.d.ts +3 -4
- package/dist/commands/orchestrate/index.js +5 -4
- package/dist/commands/orchestrate/index.js.map +1 -1
- package/dist/commands/orchestrator/index.d.ts +3 -4
- package/dist/commands/orchestrator/index.js +5 -4
- package/dist/commands/orchestrator/index.js.map +1 -1
- package/dist/commands/pr/checks.d.ts +3 -4
- package/dist/commands/pr/checks.js +5 -4
- package/dist/commands/pr/checks.js.map +1 -1
- package/dist/commands/repo/add.d.ts +3 -4
- package/dist/commands/repo/add.js +5 -4
- package/dist/commands/repo/add.js.map +1 -1
- package/dist/commands/repo/create.d.ts +3 -4
- package/dist/commands/repo/create.js +5 -4
- package/dist/commands/repo/create.js.map +1 -1
- package/dist/commands/repo/fix-remotes.d.ts +3 -4
- package/dist/commands/repo/fix-remotes.js +5 -4
- package/dist/commands/repo/fix-remotes.js.map +1 -1
- package/dist/commands/repo/index.d.ts +3 -4
- package/dist/commands/repo/index.js +5 -4
- package/dist/commands/repo/index.js.map +1 -1
- package/dist/commands/repo/list.d.ts +3 -4
- package/dist/commands/repo/list.js +5 -4
- package/dist/commands/repo/list.js.map +1 -1
- package/dist/commands/session/cleanup.d.ts +3 -4
- package/dist/commands/session/cleanup.js +5 -4
- package/dist/commands/session/cleanup.js.map +1 -1
- package/dist/commands/session/create.d.ts +3 -4
- package/dist/commands/session/create.js +5 -4
- package/dist/commands/session/create.js.map +1 -1
- package/dist/commands/session/exec.d.ts +3 -4
- package/dist/commands/session/exec.js +5 -4
- package/dist/commands/session/exec.js.map +1 -1
- package/dist/commands/session/health.js +18 -0
- package/dist/commands/session/health.js.map +1 -1
- package/dist/commands/session/index.d.ts +3 -4
- package/dist/commands/session/index.js +9 -4
- package/dist/commands/session/index.js.map +1 -1
- package/dist/commands/session/inspect.d.ts +3 -4
- package/dist/commands/session/inspect.js +5 -4
- package/dist/commands/session/inspect.js.map +1 -1
- package/dist/commands/session/list.d.ts +3 -4
- package/dist/commands/session/list.js +19 -5
- package/dist/commands/session/list.js.map +1 -1
- package/dist/commands/session/prune.d.ts +3 -4
- package/dist/commands/session/prune.js +5 -4
- package/dist/commands/session/prune.js.map +1 -1
- package/dist/commands/session/report.d.ts +25 -5
- package/dist/commands/session/report.js +201 -5
- package/dist/commands/session/report.js.map +1 -1
- package/dist/commands/session/restart.d.ts +3 -4
- package/dist/commands/session/restart.js +5 -4
- package/dist/commands/session/restart.js.map +1 -1
- package/dist/commands/session/watch.d.ts +17 -0
- package/dist/commands/session/watch.js +139 -0
- package/dist/commands/session/watch.js.map +1 -0
- package/dist/commands/ticket/index.d.ts +3 -4
- package/dist/commands/ticket/index.js +5 -4
- package/dist/commands/ticket/index.js.map +1 -1
- package/dist/commands/web.d.ts +20 -0
- package/dist/commands/web.js +82 -0
- package/dist/commands/web.js.map +1 -0
- package/dist/commands/work/hooks/add.d.ts +3 -4
- package/dist/commands/work/hooks/add.js +5 -4
- package/dist/commands/work/hooks/add.js.map +1 -1
- package/dist/commands/work/hooks/list.d.ts +3 -4
- package/dist/commands/work/hooks/list.js +5 -4
- package/dist/commands/work/hooks/list.js.map +1 -1
- package/dist/commands/work/hooks/toggle.d.ts +3 -4
- package/dist/commands/work/hooks/toggle.js +5 -4
- package/dist/commands/work/hooks/toggle.js.map +1 -1
- package/dist/commands/work/peek.d.ts +3 -4
- package/dist/commands/work/peek.js +5 -4
- package/dist/commands/work/peek.js.map +1 -1
- package/dist/commands/work/propose.d.ts +23 -0
- package/dist/commands/work/propose.js +57 -0
- package/dist/commands/work/propose.js.map +1 -0
- package/dist/commands/work/ready.js +2 -2
- package/dist/commands/work/ready.js.map +1 -1
- package/dist/commands/work/rebase.d.ts +1 -1
- package/dist/commands/work/rebase.js +52 -49
- package/dist/commands/work/rebase.js.map +1 -1
- package/dist/commands/work/ship.d.ts +6 -0
- package/dist/commands/work/ship.js +217 -48
- package/dist/commands/work/ship.js.map +1 -1
- package/dist/commands/work/start.js +3 -6
- package/dist/commands/work/start.js.map +1 -1
- package/dist/commands/work/stop.d.ts +3 -4
- package/dist/commands/work/stop.js +5 -4
- package/dist/commands/work/stop.js.map +1 -1
- package/dist/hooks/init.js +11 -1
- package/dist/hooks/init.js.map +1 -1
- package/dist/lib/branch/index.d.ts +6 -5
- package/dist/lib/branch/index.js +8 -13
- package/dist/lib/branch/index.js.map +1 -1
- package/dist/lib/dashboard/html.d.ts +2 -1
- package/dist/lib/dashboard/html.js +150 -522
- package/dist/lib/dashboard/html.js.map +1 -1
- package/dist/lib/database/db-safety.d.ts +48 -9
- package/dist/lib/database/db-safety.js +308 -43
- package/dist/lib/database/db-safety.js.map +1 -1
- package/dist/lib/database/index.d.ts +1 -1
- package/dist/lib/database/index.js +1 -1
- package/dist/lib/database/index.js.map +1 -1
- package/dist/lib/database/workspace.js +3 -1
- package/dist/lib/database/workspace.js.map +1 -1
- package/dist/lib/execution/runners/docker.js +8 -0
- package/dist/lib/execution/runners/docker.js.map +1 -1
- package/dist/lib/execution/runners/prompt-builder.js +9 -6
- package/dist/lib/execution/runners/prompt-builder.js.map +1 -1
- package/dist/lib/execution/spawner.js +2 -4
- package/dist/lib/execution/spawner.js.map +1 -1
- package/dist/lib/execution/storage.d.ts +29 -1
- package/dist/lib/execution/storage.js +77 -0
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/execution/types.d.ts +17 -6
- package/dist/lib/execution/types.js +10 -7
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/machine-config.d.ts +8 -0
- package/dist/lib/machine-config.js +37 -0
- package/dist/lib/machine-config.js.map +1 -1
- package/dist/lib/orchestrate/poller.d.ts +1 -1
- package/dist/lib/orchestrate/poller.js +1 -1
- package/dist/lib/pmo/storage/base.js +5 -3
- package/dist/lib/pmo/storage/base.js.map +1 -1
- package/dist/lib/providers/index.d.ts +1 -0
- package/dist/lib/providers/index.js +1 -0
- package/dist/lib/providers/index.js.map +1 -1
- package/dist/lib/providers/resolver.js +16 -0
- package/dist/lib/providers/resolver.js.map +1 -1
- package/dist/lib/providers/trello-provider.d.ts +28 -0
- package/dist/lib/providers/trello-provider.js +381 -0
- package/dist/lib/providers/trello-provider.js.map +1 -0
- package/dist/lib/session/heartbeat.d.ts +45 -0
- package/dist/lib/session/heartbeat.js +150 -0
- package/dist/lib/session/heartbeat.js.map +1 -0
- package/dist/lib/session/index.d.ts +7 -0
- package/dist/lib/session/index.js +8 -0
- package/dist/lib/session/index.js.map +1 -0
- package/dist/lib/session/watcher.d.ts +79 -0
- package/dist/lib/session/watcher.js +142 -0
- package/dist/lib/session/watcher.js.map +1 -0
- package/dist/lib/shipping/auto-merge.d.ts +57 -0
- package/dist/lib/shipping/auto-merge.js +311 -0
- package/dist/lib/shipping/auto-merge.js.map +1 -0
- package/dist/lib/shipping/github.d.ts +68 -0
- package/dist/lib/shipping/github.js +217 -0
- package/dist/lib/shipping/github.js.map +1 -0
- package/dist/lib/shipping/index.d.ts +13 -0
- package/dist/lib/shipping/index.js +11 -0
- package/dist/lib/shipping/index.js.map +1 -0
- package/dist/lib/shipping/rebase.d.ts +35 -0
- package/dist/lib/shipping/rebase.js +107 -0
- package/dist/lib/shipping/rebase.js.map +1 -0
- package/dist/lib/shipping/types.d.ts +181 -0
- package/dist/lib/shipping/types.js +9 -0
- package/dist/lib/shipping/types.js.map +1 -0
- package/dist/lib/trello/client.d.ts +1 -0
- package/dist/lib/trello/client.js +6 -0
- package/dist/lib/trello/client.js.map +1 -1
- package/oclif.manifest.json +908 -1009
- package/package.json +8 -8
|
@@ -2,513 +2,121 @@
|
|
|
2
2
|
* Dashboard HTML Template
|
|
3
3
|
*
|
|
4
4
|
* Returns a complete self-contained HTML page for the web dashboard.
|
|
5
|
-
*
|
|
5
|
+
* Styled to match the proletariat marketing site — Switzer font,
|
|
6
|
+
* JetBrains Mono, pink-600 accents, clean white cards, Tailwind CDN.
|
|
6
7
|
*/
|
|
7
|
-
function escapeHtml(str) {
|
|
8
|
-
return str
|
|
9
|
-
.replace(/&/g, '&')
|
|
10
|
-
.replace(/</g, '<')
|
|
11
|
-
.replace(/>/g, '>')
|
|
12
|
-
.replace(/"/g, '"')
|
|
13
|
-
.replace(/'/g, ''');
|
|
14
|
-
}
|
|
15
8
|
export function getDashboardHTML(port) {
|
|
16
9
|
return `<!DOCTYPE html>
|
|
17
|
-
<html lang="en">
|
|
10
|
+
<html lang="en" class="antialiased">
|
|
18
11
|
<head>
|
|
19
12
|
<meta charset="UTF-8">
|
|
20
13
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
21
14
|
<title>prlt dashboard</title>
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
line-height: 1.5;
|
|
46
|
-
min-height: 100vh;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/* Header */
|
|
50
|
-
.header {
|
|
51
|
-
background: var(--bg-secondary);
|
|
52
|
-
border-bottom: 1px solid var(--border);
|
|
53
|
-
padding: 12px 24px;
|
|
54
|
-
display: flex;
|
|
55
|
-
align-items: center;
|
|
56
|
-
justify-content: space-between;
|
|
57
|
-
position: sticky;
|
|
58
|
-
top: 0;
|
|
59
|
-
z-index: 100;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.header-left {
|
|
63
|
-
display: flex;
|
|
64
|
-
align-items: center;
|
|
65
|
-
gap: 12px;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.header h1 {
|
|
69
|
-
font-size: 16px;
|
|
70
|
-
font-weight: 600;
|
|
71
|
-
color: var(--text);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.header h1 span {
|
|
75
|
-
color: var(--accent);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.project-name {
|
|
79
|
-
font-size: 13px;
|
|
80
|
-
color: var(--text-muted);
|
|
81
|
-
padding: 2px 8px;
|
|
82
|
-
background: var(--bg-tertiary);
|
|
83
|
-
border-radius: 4px;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.header-right {
|
|
87
|
-
display: flex;
|
|
88
|
-
align-items: center;
|
|
89
|
-
gap: 12px;
|
|
90
|
-
font-size: 12px;
|
|
91
|
-
color: var(--text-muted);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.status-dot {
|
|
95
|
-
width: 8px;
|
|
96
|
-
height: 8px;
|
|
97
|
-
border-radius: 50%;
|
|
98
|
-
display: inline-block;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.status-dot.connected { background: var(--green); }
|
|
102
|
-
.status-dot.disconnected { background: var(--red); }
|
|
103
|
-
|
|
104
|
-
/* Main layout */
|
|
105
|
-
.main {
|
|
106
|
-
padding: 24px;
|
|
107
|
-
max-width: 1600px;
|
|
108
|
-
margin: 0 auto;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.section {
|
|
112
|
-
margin-bottom: 32px;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.section-header {
|
|
116
|
-
display: flex;
|
|
117
|
-
align-items: center;
|
|
118
|
-
gap: 8px;
|
|
119
|
-
margin-bottom: 12px;
|
|
120
|
-
font-size: 14px;
|
|
121
|
-
font-weight: 600;
|
|
122
|
-
color: var(--text-muted);
|
|
123
|
-
text-transform: uppercase;
|
|
124
|
-
letter-spacing: 0.5px;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.section-header .count {
|
|
128
|
-
font-size: 11px;
|
|
129
|
-
background: var(--bg-tertiary);
|
|
130
|
-
color: var(--text-muted);
|
|
131
|
-
padding: 1px 6px;
|
|
132
|
-
border-radius: 10px;
|
|
133
|
-
font-weight: 500;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/* Kanban Board */
|
|
137
|
-
.kanban {
|
|
138
|
-
display: flex;
|
|
139
|
-
gap: 12px;
|
|
140
|
-
overflow-x: auto;
|
|
141
|
-
padding-bottom: 8px;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.kanban-column {
|
|
145
|
-
min-width: 240px;
|
|
146
|
-
max-width: 300px;
|
|
147
|
-
flex: 1;
|
|
148
|
-
background: var(--bg-secondary);
|
|
149
|
-
border: 1px solid var(--border);
|
|
150
|
-
border-radius: 8px;
|
|
151
|
-
display: flex;
|
|
152
|
-
flex-direction: column;
|
|
153
|
-
max-height: 500px;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.kanban-column-header {
|
|
157
|
-
padding: 10px 12px;
|
|
158
|
-
border-bottom: 1px solid var(--border);
|
|
159
|
-
font-size: 13px;
|
|
160
|
-
font-weight: 600;
|
|
161
|
-
display: flex;
|
|
162
|
-
justify-content: space-between;
|
|
163
|
-
align-items: center;
|
|
164
|
-
flex-shrink: 0;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
.kanban-column-header .ticket-count {
|
|
168
|
-
font-size: 11px;
|
|
169
|
-
color: var(--text-muted);
|
|
170
|
-
background: var(--bg-tertiary);
|
|
171
|
-
padding: 1px 6px;
|
|
172
|
-
border-radius: 10px;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.kanban-column-body {
|
|
176
|
-
padding: 8px;
|
|
177
|
-
overflow-y: auto;
|
|
178
|
-
flex: 1;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.ticket-card {
|
|
182
|
-
background: var(--bg-tertiary);
|
|
183
|
-
border: 1px solid var(--border);
|
|
184
|
-
border-radius: 6px;
|
|
185
|
-
padding: 10px 12px;
|
|
186
|
-
margin-bottom: 6px;
|
|
187
|
-
cursor: default;
|
|
188
|
-
transition: border-color 0.15s;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.ticket-card:hover {
|
|
192
|
-
border-color: var(--accent);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
.ticket-id {
|
|
196
|
-
font-size: 11px;
|
|
197
|
-
font-weight: 600;
|
|
198
|
-
color: var(--accent);
|
|
199
|
-
font-family: 'SF Mono', SFMono-Regular, Consolas, monospace;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.ticket-title {
|
|
203
|
-
font-size: 13px;
|
|
204
|
-
margin-top: 4px;
|
|
205
|
-
line-height: 1.4;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.ticket-meta {
|
|
209
|
-
display: flex;
|
|
210
|
-
gap: 6px;
|
|
211
|
-
margin-top: 6px;
|
|
212
|
-
flex-wrap: wrap;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
.badge {
|
|
216
|
-
font-size: 10px;
|
|
217
|
-
padding: 1px 6px;
|
|
218
|
-
border-radius: 10px;
|
|
219
|
-
font-weight: 500;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.badge-priority { background: #1f1d2e; }
|
|
223
|
-
.badge-priority.P0 { color: var(--red); border: 1px solid var(--red); }
|
|
224
|
-
.badge-priority.P1 { color: var(--orange); border: 1px solid var(--orange); }
|
|
225
|
-
.badge-priority.P2 { color: var(--yellow); border: 1px solid var(--yellow); }
|
|
226
|
-
.badge-priority.P3 { color: var(--text-muted); border: 1px solid var(--border); }
|
|
227
|
-
|
|
228
|
-
.badge-category {
|
|
229
|
-
color: var(--purple);
|
|
230
|
-
border: 1px solid rgba(188, 140, 255, 0.3);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.badge-assignee {
|
|
234
|
-
color: var(--pink);
|
|
235
|
-
border: 1px solid rgba(247, 120, 186, 0.3);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.badge-label {
|
|
239
|
-
color: var(--text-muted);
|
|
240
|
-
border: 1px solid var(--border);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/* Agent Cards */
|
|
244
|
-
.agent-grid {
|
|
245
|
-
display: grid;
|
|
246
|
-
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
|
247
|
-
gap: 12px;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
.agent-card {
|
|
251
|
-
background: var(--bg-secondary);
|
|
252
|
-
border: 1px solid var(--border);
|
|
253
|
-
border-radius: 8px;
|
|
254
|
-
padding: 14px 16px;
|
|
255
|
-
transition: border-color 0.15s;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.agent-card:hover {
|
|
259
|
-
border-color: var(--accent);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
.agent-card.active {
|
|
263
|
-
border-left: 3px solid var(--green);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.agent-card.idle {
|
|
267
|
-
border-left: 3px solid var(--text-muted);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
.agent-name {
|
|
271
|
-
font-size: 14px;
|
|
272
|
-
font-weight: 600;
|
|
273
|
-
display: flex;
|
|
274
|
-
align-items: center;
|
|
275
|
-
gap: 6px;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
.agent-status-indicator {
|
|
279
|
-
width: 8px;
|
|
280
|
-
height: 8px;
|
|
281
|
-
border-radius: 50%;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.agent-status-indicator.active { background: var(--green); }
|
|
285
|
-
.agent-status-indicator.idle { background: var(--text-muted); }
|
|
286
|
-
|
|
287
|
-
.agent-detail {
|
|
288
|
-
font-size: 12px;
|
|
289
|
-
color: var(--text-muted);
|
|
290
|
-
margin-top: 6px;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
.agent-tickets {
|
|
294
|
-
display: flex;
|
|
295
|
-
gap: 4px;
|
|
296
|
-
flex-wrap: wrap;
|
|
297
|
-
margin-top: 8px;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
.agent-ticket-badge {
|
|
301
|
-
font-size: 10px;
|
|
302
|
-
font-family: 'SF Mono', SFMono-Regular, Consolas, monospace;
|
|
303
|
-
color: var(--accent);
|
|
304
|
-
background: rgba(88, 166, 255, 0.1);
|
|
305
|
-
border: 1px solid rgba(88, 166, 255, 0.2);
|
|
306
|
-
padding: 1px 6px;
|
|
307
|
-
border-radius: 4px;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/* Sessions Table */
|
|
311
|
-
.table-wrapper {
|
|
312
|
-
background: var(--bg-secondary);
|
|
313
|
-
border: 1px solid var(--border);
|
|
314
|
-
border-radius: 8px;
|
|
315
|
-
overflow: hidden;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
table {
|
|
319
|
-
width: 100%;
|
|
320
|
-
border-collapse: collapse;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
th {
|
|
324
|
-
text-align: left;
|
|
325
|
-
padding: 10px 14px;
|
|
326
|
-
font-size: 11px;
|
|
327
|
-
font-weight: 600;
|
|
328
|
-
color: var(--text-muted);
|
|
329
|
-
text-transform: uppercase;
|
|
330
|
-
letter-spacing: 0.5px;
|
|
331
|
-
border-bottom: 1px solid var(--border);
|
|
332
|
-
background: var(--bg-secondary);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
td {
|
|
336
|
-
padding: 10px 14px;
|
|
337
|
-
font-size: 13px;
|
|
338
|
-
border-bottom: 1px solid var(--border);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
tr:last-child td {
|
|
342
|
-
border-bottom: none;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
tr:hover td {
|
|
346
|
-
background: var(--bg-tertiary);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
.session-id {
|
|
350
|
-
font-family: 'SF Mono', SFMono-Regular, Consolas, monospace;
|
|
351
|
-
font-size: 12px;
|
|
352
|
-
color: var(--text-muted);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
.status-badge {
|
|
356
|
-
font-size: 11px;
|
|
357
|
-
padding: 2px 8px;
|
|
358
|
-
border-radius: 10px;
|
|
359
|
-
font-weight: 500;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
.status-badge.running { background: rgba(63, 185, 80, 0.15); color: var(--green); }
|
|
363
|
-
.status-badge.starting { background: rgba(210, 153, 34, 0.15); color: var(--yellow); }
|
|
364
|
-
.status-badge.orphan { background: rgba(219, 109, 40, 0.15); color: var(--orange); }
|
|
365
|
-
|
|
366
|
-
/* PR List */
|
|
367
|
-
.pr-list {
|
|
368
|
-
display: flex;
|
|
369
|
-
flex-direction: column;
|
|
370
|
-
gap: 6px;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
.pr-item {
|
|
374
|
-
background: var(--bg-secondary);
|
|
375
|
-
border: 1px solid var(--border);
|
|
376
|
-
border-radius: 8px;
|
|
377
|
-
padding: 12px 16px;
|
|
378
|
-
display: flex;
|
|
379
|
-
align-items: center;
|
|
380
|
-
gap: 12px;
|
|
381
|
-
transition: border-color 0.15s;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
.pr-item:hover {
|
|
385
|
-
border-color: var(--accent);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.pr-number {
|
|
389
|
-
font-family: 'SF Mono', SFMono-Regular, Consolas, monospace;
|
|
390
|
-
font-size: 13px;
|
|
391
|
-
color: var(--accent);
|
|
392
|
-
font-weight: 600;
|
|
393
|
-
min-width: 50px;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
.pr-title {
|
|
397
|
-
flex: 1;
|
|
398
|
-
font-size: 13px;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.pr-branch {
|
|
402
|
-
font-size: 11px;
|
|
403
|
-
font-family: 'SF Mono', SFMono-Regular, Consolas, monospace;
|
|
404
|
-
color: var(--text-muted);
|
|
405
|
-
background: var(--bg-tertiary);
|
|
406
|
-
padding: 2px 8px;
|
|
407
|
-
border-radius: 4px;
|
|
408
|
-
max-width: 250px;
|
|
409
|
-
overflow: hidden;
|
|
410
|
-
text-overflow: ellipsis;
|
|
411
|
-
white-space: nowrap;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
.ci-badge {
|
|
415
|
-
font-size: 11px;
|
|
416
|
-
padding: 2px 8px;
|
|
417
|
-
border-radius: 10px;
|
|
418
|
-
font-weight: 500;
|
|
419
|
-
white-space: nowrap;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
.ci-badge.success { background: rgba(63, 185, 80, 0.15); color: var(--green); }
|
|
423
|
-
.ci-badge.failure { background: rgba(248, 81, 73, 0.15); color: var(--red); }
|
|
424
|
-
.ci-badge.pending { background: rgba(210, 153, 34, 0.15); color: var(--yellow); }
|
|
425
|
-
.ci-badge.unknown { background: var(--bg-tertiary); color: var(--text-muted); }
|
|
426
|
-
|
|
427
|
-
.draft-badge {
|
|
428
|
-
font-size: 10px;
|
|
429
|
-
padding: 1px 6px;
|
|
430
|
-
border-radius: 10px;
|
|
431
|
-
background: var(--bg-tertiary);
|
|
432
|
-
color: var(--text-muted);
|
|
433
|
-
border: 1px solid var(--border);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/* Empty state */
|
|
437
|
-
.empty-state {
|
|
438
|
-
text-align: center;
|
|
439
|
-
padding: 32px;
|
|
440
|
-
color: var(--text-muted);
|
|
441
|
-
font-size: 13px;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/* Link styling */
|
|
445
|
-
a {
|
|
446
|
-
color: var(--accent);
|
|
447
|
-
text-decoration: none;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
a:hover {
|
|
451
|
-
text-decoration: underline;
|
|
15
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
16
|
+
<link rel="stylesheet" href="https://api.fontshare.com/css?f[]=switzer@400,500,600,700&display=swap">
|
|
17
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
18
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
19
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap">
|
|
20
|
+
<script>
|
|
21
|
+
tailwind.config = {
|
|
22
|
+
theme: {
|
|
23
|
+
extend: {
|
|
24
|
+
fontFamily: {
|
|
25
|
+
sans: ['Switzer', 'system-ui', 'sans-serif'],
|
|
26
|
+
mono: ['JetBrains Mono', 'monospace'],
|
|
27
|
+
},
|
|
28
|
+
colors: {
|
|
29
|
+
pink: {
|
|
30
|
+
600: '#D15052',
|
|
31
|
+
},
|
|
32
|
+
gray: {
|
|
33
|
+
750: '#2a2a2e',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
452
38
|
}
|
|
453
|
-
|
|
39
|
+
</script>
|
|
40
|
+
<style>
|
|
454
41
|
/* Scrollbar */
|
|
455
|
-
::-webkit-scrollbar { width:
|
|
42
|
+
::-webkit-scrollbar { width: 5px; height: 5px; }
|
|
456
43
|
::-webkit-scrollbar-track { background: transparent; }
|
|
457
|
-
::-webkit-scrollbar-thumb { background:
|
|
458
|
-
::-webkit-scrollbar-thumb:hover { background:
|
|
44
|
+
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
|
|
45
|
+
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
|
|
459
46
|
</style>
|
|
460
47
|
</head>
|
|
461
|
-
<body>
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
48
|
+
<body class="bg-white text-gray-950 font-sans min-h-screen">
|
|
49
|
+
|
|
50
|
+
<!-- Header -->
|
|
51
|
+
<header class="sticky top-0 z-50 bg-white/80 backdrop-blur-md border-b border-gray-200">
|
|
52
|
+
<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
|
|
53
|
+
<div class="flex items-center gap-4">
|
|
54
|
+
<h1 class="text-lg font-semibold tracking-tight text-gray-950">
|
|
55
|
+
<span class="text-pink-600">prlt</span> dashboard
|
|
56
|
+
</h1>
|
|
57
|
+
<span id="project-name" class="font-mono text-xs uppercase tracking-widest text-gray-500 bg-gray-100 px-3 py-1 rounded-full">loading...</span>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="flex items-center gap-3 text-xs text-gray-400">
|
|
60
|
+
<span id="status-dot" class="w-2 h-2 rounded-full bg-gray-300"></span>
|
|
61
|
+
<span id="status-text">Connecting...</span>
|
|
62
|
+
<span id="last-updated" class="text-gray-400"></span>
|
|
63
|
+
</div>
|
|
471
64
|
</div>
|
|
472
|
-
</
|
|
65
|
+
</header>
|
|
66
|
+
|
|
67
|
+
<!-- Main -->
|
|
68
|
+
<main class="max-w-7xl mx-auto px-6 py-8 space-y-10">
|
|
473
69
|
|
|
474
|
-
<div class="main">
|
|
475
70
|
<!-- Board Section -->
|
|
476
|
-
<
|
|
477
|
-
<div class="
|
|
478
|
-
|
|
479
|
-
|
|
71
|
+
<section id="board-section">
|
|
72
|
+
<div class="flex items-center gap-3 mb-4">
|
|
73
|
+
<h2 class="font-mono text-xs uppercase tracking-widest text-gray-500">Board</h2>
|
|
74
|
+
<span id="board-count" class="font-mono text-xs text-gray-400 bg-gray-100 px-2 py-0.5 rounded-full">0</span>
|
|
75
|
+
</div>
|
|
76
|
+
<div id="kanban" class="flex gap-3 overflow-x-auto pb-2"></div>
|
|
77
|
+
</section>
|
|
480
78
|
|
|
481
79
|
<!-- Agents Section -->
|
|
482
|
-
<
|
|
483
|
-
<div class="
|
|
484
|
-
|
|
485
|
-
|
|
80
|
+
<section id="agents-section">
|
|
81
|
+
<div class="flex items-center gap-3 mb-4">
|
|
82
|
+
<h2 class="font-mono text-xs uppercase tracking-widest text-gray-500">Agents</h2>
|
|
83
|
+
<span id="agents-count" class="font-mono text-xs text-gray-400 bg-gray-100 px-2 py-0.5 rounded-full">0</span>
|
|
84
|
+
</div>
|
|
85
|
+
<div id="agents-grid" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3"></div>
|
|
86
|
+
</section>
|
|
486
87
|
|
|
487
88
|
<!-- Sessions Section -->
|
|
488
|
-
<
|
|
489
|
-
<div class="
|
|
490
|
-
|
|
491
|
-
<
|
|
89
|
+
<section id="sessions-section">
|
|
90
|
+
<div class="flex items-center gap-3 mb-4">
|
|
91
|
+
<h2 class="font-mono text-xs uppercase tracking-widest text-gray-500">Sessions</h2>
|
|
92
|
+
<span id="sessions-count" class="font-mono text-xs text-gray-400 bg-gray-100 px-2 py-0.5 rounded-full">0</span>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="bg-white rounded-2xl shadow-sm ring-1 ring-gray-200 overflow-hidden">
|
|
95
|
+
<table class="w-full">
|
|
492
96
|
<thead>
|
|
493
|
-
<tr>
|
|
494
|
-
<th>Session</th>
|
|
495
|
-
<th>Ticket</th>
|
|
496
|
-
<th>Agent</th>
|
|
497
|
-
<th>Environment</th>
|
|
498
|
-
<th>Status</th>
|
|
97
|
+
<tr class="border-b border-gray-100">
|
|
98
|
+
<th class="text-left px-4 py-3 font-mono text-xs uppercase tracking-widest text-gray-400 font-medium">Session</th>
|
|
99
|
+
<th class="text-left px-4 py-3 font-mono text-xs uppercase tracking-widest text-gray-400 font-medium">Ticket</th>
|
|
100
|
+
<th class="text-left px-4 py-3 font-mono text-xs uppercase tracking-widest text-gray-400 font-medium">Agent</th>
|
|
101
|
+
<th class="text-left px-4 py-3 font-mono text-xs uppercase tracking-widest text-gray-400 font-medium">Environment</th>
|
|
102
|
+
<th class="text-left px-4 py-3 font-mono text-xs uppercase tracking-widest text-gray-400 font-medium">Status</th>
|
|
499
103
|
</tr>
|
|
500
104
|
</thead>
|
|
501
105
|
<tbody id="sessions-body"></tbody>
|
|
502
106
|
</table>
|
|
503
107
|
</div>
|
|
504
|
-
</
|
|
108
|
+
</section>
|
|
505
109
|
|
|
506
110
|
<!-- PRs Section -->
|
|
507
|
-
<
|
|
508
|
-
<div class="
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
111
|
+
<section id="prs-section">
|
|
112
|
+
<div class="flex items-center gap-3 mb-4">
|
|
113
|
+
<h2 class="font-mono text-xs uppercase tracking-widest text-gray-500">Pull Requests</h2>
|
|
114
|
+
<span id="prs-count" class="font-mono text-xs text-gray-400 bg-gray-100 px-2 py-0.5 rounded-full">0</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div id="pr-list" class="space-y-2"></div>
|
|
117
|
+
</section>
|
|
118
|
+
|
|
119
|
+
</main>
|
|
512
120
|
|
|
513
121
|
<script>
|
|
514
122
|
// Escape helper
|
|
@@ -519,6 +127,17 @@ export function getDashboardHTML(port) {
|
|
|
519
127
|
return d.innerHTML;
|
|
520
128
|
}
|
|
521
129
|
|
|
130
|
+
// Priority colors
|
|
131
|
+
function priorityClasses(p) {
|
|
132
|
+
switch (p) {
|
|
133
|
+
case 'P0': return 'text-red-600 ring-red-200 bg-red-50';
|
|
134
|
+
case 'P1': return 'text-orange-600 ring-orange-200 bg-orange-50';
|
|
135
|
+
case 'P2': return 'text-yellow-600 ring-yellow-200 bg-yellow-50';
|
|
136
|
+
case 'P3': return 'text-gray-500 ring-gray-200 bg-gray-50';
|
|
137
|
+
default: return 'text-gray-500 ring-gray-200 bg-gray-50';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
522
141
|
// Render functions
|
|
523
142
|
function renderBoard(board) {
|
|
524
143
|
const kanban = document.getElementById('kanban');
|
|
@@ -528,28 +147,28 @@ export function getDashboardHTML(port) {
|
|
|
528
147
|
document.getElementById('board-count').textContent = totalTickets;
|
|
529
148
|
|
|
530
149
|
if (cols.length === 0) {
|
|
531
|
-
kanban.innerHTML = '<
|
|
150
|
+
kanban.innerHTML = '<p class="text-sm text-gray-400 py-8 text-center w-full">No board data</p>';
|
|
532
151
|
return;
|
|
533
152
|
}
|
|
534
153
|
|
|
535
154
|
kanban.innerHTML = cols.map(col => {
|
|
536
155
|
const tickets = col.tickets || [];
|
|
537
|
-
return '<div class="
|
|
538
|
-
'<div class="
|
|
539
|
-
'<span>' + esc(col.name) + '</span>' +
|
|
540
|
-
'<span class="
|
|
156
|
+
return '<div class="min-w-[240px] max-w-[300px] flex-1 bg-white rounded-2xl shadow-sm ring-1 ring-gray-200 flex flex-col max-h-[500px]">' +
|
|
157
|
+
'<div class="px-4 py-3 border-b border-gray-100 flex justify-between items-center flex-shrink-0">' +
|
|
158
|
+
'<span class="text-sm font-medium text-gray-950">' + esc(col.name) + '</span>' +
|
|
159
|
+
'<span class="font-mono text-xs text-gray-400 bg-gray-100 px-2 py-0.5 rounded-full">' + tickets.length + '</span>' +
|
|
541
160
|
'</div>' +
|
|
542
|
-
'<div class="
|
|
161
|
+
'<div class="p-2 overflow-y-auto flex-1 space-y-1.5">' +
|
|
543
162
|
(tickets.length === 0 ? '' : tickets.map(t => {
|
|
544
163
|
let meta = '';
|
|
545
|
-
if (t.priority) meta += '<span class="
|
|
546
|
-
if (t.category) meta += '<span class="
|
|
547
|
-
if (t.assignee) meta += '<span class="
|
|
548
|
-
(t.labels || []).forEach(l => { meta += '<span class="
|
|
549
|
-
return '<div class="
|
|
550
|
-
'<div class="
|
|
551
|
-
'<div class="
|
|
552
|
-
(meta ? '<div class="
|
|
164
|
+
if (t.priority) meta += '<span class="inline-flex text-[10px] font-mono font-medium px-1.5 py-0.5 rounded-lg ring-1 ' + priorityClasses(t.priority) + '">' + esc(t.priority) + '</span>';
|
|
165
|
+
if (t.category) meta += '<span class="inline-flex text-[10px] font-mono font-medium px-1.5 py-0.5 rounded-lg ring-1 ring-purple-200 text-purple-600 bg-purple-50">' + esc(t.category) + '</span>';
|
|
166
|
+
if (t.assignee) meta += '<span class="inline-flex text-[10px] font-mono font-medium px-1.5 py-0.5 rounded-lg ring-1 ring-pink-600/20 text-pink-600 bg-pink-50">' + esc(t.assignee) + '</span>';
|
|
167
|
+
(t.labels || []).forEach(l => { meta += '<span class="inline-flex text-[10px] font-mono font-medium px-1.5 py-0.5 rounded-lg ring-1 ring-gray-200 text-gray-500 bg-gray-50">' + esc(l) + '</span>'; });
|
|
168
|
+
return '<div class="bg-gray-50 rounded-xl p-3 transition-all hover:ring-1 hover:ring-pink-600/30 cursor-default">' +
|
|
169
|
+
'<div class="font-mono text-[11px] font-semibold text-pink-600">' + esc(t.id) + '</div>' +
|
|
170
|
+
'<div class="text-sm text-gray-950 mt-1 leading-snug">' + esc(t.title) + '</div>' +
|
|
171
|
+
(meta ? '<div class="flex gap-1.5 mt-2 flex-wrap">' + meta + '</div>' : '') +
|
|
553
172
|
'</div>';
|
|
554
173
|
}).join('')) +
|
|
555
174
|
'</div>' +
|
|
@@ -562,25 +181,26 @@ export function getDashboardHTML(port) {
|
|
|
562
181
|
document.getElementById('agents-count').textContent = agents.length;
|
|
563
182
|
|
|
564
183
|
if (agents.length === 0) {
|
|
565
|
-
grid.innerHTML = '<
|
|
184
|
+
grid.innerHTML = '<p class="text-sm text-gray-400 py-8 text-center col-span-full">No agents found</p>';
|
|
566
185
|
return;
|
|
567
186
|
}
|
|
568
187
|
|
|
569
188
|
grid.innerHTML = agents.map(a => {
|
|
570
189
|
const isActive = a.hasActiveSessions;
|
|
571
|
-
const
|
|
190
|
+
const borderClass = isActive ? 'border-l-[3px] border-l-green-400' : 'border-l-[3px] border-l-gray-300';
|
|
191
|
+
const dotClass = isActive ? 'bg-green-400' : 'bg-gray-300';
|
|
572
192
|
let tickets = '';
|
|
573
193
|
if (a.assignedTickets.length > 0) {
|
|
574
|
-
tickets = '<div class="
|
|
575
|
-
a.assignedTickets.map(t => '<span class="
|
|
194
|
+
tickets = '<div class="flex gap-1.5 flex-wrap mt-3">' +
|
|
195
|
+
a.assignedTickets.map(t => '<span class="font-mono text-[10px] font-medium text-pink-600 bg-pink-50 ring-1 ring-pink-600/20 px-2 py-0.5 rounded-lg">' + esc(t) + '</span>').join('') +
|
|
576
196
|
'</div>';
|
|
577
197
|
}
|
|
578
|
-
return '<div class="
|
|
579
|
-
'<div class="
|
|
580
|
-
'<span class="
|
|
581
|
-
esc(a.name) +
|
|
198
|
+
return '<div class="bg-white rounded-2xl shadow-sm ring-1 ring-gray-200 p-4 transition-all hover:ring-pink-600/30 ' + borderClass + '">' +
|
|
199
|
+
'<div class="flex items-center gap-2">' +
|
|
200
|
+
'<span class="w-2 h-2 rounded-full flex-shrink-0 ' + dotClass + '"></span>' +
|
|
201
|
+
'<span class="text-sm font-semibold text-gray-950">' + esc(a.name) + '</span>' +
|
|
582
202
|
'</div>' +
|
|
583
|
-
(a.branch ? '<div class="
|
|
203
|
+
(a.branch ? '<div class="font-mono text-xs text-gray-400 mt-1.5 truncate">' + esc(a.branch) + '</div>' : '') +
|
|
584
204
|
tickets +
|
|
585
205
|
'</div>';
|
|
586
206
|
}).join('');
|
|
@@ -591,18 +211,22 @@ export function getDashboardHTML(port) {
|
|
|
591
211
|
document.getElementById('sessions-count').textContent = sessions.length;
|
|
592
212
|
|
|
593
213
|
if (sessions.length === 0) {
|
|
594
|
-
body.innerHTML = '<tr><td colspan="5" class="
|
|
214
|
+
body.innerHTML = '<tr><td colspan="5" class="text-sm text-gray-400 text-center py-8">No active sessions</td></tr>';
|
|
595
215
|
return;
|
|
596
216
|
}
|
|
597
217
|
|
|
598
218
|
body.innerHTML = sessions.map(s => {
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
'<td
|
|
219
|
+
const envLabel = s.environment === 'container' ? 'container' : 'host';
|
|
220
|
+
let statusCls = 'text-gray-500 bg-gray-50 ring-gray-200';
|
|
221
|
+
if (s.status === 'running') statusCls = 'text-green-600 bg-green-50 ring-green-200';
|
|
222
|
+
else if (s.status === 'starting') statusCls = 'text-yellow-600 bg-yellow-50 ring-yellow-200';
|
|
223
|
+
else if (s.status === 'orphan') statusCls = 'text-orange-600 bg-orange-50 ring-orange-200';
|
|
224
|
+
return '<tr class="border-b border-gray-50 hover:bg-gray-50/50 transition-colors">' +
|
|
225
|
+
'<td class="px-4 py-3 font-mono text-xs text-gray-400">' + esc(s.sessionId) + '</td>' +
|
|
226
|
+
'<td class="px-4 py-3 font-mono text-xs font-medium text-pink-600">' + esc(s.ticketId) + '</td>' +
|
|
227
|
+
'<td class="px-4 py-3 text-sm text-gray-950">' + esc(s.agentName) + '</td>' +
|
|
228
|
+
'<td class="px-4 py-3"><span class="font-mono text-[10px] uppercase tracking-widest text-gray-400">' + esc(envLabel) + '</span></td>' +
|
|
229
|
+
'<td class="px-4 py-3"><span class="font-mono text-[10px] font-medium px-2 py-0.5 rounded-full ring-1 ' + statusCls + '">' + esc(s.status) + '</span></td>' +
|
|
606
230
|
'</tr>';
|
|
607
231
|
}).join('');
|
|
608
232
|
}
|
|
@@ -612,19 +236,23 @@ export function getDashboardHTML(port) {
|
|
|
612
236
|
document.getElementById('prs-count').textContent = prs.length;
|
|
613
237
|
|
|
614
238
|
if (prs.length === 0) {
|
|
615
|
-
list.innerHTML = '<
|
|
239
|
+
list.innerHTML = '<p class="text-sm text-gray-400 py-8 text-center">No open pull requests</p>';
|
|
616
240
|
return;
|
|
617
241
|
}
|
|
618
242
|
|
|
619
243
|
list.innerHTML = prs.map(pr => {
|
|
620
244
|
const ciClass = pr.ciStatus || 'unknown';
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
'<
|
|
245
|
+
let ciCls = 'text-gray-500 bg-gray-50 ring-gray-200';
|
|
246
|
+
let ciLabel = 'unknown';
|
|
247
|
+
if (ciClass === 'success') { ciCls = 'text-green-600 bg-green-50 ring-green-200'; ciLabel = 'passed'; }
|
|
248
|
+
else if (ciClass === 'failure') { ciCls = 'text-red-600 bg-red-50 ring-red-200'; ciLabel = 'failed'; }
|
|
249
|
+
else if (ciClass === 'pending') { ciCls = 'text-yellow-600 bg-yellow-50 ring-yellow-200'; ciLabel = 'running'; }
|
|
250
|
+
return '<div class="bg-white rounded-2xl shadow-sm ring-1 ring-gray-200 px-5 py-3.5 flex items-center gap-4 transition-all hover:ring-pink-600/30">' +
|
|
251
|
+
'<a href="' + esc(pr.url) + '" target="_blank" class="font-mono text-sm font-semibold text-pink-600 hover:underline min-w-[50px]">#' + pr.number + '</a>' +
|
|
252
|
+
'<span class="text-sm text-gray-950 flex-1">' + esc(pr.title) + '</span>' +
|
|
253
|
+
(pr.isDraft ? '<span class="font-mono text-[10px] uppercase tracking-widest text-gray-400 ring-1 ring-gray-200 px-2 py-0.5 rounded-full">draft</span>' : '') +
|
|
254
|
+
'<span class="font-mono text-[10px] text-gray-400 bg-gray-100 px-2 py-0.5 rounded-lg max-w-[220px] truncate">' + esc(pr.headBranch) + '</span>' +
|
|
255
|
+
'<span class="font-mono text-[10px] font-medium px-2 py-0.5 rounded-full ring-1 whitespace-nowrap ' + ciCls + '">' + ciLabel + '</span>' +
|
|
628
256
|
'</div>';
|
|
629
257
|
}).join('');
|
|
630
258
|
}
|
|
@@ -632,7 +260,7 @@ export function getDashboardHTML(port) {
|
|
|
632
260
|
function renderAll(data) {
|
|
633
261
|
document.getElementById('project-name').textContent = data.projectName || data.projectId;
|
|
634
262
|
const ts = new Date(data.timestamp);
|
|
635
|
-
document.getElementById('last-updated').textContent =
|
|
263
|
+
document.getElementById('last-updated').textContent = ts.toLocaleTimeString();
|
|
636
264
|
renderBoard(data.board);
|
|
637
265
|
renderAgents(data.agents);
|
|
638
266
|
renderSessions(data.sessions);
|
|
@@ -653,7 +281,7 @@ export function getDashboardHTML(port) {
|
|
|
653
281
|
const es = new EventSource('/api/events');
|
|
654
282
|
|
|
655
283
|
es.onopen = () => {
|
|
656
|
-
dot.className = '
|
|
284
|
+
dot.className = 'w-2 h-2 rounded-full bg-green-400';
|
|
657
285
|
statusText.textContent = 'Live';
|
|
658
286
|
};
|
|
659
287
|
|
|
@@ -667,7 +295,7 @@ export function getDashboardHTML(port) {
|
|
|
667
295
|
};
|
|
668
296
|
|
|
669
297
|
es.onerror = () => {
|
|
670
|
-
dot.className = '
|
|
298
|
+
dot.className = 'w-2 h-2 rounded-full bg-red-400';
|
|
671
299
|
statusText.textContent = 'Reconnecting...';
|
|
672
300
|
es.close();
|
|
673
301
|
setTimeout(connectSSE, 3000);
|