Add 'gt dashboard' CLI command (hq-s1bg) (#65)
* Add LastActivity calculation for convoy dashboard (hq-x2xy) Adds internal/activity package with color-coded activity tracking: - Green: <2 minutes (active) - Yellow: 2-5 minutes (stale) - Red: >5 minutes (stuck) Features: - Calculate() function returns Info with formatted age and color class - Helper methods: IsActive(), IsStale(), IsStuck() - Handles edge cases: zero time, future time (clock skew) Tests: 8 test functions with 25 sub-tests covering all thresholds. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add convoy dashboard HTML template with Last Activity (hq-fq1g) Adds internal/web package with convoy dashboard template: - convoy.html with Last Activity column and color coding - Green (<2min), Yellow (2-5min), Red (>5min) activity indicators - htmx auto-refresh every 30 seconds - Progress bars for convoy completion - Status indicators for open/closed convoys - Empty state when no convoys Also includes internal/activity package (dependency from hq-x2xy): - Calculate() returns Info with formatted age and color class - Helper methods: IsActive(), IsStale(), IsStuck() Tests: 6 template tests + 8 activity tests, all passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add convoy list handler with activity data (hq-3edt) Adds HTTP handler that wires convoy dashboard template to real data: - ConvoyHandler: HTTP handler for GET / rendering convoy dashboard - LiveConvoyFetcher: Fetches convoys from beads with activity data - ConvoyFetcher interface: Enables mocking for tests Features: - Fetches open convoys from town beads - Calculates progress (completed/total) from tracked issues - Gets Last Activity from worker agent beads - Color codes activity: Green (<2min), Yellow (2-5min), Red (>5min) Includes dependencies (not yet merged): - internal/activity: Activity calculation (hq-x2xy) - internal/web/templates: HTML template (hq-fq1g) Tests: 5 handler tests + 6 template tests + 8 activity tests = 19 total 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add 'gt dashboard' CLI command (hq-s1bg) Add dashboard command to start the convoy tracking web server. Usage: gt dashboard [--port=8080] [--open] Features: - --port: Configurable HTTP port (default 8080) - --open: Auto-open browser on start - Cross-platform browser launch (darwin/linux/windows) - Graceful workspace detection 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
91
internal/cmd/dashboard.go
Normal file
91
internal/cmd/dashboard.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/gastown/internal/web"
|
||||
"github.com/steveyegge/gastown/internal/workspace"
|
||||
)
|
||||
|
||||
var (
|
||||
dashboardPort int
|
||||
dashboardOpen bool
|
||||
)
|
||||
|
||||
var dashboardCmd = &cobra.Command{
|
||||
Use: "dashboard",
|
||||
GroupID: GroupDiag,
|
||||
Short: "Start the convoy tracking web dashboard",
|
||||
Long: `Start a web server that displays the convoy tracking dashboard.
|
||||
|
||||
The dashboard shows real-time convoy status with:
|
||||
- Convoy list with status indicators
|
||||
- Progress tracking for each convoy
|
||||
- Last activity indicator (green/yellow/red)
|
||||
- Auto-refresh every 30 seconds via htmx
|
||||
|
||||
Example:
|
||||
gt dashboard # Start on default port 8080
|
||||
gt dashboard --port 3000 # Start on port 3000
|
||||
gt dashboard --open # Start and open browser`,
|
||||
RunE: runDashboard,
|
||||
}
|
||||
|
||||
func init() {
|
||||
dashboardCmd.Flags().IntVar(&dashboardPort, "port", 8080, "HTTP port to listen on")
|
||||
dashboardCmd.Flags().BoolVar(&dashboardOpen, "open", false, "Open browser automatically")
|
||||
rootCmd.AddCommand(dashboardCmd)
|
||||
}
|
||||
|
||||
func runDashboard(cmd *cobra.Command, args []string) error {
|
||||
// Verify we're in a workspace
|
||||
if _, err := workspace.FindFromCwdOrError(); err != nil {
|
||||
return fmt.Errorf("not in a Gas Town workspace: %w", err)
|
||||
}
|
||||
|
||||
// Create the live convoy fetcher
|
||||
fetcher, err := web.NewLiveConvoyFetcher()
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating convoy fetcher: %w", err)
|
||||
}
|
||||
|
||||
// Create the handler
|
||||
handler, err := web.NewConvoyHandler(fetcher)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating convoy handler: %w", err)
|
||||
}
|
||||
|
||||
// Build the URL
|
||||
url := fmt.Sprintf("http://localhost:%d", dashboardPort)
|
||||
|
||||
// Open browser if requested
|
||||
if dashboardOpen {
|
||||
go openBrowser(url)
|
||||
}
|
||||
|
||||
// Start the server
|
||||
fmt.Printf("🚚 Gas Town Dashboard starting at %s\n", url)
|
||||
fmt.Printf(" Press Ctrl+C to stop\n")
|
||||
|
||||
return http.ListenAndServe(fmt.Sprintf(":%d", dashboardPort), handler)
|
||||
}
|
||||
|
||||
// openBrowser opens the specified URL in the default browser.
|
||||
func openBrowser(url string) {
|
||||
var cmd *exec.Cmd
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
cmd = exec.Command("open", url)
|
||||
case "linux":
|
||||
cmd = exec.Command("xdg-open", url)
|
||||
case "windows":
|
||||
cmd = exec.Command("cmd", "/c", "start", url)
|
||||
default:
|
||||
return
|
||||
}
|
||||
_ = cmd.Start()
|
||||
}
|
||||
Reference in New Issue
Block a user