feat(comments): support order_by query parameter in comments API

Add an OrderBy field to the TaskComment struct with a query:"order_by"
tag so that the frontend can request ascending or descending comment
order. The value is validated to only accept "asc" or "desc", defaulting
to "asc". Also adds the corresponding swagger @Param annotation.
This commit is contained in:
kolaente 2026-02-19 14:13:01 +01:00
parent b64926be73
commit c12bbbe93e
1 changed files with 12 additions and 4 deletions

View File

@ -38,6 +38,8 @@ type TaskComment struct {
Reactions ReactionMap `xorm:"-" json:"reactions"` Reactions ReactionMap `xorm:"-" json:"reactions"`
OrderBy string `xorm:"-" json:"-" query:"order_by"`
Created time.Time `xorm:"created" json:"created"` Created time.Time `xorm:"created" json:"created"`
Updated time.Time `xorm:"updated" json:"updated"` Updated time.Time `xorm:"updated" json:"updated"`
@ -243,6 +245,7 @@ func (tc *TaskComment) ReadOne(s *xorm.Session, _ web.Auth) (err error) {
// @Produce json // @Produce json
// @Security JWTKeyAuth // @Security JWTKeyAuth
// @Param taskID path int true "Task ID" // @Param taskID path int true "Task ID"
// @Param order_by query string false "Sort order. Can be 'asc' for ascending or 'desc' for descending. Defaults to 'asc'."
// @Success 200 {array} models.TaskComment "The array with all task comments" // @Success 200 {array} models.TaskComment "The array with all task comments"
// @Failure 500 {object} models.Message "Internal error" // @Failure 500 {object} models.Message "Internal error"
// @Router /tasks/{taskID}/comments [get] // @Router /tasks/{taskID}/comments [get]
@ -257,13 +260,13 @@ func (tc *TaskComment) ReadAll(s *xorm.Session, auth web.Auth, search string, pa
return nil, 0, 0, ErrGenericForbidden{} return nil, 0, 0, ErrGenericForbidden{}
} }
return getAllCommentsForTasksWithoutPermissionCheck(s, []int64{tc.TaskID}, search, page, perPage) return getAllCommentsForTasksWithoutPermissionCheck(s, []int64{tc.TaskID}, search, page, perPage, tc.OrderBy)
} }
func addCommentsToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]*Task) (err error) { func addCommentsToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]*Task) (err error) {
// Only fetch the first page of comments when expanding tasks to avoid // Only fetch the first page of comments when expanding tasks to avoid
// loading all comments for tasks with many comments. // loading all comments for tasks with many comments.
comments, _, _, err := getAllCommentsForTasksWithoutPermissionCheck(s, taskIDs, "", 1, 50) comments, _, _, err := getAllCommentsForTasksWithoutPermissionCheck(s, taskIDs, "", 1, 50, "asc")
if err != nil { if err != nil {
return err return err
} }
@ -317,7 +320,7 @@ func addCommentCountToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64]
return nil return nil
} }
func getAllCommentsForTasksWithoutPermissionCheck(s *xorm.Session, taskIDs []int64, search string, page int, perPage int) (result []*TaskComment, resultCount int, numberOfTotalItems int64, err error) { func getAllCommentsForTasksWithoutPermissionCheck(s *xorm.Session, taskIDs []int64, search string, page int, perPage int, orderBy string) (result []*TaskComment, resultCount int, numberOfTotalItems int64, err error) {
// Because we can't extend the type in general, we need to do this here. // Because we can't extend the type in general, we need to do this here.
// Not a good solution, but saves performance. // Not a good solution, but saves performance.
type TaskCommentWithAuthor struct { type TaskCommentWithAuthor struct {
@ -325,6 +328,11 @@ func getAllCommentsForTasksWithoutPermissionCheck(s *xorm.Session, taskIDs []int
AuthorFromDB *user.User `xorm:"extends" json:"-"` AuthorFromDB *user.User `xorm:"extends" json:"-"`
} }
order := "asc"
if orderBy == "desc" {
order = "desc"
}
limit, start := getLimitFromPageIndex(page, perPage) limit, start := getLimitFromPageIndex(page, perPage)
comments := []*TaskComment{} comments := []*TaskComment{}
where := []builder.Cond{ where := []builder.Cond{
@ -337,7 +345,7 @@ func getAllCommentsForTasksWithoutPermissionCheck(s *xorm.Session, taskIDs []int
query := s. query := s.
Where(builder.And(where...)). Where(builder.And(where...)).
Join("LEFT", "users", "users.id = task_comments.author_id"). Join("LEFT", "users", "users.id = task_comments.author_id").
OrderBy("task_comments.created asc") OrderBy("task_comments.created " + order)
if limit > 0 { if limit > 0 {
query = query.Limit(limit, start) query = query.Limit(limit, start)
} }