package web
import (
"net/http"
"strconv"
"sourcecraft.dev/bigbes/sr-ht-spec/service"
)
// inboxData is the review-queue page: the open proposals waiting on the owner,
// and the digest of what auto-merged without stopping for review.
type inboxData struct {
Open []proposalRow
Digest []proposalRow
}
// proposalRow is one proposal as a listing line: enough to decide whether to
// open it, and the link that does.
type proposalRow struct {
Href string
ID int
Space string
Title string
Agent string
Approval string
}
// handleInbox renders the review queue: every open proposal on the instance,
// plus the digest of recently policy-merged content. It is the backstop the
// design describes — the link an agent hands you is the normal way in, and this
// catches the work no link reached.
func (s *Server) handleInbox(w http.ResponseWriter, r *http.Request) {
if !mayRead(r) {
s.loginRedirect(w, r)
return
}
open, err := s.reader.Inbox(r.Context())
if err != nil {
s.fail(w, r, err)
return
}
digest, err := s.reader.Digest(r.Context())
if err != nil {
s.fail(w, r, err)
return
}
vd := s.chrome(r)
vd.Title = "Review queue"
vd.Data = inboxData{
Open: proposalRows(open),
Digest: proposalRows(digest),
}
s.render(w, http.StatusOK, "inbox", vd)
}
// proposalRows turns service proposals into listing rows, building each one's
// link from its space and id — the same stable /~owner/space/p/<id> shape the
// write plane hands back.
func proposalRows(ps []service.Proposal) []proposalRow {
rows := make([]proposalRow, 0, len(ps))
for _, p := range ps {
rows = append(rows, proposalRow{
Href: proposalHref(p),
ID: p.ID,
Space: p.Space.String(),
Title: p.Title,
Agent: p.Agent,
Approval: string(p.Approval),
})
}
return rows
}
// proposalHref is the review-page link for a proposal: the same path the
// proposal URL uses, minus the origin, so it works as a relative link in the UI.
func proposalHref(p service.Proposal) string {
return "/" + p.Space.String() + "/p/" + strconv.Itoa(p.ID)
}