ikurotime / gitgud

public
main / internal/interface/web/issue_handler.go
3.8 KB · Go Raw
  1package web
  2
  3import (
  4	"errors"
  5	"net/http"
  6	"strconv"
  7	"strings"
  8
  9	"github.com/go-chi/chi"
 10
 11	"gitgud/internal/app"
 12	"gitgud/internal/domain"
 13	"gitgud/internal/interface/web/templates"
 14)
 15
 16func (h *Handlers) issuesList(w http.ResponseWriter, r *http.Request) {
 17	repo := h.viewRepo(w, r)
 18	if repo == nil {
 19		return
 20	}
 21
 22	state := r.URL.Query().Get("state")
 23	var filter domain.IssueState
 24	switch state {
 25	case "closed":
 26		filter = domain.IssueClosed
 27	case "all":
 28		filter = ""
 29	default:
 30		state = "open"
 31		filter = domain.IssueOpen
 32	}
 33
 34	issues, err := h.issues.List(r.Context(), repo.ID, filter)
 35	if err != nil {
 36		h.writeError(w, r, err)
 37		return
 38	}
 39	open, closed, err := h.issues.Counts(r.Context(), repo.ID)
 40	if err != nil {
 41		h.writeError(w, r, err)
 42		return
 43	}
 44	render(w, r, http.StatusOK, templates.IssuesList(currentUser(r.Context()), repo, state, issues, open, closed))
 45}
 46
 47func (h *Handlers) newIssue(w http.ResponseWriter, r *http.Request) {
 48	repo := h.viewRepo(w, r)
 49	if repo == nil {
 50		return
 51	}
 52	render(w, r, http.StatusOK, templates.IssueNew(currentUser(r.Context()), repo, "", "", ""))
 53}
 54
 55func (h *Handlers) createIssue(w http.ResponseWriter, r *http.Request) {
 56	repo := h.viewRepo(w, r)
 57	if repo == nil {
 58		return
 59	}
 60	title := r.FormValue("title")
 61	body := r.FormValue("body")
 62
 63	issue, err := h.issues.Open(r.Context(), repo, currentUser(r.Context()), title, body)
 64	if err != nil {
 65		if errors.Is(err, domain.ErrValidation) {
 66			msg := strings.TrimSuffix(err.Error(), ": "+domain.ErrValidation.Error())
 67			render(w, r, http.StatusBadRequest, templates.IssueNew(currentUser(r.Context()), repo, title, body, msg))
 68			return
 69		}
 70		h.writeError(w, r, err)
 71		return
 72	}
 73	http.Redirect(w, r, repoURL(repo, "/issues/"+strconv.Itoa(issue.Number)), http.StatusSeeOther)
 74}
 75
 76func (h *Handlers) issueDetail(w http.ResponseWriter, r *http.Request) {
 77	repo, issue := h.loadIssue(w, r)
 78	if issue == nil {
 79		return
 80	}
 81	comments, err := h.issues.Comments(r.Context(), issue.ID)
 82	if err != nil {
 83		h.writeError(w, r, err)
 84		return
 85	}
 86	canModify := app.CanModifyIssue(repo, issue, currentUser(r.Context()))
 87	render(w, r, http.StatusOK, templates.IssueDetail(currentUser(r.Context()), repo, issue, comments, canModify))
 88}
 89
 90func (h *Handlers) addIssueComment(w http.ResponseWriter, r *http.Request) {
 91	repo, issue := h.loadIssue(w, r)
 92	if issue == nil {
 93		return
 94	}
 95	if err := h.issues.Comment(r.Context(), issue, currentUser(r.Context()), r.FormValue("body")); err != nil {
 96		h.writeError(w, r, err)
 97		return
 98	}
 99	http.Redirect(w, r, repoURL(repo, "/issues/"+strconv.Itoa(issue.Number)), http.StatusSeeOther)
100}
101
102func (h *Handlers) closeIssue(w http.ResponseWriter, r *http.Request) {
103	repo, issue := h.loadIssue(w, r)
104	if issue == nil {
105		return
106	}
107	if err := h.issues.Close(r.Context(), repo, issue, currentUser(r.Context())); err != nil {
108		h.writeError(w, r, err)
109		return
110	}
111	http.Redirect(w, r, repoURL(repo, "/issues/"+strconv.Itoa(issue.Number)), http.StatusSeeOther)
112}
113
114func (h *Handlers) reopenIssue(w http.ResponseWriter, r *http.Request) {
115	repo, issue := h.loadIssue(w, r)
116	if issue == nil {
117		return
118	}
119	if err := h.issues.Reopen(r.Context(), repo, issue, currentUser(r.Context())); err != nil {
120		h.writeError(w, r, err)
121		return
122	}
123	http.Redirect(w, r, repoURL(repo, "/issues/"+strconv.Itoa(issue.Number)), http.StatusSeeOther)
124}
125
126func (h *Handlers) loadIssue(w http.ResponseWriter, r *http.Request) (*domain.Repository, *domain.Issue) {
127	repo := h.viewRepo(w, r)
128	if repo == nil {
129		return nil, nil
130	}
131	number, err := strconv.Atoi(chi.URLParam(r, "number"))
132	if err != nil {
133		h.notFound(w, r)
134		return nil, nil
135	}
136	issue, _, err := h.issues.Get(r.Context(), repo.ID, number)
137	if err != nil {
138		h.writeError(w, r, err)
139		return nil, nil
140	}
141	return repo, issue
142}
143
144func repoURL(repo *domain.Repository, sub string) string {
145	return "/" + repo.OwnerName + "/" + repo.Name + sub
146}