Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Show open work on repository tabs and overview

a196e404c86a5b9607bd226c7229ffc89a37d47f · Keenan Nemetz · 11d ago · parent 0e35a6a0

Show open work on repository tabs and overview

The repository header now counts open issues and change requests, and the overview sidebar lists the newest open issues and change requests with links to their full lists. Closed and merged records stay out of both: the counts and the overview describe what is still being worked on.

Issue counts come from the derived index; change requests are read from the metadata branch, where their state lives. A failed read leaves a zero or an empty section rather than turning the overview into an error page.

server/web/overview_test.go +33

@@ -0,0 +1,33 @@
1 package web
2
3 import (
4 "testing"
5 "time"
6 )
7
8 func TestNewestOverviewSortsAndLimits(t *testing.T) {
9 base := time.Date(2026, 10, 22, 12, 0, 0, 0, time.UTC)
10 list := []overviewEntity{
11 {ID: "b", Created: base},
12 {ID: "newest", Created: base.Add(2 * time.Hour)},
13 {ID: "c", Created: base.Add(-time.Hour)},
14 {ID: "a", Created: base},
15 {ID: "oldest", Created: base.Add(-2 * time.Hour)},
16 {ID: "d", Created: base.Add(-3 * time.Hour)},
17 {ID: "e", Created: base.Add(-4 * time.Hour)},
18 }
19 got := newestOverview(list)
20 if len(got) != overviewSideLimit {
21 t.Fatalf("newestOverview returned %d rows, want %d", len(got), overviewSideLimit)
22 }
23 if got[0].ID != "newest" {
24 t.Fatalf("first row = %q, want newest", got[0].ID)
25 }
26 // Equal timestamps are ordered by id, not by the order the rows arrived in.
27 if got[1].ID != "b" || got[2].ID != "a" {
28 t.Fatalf("tied rows = %q, %q; want b then a", got[1].ID, got[2].ID)
29 }
30 if got[len(got)-1].ID != "oldest" {
31 t.Fatalf("last row = %q, want oldest after the limit", got[len(got)-1].ID)
32 }
33 }