package web
import (
"errors"
"net/http"
"github.com/go-chi/chi/v5"
"sourcecraft.dev/bigbes/sr-ht-dolt/browse"
"sourcecraft.dev/bigbes/sr-ht-dolt/core"
)
// handleView renders a specialized alternative view of a repository. The view
// is selected by the {view} URL slug and must both exist in a.views and Apply
// to the tables at the resolved ref; otherwise the request is a 404 (the view
// simply does not exist for this repo). The generic table browser remains
// reachable via the tree/table routes regardless.
//
// The ref is taken from ?ref= (default: the repo's default branch). The view's
// own Template() is rendered with a fixed envelope: the chrome, the repo, the
// ref and branch list, the applicable view tabs, and the opaque value the view
// produced from Build (as .Data).
func (a *app) handleView(w http.ResponseWriter, r *http.Request) {
repo, _, _, ok := a.loadRepoForBrowse(w, r)
if !ok {
return
}
sess, ok := a.openBrowse(w, r, repo)
if !ok {
return
}
defer sess.Close()
ref := r.URL.Query().Get("ref")
if ref == "" {
branches, err := sess.Branches(r.Context())
if err != nil {
http.Error(w, "failed to list branches", http.StatusInternalServerError)
return
}
ref = browse.DefaultBranch(branches)
}
tables, err := sess.Tables(r.Context(), ref)
if err != nil {
if errors.Is(err, browse.ErrRefNotFound) {
a.notFound(w, r)
return
}
http.Error(w, "failed to read tables", http.StatusInternalServerError)
return
}
// Find the requested view; an unknown slug or a view that does not fingerprint
// these tables is reported as not found — the view does not exist here.
slug := chi.URLParam(r, "view")
var view View
for _, v := range a.views {
if v.Name() == slug {
view = v
break
}
}
if view == nil || !view.Applies(tables) {
a.notFound(w, r)
return
}
data, err := view.Build(r.Context(), sess, repo, ref, r.URL.Query())
if err != nil {
http.Error(w, "failed to build view", http.StatusInternalServerError)
return
}
// Re-list branches for the chrome/tab bar. Cheap and keeps the ref selector
// consistent whether or not ?ref= was supplied.
branches, _ := sess.Branches(r.Context())
page := struct {
basePage
Repo *core.Repo
Ref string
Branches []browse.Branch
Views []View
Data any
}{
basePage: a.newBasePage(r, view.Label()+" — "+repo.OwnerName+"/"+repo.Name),
Repo: repo,
Ref: ref,
Branches: branches,
Views: applicableViews(a.views, tables),
Data: data,
}
a.render(w, http.StatusOK, view.Template(), page)
}