diff --git a/internal/viewer/server_extra_test.go b/internal/viewer/server_extra_test.go index db60459c2..3ed259380 100644 --- a/internal/viewer/server_extra_test.go +++ b/internal/viewer/server_extra_test.go @@ -156,6 +156,60 @@ func TestRenderTemplate_SessionPage(t *testing.T) { } } +func TestRenderTemplate_SecondarySectionsCollapsedByDefault(t *testing.T) { + rr := httptest.NewRecorder() + vs := &ViewSession{ + Summary: SessionSummary{ + SessionID: "abc", + CWD: "/test", + FilesReviewed: []string{"main.go"}, + }, + TokenUsage: TokenUsageSummary{ + FileTokenBreakdown: []FileTokenUsage{{FilePath: "main.go"}}, + }, + Files: []*FileGroup{{FilePath: "main.go", Tasks: map[TaskType][]*TaskCard{}}}, + Comments: []*ReviewComment{{ + FilePath: "main.go", + Content: "Keep this visible", + }}, + } + + renderTemplate(rr, "session.html", sessionPageData{ + EncodedRepo: "repo", + RepoName: "MyRepo", + Session: vs, + }) + + body := rr.Body.String() + if count := strings.Count(body, `
`); count != 2 { + t.Fatalf("collapsed secondary section count = %d, want 2", count) + } + if strings.Contains(body, `
`) { + t.Fatal("secondary sections should be collapsed by default") + } + if !strings.Contains(body, `
`) || strings.Contains(body, `
`) { + t.Fatal("file token breakdown should be rendered and collapsed by default") + } + if !strings.Contains(body, `
`) { + t.Fatal("review comment groups should remain expanded") + } +} + +func TestRenderTemplate_HidesEmptyConversationsSection(t *testing.T) { + rr := httptest.NewRecorder() + renderTemplate(rr, "session.html", sessionPageData{ + EncodedRepo: "repo", + RepoName: "MyRepo", + Session: &ViewSession{ + Summary: SessionSummary{SessionID: "abc", CWD: "/test"}, + }, + }) + + if strings.Contains(rr.Body.String(), `Conversations`) { + t.Fatal("empty conversations section should not be rendered") + } +} + func TestRenderTemplate_ExecutionError(t *testing.T) { rr := httptest.NewRecorder() // Pass wrong data type to trigger template execution error diff --git a/internal/viewer/static/style.css b/internal/viewer/static/style.css index 234ec757e..1fab6efcc 100644 --- a/internal/viewer/static/style.css +++ b/internal/viewer/static/style.css @@ -420,6 +420,26 @@ h3 { } .token-table tbody tr:hover { background: var(--accent-soft); } +.token-breakdown-toggle { + display: flex; + align-items: center; + gap: 0.5rem; + color: var(--text-secondary); + cursor: pointer; + font-size: 0.82rem; + font-weight: 600; + list-style: none; + padding: 0.25rem 0 0.75rem; +} +.token-breakdown-toggle::-webkit-details-marker { display: none; } +.token-breakdown-toggle::marker { content: none; } +.token-breakdown-toggle .file-count-badge { margin-left: auto; } +.token-breakdown[open] > .token-breakdown-toggle .chevron-sm { transform: rotate(45deg); } +.token-breakdown-body { + overflow-x: auto; + padding-top: 0.25rem; +} + /* ── File List ── */ .file-list { list-style: none; @@ -548,6 +568,18 @@ h3 { padding: 1rem 1.25rem 1.25rem; } +.section-accordion { + margin-top: 1.25rem; +} +.section-title { + flex: 1; + font-weight: 600; +} +.section-accordion .file-list, +.section-accordion .conversations { + margin: 0; +} + /* Task Group */ .task-group { margin-bottom: 1.25rem; } .task-group:last-child { margin-bottom: 0; } diff --git a/internal/viewer/templates/session.html b/internal/viewer/templates/session.html index 9858bcdaf..a6adfbce1 100644 --- a/internal/viewer/templates/session.html +++ b/internal/viewer/templates/session.html @@ -80,20 +80,29 @@

Token Usage

{{end}} {{with .Session.TokenUsage.FileTokenBreakdown}} - - {{if or $.Session.TokenUsage.TotalCacheReadTokens $.Session.TokenUsage.TotalCacheWriteTokens}}{{end}} - - {{range .}} - - - - - {{if or $.Session.TokenUsage.TotalCacheReadTokens $.Session.TokenUsage.TotalCacheWriteTokens}}{{end}} - - - {{end}} - -
FilePromptCompletionCache ReadCache WriteTotal
{{.FilePath | truncate 60}}{{formatNumber .PromptTokens}}{{formatNumber .CompletionTokens}}{{formatNumber .CacheReadTokens}}{{formatNumber .CacheWriteTokens}}{{formatNumber (add .PromptTokens .CompletionTokens)}}
+
+ + + File breakdown + {{len .}} files + +
+ + {{if or $.Session.TokenUsage.TotalCacheReadTokens $.Session.TokenUsage.TotalCacheWriteTokens}}{{end}} + + {{range .}} + + + + + {{if or $.Session.TokenUsage.TotalCacheReadTokens $.Session.TokenUsage.TotalCacheWriteTokens}}{{end}} + + + {{end}} + +
FilePromptCompletionCache ReadCache WriteTotal
{{.FilePath | truncate 60}}{{formatNumber .PromptTokens}}{{formatNumber .CompletionTokens}}{{formatNumber .CacheReadTokens}}{{formatNumber .CacheWriteTokens}}{{formatNumber (add .PromptTokens .CompletionTokens)}}
+
+
{{end}} @@ -151,16 +160,31 @@

Review Comments ({{len .Session.Comments}} findings)

{{end}} {{if .Session.Summary.FilesReviewed}} -

Files Reviewed

-
    -{{range .Session.Summary.FilesReviewed}} -
  • {{.}}
  • -{{end}} -
+
+ + + Files Reviewed + {{len .Session.Summary.FilesReviewed}} files + +
+
    + {{range .Session.Summary.FilesReviewed}} +
  • {{.}}
  • + {{end}} +
+
+
{{end}} -

Conversations ({{len .Session.Files}} files)

-
+{{if .Session.Files}} +
+ + + Conversations + {{len .Session.Files}} files + +
+
{{range .Session.Files}}
@@ -229,7 +253,10 @@

{{end}} -
+ + +
+{{end}}