diff --git a/pkg/models/task_collection.go b/pkg/models/task_collection.go index c87f00e22f..7f55e44869 100644 --- a/pkg/models/task_collection.go +++ b/pkg/models/task_collection.go @@ -249,11 +249,20 @@ func (tf *TaskCollection) ReadAll(s *xorm.Session, a web.Auth, search string, pa opts.perPage = perPage if view != nil { - opts.sortby = append(opts.sortby, &sortParam{ - projectViewID: view.ID, - sortBy: taskPropertyPosition, - orderBy: orderAscending, - }) + var hasOrderByPosition bool + for _, param := range opts.sortby { + if param.sortBy == taskPropertyPosition { + hasOrderByPosition = true + break + } + } + if !hasOrderByPosition { + opts.sortby = append(opts.sortby, &sortParam{ + projectViewID: view.ID, + sortBy: taskPropertyPosition, + orderBy: orderAscending, + }) + } } shareAuth, is := a.(*LinkSharing) diff --git a/pkg/models/task_search.go b/pkg/models/task_search.go index 190fd150d9..c91010cc5a 100644 --- a/pkg/models/task_search.go +++ b/pkg/models/task_search.go @@ -450,6 +450,7 @@ func (t *typesenseTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, "(" + filter + ")", } + var projectViewIDForPosition int64 var sortbyFields []string for i, param := range opts.sortby { // Validate the params @@ -457,17 +458,19 @@ func (t *typesenseTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, return nil, totalCount, err } + sortBy := param.sortBy + // Typesense does not allow sorting by ID, so we sort by created timestamp instead if param.sortBy == taskPropertyID { - param.sortBy = taskPropertyCreated + sortBy = taskPropertyCreated } if param.sortBy == taskPropertyPosition { - param.sortBy = "positions.view_" + strconv.FormatInt(param.projectViewID, 10) - continue + sortBy = "positions.view_" + strconv.FormatInt(param.projectViewID, 10) + projectViewIDForPosition = param.projectViewID } - sortbyFields = append(sortbyFields, param.sortBy+"(missing_values:last):"+param.orderBy.String()) + sortbyFields = append(sortbyFields, sortBy+"(missing_values:last):"+param.orderBy.String()) if i == 2 { // Typesense supports up to 3 sorting parameters @@ -525,9 +528,14 @@ func (t *typesenseTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, return nil, 0, err } - err = t.s. + query := t.s. In("id", taskIDs). - OrderBy(orderby). - Find(&tasks) + OrderBy(orderby) + + if projectViewIDForPosition != 0 { + query = query.Join("LEFT", "task_positions", "task_positions.task_id = tasks.id AND task_positions.project_view_id = ?", projectViewIDForPosition) + } + + err = query.Find(&tasks) return tasks, int64(*result.Found), err } diff --git a/pkg/models/typesense.go b/pkg/models/typesense.go index d8934c6086..f31e1abdcd 100644 --- a/pkg/models/typesense.go +++ b/pkg/models/typesense.go @@ -240,9 +240,18 @@ func ReindexAllTasks() (err error) { return } +type TaskPositionWithView struct { + ProjectView `xorm:"extends"` + TaskPosition `xorm:"extends"` +} + func getTypesenseTaskForTask(s *xorm.Session, task *Task, projectsCache map[int64]*Project) (ttask *typesenseTask, err error) { - positions := []*TaskPosition{} - err = s.Where("task_id = ?", task.ID).Find(&positions) + positions := []*TaskPositionWithView{} + err = s. + Table("project_views"). + Where("project_views.project_id = ?", task.ProjectID). + Join("LEFT", "task_positions", "project_views.id = task_positions.project_view_id AND task_positions.task_id = ?", task.ID). + Find(&positions) if err != nil { return } @@ -312,7 +321,7 @@ func reindexTasksInTypesense(s *xorm.Session, tasks map[int64]*Task) (err error) return err } - log.Debugf("Indexed tasks %v into Typesense", tasks) + log.Debugf("Indexed %d tasks into Typesense", len(tasks)) return nil } @@ -430,7 +439,7 @@ type typesenseTask struct { Positions map[string]float64 `json:"positions"` } -func convertTaskToTypesenseTask(task *Task, positions []*TaskPosition) *typesenseTask { +func convertTaskToTypesenseTask(task *Task, positions []*TaskPositionWithView) *typesenseTask { tt := &typesenseTask{ ID: fmt.Sprintf("%d", task.ID), @@ -476,7 +485,11 @@ func convertTaskToTypesenseTask(task *Task, positions []*TaskPosition) *typesens } for _, position := range positions { - tt.Positions["view_"+strconv.FormatInt(position.ProjectViewID, 10)] = position.Position + pos := position.TaskPosition.Position + if pos == 0 { + pos = float64(task.ID) + } + tt.Positions["view_"+strconv.FormatInt(position.ProjectView.ID, 10)] = pos } return tt