196 lines
4.9 KiB
Go

package issue
import (
"context"
"net/http"
"strings"
"forge.cadoles.com/wpetit/clearcase/internal/core/service"
httpCtx "forge.cadoles.com/wpetit/clearcase/internal/http/context"
"forge.cadoles.com/wpetit/clearcase/internal/http/form"
"forge.cadoles.com/wpetit/clearcase/internal/http/handler/webui/common"
"forge.cadoles.com/wpetit/clearcase/internal/http/handler/webui/issue/component"
"forge.cadoles.com/wpetit/clearcase/internal/http/url"
"github.com/a-h/templ"
"github.com/pkg/errors"
)
func (h *Handler) getIssuePage(w http.ResponseWriter, r *http.Request) {
vmodel, err := h.fillIssuePageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
issue := component.IssuePage(*vmodel)
templ.Handler(issue).ServeHTTP(w, r)
}
func (h *Handler) fillIssuePageVModel(r *http.Request) (*component.IssuePageVModel, error) {
vmodel := &component.IssuePageVModel{
SummaryForm: component.NewIssueSummaryForm(),
IssueForm: component.NewIssueForm(),
}
err := common.FillViewModel(
r.Context(), vmodel, r,
h.fillIssuePageProjects,
h.fillIssuePageSelectedProject,
)
if err != nil {
return nil, errors.WithStack(err)
}
return vmodel, nil
}
func (h *Handler) fillIssuePageProjects(ctx context.Context, vmodel *component.IssuePageVModel, r *http.Request) error {
user := httpCtx.User(ctx)
projects, err := h.forge.GetUserProjects(ctx, user)
if err != nil {
return errors.WithStack(err)
}
vmodel.Projects = projects
return nil
}
func (h *Handler) fillIssuePageSelectedProject(ctx context.Context, vmodel *component.IssuePageVModel, r *http.Request) error {
project := r.URL.Query().Get("project")
if project == "" {
return nil
}
vmodel.SelectedProjectID = project
vmodel.SummaryForm.Field("project").Set("value", project)
return nil
}
func (h *Handler) handleIssueSummaryForm(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
issueSummaryForm := component.NewIssueSummaryForm()
if err := issueSummaryForm.Handle(r); err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel, err := h.fillIssuePageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel.SummaryForm = issueSummaryForm
if errs := issueSummaryForm.Validate(); errs != nil {
page := component.IssuePage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
return
}
projectID, err := form.FormFieldAttr[string](issueSummaryForm, "project", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
issueSummary, err := form.FormFieldAttr[string](issueSummaryForm, "summary", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
issueTemplate, err := form.FormFieldAttr[string](issueSummaryForm, "template", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
issueTemplate = strings.TrimSpace(issueTemplate)
issueTitle, issueBody, issueTips, err := h.forge.GenerateIssue(ctx, httpCtx.User(ctx), projectID, issueSummary, issueTemplate)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel.IssueTips = issueTips
vmodel.IssueForm.Field("title").Set("value", issueTitle)
vmodel.IssueForm.Field("body").Set("value", issueBody)
page := component.IssuePage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
}
func (h *Handler) handleIssueForm(w http.ResponseWriter, r *http.Request) {
issueForm := component.NewIssueForm()
if err := issueForm.Handle(r); err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel, err := h.fillIssuePageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
if errs := issueForm.Validate(); errs != nil {
vmodel.IssueForm = issueForm
page := component.IssuePage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
return
}
projectID := r.URL.Query().Get("project")
title, err := form.FormFieldAttr[string](issueForm, "title", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
body, err := form.FormFieldAttr[string](issueForm, "body", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
ctx := r.Context()
user := httpCtx.User(ctx)
issueURL, err := h.forge.CreateIssue(ctx, user, projectID, title, body)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel.IssueURL = issueURL
vmodel.SummaryForm.Field("summary").Set("value", "")
vmodel.IssueForm.Field("title").Set("value", "")
vmodel.IssueForm.Field("body").Set("value", "")
page := component.IssuePage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
}
func (h *Handler) handleError(w http.ResponseWriter, r *http.Request, err error) {
if errors.Is(err, service.ErrForgeNotAvailable) {
baseURL := url.Mutate(httpCtx.BaseURL(r.Context()), url.WithPath("/auth/logout"))
http.Redirect(w, r, baseURL.String(), http.StatusSeeOther)
return
}
common.HandleError(w, r, errors.WithStack(err))
}