Skip to content
Snippets Groups Projects
Commit 31a1f9dc authored by Colin Jakob's avatar Colin Jakob
Browse files

add controllers for displaying and handling requirement

parent 79cee4ef
Branches feature/feature6
No related tags found
1 merge request!4merge dev to main
...@@ -36,6 +36,15 @@ type ProjectDetailData struct { ...@@ -36,6 +36,15 @@ type ProjectDetailData struct {
RequirementStatuses []string // Available status options for requirements RequirementStatuses []string // Available status options for requirements
} }
// RequirementCloneFormData is passed to the requirement clone modal
type RequirementCloneFormData struct {
Name string `hvalidate:"required"`
ProjectID string
Requirement *project.RequirementSummary
Projects []*project.Project
Cloned bool
}
// RegisterController sets up all HTTP routes and handlers for project management // RegisterController sets up all HTTP routes and handlers for project management
// This function is called during application startup to configure the web routing // This function is called during application startup to configure the web routing
func RegisterController(appCtx *hctx.AppCtx, webCtx *web.Ctx, mongoManager *project.MongoManager) { func RegisterController(appCtx *hctx.AppCtx, webCtx *web.Ctx, mongoManager *project.MongoManager) {
...@@ -87,6 +96,12 @@ func RegisterController(appCtx *hctx.AppCtx, webCtx *web.Ctx, mongoManager *proj ...@@ -87,6 +96,12 @@ func RegisterController(appCtx *hctx.AppCtx, webCtx *web.Ctx, mongoManager *proj
// POST /project/search - Handle project search functionality // POST /project/search - Handle project search functionality
router.Post("/project/search", projectSearchController(appCtx, webCtx, projectService).ServeHTTP) router.Post("/project/search", projectSearchController(appCtx, webCtx, projectService).ServeHTTP)
// GET /requirement/{id}/clone/modal - Show requirement clone modal
router.Get("/requirement/{id}/clone/modal", requirementCloneModalController(appCtx, webCtx, projectService).ServeHTTP)
// POST /requirement/{id}/clone - Process requirement cloning
router.Post("/requirement/{id}/clone", requirementCloneController(appCtx, webCtx, projectService).ServeHTTP)
log.Println("INFO: Project routes registered successfully") log.Println("INFO: Project routes registered successfully")
} }
...@@ -531,3 +546,129 @@ func renderProjectEditForm(io web.IO, toUpdate *project.ProjectToUpdate, success ...@@ -531,3 +546,129 @@ func renderProjectEditForm(io web.IO, toUpdate *project.ProjectToUpdate, success
return err return err
} }
// requirementCloneModalController displays the modal for cloning a requirement
func requirementCloneModalController(appCtx *hctx.AppCtx, webCtx *web.Ctx, service *project.ProjectService) http.Handler {
return web.NewController(appCtx, webCtx, func(io web.IO) error {
ctx := io.Context()
usr := user.MustCtxUser(ctx)
// Parse requirement ID from URL
reqID, err := parseObjectID(io.Request(), "id")
if err != nil {
return io.InlineError(web.ErrInternal, err)
}
// Find the requirement by searching through all projects
var targetReq *project.RequirementSummary
projects, err := service.GetProjectsByUser(ctx, usr.ID)
if err != nil {
return io.InlineError(web.ErrInternal, err)
}
for _, proj := range projects {
projWithReqs, err := service.GetProjectWithRequirements(ctx, proj.ID)
if err != nil {
continue
}
for _, req := range projWithReqs.Requirements {
if req.ID == reqID {
targetReq = req
break
}
}
if targetReq != nil {
break
}
}
if targetReq == nil {
return io.InlineError(web.ErrInternal, errors.New("requirement not found"))
}
return io.Render(web.NewFormData(RequirementCloneFormData{
Requirement: targetReq,
Projects: projects,
}, nil), "requirement.clone.modal", "project/_modal-clone-requirement.go.html")
})
}
// requirementCloneController processes the requirement cloning form submission
func requirementCloneController(appCtx *hctx.AppCtx, webCtx *web.Ctx, service *project.ProjectService) http.Handler {
return web.NewController(appCtx, webCtx, func(io web.IO) error {
ctx := io.Context()
usr := user.MustCtxUser(ctx)
log.Printf("INFO: Starting requirement clone process for user %s", usr.ID)
// Parse requirement ID from URL
reqID, err := parseObjectID(io.Request(), "id")
if err != nil {
log.Printf("ERROR: Failed to parse requirement ID: %v", err)
return io.InlineError(web.ErrInternal, err)
}
log.Printf("INFO: Cloning requirement with ID %s", reqID.Hex())
// Get projects for form data
projects, err := service.GetProjectsByUser(ctx, usr.ID)
if err != nil {
return io.InlineError(web.ErrInternal, err)
}
// Find the source requirement
var sourceReq *project.RequirementSummary
for _, proj := range projects {
projWithReqs, err := service.GetProjectWithRequirements(ctx, proj.ID)
if err != nil {
continue
}
for _, req := range projWithReqs.Requirements {
if req.ID == reqID {
sourceReq = req
break
}
}
if sourceReq != nil {
break
}
}
if sourceReq == nil {
log.Printf("ERROR: Source requirement %s not found", reqID.Hex())
return io.InlineError(web.ErrInternal, errors.New("source requirement not found"))
}
log.Printf("INFO: Found source requirement %s", sourceReq.RequirementID)
formData := &RequirementCloneFormData{Requirement: sourceReq, Projects: projects}
err, validationErrs := web.ReadForm(io.Request(), formData, appCtx.Validator)
if err != nil {
log.Printf("ERROR: Failed to read form: %v", err)
return io.InlineError(web.ErrInternal, err)
}
log.Printf("INFO: Form data - ProjectID: %s, Name: %s", formData.ProjectID, formData.Name)
if validationErrs != nil {
log.Printf("WARN: Validation errors: %v", validationErrs)
return io.Render(web.NewFormData(formData, nil, validationErrs...), "requirement.clone.modal", "project/_modal-clone-requirement.go.html")
}
// Clone the requirement
log.Printf("INFO: Calling service.CloneRequirement with ProjectID: %s, Name: %s", formData.ProjectID, formData.Name)
err = service.CloneRequirement(ctx, reqID, formData.ProjectID, formData.Name)
if err != nil {
log.Printf("ERROR: Clone failed: %v", err)
return io.InlineError(web.ErrInternal, err)
}
log.Printf("INFO: Requirement cloned successfully")
// Return a simple success response for API calls
io.Response().Header().Set("Content-Type", "text/plain")
io.Response().WriteHeader(http.StatusOK)
_, err = io.Response().Write([]byte("Anforderung erfolgreich geklont"))
return err
})
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment