Reorder tasks, lists and kanban buckets (#923)
Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/api/pulls/923 Co-authored-by: konrad <konrad@kola-entertainments.de> Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
parent
dac315db59
commit
6ccb85a0dc
22 changed files with 475 additions and 96 deletions
|
@ -3,6 +3,7 @@
|
|||
list_id: 1
|
||||
created_by_id: 1
|
||||
limit: 9999999 # This bucket has a limit we will never exceed in the tests to make sure the logic allows for buckets with limits
|
||||
position: 2
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
- id: 2
|
||||
|
@ -10,6 +11,7 @@
|
|||
list_id: 1
|
||||
created_by_id: 1
|
||||
limit: 3
|
||||
position: 1
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
- id: 3
|
||||
|
@ -17,6 +19,7 @@
|
|||
list_id: 1
|
||||
created_by_id: 1
|
||||
is_done_bucket: 1
|
||||
position: 3
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
- id: 4
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
identifier: test1
|
||||
owner_id: 1
|
||||
namespace_id: 1
|
||||
position: 3
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -14,6 +15,7 @@
|
|||
identifier: test2
|
||||
owner_id: 3
|
||||
namespace_id: 1
|
||||
position: 2
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -23,6 +25,7 @@
|
|||
identifier: test3
|
||||
owner_id: 3
|
||||
namespace_id: 2
|
||||
position: 1
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -32,6 +35,7 @@
|
|||
identifier: test4
|
||||
owner_id: 3
|
||||
namespace_id: 3
|
||||
position: 4
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -41,6 +45,7 @@
|
|||
identifier: test5
|
||||
owner_id: 5
|
||||
namespace_id: 5
|
||||
position: 5
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -50,6 +55,7 @@
|
|||
identifier: test6
|
||||
owner_id: 6
|
||||
namespace_id: 6
|
||||
position: 6
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -59,6 +65,7 @@
|
|||
identifier: test7
|
||||
owner_id: 6
|
||||
namespace_id: 6
|
||||
position: 7
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -68,6 +75,7 @@
|
|||
identifier: test8
|
||||
owner_id: 6
|
||||
namespace_id: 6
|
||||
position: 8
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -77,6 +85,7 @@
|
|||
identifier: test9
|
||||
owner_id: 6
|
||||
namespace_id: 6
|
||||
position: 9
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -86,6 +95,7 @@
|
|||
identifier: test10
|
||||
owner_id: 6
|
||||
namespace_id: 6
|
||||
position: 10
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -95,6 +105,7 @@
|
|||
identifier: test11
|
||||
owner_id: 6
|
||||
namespace_id: 6
|
||||
position: 11
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -104,6 +115,7 @@
|
|||
identifier: test12
|
||||
owner_id: 6
|
||||
namespace_id: 7
|
||||
position: 12
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -113,6 +125,7 @@
|
|||
identifier: test13
|
||||
owner_id: 6
|
||||
namespace_id: 8
|
||||
position: 13
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -122,6 +135,7 @@
|
|||
identifier: test14
|
||||
owner_id: 6
|
||||
namespace_id: 9
|
||||
position: 14
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -131,6 +145,7 @@
|
|||
identifier: test15
|
||||
owner_id: 6
|
||||
namespace_id: 10
|
||||
position: 15
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -140,6 +155,7 @@
|
|||
identifier: test16
|
||||
owner_id: 6
|
||||
namespace_id: 11
|
||||
position: 16
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -149,6 +165,7 @@
|
|||
identifier: test17
|
||||
owner_id: 6
|
||||
namespace_id: 12
|
||||
position: 17
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
# This list is owned by user 7, and several other users have access to it via different methods.
|
||||
|
@ -160,6 +177,7 @@
|
|||
identifier: test18
|
||||
owner_id: 7
|
||||
namespace_id: 13
|
||||
position: 18
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -169,6 +187,7 @@
|
|||
identifier: test19
|
||||
owner_id: 7
|
||||
namespace_id: 14
|
||||
position: 19
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
# User 1 does not have access to this list
|
||||
|
@ -179,6 +198,7 @@
|
|||
identifier: test20
|
||||
owner_id: 13
|
||||
namespace_id: 15
|
||||
position: 20
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -188,6 +208,7 @@
|
|||
identifier: test21
|
||||
owner_id: 1
|
||||
namespace_id: 16
|
||||
position: 21
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -198,6 +219,7 @@
|
|||
owner_id: 1
|
||||
namespace_id: 1
|
||||
is_archived: 1
|
||||
position: 22
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -207,5 +229,6 @@
|
|||
identifier: test23
|
||||
owner_id: 12
|
||||
namespace_id: 17
|
||||
position: 23
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
created: 2018-12-01 01:12:04
|
||||
updated: 2018-12-01 01:12:04
|
||||
bucket_id: 1
|
||||
position: 2
|
||||
- id: 2
|
||||
title: 'task #2 done'
|
||||
done: true
|
||||
|
@ -17,6 +18,7 @@
|
|||
created: 2018-12-01 01:12:04
|
||||
updated: 2018-12-01 01:12:04
|
||||
bucket_id: 1
|
||||
position: 4
|
||||
- id: 3
|
||||
title: 'task #3 high prio'
|
||||
done: false
|
||||
|
|
|
@ -113,49 +113,49 @@ func TestTaskCollection(t *testing.T) {
|
|||
t.Run("by priority", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by priority desc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1`)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1`)
|
||||
})
|
||||
t.Run("by priority asc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
// should equal duedate asc
|
||||
t.Run("by due_date", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by duedate desc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
|
||||
})
|
||||
// Due date without unix suffix
|
||||
t.Run("by duedate asc without suffix", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by due_date without suffix", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by duedate desc without suffix", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
|
||||
})
|
||||
t.Run("by duedate asc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, urlParams)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("invalid sort parameter", func(t *testing.T) {
|
||||
_, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"loremipsum"}}, urlParams)
|
||||
|
@ -341,33 +341,33 @@ func TestTaskCollection(t *testing.T) {
|
|||
t.Run("by priority", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by priority desc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1`)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1`)
|
||||
})
|
||||
t.Run("by priority asc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
// should equal duedate asc
|
||||
t.Run("by due_date", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("by duedate desc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
|
||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
|
||||
})
|
||||
t.Run("by duedate asc", func(t *testing.T) {
|
||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"kanban_position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
|
||||
})
|
||||
t.Run("invalid parameter", func(t *testing.T) {
|
||||
// Invalid parameter should not sort at all
|
||||
|
|
71
pkg/migration/20210725153703.go
Normal file
71
pkg/migration/20210725153703.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public Licensee as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public Licensee for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type tasks20210725153703 struct {
|
||||
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"listtask"`
|
||||
Position float64 `xorm:"double null" json:"position"`
|
||||
KanbanPosition float64 `xorm:"double null" json:"kanban_position"`
|
||||
}
|
||||
|
||||
func (tasks20210725153703) TableName() string {
|
||||
return "tasks"
|
||||
}
|
||||
|
||||
func init() {
|
||||
migrations = append(migrations, &xormigrate.Migration{
|
||||
ID: "20210725153703",
|
||||
Description: "",
|
||||
Migrate: func(tx *xorm.Engine) error {
|
||||
err := tx.Sync2(tasks20210725153703{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tasks := []*tasks20210725153703{}
|
||||
err = tx.Where("position is not null").Find(&tasks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Migrate all old kanban positions to the kanban positions property
|
||||
for _, task := range tasks {
|
||||
task.KanbanPosition = task.Position
|
||||
task.Position = float64(task.ID) * math.Pow(2, 16)
|
||||
_, err = tx.
|
||||
Where("id = ?", task.ID).
|
||||
Cols("kanban_position", "position").
|
||||
Update(task)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *xorm.Engine) error {
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
68
pkg/migration/20210727204942.go
Normal file
68
pkg/migration/20210727204942.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public Licensee as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public Licensee for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type lists20210727204942 struct {
|
||||
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"list"`
|
||||
Position float64 `xorm:"double null" json:"position"`
|
||||
}
|
||||
|
||||
func (lists20210727204942) TableName() string {
|
||||
return "lists"
|
||||
}
|
||||
|
||||
func init() {
|
||||
migrations = append(migrations, &xormigrate.Migration{
|
||||
ID: "20210727204942",
|
||||
Description: "Add list position parameter",
|
||||
Migrate: func(tx *xorm.Engine) error {
|
||||
err := tx.Sync2(lists20210727204942{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lists := []*lists20210727204942{}
|
||||
err = tx.Find(&lists)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, list := range lists {
|
||||
list.Position = float64(list.ID) * math.Pow(2, 16)
|
||||
|
||||
_, err = tx.
|
||||
Where("id = ?", list.ID).
|
||||
Update(list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *xorm.Engine) error {
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
68
pkg/migration/20210727211037.go
Normal file
68
pkg/migration/20210727211037.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public Licensee as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public Licensee for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type buckets20210727211037 struct {
|
||||
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"list"`
|
||||
Position float64 `xorm:"double null" json:"position"`
|
||||
}
|
||||
|
||||
func (buckets20210727211037) TableName() string {
|
||||
return "buckets"
|
||||
}
|
||||
|
||||
func init() {
|
||||
migrations = append(migrations, &xormigrate.Migration{
|
||||
ID: "20210727211037",
|
||||
Description: "Add bucket position property",
|
||||
Migrate: func(tx *xorm.Engine) error {
|
||||
err := tx.Sync2(buckets20210727211037{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buckets := []*buckets20210727211037{}
|
||||
err = tx.Find(&buckets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, bucket := range buckets {
|
||||
bucket.Position = float64(bucket.ID) * math.Pow(2, 16)
|
||||
|
||||
_, err = tx.
|
||||
Where("id = ?", bucket.ID).
|
||||
Update(bucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *xorm.Engine) error {
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
|
@ -41,6 +41,9 @@ type Bucket struct {
|
|||
// If this bucket is the "done bucket". All tasks moved into this bucket will automatically marked as done. All tasks marked as done from elsewhere will be moved into this bucket.
|
||||
IsDoneBucket bool `xorm:"BOOL" json:"is_done_bucket"`
|
||||
|
||||
// The position this bucket has when querying all buckets. See the tasks.position property on how to use this.
|
||||
Position float64 `xorm:"double null" json:"position"`
|
||||
|
||||
// A timestamp when this bucket was created. You cannot change this value.
|
||||
Created time.Time `xorm:"created not null" json:"created"`
|
||||
// A timestamp when this bucket was last updated. You cannot change this value.
|
||||
|
@ -134,7 +137,10 @@ func (b *Bucket) ReadAll(s *xorm.Session, auth web.Auth, search string, page int
|
|||
|
||||
// Get all buckets for this list
|
||||
buckets := []*Bucket{}
|
||||
err = s.Where("list_id = ?", b.ListID).Find(&buckets)
|
||||
err = s.
|
||||
Where("list_id = ?", b.ListID).
|
||||
OrderBy("position").
|
||||
Find(&buckets)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -167,7 +173,7 @@ func (b *Bucket) ReadAll(s *xorm.Session, auth web.Auth, search string, page int
|
|||
opts.sortby = []*sortParam{
|
||||
{
|
||||
orderBy: orderAscending,
|
||||
sortBy: taskPropertyPosition,
|
||||
sortBy: taskPropertyKanbanPosition,
|
||||
},
|
||||
}
|
||||
opts.page = page
|
||||
|
@ -251,6 +257,12 @@ func (b *Bucket) Create(s *xorm.Session, a web.Auth) (err error) {
|
|||
b.CreatedByID = b.CreatedBy.ID
|
||||
|
||||
_, err = s.Insert(b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
b.Position = calculateDefaultPosition(b.ID, b.Position)
|
||||
_, err = s.Where("id = ?", b.ID).Update(b)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -289,6 +301,7 @@ func (b *Bucket) Update(s *xorm.Session, a web.Auth) (err error) {
|
|||
"title",
|
||||
"limit",
|
||||
"is_done_bucket",
|
||||
"position",
|
||||
).
|
||||
Update(b)
|
||||
return
|
||||
|
|
|
@ -49,21 +49,23 @@ func TestBucket_ReadAll(t *testing.T) {
|
|||
assert.Len(t, buckets, 3)
|
||||
|
||||
// Assert all tasks are in the right bucket
|
||||
assert.Len(t, buckets[0].Tasks, 12)
|
||||
assert.Len(t, buckets[1].Tasks, 3)
|
||||
assert.Len(t, buckets[0].Tasks, 3)
|
||||
assert.Len(t, buckets[1].Tasks, 12)
|
||||
assert.Len(t, buckets[2].Tasks, 3)
|
||||
|
||||
// Assert we have bucket 0, 1, 2, 3 but not 4 (that belongs to a different list)
|
||||
assert.Equal(t, int64(1), buckets[0].ID)
|
||||
assert.Equal(t, int64(2), buckets[1].ID)
|
||||
// Assert we have bucket 1, 2, 3 but not 4 (that belongs to a different list) and their position
|
||||
assert.Equal(t, int64(2), buckets[0].ID)
|
||||
assert.Equal(t, int64(1), buckets[1].ID)
|
||||
assert.Equal(t, int64(3), buckets[2].ID)
|
||||
|
||||
// Kinda assert all tasks are in the right buckets
|
||||
assert.Equal(t, int64(1), buckets[0].Tasks[0].BucketID)
|
||||
assert.Equal(t, int64(1), buckets[0].Tasks[1].BucketID)
|
||||
assert.Equal(t, int64(2), buckets[1].Tasks[0].BucketID)
|
||||
assert.Equal(t, int64(2), buckets[1].Tasks[1].BucketID)
|
||||
assert.Equal(t, int64(2), buckets[1].Tasks[2].BucketID)
|
||||
assert.Equal(t, int64(1), buckets[1].Tasks[0].BucketID)
|
||||
assert.Equal(t, int64(1), buckets[1].Tasks[1].BucketID)
|
||||
|
||||
assert.Equal(t, int64(2), buckets[0].Tasks[0].BucketID)
|
||||
assert.Equal(t, int64(2), buckets[0].Tasks[1].BucketID)
|
||||
assert.Equal(t, int64(2), buckets[0].Tasks[2].BucketID)
|
||||
|
||||
assert.Equal(t, int64(3), buckets[2].Tasks[0].BucketID)
|
||||
assert.Equal(t, int64(3), buckets[2].Tasks[1].BucketID)
|
||||
assert.Equal(t, int64(3), buckets[2].Tasks[2].BucketID)
|
||||
|
@ -87,7 +89,8 @@ func TestBucket_ReadAll(t *testing.T) {
|
|||
|
||||
buckets := bucketsInterface.([]*Bucket)
|
||||
assert.Len(t, buckets, 3)
|
||||
assert.Equal(t, int64(2), buckets[0].Tasks[0].ID)
|
||||
assert.Equal(t, int64(2), buckets[1].Tasks[0].ID)
|
||||
assert.Equal(t, int64(33), buckets[1].Tasks[1].ID)
|
||||
})
|
||||
t.Run("accessed by link share", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
|
|
@ -71,6 +71,9 @@ type List struct {
|
|||
// Will only returned when retreiving one list.
|
||||
Subscription *Subscription `xorm:"-" json:"subscription,omitempty"`
|
||||
|
||||
// The position this list has when querying all lists. See the tasks.position property on how to use this.
|
||||
Position float64 `xorm:"double null" json:"position"`
|
||||
|
||||
// A timestamp when this list was created. You cannot change this value.
|
||||
Created time.Time `xorm:"created not null" json:"created"`
|
||||
// A timestamp when this list was last updated. You cannot change this value.
|
||||
|
@ -284,7 +287,10 @@ func GetListSimpleByID(s *xorm.Session, listID int64) (list *List, err error) {
|
|||
return nil, ErrListDoesNotExist{ID: listID}
|
||||
}
|
||||
|
||||
exists, err := s.Where("id = ?", listID).Get(list)
|
||||
exists, err := s.
|
||||
Where("id = ?", listID).
|
||||
OrderBy("position").
|
||||
Get(list)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -361,6 +367,7 @@ func getUserListsStatement(userID int64) *builder.Builder {
|
|||
builder.Eq{"un.user_id": userID},
|
||||
builder.Eq{"l.owner_id": userID},
|
||||
)).
|
||||
OrderBy("position").
|
||||
GroupBy("l.id")
|
||||
}
|
||||
|
||||
|
@ -559,6 +566,12 @@ func CreateOrUpdateList(s *xorm.Session, list *List, auth web.Auth) (err error)
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
list.Position = calculateDefaultPosition(list.ID, list.Position)
|
||||
_, err = s.Where("id = ?", list.ID).Update(list)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if list.IsFavorite {
|
||||
if err := addToFavorites(s, list.ID, auth, FavoriteKindList); err != nil {
|
||||
return err
|
||||
|
@ -572,6 +585,7 @@ func CreateOrUpdateList(s *xorm.Session, list *List, auth web.Auth) (err error)
|
|||
"identifier",
|
||||
"hex_color",
|
||||
"background_file_id",
|
||||
"position",
|
||||
}
|
||||
if list.Description != "" {
|
||||
colsToUpdate = append(colsToUpdate, "description")
|
||||
|
|
|
@ -200,8 +200,11 @@ func TestList_ReadAll(t *testing.T) {
|
|||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, reflect.TypeOf(lists3).Kind(), reflect.Slice)
|
||||
ls := reflect.ValueOf(lists3)
|
||||
assert.Equal(t, 16, ls.Len())
|
||||
ls := lists3.([]*List)
|
||||
assert.Equal(t, 16, len(ls))
|
||||
assert.Equal(t, int64(3), ls[0].ID) // List 3 has a position of 1 and should be sorted first
|
||||
assert.Equal(t, int64(1), ls[1].ID)
|
||||
assert.Equal(t, int64(4), ls[2].ID)
|
||||
_ = s.Close()
|
||||
})
|
||||
t.Run("lists for nonexistant user", func(t *testing.T) {
|
||||
|
|
|
@ -315,6 +315,7 @@ func getNamespaceSubscriptions(s *xorm.Session, namespaceIDs []int64, userID int
|
|||
func getListsForNamespaces(s *xorm.Session, namespaceIDs []int64, archived bool) ([]*List, error) {
|
||||
lists := []*List{}
|
||||
listQuery := s.
|
||||
OrderBy("position").
|
||||
In("namespace_id", namespaceIDs)
|
||||
|
||||
if !archived {
|
||||
|
|
|
@ -73,11 +73,11 @@ func validateTaskField(fieldName string) error {
|
|||
taskPropertyCreated,
|
||||
taskPropertyUpdated,
|
||||
taskPropertyPosition,
|
||||
taskPropertyKanbanPosition,
|
||||
taskPropertyBucketID:
|
||||
return nil
|
||||
}
|
||||
return ErrInvalidTaskField{TaskField: fieldName}
|
||||
|
||||
}
|
||||
|
||||
func getTaskFilterOptsFromCollection(tf *TaskCollection) (opts *taskOptions, err error) {
|
||||
|
|
|
@ -26,25 +26,26 @@ type (
|
|||
)
|
||||
|
||||
const (
|
||||
taskPropertyID string = "id"
|
||||
taskPropertyTitle string = "title"
|
||||
taskPropertyDescription string = "description"
|
||||
taskPropertyDone string = "done"
|
||||
taskPropertyDoneAt string = "done_at"
|
||||
taskPropertyDueDate string = "due_date"
|
||||
taskPropertyCreatedByID string = "created_by_id"
|
||||
taskPropertyListID string = "list_id"
|
||||
taskPropertyRepeatAfter string = "repeat_after"
|
||||
taskPropertyPriority string = "priority"
|
||||
taskPropertyStartDate string = "start_date"
|
||||
taskPropertyEndDate string = "end_date"
|
||||
taskPropertyHexColor string = "hex_color"
|
||||
taskPropertyPercentDone string = "percent_done"
|
||||
taskPropertyUID string = "uid"
|
||||
taskPropertyCreated string = "created"
|
||||
taskPropertyUpdated string = "updated"
|
||||
taskPropertyPosition string = "position"
|
||||
taskPropertyBucketID string = "bucket_id"
|
||||
taskPropertyID string = "id"
|
||||
taskPropertyTitle string = "title"
|
||||
taskPropertyDescription string = "description"
|
||||
taskPropertyDone string = "done"
|
||||
taskPropertyDoneAt string = "done_at"
|
||||
taskPropertyDueDate string = "due_date"
|
||||
taskPropertyCreatedByID string = "created_by_id"
|
||||
taskPropertyListID string = "list_id"
|
||||
taskPropertyRepeatAfter string = "repeat_after"
|
||||
taskPropertyPriority string = "priority"
|
||||
taskPropertyStartDate string = "start_date"
|
||||
taskPropertyEndDate string = "end_date"
|
||||
taskPropertyHexColor string = "hex_color"
|
||||
taskPropertyPercentDone string = "percent_done"
|
||||
taskPropertyUID string = "uid"
|
||||
taskPropertyCreated string = "created"
|
||||
taskPropertyUpdated string = "updated"
|
||||
taskPropertyPosition string = "position"
|
||||
taskPropertyKanbanPosition string = "kanban_position"
|
||||
taskPropertyBucketID string = "bucket_id"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -90,6 +90,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
ListID: 1,
|
||||
BucketID: 1,
|
||||
IsFavorite: true,
|
||||
Position: 2,
|
||||
Labels: []*Label{
|
||||
label4,
|
||||
},
|
||||
|
@ -160,6 +161,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
CreatedBy: user1,
|
||||
ListID: 1,
|
||||
BucketID: 1,
|
||||
Position: 4,
|
||||
Labels: []*Label{
|
||||
label4,
|
||||
},
|
||||
|
@ -517,6 +519,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
Created: time.Unix(1543626724, 0).In(loc),
|
||||
Updated: time.Unix(1543626724, 0).In(loc),
|
||||
BucketID: 1,
|
||||
Position: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1033,6 +1036,51 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "order by position",
|
||||
fields: fields{
|
||||
SortBy: []string{"position", "id"},
|
||||
OrderBy: []string{"asc", "asc"},
|
||||
},
|
||||
args: args{
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
want: []*Task{
|
||||
// the other ones don't have a position set
|
||||
task3,
|
||||
task4,
|
||||
task5,
|
||||
task6,
|
||||
task7,
|
||||
task8,
|
||||
task9,
|
||||
task10,
|
||||
task11,
|
||||
task12,
|
||||
task15,
|
||||
task16,
|
||||
task17,
|
||||
task18,
|
||||
task19,
|
||||
task20,
|
||||
task21,
|
||||
task22,
|
||||
task23,
|
||||
task24,
|
||||
task25,
|
||||
task26,
|
||||
task27,
|
||||
task28,
|
||||
task29,
|
||||
task30,
|
||||
task31,
|
||||
task32,
|
||||
task33,
|
||||
// The only tasks with a position set
|
||||
task1,
|
||||
task2,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -118,6 +118,8 @@ type Task struct {
|
|||
// A 64-Bit float leaves plenty of room to initially give tasks a position with 2^16 difference to the previous task
|
||||
// which also leaves a lot of room for rearranging and sorting later.
|
||||
Position float64 `xorm:"double null" json:"position"`
|
||||
// The position of tasks in the kanban board. See the docs for the `position` property on how to use this.
|
||||
KanbanPosition float64 `xorm:"double null" json:"kanban_position"`
|
||||
|
||||
// The user who initially created the task.
|
||||
CreatedBy *user.User `xorm:"-" json:"created_by" valid:"-"`
|
||||
|
@ -836,6 +838,14 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucke
|
|||
return nil
|
||||
}
|
||||
|
||||
func calculateDefaultPosition(entityID int64, position float64) float64 {
|
||||
if position == 0 {
|
||||
return float64(entityID) * math.Pow(2, 16)
|
||||
}
|
||||
|
||||
return position
|
||||
}
|
||||
|
||||
// Create is the implementation to create a list task
|
||||
// @Summary Create a task
|
||||
// @Description Inserts a task into a list.
|
||||
|
@ -895,9 +905,8 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
|
|||
|
||||
t.Index = latestTask.Index + 1
|
||||
// If no position was supplied, set a default one
|
||||
if t.Position == 0 {
|
||||
t.Position = float64(latestTask.ID+1) * math.Pow(2, 16)
|
||||
}
|
||||
t.Position = calculateDefaultPosition(latestTask.ID+1, t.Position)
|
||||
t.KanbanPosition = calculateDefaultPosition(latestTask.ID+1, t.KanbanPosition)
|
||||
if _, err = s.Insert(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1001,6 +1010,7 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
|
|||
"bucket_id",
|
||||
"position",
|
||||
"repeat_mode",
|
||||
"kanban_position",
|
||||
}
|
||||
|
||||
// When a repeating task is marked as done, we update all deadlines and reminders and set it as undone
|
||||
|
@ -1107,6 +1117,9 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
|
|||
if t.Position == 0 {
|
||||
ot.Position = 0
|
||||
}
|
||||
if t.KanbanPosition == 0 {
|
||||
ot.KanbanPosition = 0
|
||||
}
|
||||
// Repeat from current date
|
||||
if t.RepeatMode == TaskRepeatModeDefault {
|
||||
ot.RepeatMode = TaskRepeatModeDefault
|
||||
|
|
|
@ -192,12 +192,12 @@ func TestTask_Update(t *testing.T) {
|
|||
defer s.Close()
|
||||
|
||||
task := &Task{
|
||||
ID: 4,
|
||||
Title: "test10000",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
Position: 10,
|
||||
ListID: 1,
|
||||
BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3
|
||||
ID: 4,
|
||||
Title: "test10000",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
KanbanPosition: 10,
|
||||
ListID: 1,
|
||||
BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3
|
||||
}
|
||||
err := task.Update(s, u)
|
||||
assert.NoError(t, err)
|
||||
|
|
|
@ -196,10 +196,10 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board) (fullVikunjaHierachi
|
|||
|
||||
// The usual stuff: Title, description, position, bucket id
|
||||
task := &models.Task{
|
||||
Title: card.Name,
|
||||
Description: card.Desc,
|
||||
Position: card.Pos,
|
||||
BucketID: bucketID,
|
||||
Title: card.Name,
|
||||
Description: card.Desc,
|
||||
KanbanPosition: card.Pos,
|
||||
BucketID: bucketID,
|
||||
}
|
||||
|
||||
if card.Due != nil {
|
||||
|
|
|
@ -209,11 +209,11 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
Tasks: []*models.Task{
|
||||
{
|
||||
Title: "Test Card 1",
|
||||
Description: "Card Description",
|
||||
BucketID: 1,
|
||||
Position: 123,
|
||||
DueDate: time1,
|
||||
Title: "Test Card 1",
|
||||
Description: "Card Description",
|
||||
BucketID: 1,
|
||||
KanbanPosition: 123,
|
||||
DueDate: time1,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 1",
|
||||
|
@ -248,18 +248,18 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
|
||||
* [ ] Pending Task
|
||||
* [ ] Another Pending Task`,
|
||||
BucketID: 1,
|
||||
Position: 124,
|
||||
BucketID: 1,
|
||||
KanbanPosition: 124,
|
||||
},
|
||||
{
|
||||
Title: "Test Card 3",
|
||||
BucketID: 1,
|
||||
Position: 126,
|
||||
Title: "Test Card 3",
|
||||
BucketID: 1,
|
||||
KanbanPosition: 126,
|
||||
},
|
||||
{
|
||||
Title: "Test Card 4",
|
||||
BucketID: 1,
|
||||
Position: 127,
|
||||
Title: "Test Card 4",
|
||||
BucketID: 1,
|
||||
KanbanPosition: 127,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 2",
|
||||
|
@ -268,9 +268,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
Title: "Test Card 5",
|
||||
BucketID: 2,
|
||||
Position: 111,
|
||||
Title: "Test Card 5",
|
||||
BucketID: 2,
|
||||
KanbanPosition: 111,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 3",
|
||||
|
@ -279,20 +279,20 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
Title: "Test Card 6",
|
||||
BucketID: 2,
|
||||
Position: 222,
|
||||
DueDate: time1,
|
||||
Title: "Test Card 6",
|
||||
BucketID: 2,
|
||||
KanbanPosition: 222,
|
||||
DueDate: time1,
|
||||
},
|
||||
{
|
||||
Title: "Test Card 7",
|
||||
BucketID: 2,
|
||||
Position: 333,
|
||||
Title: "Test Card 7",
|
||||
BucketID: 2,
|
||||
KanbanPosition: 333,
|
||||
},
|
||||
{
|
||||
Title: "Test Card 8",
|
||||
BucketID: 2,
|
||||
Position: 444,
|
||||
Title: "Test Card 8",
|
||||
BucketID: 2,
|
||||
KanbanPosition: 444,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -306,9 +306,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
Tasks: []*models.Task{
|
||||
{
|
||||
Title: "Test Card 634",
|
||||
BucketID: 3,
|
||||
Position: 123,
|
||||
Title: "Test Card 634",
|
||||
BucketID: 3,
|
||||
KanbanPosition: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -323,9 +323,9 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
Tasks: []*models.Task{
|
||||
{
|
||||
Title: "Test Card 63423",
|
||||
BucketID: 4,
|
||||
Position: 123,
|
||||
Title: "Test Card 63423",
|
||||
BucketID: 4,
|
||||
KanbanPosition: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -7218,6 +7218,10 @@ var doc = `{
|
|||
"type": "string"
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"description": "The position this bucket has when querying all buckets. See the tasks.position property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"sort_by": {
|
||||
"description": "The query parameter to sort by. This is for ex. done, priority, etc.",
|
||||
"type": "array",
|
||||
|
@ -7325,6 +7329,10 @@ var doc = `{
|
|||
"description": "True if a task is a favorite task. Favorite tasks show up in a separate \"Important\" list. This value depends on the user making the call to the api.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"kanban_position": {
|
||||
"description": "The position of tasks in the kanban board. See the docs for the ` + "`" + `position` + "`" + ` property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"labels": {
|
||||
"description": "An array of labels which are associated with this task.",
|
||||
"type": "array",
|
||||
|
@ -7573,6 +7581,10 @@ var doc = `{
|
|||
"description": "The user who created this list.",
|
||||
"$ref": "#/definitions/user.User"
|
||||
},
|
||||
"position": {
|
||||
"description": "The position this list has when querying all lists. See the tasks.position property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"subscription": {
|
||||
"description": "The subscription status for the user reading this list. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one list.",
|
||||
"$ref": "#/definitions/models.Subscription"
|
||||
|
@ -7901,6 +7913,10 @@ var doc = `{
|
|||
"description": "True if a task is a favorite task. Favorite tasks show up in a separate \"Important\" list. This value depends on the user making the call to the api.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"kanban_position": {
|
||||
"description": "The position of tasks in the kanban board. See the docs for the ` + "`" + `position` + "`" + ` property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"labels": {
|
||||
"description": "An array of labels which are associated with this task.",
|
||||
"type": "array",
|
||||
|
|
|
@ -7201,6 +7201,10 @@
|
|||
"type": "string"
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"description": "The position this bucket has when querying all buckets. See the tasks.position property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"sort_by": {
|
||||
"description": "The query parameter to sort by. This is for ex. done, priority, etc.",
|
||||
"type": "array",
|
||||
|
@ -7308,6 +7312,10 @@
|
|||
"description": "True if a task is a favorite task. Favorite tasks show up in a separate \"Important\" list. This value depends on the user making the call to the api.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"kanban_position": {
|
||||
"description": "The position of tasks in the kanban board. See the docs for the `position` property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"labels": {
|
||||
"description": "An array of labels which are associated with this task.",
|
||||
"type": "array",
|
||||
|
@ -7556,6 +7564,10 @@
|
|||
"description": "The user who created this list.",
|
||||
"$ref": "#/definitions/user.User"
|
||||
},
|
||||
"position": {
|
||||
"description": "The position this list has when querying all lists. See the tasks.position property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"subscription": {
|
||||
"description": "The subscription status for the user reading this list. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one list.",
|
||||
"$ref": "#/definitions/models.Subscription"
|
||||
|
@ -7884,6 +7896,10 @@
|
|||
"description": "True if a task is a favorite task. Favorite tasks show up in a separate \"Important\" list. This value depends on the user making the call to the api.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"kanban_position": {
|
||||
"description": "The position of tasks in the kanban board. See the docs for the `position` property on how to use this.",
|
||||
"type": "number"
|
||||
},
|
||||
"labels": {
|
||||
"description": "An array of labels which are associated with this task.",
|
||||
"type": "array",
|
||||
|
|
|
@ -102,6 +102,10 @@ definitions:
|
|||
items:
|
||||
type: string
|
||||
type: array
|
||||
position:
|
||||
description: The position this bucket has when querying all buckets. See the
|
||||
tasks.position property on how to use this.
|
||||
type: number
|
||||
sort_by:
|
||||
description: The query parameter to sort by. This is for ex. done, priority,
|
||||
etc.
|
||||
|
@ -186,6 +190,10 @@ definitions:
|
|||
a separate "Important" list. This value depends on the user making the call
|
||||
to the api.
|
||||
type: boolean
|
||||
kanban_position:
|
||||
description: The position of tasks in the kanban board. See the docs for the
|
||||
`position` property on how to use this.
|
||||
type: number
|
||||
labels:
|
||||
description: An array of labels which are associated with this task.
|
||||
items:
|
||||
|
@ -403,6 +411,10 @@ definitions:
|
|||
owner:
|
||||
$ref: '#/definitions/user.User'
|
||||
description: The user who created this list.
|
||||
position:
|
||||
description: The position this list has when querying all lists. See the tasks.position
|
||||
property on how to use this.
|
||||
type: number
|
||||
subscription:
|
||||
$ref: '#/definitions/models.Subscription'
|
||||
description: |-
|
||||
|
@ -669,6 +681,10 @@ definitions:
|
|||
a separate "Important" list. This value depends on the user making the call
|
||||
to the api.
|
||||
type: boolean
|
||||
kanban_position:
|
||||
description: The position of tasks in the kanban board. See the docs for the
|
||||
`position` property on how to use this.
|
||||
type: number
|
||||
labels:
|
||||
description: An array of labels which are associated with this task.
|
||||
items:
|
||||
|
|
Loading…
Reference in a new issue