Files
gitea-mobile/internal/templates/pulls.html
T
agent-company b0c060efae feat: add review status icon and merge status indicator to PR list rows
Add per-PR review state aggregation by fetching reviews concurrently
via the existing semaphore pattern. Display review status (approved,
changes requested, awaiting) and merge status (ready/conflicts) as
compact badges in each PR card row.

- Add ReviewState field to PullRequest struct
- Add GetPullReviewState() and EnrichPullsWithReviewState() to client
- Call enrichment in ListPulls handler after fetching PRs
- Update pulls template with review and merge badges
- Add CSS for .review-badge and .merge-badge classes

Closes leeworks-agents/gitea-mobile#97

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 03:07:52 +00:00

67 lines
3.1 KiB
HTML

{{define "cards"}}
{{range .Pulls}}
<div class="card" hx-get="/pulls/{{.RepoOwner}}/{{.RepoName}}/{{.Number}}" hx-target="#main-content" hx-swap="innerHTML" hx-push-url="true">
<div class="card-title">
<span class="type-badge type-pull">PR</span>
{{.Title}}
</div>
<div class="card-meta">
<span>{{.RepoOwner}}/{{.RepoName}} #{{.Number}}</span>
{{range .Labels}}
<span class="label" style="color:#{{.Color}};border:1px solid #{{.Color}}">{{.Name}}</span>
{{end}}
<span class="diff-add">+{{.Additions}}</span>
<span class="diff-del">-{{.Deletions}}</span>
{{if eq .ReviewState "approved"}}<span class="review-badge review-approved" title="Approved">&#10003;</span>
{{else if eq .ReviewState "changes_requested"}}<span class="review-badge review-changes" title="Changes requested">&#10007;</span>
{{else if eq .ReviewState "pending"}}<span class="review-badge review-pending" title="Awaiting review">&#9202;</span>
{{end}}
{{if .Mergeable}}<span class="merge-badge merge-ready" title="Ready to merge">&#9654; Ready</span>
{{else}}<span class="merge-badge merge-conflicts" title="Has conflicts or not mergeable">Conflicts</span>
{{end}}
</div>
</div>
{{end}}
{{if .HasMore}}
<div class="scroll-sentinel" hx-get="/pulls?page={{.NextPage}}&org={{.SelectedOrg}}&state={{.SelectedState}}&label={{.SelectedLabel}}&repo={{.SelectedRepo}}" hx-trigger="revealed" hx-swap="outerHTML" hx-target="this">
<div class="spinner htmx-indicator"></div>
</div>
{{end}}
{{end}}
{{define "content"}}
<h1>Pull Requests</h1>
<div class="filter-bar">
<select name="org" hx-get="/pulls" hx-trigger="change" hx-target="#main-content" hx-swap="innerHTML" hx-push-url="true" hx-include="[name='state'],[name='label']">
<option value="">All orgs</option>
{{range .Orgs}}
<option value="{{.}}" {{if eq . $.SelectedOrg}}selected{{end}}>{{.}}</option>
{{end}}
</select>
{{if .Repos}}
<select name="repo" hx-get="/pulls" hx-trigger="change" hx-target="#main-content" hx-swap="innerHTML" hx-push-url="true" hx-include="[name='org'],[name='state'],[name='label']">
<option value="">All repos</option>
{{range .Repos}}<option value="{{.}}" {{if eq . $.SelectedRepo}}selected{{end}}>{{.}}</option>{{end}}
</select>
{{end}}
<select name="state" hx-get="/pulls" hx-trigger="change" hx-target="#main-content" hx-swap="innerHTML" hx-push-url="true" hx-include="[name='org'],[name='repo'],[name='label']">
<option value="open" {{if eq .SelectedState "open"}}selected{{end}}>Open</option>
<option value="closed" {{if eq .SelectedState "closed"}}selected{{end}}>Closed</option>
</select>
<input type="text" name="label" placeholder="Filter by label..." value="{{.SelectedLabel}}"
hx-get="/pulls" hx-trigger="input changed delay:400ms" hx-target="#main-content"
hx-swap="innerHTML" hx-push-url="true" hx-include="[name='org'],[name='state'],[name='repo']">
</div>
{{if .Error}}
<p class="empty">{{.Error}}</p>
{{else if not .Pulls}}
<p class="empty">No {{.SelectedState}} pull requests found.</p>
{{else}}
<div id="pull-list">
{{template "cards" .}}
</div>
{{end}}
{{end}}