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) }