243 lines
6.4 KiB
Go
Raw Normal View History

2025-03-06 22:47:02 +01:00
package pullrequest
import (
"context"
"log/slog"
"net/http"
"strings"
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/pullrequest/component"
"github.com/a-h/templ"
"github.com/pkg/errors"
)
func (h *Handler) getPullRequestPage(w http.ResponseWriter, r *http.Request) {
vmodel, err := h.fillPullRequestPageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
pr := component.PullRequestPage(*vmodel)
templ.Handler(pr).ServeHTTP(w, r)
}
func (h *Handler) fillPullRequestPageVModel(r *http.Request) (*component.PullRequestPageVModel, error) {
vmodel := &component.PullRequestPageVModel{
SummaryForm: component.NewPullRequestSummaryForm(),
PullRequestForm: component.NewPullRequestForm(),
}
err := common.FillViewModel(
r.Context(), vmodel, r,
h.fillPullRequestPageSelectedProject,
h.fillPullRequestPagePullRequests,
h.fillPullRequestPageProjects,
h.fillPullRequestPageSelectedPullRequest,
h.fillPullRequestPageSummary,
)
if err != nil {
return nil, errors.WithStack(err)
}
return vmodel, nil
}
func (h *Handler) fillPullRequestPageProjects(ctx context.Context, vmodel *component.PullRequestPageVModel, 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) fillPullRequestPagePullRequests(ctx context.Context, vmodel *component.PullRequestPageVModel, r *http.Request) error {
if vmodel.SelectedProjectID == "" {
return nil
}
user := httpCtx.User(ctx)
pullRequests, err := h.forge.GetUserProjectOpenedPullRequests(ctx, user, vmodel.SelectedProjectID)
if err != nil {
return errors.WithStack(err)
}
vmodel.PullRequests = pullRequests
return nil
}
func (h *Handler) fillPullRequestPageSelectedProject(ctx context.Context, vmodel *component.PullRequestPageVModel, 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) fillPullRequestPageSelectedPullRequest(ctx context.Context, vmodel *component.PullRequestPageVModel, r *http.Request) error {
pullRequest := r.URL.Query().Get("pullrequest")
if pullRequest == "" {
return nil
}
vmodel.SelectedPullRequestID = pullRequest
vmodel.SummaryForm.Field("pullrequest").Set("value", pullRequest)
return nil
}
func (h *Handler) fillPullRequestPageSummary(ctx context.Context, vmodel *component.PullRequestPageVModel, r *http.Request) error {
if vmodel.SelectedProjectID == "" || vmodel.SelectedPullRequestID == "" {
return nil
}
user := httpCtx.User(ctx)
pullRequest, err := h.forge.GetUserProjectPullRequest(ctx, user, vmodel.SelectedProjectID, vmodel.SelectedPullRequestID)
if err != nil {
slog.ErrorContext(ctx, "could not retrieve selected pull request", slog.Any("error", errors.WithStack(err)))
return nil
}
vmodel.SummaryForm.Field("summary").Set("value", pullRequest.Body)
return nil
}
func (h *Handler) handlePullRequestSummaryForm(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pullRequestSummaryForm := component.NewPullRequestSummaryForm()
if err := pullRequestSummaryForm.Handle(r); err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel, err := h.fillPullRequestPageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel.SummaryForm = pullRequestSummaryForm
if errs := pullRequestSummaryForm.Validate(); errs != nil {
page := component.PullRequestPage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
return
}
projectID, err := form.FormFieldAttr[string](pullRequestSummaryForm, "project", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
pullRequestID, err := form.FormFieldAttr[string](pullRequestSummaryForm, "pullrequest", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
prSummary, err := form.FormFieldAttr[string](pullRequestSummaryForm, "summary", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
prTemplate, err := form.FormFieldAttr[string](pullRequestSummaryForm, "template", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
prTemplate = strings.TrimSpace(prTemplate)
prTitle, prBody, prTips, err := h.forge.GeneratePullRequest(ctx, httpCtx.User(ctx), projectID, pullRequestID, prSummary, prTemplate)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel.PullRequestTips = prTips
vmodel.PullRequestForm.Field("title").Set("value", prTitle)
vmodel.PullRequestForm.Field("body").Set("value", prBody)
page := component.PullRequestPage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
}
func (h *Handler) handlePullRequestForm(w http.ResponseWriter, r *http.Request) {
pullRequestForm := component.NewPullRequestForm()
if err := pullRequestForm.Handle(r); err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel, err := h.fillPullRequestPageVModel(r)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
if errs := pullRequestForm.Validate(); errs != nil {
vmodel.PullRequestForm = pullRequestForm
page := component.PullRequestPage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
return
}
projectID := r.URL.Query().Get("project")
pullRequestID := r.URL.Query().Get("pullrequest")
title, err := form.FormFieldAttr[string](pullRequestForm, "title", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
body, err := form.FormFieldAttr[string](pullRequestForm, "body", "value")
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
ctx := r.Context()
user := httpCtx.User(ctx)
issueURL, err := h.forge.UpdatePullRequest(ctx, user, projectID, pullRequestID, title, body)
if err != nil {
h.handleError(w, r, errors.WithStack(err))
return
}
vmodel.PullRequestURL = issueURL
vmodel.SummaryForm.Field("summary").Set("value", "")
vmodel.PullRequestForm.Field("title").Set("value", "")
vmodel.PullRequestForm.Field("body").Set("value", "")
page := component.PullRequestPage(*vmodel)
templ.Handler(page).ServeHTTP(w, r)
}