feat(web): unify card states — one 'Summarize now' verb, honest no-captions state
Five explicit footer states, status-primary:
1. Summarized — chip + actions, no button (unchanged)
2. No captions (TranscriptStatus=="none") — NEW: 'No transcript available' muted
text, no button, no POST URL. Removes the dead-end 'Summarize' button that
tried and failed when there were no captions to fetch.
3. Queued (SummarizeRequested) — chip + muted text, no button (unchanged)
4. Rate-limited — 'Fetching soon…' + quiet 'Summarize now' → /retry-now
5. Pending — 'Not summarized' + quiet 'Summarize now' → /summarize
One verb ('Summarize now'), one quiet style (.btn-quiet, renamed from .btn-retry
which was state-specific). User doesn't see the internal pipeline distinction;
both buttons post to their existing handlers unchanged. Form class renamed
card-nudge-form. Dropped engineer-facing tooltip; user-facing hint added.
'Try now' wording removed entirely.
This commit is contained in:
+25
-11
@@ -182,11 +182,15 @@ templ summaryList(rows []store.SummaryRow, hasConnected bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// VideoCard is one list card, also returned standalone by POST /v/{id}/summarize
|
||||
// (HTMX swaps it in place via outerHTML). A summarized video links to its detail
|
||||
// page and shows its provider chip / fallback badge / action state. An
|
||||
// unsummarized video gets a muted "pending" treatment and either a "Summarize"
|
||||
// button (to queue it) or a "Queued" chip when already requested.
|
||||
// VideoCard is one list card, returned standalone by POST /v/{id}/summarize and
|
||||
// /v/{id}/retry-now (HTMX swaps outerHTML). Five footer states, status-primary:
|
||||
// 1. Summarized — preview + chip + actions; no button.
|
||||
// 2. No captions (TranscriptStatus=="none") — terminal; "No transcript available"; no button.
|
||||
// 3. Queued (SummarizeRequested) — "Queued · waiting for the next run"; no button.
|
||||
// 4. Rate-limited — "Fetching soon" + quiet "Summarize now" → /retry-now.
|
||||
// 5. Pending (else) — "Not summarized" + quiet "Summarize now" → /summarize.
|
||||
// States 4 and 5 use one verb ("Summarize now") and one style (.btn-quiet); the
|
||||
// backend side-effect difference (clear-backoff vs. set-flag) is invisible to users.
|
||||
templ VideoCard(r store.SummaryRow) {
|
||||
<li class={ "card", templ.KV("card-pending", !r.Summarized) } id={ "video-" + r.VideoID }>
|
||||
if r.Summarized {
|
||||
@@ -204,6 +208,7 @@ templ VideoCard(r store.SummaryRow) {
|
||||
}
|
||||
<div class="card-foot">
|
||||
if r.Summarized {
|
||||
// State 1: summarized — provider chip, fallback badge, action state.
|
||||
if r.AIProvider != "" {
|
||||
<span class="chip">{ r.AIProvider }</span>
|
||||
}
|
||||
@@ -213,29 +218,38 @@ templ VideoCard(r store.SummaryRow) {
|
||||
if len(r.Actions) > 0 {
|
||||
<span class="card-state">{ strings.Join(r.Actions, ", ") }</span>
|
||||
}
|
||||
} else if r.TranscriptStatus == "none" {
|
||||
// State 2: no captions — terminal dead-end; nothing the user can do.
|
||||
<span class="card-state muted">No transcript available</span>
|
||||
} else if r.SummarizeRequested {
|
||||
// State 3: queued for the next scheduled pass.
|
||||
<span class="chip">Queued</span>
|
||||
<span class="card-state muted">waiting for the next run</span>
|
||||
} else if r.TranscriptStatus == "rate_limited" {
|
||||
// State 4: rate-limited — quiet status + quiet nudge button → retry-now handler.
|
||||
<span class="card-state muted">Fetching soon…</span>
|
||||
<form
|
||||
method="post"
|
||||
action={ retryNowURL(r.VideoID) }
|
||||
hx-post={ string(retryNowURL(r.VideoID)) }
|
||||
hx-target={ "#video-" + r.VideoID }
|
||||
hx-swap="outerHTML"
|
||||
class="retry-form"
|
||||
class="card-nudge-form"
|
||||
>
|
||||
<button type="submit" class="btn-retry" title="Fetch transcript now through the shared rate gate">Try now</button>
|
||||
<button type="submit" class="btn-quiet" title="Summarize this one now">Summarize now</button>
|
||||
</form>
|
||||
} else if r.SummarizeRequested {
|
||||
<span class="chip">Queued</span>
|
||||
<span class="card-state muted">waiting for the next run</span>
|
||||
} else {
|
||||
// State 5: pending — discovered, not yet attempted; nudge button → summarize handler.
|
||||
<span class="card-state muted">Not summarized</span>
|
||||
<form
|
||||
method="post"
|
||||
action={ summarizeURL(r.VideoID) }
|
||||
hx-post={ string(summarizeURL(r.VideoID)) }
|
||||
hx-target={ "#video-" + r.VideoID }
|
||||
hx-swap="outerHTML"
|
||||
class="card-nudge-form"
|
||||
>
|
||||
<button type="submit" class="btn-secondary">Summarize</button>
|
||||
<button type="submit" class="btn-quiet" title="Summarize this one now">Summarize now</button>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user