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.
205 lines
5.0 KiB
205 lines
5.0 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"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func Task(g *gin.RouterGroup, db database.Database) {
|
|
l := services.Loader{DB: db}
|
|
|
|
g.GET("/", handler("tasks", func(c *gin.Context) (interface{}, error) {
|
|
filter := models.TaskFilter{}
|
|
if setting := c.Query("active"); setting != "" {
|
|
active := setting == "true"
|
|
filter.Active = &active
|
|
}
|
|
if setting := c.Query("expiring"); setting != "" {
|
|
expiring := setting == "true"
|
|
filter.Expiring = &expiring
|
|
}
|
|
|
|
tasks, err := l.ListTasks(c, filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sort.Sort(
|
|
models.TaskSorter{
|
|
Fields: strings.Split(c.Query("sort"), ","),
|
|
Data: tasks,
|
|
},
|
|
)
|
|
|
|
return tasks, nil
|
|
}))
|
|
|
|
g.GET("/:id", handler("task", func(c *gin.Context) (interface{}, error) {
|
|
return l.FindTask(c, c.Param("id"))
|
|
}))
|
|
|
|
g.POST("/", handler("task", func(c *gin.Context) (interface{}, error) {
|
|
createdTime := time.Now()
|
|
task := models.Task{}
|
|
err := c.BindJSON(&task)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON")
|
|
}
|
|
if task.EndTime != nil && task.EndTime.Before(createdTime) {
|
|
return nil, slerrors.BadRequest("Task end time must be later than current time.")
|
|
}
|
|
if task.ItemAmount <= 0 {
|
|
return nil, slerrors.BadRequest("Item amount cannot be zero or negative.")
|
|
}
|
|
|
|
project, err := l.FindProject(c.Request.Context(), task.ProjectID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
item, err := l.FindItem(c.Request.Context(), task.ItemID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
task.ID = generate.TaskID()
|
|
task.UserID = auth.UserID(c)
|
|
task.CreatedTime = time.Now().UTC()
|
|
task.ItemID = item.ID
|
|
task.ProjectID = project.ID
|
|
|
|
err = db.Tasks().Insert(c.Request.Context(), task)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &models.TaskResult{
|
|
Task: task,
|
|
Logs: []*models.LogWithSecondaryItem{},
|
|
Item: &item.Item,
|
|
CompletedAmount: 0,
|
|
}, nil
|
|
}))
|
|
|
|
g.PUT("/:id", handler("task", func(c *gin.Context) (interface{}, error) {
|
|
update := models.TaskUpdate{}
|
|
err := c.BindJSON(&update)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON")
|
|
}
|
|
|
|
task, err := l.FindTask(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if update.ProjectID != nil && *update.ProjectID != task.ProjectID {
|
|
project, err := l.FindProject(c.Request.Context(), *update.ProjectID)
|
|
if err != nil {
|
|
return nil, slerrors.NotFound("Destination project")
|
|
}
|
|
|
|
// Delete any links that would have been ran over.
|
|
err = db.Tasks().DeleteLink(c.Request.Context(), models.TaskLink{
|
|
TaskID: task.ID,
|
|
ProjectID: project.ID,
|
|
})
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest(err.Error())
|
|
}
|
|
|
|
task.ProjectID = project.ID
|
|
}
|
|
|
|
task.Update(update)
|
|
if task.EndTime != nil && task.EndTime.Before(task.CreatedTime) {
|
|
return nil, slerrors.BadRequest("Task end time must be later than it was created.")
|
|
}
|
|
if task.ItemAmount <= 0 {
|
|
return nil, slerrors.BadRequest("Item amount cannot be zero or negative.")
|
|
}
|
|
|
|
err = db.Tasks().Update(c.Request.Context(), task.Task)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return task, nil
|
|
}))
|
|
|
|
g.PUT("/:id/link/:project_id", handler("taskLink", func(c *gin.Context) (interface{}, error) {
|
|
task, err := l.FindTask(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
project, err := l.FindProject(c.Request.Context(), c.Param("project_id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if task.ProjectID == project.ID {
|
|
return nil, slerrors.BadRequest("You cannot link a task within its own project")
|
|
}
|
|
|
|
err = db.Tasks().CreateLink(c.Request.Context(), models.TaskLink{
|
|
TaskID: task.ID,
|
|
ProjectID: project.ID,
|
|
})
|
|
|
|
return &models.TaskLink{
|
|
TaskID: task.ID,
|
|
ProjectID: project.ID,
|
|
}, nil
|
|
}))
|
|
|
|
g.DELETE("/:id/link/:project_id", handler("taskLink", func(c *gin.Context) (interface{}, error) {
|
|
task, err := l.FindTask(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
project, err := l.FindProject(c.Request.Context(), c.Param("project_id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = db.Tasks().DeleteLink(c.Request.Context(), models.TaskLink{
|
|
TaskID: task.ID,
|
|
ProjectID: project.ID,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &models.TaskLink{
|
|
TaskID: task.ID,
|
|
ProjectID: project.ID,
|
|
}, nil
|
|
}))
|
|
|
|
g.DELETE("/:id", handler("task", func(c *gin.Context) (interface{}, error) {
|
|
task, err := l.FindTask(c.Request.Context(), c.Param("id"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(task.Logs) > 0 {
|
|
return nil, slerrors.Forbidden("cannot delete tasks with logs.")
|
|
}
|
|
|
|
err = db.Tasks().Delete(c.Request.Context(), task.Task)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return task, nil
|
|
}))
|
|
}
|