fix(views): return tasks in their buckets
This commit is contained in:
parent
ca0550acea
commit
398c9f1056
@ -1527,27 +1527,27 @@ func (err ErrBucketDoesNotExist) HTTPError() web.HTTPError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrBucketDoesNotBelongToProject represents an error where a kanban bucket does not belong to a project
|
// ErrBucketDoesNotBelongToProjectView represents an error where a kanban bucket does not belong to a project
|
||||||
type ErrBucketDoesNotBelongToProject struct {
|
type ErrBucketDoesNotBelongToProjectView struct {
|
||||||
BucketID int64
|
BucketID int64
|
||||||
ProjectID int64
|
ProjectViewID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrBucketDoesNotBelongToProject checks if an error is ErrBucketDoesNotBelongToProject.
|
// IsErrBucketDoesNotBelongToProject checks if an error is ErrBucketDoesNotBelongToProjectView.
|
||||||
func IsErrBucketDoesNotBelongToProject(err error) bool {
|
func IsErrBucketDoesNotBelongToProject(err error) bool {
|
||||||
_, ok := err.(ErrBucketDoesNotBelongToProject)
|
_, ok := err.(ErrBucketDoesNotBelongToProjectView)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrBucketDoesNotBelongToProject) Error() string {
|
func (err ErrBucketDoesNotBelongToProjectView) Error() string {
|
||||||
return fmt.Sprintf("Bucket does not not belong to project [BucketID: %d, ProjectID: %d]", err.BucketID, err.ProjectID)
|
return fmt.Sprintf("Bucket does not not belong to project view [BucketID: %d, ProjectViewID: %d]", err.BucketID, err.ProjectViewID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrCodeBucketDoesNotBelongToProject holds the unique world-error code of this error
|
// ErrCodeBucketDoesNotBelongToProject holds the unique world-error code of this error
|
||||||
const ErrCodeBucketDoesNotBelongToProject = 10002
|
const ErrCodeBucketDoesNotBelongToProject = 10002
|
||||||
|
|
||||||
// HTTPError holds the http error description
|
// HTTPError holds the http error description
|
||||||
func (err ErrBucketDoesNotBelongToProject) HTTPError() web.HTTPError {
|
func (err ErrBucketDoesNotBelongToProjectView) HTTPError() web.HTTPError {
|
||||||
return web.HTTPError{
|
return web.HTTPError{
|
||||||
HTTPCode: http.StatusBadRequest,
|
HTTPCode: http.StatusBadRequest,
|
||||||
Code: ErrCodeBucketDoesNotBelongToProject,
|
Code: ErrCodeBucketDoesNotBelongToProject,
|
||||||
|
@ -213,7 +213,7 @@ func GetTasksInBucketsForView(s *xorm.Session, view *ProjectView, opts *taskSear
|
|||||||
|
|
||||||
opts.sortby = []*sortParam{
|
opts.sortby = []*sortParam{
|
||||||
{
|
{
|
||||||
projectViewID: view.ProjectID,
|
projectViewID: view.ID,
|
||||||
orderBy: orderAscending,
|
orderBy: orderAscending,
|
||||||
sortBy: taskPropertyPosition,
|
sortBy: taskPropertyPosition,
|
||||||
},
|
},
|
||||||
@ -260,6 +260,10 @@ func GetTasksInBucketsForView(s *xorm.Session, view *ProjectView, opts *taskSear
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, t := range ts {
|
||||||
|
t.BucketID = bucket.ID
|
||||||
|
}
|
||||||
|
|
||||||
bucket.Count = total
|
bucket.Count = total
|
||||||
|
|
||||||
tasks = append(tasks, ts...)
|
tasks = append(tasks, ts...)
|
||||||
|
@ -209,6 +209,14 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var joinTaskBuckets bool
|
||||||
|
for _, filter := range opts.parsedFilters {
|
||||||
|
if filter.field == taskPropertyBucketID {
|
||||||
|
joinTaskBuckets = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
filterCond, err := convertFiltersToDBFilterCond(opts.parsedFilters, opts.filterIncludeNulls)
|
filterCond, err := convertFiltersToDBFilterCond(opts.parsedFilters, opts.filterIncludeNulls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@ -265,20 +273,24 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if joinTaskBuckets {
|
||||||
|
query = query.Join("LEFT", "task_buckets", "task_buckets.task_id = tasks.id")
|
||||||
|
}
|
||||||
|
|
||||||
tasks = []*Task{}
|
tasks = []*Task{}
|
||||||
err = query.OrderBy(orderby).Find(&tasks)
|
err = query.
|
||||||
|
OrderBy(orderby).
|
||||||
|
Find(&tasks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, totalCount, err
|
return nil, totalCount, err
|
||||||
}
|
}
|
||||||
|
|
||||||
queryCount := d.s.Where(cond)
|
queryCount := d.s.Where(cond)
|
||||||
|
if joinTaskBuckets {
|
||||||
|
queryCount = queryCount.Join("LEFT", "task_buckets", "task_buckets.task_id = tasks.id")
|
||||||
|
}
|
||||||
totalCount, err = queryCount.
|
totalCount, err = queryCount.
|
||||||
Count(&Task{})
|
Count(&Task{})
|
||||||
if err != nil {
|
|
||||||
return nil, totalCount, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ type Task struct {
|
|||||||
|
|
||||||
// The bucket id. Will only be populated when the task is accessed via a view with buckets.
|
// The bucket id. Will only be populated when the task is accessed via a view with buckets.
|
||||||
// Can be used to move a task between buckets. In that case, the new bucket must be in the same view as the old one.
|
// Can be used to move a task between buckets. In that case, the new bucket must be in the same view as the old one.
|
||||||
BucketID int64 `xorm:"bigint null" json:"bucket_id"`
|
BucketID int64 `xorm:"<-" json:"bucket_id"`
|
||||||
|
|
||||||
// The position of the task - any task project can be sorted as usual by this parameter.
|
// The position of the task - any task project can be sorted as usual by this parameter.
|
||||||
// When accessing tasks via views with buckets, this is primarily used to sort them based on a range.
|
// When accessing tasks via views with buckets, this is primarily used to sort them based on a range.
|
||||||
@ -204,6 +204,9 @@ func (t *Task) ReadAll(_ *xorm.Session, _ web.Auth, _ string, _ int, _ int) (res
|
|||||||
|
|
||||||
func getFilterCond(f *taskFilter, includeNulls bool) (cond builder.Cond, err error) {
|
func getFilterCond(f *taskFilter, includeNulls bool) (cond builder.Cond, err error) {
|
||||||
field := "`" + f.field + "`"
|
field := "`" + f.field + "`"
|
||||||
|
if f.field == taskPropertyBucketID {
|
||||||
|
field = "task_buckets.`bucket_id`"
|
||||||
|
}
|
||||||
switch f.comparator {
|
switch f.comparator {
|
||||||
case taskFilterComparatorEquals:
|
case taskFilterComparatorEquals:
|
||||||
cond = &builder.Eq{field: f.value}
|
cond = &builder.Eq{field: f.value}
|
||||||
@ -633,15 +636,16 @@ func checkBucketLimit(s *xorm.Session, t *Task, bucket *Bucket) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Contains all the task logic to figure out what bucket to use for this task.
|
// Contains all the task logic to figure out what bucket to use for this task.
|
||||||
func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, view *ProjectView, targetBucket *TaskBucket) (err error) {
|
func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, view *ProjectView, targetBucketID int64) (err error) {
|
||||||
|
if view.BucketConfigurationMode == BucketConfigurationModeNone {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var shouldChangeBucket = true
|
var shouldChangeBucket = true
|
||||||
if targetBucket == nil {
|
targetBucket := &TaskBucket{
|
||||||
targetBucket = &TaskBucket{
|
BucketID: targetBucketID,
|
||||||
BucketID: 0,
|
TaskID: task.ID,
|
||||||
TaskID: task.ID,
|
ProjectViewID: view.ID,
|
||||||
ProjectViewID: view.ID,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oldTaskBucket := &TaskBucket{}
|
oldTaskBucket := &TaskBucket{}
|
||||||
@ -678,15 +682,12 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, view *Projec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there is a bucket set, make sure they belong to the same project as the task
|
// If there is a bucket set, make sure they belong to the same project as the task
|
||||||
if task.ProjectID != bucket.ProjectID {
|
if view.ID != bucket.ProjectViewID {
|
||||||
return ErrBucketDoesNotBelongToProject{
|
return ErrBucketDoesNotBelongToProjectView{
|
||||||
ProjectID: task.ProjectID,
|
ProjectViewID: view.ID,
|
||||||
BucketID: bucket.ID,
|
BucketID: bucket.ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the bucket limit
|
// Check the bucket limit
|
||||||
// Only check the bucket limit if the task is being moved between buckets, allow reordering the task within a bucket
|
// Only check the bucket limit if the task is being moved between buckets, allow reordering the task within a bucket
|
||||||
@ -811,7 +812,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
|
|||||||
for _, view := range views {
|
for _, view := range views {
|
||||||
|
|
||||||
// Get the default bucket and move the task there
|
// Get the default bucket and move the task there
|
||||||
err = setTaskBucket(s, t, nil, view, &TaskBucket{})
|
err = setTaskBucket(s, t, nil, view, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -913,20 +914,16 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
|
|||||||
Find(&buckets)
|
Find(&buckets)
|
||||||
|
|
||||||
for _, view := range views {
|
for _, view := range views {
|
||||||
taskBucket := &TaskBucket{
|
|
||||||
TaskID: t.ID,
|
|
||||||
ProjectViewID: view.ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only update the bucket when the current view
|
// Only update the bucket when the current view
|
||||||
|
var targetBucketID int64
|
||||||
if t.BucketID != 0 {
|
if t.BucketID != 0 {
|
||||||
bucket, has := buckets[t.BucketID]
|
bucket, has := buckets[t.BucketID]
|
||||||
if has && bucket.ProjectViewID == view.ID {
|
if has && bucket.ProjectViewID == view.ID {
|
||||||
taskBucket.BucketID = t.BucketID
|
targetBucketID = t.BucketID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setTaskBucket(s, t, &ot, view, taskBucket)
|
err = setTaskBucket(s, t, &ot, view, targetBucketID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user