Refactor ListTask to Task (#92)
This commit is contained in:
parent
be14634e1e
commit
66cdd79666
26 changed files with 206 additions and 189 deletions
|
@ -184,7 +184,7 @@ Sorry for some of them being in German, I'll tranlate them at some point.
|
||||||
* [x] Less files, but with some kind of logic
|
* [x] Less files, but with some kind of logic
|
||||||
* [x] Have extra functions for logging to call so it is possible to call `log.Info` instead of `log.Log.Info`
|
* [x] Have extra functions for logging to call so it is possible to call `log.Info` instead of `log.Log.Info`
|
||||||
* [x] `GetUserByID` and the likes should return pointers
|
* [x] `GetUserByID` and the likes should return pointers
|
||||||
* [ ] `ListTask` should be just `Task`
|
* [x] `ListTask` should be just `Task`
|
||||||
|
|
||||||
### Linters
|
### Linters
|
||||||
|
|
||||||
|
|
|
@ -70,8 +70,8 @@ func TestList(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
// Owned by user3
|
// Owned by user13
|
||||||
_, err := testHandler.testReadOne(nil, map[string]string{"list": "2"})
|
_, err := testHandler.testReadOne(nil, map[string]string{"list": "20"})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.(*echo.HTTPError).Message, `You don't have the right to see this`)
|
assert.Contains(t, err.(*echo.HTTPError).Message, `You don't have the right to see this`)
|
||||||
})
|
})
|
||||||
|
@ -177,8 +177,8 @@ func TestList(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
// Owned by user3
|
// Owned by user13
|
||||||
_, err := testHandler.testUpdate(nil, map[string]string{"list": "2"}, `{"title":"TestLoremIpsum"}`)
|
_, err := testHandler.testUpdate(nil, map[string]string{"list": "20"}, `{"title":"TestLoremIpsum"}`)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
||||||
})
|
})
|
||||||
|
@ -260,8 +260,8 @@ func TestList(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
// Owned by user3
|
// Owned by user13
|
||||||
_, err := testHandler.testDelete(nil, map[string]string{"list": "2"})
|
_, err := testHandler.testDelete(nil, map[string]string{"list": "20"})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
||||||
})
|
})
|
||||||
|
@ -371,8 +371,8 @@ func TestList(t *testing.T) {
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
|
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
// Owned by user3
|
// Owned by user13
|
||||||
_, err := testHandler.testCreate(nil, map[string]string{"namespace": "3"}, `{"title":"Lorem"}`)
|
_, err := testHandler.testCreate(nil, map[string]string{"namespace": "15"}, `{"title":"Lorem"}`)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
||||||
})
|
})
|
||||||
|
|
|
@ -25,16 +25,16 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListTask(t *testing.T) {
|
func TestTask(t *testing.T) {
|
||||||
testHandler := webHandlerTest{
|
testHandler := webHandlerTest{
|
||||||
user: &testuser1,
|
user: &testuser1,
|
||||||
strFunc: func() handler.CObject {
|
strFunc: func() handler.CObject {
|
||||||
return &models.ListTask{}
|
return &models.Task{}
|
||||||
},
|
},
|
||||||
t: t,
|
t: t,
|
||||||
}
|
}
|
||||||
// Only run specific nested tests:
|
// Only run specific nested tests:
|
||||||
// ^TestListTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$
|
// ^TestTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$
|
||||||
t.Run("ReadAll", func(t *testing.T) {
|
t.Run("ReadAll", func(t *testing.T) {
|
||||||
t.Run("Normal", func(t *testing.T) {
|
t.Run("Normal", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(nil, nil)
|
rec, err := testHandler.testReadAll(nil, nil)
|
||||||
|
@ -333,7 +333,7 @@ func TestListTask(t *testing.T) {
|
||||||
t.Run("Nonexisting", func(t *testing.T) {
|
t.Run("Nonexisting", func(t *testing.T) {
|
||||||
_, err := testHandler.testUpdate(nil, map[string]string{"listtask": "99999"}, `{"text":"Lorem Ipsum"}`)
|
_, err := testHandler.testUpdate(nil, map[string]string{"listtask": "99999"}, `{"text":"Lorem Ipsum"}`)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assertHandlerErrorCode(t, err, models.ErrCodeListTaskDoesNotExist)
|
assertHandlerErrorCode(t, err, models.ErrCodeTaskDoesNotExist)
|
||||||
})
|
})
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
|
@ -415,7 +415,7 @@ func TestListTask(t *testing.T) {
|
||||||
t.Run("Nonexisting", func(t *testing.T) {
|
t.Run("Nonexisting", func(t *testing.T) {
|
||||||
_, err := testHandler.testDelete(nil, map[string]string{"listtask": "99999"})
|
_, err := testHandler.testDelete(nil, map[string]string{"listtask": "99999"})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assertHandlerErrorCode(t, err, models.ErrCodeListTaskDoesNotExist)
|
assertHandlerErrorCode(t, err, models.ErrCodeTaskDoesNotExist)
|
||||||
})
|
})
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
|
@ -501,8 +501,8 @@ func TestListTask(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Rights check", func(t *testing.T) {
|
t.Run("Rights check", func(t *testing.T) {
|
||||||
t.Run("Forbidden", func(t *testing.T) {
|
t.Run("Forbidden", func(t *testing.T) {
|
||||||
// Owned by user3
|
// Owned by user13
|
||||||
_, err := testHandler.testCreate(nil, map[string]string{"list": "2"}, `{"text":"Lorem Ipsum"}`)
|
_, err := testHandler.testCreate(nil, map[string]string{"list": "20"}, `{"text":"Lorem Ipsum"}`)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
assert.Contains(t, err.(*echo.HTTPError).Message, `Forbidden`)
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,9 +24,9 @@ import (
|
||||||
// BulkTask is the definition of a bulk update task
|
// BulkTask is the definition of a bulk update task
|
||||||
type BulkTask struct {
|
type BulkTask struct {
|
||||||
// A list of task ids to update
|
// A list of task ids to update
|
||||||
IDs []int64 `json:"task_ids"`
|
IDs []int64 `json:"task_ids"`
|
||||||
Tasks []*ListTask `json:"-"`
|
Tasks []*Task `json:"-"`
|
||||||
ListTask
|
Task
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bt *BulkTask) checkIfTasksAreOnTheSameList() (err error) {
|
func (bt *BulkTask) checkIfTasksAreOnTheSameList() (err error) {
|
||||||
|
@ -72,7 +72,7 @@ func (bt *BulkTask) CanUpdate(a web.Auth) (bool, error) {
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security JWTKeyAuth
|
// @Security JWTKeyAuth
|
||||||
// @Param task body models.BulkTask true "The task object. Looks like a normal task, the only difference is it uses an array of list_ids to update."
|
// @Param task body models.BulkTask true "The task object. Looks like a normal task, the only difference is it uses an array of list_ids to update."
|
||||||
// @Success 200 {object} models.ListTask "The updated task object."
|
// @Success 200 {object} models.Task "The updated task object."
|
||||||
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
|
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
|
||||||
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)"
|
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
|
@ -90,7 +90,7 @@ func (bt *BulkTask) Update() (err error) {
|
||||||
for _, oldtask := range bt.Tasks {
|
for _, oldtask := range bt.Tasks {
|
||||||
|
|
||||||
// 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
|
||||||
updateDone(oldtask, &bt.ListTask)
|
updateDone(oldtask, &bt.Task)
|
||||||
|
|
||||||
// Update the assignees
|
// Update the assignees
|
||||||
if err := oldtask.updateTaskAssignees(bt.Assignees); err != nil {
|
if err := oldtask.updateTaskAssignees(bt.Assignees); err != nil {
|
||||||
|
@ -100,12 +100,12 @@ func (bt *BulkTask) Update() (err error) {
|
||||||
// For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand
|
// For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand
|
||||||
// Which is why we merge the actual task struct with the one we got from the
|
// Which is why we merge the actual task struct with the one we got from the
|
||||||
// The user struct overrides values in the actual one.
|
// The user struct overrides values in the actual one.
|
||||||
if err := mergo.Merge(oldtask, &bt.ListTask, mergo.WithOverride); err != nil {
|
if err := mergo.Merge(oldtask, &bt.Task, mergo.WithOverride); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// And because a false is considered to be a null value, we need to explicitly check that case here.
|
// And because a false is considered to be a null value, we need to explicitly check that case here.
|
||||||
if !bt.ListTask.Done {
|
if !bt.Task.Done {
|
||||||
oldtask.Done = false
|
oldtask.Done = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@ import (
|
||||||
|
|
||||||
func TestBulkTask_Update(t *testing.T) {
|
func TestBulkTask_Update(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
IDs []int64
|
IDs []int64
|
||||||
Tasks []*ListTask
|
Tasks []*Task
|
||||||
ListTask ListTask
|
Task Task
|
||||||
User *User
|
User *User
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -21,7 +21,7 @@ func TestBulkTask_Update(t *testing.T) {
|
||||||
name: "Test normal update",
|
name: "Test normal update",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
IDs: []int64{10, 11, 12},
|
IDs: []int64{10, 11, 12},
|
||||||
ListTask: ListTask{
|
Task: Task{
|
||||||
Text: "bulkupdated",
|
Text: "bulkupdated",
|
||||||
},
|
},
|
||||||
User: &User{ID: 1},
|
User: &User{ID: 1},
|
||||||
|
@ -31,7 +31,7 @@ func TestBulkTask_Update(t *testing.T) {
|
||||||
name: "Test with one task on different list",
|
name: "Test with one task on different list",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
IDs: []int64{10, 11, 12, 13},
|
IDs: []int64{10, 11, 12, 13},
|
||||||
ListTask: ListTask{
|
Task: Task{
|
||||||
Text: "bulkupdated",
|
Text: "bulkupdated",
|
||||||
},
|
},
|
||||||
User: &User{ID: 1},
|
User: &User{ID: 1},
|
||||||
|
@ -42,7 +42,7 @@ func TestBulkTask_Update(t *testing.T) {
|
||||||
name: "Test without any tasks",
|
name: "Test without any tasks",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
IDs: []int64{},
|
IDs: []int64{},
|
||||||
ListTask: ListTask{
|
Task: Task{
|
||||||
Text: "bulkupdated",
|
Text: "bulkupdated",
|
||||||
},
|
},
|
||||||
User: &User{ID: 1},
|
User: &User{ID: 1},
|
||||||
|
@ -53,9 +53,9 @@ func TestBulkTask_Update(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
bt := &BulkTask{
|
bt := &BulkTask{
|
||||||
IDs: tt.fields.IDs,
|
IDs: tt.fields.IDs,
|
||||||
Tasks: tt.fields.Tasks,
|
Tasks: tt.fields.Tasks,
|
||||||
ListTask: tt.fields.ListTask,
|
Task: tt.fields.Task,
|
||||||
}
|
}
|
||||||
allowed, _ := bt.CanUpdate(tt.fields.User)
|
allowed, _ := bt.CanUpdate(tt.fields.User)
|
||||||
if !allowed != tt.wantForbidden {
|
if !allowed != tt.wantForbidden {
|
|
@ -427,48 +427,48 @@ func (err ErrListTitleCannotBeEmpty) HTTPError() web.HTTPError {
|
||||||
// List task errors
|
// List task errors
|
||||||
// ================
|
// ================
|
||||||
|
|
||||||
// ErrListTaskCannotBeEmpty represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
|
// ErrTaskCannotBeEmpty represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
|
||||||
type ErrListTaskCannotBeEmpty struct{}
|
type ErrTaskCannotBeEmpty struct{}
|
||||||
|
|
||||||
// IsErrListTaskCannotBeEmpty checks if an error is a ErrListDoesNotExist.
|
// IsErrTaskCannotBeEmpty checks if an error is a ErrListDoesNotExist.
|
||||||
func IsErrListTaskCannotBeEmpty(err error) bool {
|
func IsErrTaskCannotBeEmpty(err error) bool {
|
||||||
_, ok := err.(ErrListTaskCannotBeEmpty)
|
_, ok := err.(ErrTaskCannotBeEmpty)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrListTaskCannotBeEmpty) Error() string {
|
func (err ErrTaskCannotBeEmpty) Error() string {
|
||||||
return fmt.Sprintf("List task text cannot be empty.")
|
return fmt.Sprintf("List task text cannot be empty.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrCodeListTaskCannotBeEmpty holds the unique world-error code of this error
|
// ErrCodeTaskCannotBeEmpty holds the unique world-error code of this error
|
||||||
const ErrCodeListTaskCannotBeEmpty = 4001
|
const ErrCodeTaskCannotBeEmpty = 4001
|
||||||
|
|
||||||
// HTTPError holds the http error description
|
// HTTPError holds the http error description
|
||||||
func (err ErrListTaskCannotBeEmpty) HTTPError() web.HTTPError {
|
func (err ErrTaskCannotBeEmpty) HTTPError() web.HTTPError {
|
||||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeListTaskCannotBeEmpty, Message: "You must provide at least a list task text."}
|
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTaskCannotBeEmpty, Message: "You must provide at least a list task text."}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrListTaskDoesNotExist represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
|
// ErrTaskDoesNotExist represents a "ErrListDoesNotExist" kind of error. Used if the list does not exist.
|
||||||
type ErrListTaskDoesNotExist struct {
|
type ErrTaskDoesNotExist struct {
|
||||||
ID int64
|
ID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrListTaskDoesNotExist checks if an error is a ErrListDoesNotExist.
|
// IsErrTaskDoesNotExist checks if an error is a ErrListDoesNotExist.
|
||||||
func IsErrListTaskDoesNotExist(err error) bool {
|
func IsErrTaskDoesNotExist(err error) bool {
|
||||||
_, ok := err.(ErrListTaskDoesNotExist)
|
_, ok := err.(ErrTaskDoesNotExist)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrListTaskDoesNotExist) Error() string {
|
func (err ErrTaskDoesNotExist) Error() string {
|
||||||
return fmt.Sprintf("List task does not exist. [ID: %d]", err.ID)
|
return fmt.Sprintf("List task does not exist. [ID: %d]", err.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrCodeListTaskDoesNotExist holds the unique world-error code of this error
|
// ErrCodeTaskDoesNotExist holds the unique world-error code of this error
|
||||||
const ErrCodeListTaskDoesNotExist = 4002
|
const ErrCodeTaskDoesNotExist = 4002
|
||||||
|
|
||||||
// HTTPError holds the http error description
|
// HTTPError holds the http error description
|
||||||
func (err ErrListTaskDoesNotExist) HTTPError() web.HTTPError {
|
func (err ErrTaskDoesNotExist) HTTPError() web.HTTPError {
|
||||||
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListTaskDoesNotExist, Message: "This list task does not exist"}
|
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeTaskDoesNotExist, Message: "This list task does not exist"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrBulkTasksMustBeInSameList represents a "ErrBulkTasksMustBeInSameList" kind of error.
|
// ErrBulkTasksMustBeInSameList represents a "ErrBulkTasksMustBeInSameList" kind of error.
|
||||||
|
|
|
@ -152,3 +152,11 @@
|
||||||
namespace_id: 14
|
namespace_id: 14
|
||||||
updated: 0
|
updated: 0
|
||||||
created: 0
|
created: 0
|
||||||
|
-
|
||||||
|
id: 20
|
||||||
|
title: Test20
|
||||||
|
description: Lorem Ipsum
|
||||||
|
owner_id: 13
|
||||||
|
namespace_id: 15
|
||||||
|
updated: 0
|
||||||
|
created: 0
|
||||||
|
|
|
@ -70,3 +70,9 @@
|
||||||
owner_id: 7
|
owner_id: 7
|
||||||
updated: 0
|
updated: 0
|
||||||
created: 0
|
created: 0
|
||||||
|
- id: 15
|
||||||
|
name: testnamespace15
|
||||||
|
description: Lorem Ipsum
|
||||||
|
owner_id: 13
|
||||||
|
updated: 0
|
||||||
|
created: 0
|
||||||
|
|
|
@ -109,7 +109,7 @@ func (lt *LabelTask) Create(a web.Auth) (err error) {
|
||||||
// @Router /tasks/{task}/labels [get]
|
// @Router /tasks/{task}/labels [get]
|
||||||
func (lt *LabelTask) ReadAll(search string, a web.Auth, page int) (labels interface{}, err error) {
|
func (lt *LabelTask) ReadAll(search string, a web.Auth, page int) (labels interface{}, err error) {
|
||||||
// Check if the user has the right to see the task
|
// Check if the user has the right to see the task
|
||||||
task := ListTask{ID: lt.TaskID}
|
task := Task{ID: lt.TaskID}
|
||||||
canRead, err := task.CanRead(a)
|
canRead, err := task.CanRead(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -193,7 +193,7 @@ func getLabelsByTaskIDs(opts *LabelByTaskIDsOptions) (ls []*labelWithTaskID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create or update a bunch of task labels
|
// Create or update a bunch of task labels
|
||||||
func (t *ListTask) updateTaskLabels(creator web.Auth, labels []*Label) (err error) {
|
func (t *Task) updateTaskLabels(creator web.Auth, labels []*Label) (err error) {
|
||||||
|
|
||||||
// If we don't have any new labels, delete everything right away. Saves us some hassle.
|
// If we don't have any new labels, delete everything right away. Saves us some hassle.
|
||||||
if len(labels) == 0 && len(t.Labels) > 0 {
|
if len(labels) == 0 && len(t.Labels) > 0 {
|
||||||
|
|
|
@ -76,7 +76,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
||||||
a: &User{ID: 1},
|
a: &User{ID: 1},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
errType: IsErrListTaskDoesNotExist,
|
errType: IsErrTaskDoesNotExist,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -168,7 +168,7 @@ func TestLabelTask_Create(t *testing.T) {
|
||||||
},
|
},
|
||||||
wantForbidden: true,
|
wantForbidden: true,
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
errType: IsErrListTaskDoesNotExist,
|
errType: IsErrTaskDoesNotExist,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -35,7 +35,7 @@ type List struct {
|
||||||
// The user who created this list.
|
// The user who created this list.
|
||||||
Owner *User `xorm:"-" json:"owner" valid:"-"`
|
Owner *User `xorm:"-" json:"owner" valid:"-"`
|
||||||
// An array of tasks which belong to the list.
|
// An array of tasks which belong to the list.
|
||||||
Tasks []*ListTask `xorm:"-" json:"tasks"`
|
Tasks []*Task `xorm:"-" json:"tasks"`
|
||||||
|
|
||||||
// A unix timestamp when this list was created. You cannot change this value.
|
// A unix timestamp when this list was created. You cannot change this value.
|
||||||
Created int64 `xorm:"created not null" json:"created"`
|
Created int64 `xorm:"created not null" json:"created"`
|
||||||
|
@ -206,7 +206,7 @@ func AddListDetails(lists []*List) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all tasks
|
// Get all tasks
|
||||||
ts := []*ListTask{}
|
ts := []*Task{}
|
||||||
err = x.In("list_id", listIDs).Find(&ts)
|
err = x.In("list_id", listIDs).Find(&ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -354,6 +354,6 @@ func (l *List) Delete() (err error) {
|
||||||
metrics.UpdateCount(-1, metrics.ListCountKey)
|
metrics.UpdateCount(-1, metrics.ListCountKey)
|
||||||
|
|
||||||
// Delete all todotasks on that list
|
// Delete all todotasks on that list
|
||||||
_, err = x.Where("list_id = ?", l.ID).Delete(&ListTask{})
|
_, err = x.Where("list_id = ?", l.ID).Delete(&Task{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ func (l *List) checkRight(a web.Auth, rights ...Right) (bool, error) {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user is the owner of a namespace, it has any right, all the time
|
||||||
|
conds = append(conds, builder.Eq{"n.owner_id": a.GetID()})
|
||||||
|
|
||||||
exists, err := x.Select("l.*").
|
exists, err := x.Select("l.*").
|
||||||
Table("list").
|
Table("list").
|
||||||
Alias("l").
|
Alias("l").
|
||||||
|
|
|
@ -36,7 +36,7 @@ func GetTables() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
&User{},
|
&User{},
|
||||||
&List{},
|
&List{},
|
||||||
&ListTask{},
|
&Task{},
|
||||||
&Team{},
|
&Team{},
|
||||||
&TeamMember{},
|
&TeamMember{},
|
||||||
&TeamList{},
|
&TeamList{},
|
||||||
|
@ -44,7 +44,7 @@ func GetTables() []interface{} {
|
||||||
&Namespace{},
|
&Namespace{},
|
||||||
&ListUser{},
|
&ListUser{},
|
||||||
&NamespaceUser{},
|
&NamespaceUser{},
|
||||||
&ListTaskAssginee{},
|
&TaskAssginee{},
|
||||||
&Label{},
|
&Label{},
|
||||||
&LabelTask{},
|
&LabelTask{},
|
||||||
&TaskReminder{},
|
&TaskReminder{},
|
||||||
|
|
|
@ -330,7 +330,7 @@ func (n *Namespace) Delete() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete tasks
|
// Delete tasks
|
||||||
_, err = x.In("list_id", listIDs).Delete(&ListTask{})
|
_, err = x.In("list_id", listIDs).Delete(&Task{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ import (
|
||||||
"code.vikunja.io/web"
|
"code.vikunja.io/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListTaskAssginee represents an assignment of a user to a task
|
// TaskAssginee represents an assignment of a user to a task
|
||||||
type ListTaskAssginee struct {
|
type TaskAssginee struct {
|
||||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"-"`
|
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"-"`
|
||||||
TaskID int64 `xorm:"int(11) INDEX not null" json:"-" param:"listtask"`
|
TaskID int64 `xorm:"int(11) INDEX not null" json:"-" param:"listtask"`
|
||||||
UserID int64 `xorm:"int(11) INDEX not null" json:"user_id" param:"user"`
|
UserID int64 `xorm:"int(11) INDEX not null" json:"user_id" param:"user"`
|
||||||
|
@ -32,18 +32,18 @@ type ListTaskAssginee struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName makes a pretty table name
|
// TableName makes a pretty table name
|
||||||
func (ListTaskAssginee) TableName() string {
|
func (TaskAssginee) TableName() string {
|
||||||
return "task_assignees"
|
return "task_assignees"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListTaskAssigneeWithUser is a helper type to deal with user joins
|
// TaskAssigneeWithUser is a helper type to deal with user joins
|
||||||
type ListTaskAssigneeWithUser struct {
|
type TaskAssigneeWithUser struct {
|
||||||
TaskID int64
|
TaskID int64
|
||||||
User `xorm:"extends"`
|
User `xorm:"extends"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*ListTaskAssigneeWithUser, err error) {
|
func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*TaskAssigneeWithUser, err error) {
|
||||||
taskAssignees = []*ListTaskAssigneeWithUser{nil}
|
taskAssignees = []*TaskAssigneeWithUser{nil}
|
||||||
err = x.Table("task_assignees").
|
err = x.Table("task_assignees").
|
||||||
Select("task_id, users.*").
|
Select("task_id, users.*").
|
||||||
In("task_id", taskIDs).
|
In("task_id", taskIDs).
|
||||||
|
@ -53,12 +53,12 @@ func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*ListTaskAssi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create or update a bunch of task assignees
|
// Create or update a bunch of task assignees
|
||||||
func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) {
|
func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
|
||||||
|
|
||||||
// If we don't have any new assignees, delete everything right away. Saves us some hassle.
|
// If we don't have any new assignees, delete everything right away. Saves us some hassle.
|
||||||
if len(assignees) == 0 && len(t.Assignees) > 0 {
|
if len(assignees) == 0 && len(t.Assignees) > 0 {
|
||||||
_, err = x.Where("task_id = ?", t.ID).
|
_, err = x.Where("task_id = ?", t.ID).
|
||||||
Delete(ListTaskAssginee{})
|
Delete(TaskAssginee{})
|
||||||
t.setTaskAssignees(assignees)
|
t.setTaskAssignees(assignees)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) {
|
||||||
if len(assigneesToDelete) > 0 {
|
if len(assigneesToDelete) > 0 {
|
||||||
_, err = x.In("user_id", assigneesToDelete).
|
_, err = x.In("user_id", assigneesToDelete).
|
||||||
And("task_id = ?", t.ID).
|
And("task_id = ?", t.ID).
|
||||||
Delete(ListTaskAssginee{})
|
Delete(TaskAssginee{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Small helper functions to set the new assignees in various places
|
// Small helper functions to set the new assignees in various places
|
||||||
func (t *ListTask) setTaskAssignees(assignees []*User) {
|
func (t *Task) setTaskAssignees(assignees []*User) {
|
||||||
if len(assignees) == 0 {
|
if len(assignees) == 0 {
|
||||||
t.Assignees = nil
|
t.Assignees = nil
|
||||||
return
|
return
|
||||||
|
@ -152,8 +152,8 @@ func (t *ListTask) setTaskAssignees(assignees []*User) {
|
||||||
// @Failure 403 {object} code.vikunja.io/web.HTTPError "Not allowed to delete the assignee."
|
// @Failure 403 {object} code.vikunja.io/web.HTTPError "Not allowed to delete the assignee."
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/{taskID}/assignees/{userID} [delete]
|
// @Router /tasks/{taskID}/assignees/{userID} [delete]
|
||||||
func (la *ListTaskAssginee) Delete() (err error) {
|
func (la *TaskAssginee) Delete() (err error) {
|
||||||
_, err = x.Delete(&ListTaskAssginee{TaskID: la.TaskID, UserID: la.UserID})
|
_, err = x.Delete(&TaskAssginee{TaskID: la.TaskID, UserID: la.UserID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -169,13 +169,13 @@ func (la *ListTaskAssginee) Delete() (err error) {
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security JWTKeyAuth
|
// @Security JWTKeyAuth
|
||||||
// @Param assignee body models.ListTaskAssginee true "The assingee object"
|
// @Param assignee body models.TaskAssginee true "The assingee object"
|
||||||
// @Param taskID path int true "Task ID"
|
// @Param taskID path int true "Task ID"
|
||||||
// @Success 200 {object} models.ListTaskAssginee "The created assingee object."
|
// @Success 200 {object} models.TaskAssginee "The created assingee object."
|
||||||
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
|
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/{taskID}/assignees [put]
|
// @Router /tasks/{taskID}/assignees [put]
|
||||||
func (la *ListTaskAssginee) Create(a web.Auth) (err error) {
|
func (la *TaskAssginee) Create(a web.Auth) (err error) {
|
||||||
|
|
||||||
// Get the list to perform later checks
|
// Get the list to perform later checks
|
||||||
list, err := GetListSimplByTaskID(la.TaskID)
|
list, err := GetListSimplByTaskID(la.TaskID)
|
||||||
|
@ -183,11 +183,11 @@ func (la *ListTaskAssginee) Create(a web.Auth) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
task := &ListTask{ID: la.TaskID}
|
task := &Task{ID: la.TaskID}
|
||||||
return task.addNewAssigneeByID(la.UserID, list)
|
return task.addNewAssigneeByID(la.UserID, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err error) {
|
func (t *Task) addNewAssigneeByID(newAssigneeID int64, list *List) (err error) {
|
||||||
// Check if the user exists and has access to the list
|
// Check if the user exists and has access to the list
|
||||||
newAssignee, err := GetUserByID(newAssigneeID)
|
newAssignee, err := GetUserByID(newAssigneeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -201,7 +201,7 @@ func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err erro
|
||||||
return ErrUserDoesNotHaveAccessToList{list.ID, newAssigneeID}
|
return ErrUserDoesNotHaveAccessToList{list.ID, newAssigneeID}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = x.Insert(ListTaskAssginee{
|
_, err = x.Insert(TaskAssginee{
|
||||||
TaskID: t.ID,
|
TaskID: t.ID,
|
||||||
UserID: newAssigneeID,
|
UserID: newAssigneeID,
|
||||||
})
|
})
|
||||||
|
@ -225,7 +225,7 @@ func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err erro
|
||||||
// @Success 200 {array} models.User "The assignees"
|
// @Success 200 {array} models.User "The assignees"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /labels [get]
|
// @Router /labels [get]
|
||||||
func (la *ListTaskAssginee) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
|
func (la *TaskAssginee) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
|
||||||
var taskAssignees []*User
|
var taskAssignees []*User
|
||||||
err := x.Table("task_assignees").
|
err := x.Table("task_assignees").
|
||||||
Select("users.*").
|
Select("users.*").
|
||||||
|
@ -255,7 +255,7 @@ type BulkAssignees struct {
|
||||||
// @Security JWTKeyAuth
|
// @Security JWTKeyAuth
|
||||||
// @Param assignee body models.BulkAssignees true "The array of assignees"
|
// @Param assignee body models.BulkAssignees true "The array of assignees"
|
||||||
// @Param taskID path int true "Task ID"
|
// @Param taskID path int true "Task ID"
|
||||||
// @Success 200 {object} models.ListTaskAssginee "The created assingees object."
|
// @Success 200 {object} models.TaskAssginee "The created assingees object."
|
||||||
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
|
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid assignee object provided."
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/{taskID}/assignees/bulk [post]
|
// @Router /tasks/{taskID}/assignees/bulk [post]
|
|
@ -21,21 +21,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CanCreate checks if a user can add a new assignee
|
// CanCreate checks if a user can add a new assignee
|
||||||
func (la *ListTaskAssginee) CanCreate(a web.Auth) (bool, error) {
|
func (la *TaskAssginee) CanCreate(a web.Auth) (bool, error) {
|
||||||
return canDoListTaskAssingee(la.TaskID, a)
|
return canDoTaskAssingee(la.TaskID, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanCreate checks if a user can add a new assignee
|
// CanCreate checks if a user can add a new assignee
|
||||||
func (ba *BulkAssignees) CanCreate(a web.Auth) (bool, error) {
|
func (ba *BulkAssignees) CanCreate(a web.Auth) (bool, error) {
|
||||||
return canDoListTaskAssingee(ba.TaskID, a)
|
return canDoTaskAssingee(ba.TaskID, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanDelete checks if a user can delete an assignee
|
// CanDelete checks if a user can delete an assignee
|
||||||
func (la *ListTaskAssginee) CanDelete(a web.Auth) (bool, error) {
|
func (la *TaskAssginee) CanDelete(a web.Auth) (bool, error) {
|
||||||
return canDoListTaskAssingee(la.TaskID, a)
|
return canDoTaskAssingee(la.TaskID, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func canDoListTaskAssingee(taskID int64, a web.Auth) (bool, error) {
|
func canDoTaskAssingee(taskID int64, a web.Auth) (bool, error) {
|
||||||
// Check if the current user can edit the list
|
// Check if the current user can edit the list
|
||||||
list, err := GetListSimplByTaskID(taskID)
|
list, err := GetListSimplByTaskID(taskID)
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"code.vikunja.io/web"
|
"code.vikunja.io/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sortTasksForTesting(by SortBy) (tasks []*ListTask) {
|
func sortTasksForTesting(by SortBy) (tasks []*Task) {
|
||||||
user1 := &User{
|
user1 := &User{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
|
@ -37,7 +37,7 @@ func sortTasksForTesting(by SortBy) (tasks []*ListTask) {
|
||||||
AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed", // hash for ""
|
AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed", // hash for ""
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks = []*ListTask{
|
tasks = []*Task{
|
||||||
{
|
{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Text: "task #1",
|
Text: "task #1",
|
||||||
|
@ -341,7 +341,7 @@ func sortTasksForTesting(by SortBy) (tasks []*ListTask) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListTask_ReadAll(t *testing.T) {
|
func TestTask_ReadAll(t *testing.T) {
|
||||||
assert.NoError(t, LoadFixtures())
|
assert.NoError(t, LoadFixtures())
|
||||||
|
|
||||||
// Dummy users
|
// Dummy users
|
||||||
|
@ -368,7 +368,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
Sorting string
|
Sorting string
|
||||||
StartDateSortUnix int64
|
StartDateSortUnix int64
|
||||||
EndDateSortUnix int64
|
EndDateSortUnix int64
|
||||||
Subtasks []*ListTask
|
Subtasks []*Task
|
||||||
Created int64
|
Created int64
|
||||||
Updated int64
|
Updated int64
|
||||||
CreatedBy *User
|
CreatedBy *User
|
||||||
|
@ -388,7 +388,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks normally",
|
name: "ReadAll Tasks normally",
|
||||||
fields: fields{},
|
fields: fields{},
|
||||||
args: args{
|
args: args{
|
||||||
search: "",
|
search: "",
|
||||||
|
@ -399,7 +399,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks sorted by priority (desc)",
|
name: "ReadAll Tasks sorted by priority (desc)",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
Sorting: "priority",
|
Sorting: "priority",
|
||||||
},
|
},
|
||||||
|
@ -412,7 +412,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks sorted by priority asc",
|
name: "ReadAll Tasks sorted by priority asc",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
Sorting: "priorityasc",
|
Sorting: "priorityasc",
|
||||||
},
|
},
|
||||||
|
@ -425,7 +425,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks sorted by priority desc",
|
name: "ReadAll Tasks sorted by priority desc",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
Sorting: "prioritydesc",
|
Sorting: "prioritydesc",
|
||||||
},
|
},
|
||||||
|
@ -438,7 +438,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks sorted by due date default desc",
|
name: "ReadAll Tasks sorted by due date default desc",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
Sorting: "duedate",
|
Sorting: "duedate",
|
||||||
},
|
},
|
||||||
|
@ -451,7 +451,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks sorted by due date asc",
|
name: "ReadAll Tasks sorted by due date asc",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
Sorting: "duedateasc",
|
Sorting: "duedateasc",
|
||||||
},
|
},
|
||||||
|
@ -464,7 +464,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks sorted by due date desc",
|
name: "ReadAll Tasks sorted by due date desc",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
Sorting: "duedatedesc",
|
Sorting: "duedatedesc",
|
||||||
},
|
},
|
||||||
|
@ -478,7 +478,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks with range",
|
name: "ReadAll Tasks with range",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
StartDateSortUnix: 1544500000,
|
StartDateSortUnix: 1544500000,
|
||||||
EndDateSortUnix: 1544600000,
|
EndDateSortUnix: 1544600000,
|
||||||
|
@ -488,7 +488,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
a: &User{ID: 1},
|
a: &User{ID: 1},
|
||||||
page: 0,
|
page: 0,
|
||||||
},
|
},
|
||||||
want: []*ListTask{
|
want: []*Task{
|
||||||
{
|
{
|
||||||
ID: 7,
|
ID: 7,
|
||||||
Text: "task #7 with start date",
|
Text: "task #7 with start date",
|
||||||
|
@ -514,7 +514,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks with range",
|
name: "ReadAll Tasks with range",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
StartDateSortUnix: 1544700000,
|
StartDateSortUnix: 1544700000,
|
||||||
EndDateSortUnix: 1545000000,
|
EndDateSortUnix: 1545000000,
|
||||||
|
@ -524,7 +524,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
a: &User{ID: 1},
|
a: &User{ID: 1},
|
||||||
page: 0,
|
page: 0,
|
||||||
},
|
},
|
||||||
want: []*ListTask{
|
want: []*Task{
|
||||||
{
|
{
|
||||||
ID: 8,
|
ID: 8,
|
||||||
Text: "task #8 with end date",
|
Text: "task #8 with end date",
|
||||||
|
@ -550,7 +550,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ReadAll ListTasks with range without end date",
|
name: "ReadAll Tasks with range without end date",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
StartDateSortUnix: 1544700000,
|
StartDateSortUnix: 1544700000,
|
||||||
},
|
},
|
||||||
|
@ -559,7 +559,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
a: &User{ID: 1},
|
a: &User{ID: 1},
|
||||||
page: 0,
|
page: 0,
|
||||||
},
|
},
|
||||||
want: []*ListTask{
|
want: []*Task{
|
||||||
{
|
{
|
||||||
ID: 8,
|
ID: 8,
|
||||||
Text: "task #8 with end date",
|
Text: "task #8 with end date",
|
||||||
|
@ -587,7 +587,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
lt := &ListTask{
|
lt := &Task{
|
||||||
ID: tt.fields.ID,
|
ID: tt.fields.ID,
|
||||||
Text: tt.fields.Text,
|
Text: tt.fields.Text,
|
||||||
Description: tt.fields.Description,
|
Description: tt.fields.Description,
|
||||||
|
@ -611,7 +611,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
}
|
}
|
||||||
got, err := lt.ReadAll(tt.args.search, tt.args.a, tt.args.page)
|
got, err := lt.ReadAll(tt.args.search, tt.args.a, tt.args.page)
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("Test %s, ListTask.ReadAll() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
t.Errorf("Test %s, Task.ReadAll() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if diff, equal := messagediff.PrettyDiff(got, tt.want); !equal {
|
if diff, equal := messagediff.PrettyDiff(got, tt.want); !equal {
|
|
@ -25,8 +25,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListTask represents an task in a todolist
|
// Task represents an task in a todolist
|
||||||
type ListTask struct {
|
type Task struct {
|
||||||
// The unique, numeric id of this task.
|
// The unique, numeric id of this task.
|
||||||
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"listtask"`
|
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"listtask"`
|
||||||
// The task text. This is what you'll see in the list.
|
// The task text. This is what you'll see in the list.
|
||||||
|
@ -69,7 +69,7 @@ type ListTask struct {
|
||||||
EndDateSortUnix int64 `xorm:"-" json:"-" query:"enddate"`
|
EndDateSortUnix int64 `xorm:"-" json:"-" query:"enddate"`
|
||||||
|
|
||||||
// An array of subtasks.
|
// An array of subtasks.
|
||||||
Subtasks []*ListTask `xorm:"-" json:"subtasks"`
|
Subtasks []*Task `xorm:"-" json:"subtasks"`
|
||||||
|
|
||||||
// A unix timestamp when this task was created. You cannot change this value.
|
// A unix timestamp when this task was created. You cannot change this value.
|
||||||
Created int64 `xorm:"created not null" json:"created"`
|
Created int64 `xorm:"created not null" json:"created"`
|
||||||
|
@ -84,7 +84,7 @@ type ListTask struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for listtasks
|
// TableName returns the table name for listtasks
|
||||||
func (ListTask) TableName() string {
|
func (Task) TableName() string {
|
||||||
return "tasks"
|
return "tasks"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,10 +125,10 @@ const (
|
||||||
// @Param startdate query int false "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time."
|
// @Param startdate query int false "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time."
|
||||||
// @Param enddate query int false "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time."
|
// @Param enddate query int false "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time."
|
||||||
// @Security JWTKeyAuth
|
// @Security JWTKeyAuth
|
||||||
// @Success 200 {array} models.ListTask "The tasks"
|
// @Success 200 {array} models.Task "The tasks"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/all [get]
|
// @Router /tasks/all [get]
|
||||||
func (t *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
|
func (t *Task) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
|
||||||
var sortby SortBy
|
var sortby SortBy
|
||||||
switch t.Sorting {
|
switch t.Sorting {
|
||||||
case "priority":
|
case "priority":
|
||||||
|
@ -151,7 +151,7 @@ func (t *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, er
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetTasksByUser returns all tasks for a user
|
//GetTasksByUser returns all tasks for a user
|
||||||
func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate time.Time, endDate time.Time) ([]*ListTask, error) {
|
func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate time.Time, endDate time.Time) ([]*Task, error) {
|
||||||
// Get all lists
|
// Get all lists
|
||||||
lists, err := getRawListsForUser("", u, page)
|
lists, err := getRawListsForUser("", u, page)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -176,7 +176,7 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
|
||||||
orderby = "due_date_unix asc"
|
orderby = "due_date_unix asc"
|
||||||
}
|
}
|
||||||
|
|
||||||
taskMap := make(map[int64]*ListTask)
|
taskMap := make(map[int64]*Task)
|
||||||
|
|
||||||
// Then return all tasks for that lists
|
// Then return all tasks for that lists
|
||||||
if startDate.Unix() != 0 || endDate.Unix() != 0 {
|
if startDate.Unix() != 0 || endDate.Unix() != 0 {
|
||||||
|
@ -222,7 +222,7 @@ func GetTasksByUser(search string, u *User, page int, sortby SortBy, startDate t
|
||||||
return tasks, err
|
return tasks, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortTasks(tasks []*ListTask, by SortBy) {
|
func sortTasks(tasks []*Task, by SortBy) {
|
||||||
switch by {
|
switch by {
|
||||||
case SortTasksByPriorityDesc:
|
case SortTasksByPriorityDesc:
|
||||||
sort.Slice(tasks, func(i, j int) bool {
|
sort.Slice(tasks, func(i, j int) bool {
|
||||||
|
@ -244,9 +244,9 @@ func sortTasks(tasks []*ListTask, by SortBy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTasksByListID gets all todotasks for a list
|
// GetTasksByListID gets all todotasks for a list
|
||||||
func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
|
func GetTasksByListID(listID int64) (tasks []*Task, err error) {
|
||||||
// make a map so we can put in a lot of other stuff more easily
|
// make a map so we can put in a lot of other stuff more easily
|
||||||
taskMap := make(map[int64]*ListTask, len(tasks))
|
taskMap := make(map[int64]*Task, len(tasks))
|
||||||
err = x.Where("list_id = ?", listID).Find(&taskMap)
|
err = x.Where("list_id = ?", listID).Find(&taskMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -257,30 +257,30 @@ func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTaskByIDSimple returns a raw task without extra data by the task ID
|
// GetTaskByIDSimple returns a raw task without extra data by the task ID
|
||||||
func GetTaskByIDSimple(taskID int64) (task ListTask, err error) {
|
func GetTaskByIDSimple(taskID int64) (task Task, err error) {
|
||||||
if taskID < 1 {
|
if taskID < 1 {
|
||||||
return ListTask{}, ErrListTaskDoesNotExist{taskID}
|
return Task{}, ErrTaskDoesNotExist{taskID}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetTaskSimple(&ListTask{ID: taskID})
|
return GetTaskSimple(&Task{ID: taskID})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTaskSimple returns a raw task without extra data
|
// GetTaskSimple returns a raw task without extra data
|
||||||
func GetTaskSimple(t *ListTask) (task ListTask, err error) {
|
func GetTaskSimple(t *Task) (task Task, err error) {
|
||||||
task = *t
|
task = *t
|
||||||
exists, err := x.Get(&task)
|
exists, err := x.Get(&task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ListTask{}, err
|
return Task{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
return ListTask{}, ErrListTaskDoesNotExist{t.ID}
|
return Task{}, ErrTaskDoesNotExist{t.ID}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTaskByID returns all tasks a list has
|
// GetTaskByID returns all tasks a list has
|
||||||
func GetTaskByID(listTaskID int64) (listTask ListTask, err error) {
|
func GetTaskByID(listTaskID int64) (listTask Task, err error) {
|
||||||
listTask, err = GetTaskByIDSimple(listTaskID)
|
listTask, err = GetTaskByIDSimple(listTaskID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -321,11 +321,11 @@ func GetTaskByID(listTaskID int64) (listTask ListTask, err error) {
|
||||||
func (bt *BulkTask) GetTasksByIDs() (err error) {
|
func (bt *BulkTask) GetTasksByIDs() (err error) {
|
||||||
for _, id := range bt.IDs {
|
for _, id := range bt.IDs {
|
||||||
if id < 1 {
|
if id < 1 {
|
||||||
return ErrListTaskDoesNotExist{id}
|
return ErrTaskDoesNotExist{id}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
taskMap := make(map[int64]*ListTask, len(bt.Tasks))
|
taskMap := make(map[int64]*Task, len(bt.Tasks))
|
||||||
err = x.In("id", bt.IDs).Find(&taskMap)
|
err = x.In("id", bt.IDs).Find(&taskMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -336,8 +336,8 @@ func (bt *BulkTask) GetTasksByIDs() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTasksByUIDs gets all tasks from a bunch of uids
|
// GetTasksByUIDs gets all tasks from a bunch of uids
|
||||||
func GetTasksByUIDs(uids []string) (tasks []*ListTask, err error) {
|
func GetTasksByUIDs(uids []string) (tasks []*Task, err error) {
|
||||||
taskMap := make(map[int64]*ListTask)
|
taskMap := make(map[int64]*Task)
|
||||||
err = x.In("uid", uids).Find(&taskMap)
|
err = x.In("uid", uids).Find(&taskMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -349,7 +349,7 @@ func GetTasksByUIDs(uids []string) (tasks []*ListTask, err error) {
|
||||||
|
|
||||||
// This function takes a map with pointers and returns a slice with pointers to tasks
|
// This function takes a map with pointers and returns a slice with pointers to tasks
|
||||||
// It adds more stuff like assignees/labels/etc to a bunch of tasks
|
// It adds more stuff like assignees/labels/etc to a bunch of tasks
|
||||||
func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err error) {
|
func addMoreInfoToTasks(taskMap map[int64]*Task) (tasks []*Task, err error) {
|
||||||
|
|
||||||
// No need to iterate over users and stuff if the list doesn't has tasks
|
// No need to iterate over users and stuff if the list doesn't has tasks
|
||||||
if len(taskMap) == 0 {
|
if len(taskMap) == 0 {
|
||||||
|
@ -430,7 +430,7 @@ func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err err
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a complete slice from the map
|
// make a complete slice from the map
|
||||||
tasks = []*ListTask{}
|
tasks = []*Task{}
|
||||||
for _, t := range taskMap {
|
for _, t := range taskMap {
|
||||||
tasks = append(tasks, t)
|
tasks = append(tasks, t)
|
||||||
}
|
}
|
||||||
|
@ -453,19 +453,19 @@ func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err err
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security JWTKeyAuth
|
// @Security JWTKeyAuth
|
||||||
// @Param id path int true "List ID"
|
// @Param id path int true "List ID"
|
||||||
// @Param task body models.ListTask true "The task object"
|
// @Param task body models.Task true "The task object"
|
||||||
// @Success 200 {object} models.ListTask "The created task object."
|
// @Success 200 {object} models.Task "The created task object."
|
||||||
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
|
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
|
||||||
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
|
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /lists/{id} [put]
|
// @Router /lists/{id} [put]
|
||||||
func (t *ListTask) Create(a web.Auth) (err error) {
|
func (t *Task) Create(a web.Auth) (err error) {
|
||||||
|
|
||||||
t.ID = 0
|
t.ID = 0
|
||||||
|
|
||||||
// Check if we have at least a text
|
// Check if we have at least a text
|
||||||
if t.Text == "" {
|
if t.Text == "" {
|
||||||
return ErrListTaskCannotBeEmpty{}
|
return ErrTaskCannotBeEmpty{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the list exists
|
// Check if the list exists
|
||||||
|
@ -514,13 +514,13 @@ func (t *ListTask) Create(a web.Auth) (err error) {
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security JWTKeyAuth
|
// @Security JWTKeyAuth
|
||||||
// @Param id path int true "Task ID"
|
// @Param id path int true "Task ID"
|
||||||
// @Param task body models.ListTask true "The task object"
|
// @Param task body models.Task true "The task object"
|
||||||
// @Success 200 {object} models.ListTask "The updated task object."
|
// @Success 200 {object} models.Task "The updated task object."
|
||||||
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
|
// @Failure 400 {object} code.vikunja.io/web.HTTPError "Invalid task object provided."
|
||||||
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)"
|
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the task (aka its list)"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/{id} [post]
|
// @Router /tasks/{id} [post]
|
||||||
func (t *ListTask) Update() (err error) {
|
func (t *Task) Update() (err error) {
|
||||||
// Check if the task exists
|
// Check if the task exists
|
||||||
ot, err := GetTaskByID(t.ID)
|
ot, err := GetTaskByID(t.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -634,7 +634,7 @@ func (t *ListTask) Update() (err error) {
|
||||||
|
|
||||||
// This helper function updates the reminders and doneAtUnix of the *old* task (since that's the one we're inserting
|
// This helper function updates the reminders and doneAtUnix of the *old* task (since that's the one we're inserting
|
||||||
// with updated values into the db)
|
// with updated values into the db)
|
||||||
func updateDone(oldTask *ListTask, newTask *ListTask) {
|
func updateDone(oldTask *Task, newTask *Task) {
|
||||||
if !oldTask.Done && newTask.Done && oldTask.RepeatAfter > 0 {
|
if !oldTask.Done && newTask.Done && oldTask.RepeatAfter > 0 {
|
||||||
oldTask.DueDateUnix = oldTask.DueDateUnix + oldTask.RepeatAfter // assuming we'll save the old task (merged)
|
oldTask.DueDateUnix = oldTask.DueDateUnix + oldTask.RepeatAfter // assuming we'll save the old task (merged)
|
||||||
|
|
||||||
|
@ -657,7 +657,7 @@ func updateDone(oldTask *ListTask, newTask *ListTask) {
|
||||||
|
|
||||||
// Creates or deletes all necessary remindes without unneded db operations.
|
// Creates or deletes all necessary remindes without unneded db operations.
|
||||||
// The parameter is a slice with unix dates which holds the new reminders.
|
// The parameter is a slice with unix dates which holds the new reminders.
|
||||||
func (t *ListTask) updateReminders(reminders []int64) (err error) {
|
func (t *Task) updateReminders(reminders []int64) (err error) {
|
||||||
|
|
||||||
// If we're removing everything, delete all reminders right away
|
// If we're removing everything, delete all reminders right away
|
||||||
if len(reminders) == 0 && len(t.RemindersUnix) > 0 {
|
if len(reminders) == 0 && len(t.RemindersUnix) > 0 {
|
||||||
|
@ -701,7 +701,7 @@ func (t *ListTask) updateReminders(reminders []int64) (err error) {
|
||||||
if len(remindersToDelete) > 0 {
|
if len(remindersToDelete) > 0 {
|
||||||
_, err = x.In("reminder_unix", remindersToDelete).
|
_, err = x.In("reminder_unix", remindersToDelete).
|
||||||
And("task_id = ?", t.ID).
|
And("task_id = ?", t.ID).
|
||||||
Delete(ListTaskAssginee{})
|
Delete(TaskAssginee{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -743,7 +743,7 @@ func (t *ListTask) updateReminders(reminders []int64) (err error) {
|
||||||
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
|
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/{id} [delete]
|
// @Router /tasks/{id} [delete]
|
||||||
func (t *ListTask) Delete() (err error) {
|
func (t *Task) Delete() (err error) {
|
||||||
|
|
||||||
// Check if it exists
|
// Check if it exists
|
||||||
_, err = GetTaskByID(t.ID)
|
_, err = GetTaskByID(t.ID)
|
||||||
|
@ -751,12 +751,12 @@ func (t *ListTask) Delete() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = x.ID(t.ID).Delete(ListTask{}); err != nil {
|
if _, err = x.ID(t.ID).Delete(Task{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete assignees
|
// Delete assignees
|
||||||
if _, err = x.Where("task_id = ?", t.ID).Delete(ListTaskAssginee{}); err != nil {
|
if _, err = x.Where("task_id = ?", t.ID).Delete(TaskAssginee{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,25 +21,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CanDelete checks if the user can delete an task
|
// CanDelete checks if the user can delete an task
|
||||||
func (t *ListTask) CanDelete(a web.Auth) (bool, error) {
|
func (t *Task) CanDelete(a web.Auth) (bool, error) {
|
||||||
return t.canDoListTask(a)
|
return t.canDoTask(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanUpdate determines if a user has the right to update a list task
|
// CanUpdate determines if a user has the right to update a list task
|
||||||
func (t *ListTask) CanUpdate(a web.Auth) (bool, error) {
|
func (t *Task) CanUpdate(a web.Auth) (bool, error) {
|
||||||
return t.canDoListTask(a)
|
return t.canDoTask(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanCreate determines if a user has the right to create a list task
|
// CanCreate determines if a user has the right to create a list task
|
||||||
func (t *ListTask) CanCreate(a web.Auth) (bool, error) {
|
func (t *Task) CanCreate(a web.Auth) (bool, error) {
|
||||||
// A user can do a task if he has write acces to its list
|
// A user can do a task if he has write acces to its list
|
||||||
l := &List{ID: t.ListID}
|
l := &List{ID: t.ListID}
|
||||||
return l.CanWrite(a)
|
return l.CanWrite(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanRead determines if a user can read a task
|
// CanRead determines if a user can read a task
|
||||||
func (t *ListTask) CanRead(a web.Auth) (canRead bool, err error) {
|
func (t *Task) CanRead(a web.Auth) (canRead bool, err error) {
|
||||||
//return t.canDoListTask(a)
|
//return t.canDoTask(a)
|
||||||
// Get the task, error out if it doesn't exist
|
// Get the task, error out if it doesn't exist
|
||||||
*t, err = GetTaskByIDSimple(t.ID)
|
*t, err = GetTaskByIDSimple(t.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -52,7 +52,7 @@ func (t *ListTask) CanRead(a web.Auth) (canRead bool, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to check if a user can do stuff on a list task
|
// Helper function to check if a user can do stuff on a list task
|
||||||
func (t *ListTask) canDoListTask(a web.Auth) (bool, error) {
|
func (t *Task) canDoTask(a web.Auth) (bool, error) {
|
||||||
// Get the task
|
// Get the task
|
||||||
lI, err := GetTaskByIDSimple(t.ID)
|
lI, err := GetTaskByIDSimple(t.ID)
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -21,11 +21,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListTask_Create(t *testing.T) {
|
func TestTask_Create(t *testing.T) {
|
||||||
//assert.NoError(t, LoadFixtures())
|
//assert.NoError(t, LoadFixtures())
|
||||||
|
|
||||||
// Fake list task
|
// Fake list task
|
||||||
listtask := ListTask{
|
listtask := Task{
|
||||||
Text: "Lorem",
|
Text: "Lorem",
|
||||||
Description: "Lorem Ipsum BACKERY",
|
Description: "Lorem Ipsum BACKERY",
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -63,13 +63,13 @@ func TestListTask_Create(t *testing.T) {
|
||||||
listtask.ID = 0
|
listtask.ID = 0
|
||||||
err = listtask.Delete()
|
err = listtask.Delete()
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrListTaskDoesNotExist(err))
|
assert.True(t, IsErrTaskDoesNotExist(err))
|
||||||
|
|
||||||
// Try adding a list task with an empty text
|
// Try adding a list task with an empty text
|
||||||
listtask.Text = ""
|
listtask.Text = ""
|
||||||
err = listtask.Create(doer)
|
err = listtask.Create(doer)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrListTaskCannotBeEmpty(err))
|
assert.True(t, IsErrTaskCannotBeEmpty(err))
|
||||||
|
|
||||||
// Try adding one to a nonexistant list
|
// Try adding one to a nonexistant list
|
||||||
listtask.ListID = 99993939
|
listtask.ListID = 99993939
|
||||||
|
@ -82,7 +82,7 @@ func TestListTask_Create(t *testing.T) {
|
||||||
listtask.ID = 94829352
|
listtask.ID = 94829352
|
||||||
err = listtask.Update()
|
err = listtask.Update()
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, IsErrListTaskDoesNotExist(err))
|
assert.True(t, IsErrTaskDoesNotExist(err))
|
||||||
|
|
||||||
// Try inserting an task with a nonexistant user
|
// Try inserting an task with a nonexistant user
|
||||||
nUser := &User{ID: 9482385}
|
nUser := &User{ID: 9482385}
|
||||||
|
@ -94,14 +94,14 @@ func TestListTask_Create(t *testing.T) {
|
||||||
|
|
||||||
func TestUpdateDone(t *testing.T) {
|
func TestUpdateDone(t *testing.T) {
|
||||||
t.Run("marking a task as done", func(t *testing.T) {
|
t.Run("marking a task as done", func(t *testing.T) {
|
||||||
oldTask := &ListTask{Done: false}
|
oldTask := &Task{Done: false}
|
||||||
newTask := &ListTask{Done: true}
|
newTask := &Task{Done: true}
|
||||||
updateDone(oldTask, newTask)
|
updateDone(oldTask, newTask)
|
||||||
assert.NotEqual(t, int64(0), oldTask.DoneAtUnix)
|
assert.NotEqual(t, int64(0), oldTask.DoneAtUnix)
|
||||||
})
|
})
|
||||||
t.Run("unmarking a task as done", func(t *testing.T) {
|
t.Run("unmarking a task as done", func(t *testing.T) {
|
||||||
oldTask := &ListTask{Done: true}
|
oldTask := &Task{Done: true}
|
||||||
newTask := &ListTask{Done: false}
|
newTask := &Task{Done: false}
|
||||||
updateDone(oldTask, newTask)
|
updateDone(oldTask, newTask)
|
||||||
assert.Equal(t, int64(0), oldTask.DoneAtUnix)
|
assert.Equal(t, int64(0), oldTask.DoneAtUnix)
|
||||||
})
|
})
|
|
@ -100,7 +100,7 @@ func TaskHandler(c echo.Context) error {
|
||||||
|
|
||||||
storage := &VikunjaCaldavListStorage{
|
storage := &VikunjaCaldavListStorage{
|
||||||
list: &models.List{ID: listID},
|
list: &models.List{ID: listID},
|
||||||
task: &models.ListTask{UID: taskUID},
|
task: &models.Task{UID: taskUID},
|
||||||
user: &u,
|
user: &u,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ type VikunjaCaldavListStorage struct {
|
||||||
// Used when handling a list
|
// Used when handling a list
|
||||||
list *models.List
|
list *models.List
|
||||||
// Used when handling a single task, like updating
|
// Used when handling a single task, like updating
|
||||||
task *models.ListTask
|
task *models.Task
|
||||||
// The current user
|
// The current user
|
||||||
user *models.User
|
user *models.User
|
||||||
isPrincipal bool
|
isPrincipal bool
|
||||||
|
@ -176,7 +176,7 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByFilters(rpath string, filter
|
||||||
//return vcls.GetResources(rpath, false)
|
//return vcls.GetResources(rpath, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTaskURL(task *models.ListTask) string {
|
func getTaskURL(task *models.Task) string {
|
||||||
return ListBasePath + "/" + strconv.FormatInt(task.ListID, 10) + `/` + task.UID + `.ics`
|
return ListBasePath + "/" + strconv.FormatInt(task.ListID, 10) + `/` + task.UID + `.ics`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,9 +187,9 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource,
|
||||||
if vcls.task != nil {
|
if vcls.task != nil {
|
||||||
// save and override the updated unix date to not break any later etag checks
|
// save and override the updated unix date to not break any later etag checks
|
||||||
updated := vcls.task.Updated
|
updated := vcls.task.Updated
|
||||||
task, err := models.GetTaskSimple(&models.ListTask{ID: vcls.task.ID, UID: vcls.task.UID})
|
task, err := models.GetTaskSimple(&models.Task{ID: vcls.task.ID, UID: vcls.task.UID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrListTaskDoesNotExist(err) {
|
if models.IsErrTaskDoesNotExist(err) {
|
||||||
return nil, false, errs.ResourceNotFoundError
|
return nil, false, errs.ResourceNotFoundError
|
||||||
}
|
}
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
|
@ -316,7 +316,7 @@ func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error {
|
||||||
// VikunjaListResourceAdapter holds the actual resource
|
// VikunjaListResourceAdapter holds the actual resource
|
||||||
type VikunjaListResourceAdapter struct {
|
type VikunjaListResourceAdapter struct {
|
||||||
list *models.List
|
list *models.List
|
||||||
task *models.ListTask
|
task *models.Task
|
||||||
|
|
||||||
isPrincipal bool
|
isPrincipal bool
|
||||||
isCollection bool
|
isCollection bool
|
||||||
|
@ -356,7 +356,7 @@ func (vlra *VikunjaListResourceAdapter) GetContent() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if vlra.task != nil {
|
if vlra.task != nil {
|
||||||
list := models.List{Tasks: []*models.ListTask{vlra.task}}
|
list := models.List{Tasks: []*models.Task{vlra.task}}
|
||||||
return getCaldavTodosForTasks(&list)
|
return getCaldavTodosForTasks(&list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ func getCaldavTodosForTasks(list *models.List) string {
|
||||||
return caldav.ParseTodos(caldavConfig, caldavtodos)
|
return caldav.ParseTodos(caldavConfig, caldavtodos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTaskFromVTODO(content string) (vTask *models.ListTask, err error) {
|
func parseTaskFromVTODO(content string) (vTask *models.Task, err error) {
|
||||||
parsed, err := ical.ParseCalendar(content)
|
parsed, err := ical.ParseCalendar(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -89,7 +89,7 @@ func parseTaskFromVTODO(content string) (vTask *models.ListTask, err error) {
|
||||||
// Parse the enddate
|
// Parse the enddate
|
||||||
duration, _ := time.ParseDuration(task["DURATION"])
|
duration, _ := time.ParseDuration(task["DURATION"])
|
||||||
|
|
||||||
vTask = &models.ListTask{
|
vTask = &models.Task{
|
||||||
UID: task["UID"],
|
UID: task["UID"],
|
||||||
Text: task["SUMMARY"],
|
Text: task["SUMMARY"],
|
||||||
Description: task["DESCRIPTION"],
|
Description: task["DESCRIPTION"],
|
||||||
|
|
|
@ -55,7 +55,7 @@ func setupMetrics(a *echo.Group) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
metrics.TaskCountKey,
|
metrics.TaskCountKey,
|
||||||
models.ListTask{},
|
models.Task{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
metrics.TeamCountKey,
|
metrics.TeamCountKey,
|
||||||
|
|
|
@ -196,7 +196,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||||
|
|
||||||
taskHandler := &handler.WebHandler{
|
taskHandler := &handler.WebHandler{
|
||||||
EmptyStruct: func() handler.CObject {
|
EmptyStruct: func() handler.CObject {
|
||||||
return &models.ListTask{}
|
return &models.Task{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
a.PUT("/lists/:list", taskHandler.CreateWeb)
|
a.PUT("/lists/:list", taskHandler.CreateWeb)
|
||||||
|
@ -213,7 +213,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||||
|
|
||||||
assigneeTaskHandler := &handler.WebHandler{
|
assigneeTaskHandler := &handler.WebHandler{
|
||||||
EmptyStruct: func() handler.CObject {
|
EmptyStruct: func() handler.CObject {
|
||||||
return &models.ListTaskAssginee{}
|
return &models.TaskAssginee{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
a.PUT("/tasks/:listtask/assignees", assigneeTaskHandler.CreateWeb)
|
a.PUT("/tasks/:listtask/assignees", assigneeTaskHandler.CreateWeb)
|
||||||
|
|
|
@ -488,7 +488,7 @@ var doc = `{
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -497,7 +497,7 @@ var doc = `{
|
||||||
"description": "The created task object.",
|
"description": "The created task object.",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -2393,7 +2393,7 @@ var doc = `{
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2442,7 +2442,7 @@ var doc = `{
|
||||||
"description": "The updated task object.",
|
"description": "The updated task object.",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -2502,7 +2502,7 @@ var doc = `{
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -2511,7 +2511,7 @@ var doc = `{
|
||||||
"description": "The updated task object.",
|
"description": "The updated task object.",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -2618,7 +2618,7 @@ var doc = `{
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTaskAssginee"
|
"$ref": "#/definitions/models.TaskAssginee"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2634,7 +2634,7 @@ var doc = `{
|
||||||
"description": "The created assingee object.",
|
"description": "The created assingee object.",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTaskAssginee"
|
"$ref": "#/definitions/models.TaskAssginee"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -2696,7 +2696,7 @@ var doc = `{
|
||||||
"description": "The created assingees object.",
|
"description": "The created assingees object.",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.ListTaskAssginee"
|
"$ref": "#/definitions/models.TaskAssginee"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
|
@ -3803,7 +3803,7 @@ var doc = `{
|
||||||
"description": "An array of subtasks.",
|
"description": "An array of subtasks.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"task_ids": {
|
"task_ids": {
|
||||||
|
@ -3920,7 +3920,7 @@ var doc = `{
|
||||||
"description": "An array of tasks which belong to the list.",
|
"description": "An array of tasks which belong to the list.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"title": {
|
"title": {
|
||||||
|
@ -3935,7 +3935,7 @@ var doc = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"models.ListTask": {
|
"models.Task": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"assignees": {
|
"assignees": {
|
||||||
|
@ -4021,7 +4021,7 @@ var doc = `{
|
||||||
"description": "An array of subtasks.",
|
"description": "An array of subtasks.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/models.ListTask"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"text": {
|
"text": {
|
||||||
|
@ -4036,7 +4036,7 @@ var doc = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"models.ListTaskAssginee": {
|
"models.TaskAssginee": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"created": {
|
"created": {
|
||||||
|
|
Loading…
Reference in a new issue