detached 302b124

#28 feat(web): list running CI runs in the inbox and open it with Shift+I

state
merged · 801147f · squash
branch
feat/inbox-runs → main
opened
bnema ·
updated

The owner's inbox lists queued and in-progress CI runs in a Running section (after Awaiting moderation), with a running count, the ?repo= filter, and live refresh on run status changes. CI off: no section.

Shift+I opens the inbox from any page for the signed-in owner; lowercase i still opens the issues tab. The help dialog and the inbox button announce it.

Checks: go build, go vet, go test ./internal/..., node --test jstest (199 pass). Wrap-up review (go + js) done; one a11y finding fixed.

CommitSubjectAuthorDateSignatureStatus
302b124feat(web): announce the Shift+I shortcut on the inbox buttonbriceGPG Verified
0f18a24feat(web): list running CI runs in the inbox and open it with Shift+IbriceGPG Verified

Checks 4

52 files · +902 -425
4/4
M docs/issues.md +3 -1
@@ -50,7 +50,9 @@ Limits: the 100 most recent commits of the merge request, 16 KiB of each text, 1
5050
5151 The signed-in owner has an Inbox at `/-/inbox`, reached from the **Inbox** button at the top left of the home page, which shows the number of open items. It lists the open merge requests and the open issues of every repository, most recently updated first. The counters at the top (`N merge requests · M issues`) always count everything; `?repo=<name>` restricts the two lists to one repository, and the repository links under the counters set it. Repositories with issues off contribute no issues.
5252
53-The page updates live: merge request and issue events of any repository refresh the counters and the lists. Anyone who is not the signed-in owner, including a token, gets the same 404 as for an unknown page, and the same answer for the `owner` event stream it follows.
53+The **Running** section, after **Awaiting moderation**, lists queued and in-progress CI runs newest first, with links to each run, its repository, ref, and start time. The `N running` counter counts every repository; the repository filter also applies to this section. **Shift+I** (`I`) opens the inbox from any page for the signed-in owner, unless single-key shortcuts are off; lowercase `i` still opens the issues tab.
54+
55+The page updates live: run status changes, merge request and issue events of any repository refresh the counters and the lists. Anyone who is not the signed-in owner, including a token, gets the same 404 as for an unknown page, and the same answer for the `owner` event stream it follows.
5456
5557 ## Public form and moderation
5658
@@ -50,7 +50,9 @@ Limits: the 100 most recent commits of the merge request, 16 KiB of each text, 1
50 50
51 The signed-in owner has an Inbox at `/-/inbox`, reached from the **Inbox** button at the top left of the home page, which shows the number of open items. It lists the open merge requests and the open issues of every repository, most recently updated first. The counters at the top (`N merge requests · M issues`) always count everything; `?repo=<name>` restricts the two lists to one repository, and the repository links under the counters set it. Repositories with issues off contribute no issues.51 The signed-in owner has an Inbox at `/-/inbox`, reached from the **Inbox** button at the top left of the home page, which shows the number of open items. It lists the open merge requests and the open issues of every repository, most recently updated first. The counters at the top (`N merge requests · M issues`) always count everything; `?repo=<name>` restricts the two lists to one repository, and the repository links under the counters set it. Repositories with issues off contribute no issues.
52 52
53-The page updates live: merge request and issue events of any repository refresh the counters and the lists. Anyone who is not the signed-in owner, including a token, gets the same 404 as for an unknown page, and the same answer for the `owner` event stream it follows.53+The **Running** section, after **Awaiting moderation**, lists queued and in-progress CI runs newest first, with links to each run, its repository, ref, and start time. The `N running` counter counts every repository; the repository filter also applies to this section. **Shift+I** (`I`) opens the inbox from any page for the signed-in owner, unless single-key shortcuts are off; lowercase `i` still opens the issues tab.
54+
55+The page updates live: run status changes, merge request and issue events of any repository refresh the counters and the lists. Anyone who is not the signed-in owner, including a token, gets the same 404 as for an unknown page, and the same answer for the `owner` event stream it follows.
54 56
55 ## Public form and moderation57 ## Public form and moderation
56 58
M docs/releases.md +5 -44
@@ -57,60 +57,21 @@ the S3 endpoint. Stored-token publishers need `release:write` and, for private
5757 repository reads, `repo:read`. The owner component is `ERMITE_OWNER` (`owner` by
5858 default).
5959
60-GoReleaser does not read `GITHUB_API_URL` or `GITHUB_SERVER_URL` by itself, so
61-template `github_urls` from them (replace the fallback host and repository):
60+GoReleaser configuration (replace the host and repository):
6261
6362 ```yaml
6463 version: 2
65-# In CI the runner sets GITHUB_API_URL and GITHUB_SERVER_URL to the address the
66-# job can reach; the public URLs are the fallback for a local run.
6764 github_urls:
68- api: '{{ or (index .Env "GITHUB_API_URL") "https://git.example.org/-/github/api" }}/'
69- upload: '{{ or (index .Env "GITHUB_API_URL") "https://git.example.org/-/github/api" }}/uploads/'
70- download: '{{ or (index .Env "GITHUB_SERVER_URL") "https://git.example.org" }}/'
65+ api: https://git.example.org/-/github/api/
66+ upload: https://git.example.org/-/github/api/uploads/
67+ download: https://git.example.org/
7168 release:
7269 github:
7370 owner: owner
7471 name: app
7572 ```
7673
77-In a CI job the runner rewrites the server and API URLs to an origin the job
78-can reach, which may differ from the public URL (for example `http://ermite:7341`
79-with a relayed forge). Sandboxes block private and CGNAT ranges, so a job that
80-targets only the public URL times out (`dial tcp 100.x:443: i/o timeout`). A
81-plain-http relay needs no TLS option. The API base gets `api/v3/` appended by
82-the client; ermite accepts that alias. Locally, run
83-`GITHUB_TOKEN=<token> goreleaser release --clean` from a tagged checkout; the
84-fallbacks apply.
85-
86-Workflow:
87-
88-```yaml
89-name: release
90-on:
91- push:
92- tags: ['v*']
93-permissions:
94- contents: write
95-jobs:
96- release:
97- runs-on: ubuntu-latest
98- steps:
99- - uses: actions/checkout@v4
100- with:
101- fetch-depth: 0
102- - uses: actions/setup-go@v5
103- with:
104- go-version-file: go.mod
105- - uses: goreleaser/goreleaser-action@v6
106- with:
107- args: release --clean
108- env:
109- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110-```
111-
112-An existing GitHub workflow must be enabled on ermite:
113-`ermite workflow enable <repo> .github/workflows/release.yml`.
74+Run `GITHUB_TOKEN=<token> goreleaser release --clean` from a tagged checkout.
11475
11576 On an ermite runner, the job supplies `GITHUB_API_URL`, `GITHUB_SERVER_URL` and
11677 `GITHUB_TOKEN`; no endpoint override is needed for action-gh-release:
@@ -57,60 +57,21 @@ the S3 endpoint. Stored-token publishers need `release:write` and, for private
57 repository reads, `repo:read`. The owner component is `ERMITE_OWNER` (`owner` by57 repository reads, `repo:read`. The owner component is `ERMITE_OWNER` (`owner` by
58 default).58 default).
59 59
60-GoReleaser does not read `GITHUB_API_URL` or `GITHUB_SERVER_URL` by itself, so60+GoReleaser configuration (replace the host and repository):
61-template `github_urls` from them (replace the fallback host and repository):
62 61
63 ```yaml62 ```yaml
64 version: 263 version: 2
65-# In CI the runner sets GITHUB_API_URL and GITHUB_SERVER_URL to the address the
66-# job can reach; the public URLs are the fallback for a local run.
67 github_urls:64 github_urls:
68- api: '{{ or (index .Env "GITHUB_API_URL") "https://git.example.org/-/github/api" }}/'65+ api: https://git.example.org/-/github/api/
69- upload: '{{ or (index .Env "GITHUB_API_URL") "https://git.example.org/-/github/api" }}/uploads/'66+ upload: https://git.example.org/-/github/api/uploads/
70- download: '{{ or (index .Env "GITHUB_SERVER_URL") "https://git.example.org" }}/'67+ download: https://git.example.org/
71 release:68 release:
72 github:69 github:
73 owner: owner70 owner: owner
74 name: app71 name: app
75 ```72 ```
76 73
77-In a CI job the runner rewrites the server and API URLs to an origin the job74+Run `GITHUB_TOKEN=<token> goreleaser release --clean` from a tagged checkout.
78-can reach, which may differ from the public URL (for example `http://ermite:7341`
79-with a relayed forge). Sandboxes block private and CGNAT ranges, so a job that
80-targets only the public URL times out (`dial tcp 100.x:443: i/o timeout`). A
81-plain-http relay needs no TLS option. The API base gets `api/v3/` appended by
82-the client; ermite accepts that alias. Locally, run
83-`GITHUB_TOKEN=<token> goreleaser release --clean` from a tagged checkout; the
84-fallbacks apply.
85-
86-Workflow:
87-
88-```yaml
89-name: release
90-on:
91- push:
92- tags: ['v*']
93-permissions:
94- contents: write
95-jobs:
96- release:
97- runs-on: ubuntu-latest
98- steps:
99- - uses: actions/checkout@v4
100- with:
101- fetch-depth: 0
102- - uses: actions/setup-go@v5
103- with:
104- go-version-file: go.mod
105- - uses: goreleaser/goreleaser-action@v6
106- with:
107- args: release --clean
108- env:
109- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110-```
111-
112-An existing GitHub workflow must be enabled on ermite:
113-`ermite workflow enable <repo> .github/workflows/release.yml`.
114 75
115 On an ermite runner, the job supplies `GITHUB_API_URL`, `GITHUB_SERVER_URL` and76 On an ermite runner, the job supplies `GITHUB_API_URL`, `GITHUB_SERVER_URL` and
116 `GITHUB_TOKEN`; no endpoint override is needed for action-gh-release:77 `GITHUB_TOKEN`; no endpoint override is needed for action-gh-release:
M internal/adapters/web/inbox.go +25 -3
@@ -67,8 +67,17 @@ type InboxRepoLink struct {
6767 Current bool
6868 }
6969
70-// InboxPage is the inbox: the counters, the filter and the two lists.
70+// InboxRunRow adds repository and start time to the Actions run display.
71+type InboxRunRow struct {
72+ RunRow
73+ Repo, RepoHref, When, WhenAt string
74+}
75+
76+// InboxPage is the inbox: counters, repository filter and item lists.
7177 type InboxPage struct {
78+ Running int
79+ RunsEnabled bool
80+ Runs []InboxRunRow
7281 // MergeRequests and Issues count every open item, whatever the filter.
7382 MergeRequests, Issues int
7483 // PendingCount counts every issue awaiting moderation.
@@ -106,6 +115,19 @@ func inboxFilter(r *http.Request) (domain.RepoName, error) {
106115 func (s *Server) inboxPage(ov ports.InboxOverview, filter domain.RepoName) InboxPage {
107116 now := s.cfg.Now()
108117 p := InboxPage{MergeRequests: ov.Counts.MergeRequests, Issues: ov.Counts.Issues, PendingCount: ov.Counts.Pending, Filter: filter.String()}
118+ p.Running, p.RunsEnabled = ov.Counts.Running, ov.RunsEnabled
119+ for _, run := range ov.Runs {
120+ r := InboxRunRow{RunRow: s.runRow(run.Repo.String(), run, now), Repo: run.Repo.String(), RepoHref: repoHref(run.Repo.String())}
121+ if run.Status == domain.CIInProgress {
122+ r.State = "in progress"
123+ }
124+ ts := run.StartedAt
125+ if ts.IsZero() {
126+ ts = run.CreatedAt
127+ }
128+ r.When, r.WhenAt = whenOf(now, ts)
129+ p.Runs = append(p.Runs, r)
130+ }
109131 for _, pi := range ov.Pending {
110132 p.Pending = append(p.Pending, s.pendingRow(now, pi, filter))
111133 }
@@ -266,7 +288,7 @@ func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment
266288 switch we.Event.(type) {
267289 case domain.MergeRequestOpened, domain.MergeRequestMerged, domain.MergeRequestClosed, domain.MergeRequestReady, domain.CommentAdded, domain.CommentEdited, domain.CommentDeleted, domain.CommentResolved,
268290 domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented, domain.IssueSubmitted, domain.IssuePendingRemoved,
269- domain.RepoUpdated, domain.RepoDeleted:
291+ domain.RepoUpdated, domain.RepoDeleted, domain.RunUpdated:
270292 default:
271293 return nil, nil
272294 }
@@ -283,7 +305,7 @@ func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment
283305 }
284306 p := l.s.inboxPage(ov, filter)
285307 var out []fragment
286- for _, c := range []templ.Component{InboxCounters(p), InboxRepos(p), InboxPending(p), InboxMRs(p), InboxIssues(p)} {
308+ for _, c := range []templ.Component{InboxCounters(p), InboxRepos(p), InboxPending(p), InboxRuns(p), InboxMRs(p), InboxIssues(p)} {
287309 f, err := renderFragment(ctx, inboxEvent, c)
288310 if err != nil {
289311 return nil, err
@@ -67,8 +67,17 @@ type InboxRepoLink struct {
67 Current bool67 Current bool
68 }68 }
69 69
70-// InboxPage is the inbox: the counters, the filter and the two lists.70+// InboxRunRow adds repository and start time to the Actions run display.
71+type InboxRunRow struct {
72+ RunRow
73+ Repo, RepoHref, When, WhenAt string
74+}
75+
76+// InboxPage is the inbox: counters, repository filter and item lists.
71 type InboxPage struct {77 type InboxPage struct {
78+ Running int
79+ RunsEnabled bool
80+ Runs []InboxRunRow
72 // MergeRequests and Issues count every open item, whatever the filter.81 // MergeRequests and Issues count every open item, whatever the filter.
73 MergeRequests, Issues int82 MergeRequests, Issues int
74 // PendingCount counts every issue awaiting moderation.83 // PendingCount counts every issue awaiting moderation.
@@ -106,6 +115,19 @@ func inboxFilter(r *http.Request) (domain.RepoName, error) {
106 func (s *Server) inboxPage(ov ports.InboxOverview, filter domain.RepoName) InboxPage {115 func (s *Server) inboxPage(ov ports.InboxOverview, filter domain.RepoName) InboxPage {
107 now := s.cfg.Now()116 now := s.cfg.Now()
108 p := InboxPage{MergeRequests: ov.Counts.MergeRequests, Issues: ov.Counts.Issues, PendingCount: ov.Counts.Pending, Filter: filter.String()}117 p := InboxPage{MergeRequests: ov.Counts.MergeRequests, Issues: ov.Counts.Issues, PendingCount: ov.Counts.Pending, Filter: filter.String()}
118+ p.Running, p.RunsEnabled = ov.Counts.Running, ov.RunsEnabled
119+ for _, run := range ov.Runs {
120+ r := InboxRunRow{RunRow: s.runRow(run.Repo.String(), run, now), Repo: run.Repo.String(), RepoHref: repoHref(run.Repo.String())}
121+ if run.Status == domain.CIInProgress {
122+ r.State = "in progress"
123+ }
124+ ts := run.StartedAt
125+ if ts.IsZero() {
126+ ts = run.CreatedAt
127+ }
128+ r.When, r.WhenAt = whenOf(now, ts)
129+ p.Runs = append(p.Runs, r)
130+ }
109 for _, pi := range ov.Pending {131 for _, pi := range ov.Pending {
110 p.Pending = append(p.Pending, s.pendingRow(now, pi, filter))132 p.Pending = append(p.Pending, s.pendingRow(now, pi, filter))
111 }133 }
@@ -266,7 +288,7 @@ func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment
266 switch we.Event.(type) {288 switch we.Event.(type) {
267 case domain.MergeRequestOpened, domain.MergeRequestMerged, domain.MergeRequestClosed, domain.MergeRequestReady, domain.CommentAdded, domain.CommentEdited, domain.CommentDeleted, domain.CommentResolved,289 case domain.MergeRequestOpened, domain.MergeRequestMerged, domain.MergeRequestClosed, domain.MergeRequestReady, domain.CommentAdded, domain.CommentEdited, domain.CommentDeleted, domain.CommentResolved,
268 domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented, domain.IssueSubmitted, domain.IssuePendingRemoved,290 domain.IssueOpened, domain.IssueClosed, domain.IssueReopened, domain.IssueCommented, domain.IssueSubmitted, domain.IssuePendingRemoved,
269- domain.RepoUpdated, domain.RepoDeleted:291+ domain.RepoUpdated, domain.RepoDeleted, domain.RunUpdated:
270 default:292 default:
271 return nil, nil293 return nil, nil
272 }294 }
@@ -283,7 +305,7 @@ func (l *liveStream) inbox(ctx context.Context, we ports.WatchEvent) ([]fragment
283 }305 }
284 p := l.s.inboxPage(ov, filter)306 p := l.s.inboxPage(ov, filter)
285 var out []fragment307 var out []fragment
286- for _, c := range []templ.Component{InboxCounters(p), InboxRepos(p), InboxPending(p), InboxMRs(p), InboxIssues(p)} {308+ for _, c := range []templ.Component{InboxCounters(p), InboxRepos(p), InboxPending(p), InboxRuns(p), InboxMRs(p), InboxIssues(p)} {
287 f, err := renderFragment(ctx, inboxEvent, c)309 f, err := renderFragment(ctx, inboxEvent, c)
288 if err != nil {310 if err != nil {
289 return nil, err311 return nil, err
M internal/adapters/web/inbox.templ +34 -1
@@ -12,6 +12,7 @@ templ Inbox(l Layout, p InboxPage) {
1212 @InboxCounters(p)
1313 @InboxRepos(p)
1414 @InboxPending(p)
15+ @InboxRuns(p)
1516 @InboxMRs(p)
1617 @InboxIssues(p)
1718 </div>
@@ -20,7 +21,7 @@ templ Inbox(l Layout, p InboxPage) {
2021
2122 templ InboxCounters(p InboxPage) {
2223 <p id="inbox-counts" class="inbox-counts">
23- <strong>{ itoa(p.MergeRequests) }</strong> merge requests · <strong>{ itoa(p.Issues) }</strong> issues · <strong>{ itoa(p.PendingCount) }</strong> awaiting moderation
24+ <strong>{ itoa(p.MergeRequests) }</strong> merge requests · <strong>{ itoa(p.Issues) }</strong> issues · <strong>{ itoa(p.PendingCount) }</strong> awaiting moderation · <strong>{ itoa(p.Running) }</strong> running
2425 </p>
2526 }
2627
@@ -113,3 +114,35 @@ templ inboxRows(rows []InboxRow, label string) {
113114 </table>
114115 }
115116 }
117+
118+// InboxRuns stays as an empty fragment when CI is disabled.
119+templ InboxRuns(p InboxPage) {
120+ <section id="inbox-runs" hidden?={ !p.RunsEnabled }
121+ if p.RunsEnabled {
122+ aria-labelledby="inbox-runs-h"
123+ }
124+ >
125+ if p.RunsEnabled {
126+ <h2 id="inbox-runs-h" class="rule-h"><span>Running</span><span class="count">{ itoa(len(p.Runs)) }</span></h2>
127+ if len(p.Runs) == 0 {
128+ <p class="lede dim">no runs in progress.</p>
129+ } else {
130+ <table class="list mrs" aria-label="Running">
131+ <tbody data-rows>
132+ for _, r := range p.Runs {
133+ <tr>
134+ <td class="c-st">@CheckIcon(r.Kind, r.State)<span class="dim">{ r.State }</span></td>
135+ <td class="c-subject"><a href={ templ.SafeURL(r.Href) }>{ r.Workflow }{ " " }{ r.Number }</a> <a class="mute" href={ templ.SafeURL(r.RepoHref) }>{ r.Repo }</a> <span class="dim">{ r.Ref }{ " " }{ r.Event }</span></td>
136+ <td class="c-when nowrap dim">
137+ if r.WhenAt != "" {
138+ <time datetime={ r.WhenAt } title={ r.WhenAt }>{ r.When }</time>
139+ }
140+ </td>
141+ </tr>
142+ }
143+ </tbody>
144+ </table>
145+ }
146+ }
147+ </section>
148+}
@@ -12,6 +12,7 @@ templ Inbox(l Layout, p InboxPage) {
12 @InboxCounters(p)12 @InboxCounters(p)
13 @InboxRepos(p)13 @InboxRepos(p)
14 @InboxPending(p)14 @InboxPending(p)
15+ @InboxRuns(p)
15 @InboxMRs(p)16 @InboxMRs(p)
16 @InboxIssues(p)17 @InboxIssues(p)
17 </div>18 </div>
@@ -20,7 +21,7 @@ templ Inbox(l Layout, p InboxPage) {
20 21
21 templ InboxCounters(p InboxPage) {22 templ InboxCounters(p InboxPage) {
22 <p id="inbox-counts" class="inbox-counts">23 <p id="inbox-counts" class="inbox-counts">
23- <strong>{ itoa(p.MergeRequests) }</strong> merge requests · <strong>{ itoa(p.Issues) }</strong> issues · <strong>{ itoa(p.PendingCount) }</strong> awaiting moderation24+ <strong>{ itoa(p.MergeRequests) }</strong> merge requests · <strong>{ itoa(p.Issues) }</strong> issues · <strong>{ itoa(p.PendingCount) }</strong> awaiting moderation · <strong>{ itoa(p.Running) }</strong> running
24 </p>25 </p>
25 }26 }
26 27
@@ -113,3 +114,35 @@ templ inboxRows(rows []InboxRow, label string) {
113 </table>114 </table>
114 }115 }
115 }116 }
117+
118+// InboxRuns stays as an empty fragment when CI is disabled.
119+templ InboxRuns(p InboxPage) {
120+ <section id="inbox-runs" hidden?={ !p.RunsEnabled }
121+ if p.RunsEnabled {
122+ aria-labelledby="inbox-runs-h"
123+ }
124+ >
125+ if p.RunsEnabled {
126+ <h2 id="inbox-runs-h" class="rule-h"><span>Running</span><span class="count">{ itoa(len(p.Runs)) }</span></h2>
127+ if len(p.Runs) == 0 {
128+ <p class="lede dim">no runs in progress.</p>
129+ } else {
130+ <table class="list mrs" aria-label="Running">
131+ <tbody data-rows>
132+ for _, r := range p.Runs {
133+ <tr>
134+ <td class="c-st">@CheckIcon(r.Kind, r.State)<span class="dim">{ r.State }</span></td>
135+ <td class="c-subject"><a href={ templ.SafeURL(r.Href) }>{ r.Workflow }{ " " }{ r.Number }</a> <a class="mute" href={ templ.SafeURL(r.RepoHref) }>{ r.Repo }</a> <span class="dim">{ r.Ref }{ " " }{ r.Event }</span></td>
136+ <td class="c-when nowrap dim">
137+ if r.WhenAt != "" {
138+ <time datetime={ r.WhenAt } title={ r.WhenAt }>{ r.When }</time>
139+ }
140+ </td>
141+ </tr>
142+ }
143+ </tbody>
144+ </table>
145+ }
146+ }
147+ </section>
148+}
M internal/adapters/web/inbox_templ.go +451 -173
@@ -62,6 +62,10 @@ func Inbox(l Layout, p InboxPage) templ.Component {
6262 if templ_7745c5c3_Err != nil {
6363 return templ_7745c5c3_Err
6464 }
65+ templ_7745c5c3_Err = InboxRuns(p).Render(ctx, templ_7745c5c3_Buffer)
66+ if templ_7745c5c3_Err != nil {
67+ return templ_7745c5c3_Err
68+ }
6569 templ_7745c5c3_Err = InboxMRs(p).Render(ctx, templ_7745c5c3_Buffer)
6670 if templ_7745c5c3_Err != nil {
6771 return templ_7745c5c3_Err
@@ -112,7 +116,7 @@ func InboxCounters(p InboxPage) templ.Component {
112116 var templ_7745c5c3_Var4 string
113117 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.MergeRequests))
114118 if templ_7745c5c3_Err != nil {
115- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 23, Col: 33}
119+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 33}
116120 }
117121 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
118122 if templ_7745c5c3_Err != nil {
@@ -125,7 +129,7 @@ func InboxCounters(p InboxPage) templ.Component {
125129 var templ_7745c5c3_Var5 string
126130 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Issues))
127131 if templ_7745c5c3_Err != nil {
128- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 23, Col: 87}
132+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 87}
129133 }
130134 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
131135 if templ_7745c5c3_Err != nil {
@@ -138,13 +142,26 @@ func InboxCounters(p InboxPage) templ.Component {
138142 var templ_7745c5c3_Var6 string
139143 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))
140144 if templ_7745c5c3_Err != nil {
141- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 23, Col: 139}
145+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 139}
142146 }
143147 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
144148 if templ_7745c5c3_Err != nil {
145149 return templ_7745c5c3_Err
146150 }
147- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</strong> awaiting moderation</p>")
151+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</strong> awaiting moderation · <strong>")
152+ if templ_7745c5c3_Err != nil {
153+ return templ_7745c5c3_Err
154+ }
155+ var templ_7745c5c3_Var7 string
156+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Running))
157+ if templ_7745c5c3_Err != nil {
158+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 199}
159+ }
160+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
161+ if templ_7745c5c3_Err != nil {
162+ return templ_7745c5c3_Err
163+ }
164+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</strong> running</p>")
148165 if templ_7745c5c3_Err != nil {
149166 return templ_7745c5c3_Err
150167 }
@@ -168,58 +185,58 @@ func InboxRepos(p InboxPage) templ.Component {
168185 }()
169186 }
170187 ctx = templ.InitializeContext(ctx)
171- templ_7745c5c3_Var7 := templ.GetChildren(ctx)
172- if templ_7745c5c3_Var7 == nil {
173- templ_7745c5c3_Var7 = templ.NopComponent
188+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
189+ if templ_7745c5c3_Var8 == nil {
190+ templ_7745c5c3_Var8 = templ.NopComponent
174191 }
175192 ctx = templ.ClearChildren(ctx)
176- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<nav id=\"inbox-repos\" class=\"since\" aria-label=\"Repository\">")
193+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<nav id=\"inbox-repos\" class=\"since\" aria-label=\"Repository\">")
177194 if templ_7745c5c3_Err != nil {
178195 return templ_7745c5c3_Err
179196 }
180197 for _, r := range p.Repos {
181- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<a href=\"")
198+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a href=\"")
182199 if templ_7745c5c3_Err != nil {
183200 return templ_7745c5c3_Err
184201 }
185- var templ_7745c5c3_Var8 templ.SafeURL
186- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.Href))
202+ var templ_7745c5c3_Var9 templ.SafeURL
203+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.Href))
187204 if templ_7745c5c3_Err != nil {
188- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 31, Col: 32}
205+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 32, Col: 32}
189206 }
190- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
207+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
191208 if templ_7745c5c3_Err != nil {
192209 return templ_7745c5c3_Err
193210 }
194- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"")
211+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"")
195212 if templ_7745c5c3_Err != nil {
196213 return templ_7745c5c3_Err
197214 }
198215 if r.Current {
199- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " aria-current=\"page\"")
216+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " aria-current=\"page\"")
200217 if templ_7745c5c3_Err != nil {
201218 return templ_7745c5c3_Err
202219 }
203220 }
204- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, ">")
221+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, ">")
205222 if templ_7745c5c3_Err != nil {
206223 return templ_7745c5c3_Err
207224 }
208- var templ_7745c5c3_Var9 string
209- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(r.Label)
225+ var templ_7745c5c3_Var10 string
226+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(r.Label)
210227 if templ_7745c5c3_Err != nil {
211- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 35, Col: 13}
228+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 36, Col: 13}
212229 }
213- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
230+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
214231 if templ_7745c5c3_Err != nil {
215232 return templ_7745c5c3_Err
216233 }
217- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a>")
234+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a>")
218235 if templ_7745c5c3_Err != nil {
219236 return templ_7745c5c3_Err
220237 }
221238 }
222- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</nav>")
239+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</nav>")
223240 if templ_7745c5c3_Err != nil {
224241 return templ_7745c5c3_Err
225242 }
@@ -246,219 +263,219 @@ func InboxPending(p InboxPage) templ.Component {
246263 }()
247264 }
248265 ctx = templ.InitializeContext(ctx)
249- templ_7745c5c3_Var10 := templ.GetChildren(ctx)
250- if templ_7745c5c3_Var10 == nil {
251- templ_7745c5c3_Var10 = templ.NopComponent
266+ templ_7745c5c3_Var11 := templ.GetChildren(ctx)
267+ if templ_7745c5c3_Var11 == nil {
268+ templ_7745c5c3_Var11 = templ.NopComponent
252269 }
253270 ctx = templ.ClearChildren(ctx)
254- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<section id=\"inbox-pending\" aria-labelledby=\"inbox-pending-h\"><h2 id=\"inbox-pending-h\" class=\"rule-h\"><span>Awaiting moderation</span><span class=\"count\">")
271+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<section id=\"inbox-pending\" aria-labelledby=\"inbox-pending-h\"><h2 id=\"inbox-pending-h\" class=\"rule-h\"><span>Awaiting moderation</span><span class=\"count\">")
255272 if templ_7745c5c3_Err != nil {
256273 return templ_7745c5c3_Err
257274 }
258- var templ_7745c5c3_Var11 string
259- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))
275+ var templ_7745c5c3_Var12 string
276+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))
260277 if templ_7745c5c3_Err != nil {
261- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 45, Col: 116}
278+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 46, Col: 116}
262279 }
263- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
280+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
264281 if templ_7745c5c3_Err != nil {
265282 return templ_7745c5c3_Err
266283 }
267- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</span></h2>")
284+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span></h2>")
268285 if templ_7745c5c3_Err != nil {
269286 return templ_7745c5c3_Err
270287 }
271288 if len(p.Pending) > 0 {
272- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<ul class=\"pending-list\">")
289+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<ul class=\"pending-list\">")
273290 if templ_7745c5c3_Err != nil {
274291 return templ_7745c5c3_Err
275292 }
276293 for _, m := range p.Pending {
277- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<li class=\"pending\"><div class=\"p-head\"><a href=\"")
294+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<li class=\"pending\"><div class=\"p-head\"><a href=\"")
278295 if templ_7745c5c3_Err != nil {
279296 return templ_7745c5c3_Err
280297 }
281- var templ_7745c5c3_Var12 templ.SafeURL
282- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))
298+ var templ_7745c5c3_Var13 templ.SafeURL
299+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))
283300 if templ_7745c5c3_Err != nil {
284- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 51, Col: 42}
301+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 52, Col: 42}
285302 }
286- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
303+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
287304 if templ_7745c5c3_Err != nil {
288305 return templ_7745c5c3_Err
289306 }
290- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">")
307+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\">")
291308 if templ_7745c5c3_Err != nil {
292309 return templ_7745c5c3_Err
293310 }
294- var templ_7745c5c3_Var13 string
295- templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)
311+ var templ_7745c5c3_Var14 string
312+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)
296313 if templ_7745c5c3_Err != nil {
297- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 51, Col: 53}
314+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 52, Col: 53}
298315 }
299- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
316+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
300317 if templ_7745c5c3_Err != nil {
301318 return templ_7745c5c3_Err
302319 }
303- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a> <span>")
320+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</a> <span>")
304321 if templ_7745c5c3_Err != nil {
305322 return templ_7745c5c3_Err
306323 }
307- var templ_7745c5c3_Var14 string
308- templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(m.Author)
324+ var templ_7745c5c3_Var15 string
325+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(m.Author)
309326 if templ_7745c5c3_Err != nil {
310- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 52, Col: 23}
327+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 53, Col: 23}
311328 }
312- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
329+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
313330 if templ_7745c5c3_Err != nil {
314331 return templ_7745c5c3_Err
315332 }
316- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</span> ")
333+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</span> ")
317334 if templ_7745c5c3_Err != nil {
318335 return templ_7745c5c3_Err
319336 }
320337 if m.WhenAt != "" {
321- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<time datetime=\"")
338+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<time datetime=\"")
322339 if templ_7745c5c3_Err != nil {
323340 return templ_7745c5c3_Err
324341 }
325- var templ_7745c5c3_Var15 string
326- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
342+ var templ_7745c5c3_Var16 string
343+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
327344 if templ_7745c5c3_Err != nil {
328- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 54, Col: 33}
345+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 55, Col: 33}
329346 }
330- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var15)
347+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16)
331348 if templ_7745c5c3_Err != nil {
332349 return templ_7745c5c3_Err
333350 }
334- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" title=\"")
351+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" title=\"")
335352 if templ_7745c5c3_Err != nil {
336353 return templ_7745c5c3_Err
337354 }
338- var templ_7745c5c3_Var16 string
339- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
355+ var templ_7745c5c3_Var17 string
356+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
340357 if templ_7745c5c3_Err != nil {
341- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 54, Col: 52}
358+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 55, Col: 52}
342359 }
343- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16)
360+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17)
344361 if templ_7745c5c3_Err != nil {
345362 return templ_7745c5c3_Err
346363 }
347- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">")
364+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\">")
348365 if templ_7745c5c3_Err != nil {
349366 return templ_7745c5c3_Err
350367 }
351- var templ_7745c5c3_Var17 string
352- templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)
368+ var templ_7745c5c3_Var18 string
369+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)
353370 if templ_7745c5c3_Err != nil {
354- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 54, Col: 63}
371+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 55, Col: 63}
355372 }
356- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
373+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
357374 if templ_7745c5c3_Err != nil {
358375 return templ_7745c5c3_Err
359376 }
360- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</time>")
377+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</time>")
361378 if templ_7745c5c3_Err != nil {
362379 return templ_7745c5c3_Err
363380 }
364381 }
365- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div><p class=\"p-title\">")
382+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</div><p class=\"p-title\">")
366383 if templ_7745c5c3_Err != nil {
367384 return templ_7745c5c3_Err
368385 }
369- var templ_7745c5c3_Var18 string
370- templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)
386+ var templ_7745c5c3_Var19 string
387+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)
371388 if templ_7745c5c3_Err != nil {
372- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 57, Col: 34}
389+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 58, Col: 34}
373390 }
374- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
391+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
375392 if templ_7745c5c3_Err != nil {
376393 return templ_7745c5c3_Err
377394 }
378- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</p>")
395+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</p>")
379396 if templ_7745c5c3_Err != nil {
380397 return templ_7745c5c3_Err
381398 }
382399 if m.Preview != "" {
383- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<p class=\"p-body\">")
400+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<p class=\"p-body\">")
384401 if templ_7745c5c3_Err != nil {
385402 return templ_7745c5c3_Err
386403 }
387- var templ_7745c5c3_Var19 string
388- templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(m.Preview)
404+ var templ_7745c5c3_Var20 string
405+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(m.Preview)
389406 if templ_7745c5c3_Err != nil {
390- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 59, Col: 36}
407+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 60, Col: 36}
391408 }
392- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
409+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
393410 if templ_7745c5c3_Err != nil {
394411 return templ_7745c5c3_Err
395412 }
396- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</p>")
413+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</p>")
397414 if templ_7745c5c3_Err != nil {
398415 return templ_7745c5c3_Err
399416 }
400417 }
401418 if m.Approve != "" {
402- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"p-btns\"><form method=\"post\" action=\"")
419+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<div class=\"p-btns\"><form method=\"post\" action=\"")
403420 if templ_7745c5c3_Err != nil {
404421 return templ_7745c5c3_Err
405422 }
406- var templ_7745c5c3_Var20 templ.SafeURL
407- templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Approve))
423+ var templ_7745c5c3_Var21 templ.SafeURL
424+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Approve))
408425 if templ_7745c5c3_Err != nil {
409- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 63, Col: 61}
426+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 64, Col: 61}
410427 }
411- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
428+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
412429 if templ_7745c5c3_Err != nil {
413430 return templ_7745c5c3_Err
414431 }
415- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\"><button type=\"submit\" class=\"btn primary\">Approve</button></form><form method=\"post\" action=\"")
432+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\"><button type=\"submit\" class=\"btn primary\">Approve</button></form><form method=\"post\" action=\"")
416433 if templ_7745c5c3_Err != nil {
417434 return templ_7745c5c3_Err
418435 }
419- var templ_7745c5c3_Var21 templ.SafeURL
420- templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Reject))
436+ var templ_7745c5c3_Var22 templ.SafeURL
437+ templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Reject))
421438 if templ_7745c5c3_Err != nil {
422- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 64, Col: 60}
439+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 65, Col: 60}
423440 }
424- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
441+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
425442 if templ_7745c5c3_Err != nil {
426443 return templ_7745c5c3_Err
427444 }
428- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\"><button type=\"submit\" class=\"btn\">Reject</button></form><form method=\"post\" action=\"")
445+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\"><button type=\"submit\" class=\"btn\">Reject</button></form><form method=\"post\" action=\"")
429446 if templ_7745c5c3_Err != nil {
430447 return templ_7745c5c3_Err
431448 }
432- var templ_7745c5c3_Var22 templ.SafeURL
433- templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Ban))
449+ var templ_7745c5c3_Var23 templ.SafeURL
450+ templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Ban))
434451 if templ_7745c5c3_Err != nil {
435- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 65, Col: 57}
452+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 66, Col: 57}
436453 }
437- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
454+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
438455 if templ_7745c5c3_Err != nil {
439456 return templ_7745c5c3_Err
440457 }
441- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\"><button type=\"submit\" class=\"btn danger\">Reject and ban</button></form></div>")
458+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\"><button type=\"submit\" class=\"btn danger\">Reject and ban</button></form></div>")
442459 if templ_7745c5c3_Err != nil {
443460 return templ_7745c5c3_Err
444461 }
445462 }
446- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</li>")
463+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</li>")
447464 if templ_7745c5c3_Err != nil {
448465 return templ_7745c5c3_Err
449466 }
450467 }
451- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</ul>")
468+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</ul>")
452469 if templ_7745c5c3_Err != nil {
453470 return templ_7745c5c3_Err
454471 }
455472 } else {
456- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<p class=\"lede dim\">nothing awaits moderation.</p>")
473+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<p class=\"lede dim\">nothing awaits moderation.</p>")
457474 if templ_7745c5c3_Err != nil {
458475 return templ_7745c5c3_Err
459476 }
460477 }
461- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</section>")
478+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</section>")
462479 if templ_7745c5c3_Err != nil {
463480 return templ_7745c5c3_Err
464481 }
@@ -482,25 +499,25 @@ func InboxMRs(p InboxPage) templ.Component {
482499 }()
483500 }
484501 ctx = templ.InitializeContext(ctx)
485- templ_7745c5c3_Var23 := templ.GetChildren(ctx)
486- if templ_7745c5c3_Var23 == nil {
487- templ_7745c5c3_Var23 = templ.NopComponent
502+ templ_7745c5c3_Var24 := templ.GetChildren(ctx)
503+ if templ_7745c5c3_Var24 == nil {
504+ templ_7745c5c3_Var24 = templ.NopComponent
488505 }
489506 ctx = templ.ClearChildren(ctx)
490- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<section id=\"inbox-mrs\" aria-labelledby=\"inbox-mrs-h\"><h2 id=\"inbox-mrs-h\" class=\"rule-h\"><span>Open merge requests</span><span class=\"count\">")
507+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<section id=\"inbox-mrs\" aria-labelledby=\"inbox-mrs-h\"><h2 id=\"inbox-mrs-h\" class=\"rule-h\"><span>Open merge requests</span><span class=\"count\">")
491508 if templ_7745c5c3_Err != nil {
492509 return templ_7745c5c3_Err
493510 }
494- var templ_7745c5c3_Var24 string
495- templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.MRs)))
511+ var templ_7745c5c3_Var25 string
512+ templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.MRs)))
496513 if templ_7745c5c3_Err != nil {
497- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 79, Col: 108}
514+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 80, Col: 108}
498515 }
499- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
516+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
500517 if templ_7745c5c3_Err != nil {
501518 return templ_7745c5c3_Err
502519 }
503- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</span></h2>")
520+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</span></h2>")
504521 if templ_7745c5c3_Err != nil {
505522 return templ_7745c5c3_Err
506523 }
@@ -509,12 +526,12 @@ func InboxMRs(p InboxPage) templ.Component {
509526 return templ_7745c5c3_Err
510527 }
511528 if len(p.MRs) == 0 {
512- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<p class=\"lede dim\">no open merge requests.</p>")
529+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<p class=\"lede dim\">no open merge requests.</p>")
513530 if templ_7745c5c3_Err != nil {
514531 return templ_7745c5c3_Err
515532 }
516533 }
517- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</section>")
534+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</section>")
518535 if templ_7745c5c3_Err != nil {
519536 return templ_7745c5c3_Err
520537 }
@@ -538,25 +555,25 @@ func InboxIssues(p InboxPage) templ.Component {
538555 }()
539556 }
540557 ctx = templ.InitializeContext(ctx)
541- templ_7745c5c3_Var25 := templ.GetChildren(ctx)
542- if templ_7745c5c3_Var25 == nil {
543- templ_7745c5c3_Var25 = templ.NopComponent
558+ templ_7745c5c3_Var26 := templ.GetChildren(ctx)
559+ if templ_7745c5c3_Var26 == nil {
560+ templ_7745c5c3_Var26 = templ.NopComponent
544561 }
545562 ctx = templ.ClearChildren(ctx)
546- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<section id=\"inbox-issues\" aria-labelledby=\"inbox-issues-h\"><h2 id=\"inbox-issues-h\" class=\"rule-h\"><span>Open issues</span><span class=\"count\">")
563+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<section id=\"inbox-issues\" aria-labelledby=\"inbox-issues-h\"><h2 id=\"inbox-issues-h\" class=\"rule-h\"><span>Open issues</span><span class=\"count\">")
547564 if templ_7745c5c3_Err != nil {
548565 return templ_7745c5c3_Err
549566 }
550- var templ_7745c5c3_Var26 string
551- templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.IssueRows)))
567+ var templ_7745c5c3_Var27 string
568+ templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.IssueRows)))
552569 if templ_7745c5c3_Err != nil {
553- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 89, Col: 109}
570+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 90, Col: 109}
554571 }
555- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
572+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
556573 if templ_7745c5c3_Err != nil {
557574 return templ_7745c5c3_Err
558575 }
559- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</span></h2>")
576+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</span></h2>")
560577 if templ_7745c5c3_Err != nil {
561578 return templ_7745c5c3_Err
562579 }
@@ -565,12 +582,12 @@ func InboxIssues(p InboxPage) templ.Component {
565582 return templ_7745c5c3_Err
566583 }
567584 if len(p.IssueRows) == 0 {
568- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<p class=\"lede dim\">no open issues.</p>")
585+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<p class=\"lede dim\">no open issues.</p>")
569586 if templ_7745c5c3_Err != nil {
570587 return templ_7745c5c3_Err
571588 }
572589 }
573- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</section>")
590+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</section>")
574591 if templ_7745c5c3_Err != nil {
575592 return templ_7745c5c3_Err
576593 }
@@ -594,160 +611,160 @@ func inboxRows(rows []InboxRow, label string) templ.Component {
594611 }()
595612 }
596613 ctx = templ.InitializeContext(ctx)
597- templ_7745c5c3_Var27 := templ.GetChildren(ctx)
598- if templ_7745c5c3_Var27 == nil {
599- templ_7745c5c3_Var27 = templ.NopComponent
614+ templ_7745c5c3_Var28 := templ.GetChildren(ctx)
615+ if templ_7745c5c3_Var28 == nil {
616+ templ_7745c5c3_Var28 = templ.NopComponent
600617 }
601618 ctx = templ.ClearChildren(ctx)
602619 if len(rows) > 0 {
603- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<table class=\"list mrs\" aria-label=\"")
620+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<table class=\"list mrs\" aria-label=\"")
604621 if templ_7745c5c3_Err != nil {
605622 return templ_7745c5c3_Err
606623 }
607- var templ_7745c5c3_Var28 string
608- templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.ResolveAttributeValue(label)
624+ var templ_7745c5c3_Var29 string
625+ templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.ResolveAttributeValue(label)
609626 if templ_7745c5c3_Err != nil {
610- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 99, Col: 44}
627+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 100, Col: 44}
611628 }
612- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28)
629+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var29)
613630 if templ_7745c5c3_Err != nil {
614631 return templ_7745c5c3_Err
615632 }
616- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\"><tbody data-rows>")
633+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\"><tbody data-rows>")
617634 if templ_7745c5c3_Err != nil {
618635 return templ_7745c5c3_Err
619636 }
620637 for _, m := range rows {
621- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<tr")
638+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<tr")
622639 if templ_7745c5c3_Err != nil {
623640 return templ_7745c5c3_Err
624641 }
625642 if m.Cursor {
626- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, " data-cursor")
643+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " data-cursor")
627644 if templ_7745c5c3_Err != nil {
628645 return templ_7745c5c3_Err
629646 }
630647 }
631- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " data-state=\"open\"><td class=\"c-n mute\">")
648+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, " data-state=\"open\"><td class=\"c-n mute\">")
632649 if templ_7745c5c3_Err != nil {
633650 return templ_7745c5c3_Err
634651 }
635- var templ_7745c5c3_Var29 string
636- templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(m.Number)
652+ var templ_7745c5c3_Var30 string
653+ templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(m.Number)
637654 if templ_7745c5c3_Err != nil {
638- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 103, Col: 37}
655+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 37}
639656 }
640- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
657+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
641658 if templ_7745c5c3_Err != nil {
642659 return templ_7745c5c3_Err
643660 }
644- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</td><td class=\"c-subject\"><a href=\"")
661+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</td><td class=\"c-subject\"><a href=\"")
645662 if templ_7745c5c3_Err != nil {
646663 return templ_7745c5c3_Err
647664 }
648- var templ_7745c5c3_Var30 templ.SafeURL
649- templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Href))
665+ var templ_7745c5c3_Var31 templ.SafeURL
666+ templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Href))
650667 if templ_7745c5c3_Err != nil {
651- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 59}
668+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 59}
652669 }
653- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
670+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
654671 if templ_7745c5c3_Err != nil {
655672 return templ_7745c5c3_Err
656673 }
657- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "\">")
674+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\">")
658675 if templ_7745c5c3_Err != nil {
659676 return templ_7745c5c3_Err
660677 }
661- var templ_7745c5c3_Var31 string
662- templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)
678+ var templ_7745c5c3_Var32 string
679+ templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)
663680 if templ_7745c5c3_Err != nil {
664- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 71}
681+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 71}
665682 }
666- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
683+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
667684 if templ_7745c5c3_Err != nil {
668685 return templ_7745c5c3_Err
669686 }
670- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</a> <a class=\"mute\" href=\"")
687+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "</a> <a class=\"mute\" href=\"")
671688 if templ_7745c5c3_Err != nil {
672689 return templ_7745c5c3_Err
673690 }
674- var templ_7745c5c3_Var32 templ.SafeURL
675- templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))
691+ var templ_7745c5c3_Var33 templ.SafeURL
692+ templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))
676693 if templ_7745c5c3_Err != nil {
677- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 126}
694+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 126}
678695 }
679- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
696+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
680697 if templ_7745c5c3_Err != nil {
681698 return templ_7745c5c3_Err
682699 }
683- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\">")
700+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\">")
684701 if templ_7745c5c3_Err != nil {
685702 return templ_7745c5c3_Err
686703 }
687- var templ_7745c5c3_Var33 string
688- templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)
704+ var templ_7745c5c3_Var34 string
705+ templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)
689706 if templ_7745c5c3_Err != nil {
690- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 137}
707+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 137}
691708 }
692- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
709+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
693710 if templ_7745c5c3_Err != nil {
694711 return templ_7745c5c3_Err
695712 }
696- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "</a></td><td class=\"c-when nowrap dim\">")
713+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</a></td><td class=\"c-when nowrap dim\">")
697714 if templ_7745c5c3_Err != nil {
698715 return templ_7745c5c3_Err
699716 }
700717 if m.WhenAt != "" {
701- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "<time datetime=\"")
718+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "<time datetime=\"")
702719 if templ_7745c5c3_Err != nil {
703720 return templ_7745c5c3_Err
704721 }
705- var templ_7745c5c3_Var34 string
706- templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
722+ var templ_7745c5c3_Var35 string
723+ templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
707724 if templ_7745c5c3_Err != nil {
708- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 107, Col: 33}
725+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 108, Col: 33}
709726 }
710- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var34)
727+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35)
711728 if templ_7745c5c3_Err != nil {
712729 return templ_7745c5c3_Err
713730 }
714- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" title=\"")
731+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" title=\"")
715732 if templ_7745c5c3_Err != nil {
716733 return templ_7745c5c3_Err
717734 }
718- var templ_7745c5c3_Var35 string
719- templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
735+ var templ_7745c5c3_Var36 string
736+ templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
720737 if templ_7745c5c3_Err != nil {
721- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 107, Col: 52}
738+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 108, Col: 52}
722739 }
723- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35)
740+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var36)
724741 if templ_7745c5c3_Err != nil {
725742 return templ_7745c5c3_Err
726743 }
727- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\">")
744+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "\">")
728745 if templ_7745c5c3_Err != nil {
729746 return templ_7745c5c3_Err
730747 }
731- var templ_7745c5c3_Var36 string
732- templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)
748+ var templ_7745c5c3_Var37 string
749+ templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)
733750 if templ_7745c5c3_Err != nil {
734- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 107, Col: 63}
751+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 108, Col: 63}
735752 }
736- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36))
753+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37))
737754 if templ_7745c5c3_Err != nil {
738755 return templ_7745c5c3_Err
739756 }
740- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</time>")
757+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</time>")
741758 if templ_7745c5c3_Err != nil {
742759 return templ_7745c5c3_Err
743760 }
744761 }
745- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</td></tr>")
762+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</td></tr>")
746763 if templ_7745c5c3_Err != nil {
747764 return templ_7745c5c3_Err
748765 }
749766 }
750- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</tbody></table>")
767+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "</tbody></table>")
751768 if templ_7745c5c3_Err != nil {
752769 return templ_7745c5c3_Err
753770 }
@@ -756,4 +773,265 @@ func inboxRows(rows []InboxRow, label string) templ.Component {
756773 })
757774 }
758775
776+// InboxRuns stays as an empty fragment when CI is disabled.
777+func InboxRuns(p InboxPage) templ.Component {
778+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
779+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
780+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
781+ return templ_7745c5c3_CtxErr
782+ }
783+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
784+ if !templ_7745c5c3_IsBuffer {
785+ defer func() {
786+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
787+ if templ_7745c5c3_Err == nil {
788+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
789+ }
790+ }()
791+ }
792+ ctx = templ.InitializeContext(ctx)
793+ templ_7745c5c3_Var38 := templ.GetChildren(ctx)
794+ if templ_7745c5c3_Var38 == nil {
795+ templ_7745c5c3_Var38 = templ.NopComponent
796+ }
797+ ctx = templ.ClearChildren(ctx)
798+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<section id=\"inbox-runs\"")
799+ if templ_7745c5c3_Err != nil {
800+ return templ_7745c5c3_Err
801+ }
802+ if !p.RunsEnabled {
803+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, " hidden")
804+ if templ_7745c5c3_Err != nil {
805+ return templ_7745c5c3_Err
806+ }
807+ }
808+ if p.RunsEnabled {
809+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, " aria-labelledby=\"inbox-runs-h\"")
810+ if templ_7745c5c3_Err != nil {
811+ return templ_7745c5c3_Err
812+ }
813+ }
814+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, ">")
815+ if templ_7745c5c3_Err != nil {
816+ return templ_7745c5c3_Err
817+ }
818+ if p.RunsEnabled {
819+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "<h2 id=\"inbox-runs-h\" class=\"rule-h\"><span>Running</span><span class=\"count\">")
820+ if templ_7745c5c3_Err != nil {
821+ return templ_7745c5c3_Err
822+ }
823+ var templ_7745c5c3_Var39 string
824+ templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Runs)))
825+ if templ_7745c5c3_Err != nil {
826+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 126, Col: 99}
827+ }
828+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39))
829+ if templ_7745c5c3_Err != nil {
830+ return templ_7745c5c3_Err
831+ }
832+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</span></h2>")
833+ if templ_7745c5c3_Err != nil {
834+ return templ_7745c5c3_Err
835+ }
836+ if len(p.Runs) == 0 {
837+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<p class=\"lede dim\">no runs in progress.</p>")
838+ if templ_7745c5c3_Err != nil {
839+ return templ_7745c5c3_Err
840+ }
841+ } else {
842+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "<table class=\"list mrs\" aria-label=\"Running\"><tbody data-rows>")
843+ if templ_7745c5c3_Err != nil {
844+ return templ_7745c5c3_Err
845+ }
846+ for _, r := range p.Runs {
847+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "<tr><td class=\"c-st\">")
848+ if templ_7745c5c3_Err != nil {
849+ return templ_7745c5c3_Err
850+ }
851+ templ_7745c5c3_Err = CheckIcon(r.Kind, r.State).Render(ctx, templ_7745c5c3_Buffer)
852+ if templ_7745c5c3_Err != nil {
853+ return templ_7745c5c3_Err
854+ }
855+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "<span class=\"dim\">")
856+ if templ_7745c5c3_Err != nil {
857+ return templ_7745c5c3_Err
858+ }
859+ var templ_7745c5c3_Var40 string
860+ templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(r.State)
861+ if templ_7745c5c3_Err != nil {
862+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 134, Col: 79}
863+ }
864+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
865+ if templ_7745c5c3_Err != nil {
866+ return templ_7745c5c3_Err
867+ }
868+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</span></td><td class=\"c-subject\"><a href=\"")
869+ if templ_7745c5c3_Err != nil {
870+ return templ_7745c5c3_Err
871+ }
872+ var templ_7745c5c3_Var41 templ.SafeURL
873+ templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.Href))
874+ if templ_7745c5c3_Err != nil {
875+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 61}
876+ }
877+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41))
878+ if templ_7745c5c3_Err != nil {
879+ return templ_7745c5c3_Err
880+ }
881+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "\">")
882+ if templ_7745c5c3_Err != nil {
883+ return templ_7745c5c3_Err
884+ }
885+ var templ_7745c5c3_Var42 string
886+ templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(r.Workflow)
887+ if templ_7745c5c3_Err != nil {
888+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 76}
889+ }
890+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42))
891+ if templ_7745c5c3_Err != nil {
892+ return templ_7745c5c3_Err
893+ }
894+ var templ_7745c5c3_Var43 string
895+ templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
896+ if templ_7745c5c3_Err != nil {
897+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 83}
898+ }
899+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43))
900+ if templ_7745c5c3_Err != nil {
901+ return templ_7745c5c3_Err
902+ }
903+ var templ_7745c5c3_Var44 string
904+ templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(r.Number)
905+ if templ_7745c5c3_Err != nil {
906+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 95}
907+ }
908+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44))
909+ if templ_7745c5c3_Err != nil {
910+ return templ_7745c5c3_Err
911+ }
912+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "</a> <a class=\"mute\" href=\"")
913+ if templ_7745c5c3_Err != nil {
914+ return templ_7745c5c3_Err
915+ }
916+ var templ_7745c5c3_Var45 templ.SafeURL
917+ templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.RepoHref))
918+ if templ_7745c5c3_Err != nil {
919+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 150}
920+ }
921+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45))
922+ if templ_7745c5c3_Err != nil {
923+ return templ_7745c5c3_Err
924+ }
925+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "\">")
926+ if templ_7745c5c3_Err != nil {
927+ return templ_7745c5c3_Err
928+ }
929+ var templ_7745c5c3_Var46 string
930+ templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(r.Repo)
931+ if templ_7745c5c3_Err != nil {
932+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 161}
933+ }
934+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46))
935+ if templ_7745c5c3_Err != nil {
936+ return templ_7745c5c3_Err
937+ }
938+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "</a> <span class=\"dim\">")
939+ if templ_7745c5c3_Err != nil {
940+ return templ_7745c5c3_Err
941+ }
942+ var templ_7745c5c3_Var47 string
943+ templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(r.Ref)
944+ if templ_7745c5c3_Err != nil {
945+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 193}
946+ }
947+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47))
948+ if templ_7745c5c3_Err != nil {
949+ return templ_7745c5c3_Err
950+ }
951+ var templ_7745c5c3_Var48 string
952+ templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
953+ if templ_7745c5c3_Err != nil {
954+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 200}
955+ }
956+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48))
957+ if templ_7745c5c3_Err != nil {
958+ return templ_7745c5c3_Err
959+ }
960+ var templ_7745c5c3_Var49 string
961+ templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(r.Event)
962+ if templ_7745c5c3_Err != nil {
963+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 211}
964+ }
965+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49))
966+ if templ_7745c5c3_Err != nil {
967+ return templ_7745c5c3_Err
968+ }
969+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "</span></td><td class=\"c-when nowrap dim\">")
970+ if templ_7745c5c3_Err != nil {
971+ return templ_7745c5c3_Err
972+ }
973+ if r.WhenAt != "" {
974+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "<time datetime=\"")
975+ if templ_7745c5c3_Err != nil {
976+ return templ_7745c5c3_Err
977+ }
978+ var templ_7745c5c3_Var50 string
979+ templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.ResolveAttributeValue(r.WhenAt)
980+ if templ_7745c5c3_Err != nil {
981+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 138, Col: 35}
982+ }
983+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var50)
984+ if templ_7745c5c3_Err != nil {
985+ return templ_7745c5c3_Err
986+ }
987+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\" title=\"")
988+ if templ_7745c5c3_Err != nil {
989+ return templ_7745c5c3_Err
990+ }
991+ var templ_7745c5c3_Var51 string
992+ templ_7745c5c3_Var51, templ_7745c5c3_Err = templ.ResolveAttributeValue(r.WhenAt)
993+ if templ_7745c5c3_Err != nil {
994+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 138, Col: 54}
995+ }
996+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var51)
997+ if templ_7745c5c3_Err != nil {
998+ return templ_7745c5c3_Err
999+ }
1000+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\">")
1001+ if templ_7745c5c3_Err != nil {
1002+ return templ_7745c5c3_Err
1003+ }
1004+ var templ_7745c5c3_Var52 string
1005+ templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(r.When)
1006+ if templ_7745c5c3_Err != nil {
1007+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 138, Col: 65}
1008+ }
1009+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52))
1010+ if templ_7745c5c3_Err != nil {
1011+ return templ_7745c5c3_Err
1012+ }
1013+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "</time>")
1014+ if templ_7745c5c3_Err != nil {
1015+ return templ_7745c5c3_Err
1016+ }
1017+ }
1018+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "</td></tr>")
1019+ if templ_7745c5c3_Err != nil {
1020+ return templ_7745c5c3_Err
1021+ }
1022+ }
1023+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "</tbody></table>")
1024+ if templ_7745c5c3_Err != nil {
1025+ return templ_7745c5c3_Err
1026+ }
1027+ }
1028+ }
1029+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "</section>")
1030+ if templ_7745c5c3_Err != nil {
1031+ return templ_7745c5c3_Err
1032+ }
1033+ return nil
1034+ })
1035+}
1036+
7591037 var _ = templruntime.GeneratedTemplate
@@ -62,6 +62,10 @@ func Inbox(l Layout, p InboxPage) templ.Component {
62 if templ_7745c5c3_Err != nil {62 if templ_7745c5c3_Err != nil {
63 return templ_7745c5c3_Err63 return templ_7745c5c3_Err
64 }64 }
65+ templ_7745c5c3_Err = InboxRuns(p).Render(ctx, templ_7745c5c3_Buffer)
66+ if templ_7745c5c3_Err != nil {
67+ return templ_7745c5c3_Err
68+ }
65 templ_7745c5c3_Err = InboxMRs(p).Render(ctx, templ_7745c5c3_Buffer)69 templ_7745c5c3_Err = InboxMRs(p).Render(ctx, templ_7745c5c3_Buffer)
66 if templ_7745c5c3_Err != nil {70 if templ_7745c5c3_Err != nil {
67 return templ_7745c5c3_Err71 return templ_7745c5c3_Err
@@ -112,7 +116,7 @@ func InboxCounters(p InboxPage) templ.Component {
112 var templ_7745c5c3_Var4 string116 var templ_7745c5c3_Var4 string
113 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.MergeRequests))117 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.MergeRequests))
114 if templ_7745c5c3_Err != nil {118 if templ_7745c5c3_Err != nil {
115- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 23, Col: 33}119+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 33}
116 }120 }
117 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))121 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
118 if templ_7745c5c3_Err != nil {122 if templ_7745c5c3_Err != nil {
@@ -125,7 +129,7 @@ func InboxCounters(p InboxPage) templ.Component {
125 var templ_7745c5c3_Var5 string129 var templ_7745c5c3_Var5 string
126 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Issues))130 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Issues))
127 if templ_7745c5c3_Err != nil {131 if templ_7745c5c3_Err != nil {
128- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 23, Col: 87}132+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 87}
129 }133 }
130 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))134 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
131 if templ_7745c5c3_Err != nil {135 if templ_7745c5c3_Err != nil {
@@ -138,13 +142,26 @@ func InboxCounters(p InboxPage) templ.Component {
138 var templ_7745c5c3_Var6 string142 var templ_7745c5c3_Var6 string
139 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))143 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))
140 if templ_7745c5c3_Err != nil {144 if templ_7745c5c3_Err != nil {
141- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 23, Col: 139}145+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 139}
142 }146 }
143 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))147 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
144 if templ_7745c5c3_Err != nil {148 if templ_7745c5c3_Err != nil {
145 return templ_7745c5c3_Err149 return templ_7745c5c3_Err
146 }150 }
147- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</strong> awaiting moderation</p>")151+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</strong> awaiting moderation · <strong>")
152+ if templ_7745c5c3_Err != nil {
153+ return templ_7745c5c3_Err
154+ }
155+ var templ_7745c5c3_Var7 string
156+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Running))
157+ if templ_7745c5c3_Err != nil {
158+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 24, Col: 199}
159+ }
160+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
161+ if templ_7745c5c3_Err != nil {
162+ return templ_7745c5c3_Err
163+ }
164+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</strong> running</p>")
148 if templ_7745c5c3_Err != nil {165 if templ_7745c5c3_Err != nil {
149 return templ_7745c5c3_Err166 return templ_7745c5c3_Err
150 }167 }
@@ -168,58 +185,58 @@ func InboxRepos(p InboxPage) templ.Component {
168 }()185 }()
169 }186 }
170 ctx = templ.InitializeContext(ctx)187 ctx = templ.InitializeContext(ctx)
171- templ_7745c5c3_Var7 := templ.GetChildren(ctx)188+ templ_7745c5c3_Var8 := templ.GetChildren(ctx)
172- if templ_7745c5c3_Var7 == nil {189+ if templ_7745c5c3_Var8 == nil {
173- templ_7745c5c3_Var7 = templ.NopComponent190+ templ_7745c5c3_Var8 = templ.NopComponent
174 }191 }
175 ctx = templ.ClearChildren(ctx)192 ctx = templ.ClearChildren(ctx)
176- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<nav id=\"inbox-repos\" class=\"since\" aria-label=\"Repository\">")193+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<nav id=\"inbox-repos\" class=\"since\" aria-label=\"Repository\">")
177 if templ_7745c5c3_Err != nil {194 if templ_7745c5c3_Err != nil {
178 return templ_7745c5c3_Err195 return templ_7745c5c3_Err
179 }196 }
180 for _, r := range p.Repos {197 for _, r := range p.Repos {
181- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<a href=\"")198+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a href=\"")
182 if templ_7745c5c3_Err != nil {199 if templ_7745c5c3_Err != nil {
183 return templ_7745c5c3_Err200 return templ_7745c5c3_Err
184 }201 }
185- var templ_7745c5c3_Var8 templ.SafeURL202+ var templ_7745c5c3_Var9 templ.SafeURL
186- templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.Href))203+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.Href))
187 if templ_7745c5c3_Err != nil {204 if templ_7745c5c3_Err != nil {
188- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 31, Col: 32}205+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 32, Col: 32}
189 }206 }
190- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))207+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
191 if templ_7745c5c3_Err != nil {208 if templ_7745c5c3_Err != nil {
192 return templ_7745c5c3_Err209 return templ_7745c5c3_Err
193 }210 }
194- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"")211+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"")
195 if templ_7745c5c3_Err != nil {212 if templ_7745c5c3_Err != nil {
196 return templ_7745c5c3_Err213 return templ_7745c5c3_Err
197 }214 }
198 if r.Current {215 if r.Current {
199- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " aria-current=\"page\"")216+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " aria-current=\"page\"")
200 if templ_7745c5c3_Err != nil {217 if templ_7745c5c3_Err != nil {
201 return templ_7745c5c3_Err218 return templ_7745c5c3_Err
202 }219 }
203 }220 }
204- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, ">")221+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, ">")
205 if templ_7745c5c3_Err != nil {222 if templ_7745c5c3_Err != nil {
206 return templ_7745c5c3_Err223 return templ_7745c5c3_Err
207 }224 }
208- var templ_7745c5c3_Var9 string225+ var templ_7745c5c3_Var10 string
209- templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(r.Label)226+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(r.Label)
210 if templ_7745c5c3_Err != nil {227 if templ_7745c5c3_Err != nil {
211- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 35, Col: 13}228+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 36, Col: 13}
212 }229 }
213- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))230+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
214 if templ_7745c5c3_Err != nil {231 if templ_7745c5c3_Err != nil {
215 return templ_7745c5c3_Err232 return templ_7745c5c3_Err
216 }233 }
217- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a>")234+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a>")
218 if templ_7745c5c3_Err != nil {235 if templ_7745c5c3_Err != nil {
219 return templ_7745c5c3_Err236 return templ_7745c5c3_Err
220 }237 }
221 }238 }
222- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</nav>")239+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</nav>")
223 if templ_7745c5c3_Err != nil {240 if templ_7745c5c3_Err != nil {
224 return templ_7745c5c3_Err241 return templ_7745c5c3_Err
225 }242 }
@@ -246,219 +263,219 @@ func InboxPending(p InboxPage) templ.Component {
246 }()263 }()
247 }264 }
248 ctx = templ.InitializeContext(ctx)265 ctx = templ.InitializeContext(ctx)
249- templ_7745c5c3_Var10 := templ.GetChildren(ctx)266+ templ_7745c5c3_Var11 := templ.GetChildren(ctx)
250- if templ_7745c5c3_Var10 == nil {267+ if templ_7745c5c3_Var11 == nil {
251- templ_7745c5c3_Var10 = templ.NopComponent268+ templ_7745c5c3_Var11 = templ.NopComponent
252 }269 }
253 ctx = templ.ClearChildren(ctx)270 ctx = templ.ClearChildren(ctx)
254- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<section id=\"inbox-pending\" aria-labelledby=\"inbox-pending-h\"><h2 id=\"inbox-pending-h\" class=\"rule-h\"><span>Awaiting moderation</span><span class=\"count\">")271+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<section id=\"inbox-pending\" aria-labelledby=\"inbox-pending-h\"><h2 id=\"inbox-pending-h\" class=\"rule-h\"><span>Awaiting moderation</span><span class=\"count\">")
255 if templ_7745c5c3_Err != nil {272 if templ_7745c5c3_Err != nil {
256 return templ_7745c5c3_Err273 return templ_7745c5c3_Err
257 }274 }
258- var templ_7745c5c3_Var11 string275+ var templ_7745c5c3_Var12 string
259- templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))276+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.PendingCount))
260 if templ_7745c5c3_Err != nil {277 if templ_7745c5c3_Err != nil {
261- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 45, Col: 116}278+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 46, Col: 116}
262 }279 }
263- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))280+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
264 if templ_7745c5c3_Err != nil {281 if templ_7745c5c3_Err != nil {
265 return templ_7745c5c3_Err282 return templ_7745c5c3_Err
266 }283 }
267- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</span></h2>")284+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</span></h2>")
268 if templ_7745c5c3_Err != nil {285 if templ_7745c5c3_Err != nil {
269 return templ_7745c5c3_Err286 return templ_7745c5c3_Err
270 }287 }
271 if len(p.Pending) > 0 {288 if len(p.Pending) > 0 {
272- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<ul class=\"pending-list\">")289+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<ul class=\"pending-list\">")
273 if templ_7745c5c3_Err != nil {290 if templ_7745c5c3_Err != nil {
274 return templ_7745c5c3_Err291 return templ_7745c5c3_Err
275 }292 }
276 for _, m := range p.Pending {293 for _, m := range p.Pending {
277- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<li class=\"pending\"><div class=\"p-head\"><a href=\"")294+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<li class=\"pending\"><div class=\"p-head\"><a href=\"")
278 if templ_7745c5c3_Err != nil {295 if templ_7745c5c3_Err != nil {
279 return templ_7745c5c3_Err296 return templ_7745c5c3_Err
280 }297 }
281- var templ_7745c5c3_Var12 templ.SafeURL298+ var templ_7745c5c3_Var13 templ.SafeURL
282- templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))299+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))
283 if templ_7745c5c3_Err != nil {300 if templ_7745c5c3_Err != nil {
284- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 51, Col: 42}301+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 52, Col: 42}
285 }302 }
286- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))303+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
287 if templ_7745c5c3_Err != nil {304 if templ_7745c5c3_Err != nil {
288 return templ_7745c5c3_Err305 return templ_7745c5c3_Err
289 }306 }
290- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">")307+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\">")
291 if templ_7745c5c3_Err != nil {308 if templ_7745c5c3_Err != nil {
292 return templ_7745c5c3_Err309 return templ_7745c5c3_Err
293 }310 }
294- var templ_7745c5c3_Var13 string311+ var templ_7745c5c3_Var14 string
295- templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)312+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)
296 if templ_7745c5c3_Err != nil {313 if templ_7745c5c3_Err != nil {
297- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 51, Col: 53}314+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 52, Col: 53}
298 }315 }
299- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))316+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
300 if templ_7745c5c3_Err != nil {317 if templ_7745c5c3_Err != nil {
301 return templ_7745c5c3_Err318 return templ_7745c5c3_Err
302 }319 }
303- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</a> <span>")320+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</a> <span>")
304 if templ_7745c5c3_Err != nil {321 if templ_7745c5c3_Err != nil {
305 return templ_7745c5c3_Err322 return templ_7745c5c3_Err
306 }323 }
307- var templ_7745c5c3_Var14 string324+ var templ_7745c5c3_Var15 string
308- templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(m.Author)325+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(m.Author)
309 if templ_7745c5c3_Err != nil {326 if templ_7745c5c3_Err != nil {
310- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 52, Col: 23}327+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 53, Col: 23}
311 }328 }
312- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))329+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
313 if templ_7745c5c3_Err != nil {330 if templ_7745c5c3_Err != nil {
314 return templ_7745c5c3_Err331 return templ_7745c5c3_Err
315 }332 }
316- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</span> ")333+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</span> ")
317 if templ_7745c5c3_Err != nil {334 if templ_7745c5c3_Err != nil {
318 return templ_7745c5c3_Err335 return templ_7745c5c3_Err
319 }336 }
320 if m.WhenAt != "" {337 if m.WhenAt != "" {
321- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<time datetime=\"")338+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<time datetime=\"")
322 if templ_7745c5c3_Err != nil {339 if templ_7745c5c3_Err != nil {
323 return templ_7745c5c3_Err340 return templ_7745c5c3_Err
324 }341 }
325- var templ_7745c5c3_Var15 string342+ var templ_7745c5c3_Var16 string
326- templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)343+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
327 if templ_7745c5c3_Err != nil {344 if templ_7745c5c3_Err != nil {
328- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 54, Col: 33}345+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 55, Col: 33}
329 }346 }
330- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var15)347+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16)
331 if templ_7745c5c3_Err != nil {348 if templ_7745c5c3_Err != nil {
332 return templ_7745c5c3_Err349 return templ_7745c5c3_Err
333 }350 }
334- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "\" title=\"")351+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\" title=\"")
335 if templ_7745c5c3_Err != nil {352 if templ_7745c5c3_Err != nil {
336 return templ_7745c5c3_Err353 return templ_7745c5c3_Err
337 }354 }
338- var templ_7745c5c3_Var16 string355+ var templ_7745c5c3_Var17 string
339- templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)356+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
340 if templ_7745c5c3_Err != nil {357 if templ_7745c5c3_Err != nil {
341- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 54, Col: 52}358+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 55, Col: 52}
342 }359 }
343- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16)360+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17)
344 if templ_7745c5c3_Err != nil {361 if templ_7745c5c3_Err != nil {
345 return templ_7745c5c3_Err362 return templ_7745c5c3_Err
346 }363 }
347- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "\">")364+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\">")
348 if templ_7745c5c3_Err != nil {365 if templ_7745c5c3_Err != nil {
349 return templ_7745c5c3_Err366 return templ_7745c5c3_Err
350 }367 }
351- var templ_7745c5c3_Var17 string368+ var templ_7745c5c3_Var18 string
352- templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)369+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)
353 if templ_7745c5c3_Err != nil {370 if templ_7745c5c3_Err != nil {
354- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 54, Col: 63}371+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 55, Col: 63}
355 }372 }
356- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))373+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
357 if templ_7745c5c3_Err != nil {374 if templ_7745c5c3_Err != nil {
358 return templ_7745c5c3_Err375 return templ_7745c5c3_Err
359 }376 }
360- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</time>")377+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</time>")
361 if templ_7745c5c3_Err != nil {378 if templ_7745c5c3_Err != nil {
362 return templ_7745c5c3_Err379 return templ_7745c5c3_Err
363 }380 }
364 }381 }
365- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</div><p class=\"p-title\">")382+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</div><p class=\"p-title\">")
366 if templ_7745c5c3_Err != nil {383 if templ_7745c5c3_Err != nil {
367 return templ_7745c5c3_Err384 return templ_7745c5c3_Err
368 }385 }
369- var templ_7745c5c3_Var18 string386+ var templ_7745c5c3_Var19 string
370- templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)387+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)
371 if templ_7745c5c3_Err != nil {388 if templ_7745c5c3_Err != nil {
372- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 57, Col: 34}389+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 58, Col: 34}
373 }390 }
374- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))391+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
375 if templ_7745c5c3_Err != nil {392 if templ_7745c5c3_Err != nil {
376 return templ_7745c5c3_Err393 return templ_7745c5c3_Err
377 }394 }
378- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</p>")395+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</p>")
379 if templ_7745c5c3_Err != nil {396 if templ_7745c5c3_Err != nil {
380 return templ_7745c5c3_Err397 return templ_7745c5c3_Err
381 }398 }
382 if m.Preview != "" {399 if m.Preview != "" {
383- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<p class=\"p-body\">")400+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<p class=\"p-body\">")
384 if templ_7745c5c3_Err != nil {401 if templ_7745c5c3_Err != nil {
385 return templ_7745c5c3_Err402 return templ_7745c5c3_Err
386 }403 }
387- var templ_7745c5c3_Var19 string404+ var templ_7745c5c3_Var20 string
388- templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(m.Preview)405+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(m.Preview)
389 if templ_7745c5c3_Err != nil {406 if templ_7745c5c3_Err != nil {
390- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 59, Col: 36}407+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 60, Col: 36}
391 }408 }
392- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))409+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
393 if templ_7745c5c3_Err != nil {410 if templ_7745c5c3_Err != nil {
394 return templ_7745c5c3_Err411 return templ_7745c5c3_Err
395 }412 }
396- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</p>")413+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</p>")
397 if templ_7745c5c3_Err != nil {414 if templ_7745c5c3_Err != nil {
398 return templ_7745c5c3_Err415 return templ_7745c5c3_Err
399 }416 }
400 }417 }
401 if m.Approve != "" {418 if m.Approve != "" {
402- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"p-btns\"><form method=\"post\" action=\"")419+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<div class=\"p-btns\"><form method=\"post\" action=\"")
403 if templ_7745c5c3_Err != nil {420 if templ_7745c5c3_Err != nil {
404 return templ_7745c5c3_Err421 return templ_7745c5c3_Err
405 }422 }
406- var templ_7745c5c3_Var20 templ.SafeURL423+ var templ_7745c5c3_Var21 templ.SafeURL
407- templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Approve))424+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Approve))
408 if templ_7745c5c3_Err != nil {425 if templ_7745c5c3_Err != nil {
409- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 63, Col: 61}426+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 64, Col: 61}
410 }427 }
411- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))428+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
412 if templ_7745c5c3_Err != nil {429 if templ_7745c5c3_Err != nil {
413 return templ_7745c5c3_Err430 return templ_7745c5c3_Err
414 }431 }
415- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\"><button type=\"submit\" class=\"btn primary\">Approve</button></form><form method=\"post\" action=\"")432+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\"><button type=\"submit\" class=\"btn primary\">Approve</button></form><form method=\"post\" action=\"")
416 if templ_7745c5c3_Err != nil {433 if templ_7745c5c3_Err != nil {
417 return templ_7745c5c3_Err434 return templ_7745c5c3_Err
418 }435 }
419- var templ_7745c5c3_Var21 templ.SafeURL436+ var templ_7745c5c3_Var22 templ.SafeURL
420- templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Reject))437+ templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Reject))
421 if templ_7745c5c3_Err != nil {438 if templ_7745c5c3_Err != nil {
422- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 64, Col: 60}439+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 65, Col: 60}
423 }440 }
424- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))441+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
425 if templ_7745c5c3_Err != nil {442 if templ_7745c5c3_Err != nil {
426 return templ_7745c5c3_Err443 return templ_7745c5c3_Err
427 }444 }
428- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\"><button type=\"submit\" class=\"btn\">Reject</button></form><form method=\"post\" action=\"")445+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\"><button type=\"submit\" class=\"btn\">Reject</button></form><form method=\"post\" action=\"")
429 if templ_7745c5c3_Err != nil {446 if templ_7745c5c3_Err != nil {
430 return templ_7745c5c3_Err447 return templ_7745c5c3_Err
431 }448 }
432- var templ_7745c5c3_Var22 templ.SafeURL449+ var templ_7745c5c3_Var23 templ.SafeURL
433- templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Ban))450+ templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Ban))
434 if templ_7745c5c3_Err != nil {451 if templ_7745c5c3_Err != nil {
435- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 65, Col: 57}452+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 66, Col: 57}
436 }453 }
437- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))454+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
438 if templ_7745c5c3_Err != nil {455 if templ_7745c5c3_Err != nil {
439 return templ_7745c5c3_Err456 return templ_7745c5c3_Err
440 }457 }
441- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\"><button type=\"submit\" class=\"btn danger\">Reject and ban</button></form></div>")458+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\"><button type=\"submit\" class=\"btn danger\">Reject and ban</button></form></div>")
442 if templ_7745c5c3_Err != nil {459 if templ_7745c5c3_Err != nil {
443 return templ_7745c5c3_Err460 return templ_7745c5c3_Err
444 }461 }
445 }462 }
446- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "</li>")463+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</li>")
447 if templ_7745c5c3_Err != nil {464 if templ_7745c5c3_Err != nil {
448 return templ_7745c5c3_Err465 return templ_7745c5c3_Err
449 }466 }
450 }467 }
451- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</ul>")468+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</ul>")
452 if templ_7745c5c3_Err != nil {469 if templ_7745c5c3_Err != nil {
453 return templ_7745c5c3_Err470 return templ_7745c5c3_Err
454 }471 }
455 } else {472 } else {
456- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<p class=\"lede dim\">nothing awaits moderation.</p>")473+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<p class=\"lede dim\">nothing awaits moderation.</p>")
457 if templ_7745c5c3_Err != nil {474 if templ_7745c5c3_Err != nil {
458 return templ_7745c5c3_Err475 return templ_7745c5c3_Err
459 }476 }
460 }477 }
461- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</section>")478+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</section>")
462 if templ_7745c5c3_Err != nil {479 if templ_7745c5c3_Err != nil {
463 return templ_7745c5c3_Err480 return templ_7745c5c3_Err
464 }481 }
@@ -482,25 +499,25 @@ func InboxMRs(p InboxPage) templ.Component {
482 }()499 }()
483 }500 }
484 ctx = templ.InitializeContext(ctx)501 ctx = templ.InitializeContext(ctx)
485- templ_7745c5c3_Var23 := templ.GetChildren(ctx)502+ templ_7745c5c3_Var24 := templ.GetChildren(ctx)
486- if templ_7745c5c3_Var23 == nil {503+ if templ_7745c5c3_Var24 == nil {
487- templ_7745c5c3_Var23 = templ.NopComponent504+ templ_7745c5c3_Var24 = templ.NopComponent
488 }505 }
489 ctx = templ.ClearChildren(ctx)506 ctx = templ.ClearChildren(ctx)
490- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<section id=\"inbox-mrs\" aria-labelledby=\"inbox-mrs-h\"><h2 id=\"inbox-mrs-h\" class=\"rule-h\"><span>Open merge requests</span><span class=\"count\">")507+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<section id=\"inbox-mrs\" aria-labelledby=\"inbox-mrs-h\"><h2 id=\"inbox-mrs-h\" class=\"rule-h\"><span>Open merge requests</span><span class=\"count\">")
491 if templ_7745c5c3_Err != nil {508 if templ_7745c5c3_Err != nil {
492 return templ_7745c5c3_Err509 return templ_7745c5c3_Err
493 }510 }
494- var templ_7745c5c3_Var24 string511+ var templ_7745c5c3_Var25 string
495- templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.MRs)))512+ templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.MRs)))
496 if templ_7745c5c3_Err != nil {513 if templ_7745c5c3_Err != nil {
497- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 79, Col: 108}514+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 80, Col: 108}
498 }515 }
499- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))516+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
500 if templ_7745c5c3_Err != nil {517 if templ_7745c5c3_Err != nil {
501 return templ_7745c5c3_Err518 return templ_7745c5c3_Err
502 }519 }
503- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</span></h2>")520+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</span></h2>")
504 if templ_7745c5c3_Err != nil {521 if templ_7745c5c3_Err != nil {
505 return templ_7745c5c3_Err522 return templ_7745c5c3_Err
506 }523 }
@@ -509,12 +526,12 @@ func InboxMRs(p InboxPage) templ.Component {
509 return templ_7745c5c3_Err526 return templ_7745c5c3_Err
510 }527 }
511 if len(p.MRs) == 0 {528 if len(p.MRs) == 0 {
512- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "<p class=\"lede dim\">no open merge requests.</p>")529+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<p class=\"lede dim\">no open merge requests.</p>")
513 if templ_7745c5c3_Err != nil {530 if templ_7745c5c3_Err != nil {
514 return templ_7745c5c3_Err531 return templ_7745c5c3_Err
515 }532 }
516 }533 }
517- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</section>")534+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</section>")
518 if templ_7745c5c3_Err != nil {535 if templ_7745c5c3_Err != nil {
519 return templ_7745c5c3_Err536 return templ_7745c5c3_Err
520 }537 }
@@ -538,25 +555,25 @@ func InboxIssues(p InboxPage) templ.Component {
538 }()555 }()
539 }556 }
540 ctx = templ.InitializeContext(ctx)557 ctx = templ.InitializeContext(ctx)
541- templ_7745c5c3_Var25 := templ.GetChildren(ctx)558+ templ_7745c5c3_Var26 := templ.GetChildren(ctx)
542- if templ_7745c5c3_Var25 == nil {559+ if templ_7745c5c3_Var26 == nil {
543- templ_7745c5c3_Var25 = templ.NopComponent560+ templ_7745c5c3_Var26 = templ.NopComponent
544 }561 }
545 ctx = templ.ClearChildren(ctx)562 ctx = templ.ClearChildren(ctx)
546- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<section id=\"inbox-issues\" aria-labelledby=\"inbox-issues-h\"><h2 id=\"inbox-issues-h\" class=\"rule-h\"><span>Open issues</span><span class=\"count\">")563+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<section id=\"inbox-issues\" aria-labelledby=\"inbox-issues-h\"><h2 id=\"inbox-issues-h\" class=\"rule-h\"><span>Open issues</span><span class=\"count\">")
547 if templ_7745c5c3_Err != nil {564 if templ_7745c5c3_Err != nil {
548 return templ_7745c5c3_Err565 return templ_7745c5c3_Err
549 }566 }
550- var templ_7745c5c3_Var26 string567+ var templ_7745c5c3_Var27 string
551- templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.IssueRows)))568+ templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.IssueRows)))
552 if templ_7745c5c3_Err != nil {569 if templ_7745c5c3_Err != nil {
553- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 89, Col: 109}570+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 90, Col: 109}
554 }571 }
555- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))572+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
556 if templ_7745c5c3_Err != nil {573 if templ_7745c5c3_Err != nil {
557 return templ_7745c5c3_Err574 return templ_7745c5c3_Err
558 }575 }
559- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</span></h2>")576+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</span></h2>")
560 if templ_7745c5c3_Err != nil {577 if templ_7745c5c3_Err != nil {
561 return templ_7745c5c3_Err578 return templ_7745c5c3_Err
562 }579 }
@@ -565,12 +582,12 @@ func InboxIssues(p InboxPage) templ.Component {
565 return templ_7745c5c3_Err582 return templ_7745c5c3_Err
566 }583 }
567 if len(p.IssueRows) == 0 {584 if len(p.IssueRows) == 0 {
568- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "<p class=\"lede dim\">no open issues.</p>")585+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<p class=\"lede dim\">no open issues.</p>")
569 if templ_7745c5c3_Err != nil {586 if templ_7745c5c3_Err != nil {
570 return templ_7745c5c3_Err587 return templ_7745c5c3_Err
571 }588 }
572 }589 }
573- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</section>")590+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</section>")
574 if templ_7745c5c3_Err != nil {591 if templ_7745c5c3_Err != nil {
575 return templ_7745c5c3_Err592 return templ_7745c5c3_Err
576 }593 }
@@ -594,160 +611,160 @@ func inboxRows(rows []InboxRow, label string) templ.Component {
594 }()611 }()
595 }612 }
596 ctx = templ.InitializeContext(ctx)613 ctx = templ.InitializeContext(ctx)
597- templ_7745c5c3_Var27 := templ.GetChildren(ctx)614+ templ_7745c5c3_Var28 := templ.GetChildren(ctx)
598- if templ_7745c5c3_Var27 == nil {615+ if templ_7745c5c3_Var28 == nil {
599- templ_7745c5c3_Var27 = templ.NopComponent616+ templ_7745c5c3_Var28 = templ.NopComponent
600 }617 }
601 ctx = templ.ClearChildren(ctx)618 ctx = templ.ClearChildren(ctx)
602 if len(rows) > 0 {619 if len(rows) > 0 {
603- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<table class=\"list mrs\" aria-label=\"")620+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<table class=\"list mrs\" aria-label=\"")
604 if templ_7745c5c3_Err != nil {621 if templ_7745c5c3_Err != nil {
605 return templ_7745c5c3_Err622 return templ_7745c5c3_Err
606 }623 }
607- var templ_7745c5c3_Var28 string624+ var templ_7745c5c3_Var29 string
608- templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.ResolveAttributeValue(label)625+ templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.ResolveAttributeValue(label)
609 if templ_7745c5c3_Err != nil {626 if templ_7745c5c3_Err != nil {
610- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 99, Col: 44}627+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 100, Col: 44}
611 }628 }
612- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28)629+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var29)
613 if templ_7745c5c3_Err != nil {630 if templ_7745c5c3_Err != nil {
614 return templ_7745c5c3_Err631 return templ_7745c5c3_Err
615 }632 }
616- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\"><tbody data-rows>")633+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\"><tbody data-rows>")
617 if templ_7745c5c3_Err != nil {634 if templ_7745c5c3_Err != nil {
618 return templ_7745c5c3_Err635 return templ_7745c5c3_Err
619 }636 }
620 for _, m := range rows {637 for _, m := range rows {
621- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<tr")638+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<tr")
622 if templ_7745c5c3_Err != nil {639 if templ_7745c5c3_Err != nil {
623 return templ_7745c5c3_Err640 return templ_7745c5c3_Err
624 }641 }
625 if m.Cursor {642 if m.Cursor {
626- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, " data-cursor")643+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " data-cursor")
627 if templ_7745c5c3_Err != nil {644 if templ_7745c5c3_Err != nil {
628 return templ_7745c5c3_Err645 return templ_7745c5c3_Err
629 }646 }
630 }647 }
631- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, " data-state=\"open\"><td class=\"c-n mute\">")648+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, " data-state=\"open\"><td class=\"c-n mute\">")
632 if templ_7745c5c3_Err != nil {649 if templ_7745c5c3_Err != nil {
633 return templ_7745c5c3_Err650 return templ_7745c5c3_Err
634 }651 }
635- var templ_7745c5c3_Var29 string652+ var templ_7745c5c3_Var30 string
636- templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(m.Number)653+ templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(m.Number)
637 if templ_7745c5c3_Err != nil {654 if templ_7745c5c3_Err != nil {
638- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 103, Col: 37}655+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 37}
639 }656 }
640- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))657+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
641 if templ_7745c5c3_Err != nil {658 if templ_7745c5c3_Err != nil {
642 return templ_7745c5c3_Err659 return templ_7745c5c3_Err
643 }660 }
644- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</td><td class=\"c-subject\"><a href=\"")661+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</td><td class=\"c-subject\"><a href=\"")
645 if templ_7745c5c3_Err != nil {662 if templ_7745c5c3_Err != nil {
646 return templ_7745c5c3_Err663 return templ_7745c5c3_Err
647 }664 }
648- var templ_7745c5c3_Var30 templ.SafeURL665+ var templ_7745c5c3_Var31 templ.SafeURL
649- templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Href))666+ templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.Href))
650 if templ_7745c5c3_Err != nil {667 if templ_7745c5c3_Err != nil {
651- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 59}668+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 59}
652 }669 }
653- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))670+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
654 if templ_7745c5c3_Err != nil {671 if templ_7745c5c3_Err != nil {
655 return templ_7745c5c3_Err672 return templ_7745c5c3_Err
656 }673 }
657- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "\">")674+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "\">")
658 if templ_7745c5c3_Err != nil {675 if templ_7745c5c3_Err != nil {
659 return templ_7745c5c3_Err676 return templ_7745c5c3_Err
660 }677 }
661- var templ_7745c5c3_Var31 string678+ var templ_7745c5c3_Var32 string
662- templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)679+ templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(m.Title)
663 if templ_7745c5c3_Err != nil {680 if templ_7745c5c3_Err != nil {
664- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 71}681+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 71}
665 }682 }
666- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))683+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
667 if templ_7745c5c3_Err != nil {684 if templ_7745c5c3_Err != nil {
668 return templ_7745c5c3_Err685 return templ_7745c5c3_Err
669 }686 }
670- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</a> <a class=\"mute\" href=\"")687+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "</a> <a class=\"mute\" href=\"")
671 if templ_7745c5c3_Err != nil {688 if templ_7745c5c3_Err != nil {
672 return templ_7745c5c3_Err689 return templ_7745c5c3_Err
673 }690 }
674- var templ_7745c5c3_Var32 templ.SafeURL691+ var templ_7745c5c3_Var33 templ.SafeURL
675- templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))692+ templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(m.RepoHref))
676 if templ_7745c5c3_Err != nil {693 if templ_7745c5c3_Err != nil {
677- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 126}694+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 126}
678 }695 }
679- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))696+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
680 if templ_7745c5c3_Err != nil {697 if templ_7745c5c3_Err != nil {
681 return templ_7745c5c3_Err698 return templ_7745c5c3_Err
682 }699 }
683- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\">")700+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "\">")
684 if templ_7745c5c3_Err != nil {701 if templ_7745c5c3_Err != nil {
685 return templ_7745c5c3_Err702 return templ_7745c5c3_Err
686 }703 }
687- var templ_7745c5c3_Var33 string704+ var templ_7745c5c3_Var34 string
688- templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)705+ templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(m.Repo)
689 if templ_7745c5c3_Err != nil {706 if templ_7745c5c3_Err != nil {
690- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 104, Col: 137}707+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 105, Col: 137}
691 }708 }
692- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))709+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
693 if templ_7745c5c3_Err != nil {710 if templ_7745c5c3_Err != nil {
694 return templ_7745c5c3_Err711 return templ_7745c5c3_Err
695 }712 }
696- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "</a></td><td class=\"c-when nowrap dim\">")713+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</a></td><td class=\"c-when nowrap dim\">")
697 if templ_7745c5c3_Err != nil {714 if templ_7745c5c3_Err != nil {
698 return templ_7745c5c3_Err715 return templ_7745c5c3_Err
699 }716 }
700 if m.WhenAt != "" {717 if m.WhenAt != "" {
701- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "<time datetime=\"")718+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "<time datetime=\"")
702 if templ_7745c5c3_Err != nil {719 if templ_7745c5c3_Err != nil {
703 return templ_7745c5c3_Err720 return templ_7745c5c3_Err
704 }721 }
705- var templ_7745c5c3_Var34 string722+ var templ_7745c5c3_Var35 string
706- templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)723+ templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
707 if templ_7745c5c3_Err != nil {724 if templ_7745c5c3_Err != nil {
708- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 107, Col: 33}725+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 108, Col: 33}
709 }726 }
710- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var34)727+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35)
711 if templ_7745c5c3_Err != nil {728 if templ_7745c5c3_Err != nil {
712 return templ_7745c5c3_Err729 return templ_7745c5c3_Err
713 }730 }
714- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\" title=\"")731+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\" title=\"")
715 if templ_7745c5c3_Err != nil {732 if templ_7745c5c3_Err != nil {
716 return templ_7745c5c3_Err733 return templ_7745c5c3_Err
717 }734 }
718- var templ_7745c5c3_Var35 string735+ var templ_7745c5c3_Var36 string
719- templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)736+ templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.WhenAt)
720 if templ_7745c5c3_Err != nil {737 if templ_7745c5c3_Err != nil {
721- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 107, Col: 52}738+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 108, Col: 52}
722 }739 }
723- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35)740+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var36)
724 if templ_7745c5c3_Err != nil {741 if templ_7745c5c3_Err != nil {
725 return templ_7745c5c3_Err742 return templ_7745c5c3_Err
726 }743 }
727- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "\">")744+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "\">")
728 if templ_7745c5c3_Err != nil {745 if templ_7745c5c3_Err != nil {
729 return templ_7745c5c3_Err746 return templ_7745c5c3_Err
730 }747 }
731- var templ_7745c5c3_Var36 string748+ var templ_7745c5c3_Var37 string
732- templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)749+ templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(m.When)
733 if templ_7745c5c3_Err != nil {750 if templ_7745c5c3_Err != nil {
734- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 107, Col: 63}751+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 108, Col: 63}
735 }752 }
736- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36))753+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37))
737 if templ_7745c5c3_Err != nil {754 if templ_7745c5c3_Err != nil {
738 return templ_7745c5c3_Err755 return templ_7745c5c3_Err
739 }756 }
740- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</time>")757+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</time>")
741 if templ_7745c5c3_Err != nil {758 if templ_7745c5c3_Err != nil {
742 return templ_7745c5c3_Err759 return templ_7745c5c3_Err
743 }760 }
744 }761 }
745- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "</td></tr>")762+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</td></tr>")
746 if templ_7745c5c3_Err != nil {763 if templ_7745c5c3_Err != nil {
747 return templ_7745c5c3_Err764 return templ_7745c5c3_Err
748 }765 }
749 }766 }
750- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "</tbody></table>")767+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "</tbody></table>")
751 if templ_7745c5c3_Err != nil {768 if templ_7745c5c3_Err != nil {
752 return templ_7745c5c3_Err769 return templ_7745c5c3_Err
753 }770 }
@@ -756,4 +773,265 @@ func inboxRows(rows []InboxRow, label string) templ.Component {
756 })773 })
757 }774 }
758 775
776+// InboxRuns stays as an empty fragment when CI is disabled.
777+func InboxRuns(p InboxPage) templ.Component {
778+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
779+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
780+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
781+ return templ_7745c5c3_CtxErr
782+ }
783+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
784+ if !templ_7745c5c3_IsBuffer {
785+ defer func() {
786+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
787+ if templ_7745c5c3_Err == nil {
788+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
789+ }
790+ }()
791+ }
792+ ctx = templ.InitializeContext(ctx)
793+ templ_7745c5c3_Var38 := templ.GetChildren(ctx)
794+ if templ_7745c5c3_Var38 == nil {
795+ templ_7745c5c3_Var38 = templ.NopComponent
796+ }
797+ ctx = templ.ClearChildren(ctx)
798+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "<section id=\"inbox-runs\"")
799+ if templ_7745c5c3_Err != nil {
800+ return templ_7745c5c3_Err
801+ }
802+ if !p.RunsEnabled {
803+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, " hidden")
804+ if templ_7745c5c3_Err != nil {
805+ return templ_7745c5c3_Err
806+ }
807+ }
808+ if p.RunsEnabled {
809+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, " aria-labelledby=\"inbox-runs-h\"")
810+ if templ_7745c5c3_Err != nil {
811+ return templ_7745c5c3_Err
812+ }
813+ }
814+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, ">")
815+ if templ_7745c5c3_Err != nil {
816+ return templ_7745c5c3_Err
817+ }
818+ if p.RunsEnabled {
819+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "<h2 id=\"inbox-runs-h\" class=\"rule-h\"><span>Running</span><span class=\"count\">")
820+ if templ_7745c5c3_Err != nil {
821+ return templ_7745c5c3_Err
822+ }
823+ var templ_7745c5c3_Var39 string
824+ templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Runs)))
825+ if templ_7745c5c3_Err != nil {
826+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 126, Col: 99}
827+ }
828+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39))
829+ if templ_7745c5c3_Err != nil {
830+ return templ_7745c5c3_Err
831+ }
832+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "</span></h2>")
833+ if templ_7745c5c3_Err != nil {
834+ return templ_7745c5c3_Err
835+ }
836+ if len(p.Runs) == 0 {
837+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<p class=\"lede dim\">no runs in progress.</p>")
838+ if templ_7745c5c3_Err != nil {
839+ return templ_7745c5c3_Err
840+ }
841+ } else {
842+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "<table class=\"list mrs\" aria-label=\"Running\"><tbody data-rows>")
843+ if templ_7745c5c3_Err != nil {
844+ return templ_7745c5c3_Err
845+ }
846+ for _, r := range p.Runs {
847+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "<tr><td class=\"c-st\">")
848+ if templ_7745c5c3_Err != nil {
849+ return templ_7745c5c3_Err
850+ }
851+ templ_7745c5c3_Err = CheckIcon(r.Kind, r.State).Render(ctx, templ_7745c5c3_Buffer)
852+ if templ_7745c5c3_Err != nil {
853+ return templ_7745c5c3_Err
854+ }
855+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "<span class=\"dim\">")
856+ if templ_7745c5c3_Err != nil {
857+ return templ_7745c5c3_Err
858+ }
859+ var templ_7745c5c3_Var40 string
860+ templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(r.State)
861+ if templ_7745c5c3_Err != nil {
862+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 134, Col: 79}
863+ }
864+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
865+ if templ_7745c5c3_Err != nil {
866+ return templ_7745c5c3_Err
867+ }
868+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</span></td><td class=\"c-subject\"><a href=\"")
869+ if templ_7745c5c3_Err != nil {
870+ return templ_7745c5c3_Err
871+ }
872+ var templ_7745c5c3_Var41 templ.SafeURL
873+ templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.Href))
874+ if templ_7745c5c3_Err != nil {
875+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 61}
876+ }
877+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41))
878+ if templ_7745c5c3_Err != nil {
879+ return templ_7745c5c3_Err
880+ }
881+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "\">")
882+ if templ_7745c5c3_Err != nil {
883+ return templ_7745c5c3_Err
884+ }
885+ var templ_7745c5c3_Var42 string
886+ templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(r.Workflow)
887+ if templ_7745c5c3_Err != nil {
888+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 76}
889+ }
890+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42))
891+ if templ_7745c5c3_Err != nil {
892+ return templ_7745c5c3_Err
893+ }
894+ var templ_7745c5c3_Var43 string
895+ templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
896+ if templ_7745c5c3_Err != nil {
897+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 83}
898+ }
899+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43))
900+ if templ_7745c5c3_Err != nil {
901+ return templ_7745c5c3_Err
902+ }
903+ var templ_7745c5c3_Var44 string
904+ templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(r.Number)
905+ if templ_7745c5c3_Err != nil {
906+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 95}
907+ }
908+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44))
909+ if templ_7745c5c3_Err != nil {
910+ return templ_7745c5c3_Err
911+ }
912+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "</a> <a class=\"mute\" href=\"")
913+ if templ_7745c5c3_Err != nil {
914+ return templ_7745c5c3_Err
915+ }
916+ var templ_7745c5c3_Var45 templ.SafeURL
917+ templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(r.RepoHref))
918+ if templ_7745c5c3_Err != nil {
919+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 150}
920+ }
921+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45))
922+ if templ_7745c5c3_Err != nil {
923+ return templ_7745c5c3_Err
924+ }
925+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "\">")
926+ if templ_7745c5c3_Err != nil {
927+ return templ_7745c5c3_Err
928+ }
929+ var templ_7745c5c3_Var46 string
930+ templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(r.Repo)
931+ if templ_7745c5c3_Err != nil {
932+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 161}
933+ }
934+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46))
935+ if templ_7745c5c3_Err != nil {
936+ return templ_7745c5c3_Err
937+ }
938+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "</a> <span class=\"dim\">")
939+ if templ_7745c5c3_Err != nil {
940+ return templ_7745c5c3_Err
941+ }
942+ var templ_7745c5c3_Var47 string
943+ templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(r.Ref)
944+ if templ_7745c5c3_Err != nil {
945+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 193}
946+ }
947+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47))
948+ if templ_7745c5c3_Err != nil {
949+ return templ_7745c5c3_Err
950+ }
951+ var templ_7745c5c3_Var48 string
952+ templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(" ")
953+ if templ_7745c5c3_Err != nil {
954+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 200}
955+ }
956+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48))
957+ if templ_7745c5c3_Err != nil {
958+ return templ_7745c5c3_Err
959+ }
960+ var templ_7745c5c3_Var49 string
961+ templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(r.Event)
962+ if templ_7745c5c3_Err != nil {
963+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 135, Col: 211}
964+ }
965+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49))
966+ if templ_7745c5c3_Err != nil {
967+ return templ_7745c5c3_Err
968+ }
969+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "</span></td><td class=\"c-when nowrap dim\">")
970+ if templ_7745c5c3_Err != nil {
971+ return templ_7745c5c3_Err
972+ }
973+ if r.WhenAt != "" {
974+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "<time datetime=\"")
975+ if templ_7745c5c3_Err != nil {
976+ return templ_7745c5c3_Err
977+ }
978+ var templ_7745c5c3_Var50 string
979+ templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.ResolveAttributeValue(r.WhenAt)
980+ if templ_7745c5c3_Err != nil {
981+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 138, Col: 35}
982+ }
983+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var50)
984+ if templ_7745c5c3_Err != nil {
985+ return templ_7745c5c3_Err
986+ }
987+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "\" title=\"")
988+ if templ_7745c5c3_Err != nil {
989+ return templ_7745c5c3_Err
990+ }
991+ var templ_7745c5c3_Var51 string
992+ templ_7745c5c3_Var51, templ_7745c5c3_Err = templ.ResolveAttributeValue(r.WhenAt)
993+ if templ_7745c5c3_Err != nil {
994+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 138, Col: 54}
995+ }
996+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var51)
997+ if templ_7745c5c3_Err != nil {
998+ return templ_7745c5c3_Err
999+ }
1000+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "\">")
1001+ if templ_7745c5c3_Err != nil {
1002+ return templ_7745c5c3_Err
1003+ }
1004+ var templ_7745c5c3_Var52 string
1005+ templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(r.When)
1006+ if templ_7745c5c3_Err != nil {
1007+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/inbox.templ`, Line: 138, Col: 65}
1008+ }
1009+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52))
1010+ if templ_7745c5c3_Err != nil {
1011+ return templ_7745c5c3_Err
1012+ }
1013+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "</time>")
1014+ if templ_7745c5c3_Err != nil {
1015+ return templ_7745c5c3_Err
1016+ }
1017+ }
1018+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "</td></tr>")
1019+ if templ_7745c5c3_Err != nil {
1020+ return templ_7745c5c3_Err
1021+ }
1022+ }
1023+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "</tbody></table>")
1024+ if templ_7745c5c3_Err != nil {
1025+ return templ_7745c5c3_Err
1026+ }
1027+ }
1028+ }
1029+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "</section>")
1030+ if templ_7745c5c3_Err != nil {
1031+ return templ_7745c5c3_Err
1032+ }
1033+ return nil
1034+ })
1035+}
1036+
759 var _ = templruntime.GeneratedTemplate1037 var _ = templruntime.GeneratedTemplate
M internal/adapters/web/inbox_test.go +6 -4
@@ -180,12 +180,13 @@ func TestInboxLiveFragments(t *testing.T) {
180180 ls := &liveStream{s: srv, view: "inbox"}
181181 frags, err := ls.render(withOwner(t.Context()), ports.WatchEvent{ID: "b-1", Event: domain.IssueOpened{Issue: domain.Issue{Repo: repoName(t, "beta"), Number: 7}}})
182182 require.NoError(t, err)
183- require.Len(t, frags, 5)
183+ require.Len(t, frags, 6)
184184 assert.Contains(t, frags[0].html, `id="inbox-counts"`)
185185 assert.Contains(t, frags[1].html, `id="inbox-repos"`)
186186 assert.Contains(t, frags[2].html, `id="inbox-pending"`)
187- assert.Contains(t, frags[3].html, `id="inbox-mrs"`)
188- assert.Contains(t, frags[4].html, `id="inbox-issues"`)
187+ assert.Contains(t, frags[3].html, `id="inbox-runs"`)
188+ assert.Contains(t, frags[4].html, `id="inbox-mrs"`)
189+ assert.Contains(t, frags[5].html, `id="inbox-issues"`)
189190
190191 none, err := ls.render(withOwner(t.Context()), ports.WatchEvent{Event: domain.PushEvent{Repo: repoName(t, "beta")}})
191192 require.NoError(t, err)
@@ -286,6 +287,7 @@ func TestInboxRefreshesOnRepoEvents(t *testing.T) {
286287 t.Parallel()
287288 for name, ev := range map[string]domain.Event{
288289 "issues turned off": domain.RepoUpdated{Repo: repoName(t, "beta")},
290+ "run updated": domain.RunUpdated{},
289291 "repo deleted": domain.RepoDeleted{Repo: repoName(t, "beta")},
290292 } {
291293 t.Run(name, func(t *testing.T) {
@@ -297,7 +299,7 @@ func TestInboxRefreshesOnRepoEvents(t *testing.T) {
297299 ls := &liveStream{s: srv, view: "inbox"}
298300 frags, err := ls.render(withOwner(t.Context()), ports.WatchEvent{ID: "b-1", Event: ev})
299301 require.NoError(t, err)
300- require.Len(t, frags, 5)
302+ require.Len(t, frags, 6)
301303 all := ""
302304 for _, f := range frags {
303305 all += f.html
@@ -180,12 +180,13 @@ func TestInboxLiveFragments(t *testing.T) {
180 ls := &liveStream{s: srv, view: "inbox"}180 ls := &liveStream{s: srv, view: "inbox"}
181 frags, err := ls.render(withOwner(t.Context()), ports.WatchEvent{ID: "b-1", Event: domain.IssueOpened{Issue: domain.Issue{Repo: repoName(t, "beta"), Number: 7}}})181 frags, err := ls.render(withOwner(t.Context()), ports.WatchEvent{ID: "b-1", Event: domain.IssueOpened{Issue: domain.Issue{Repo: repoName(t, "beta"), Number: 7}}})
182 require.NoError(t, err)182 require.NoError(t, err)
183- require.Len(t, frags, 5)183+ require.Len(t, frags, 6)
184 assert.Contains(t, frags[0].html, `id="inbox-counts"`)184 assert.Contains(t, frags[0].html, `id="inbox-counts"`)
185 assert.Contains(t, frags[1].html, `id="inbox-repos"`)185 assert.Contains(t, frags[1].html, `id="inbox-repos"`)
186 assert.Contains(t, frags[2].html, `id="inbox-pending"`)186 assert.Contains(t, frags[2].html, `id="inbox-pending"`)
187- assert.Contains(t, frags[3].html, `id="inbox-mrs"`)187+ assert.Contains(t, frags[3].html, `id="inbox-runs"`)
188- assert.Contains(t, frags[4].html, `id="inbox-issues"`)188+ assert.Contains(t, frags[4].html, `id="inbox-mrs"`)
189+ assert.Contains(t, frags[5].html, `id="inbox-issues"`)
189 190
190 none, err := ls.render(withOwner(t.Context()), ports.WatchEvent{Event: domain.PushEvent{Repo: repoName(t, "beta")}})191 none, err := ls.render(withOwner(t.Context()), ports.WatchEvent{Event: domain.PushEvent{Repo: repoName(t, "beta")}})
191 require.NoError(t, err)192 require.NoError(t, err)
@@ -286,6 +287,7 @@ func TestInboxRefreshesOnRepoEvents(t *testing.T) {
286 t.Parallel()287 t.Parallel()
287 for name, ev := range map[string]domain.Event{288 for name, ev := range map[string]domain.Event{
288 "issues turned off": domain.RepoUpdated{Repo: repoName(t, "beta")},289 "issues turned off": domain.RepoUpdated{Repo: repoName(t, "beta")},
290+ "run updated": domain.RunUpdated{},
289 "repo deleted": domain.RepoDeleted{Repo: repoName(t, "beta")},291 "repo deleted": domain.RepoDeleted{Repo: repoName(t, "beta")},
290 } {292 } {
291 t.Run(name, func(t *testing.T) {293 t.Run(name, func(t *testing.T) {
@@ -297,7 +299,7 @@ func TestInboxRefreshesOnRepoEvents(t *testing.T) {
297 ls := &liveStream{s: srv, view: "inbox"}299 ls := &liveStream{s: srv, view: "inbox"}
298 frags, err := ls.render(withOwner(t.Context()), ports.WatchEvent{ID: "b-1", Event: ev})300 frags, err := ls.render(withOwner(t.Context()), ports.WatchEvent{ID: "b-1", Event: ev})
299 require.NoError(t, err)301 require.NoError(t, err)
300- require.Len(t, frags, 5)302+ require.Len(t, frags, 6)
301 all := ""303 all := ""
302 for _, f := range frags {304 for _, f := range frags {
303 all += f.html305 all += f.html
A internal/adapters/web/jstest/keys.test.mjs +29 -0
@@ -0,0 +1,29 @@
1+// Exercise the production keydown handler without loading the rest of the page.
2+import assert from 'node:assert/strict';
3+import { readFileSync } from 'node:fs';
4+import { test } from 'node:test';
5+const src = readFileSync(new URL('../static/js/ermite.js', import.meta.url), 'utf8');
6+const block = src.slice(src.indexOf(' // 1. Keys.'), src.indexOf(' // 2. A [data-fire]'));
7+
8+function page({ owner = true, off = false, typing = false, dialog = false } = {}) {
9+ let handler;
10+ const fired = [];
11+ const window = { ermiteKeys: { blocks: () => off } };
12+ const $ = (s) => s === 'dialog[open]' ? dialog : s === '[data-inbox]' ? owner : null;
13+ new Function('window', '$', 'ermite', 'addEventListener', block)(window, $, { fire: (n) => fired.push(n) }, (_, f) => { handler = f; });
14+ return (key) => {
15+ const e = { key, shiftKey: key === 'I', preventDefault() {}, target: { closest: (s) => s.startsWith('input') && typing } };
16+ handler(e);
17+ return fired;
18+ };
19+}
20+test('Shift+I opens inbox while lowercase i retains the issues tab', () => {
21+ const press = page();
22+ assert.deepEqual(press('I'), ['inbox']);
23+ assert.deepEqual(press('i'), ['inbox', 'i']);
24+});
25+test('inbox shortcut respects preference, fields, dialogs, and owner target', () => {
26+ for (const options of [{ off: true }, { typing: true }, { dialog: true }, { owner: false }]) {
27+ assert.deepEqual(page(options)('I'), [], JSON.stringify(options));
28+ }
29+});
@@ -0,0 +1,29 @@
1+// Exercise the production keydown handler without loading the rest of the page.
2+import assert from 'node:assert/strict';
3+import { readFileSync } from 'node:fs';
4+import { test } from 'node:test';
5+const src = readFileSync(new URL('../static/js/ermite.js', import.meta.url), 'utf8');
6+const block = src.slice(src.indexOf(' // 1. Keys.'), src.indexOf(' // 2. A [data-fire]'));
7+
8+function page({ owner = true, off = false, typing = false, dialog = false } = {}) {
9+ let handler;
10+ const fired = [];
11+ const window = { ermiteKeys: { blocks: () => off } };
12+ const $ = (s) => s === 'dialog[open]' ? dialog : s === '[data-inbox]' ? owner : null;
13+ new Function('window', '$', 'ermite', 'addEventListener', block)(window, $, { fire: (n) => fired.push(n) }, (_, f) => { handler = f; });
14+ return (key) => {
15+ const e = { key, shiftKey: key === 'I', preventDefault() {}, target: { closest: (s) => s.startsWith('input') && typing } };
16+ handler(e);
17+ return fired;
18+ };
19+}
20+test('Shift+I opens inbox while lowercase i retains the issues tab', () => {
21+ const press = page();
22+ assert.deepEqual(press('I'), ['inbox']);
23+ assert.deepEqual(press('i'), ['inbox', 'i']);
24+});
25+test('inbox shortcut respects preference, fields, dialogs, and owner target', () => {
26+ for (const options of [{ off: true }, { typing: true }, { dialog: true }, { owner: false }]) {
27+ assert.deepEqual(page(options)('I'), [], JSON.stringify(options));
28+ }
29+});
M internal/adapters/web/keys.templ +1 -0
@@ -28,6 +28,7 @@ templ Keys() {
2828 k-r from:body -> ermite.tab('r');
2929 k-m from:body -> ermite.tab('m');
3030 k-i from:body -> ermite.tab('i');
31+ k-inbox from:body -> ermite.go('[data-inbox]');
3132 k-next from:body -> ermite.nextNote();
3233 k-split from:body -> ermite.layout('split');
3334 k-unified from:body -> ermite.layout('unified');
@@ -28,6 +28,7 @@ templ Keys() {
28 k-r from:body -> ermite.tab('r');28 k-r from:body -> ermite.tab('r');
29 k-m from:body -> ermite.tab('m');29 k-m from:body -> ermite.tab('m');
30 k-i from:body -> ermite.tab('i');30 k-i from:body -> ermite.tab('i');
31+ k-inbox from:body -> ermite.go('[data-inbox]');
31 k-next from:body -> ermite.nextNote();32 k-next from:body -> ermite.nextNote();
32 k-split from:body -> ermite.layout('split');33 k-split from:body -> ermite.layout('split');
33 k-unified from:body -> ermite.layout('unified');34 k-unified from:body -> ermite.layout('unified');
M internal/adapters/web/keys_templ.go +1 -1 generated file: collapsed
M internal/adapters/web/overlays.templ +3 -0
@@ -27,6 +27,9 @@ templ OverlayHelp(mr bool) {
2727 <div><dt><kbd>/</kbd></dt><dd>filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)</dd></div>
2828 <div><dt><kbd>b</kbd></dt><dd>{ "switch" } branch or tag</dd></div>
2929 <div><dt><kbd>s</kbd> <kbd>t</kbd> <kbd>c</kbd> <kbd>r</kbd> <kbd>m</kbd> <kbd>i</kbd></dt><dd>tabs: summary, files, commits, branches &amp; tags, merge requests, issues</dd></div>
30+ if SignedIn(ctx) {
31+ <div><dt><kbd>I</kbd></dt><dd>inbox</dd></div>
32+ }
3033 <div><dt><kbd>g h</kbd></dt><dd>home</dd></div>
3134 <div><dt><kbd>w</kbd></dt><dd>wide mode: use the whole width of the screen, or not (remembered)</dd></div>
3235 <div><dt><kbd>y</kbd></dt><dd>copy a permalink pinned to the commit</dd></div>
@@ -27,6 +27,9 @@ templ OverlayHelp(mr bool) {
27 <div><dt><kbd>/</kbd></dt><dd>filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)</dd></div>27 <div><dt><kbd>/</kbd></dt><dd>filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)</dd></div>
28 <div><dt><kbd>b</kbd></dt><dd>{ "switch" } branch or tag</dd></div>28 <div><dt><kbd>b</kbd></dt><dd>{ "switch" } branch or tag</dd></div>
29 <div><dt><kbd>s</kbd> <kbd>t</kbd> <kbd>c</kbd> <kbd>r</kbd> <kbd>m</kbd> <kbd>i</kbd></dt><dd>tabs: summary, files, commits, branches &amp; tags, merge requests, issues</dd></div>29 <div><dt><kbd>s</kbd> <kbd>t</kbd> <kbd>c</kbd> <kbd>r</kbd> <kbd>m</kbd> <kbd>i</kbd></dt><dd>tabs: summary, files, commits, branches &amp; tags, merge requests, issues</dd></div>
30+ if SignedIn(ctx) {
31+ <div><dt><kbd>I</kbd></dt><dd>inbox</dd></div>
32+ }
30 <div><dt><kbd>g h</kbd></dt><dd>home</dd></div>33 <div><dt><kbd>g h</kbd></dt><dd>home</dd></div>
31 <div><dt><kbd>w</kbd></dt><dd>wide mode: use the whole width of the screen, or not (remembered)</dd></div>34 <div><dt><kbd>w</kbd></dt><dd>wide mode: use the whole width of the screen, or not (remembered)</dd></div>
32 <div><dt><kbd>y</kbd></dt><dd>copy a permalink pinned to the commit</dd></div>35 <div><dt><kbd>y</kbd></dt><dd>copy a permalink pinned to the commit</dd></div>
M internal/adapters/web/overlays_templ.go +49 -39 generated file: collapsed
M internal/adapters/web/shell.templ +5 -1
@@ -67,6 +67,9 @@ templ Shell(l Layout, rail templ.Component) {
6767 </div>
6868 @Footer(l)
6969 @Hint(l)
70+ if SignedIn(ctx) {
71+ <a hidden data-inbox href={ inboxPath }>Inbox</a>
72+ }
7073 @OverlayHelp(l.MR)
7174 @OverlayRefs(l)
7275 @OverlayCmd(l.Cmd)
@@ -87,7 +90,8 @@ templ Header(l Layout) {
8790 <a
8891 class="btn inbox-btn"
8992 href={ templ.SafeURL(l.Inbox.Href) }
90- title="inbox"
93+ title="inbox (I)"
94+ aria-keyshortcuts="Shift+I"
9195 >
9296 <span class="ico i-mailbox" aria-hidden="true"></span>
9397 Inbox
@@ -67,6 +67,9 @@ templ Shell(l Layout, rail templ.Component) {
67 </div>67 </div>
68 @Footer(l)68 @Footer(l)
69 @Hint(l)69 @Hint(l)
70+ if SignedIn(ctx) {
71+ <a hidden data-inbox href={ inboxPath }>Inbox</a>
72+ }
70 @OverlayHelp(l.MR)73 @OverlayHelp(l.MR)
71 @OverlayRefs(l)74 @OverlayRefs(l)
72 @OverlayCmd(l.Cmd)75 @OverlayCmd(l.Cmd)
@@ -87,7 +90,8 @@ templ Header(l Layout) {
87 <a90 <a
88 class="btn inbox-btn"91 class="btn inbox-btn"
89 href={ templ.SafeURL(l.Inbox.Href) }92 href={ templ.SafeURL(l.Inbox.Href) }
90- title="inbox"93+ title="inbox (I)"
94+ aria-keyshortcuts="Shift+I"
91 >95 >
92 <span class="ico i-mailbox" aria-hidden="true"></span>96 <span class="ico i-mailbox" aria-hidden="true"></span>
93 Inbox97 Inbox
M internal/adapters/web/shell_templ.go +152 -133 generated file: collapsed
M internal/adapters/web/static/js/ermite.js +2 -2
@@ -612,7 +612,7 @@
612612
613613 // 1. Keys.
614614 const single = { j: 'j', k: 'k', G: 'bottom', '/': 'filter', '?': 'help', b: 'refs', f: 'cmd', ':': 'cmd', y: 'permalink',
615- s: 's', t: 't', c: 'c', r: 'r', m: 'm', i: 'i', n: 'next', h: 'left', l: 'right', d: 'split', u: 'unified', x: 'collapse', w: 'wide', e: 'expand', E: 'expandAll', Enter: 'open', Escape: 'esc',
615+ s: 's', t: 't', c: 'c', r: 'r', m: 'm', i: 'i', I: 'inbox', n: 'next', h: 'left', l: 'right', d: 'split', u: 'unified', x: 'collapse', w: 'wide', e: 'expand', E: 'expandAll', Enter: 'open', Escape: 'esc',
616616 // the merge request page (mr.js): the merge menu, mark read
617617 M: 'merge', R: 'read' };
618618 // "g t" is the key "t": the tabs have one event each.
@@ -654,7 +654,7 @@
654654 // page-level keys, as on the other lists.
655655 if (!e.shiftKey && e.target.closest?.('#tree-rows') && window.ermiteTree?.arrow(e.key)) { e.preventDefault(); return; }
656656 const name = single[e.key];
657- if (!name) return;
657+ if (!name || (name === 'inbox' && !$('[data-inbox]'))) return;
658658 if (e.key !== 'Enter' || !$('dialog[open]')) e.preventDefault();
659659 ermite.fire(name);
660660 });
@@ -612,7 +612,7 @@
612 612
613 // 1. Keys.613 // 1. Keys.
614 const single = { j: 'j', k: 'k', G: 'bottom', '/': 'filter', '?': 'help', b: 'refs', f: 'cmd', ':': 'cmd', y: 'permalink',614 const single = { j: 'j', k: 'k', G: 'bottom', '/': 'filter', '?': 'help', b: 'refs', f: 'cmd', ':': 'cmd', y: 'permalink',
615- s: 's', t: 't', c: 'c', r: 'r', m: 'm', i: 'i', n: 'next', h: 'left', l: 'right', d: 'split', u: 'unified', x: 'collapse', w: 'wide', e: 'expand', E: 'expandAll', Enter: 'open', Escape: 'esc',615+ s: 's', t: 't', c: 'c', r: 'r', m: 'm', i: 'i', I: 'inbox', n: 'next', h: 'left', l: 'right', d: 'split', u: 'unified', x: 'collapse', w: 'wide', e: 'expand', E: 'expandAll', Enter: 'open', Escape: 'esc',
616 // the merge request page (mr.js): the merge menu, mark read616 // the merge request page (mr.js): the merge menu, mark read
617 M: 'merge', R: 'read' };617 M: 'merge', R: 'read' };
618 // "g t" is the key "t": the tabs have one event each.618 // "g t" is the key "t": the tabs have one event each.
@@ -654,7 +654,7 @@
654 // page-level keys, as on the other lists.654 // page-level keys, as on the other lists.
655 if (!e.shiftKey && e.target.closest?.('#tree-rows') && window.ermiteTree?.arrow(e.key)) { e.preventDefault(); return; }655 if (!e.shiftKey && e.target.closest?.('#tree-rows') && window.ermiteTree?.arrow(e.key)) { e.preventDefault(); return; }
656 const name = single[e.key];656 const name = single[e.key];
657- if (!name) return;657+ if (!name || (name === 'inbox' && !$('[data-inbox]'))) return;
658 if (e.key !== 'Enter' || !$('dialog[open]')) e.preventDefault();658 if (e.key !== 'Enter' || !$('dialog[open]')) e.preventDefault();
659 ermite.fire(name);659 ermite.fire(name);
660 });660 });
M internal/app/forge.go +1 -1
@@ -412,7 +412,7 @@ func newForge(ctx context.Context, cfg config.Config, opts options) (_ *forge, e
412412 BaseDifficulty: opts.issuePoW, MaxDifficulty: opts.issuePoW, MinFillTime: fastFill(opts.issuePoW),
413413 })
414414 f.Inbox = usecase.NewInbox(usecase.InboxConfig{
415- Meta: store, MergeRequests: store.MergeRequests(), Issues: store.Issues(), Pending: store.PendingIssues(),
415+ Meta: store, MergeRequests: store.MergeRequests(), Issues: store.Issues(), Pending: store.PendingIssues(), CI: store.CI(),
416416 })
417417 f.CI.SetPullGate(f.MergeRequests)
418418 f.AutoMerge.Start()
@@ -412,7 +412,7 @@ func newForge(ctx context.Context, cfg config.Config, opts options) (_ *forge, e
412 BaseDifficulty: opts.issuePoW, MaxDifficulty: opts.issuePoW, MinFillTime: fastFill(opts.issuePoW),412 BaseDifficulty: opts.issuePoW, MaxDifficulty: opts.issuePoW, MinFillTime: fastFill(opts.issuePoW),
413 })413 })
414 f.Inbox = usecase.NewInbox(usecase.InboxConfig{414 f.Inbox = usecase.NewInbox(usecase.InboxConfig{
415- Meta: store, MergeRequests: store.MergeRequests(), Issues: store.Issues(), Pending: store.PendingIssues(),415+ Meta: store, MergeRequests: store.MergeRequests(), Issues: store.Issues(), Pending: store.PendingIssues(), CI: store.CI(),
416 })416 })
417 f.CI.SetPullGate(f.MergeRequests)417 f.CI.SetPullGate(f.MergeRequests)
418 f.AutoMerge.Start()418 f.AutoMerge.Start()
M internal/app/testdata/web/blob-binary.html +1 -0
@@ -428,6 +428,7 @@
428428 k-r from:body -> ermite.tab('r');
429429 k-m from:body -> ermite.tab('m');
430430 k-i from:body -> ermite.tab('i');
431+ k-inbox from:body -> ermite.go('[data-inbox]');
431432 k-next from:body -> ermite.nextNote();
432433 k-split from:body -> ermite.layout('split');
433434 k-unified from:body -> ermite.layout('unified');
@@ -428,6 +428,7 @@
428 k-r from:body -> ermite.tab('r');428 k-r from:body -> ermite.tab('r');
429 k-m from:body -> ermite.tab('m');429 k-m from:body -> ermite.tab('m');
430 k-i from:body -> ermite.tab('i');430 k-i from:body -> ermite.tab('i');
431+ k-inbox from:body -> ermite.go('[data-inbox]');
431 k-next from:body -> ermite.nextNote();432 k-next from:body -> ermite.nextNote();
432 k-split from:body -> ermite.layout('split');433 k-split from:body -> ermite.layout('split');
433 k-unified from:body -> ermite.layout('unified');434 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-code.html +1 -0
@@ -498,6 +498,7 @@
498498 k-r from:body -> ermite.tab('r');
499499 k-m from:body -> ermite.tab('m');
500500 k-i from:body -> ermite.tab('i');
501+ k-inbox from:body -> ermite.go('[data-inbox]');
501502 k-next from:body -> ermite.nextNote();
502503 k-split from:body -> ermite.layout('split');
503504 k-unified from:body -> ermite.layout('unified');
@@ -498,6 +498,7 @@
498 k-r from:body -> ermite.tab('r');498 k-r from:body -> ermite.tab('r');
499 k-m from:body -> ermite.tab('m');499 k-m from:body -> ermite.tab('m');
500 k-i from:body -> ermite.tab('i');500 k-i from:body -> ermite.tab('i');
501+ k-inbox from:body -> ermite.go('[data-inbox]');
501 k-next from:body -> ermite.nextNote();502 k-next from:body -> ermite.nextNote();
502 k-split from:body -> ermite.layout('split');503 k-split from:body -> ermite.layout('split');
503 k-unified from:body -> ermite.layout('unified');504 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-empty.html +1 -0
@@ -428,6 +428,7 @@
428428 k-r from:body -> ermite.tab('r');
429429 k-m from:body -> ermite.tab('m');
430430 k-i from:body -> ermite.tab('i');
431+ k-inbox from:body -> ermite.go('[data-inbox]');
431432 k-next from:body -> ermite.nextNote();
432433 k-split from:body -> ermite.layout('split');
433434 k-unified from:body -> ermite.layout('unified');
@@ -428,6 +428,7 @@
428 k-r from:body -> ermite.tab('r');428 k-r from:body -> ermite.tab('r');
429 k-m from:body -> ermite.tab('m');429 k-m from:body -> ermite.tab('m');
430 k-i from:body -> ermite.tab('i');430 k-i from:body -> ermite.tab('i');
431+ k-inbox from:body -> ermite.go('[data-inbox]');
431 k-next from:body -> ermite.nextNote();432 k-next from:body -> ermite.nextNote();
432 k-split from:body -> ermite.layout('split');433 k-split from:body -> ermite.layout('split');
433 k-unified from:body -> ermite.layout('unified');434 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-image.html +1 -0
@@ -430,6 +430,7 @@
430430 k-r from:body -> ermite.tab('r');
431431 k-m from:body -> ermite.tab('m');
432432 k-i from:body -> ermite.tab('i');
433+ k-inbox from:body -> ermite.go('[data-inbox]');
433434 k-next from:body -> ermite.nextNote();
434435 k-split from:body -> ermite.layout('split');
435436 k-unified from:body -> ermite.layout('unified');
@@ -430,6 +430,7 @@
430 k-r from:body -> ermite.tab('r');430 k-r from:body -> ermite.tab('r');
431 k-m from:body -> ermite.tab('m');431 k-m from:body -> ermite.tab('m');
432 k-i from:body -> ermite.tab('i');432 k-i from:body -> ermite.tab('i');
433+ k-inbox from:body -> ermite.go('[data-inbox]');
433 k-next from:body -> ermite.nextNote();434 k-next from:body -> ermite.nextNote();
434 k-split from:body -> ermite.layout('split');435 k-split from:body -> ermite.layout('split');
435 k-unified from:body -> ermite.layout('unified');436 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-markdown.html +1 -0
@@ -495,6 +495,7 @@
495495 k-r from:body -> ermite.tab('r');
496496 k-m from:body -> ermite.tab('m');
497497 k-i from:body -> ermite.tab('i');
498+ k-inbox from:body -> ermite.go('[data-inbox]');
498499 k-next from:body -> ermite.nextNote();
499500 k-split from:body -> ermite.layout('split');
500501 k-unified from:body -> ermite.layout('unified');
@@ -495,6 +495,7 @@
495 k-r from:body -> ermite.tab('r');495 k-r from:body -> ermite.tab('r');
496 k-m from:body -> ermite.tab('m');496 k-m from:body -> ermite.tab('m');
497 k-i from:body -> ermite.tab('i');497 k-i from:body -> ermite.tab('i');
498+ k-inbox from:body -> ermite.go('[data-inbox]');
498 k-next from:body -> ermite.nextNote();499 k-next from:body -> ermite.nextNote();
499 k-split from:body -> ermite.layout('split');500 k-split from:body -> ermite.layout('split');
500 k-unified from:body -> ermite.layout('unified');501 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-svg.html +1 -0
@@ -453,6 +453,7 @@
453453 k-r from:body -> ermite.tab('r');
454454 k-m from:body -> ermite.tab('m');
455455 k-i from:body -> ermite.tab('i');
456+ k-inbox from:body -> ermite.go('[data-inbox]');
456457 k-next from:body -> ermite.nextNote();
457458 k-split from:body -> ermite.layout('split');
458459 k-unified from:body -> ermite.layout('unified');
@@ -453,6 +453,7 @@
453 k-r from:body -> ermite.tab('r');453 k-r from:body -> ermite.tab('r');
454 k-m from:body -> ermite.tab('m');454 k-m from:body -> ermite.tab('m');
455 k-i from:body -> ermite.tab('i');455 k-i from:body -> ermite.tab('i');
456+ k-inbox from:body -> ermite.go('[data-inbox]');
456 k-next from:body -> ermite.nextNote();457 k-next from:body -> ermite.nextNote();
457 k-split from:body -> ermite.layout('split');458 k-split from:body -> ermite.layout('split');
458 k-unified from:body -> ermite.layout('unified');459 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-text.html +1 -0
@@ -448,6 +448,7 @@
448448 k-r from:body -> ermite.tab('r');
449449 k-m from:body -> ermite.tab('m');
450450 k-i from:body -> ermite.tab('i');
451+ k-inbox from:body -> ermite.go('[data-inbox]');
451452 k-next from:body -> ermite.nextNote();
452453 k-split from:body -> ermite.layout('split');
453454 k-unified from:body -> ermite.layout('unified');
@@ -448,6 +448,7 @@
448 k-r from:body -> ermite.tab('r');448 k-r from:body -> ermite.tab('r');
449 k-m from:body -> ermite.tab('m');449 k-m from:body -> ermite.tab('m');
450 k-i from:body -> ermite.tab('i');450 k-i from:body -> ermite.tab('i');
451+ k-inbox from:body -> ermite.go('[data-inbox]');
451 k-next from:body -> ermite.nextNote();452 k-next from:body -> ermite.nextNote();
452 k-split from:body -> ermite.layout('split');453 k-split from:body -> ermite.layout('split');
453 k-unified from:body -> ermite.layout('unified');454 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-too-large.html +1 -0
@@ -428,6 +428,7 @@
428428 k-r from:body -> ermite.tab('r');
429429 k-m from:body -> ermite.tab('m');
430430 k-i from:body -> ermite.tab('i');
431+ k-inbox from:body -> ermite.go('[data-inbox]');
431432 k-next from:body -> ermite.nextNote();
432433 k-split from:body -> ermite.layout('split');
433434 k-unified from:body -> ermite.layout('unified');
@@ -428,6 +428,7 @@
428 k-r from:body -> ermite.tab('r');428 k-r from:body -> ermite.tab('r');
429 k-m from:body -> ermite.tab('m');429 k-m from:body -> ermite.tab('m');
430 k-i from:body -> ermite.tab('i');430 k-i from:body -> ermite.tab('i');
431+ k-inbox from:body -> ermite.go('[data-inbox]');
431 k-next from:body -> ermite.nextNote();432 k-next from:body -> ermite.nextNote();
432 k-split from:body -> ermite.layout('split');433 k-split from:body -> ermite.layout('split');
433 k-unified from:body -> ermite.layout('unified');434 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/blob-trojan.html +1 -0
@@ -495,6 +495,7 @@
495495 k-r from:body -> ermite.tab('r');
496496 k-m from:body -> ermite.tab('m');
497497 k-i from:body -> ermite.tab('i');
498+ k-inbox from:body -> ermite.go('[data-inbox]');
498499 k-next from:body -> ermite.nextNote();
499500 k-split from:body -> ermite.layout('split');
500501 k-unified from:body -> ermite.layout('unified');
@@ -495,6 +495,7 @@
495 k-r from:body -> ermite.tab('r');495 k-r from:body -> ermite.tab('r');
496 k-m from:body -> ermite.tab('m');496 k-m from:body -> ermite.tab('m');
497 k-i from:body -> ermite.tab('i');497 k-i from:body -> ermite.tab('i');
498+ k-inbox from:body -> ermite.go('[data-inbox]');
498 k-next from:body -> ermite.nextNote();499 k-next from:body -> ermite.nextNote();
499 k-split from:body -> ermite.layout('split');500 k-split from:body -> ermite.layout('split');
500 k-unified from:body -> ermite.layout('unified');501 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/commit-big.html +1 -0
@@ -480,6 +480,7 @@
480480 k-r from:body -> ermite.tab('r');
481481 k-m from:body -> ermite.tab('m');
482482 k-i from:body -> ermite.tab('i');
483+ k-inbox from:body -> ermite.go('[data-inbox]');
483484 k-next from:body -> ermite.nextNote();
484485 k-split from:body -> ermite.layout('split');
485486 k-unified from:body -> ermite.layout('unified');
@@ -480,6 +480,7 @@
480 k-r from:body -> ermite.tab('r');480 k-r from:body -> ermite.tab('r');
481 k-m from:body -> ermite.tab('m');481 k-m from:body -> ermite.tab('m');
482 k-i from:body -> ermite.tab('i');482 k-i from:body -> ermite.tab('i');
483+ k-inbox from:body -> ermite.go('[data-inbox]');
483 k-next from:body -> ermite.nextNote();484 k-next from:body -> ermite.nextNote();
484 k-split from:body -> ermite.layout('split');485 k-split from:body -> ermite.layout('split');
485 k-unified from:body -> ermite.layout('unified');486 k-unified from:body -> ermite.layout('unified');
M internal/app/testdata/web/commit-binary.html +1 -0
M internal/app/testdata/web/commit-merge.html +1 -0
M internal/app/testdata/web/commit-modify-split.html +1 -0
M internal/app/testdata/web/commit-modify.html +1 -0
M internal/app/testdata/web/commit-rename.html +1 -0
M internal/app/testdata/web/commit-root.html +1 -0
M internal/app/testdata/web/commit-trojan.html +1 -0
M internal/app/testdata/web/commits-page2.html +1 -0
M internal/app/testdata/web/commits-path.html +1 -0
M internal/app/testdata/web/commits-root.html +1 -0
M internal/app/testdata/web/commits-small.html +1 -0
M internal/app/testdata/web/empty.html +1 -0
M internal/app/testdata/web/home.html +1 -0
M internal/app/testdata/web/not-found-page.html +1 -0
M internal/app/testdata/web/not-found.html +1 -0
M internal/app/testdata/web/refs.html +1 -0
M internal/app/testdata/web/summary.html +1 -0
M internal/app/testdata/web/tree-nested.html +1 -0
M internal/app/testdata/web/tree-root.html +1 -0
M internal/app/testdata/web/tree-slash-ref.html +1 -0
M internal/app/testdata/web/tree-subdir.html +1 -0
M internal/app/web_inbox_test.go +32 -2
M internal/ports/dto.go +6 -3
M internal/usecase/events.go +2 -2
M internal/usecase/inbox.go +31 -2
M internal/usecase/inbox_test.go +33 -0
M skills/ermite/SKILL.md +0 -13

Comments0 open / 0

no comments yet.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
l
merge request: the list of files (j k move, enter opens, esc back)
M
merge request: the merge menu; there 1–3 pick the mode, D deletes the branch, enter merges
R
merge request: mark the head read
esc
close a dialog, leave a field

Branches 2

Tags 42

↑↓ moveenter openesc close