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
Signed by: konrad
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 {
BucketID int64 `xorm:"bigint not null index"`
TaskID int64 `xorm:"bigint not null index"`
BucketID int64 `xorm:"bigint not null index"`
TaskID int64 `xorm:"bigint not null index"`
ProjectViewID int64 `xorm:"bigint not null index"`
}
func (taskBuckets20240315110428) TableName() string {

View File

@ -71,8 +71,13 @@ func (b *Bucket) TableName() string {
}
type TaskBucket struct {
BucketID int64 `xorm:"bigint not null index"`
TaskID int64 `xorm:"bigint not null index"`
BucketID 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) {

View File

@ -151,6 +151,14 @@ func (p *ProjectView) TableName() string {
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
// @Summary Get all project views for a 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{}
}
projectViews := []*ProjectView{}
err = s.
Where("project_id = ?", p.ProjectID).
Find(&projectViews)
projectViews, err := getViewsForProject(s, p.ProjectID)
if err != nil {
return
return nil, 0, 0, err
}
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.
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 {
view, err = GetProjectViewByID(s, view.ID, task.ProjectID)
if err != nil {
return nil, err
var shouldChangeBucket = true
if targetBucket == nil {
targetBucket = &TaskBucket{
BucketID: 0,
TaskID: task.ID,
ProjectViewID: view.ID,
}
}
var bucket *Bucket
if task.Done && originalTask != nil &&
(!originalTask.Done || task.ProjectID != originalTask.ProjectID) {
task.BucketID = view.DoneBucketID
oldTaskBucket := &TaskBucket{}
_, err = s.
Where("task_id = ? AND project_view_id = ?", task.ID, view.ID).
Get(oldTaskBucket)
if err != nil {
return
}
if task.BucketID == 0 && originalTask != nil && originalTask.BucketID != 0 {
task.BucketID = originalTask.BucketID
if task.Done && originalTask != nil &&
(!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
// 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.
if task.BucketID == 0 ||
if targetBucket.BucketID == 0 ||
(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 {
return
}
}
if bucket == nil {
bucket, err = getBucketByID(s, task.BucketID)
if err != nil {
return
}
bucket, err := getBucketByID(s, targetBucket.BucketID)
if err != nil {
return err
}
// 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
// Only check the bucket limit if the task is being moved between buckets, allow reordering the task within a bucket
if doCheckBucketLimit {
if err := checkBucketLimit(s, task, bucket); err != nil {
return nil, err
if targetBucket.BucketID != 0 && targetBucket.BucketID != oldTaskBucket.BucketID {
err = checkBucketLimit(s, task, bucket)
if err != nil {
return err
}
}
@ -703,7 +711,26 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucke
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 {
@ -714,6 +741,18 @@ func calculateDefaultPosition(entityID int64, position float64) float64 {
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) {
latestTask := &Task{}
_, err = s.
@ -771,21 +810,12 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
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
t.Index, err = getNextTaskIndex(s, t.ProjectID)
if err != nil {
return err
}
// If no position was supplied, set a default one
t.Position = calculateDefaultPosition(t.Index, t.Position)
t.HexColor = utils.NormalizeHex(t.HexColor)
_, err = s.Insert(t)
@ -793,6 +823,25 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (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
// 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
ot.Reminders = reminders
project, err := GetProjectSimpleByID(s, t.ProjectID)
views, err := getViewsForProject(s, t.ProjectID)
if err != nil {
return err
}
targetBucket, err := setTaskBucket(s, t, &ot, t.BucketID != 0 && t.BucketID != ot.BucketID, nil)
if err != nil {
return err
}
for _, view := range views {
// bucket id mitgeben, dann den view zu dem bucket suchen und updaten wenn nötig
// If the task was moved into the done bucket and the task has a repeating cycle we should not update
// the bucket.
if targetBucket.ID == project.DoneBucketID && t.RepeatAfter > 0 {
t.Done = true // This will trigger the correct re-scheduling of the task (happening in updateDone later)
t.BucketID = ot.BucketID
taskBucket := &TaskBucket{
BucketID: t.BucketID,
TaskID: t.ID,
ProjectViewID: view.ID,
}
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
@ -909,7 +966,6 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
"percent_done",
"project_id",
"bucket_id",
"position",
"repeat_mode",
"cover_image_attachment_id",
}