1
0

feat(views)!: make updating a bucket work again

This commit is contained in:
kolaente 2024-03-15 13:12:56 +01:00
parent a13276e28e
commit f2a0d69670
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
4 changed files with 118 additions and 51 deletions

View File

@ -33,8 +33,9 @@ func (task20240315110428) TableName() string {
} }
type taskBuckets20240315110428 struct { type taskBuckets20240315110428 struct {
BucketID int64 `xorm:"bigint not null index"` BucketID int64 `xorm:"bigint not null index"`
TaskID int64 `xorm:"bigint not null index"` TaskID int64 `xorm:"bigint not null index"`
ProjectViewID int64 `xorm:"bigint not null index"`
} }
func (taskBuckets20240315110428) TableName() string { func (taskBuckets20240315110428) TableName() string {

View File

@ -71,8 +71,13 @@ func (b *Bucket) TableName() string {
} }
type TaskBucket struct { type TaskBucket struct {
BucketID int64 `xorm:"bigint not null index"` BucketID int64 `xorm:"bigint not null index"`
TaskID int64 `xorm:"bigint not null index"` TaskID int64 `xorm:"bigint not null index"`
ProjectViewID int64 `xorm:"bigint not null index"`
}
func (b *TaskBucket) TableName() string {
return "task_buckets"
} }
func getBucketByID(s *xorm.Session, id int64) (b *Bucket, err error) { func getBucketByID(s *xorm.Session, id int64) (b *Bucket, err error) {

View File

@ -151,6 +151,14 @@ func (p *ProjectView) TableName() string {
return "project_views" return "project_views"
} }
func getViewsForProject(s *xorm.Session, projectID int64) (views []*ProjectView, err error) {
views = []*ProjectView{}
err = s.
Where("project_id = ?", projectID).
Find(&views)
return
}
// ReadAll gets all project views // ReadAll gets all project views
// @Summary Get all project views for a project // @Summary Get all project views for a project
// @Description Returns all project views for a sepcific project // @Description Returns all project views for a sepcific project
@ -173,12 +181,9 @@ func (p *ProjectView) ReadAll(s *xorm.Session, a web.Auth, _ string, _ int, _ in
return nil, 0, 0, ErrGenericForbidden{} return nil, 0, 0, ErrGenericForbidden{}
} }
projectViews := []*ProjectView{} projectViews, err := getViewsForProject(s, p.ProjectID)
err = s.
Where("project_id = ?", p.ProjectID).
Find(&projectViews)
if err != nil { if err != nil {
return return nil, 0, 0, err
} }
totalCount, err := s. totalCount, err := s.

View File

@ -648,41 +648,48 @@ 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, doCheckBucketLimit bool, view *ProjectView) (targetBucket *Bucket, err error) { func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, view *ProjectView, targetBucket *TaskBucket) (err error) {
if view == nil { var shouldChangeBucket = true
view, err = GetProjectViewByID(s, view.ID, task.ProjectID) if targetBucket == nil {
if err != nil { targetBucket = &TaskBucket{
return nil, err BucketID: 0,
TaskID: task.ID,
ProjectViewID: view.ID,
} }
} }
var bucket *Bucket oldTaskBucket := &TaskBucket{}
if task.Done && originalTask != nil && _, err = s.
(!originalTask.Done || task.ProjectID != originalTask.ProjectID) { Where("task_id = ? AND project_view_id = ?", task.ID, view.ID).
task.BucketID = view.DoneBucketID Get(oldTaskBucket)
if err != nil {
return
} }
if task.BucketID == 0 && originalTask != nil && originalTask.BucketID != 0 { if task.Done && originalTask != nil &&
task.BucketID = originalTask.BucketID (!originalTask.Done || task.ProjectID != originalTask.ProjectID) {
targetBucket.BucketID = view.DoneBucketID
}
if targetBucket.BucketID == 0 && oldTaskBucket.BucketID != 0 {
shouldChangeBucket = false
} }
// Either no bucket was provided or the task was moved between projects // Either no bucket was provided or the task was moved between projects
// But if the task was moved between projects, don't update the done bucket // But if the task was moved between projects, don't update the done bucket
// because then we have it already updated to the done bucket. // because then we have it already updated to the done bucket.
if task.BucketID == 0 || if targetBucket.BucketID == 0 ||
(originalTask != nil && task.ProjectID != 0 && originalTask.ProjectID != task.ProjectID && !task.Done) { (originalTask != nil && task.ProjectID != 0 && originalTask.ProjectID != task.ProjectID && !task.Done) {
task.BucketID, err = getDefaultBucketID(s, view) targetBucket.BucketID, err = getDefaultBucketID(s, view)
if err != nil { if err != nil {
return return
} }
} }
if bucket == nil { bucket, err := getBucketByID(s, targetBucket.BucketID)
bucket, err = getBucketByID(s, task.BucketID) if err != nil {
if err != nil { return err
return
}
} }
// 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
@ -693,9 +700,10 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucke
// 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
if doCheckBucketLimit { if targetBucket.BucketID != 0 && targetBucket.BucketID != oldTaskBucket.BucketID {
if err := checkBucketLimit(s, task, bucket); err != nil { err = checkBucketLimit(s, task, bucket)
return nil, err if err != nil {
return err
} }
} }
@ -703,7 +711,26 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucke
task.Done = true task.Done = true
} }
return bucket, nil // If the task was moved into the done bucket and the task has a repeating cycle we should not update
// the bucket.
if bucket.ID == view.DoneBucketID && task.RepeatAfter > 0 {
task.Done = true // This will trigger the correct re-scheduling of the task (happening in updateDone later)
shouldChangeBucket = false
}
if shouldChangeBucket {
_, err = s.
Where("task_id = ? AND project_view_id = ?", task.ID, view.ID).
Delete(&TaskBucket{})
if err != nil {
return
}
targetBucket.BucketID = bucket.ID
_, err = s.Insert(targetBucket)
}
return
} }
func calculateDefaultPosition(entityID int64, position float64) float64 { func calculateDefaultPosition(entityID int64, position float64) float64 {
@ -714,6 +741,18 @@ func calculateDefaultPosition(entityID int64, position float64) float64 {
return position return position
} }
func (t *Task) setTaskPosition(s *xorm.Session, position float64, view *ProjectView) (err error) {
pos := &TaskPosition{
TaskID: t.ID,
ProjectViewID: view.ID,
Position: calculateDefaultPosition(t.Index, position),
}
_, err = s.Insert(pos)
return
}
func getNextTaskIndex(s *xorm.Session, projectID int64) (nextIndex int64, err error) { func getNextTaskIndex(s *xorm.Session, projectID int64) (nextIndex int64, err error) {
latestTask := &Task{} latestTask := &Task{}
_, err = s. _, err = s.
@ -771,21 +810,12 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
t.UID = uuid.NewString() t.UID = uuid.NewString()
} }
// Get the default bucket and move the task there
_, err = setTaskBucket(s, t, nil, true, nil)
if err != nil {
return
}
// Get the index for this task // Get the index for this task
t.Index, err = getNextTaskIndex(s, t.ProjectID) t.Index, err = getNextTaskIndex(s, t.ProjectID)
if err != nil { if err != nil {
return err return err
} }
// If no position was supplied, set a default one
t.Position = calculateDefaultPosition(t.Index, t.Position)
t.HexColor = utils.NormalizeHex(t.HexColor) t.HexColor = utils.NormalizeHex(t.HexColor)
_, err = s.Insert(t) _, err = s.Insert(t)
@ -793,6 +823,25 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
return err return err
} }
views, err := getViewsForProject(s, t.ProjectID)
if err != nil {
return err
}
for _, view := range views {
// Get the default bucket and move the task there
err = setTaskBucket(s, t, nil, view, &TaskBucket{})
if err != nil {
return
}
err = t.setTaskPosition(s, t.Position, view)
if err != nil {
return
}
}
t.CreatedBy = createdBy t.CreatedBy = createdBy
// Update the assignees // Update the assignees
@ -864,21 +913,29 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
// Old task has the stored reminders // Old task has the stored reminders
ot.Reminders = reminders ot.Reminders = reminders
project, err := GetProjectSimpleByID(s, t.ProjectID) views, err := getViewsForProject(s, t.ProjectID)
if err != nil { if err != nil {
return err return err
} }
targetBucket, err := setTaskBucket(s, t, &ot, t.BucketID != 0 && t.BucketID != ot.BucketID, nil) for _, view := range views {
if err != nil { // bucket id mitgeben, dann den view zu dem bucket suchen und updaten wenn nötig
return err
}
// If the task was moved into the done bucket and the task has a repeating cycle we should not update taskBucket := &TaskBucket{
// the bucket. BucketID: t.BucketID,
if targetBucket.ID == project.DoneBucketID && t.RepeatAfter > 0 { TaskID: t.ID,
t.Done = true // This will trigger the correct re-scheduling of the task (happening in updateDone later) ProjectViewID: view.ID,
t.BucketID = ot.BucketID }
err = setTaskBucket(s, t, &ot, view, taskBucket)
if err != nil {
return err
}
err = t.setTaskPosition(s, t.Position, view)
if err != nil {
return
}
} }
// When a repeating task is marked as done, we update all deadlines and reminders and set it as undone // When a repeating task is marked as done, we update all deadlines and reminders and set it as undone
@ -909,7 +966,6 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
"percent_done", "percent_done",
"project_id", "project_id",
"bucket_id", "bucket_id",
"position",
"repeat_mode", "repeat_mode",
"cover_image_attachment_id", "cover_image_attachment_id",
} }