feat(task): expand reactions via parameter

This commit is contained in:
kolaente 2025-01-24 11:39:51 +01:00
parent 68d07a8c0f
commit e887cdeb5e
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
6 changed files with 77 additions and 17 deletions

View File

@ -15,6 +15,7 @@ import type {IRepeatMode} from '@/types/IRepeatMode'
import type {PartialWithId} from '@/types/PartialWithId'
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
import type {IReactionPerEntity} from '@/modelTypes/IReaction'
import type {ExpandTaskFilterParam} from '@/services/taskCollection.ts'
export interface ITask extends IAbstract {
id: number

View File

@ -4,7 +4,7 @@ import TaskModel from '@/models/task'
import type {ITask} from '@/modelTypes/ITask'
import BucketModel from '@/models/bucket'
export type ExpandTaskFilterParam = 'subtasks' | null
export type ExpandTaskFilterParam = 'subtasks' | 'buckets' | 'reactions' | null
export interface TaskFilterParams {
sort_by: ('start_date' | 'end_date' | 'due_date' | 'done' | 'id' | 'position')[],

View File

@ -735,7 +735,7 @@ watch(
}
try {
const loaded = await taskService.get({id})
const loaded = await taskService.get({id}, {expand: 'reactions'})
Object.assign(task.value, loaded)
attachmentStore.set(task.value.attachments)
taskColor.value = task.value.hexColor

View File

@ -53,6 +53,7 @@ type TaskCollection struct {
// second step, will fetch all of these subtasks. This may result in more tasks than the
// pagination limit being returned, but all subtasks will be present in the response.
// If set to `buckets`, the buckets of each task will be present in the response.
// If set to `reactions`, the reactions of each task will be present in the response.
// You can set this multiple times with different values.
Expand []TaskCollectionExpandable `query:"expand" json:"-"`
@ -66,6 +67,7 @@ type TaskCollectionExpandable string
const TaskCollectionExpandSubtasks TaskCollectionExpandable = `subtasks`
const TaskCollectionExpandBuckets TaskCollectionExpandable = `buckets`
const TaskCollectionExpandReactions TaskCollectionExpandable = `reactions`
// Validate validates if the TaskCollectionExpandable value is valid.
func (t TaskCollectionExpandable) Validate() error {
@ -74,9 +76,11 @@ func (t TaskCollectionExpandable) Validate() error {
return nil
case TaskCollectionExpandBuckets:
return nil
case TaskCollectionExpandReactions:
return nil
}
return InvalidFieldErrorWithMessage([]string{"expand"}, "Expand must be one of the following values: subtasks, buckets")
return InvalidFieldErrorWithMessage([]string{"expand"}, "Expand must be one of the following values: subtasks, buckets, reactions")
}
func validateTaskField(fieldName string) error {
@ -239,7 +243,7 @@ func getFilterValueForBucketFilter(filter string, view *ProjectView) (newFilter
// @Param filter query string false "The filter query to match tasks by. Check out https://vikunja.io/docs/filters for a full explanation of the feature."
// @Param filter_timezone query string false "The time zone which should be used for date match (statements like "now" resolve to different actual times)"
// @Param filter_include_nulls query string false "If set to true the result will include filtered fields whose value is set to `null`. Available values are `true` or `false`. Defaults to `false`."
// @Param expand query string false "If set to `subtasks`, Vikunja will fetch only tasks which do not have subtasks and then in a second step, will fetch all of these subtasks. This may result in more tasks than the pagination limit being returned, but all subtasks will be present in the response. If set to `buckets`, the buckets of each task will be present in the response. You can set this multiple times with different values.
// @Param expand query string false "If set to `subtasks`, Vikunja will fetch only tasks which do not have subtasks and then in a second step, will fetch all of these subtasks. This may result in more tasks than the pagination limit being returned, but all subtasks will be present in the response. If set to `buckets`, the buckets of each task will be present in the response. If set to `reactions`, the reactions of each task will be present in the response. You can set this multiple times with different values.
// @Security JWTKeyAuth
// @Success 200 {array} models.Task "The tasks"
// @Failure 500 {object} models.Message "Internal error"

View File

@ -105,9 +105,6 @@ func TestTaskCollection_ReadAll(t *testing.T) {
CreatedBy: user1,
ProjectID: 1,
IsFavorite: true,
Reactions: ReactionMap{
"👋": []*user.User{user1},
},
Labels: []*Label{
label4,
},
@ -167,6 +164,11 @@ func TestTaskCollection_ReadAll(t *testing.T) {
Created: time.Unix(1543626724, 0).In(loc),
Updated: time.Unix(1543626724, 0).In(loc),
}
var task1WithReaction = &Task{}
*task1WithReaction = *task1
task1WithReaction.Reactions = ReactionMap{
"👋": []*user.User{user1},
}
task2 := &Task{
ID: 2,
Title: "task #2 done",
@ -652,6 +654,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
FilterIncludeNulls bool
Filter string
Expand []TaskCollectionExpandable
CRUDable web.CRUDable
Rights web.Rights
}
@ -723,6 +727,51 @@ func TestTaskCollection_ReadAll(t *testing.T) {
},
wantErr: false,
},
{
name: "ReadAll Tasks with expanded reaction",
fields: fields{
Expand: []TaskCollectionExpandable{
TaskCollectionExpandReactions,
},
},
args: defaultArgs,
want: []*Task{
task1WithReaction,
task2,
task3,
task4,
task5,
task6,
task7,
task8,
task9,
task10,
task11,
task12,
task15,
task16,
task17,
task18,
task19,
task20,
task21,
task22,
task23,
task24,
task25,
task26,
task27,
task28,
task29,
task30,
task31,
task32,
task33,
task35,
task39,
},
wantErr: false,
},
{
// For more sorting tests see task_collection_sort_test.go
name: "sorted by done asc and id desc",
@ -1465,6 +1514,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
Filter: tt.fields.Filter,
Expand: tt.fields.Expand,
CRUDable: tt.fields.CRUDable,
Rights: tt.fields.Rights,
}

View File

@ -672,11 +672,6 @@ func addMoreInfoToTasks(s *xorm.Session, taskMap map[int64]*Task, a web.Auth, vi
return err
}
reactions, err := getReactionsForEntityIDs(s, ReactionKindTask, taskIDs)
if err != nil {
return
}
var positionsMap = make(map[int64]*TaskPosition)
if view != nil {
positions, err := getPositionsForView(s, view)
@ -688,6 +683,7 @@ func addMoreInfoToTasks(s *xorm.Session, taskMap map[int64]*Task, a web.Auth, vi
}
}
var reactions map[int64]ReactionMap
if expand != nil {
expanded := make(map[TaskCollectionExpandable]bool)
for _, expandable := range expand {
@ -695,11 +691,17 @@ func addMoreInfoToTasks(s *xorm.Session, taskMap map[int64]*Task, a web.Auth, vi
continue
}
if expandable == TaskCollectionExpandBuckets {
switch expandable {
case TaskCollectionExpandBuckets:
err = addBucketsToTasks(s, a, taskIDs, taskMap)
if err != nil {
return err
}
case TaskCollectionExpandReactions:
reactions, err = getReactionsForEntityIDs(s, ReactionKindTask, taskIDs)
if err != nil {
return
}
}
expanded[expandable] = true
}
@ -722,9 +724,11 @@ func addMoreInfoToTasks(s *xorm.Session, taskMap map[int64]*Task, a web.Auth, vi
task.IsFavorite = taskFavorites[task.ID]
r, has := reactions[task.ID]
if has {
task.Reactions = r
if reactions != nil {
r, has := reactions[task.ID]
if has {
task.Reactions = r
}
}
p, has := positionsMap[task.ID]
@ -1677,7 +1681,7 @@ func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) {
// @Accept json
// @Produce json
// @Param id path int true "The task ID"
// @Param expand query string false "If set to `subtasks`, Vikunja will fetch only tasks which do not have subtasks and then in a second step, will fetch all of these subtasks. This may result in more tasks than the pagination limit being returned, but all subtasks will be present in the response. If set to `buckets`, the buckets of each task will be present in the response. You can set this multiple times with different values.
// @Param expand query string false "If set to `subtasks`, Vikunja will fetch only tasks which do not have subtasks and then in a second step, will fetch all of these subtasks. This may result in more tasks than the pagination limit being returned, but all subtasks will be present in the response. If set to `buckets`, the buckets of each task will be present in the response. If set to `reactions`, the reactions of each task will be present in the response. You can set this multiple times with different values.
// @Security JWTKeyAuth
// @Success 200 {object} models.Task "The task"
// @Failure 404 {object} models.Message "Task not found"