bgrun 3.12.0 → 3.12.2
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/dashboard/app/api/check-port/route.ts +35 -0
- package/dashboard/app/api/dependencies/route.ts +40 -0
- package/dashboard/app/api/deploy/[name]/route.ts +6 -41
- package/dashboard/app/api/deploy-all/route.ts +25 -0
- package/dashboard/app/api/guard/route.ts +4 -1
- package/dashboard/app/api/guard-events/route.ts +5 -0
- package/dashboard/app/api/history/route.ts +39 -0
- package/dashboard/app/api/next-port/route.ts +32 -0
- package/dashboard/app/api/processes/route.ts +11 -3
- package/dashboard/app/api/restart/[name]/route.ts +7 -0
- package/dashboard/app/api/start/route.ts +11 -0
- package/dashboard/app/api/stop/[name]/route.ts +4 -1
- package/dashboard/app/api/templates/route.ts +47 -0
- package/dashboard/app/globals.css +1565 -5
- package/dashboard/app/page.client.tsx +1907 -2
- package/dashboard/app/page.tsx +292 -5
- package/dist/index.js +787 -194
- package/package.json +2 -2
- package/scripts/bgr-startup.ps1 +3 -3
- package/scripts/bgrun-startup.ps1 +91 -0
- package/src/bgrun.test.ts +171 -0
- package/src/commands/details.ts +17 -3
- package/src/commands/list.ts +37 -4
- package/src/commands/run.ts +21 -3
- package/src/db.ts +257 -0
- package/src/deploy.ts +163 -0
- package/src/guard.ts +51 -0
- package/src/index.ts +92 -14
- package/src/index_copy.ts +614 -0
- package/src/logger.ts +12 -2
- package/src/platform.ts +101 -56
- package/src/server.ts +87 -3
- package/src/utils.ts +2 -2
package/dashboard/app/page.tsx
CHANGED
|
@@ -12,20 +12,20 @@ export default function DashboardPage() {
|
|
|
12
12
|
<div className="toast-container" id="toast-container"></div>
|
|
13
13
|
|
|
14
14
|
{/* Stats Grid */}
|
|
15
|
-
<div className="stats-grid">
|
|
16
|
-
<div className="stat-card">
|
|
15
|
+
<div className="stats-grid" id="stats-grid">
|
|
16
|
+
<div className="stat-card stat-clickable" data-stat-filter="all">
|
|
17
17
|
<div className="stat-label">Total Processes</div>
|
|
18
18
|
<div className="stat-value" id="total-count">–</div>
|
|
19
19
|
</div>
|
|
20
|
-
<div className="stat-card running">
|
|
20
|
+
<div className="stat-card running stat-clickable" data-stat-filter="running">
|
|
21
21
|
<div className="stat-label">Running</div>
|
|
22
22
|
<div className="stat-value" id="running-count">–</div>
|
|
23
23
|
</div>
|
|
24
|
-
<div className="stat-card stopped">
|
|
24
|
+
<div className="stat-card stopped stat-clickable" data-stat-filter="stopped">
|
|
25
25
|
<div className="stat-label">Stopped</div>
|
|
26
26
|
<div className="stat-value" id="stopped-count">–</div>
|
|
27
27
|
</div>
|
|
28
|
-
<div className="stat-card guarded">
|
|
28
|
+
<div className="stat-card guarded stat-clickable" data-stat-filter="guarded">
|
|
29
29
|
<div className="stat-label">Guarded</div>
|
|
30
30
|
<div className="stat-value" id="guarded-count">–</div>
|
|
31
31
|
</div>
|
|
@@ -37,6 +37,23 @@ export default function DashboardPage() {
|
|
|
37
37
|
<div className="stat-label">Guard Restarts</div>
|
|
38
38
|
<div className="stat-value" id="restarts-count">0</div>
|
|
39
39
|
</div>
|
|
40
|
+
<div className="stat-card uptime">
|
|
41
|
+
<div className="stat-label">Longest Uptime</div>
|
|
42
|
+
<div className="stat-value" id="uptime-longest">–</div>
|
|
43
|
+
</div>
|
|
44
|
+
<div className="stat-card uptime-total">
|
|
45
|
+
<div className="stat-label">Total Uptime</div>
|
|
46
|
+
<div className="stat-value" id="uptime-total">–</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
{/* Guard Activity Feed */}
|
|
51
|
+
<div className="guard-activity" id="guard-activity">
|
|
52
|
+
<div className="guard-activity-header">
|
|
53
|
+
<span className="guard-activity-title">🛡️ Guard Activity</span>
|
|
54
|
+
<span className="guard-activity-empty" id="guard-activity-empty">No recent activity</span>
|
|
55
|
+
</div>
|
|
56
|
+
<div className="guard-activity-list" id="guard-activity-list"></div>
|
|
40
57
|
</div>
|
|
41
58
|
|
|
42
59
|
{/* Toolbar */}
|
|
@@ -56,6 +73,14 @@ export default function DashboardPage() {
|
|
|
56
73
|
<span className="search-count" id="search-count" style={{ display: 'none' }}></span>
|
|
57
74
|
<span className="search-shortcut">/</span>
|
|
58
75
|
</div>
|
|
76
|
+
<span className="stat-filter-badge" id="stat-filter-badge" style={{ display: 'none' }}>
|
|
77
|
+
<span id="stat-filter-badge-label"></span>
|
|
78
|
+
<button className="stat-filter-badge-clear" id="stat-filter-badge-clear" type="button" title="Clear status filter">✕</button>
|
|
79
|
+
</span>
|
|
80
|
+
<select className="group-filter" id="group-filter">
|
|
81
|
+
<option value="">All Groups</option>
|
|
82
|
+
</select>
|
|
83
|
+
<div className="deploy-preset-scopes" id="deploy-preset-scopes"></div>
|
|
59
84
|
</div>
|
|
60
85
|
<div className="toolbar-right">
|
|
61
86
|
<button className="btn btn-ghost btn-icon" id="refresh-btn" title="Refresh">
|
|
@@ -70,13 +95,68 @@ export default function DashboardPage() {
|
|
|
70
95
|
</svg>
|
|
71
96
|
<span id="guard-all-label">Guard All</span>
|
|
72
97
|
</button>
|
|
98
|
+
<button className="btn btn-ghost" id="deploy-all-btn" title="Git pull + restart all deployable processes">
|
|
99
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
100
|
+
<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" />
|
|
101
|
+
<path d="M12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" />
|
|
102
|
+
<path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0" />
|
|
103
|
+
<path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" />
|
|
104
|
+
</svg>
|
|
105
|
+
<span id="deploy-all-label">Deploy All</span>
|
|
106
|
+
</button>
|
|
107
|
+
<div className="deploy-controls">
|
|
108
|
+
<label className="deploy-concurrency-wrap" title="Bulk deploy concurrency (saved per group)">
|
|
109
|
+
<span className="deploy-concurrency-label">Deploy</span>
|
|
110
|
+
<select className="deploy-concurrency-select" id="deploy-concurrency-select">
|
|
111
|
+
<option value="1">1×</option>
|
|
112
|
+
<option value="2">2×</option>
|
|
113
|
+
<option value="3">3×</option>
|
|
114
|
+
<option value="4">4×</option>
|
|
115
|
+
</select>
|
|
116
|
+
</label>
|
|
117
|
+
<span className="deploy-preset-source" id="deploy-preset-source" title="Current deploy preset source">default</span>
|
|
118
|
+
<button className="btn btn-ghost btn-icon" id="deploy-preset-reset-btn" title="Reset saved deploy preset for current group">
|
|
119
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
120
|
+
<polyline points="1 4 1 10 7 10" />
|
|
121
|
+
<path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10" />
|
|
122
|
+
</svg>
|
|
123
|
+
</button>
|
|
124
|
+
</div>
|
|
73
125
|
<span className="guard-sentinel-pill" id="guard-sentinel-pill" title="Standalone guard process status">
|
|
74
126
|
<span className="guard-sentinel-dot" id="guard-sentinel-dot" />
|
|
75
127
|
<span id="guard-sentinel-label">Guard: –</span>
|
|
76
128
|
</span>
|
|
129
|
+
<button className="btn btn-ghost btn-icon" id="theme-toggle-btn" title="Toggle light/dark theme">
|
|
130
|
+
<span id="theme-toggle-icon" style={{ fontSize: '0.85rem' }}>🌙</span>
|
|
131
|
+
</button>
|
|
77
132
|
<button className="btn btn-ghost btn-icon" id="shortcuts-btn" title="Keyboard Shortcuts (?)">
|
|
78
133
|
<span style={{ fontSize: '0.85rem', fontWeight: '700' }}>?</span>
|
|
79
134
|
</button>
|
|
135
|
+
<button className="btn btn-secondary" id="templates-btn">
|
|
136
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
137
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
138
|
+
<polyline points="14 2 14 8 20 8" />
|
|
139
|
+
</svg>
|
|
140
|
+
Templates
|
|
141
|
+
</button>
|
|
142
|
+
<button className="btn btn-ghost" id="deps-btn" title="Process Dependencies">
|
|
143
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
144
|
+
<circle cx="6" cy="6" r="3" />
|
|
145
|
+
<circle cx="18" cy="6" r="3" />
|
|
146
|
+
<circle cx="18" cy="18" r="3" />
|
|
147
|
+
<line x1="9" y1="6" x2="15" y2="6" />
|
|
148
|
+
<path d="M18 9v6" />
|
|
149
|
+
<path d="M9 6l6 9" />
|
|
150
|
+
</svg>
|
|
151
|
+
Deps
|
|
152
|
+
</button>
|
|
153
|
+
<button className="btn btn-ghost" id="history-btn">
|
|
154
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
155
|
+
<circle cx="12" cy="12" r="10" />
|
|
156
|
+
<polyline points="12 6 12 12 16 14" />
|
|
157
|
+
</svg>
|
|
158
|
+
History
|
|
159
|
+
</button>
|
|
80
160
|
<button className="btn btn-primary" id="new-process-btn">
|
|
81
161
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
82
162
|
<line x1="12" y1="5" x2="12" y2="19" />
|
|
@@ -218,6 +298,19 @@ export default function DashboardPage() {
|
|
|
218
298
|
<label htmlFor="process-directory-input">Working Directory</label>
|
|
219
299
|
<input type="text" id="process-directory-input" placeholder="/path/to/project" />
|
|
220
300
|
</div>
|
|
301
|
+
<div className="form-group">
|
|
302
|
+
<label htmlFor="process-port-input">Port <span style={{ fontWeight: 400, color: 'var(--text-muted)' }}>(optional)</span></label>
|
|
303
|
+
<div className="port-input-wrap">
|
|
304
|
+
<input type="number" id="process-port-input" placeholder="auto" min="1" max="65535" />
|
|
305
|
+
<button className="btn btn-ghost btn-sm" id="suggest-port-btn" type="button" title="Auto-assign next available port">Suggest</button>
|
|
306
|
+
</div>
|
|
307
|
+
<div className="port-range-wrap">
|
|
308
|
+
<span className="port-range-label">Range</span>
|
|
309
|
+
<input type="number" id="port-range-min" className="port-range-input" placeholder="3001" min="1" max="65535" />
|
|
310
|
+
<span className="port-range-sep">–</span>
|
|
311
|
+
<input type="number" id="port-range-max" className="port-range-input" placeholder="4000" min="1" max="65535" />
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
221
314
|
</div>
|
|
222
315
|
<div className="modal-footer">
|
|
223
316
|
<button className="btn btn-ghost" id="modal-cancel-btn">Cancel</button>
|
|
@@ -226,6 +319,199 @@ export default function DashboardPage() {
|
|
|
226
319
|
</div>
|
|
227
320
|
</div>
|
|
228
321
|
|
|
322
|
+
{/* History Modal */}
|
|
323
|
+
{/* Dependencies Modal */}
|
|
324
|
+
<div className="modal-overlay" id="deps-modal">
|
|
325
|
+
<div className="modal modal-wide">
|
|
326
|
+
<div className="modal-header">
|
|
327
|
+
<h3>🔗 Process Dependencies</h3>
|
|
328
|
+
<button className="modal-close" id="deps-modal-close">✕</button>
|
|
329
|
+
</div>
|
|
330
|
+
<div className="modal-body">
|
|
331
|
+
<div className="deps-controls">
|
|
332
|
+
<select id="deps-process-select" className="history-select">
|
|
333
|
+
<option value="">Select process...</option>
|
|
334
|
+
</select>
|
|
335
|
+
<span className="deps-arrow">depends on →</span>
|
|
336
|
+
<select id="deps-target-select" className="history-select">
|
|
337
|
+
<option value="">Select dependency...</option>
|
|
338
|
+
</select>
|
|
339
|
+
<button className="btn btn-primary btn-sm" id="deps-add-btn">Add</button>
|
|
340
|
+
</div>
|
|
341
|
+
<div className="deps-graph-container" id="deps-graph-container">
|
|
342
|
+
<svg id="deps-graph-svg" width="100%" height="400"></svg>
|
|
343
|
+
</div>
|
|
344
|
+
<div className="deps-list" id="deps-list"></div>
|
|
345
|
+
<div className="deps-start-order" id="deps-start-order"></div>
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
</div>
|
|
349
|
+
|
|
350
|
+
<div className="modal-overlay" id="history-modal">
|
|
351
|
+
<div className="modal modal-wide">
|
|
352
|
+
<div className="modal-header">
|
|
353
|
+
<h3>📜 Process History</h3>
|
|
354
|
+
<button className="modal-close" id="history-modal-close">✕</button>
|
|
355
|
+
</div>
|
|
356
|
+
<div className="modal-body">
|
|
357
|
+
<div className="history-filters">
|
|
358
|
+
<select id="history-process-filter" className="history-select">
|
|
359
|
+
<option value="">All Processes</option>
|
|
360
|
+
</select>
|
|
361
|
+
<select id="history-event-filter" className="history-select">
|
|
362
|
+
<option value="">All Events</option>
|
|
363
|
+
<option value="start">Start</option>
|
|
364
|
+
<option value="stop">Stop</option>
|
|
365
|
+
<option value="restart">Restart</option>
|
|
366
|
+
<option value="deploy">Deploy</option>
|
|
367
|
+
<option value="guard_on">Guard On</option>
|
|
368
|
+
<option value="guard_off">Guard Off</option>
|
|
369
|
+
</select>
|
|
370
|
+
<input id="history-metadata-filter" className="history-select history-search" type="text" placeholder="Filter metadata (comma-separated)..." />
|
|
371
|
+
<label className="history-density-wrap" title="History row density">
|
|
372
|
+
<span className="history-density-label">Density</span>
|
|
373
|
+
<select id="history-density-select" className="history-select history-density-select">
|
|
374
|
+
<option value="cozy">Cozy</option>
|
|
375
|
+
<option value="compact">Compact</option>
|
|
376
|
+
</select>
|
|
377
|
+
</label>
|
|
378
|
+
<label className="history-shortcuts-toggle" title="Show quick-action affordances in History rows">
|
|
379
|
+
<input id="history-shortcuts-toggle" type="checkbox" />
|
|
380
|
+
<span>Shortcuts</span>
|
|
381
|
+
</label>
|
|
382
|
+
<label className="history-density-wrap" title="Default History details state">
|
|
383
|
+
<span className="history-density-label">Details</span>
|
|
384
|
+
<select id="history-details-default-select" className="history-select history-density-select">
|
|
385
|
+
<option value="collapsed">Collapsed</option>
|
|
386
|
+
<option value="expanded">Expanded</option>
|
|
387
|
+
</select>
|
|
388
|
+
</label>
|
|
389
|
+
<button className="btn btn-ghost btn-sm" id="history-clear-filters-btn" title="Clear all history filters">Clear</button>
|
|
390
|
+
</div>
|
|
391
|
+
<div className="history-hints-bar">
|
|
392
|
+
<div className="history-hints-bar-left">
|
|
393
|
+
<span className="history-hints-title">Keyboard shortcuts</span>
|
|
394
|
+
<div className="history-focus-controls">
|
|
395
|
+
<button className="history-focus-jump" id="history-focus-prev" type="button" title="Focus previous History row">←</button>
|
|
396
|
+
<span className="history-focus-status" id="history-focus-status">No row selected</span>
|
|
397
|
+
<button className="history-focus-jump" id="history-focus-next" type="button" title="Focus next History row">→</button>
|
|
398
|
+
</div>
|
|
399
|
+
<label className="history-auto-open-toggle" title="Automatically sync the process drawer while stepping through History rows">
|
|
400
|
+
<input id="history-auto-open-toggle" type="checkbox" />
|
|
401
|
+
<span>Auto-open</span>
|
|
402
|
+
</label>
|
|
403
|
+
<label className="history-hint-density-wrap" title="Auto-open behavior while stepping through History rows">
|
|
404
|
+
<span className="history-density-label">Scope</span>
|
|
405
|
+
<select id="history-focus-scope-select" className="history-select history-hint-density-select">
|
|
406
|
+
<option value="sync">Sync drawer</option>
|
|
407
|
+
<option value="inspect">Inspect</option>
|
|
408
|
+
</select>
|
|
409
|
+
</label>
|
|
410
|
+
</div>
|
|
411
|
+
<div className="history-hints-actions">
|
|
412
|
+
<label className="history-hint-density-wrap" title="Keyboard hint density">
|
|
413
|
+
<span className="history-density-label">Hints</span>
|
|
414
|
+
<select id="history-hint-density-select" className="history-select history-hint-density-select">
|
|
415
|
+
<option value="full">Full</option>
|
|
416
|
+
<option value="compact">Compact</option>
|
|
417
|
+
</select>
|
|
418
|
+
</label>
|
|
419
|
+
<details className="history-hint-groups-menu">
|
|
420
|
+
<summary className="history-hints-toggle" title="Choose which History hint groups to show">Groups</summary>
|
|
421
|
+
<div className="history-hint-groups-panel">
|
|
422
|
+
<div className="history-hint-presets">
|
|
423
|
+
<button className="history-hint-preset" type="button" data-history-hint-preset="minimal">Minimal</button>
|
|
424
|
+
<button className="history-hint-preset" type="button" data-history-hint-preset="navigation">Navigation</button>
|
|
425
|
+
<button className="history-hint-preset" type="button" data-history-hint-preset="all">All</button>
|
|
426
|
+
<span className="history-hint-preset-state" id="history-hint-preset-state">Custom</span>
|
|
427
|
+
</div>
|
|
428
|
+
<label className="history-hint-group-option"><input id="history-hint-group-nav" type="checkbox" /> <span>Navigation</span></label>
|
|
429
|
+
<label className="history-hint-group-option"><input id="history-hint-group-open" type="checkbox" /> <span>Open</span></label>
|
|
430
|
+
<label className="history-hint-group-option"><input id="history-hint-group-filter" type="checkbox" /> <span>Filters</span></label>
|
|
431
|
+
<label className="history-hint-group-option"><input id="history-hint-group-details" type="checkbox" /> <span>Details</span></label>
|
|
432
|
+
<label className="history-hint-group-option"><input id="history-hint-group-close" type="checkbox" /> <span>Close</span></label>
|
|
433
|
+
</div>
|
|
434
|
+
</details>
|
|
435
|
+
<button className="history-hints-toggle" id="history-hints-toggle" type="button" title="Hide keyboard shortcut hints">Hide</button>
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
<div className="history-keyboard-hints" id="history-keyboard-hints" aria-label="History keyboard shortcuts">
|
|
439
|
+
<span className="history-keyboard-hint" data-hint-group="nav"><kbd>↑</kbd><kbd>↓</kbd><span>Move</span></span>
|
|
440
|
+
<span className="history-keyboard-hint" data-hint-group="open"><kbd>Enter</kbd><span>Open</span></span>
|
|
441
|
+
<span className="history-keyboard-hint" data-hint-group="filter"><kbd>F</kbd><span>Process filter</span></span>
|
|
442
|
+
<span className="history-keyboard-hint" data-hint-group="filter"><kbd>E</kbd><span>Event filter</span></span>
|
|
443
|
+
<span className="history-keyboard-hint" data-hint-group="details"><kbd>Space</kbd><span>Toggle details</span></span>
|
|
444
|
+
<span className="history-keyboard-hint" data-hint-group="close"><kbd>Esc</kbd><span>Close</span></span>
|
|
445
|
+
</div>
|
|
446
|
+
<div className="history-list" id="history-list">
|
|
447
|
+
<div className="history-empty">No history yet</div>
|
|
448
|
+
</div>
|
|
449
|
+
</div>
|
|
450
|
+
</div>
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
{/* Templates Modal */}
|
|
454
|
+
<div className="modal-overlay" id="templates-modal">
|
|
455
|
+
<div className="modal modal-wide">
|
|
456
|
+
<div className="modal-header">
|
|
457
|
+
<h3>📋 Process Templates</h3>
|
|
458
|
+
<button className="modal-close" id="templates-modal-close">✕</button>
|
|
459
|
+
</div>
|
|
460
|
+
<div className="modal-body">
|
|
461
|
+
<div className="templates-form">
|
|
462
|
+
<div className="form-row">
|
|
463
|
+
<div className="form-group">
|
|
464
|
+
<label htmlFor="template-name">Template Name</label>
|
|
465
|
+
<input type="text" id="template-name" placeholder="my-template" />
|
|
466
|
+
</div>
|
|
467
|
+
<div className="form-group">
|
|
468
|
+
<label htmlFor="template-command">Command</label>
|
|
469
|
+
<input type="text" id="template-command" placeholder="bun run dev" />
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
<div className="form-row">
|
|
473
|
+
<div className="form-group">
|
|
474
|
+
<label htmlFor="template-directory">Working Directory</label>
|
|
475
|
+
<input type="text" id="template-directory" placeholder="/path/to/project" />
|
|
476
|
+
</div>
|
|
477
|
+
<div className="form-group">
|
|
478
|
+
<label htmlFor="template-group">Group</label>
|
|
479
|
+
<input type="text" id="template-group" placeholder="my-group" />
|
|
480
|
+
</div>
|
|
481
|
+
</div>
|
|
482
|
+
<div className="form-group">
|
|
483
|
+
<label htmlFor="template-env">Environment (KEY=VAL,KEY2=VAL2)</label>
|
|
484
|
+
<input type="text" id="template-env" placeholder="BGR_KEEP_ALIVE=true,PORT=3000" />
|
|
485
|
+
</div>
|
|
486
|
+
<div className="templates-actions">
|
|
487
|
+
<button className="btn btn-primary" id="template-save-btn">Save Template</button>
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
<div className="templates-list" id="templates-list">
|
|
491
|
+
<div className="templates-empty">No templates saved yet</div>
|
|
492
|
+
</div>
|
|
493
|
+
</div>
|
|
494
|
+
</div>
|
|
495
|
+
</div>
|
|
496
|
+
|
|
497
|
+
{/* Deploy Results Modal */}
|
|
498
|
+
<div className="modal-overlay" id="deploy-results-modal">
|
|
499
|
+
<div className="modal modal-wide">
|
|
500
|
+
<div className="modal-header">
|
|
501
|
+
<h3>🚀 Deploy Results</h3>
|
|
502
|
+
<button className="modal-close" id="deploy-results-modal-close">✕</button>
|
|
503
|
+
</div>
|
|
504
|
+
<div className="modal-body">
|
|
505
|
+
<div className="deploy-results-summary" id="deploy-results-summary">
|
|
506
|
+
No deploy results yet
|
|
507
|
+
</div>
|
|
508
|
+
<div className="deploy-results-list" id="deploy-results-list">
|
|
509
|
+
<div className="history-empty">Run a bulk deploy to see detailed results</div>
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
512
|
+
</div>
|
|
513
|
+
</div>
|
|
514
|
+
|
|
229
515
|
{/* Keyboard Shortcuts Overlay */}
|
|
230
516
|
<div className="shortcuts-overlay" id="shortcuts-overlay">
|
|
231
517
|
<div className="shortcuts-panel">
|
|
@@ -248,6 +534,7 @@ export default function DashboardPage() {
|
|
|
248
534
|
<div className="shortcut-row"><kbd>G</kbd><span>Toggle guard</span></div>
|
|
249
535
|
<div className="shortcut-row"><kbd>D</kbd><span>Delete process</span></div>
|
|
250
536
|
<div className="shortcut-row"><kbd>N</kbd><span>New process</span></div>
|
|
537
|
+
<div className="shortcut-row"><kbd>T</kbd><span>Cycle stat filter</span></div>
|
|
251
538
|
<div className="shortcut-row"><kbd>?</kbd><span>This help</span></div>
|
|
252
539
|
</div>
|
|
253
540
|
</div>
|