Plan stuff. Log stuff.
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.

178 lines
4.2 KiB

4 years ago
  1. package api
  2. import (
  3. "github.com/gin-gonic/gin"
  4. "github.com/gisle/stufflog/database"
  5. "github.com/gisle/stufflog/models"
  6. "github.com/gisle/stufflog/services"
  7. "github.com/gisle/stufflog/slerrors"
  8. "sort"
  9. )
  10. func Period(g *gin.RouterGroup, db database.Database, scoring *services.ScoringService, auth *services.AuthService) {
  11. type resObj struct {
  12. Period *models.Period `json:"period,omitempty"`
  13. Periods []*models.Period `json:"periods,omitempty"`
  14. Activities []*models.Activity `json:"activities,omitempty"`
  15. }
  16. g.Use(auth.GinSessionMiddleware(true))
  17. // GET / – List own periods.
  18. g.GET("/", func(c *gin.Context) {
  19. user := auth.UserFromContext(c)
  20. periods, err := db.Periods().ListUser(c.Request.Context(), *user)
  21. if err != nil {
  22. slerrors.GinRespond(c, err)
  23. return
  24. }
  25. sort.Sort(models.PeriodsByFrom(periods))
  26. c.JSON(200, resObj{Periods: periods})
  27. })
  28. // GET / — Find a period
  29. g.GET("/:id", func(c *gin.Context) {
  30. user := auth.UserFromContext(c)
  31. period, err := db.Periods().FindID(c.Request.Context(), c.Param("id"))
  32. if err != nil {
  33. slerrors.GinRespond(c, err)
  34. return
  35. }
  36. if period.UserID != user.ID {
  37. slerrors.GinRespond(c, slerrors.NotFound("Period"))
  38. return
  39. }
  40. activities := make([]*models.Activity, 0, 8)
  41. activityAdded := make(map[string]bool)
  42. for _, goal := range period.Goals {
  43. if !activityAdded[goal.ActivityID] {
  44. activityAdded[goal.ActivityID] = true
  45. activity, err := db.Activities().FindID(c.Request.Context(), goal.ActivityID)
  46. if err != nil {
  47. slerrors.GinRespond(c, err)
  48. return
  49. }
  50. activities = append(activities, activity)
  51. }
  52. }
  53. c.JSON(200, resObj{Period: period, Activities: activities})
  54. })
  55. // POST / – Create a period
  56. g.POST("/", func(c *gin.Context) {
  57. user := auth.UserFromContext(c)
  58. period := models.Period{}
  59. err := c.BindJSON(&period)
  60. if err != nil {
  61. slerrors.GinRespond(c, &slerrors.SLError{Code: 400, Text: err.Error()})
  62. return
  63. }
  64. period.GenerateIDs()
  65. period.RemoveDuplicateTags()
  66. period.UserID = user.ID
  67. period.Logs = make([]models.PeriodLog, 0)
  68. period.ShouldReScore = false
  69. if period.Tags == nil {
  70. period.Tags = make([]string, 0)
  71. }
  72. if period.Goals == nil {
  73. period.Goals = make([]models.PeriodGoal, 0)
  74. }
  75. for i := range period.Goals {
  76. if period.Goals[i].SubGoals == nil {
  77. period.Goals[i].SubGoals = make([]models.PeriodSubGoal, 0)
  78. }
  79. }
  80. err = db.Periods().Insert(c.Request.Context(), period)
  81. if err != nil {
  82. slerrors.GinRespond(c, err)
  83. return
  84. }
  85. c.JSON(200, resObj{Period: &period})
  86. })
  87. // PATCH /:id – Update one Period
  88. g.PATCH("/:id", func(c *gin.Context) {
  89. user := auth.UserFromContext(c)
  90. updates := make([]*models.PeriodUpdate, 0, 8)
  91. err := c.BindJSON(&updates)
  92. if err != nil {
  93. slerrors.GinRespond(c, &slerrors.SLError{Code: 400, Text: err.Error()})
  94. return
  95. }
  96. period, err := db.Periods().FindID(c.Request.Context(), c.Param("id"))
  97. if err != nil {
  98. slerrors.GinRespond(c, err)
  99. return
  100. }
  101. if period.UserID != user.ID {
  102. slerrors.GinRespond(c, slerrors.NotFound("Period"))
  103. return
  104. }
  105. for _, update := range updates {
  106. if update.AddLog != nil {
  107. score, err := scoring.ScoreOne(c.Request.Context(), *period, *update.AddLog)
  108. if err != nil {
  109. slerrors.GinRespond(c, err)
  110. return
  111. }
  112. update.AddLog.Score = score
  113. }
  114. }
  115. period, err = db.Periods().Update(c.Request.Context(), *period, updates)
  116. if err != nil {
  117. slerrors.GinRespond(c, err)
  118. return
  119. }
  120. if period.ShouldReScore {
  121. period, err = scoring.ScoreAll(c.Request.Context(), *period)
  122. if err != nil {
  123. slerrors.GinRespond(c, err)
  124. return
  125. }
  126. }
  127. c.JSON(200, resObj{Period: period})
  128. })
  129. // DELETE /:id – Delete a period
  130. g.DELETE("/:id", func(c *gin.Context) {
  131. user := auth.UserFromContext(c)
  132. period, err := db.Periods().FindID(c.Request.Context(), c.Param("id"))
  133. if err != nil {
  134. slerrors.GinRespond(c, err)
  135. return
  136. }
  137. if period.UserID != user.ID {
  138. slerrors.GinRespond(c, slerrors.NotFound("Period"))
  139. return
  140. }
  141. err = db.Periods().Remove(c.Request.Context(), *period)
  142. if err != nil {
  143. slerrors.GinRespond(c, err)
  144. return
  145. }
  146. c.JSON(200, resObj{Period: period})
  147. })
  148. }