Files
projax/gitea/repo.go
mAi 0c3507c6d7 feat(phase 3g dashboard polish): stale-projects card + refresh button + empty-collapse
- gitea.GetRepo returns FullName + UpdatedAt for the stale-card probe
- dashboard collectStale: mai-managed items + linked-repo updated_at >60d
  + zero open tasks + zero open issues. Sorted longest-stale first, ≤20.
  Multi-repo items need ALL repos quiet to count as stale. Reuses the
  4-worker pool + the already-aggregated task/issue counts from the
  Tasks / Issues cards (no extra DAV/Gitea fetches).
- dashboardCache.invalidate(key) busts a single filter's cache entry;
  ?refresh=1 routes through it so ↻ button gets fresh data.
- "updated Nm ago · cached/fresh" label + ↻ refresh link in dashboard
  chrome.
- Empty-card collapse: with no filter + zero rows the card renders as
  a one-line muted note instead of full chrome. Filter-active cards
  keep chrome so m can tell "filter hid it" from "nothing there".
- design.md §"Dashboard / daily-driver view" extended with the 4 new
  surfaces; the 3e "stale (3f)" out-of-scope line dropped.
- 5 new tests: stale-surface, stale-skip-recent, refresh-busts-cache,
  empty-collapse, filter-keeps-chrome. 2 unit tests for gitea.GetRepo.
2026-05-15 19:13:43 +02:00

41 lines
1.1 KiB
Go

package gitea
import (
"context"
"encoding/json"
"time"
)
// Repo is the slice of /repos/{owner}/{repo} projax cares about for the
// stale-projects dashboard card: the timestamp Gitea last touched the repo
// (commits, issues, releases all bump this).
type Repo struct {
FullName string // e.g. "m/projax"
UpdatedAt time.Time
Empty bool // freshly-created repo with no commits yet
}
type rawRepo struct {
FullName string `json:"full_name"`
UpdatedAt time.Time `json:"updated_at"`
Empty bool `json:"empty"`
}
// GetRepo fetches the repo's metadata. Returns ErrNotFound when the API
// returns 404 (repo renamed / deleted / token lacks access).
func (c *Client) GetRepo(ctx context.Context, owner, repo string) (*Repo, error) {
resp, err := c.do(ctx, "GET", "/repos/"+owner+"/"+repo, nil, nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, readErr(resp, "get repo")
}
var r rawRepo
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return nil, err
}
return &Repo{FullName: r.FullName, UpdatedAt: r.UpdatedAt, Empty: r.Empty}, nil
}