You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.4 KiB
126 lines
3.4 KiB
package api
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gissleh/stufflog/database"
|
|
"github.com/gissleh/stufflog/internal/auth"
|
|
"github.com/gissleh/stufflog/internal/generate"
|
|
"github.com/gissleh/stufflog/internal/slerrors"
|
|
"github.com/gissleh/stufflog/models"
|
|
"github.com/gissleh/stufflog/services"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func Project(g *gin.RouterGroup, db database.Database) {
|
|
l := services.Loader{DB: db}
|
|
|
|
g.GET("/", handler("projects", func(c *gin.Context) (interface{}, error) {
|
|
filter := models.ProjectFilter{}
|
|
if setting := c.Query("active"); setting != "" {
|
|
active := setting == "true"
|
|
filter.Active = &active
|
|
}
|
|
if setting := c.Query("include-semi-active"); setting != "" {
|
|
filter.IncludeSemiActive = setting == "true"
|
|
}
|
|
if setting := c.Query("expiring"); setting != "" {
|
|
filter.Expiring = setting == "true"
|
|
}
|
|
if setting := c.Query("favorite"); setting != "" {
|
|
favorite := setting == "true"
|
|
filter.Favorite = &favorite
|
|
}
|
|
if setting := c.Query("ungrouped"); setting != "" {
|
|
filter.Ungrouped = setting == "true"
|
|
}
|
|
if setting := c.Query("groups"); setting != "" {
|
|
filter.ProjectGroupIDs = strings.Split(setting, ",")
|
|
}
|
|
|
|
return l.ListProjects(c, filter)
|
|
}))
|
|
|
|
g.GET("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
return l.FindProject(c, c.Param("id"))
|
|
}))
|
|
|
|
g.POST("/", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
project := models.Project{}
|
|
err := c.BindJSON(&project)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON")
|
|
}
|
|
if project.EndTime != nil && project.EndTime.Before(time.Now()) {
|
|
return nil, slerrors.BadRequest("Project end time must be later than current time.")
|
|
}
|
|
if project.StartTime != nil && (project.EndTime == nil || !project.StartTime.Before(*project.EndTime)) {
|
|
return nil, slerrors.BadRequest("Project start time must be before end time.")
|
|
}
|
|
|
|
project.ID = generate.ProjectID()
|
|
project.UserID = auth.UserID(c)
|
|
project.CreatedTime = time.Now().UTC()
|
|
|
|
err = db.Projects().Insert(c.Request.Context(), project)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if project.Active && project.StatusTag != nil {
|
|
project.StatusTag = nil
|
|
}
|
|
if project.SubtractAmount < 0 {
|
|
project.SubtractAmount = 0
|
|
}
|
|
|
|
return &models.ProjectResult{
|
|
Project: project,
|
|
Tasks: []*models.TaskResult{},
|
|
}, nil
|
|
}))
|
|
|
|
g.PUT("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
update := models.ProjectUpdate{}
|
|
err := c.BindJSON(&update)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON")
|
|
}
|
|
|
|
project, err := l.FindProject(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
project.Update(update)
|
|
|
|
if project.StartTime != nil && (project.EndTime == nil || !project.StartTime.Before(*project.EndTime)) {
|
|
return nil, slerrors.BadRequest("Project start time must be before end time.")
|
|
}
|
|
|
|
err = db.Projects().Update(c.Request.Context(), project.Project)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return project, nil
|
|
}))
|
|
|
|
g.DELETE("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
project, err := l.FindProject(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(project.Tasks) > 0 {
|
|
return nil, slerrors.Forbidden("cannot delete non-empty projects.")
|
|
}
|
|
|
|
err = db.Projects().Delete(c.Request.Context(), project.Project)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return project, nil
|
|
}))
|
|
}
|