Add task identifier (#115)
This commit is contained in:
parent
1a47d7d80d
commit
720df3cbed
18 changed files with 811 additions and 217 deletions
2
Makefile
2
Makefile
|
@ -214,7 +214,7 @@ gocyclo-check:
|
||||||
go get -u github.com/fzipp/gocyclo; \
|
go get -u github.com/fzipp/gocyclo; \
|
||||||
go install $(GOFLAGS) github.com/fzipp/gocyclo; \
|
go install $(GOFLAGS) github.com/fzipp/gocyclo; \
|
||||||
fi
|
fi
|
||||||
for S in $(GOFILES); do gocyclo -over 23 $$S || exit 1; done;
|
for S in $(GOFILES); do gocyclo -over 24 $$S || exit 1; done;
|
||||||
|
|
||||||
.PHONY: static-check
|
.PHONY: static-check
|
||||||
static-check:
|
static-check:
|
||||||
|
|
|
@ -33,6 +33,7 @@ This document describes the different errors Vikunja can return.
|
||||||
| 3004 | 403 | The user needs to have read permissions on that list to perform that action. |
|
| 3004 | 403 | The user needs to have read permissions on that list to perform that action. |
|
||||||
| 3005 | 400 | The list title cannot be empty. |
|
| 3005 | 400 | The list title cannot be empty. |
|
||||||
| 3006 | 404 | The list share does not exist. |
|
| 3006 | 404 | The list share does not exist. |
|
||||||
|
| 3007 | 400 | A list with this identifier already exists. |
|
||||||
| 4001 | 400 | The list task text cannot be empty. |
|
| 4001 | 400 | The list task text cannot be empty. |
|
||||||
| 4002 | 404 | The list task does not exist. |
|
| 4002 | 404 | The list task does not exist. |
|
||||||
| 4003 | 403 | All bulk editing tasks must belong to the same list. |
|
| 4003 | 403 | All bulk editing tasks must belong to the same list. |
|
||||||
|
|
|
@ -95,33 +95,33 @@ func TestTaskCollection(t *testing.T) {
|
||||||
t.Run("by priority", func(t *testing.T) {
|
t.Run("by priority", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, urlParams)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, urlParams)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("by priority desc", func(t *testing.T) {
|
t.Run("by priority desc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, urlParams)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, urlParams)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`)
|
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`)
|
||||||
})
|
})
|
||||||
t.Run("by priority asc", func(t *testing.T) {
|
t.Run("by priority asc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, urlParams)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, urlParams)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
// should equal duedate asc
|
// should equal duedate asc
|
||||||
t.Run("by duedate", func(t *testing.T) {
|
t.Run("by duedate", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}}, urlParams)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}}, urlParams)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("by duedate desc", func(t *testing.T) {
|
t.Run("by duedate desc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"desc"}}, urlParams)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"desc"}}, urlParams)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date`)
|
||||||
})
|
})
|
||||||
t.Run("by duedate asc", func(t *testing.T) {
|
t.Run("by duedate asc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"asc"}}, urlParams)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"asc"}}, urlParams)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("invalid sort parameter", func(t *testing.T) {
|
t.Run("invalid sort parameter", func(t *testing.T) {
|
||||||
_, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"loremipsum"}}, urlParams)
|
_, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"loremipsum"}}, urlParams)
|
||||||
|
@ -249,33 +249,33 @@ func TestTaskCollection(t *testing.T) {
|
||||||
t.Run("by priority", func(t *testing.T) {
|
t.Run("by priority", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, nil)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("by priority desc", func(t *testing.T) {
|
t.Run("by priority desc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, nil)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`)
|
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`)
|
||||||
})
|
})
|
||||||
t.Run("by priority asc", func(t *testing.T) {
|
t.Run("by priority asc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, nil)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
// should equal duedate asc
|
// should equal duedate asc
|
||||||
t.Run("by duedate", func(t *testing.T) {
|
t.Run("by duedate", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}}, nil)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("by duedate desc", func(t *testing.T) {
|
t.Run("by duedate desc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"desc"}}, nil)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"desc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
||||||
})
|
})
|
||||||
t.Run("by duedate asc", func(t *testing.T) {
|
t.Run("by duedate asc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"asc"}}, nil)
|
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date_unix"}, "order_by": []string{"asc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("invalid parameter", func(t *testing.T) {
|
t.Run("invalid parameter", func(t *testing.T) {
|
||||||
// Invalid parameter should not sort at all
|
// Invalid parameter should not sort at all
|
||||||
|
|
44
pkg/migration/20191207204427.go
Normal file
44
pkg/migration/20191207204427.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2019 Vikunja and contriubtors. All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of Vikunja.
|
||||||
|
//
|
||||||
|
// Vikunja is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Vikunja 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package migration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
"src.techknowlogick.com/xormigrate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type list20191207204427 struct {
|
||||||
|
Identifier string `xorm:"varchar(10) null" json:"identifier"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list20191207204427) TableName() string {
|
||||||
|
return "list"
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
migrations = append(migrations, &xormigrate.Migration{
|
||||||
|
ID: "20191207204427",
|
||||||
|
Description: "Add task identifier to list",
|
||||||
|
Migrate: func(tx *xorm.Engine) error {
|
||||||
|
return tx.Sync2(list20191207204427{})
|
||||||
|
},
|
||||||
|
Rollback: func(tx *xorm.Engine) error {
|
||||||
|
return dropTableColum(tx, "list", "indentifier")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
77
pkg/migration/20191207220736.go
Normal file
77
pkg/migration/20191207220736.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2019 Vikunja and contriubtors. All rights reserved.
|
||||||
|
//
|
||||||
|
// This file is part of Vikunja.
|
||||||
|
//
|
||||||
|
// Vikunja is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Vikunja 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package migration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
"src.techknowlogick.com/xormigrate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type task20191207220736 struct {
|
||||||
|
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"listtask"`
|
||||||
|
Index int64 `xorm:"int(11) not null default 0" json:"index"`
|
||||||
|
ListID int64 `xorm:"int(11) INDEX not null" json:"listID" param:"list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (task20191207220736) TableName() string {
|
||||||
|
return "tasks"
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
migrations = append(migrations, &xormigrate.Migration{
|
||||||
|
ID: "20191207220736",
|
||||||
|
Description: "Add task index to tasks",
|
||||||
|
Migrate: func(tx *xorm.Engine) error {
|
||||||
|
err := tx.Sync2(task20191207220736{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all tasks, ordered by list and id
|
||||||
|
tasks := []*task20191207220736{}
|
||||||
|
err = tx.
|
||||||
|
OrderBy("list_id asc, id asc").
|
||||||
|
Find(&tasks)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentIndex int64 = 1
|
||||||
|
for i, task := range tasks {
|
||||||
|
// Reset the current counter if we're encountering a new list
|
||||||
|
// We can do this because the list is sorted by list id
|
||||||
|
if i > 0 && tasks[i-1].ListID != task.ListID {
|
||||||
|
currentIndex = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
task.Index = currentIndex
|
||||||
|
_, err = tx.Where("id = ?", task.ID).Update(task)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Rollback: func(tx *xorm.Engine) error {
|
||||||
|
return dropTableColum(tx, "tasks", "index")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -471,6 +471,33 @@ func (err ErrListShareDoesNotExist) HTTPError() web.HTTPError {
|
||||||
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListShareDoesNotExist, Message: "The list share does not exist."}
|
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeListShareDoesNotExist, Message: "The list share does not exist."}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrListIdentifierIsNotUnique represents a "ErrListIdentifierIsNotUnique" kind of error. Used if the provided list identifier is not unique.
|
||||||
|
type ErrListIdentifierIsNotUnique struct {
|
||||||
|
Identifier string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrListIdentifierIsNotUnique checks if an error is a ErrListIdentifierIsNotUnique.
|
||||||
|
func IsErrListIdentifierIsNotUnique(err error) bool {
|
||||||
|
_, ok := err.(ErrListIdentifierIsNotUnique)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrListIdentifierIsNotUnique) Error() string {
|
||||||
|
return fmt.Sprintf("List identifier is not unique.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrCodeListIdentifierIsNotUnique holds the unique world-error code of this error
|
||||||
|
const ErrCodeListIdentifierIsNotUnique = 3007
|
||||||
|
|
||||||
|
// HTTPError holds the http error description
|
||||||
|
func (err ErrListIdentifierIsNotUnique) HTTPError() web.HTTPError {
|
||||||
|
return web.HTTPError{
|
||||||
|
HTTPCode: http.StatusBadRequest,
|
||||||
|
Code: ErrCodeListIdentifierIsNotUnique,
|
||||||
|
Message: "A list with this identifier already exists.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ================
|
// ================
|
||||||
// List task errors
|
// List task errors
|
||||||
// ================
|
// ================
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
id: 1
|
id: 1
|
||||||
title: Test1
|
title: Test1
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test1
|
||||||
owner_id: 1
|
owner_id: 1
|
||||||
namespace_id: 1
|
namespace_id: 1
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
id: 2
|
id: 2
|
||||||
title: Test2
|
title: Test2
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test2
|
||||||
owner_id: 3
|
owner_id: 3
|
||||||
namespace_id: 1
|
namespace_id: 1
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
id: 3
|
id: 3
|
||||||
title: Test3
|
title: Test3
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test3
|
||||||
owner_id: 3
|
owner_id: 3
|
||||||
namespace_id: 2
|
namespace_id: 2
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -26,6 +29,7 @@
|
||||||
id: 4
|
id: 4
|
||||||
title: Test4
|
title: Test4
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test4
|
||||||
owner_id: 3
|
owner_id: 3
|
||||||
namespace_id: 3
|
namespace_id: 3
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -34,6 +38,7 @@
|
||||||
id: 5
|
id: 5
|
||||||
title: Test5
|
title: Test5
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test5
|
||||||
owner_id: 5
|
owner_id: 5
|
||||||
namespace_id: 5
|
namespace_id: 5
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -42,6 +47,7 @@
|
||||||
id: 6
|
id: 6
|
||||||
title: Test6
|
title: Test6
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test6
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 6
|
namespace_id: 6
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -50,6 +56,7 @@
|
||||||
id: 7
|
id: 7
|
||||||
title: Test7
|
title: Test7
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test7
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 6
|
namespace_id: 6
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -58,6 +65,7 @@
|
||||||
id: 8
|
id: 8
|
||||||
title: Test8
|
title: Test8
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test8
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 6
|
namespace_id: 6
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -66,6 +74,7 @@
|
||||||
id: 9
|
id: 9
|
||||||
title: Test9
|
title: Test9
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test9
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 6
|
namespace_id: 6
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -74,6 +83,7 @@
|
||||||
id: 10
|
id: 10
|
||||||
title: Test10
|
title: Test10
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test10
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 6
|
namespace_id: 6
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -82,6 +92,7 @@
|
||||||
id: 11
|
id: 11
|
||||||
title: Test11
|
title: Test11
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test11
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 6
|
namespace_id: 6
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -90,6 +101,7 @@
|
||||||
id: 12
|
id: 12
|
||||||
title: Test12
|
title: Test12
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test12
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 7
|
namespace_id: 7
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -98,6 +110,7 @@
|
||||||
id: 13
|
id: 13
|
||||||
title: Test13
|
title: Test13
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test13
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 8
|
namespace_id: 8
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -106,6 +119,7 @@
|
||||||
id: 14
|
id: 14
|
||||||
title: Test14
|
title: Test14
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test14
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 9
|
namespace_id: 9
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -114,6 +128,7 @@
|
||||||
id: 15
|
id: 15
|
||||||
title: Test15
|
title: Test15
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test15
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 10
|
namespace_id: 10
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -122,6 +137,7 @@
|
||||||
id: 16
|
id: 16
|
||||||
title: Test16
|
title: Test16
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test16
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 11
|
namespace_id: 11
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -130,6 +146,7 @@
|
||||||
id: 17
|
id: 17
|
||||||
title: Test17
|
title: Test17
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test17
|
||||||
owner_id: 6
|
owner_id: 6
|
||||||
namespace_id: 12
|
namespace_id: 12
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -140,6 +157,7 @@
|
||||||
id: 18
|
id: 18
|
||||||
title: Test18
|
title: Test18
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test18
|
||||||
owner_id: 7
|
owner_id: 7
|
||||||
namespace_id: 13
|
namespace_id: 13
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -148,6 +166,7 @@
|
||||||
id: 19
|
id: 19
|
||||||
title: Test19
|
title: Test19
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test19
|
||||||
owner_id: 7
|
owner_id: 7
|
||||||
namespace_id: 14
|
namespace_id: 14
|
||||||
updated: 0
|
updated: 0
|
||||||
|
@ -156,6 +175,7 @@
|
||||||
id: 20
|
id: 20
|
||||||
title: Test20
|
title: Test20
|
||||||
description: Lorem Ipsum
|
description: Lorem Ipsum
|
||||||
|
identifier: test20
|
||||||
owner_id: 13
|
owner_id: 13
|
||||||
namespace_id: 15
|
namespace_id: 15
|
||||||
updated: 0
|
updated: 0
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
description: 'Lorem Ipsum'
|
description: 'Lorem Ipsum'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 2
|
- id: 2
|
||||||
|
@ -10,12 +11,14 @@
|
||||||
done: true
|
done: true
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 2
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 3
|
- id: 3
|
||||||
text: 'task #3 high prio'
|
text: 'task #3 high prio'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 3
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
priority: 100
|
priority: 100
|
||||||
|
@ -23,6 +26,7 @@
|
||||||
text: 'task #4 low prio'
|
text: 'task #4 low prio'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 4
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
priority: 1
|
priority: 1
|
||||||
|
@ -30,6 +34,7 @@
|
||||||
text: 'task #5 higher due date'
|
text: 'task #5 higher due date'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 5
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
due_date_unix: 1543636724
|
due_date_unix: 1543636724
|
||||||
|
@ -37,6 +42,7 @@
|
||||||
text: 'task #6 lower due date'
|
text: 'task #6 lower due date'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 6
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
due_date_unix: 1543616724
|
due_date_unix: 1543616724
|
||||||
|
@ -44,6 +50,7 @@
|
||||||
text: 'task #7 with start date'
|
text: 'task #7 with start date'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 7
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
start_date_unix: 1544600000
|
start_date_unix: 1544600000
|
||||||
|
@ -51,6 +58,7 @@
|
||||||
text: 'task #8 with end date'
|
text: 'task #8 with end date'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 8
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
end_date_unix: 1544700000
|
end_date_unix: 1544700000
|
||||||
|
@ -58,6 +66,7 @@
|
||||||
text: 'task #9 with start and end date'
|
text: 'task #9 with start and end date'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 9
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
start_date_unix: 1544600000
|
start_date_unix: 1544600000
|
||||||
|
@ -66,108 +75,126 @@
|
||||||
text: 'task #10 basic'
|
text: 'task #10 basic'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 10
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 11
|
- id: 11
|
||||||
text: 'task #11 basic'
|
text: 'task #11 basic'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 11
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 12
|
- id: 12
|
||||||
text: 'task #12 basic'
|
text: 'task #12 basic'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 12
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 13
|
- id: 13
|
||||||
text: 'task #13 basic other list'
|
text: 'task #13 basic other list'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 2
|
list_id: 2
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 14
|
- id: 14
|
||||||
text: 'task #14 basic other list'
|
text: 'task #14 basic other list'
|
||||||
created_by_id: 5
|
created_by_id: 5
|
||||||
list_id: 5
|
list_id: 5
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 15
|
- id: 15
|
||||||
text: 'task #15'
|
text: 'task #15'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 6
|
list_id: 6
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 16
|
- id: 16
|
||||||
text: 'task #16'
|
text: 'task #16'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 7
|
list_id: 7
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 17
|
- id: 17
|
||||||
text: 'task #17'
|
text: 'task #17'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 8
|
list_id: 8
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 18
|
- id: 18
|
||||||
text: 'task #18'
|
text: 'task #18'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 9
|
list_id: 9
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 19
|
- id: 19
|
||||||
text: 'task #19'
|
text: 'task #19'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 10
|
list_id: 10
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 20
|
- id: 20
|
||||||
text: 'task #20'
|
text: 'task #20'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 11
|
list_id: 11
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 21
|
- id: 21
|
||||||
text: 'task #21'
|
text: 'task #21'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 12
|
list_id: 12
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 22
|
- id: 22
|
||||||
text: 'task #22'
|
text: 'task #22'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 13
|
list_id: 13
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 23
|
- id: 23
|
||||||
text: 'task #23'
|
text: 'task #23'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 14
|
list_id: 14
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 24
|
- id: 24
|
||||||
text: 'task #24'
|
text: 'task #24'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 15
|
list_id: 15
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 25
|
- id: 25
|
||||||
text: 'task #25'
|
text: 'task #25'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 16
|
list_id: 16
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 26
|
- id: 26
|
||||||
text: 'task #26'
|
text: 'task #26'
|
||||||
created_by_id: 6
|
created_by_id: 6
|
||||||
list_id: 17
|
list_id: 17
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 27
|
- id: 27
|
||||||
text: 'task #27 with reminders'
|
text: 'task #27 with reminders'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 12
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 28
|
- id: 28
|
||||||
|
@ -176,24 +203,28 @@
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
repeat_after: 3600
|
repeat_after: 3600
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 13
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 29
|
- id: 29
|
||||||
text: 'task #29 with parent task (1)'
|
text: 'task #29 with parent task (1)'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 14
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 30
|
- id: 30
|
||||||
text: 'task #30 with assignees'
|
text: 'task #30 with assignees'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 15
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 31
|
- id: 31
|
||||||
text: 'task #31 with color'
|
text: 'task #31 with color'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 16
|
||||||
hex_color: f0f0f0
|
hex_color: f0f0f0
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
|
@ -201,12 +232,14 @@
|
||||||
text: 'task #32'
|
text: 'task #32'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 3
|
list_id: 3
|
||||||
|
index: 1
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
- id: 33
|
- id: 33
|
||||||
text: 'task #33 with percent done'
|
text: 'task #33 with percent done'
|
||||||
created_by_id: 1
|
created_by_id: 1
|
||||||
list_id: 1
|
list_id: 1
|
||||||
|
index: 17
|
||||||
percent_done: 0.5
|
percent_done: 0.5
|
||||||
created: 1543626724
|
created: 1543626724
|
||||||
updated: 1543626724
|
updated: 1543626724
|
||||||
|
|
|
@ -29,6 +29,9 @@ type List struct {
|
||||||
Title string `xorm:"varchar(250) not null" json:"title" valid:"required,runelength(3|250)" minLength:"3" maxLength:"250"`
|
Title string `xorm:"varchar(250) not null" json:"title" valid:"required,runelength(3|250)" minLength:"3" maxLength:"250"`
|
||||||
// The description of the list.
|
// The description of the list.
|
||||||
Description string `xorm:"longtext null" json:"description"`
|
Description string `xorm:"longtext null" json:"description"`
|
||||||
|
// The unique list short identifier. Used to build task identifiers.
|
||||||
|
Identifier string `xorm:"varchar(10) null" json:"identifier" valid:"runelength(0|10)" minLength:"0" maxLength:"10"`
|
||||||
|
|
||||||
OwnerID int64 `xorm:"int(11) INDEX not null" json:"-"`
|
OwnerID int64 `xorm:"int(11) INDEX not null" json:"-"`
|
||||||
NamespaceID int64 `xorm:"int(11) INDEX not null" json:"-" param:"namespace"`
|
NamespaceID int64 `xorm:"int(11) INDEX not null" json:"-" param:"namespace"`
|
||||||
|
|
||||||
|
@ -265,6 +268,17 @@ func CreateOrUpdateList(list *List) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the identifier is unique and not empty
|
||||||
|
if list.Identifier != "" {
|
||||||
|
exists, err := x.Where("identifier = ?", list.Identifier).Exist(&List{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
return ErrListIdentifierIsNotUnique{Identifier: list.Identifier}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if list.ID == 0 {
|
if list.ID == 0 {
|
||||||
_, err = x.Insert(list)
|
_, err = x.Insert(list)
|
||||||
metrics.UpdateCount(1, metrics.ListCountKey)
|
metrics.UpdateCount(1, metrics.ListCountKey)
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
// Vikunja is a todo-list application to facilitate your life.
|
|
||||||
// Copyright 2018-2019 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 General Public License 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 General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestList_Create(t *testing.T) {
|
|
||||||
// Create test database
|
|
||||||
//assert.NoError(t, LoadFixtures())
|
|
||||||
|
|
||||||
// Get our doer
|
|
||||||
doer, err := GetUserByID(1)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// Dummy list for testing
|
|
||||||
dummylist := List{
|
|
||||||
Title: "test",
|
|
||||||
Description: "Lorem Ipsum",
|
|
||||||
NamespaceID: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the user can create
|
|
||||||
allowed, _ := dummylist.CanCreate(doer)
|
|
||||||
assert.True(t, allowed)
|
|
||||||
|
|
||||||
// Create it
|
|
||||||
err = dummylist.Create(doer)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// Get the list
|
|
||||||
newdummy := List{ID: dummylist.ID}
|
|
||||||
canRead, err := newdummy.CanRead(doer)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, canRead)
|
|
||||||
err = newdummy.ReadOne()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, dummylist.Title, newdummy.Title)
|
|
||||||
assert.Equal(t, dummylist.Description, newdummy.Description)
|
|
||||||
assert.Equal(t, dummylist.OwnerID, doer.ID)
|
|
||||||
|
|
||||||
// Check if the user can see it
|
|
||||||
allowed, _ = dummylist.CanRead(doer)
|
|
||||||
assert.True(t, allowed)
|
|
||||||
|
|
||||||
// Try updating a list
|
|
||||||
allowed, _ = dummylist.CanUpdate(doer)
|
|
||||||
assert.True(t, allowed)
|
|
||||||
dummylist.Description = "Lorem Ipsum dolor sit amet."
|
|
||||||
err = dummylist.Update()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// Delete it
|
|
||||||
allowed, _ = dummylist.CanDelete(doer)
|
|
||||||
assert.True(t, allowed)
|
|
||||||
|
|
||||||
err = dummylist.Delete()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// Try updating a nonexistant list
|
|
||||||
err = dummylist.Update()
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrListDoesNotExist(err))
|
|
||||||
|
|
||||||
// Check creation with a nonexistant namespace
|
|
||||||
list3 := List{
|
|
||||||
Title: "test",
|
|
||||||
Description: "Lorem Ipsum",
|
|
||||||
NamespaceID: 876694,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = list3.Create(doer)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
|
||||||
|
|
||||||
// Try creating with a nonexistant owner
|
|
||||||
nUser := &User{ID: 9482385}
|
|
||||||
err = dummylist.Create(nUser)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrUserDoesNotExist(err))
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
// Vikunja is a todo-list application to facilitate your life.
|
|
||||||
// Copyright 2018-2019 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 General Public License 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 General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestList_ReadAll(t *testing.T) {
|
|
||||||
// Create test database
|
|
||||||
//assert.NoError(t, LoadFixtures())
|
|
||||||
|
|
||||||
// Get all lists for our namespace
|
|
||||||
lists, err := GetListsByNamespaceID(1, &User{})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, len(lists), 2)
|
|
||||||
|
|
||||||
// Get all lists our user has access to
|
|
||||||
u, err := GetUserByID(1)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
lists2 := List{}
|
|
||||||
lists3, _, _, err := lists2.ReadAll(u, "", 1, 50)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, reflect.TypeOf(lists3).Kind(), reflect.Slice)
|
|
||||||
s := reflect.ValueOf(lists3)
|
|
||||||
assert.Equal(t, 16, s.Len())
|
|
||||||
|
|
||||||
// Try getting lists for a nonexistant user
|
|
||||||
_, _, _, err = lists2.ReadAll(&User{ID: 984234}, "", 1, 50)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.True(t, IsErrUserDoesNotExist(err))
|
|
||||||
}
|
|
157
pkg/models/list_test.go
Normal file
157
pkg/models/list_test.go
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
// Vikunja is a todo-list application to facilitate your life.
|
||||||
|
// Copyright 2018-2019 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 General Public License 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestList_CreateOrUpdate(t *testing.T) {
|
||||||
|
user := &User{
|
||||||
|
ID: 1,
|
||||||
|
Username: "user1",
|
||||||
|
Email: "user1@example.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("create", func(t *testing.T) {
|
||||||
|
t.Run("normal", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
Title: "test",
|
||||||
|
Description: "Lorem Ipsum",
|
||||||
|
NamespaceID: 1,
|
||||||
|
}
|
||||||
|
err := list.Create(user)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
t.Run("nonexistant namespace", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
Title: "test",
|
||||||
|
Description: "Lorem Ipsum",
|
||||||
|
NamespaceID: 999999,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := list.Create(user)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||||
|
})
|
||||||
|
t.Run("nonexistant owner", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
user := &User{ID: 9482385}
|
||||||
|
list := List{
|
||||||
|
Title: "test",
|
||||||
|
Description: "Lorem Ipsum",
|
||||||
|
NamespaceID: 1,
|
||||||
|
}
|
||||||
|
err := list.Create(user)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrUserDoesNotExist(err))
|
||||||
|
})
|
||||||
|
t.Run("existing identifier", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
Title: "test",
|
||||||
|
Description: "Lorem Ipsum",
|
||||||
|
Identifier: "test1",
|
||||||
|
NamespaceID: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := list.Create(user)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrListIdentifierIsNotUnique(err))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("update", func(t *testing.T) {
|
||||||
|
t.Run("normal", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
ID: 1,
|
||||||
|
Title: "test",
|
||||||
|
Description: "Lorem Ipsum",
|
||||||
|
NamespaceID: 1,
|
||||||
|
}
|
||||||
|
list.Description = "Lorem Ipsum dolor sit amet."
|
||||||
|
err := list.Update()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
})
|
||||||
|
t.Run("nonexistant", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
ID: 99999999,
|
||||||
|
Title: "test",
|
||||||
|
}
|
||||||
|
err := list.Update()
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrListDoesNotExist(err))
|
||||||
|
|
||||||
|
})
|
||||||
|
t.Run("existing identifier", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
Title: "test",
|
||||||
|
Description: "Lorem Ipsum",
|
||||||
|
Identifier: "test1",
|
||||||
|
NamespaceID: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := list.Create(user)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrListIdentifierIsNotUnique(err))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestList_Delete(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
list := List{
|
||||||
|
ID: 1,
|
||||||
|
}
|
||||||
|
err := list.Delete()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestList_ReadAll(t *testing.T) {
|
||||||
|
t.Run("all in namespace", func(t *testing.T) {
|
||||||
|
initFixtures(t)
|
||||||
|
// Get all lists for our namespace
|
||||||
|
lists, err := GetListsByNamespaceID(1, &User{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(lists), 2)
|
||||||
|
})
|
||||||
|
t.Run("all lists for user", func(t *testing.T) {
|
||||||
|
u := &User{ID: 1}
|
||||||
|
list := List{}
|
||||||
|
lists3, _, _, err := list.ReadAll(u, "", 1, 50)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, reflect.TypeOf(lists3).Kind(), reflect.Slice)
|
||||||
|
s := reflect.ValueOf(lists3)
|
||||||
|
assert.Equal(t, 16, s.Len())
|
||||||
|
})
|
||||||
|
t.Run("lists for nonexistant user", func(t *testing.T) {
|
||||||
|
user := &User{ID: 999999}
|
||||||
|
list := List{}
|
||||||
|
_, _, _, err := list.ReadAll(user, "", 1, 50)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, IsErrUserDoesNotExist(err))
|
||||||
|
})
|
||||||
|
}
|
|
@ -55,6 +55,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Text: "task #1",
|
Text: "task #1",
|
||||||
Description: "Lorem Ipsum",
|
Description: "Lorem Ipsum",
|
||||||
|
Identifier: "test1-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -73,6 +75,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
{
|
{
|
||||||
ID: 29,
|
ID: 29,
|
||||||
Text: "task #29 with parent task (1)",
|
Text: "task #29 with parent task (1)",
|
||||||
|
Index: 14,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
Created: 1543626724,
|
Created: 1543626724,
|
||||||
|
@ -109,6 +112,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task2 := &Task{
|
task2 := &Task{
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Text: "task #2 done",
|
Text: "task #2 done",
|
||||||
|
Identifier: "test1-2",
|
||||||
|
Index: 2,
|
||||||
Done: true,
|
Done: true,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
|
@ -130,6 +135,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task3 := &Task{
|
task3 := &Task{
|
||||||
ID: 3,
|
ID: 3,
|
||||||
Text: "task #3 high prio",
|
Text: "task #3 high prio",
|
||||||
|
Identifier: "test1-3",
|
||||||
|
Index: 3,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -141,6 +148,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task4 := &Task{
|
task4 := &Task{
|
||||||
ID: 4,
|
ID: 4,
|
||||||
Text: "task #4 low prio",
|
Text: "task #4 low prio",
|
||||||
|
Identifier: "test1-4",
|
||||||
|
Index: 4,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -152,6 +161,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task5 := &Task{
|
task5 := &Task{
|
||||||
ID: 5,
|
ID: 5,
|
||||||
Text: "task #5 higher due date",
|
Text: "task #5 higher due date",
|
||||||
|
Identifier: "test1-5",
|
||||||
|
Index: 5,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -163,6 +174,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task6 := &Task{
|
task6 := &Task{
|
||||||
ID: 6,
|
ID: 6,
|
||||||
Text: "task #6 lower due date",
|
Text: "task #6 lower due date",
|
||||||
|
Identifier: "test1-6",
|
||||||
|
Index: 6,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -174,6 +187,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task7 := &Task{
|
task7 := &Task{
|
||||||
ID: 7,
|
ID: 7,
|
||||||
Text: "task #7 with start date",
|
Text: "task #7 with start date",
|
||||||
|
Identifier: "test1-7",
|
||||||
|
Index: 7,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -185,6 +200,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task8 := &Task{
|
task8 := &Task{
|
||||||
ID: 8,
|
ID: 8,
|
||||||
Text: "task #8 with end date",
|
Text: "task #8 with end date",
|
||||||
|
Identifier: "test1-8",
|
||||||
|
Index: 8,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -196,6 +213,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task9 := &Task{
|
task9 := &Task{
|
||||||
ID: 9,
|
ID: 9,
|
||||||
Text: "task #9 with start and end date",
|
Text: "task #9 with start and end date",
|
||||||
|
Identifier: "test1-9",
|
||||||
|
Index: 9,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -208,6 +227,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task10 := &Task{
|
task10 := &Task{
|
||||||
ID: 10,
|
ID: 10,
|
||||||
Text: "task #10 basic",
|
Text: "task #10 basic",
|
||||||
|
Identifier: "test1-10",
|
||||||
|
Index: 10,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -218,6 +239,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task11 := &Task{
|
task11 := &Task{
|
||||||
ID: 11,
|
ID: 11,
|
||||||
Text: "task #11 basic",
|
Text: "task #11 basic",
|
||||||
|
Identifier: "test1-11",
|
||||||
|
Index: 11,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -228,6 +251,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task12 := &Task{
|
task12 := &Task{
|
||||||
ID: 12,
|
ID: 12,
|
||||||
Text: "task #12 basic",
|
Text: "task #12 basic",
|
||||||
|
Identifier: "test1-12",
|
||||||
|
Index: 12,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -238,6 +263,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task15 := &Task{
|
task15 := &Task{
|
||||||
ID: 15,
|
ID: 15,
|
||||||
Text: "task #15",
|
Text: "task #15",
|
||||||
|
Identifier: "test6-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 6,
|
ListID: 6,
|
||||||
|
@ -248,6 +275,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task16 := &Task{
|
task16 := &Task{
|
||||||
ID: 16,
|
ID: 16,
|
||||||
Text: "task #16",
|
Text: "task #16",
|
||||||
|
Identifier: "test7-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 7,
|
ListID: 7,
|
||||||
|
@ -258,6 +287,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task17 := &Task{
|
task17 := &Task{
|
||||||
ID: 17,
|
ID: 17,
|
||||||
Text: "task #17",
|
Text: "task #17",
|
||||||
|
Identifier: "test8-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 8,
|
ListID: 8,
|
||||||
|
@ -268,6 +299,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task18 := &Task{
|
task18 := &Task{
|
||||||
ID: 18,
|
ID: 18,
|
||||||
Text: "task #18",
|
Text: "task #18",
|
||||||
|
Identifier: "test9-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 9,
|
ListID: 9,
|
||||||
|
@ -278,6 +311,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task19 := &Task{
|
task19 := &Task{
|
||||||
ID: 19,
|
ID: 19,
|
||||||
Text: "task #19",
|
Text: "task #19",
|
||||||
|
Identifier: "test10-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 10,
|
ListID: 10,
|
||||||
|
@ -288,6 +323,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task20 := &Task{
|
task20 := &Task{
|
||||||
ID: 20,
|
ID: 20,
|
||||||
Text: "task #20",
|
Text: "task #20",
|
||||||
|
Identifier: "test11-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 11,
|
ListID: 11,
|
||||||
|
@ -298,6 +335,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task21 := &Task{
|
task21 := &Task{
|
||||||
ID: 21,
|
ID: 21,
|
||||||
Text: "task #21",
|
Text: "task #21",
|
||||||
|
Identifier: "test12-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 12,
|
ListID: 12,
|
||||||
|
@ -308,6 +347,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task22 := &Task{
|
task22 := &Task{
|
||||||
ID: 22,
|
ID: 22,
|
||||||
Text: "task #22",
|
Text: "task #22",
|
||||||
|
Identifier: "test13-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 13,
|
ListID: 13,
|
||||||
|
@ -318,6 +359,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task23 := &Task{
|
task23 := &Task{
|
||||||
ID: 23,
|
ID: 23,
|
||||||
Text: "task #23",
|
Text: "task #23",
|
||||||
|
Identifier: "test14-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 14,
|
ListID: 14,
|
||||||
|
@ -328,6 +371,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task24 := &Task{
|
task24 := &Task{
|
||||||
ID: 24,
|
ID: 24,
|
||||||
Text: "task #24",
|
Text: "task #24",
|
||||||
|
Identifier: "test15-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 15,
|
ListID: 15,
|
||||||
|
@ -338,6 +383,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task25 := &Task{
|
task25 := &Task{
|
||||||
ID: 25,
|
ID: 25,
|
||||||
Text: "task #25",
|
Text: "task #25",
|
||||||
|
Identifier: "test16-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 16,
|
ListID: 16,
|
||||||
|
@ -348,6 +395,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task26 := &Task{
|
task26 := &Task{
|
||||||
ID: 26,
|
ID: 26,
|
||||||
Text: "task #26",
|
Text: "task #26",
|
||||||
|
Identifier: "test17-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 6,
|
CreatedByID: 6,
|
||||||
CreatedBy: user6,
|
CreatedBy: user6,
|
||||||
ListID: 17,
|
ListID: 17,
|
||||||
|
@ -358,6 +407,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task27 := &Task{
|
task27 := &Task{
|
||||||
ID: 27,
|
ID: 27,
|
||||||
Text: "task #27 with reminders",
|
Text: "task #27 with reminders",
|
||||||
|
Identifier: "test1-12",
|
||||||
|
Index: 12,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
RemindersUnix: []int64{1543626724, 1543626824},
|
RemindersUnix: []int64{1543626724, 1543626824},
|
||||||
|
@ -369,6 +420,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task28 := &Task{
|
task28 := &Task{
|
||||||
ID: 28,
|
ID: 28,
|
||||||
Text: "task #28 with repeat after",
|
Text: "task #28 with repeat after",
|
||||||
|
Identifier: "test1-13",
|
||||||
|
Index: 13,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -380,6 +433,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task29 := &Task{
|
task29 := &Task{
|
||||||
ID: 29,
|
ID: 29,
|
||||||
Text: "task #29 with parent task (1)",
|
Text: "task #29 with parent task (1)",
|
||||||
|
Identifier: "test1-14",
|
||||||
|
Index: 14,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -389,6 +444,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Text: "task #1",
|
Text: "task #1",
|
||||||
Description: "Lorem Ipsum",
|
Description: "Lorem Ipsum",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
Created: 1543626724,
|
Created: 1543626724,
|
||||||
|
@ -402,6 +458,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task30 := &Task{
|
task30 := &Task{
|
||||||
ID: 30,
|
ID: 30,
|
||||||
Text: "task #30 with assignees",
|
Text: "task #30 with assignees",
|
||||||
|
Identifier: "test1-15",
|
||||||
|
Index: 15,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
@ -416,6 +474,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task31 := &Task{
|
task31 := &Task{
|
||||||
ID: 31,
|
ID: 31,
|
||||||
Text: "task #31 with color",
|
Text: "task #31 with color",
|
||||||
|
Identifier: "test1-16",
|
||||||
|
Index: 16,
|
||||||
HexColor: "f0f0f0",
|
HexColor: "f0f0f0",
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
|
@ -427,6 +487,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task32 := &Task{
|
task32 := &Task{
|
||||||
ID: 32,
|
ID: 32,
|
||||||
Text: "task #32",
|
Text: "task #32",
|
||||||
|
Identifier: "test3-1",
|
||||||
|
Index: 1,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 3,
|
ListID: 3,
|
||||||
|
@ -437,6 +499,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
||||||
task33 := &Task{
|
task33 := &Task{
|
||||||
ID: 33,
|
ID: 33,
|
||||||
Text: "task #33 with percent done",
|
Text: "task #33 with percent done",
|
||||||
|
Identifier: "test1-17",
|
||||||
|
Index: 17,
|
||||||
CreatedByID: 1,
|
CreatedByID: 1,
|
||||||
CreatedBy: user1,
|
CreatedBy: user1,
|
||||||
ListID: 1,
|
ListID: 1,
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"code.vikunja.io/web"
|
"code.vikunja.io/web"
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -62,6 +63,11 @@ type Task struct {
|
||||||
// Determines how far a task is left from being done
|
// Determines how far a task is left from being done
|
||||||
PercentDone float64 `xorm:"DOUBLE null" json:"percentDone"`
|
PercentDone float64 `xorm:"DOUBLE null" json:"percentDone"`
|
||||||
|
|
||||||
|
// The task identifier, based on the list identifier and the task's index
|
||||||
|
Identifier string `xorm:"-" json:"identifier"`
|
||||||
|
// The task index, calculated per list
|
||||||
|
Index int64 `xorm:"int(11) not null default 0" json:"index"`
|
||||||
|
|
||||||
// The UID is currently not used for anything other than caldav, which is why we don't expose it over json
|
// The UID is currently not used for anything other than caldav, which is why we don't expose it over json
|
||||||
UID string `xorm:"varchar(250) null" json:"-"`
|
UID string `xorm:"varchar(250) null" json:"-"`
|
||||||
|
|
||||||
|
@ -230,19 +236,6 @@ func getTasksForLists(lists []*List, opts *taskOptions) (tasks []*Task, resultCo
|
||||||
return tasks, resultCount, totalItems, err
|
return tasks, resultCount, totalItems, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTasksByListID gets all todotasks for a list
|
|
||||||
func GetTasksByListID(listID int64) (tasks []*Task, err error) {
|
|
||||||
// make a map so we can put in a lot of other stuff more easily
|
|
||||||
taskMap := make(map[int64]*Task, len(tasks))
|
|
||||||
err = x.Where("list_id = ?", listID).Find(&taskMap)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks, err = addMoreInfoToTasks(taskMap)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 Task, err error) {
|
func GetTaskByIDSimple(taskID int64) (task Task, err error) {
|
||||||
if taskID < 1 {
|
if taskID < 1 {
|
||||||
|
@ -314,9 +307,11 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (tasks []*Task, err error) {
|
||||||
// Get all users & task ids and put them into the array
|
// Get all users & task ids and put them into the array
|
||||||
var userIDs []int64
|
var userIDs []int64
|
||||||
var taskIDs []int64
|
var taskIDs []int64
|
||||||
|
var listIDs []int64
|
||||||
for _, i := range taskMap {
|
for _, i := range taskMap {
|
||||||
taskIDs = append(taskIDs, i.ID)
|
taskIDs = append(taskIDs, i.ID)
|
||||||
userIDs = append(userIDs, i.CreatedByID)
|
userIDs = append(userIDs, i.CreatedByID)
|
||||||
|
listIDs = append(listIDs, i.ListID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all assignees
|
// Get all assignees
|
||||||
|
@ -399,6 +394,13 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (tasks []*Task, err error) {
|
||||||
taskRemindersUnix[r.TaskID] = append(taskRemindersUnix[r.TaskID], r.ReminderUnix)
|
taskRemindersUnix[r.TaskID] = append(taskRemindersUnix[r.TaskID], r.ReminderUnix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all identifiers
|
||||||
|
lists := make(map[int64]*List, len(listIDs))
|
||||||
|
err = x.In("id", listIDs).Find(&lists)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Add all user objects to the appropriate tasks
|
// Add all user objects to the appropriate tasks
|
||||||
for _, task := range taskMap {
|
for _, task := range taskMap {
|
||||||
|
|
||||||
|
@ -410,6 +412,9 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (tasks []*Task, err error) {
|
||||||
|
|
||||||
// Prepare the subtasks
|
// Prepare the subtasks
|
||||||
task.RelatedTasks = make(RelatedTaskMap)
|
task.RelatedTasks = make(RelatedTaskMap)
|
||||||
|
|
||||||
|
// Build the task identifier from the list identifier and task index
|
||||||
|
task.Identifier = lists[task.ListID].Identifier + "-" + strconv.FormatInt(task.Index, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all related tasks
|
// Get all related tasks
|
||||||
|
@ -785,7 +790,7 @@ func (t *Task) Delete() (err error) {
|
||||||
// @Success 200 {object} models.Task "The task"
|
// @Success 200 {object} models.Task "The task"
|
||||||
// @Failure 404 {object} models.Message "Task not found"
|
// @Failure 404 {object} models.Message "Task not found"
|
||||||
// @Failure 500 {object} models.Message "Internal error"
|
// @Failure 500 {object} models.Message "Internal error"
|
||||||
// @Router /tasks/all [get]
|
// @Router /tasks/{ID} [get]
|
||||||
func (t *Task) ReadOne() (err error) {
|
func (t *Task) ReadOne() (err error) {
|
||||||
|
|
||||||
taskMap := make(map[int64]*Task, 1)
|
taskMap := make(map[int64]*Task, 1)
|
||||||
|
|
|
@ -24,9 +24,11 @@ import (
|
||||||
"code.vikunja.io/api/pkg/mail"
|
"code.vikunja.io/api/pkg/mail"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/testfixtures.v2"
|
"gopkg.in/testfixtures.v2"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupTests takes care of seting up the db, fixtures etc.
|
// SetupTests takes care of seting up the db, fixtures etc.
|
||||||
|
@ -84,3 +86,9 @@ func createTestEngine(fixturesDir string) error {
|
||||||
func initSchema(tx *xorm.Engine) error {
|
func initSchema(tx *xorm.Engine) error {
|
||||||
return tx.Sync2(GetTables()...)
|
return tx.Sync2(GetTables()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initFixtures(t *testing.T) {
|
||||||
|
// Init db fixtures
|
||||||
|
err := db.LoadFixtures()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
// This file was generated by swaggo/swag at
|
// This file was generated by swaggo/swag at
|
||||||
// 2019-12-07 20:29:10.551783293 +0100 CET m=+0.172017440
|
// 2019-12-07 22:54:02.661375666 +0100 CET m=+0.164990732
|
||||||
|
|
||||||
package swagger
|
package swagger
|
||||||
|
|
||||||
|
@ -2649,7 +2649,7 @@ var doc = `{
|
||||||
"JWTKeyAuth": []
|
"JWTKeyAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Returns one task by its ID",
|
"description": "Returns all tasks on any list the user has access to.",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -2659,27 +2659,53 @@ var doc = `{
|
||||||
"tags": [
|
"tags": [
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
"summary": "Get one task",
|
"summary": "Get tasks",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "The task ID",
|
"description": "The page number. Used for pagination. If not provided, the first page of results is returned.",
|
||||||
"name": "ID",
|
"name": "page",
|
||||||
"in": "path",
|
"in": "query"
|
||||||
"required": true
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page.",
|
||||||
|
"name": "per_page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Search tasks by task text.",
|
||||||
|
"name": "s",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, duedate, duedatedesc, duedateasc.",
|
||||||
|
"name": "sort",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "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.",
|
||||||
|
"name": "startdate",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "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.",
|
||||||
|
"name": "enddate",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "The task",
|
"description": "The tasks",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
"$ref": "#/definitions/models.Task"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"404": {
|
|
||||||
"description": "Task not found",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/models.Message"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
|
@ -2749,6 +2775,55 @@ var doc = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/tasks/{ID}": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"JWTKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Returns one task by its ID",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Get one task",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The task ID",
|
||||||
|
"name": "ID",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The task",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Task"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Task not found",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Message"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Message"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/tasks/{id}": {
|
"/tasks/{id}": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@ -4481,6 +4556,14 @@ var doc = `{
|
||||||
"description": "The unique, numeric id of this task.",
|
"description": "The unique, numeric id of this task.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The task identifier, based on the list identifier and the task's index",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "The task index, calculated per list",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"description": "An array of labels which are associated with this task.",
|
"description": "An array of labels which are associated with this task.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -4663,6 +4746,12 @@ var doc = `{
|
||||||
"description": "The unique, numeric id of this list.",
|
"description": "The unique, numeric id of this list.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The unique list short identifier. Used to build task identifiers.",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 10,
|
||||||
|
"minLength": 0
|
||||||
|
},
|
||||||
"owner": {
|
"owner": {
|
||||||
"description": "The user who created this list.",
|
"description": "The user who created this list.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -4894,6 +4983,14 @@ var doc = `{
|
||||||
"description": "The unique, numeric id of this task.",
|
"description": "The unique, numeric id of this task.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The task identifier, based on the list identifier and the task's index",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "The task index, calculated per list",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"description": "An array of labels which are associated with this task.",
|
"description": "An array of labels which are associated with this task.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -5002,6 +5099,14 @@ var doc = `{
|
||||||
"description": "The unique, numeric id of this task.",
|
"description": "The unique, numeric id of this task.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The task identifier, based on the list identifier and the task's index",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "The task index, calculated per list",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"description": "An array of labels which are associated with this task.",
|
"description": "An array of labels which are associated with this task.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
|
|
@ -2631,7 +2631,7 @@
|
||||||
"JWTKeyAuth": []
|
"JWTKeyAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Returns one task by its ID",
|
"description": "Returns all tasks on any list the user has access to.",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -2641,27 +2641,53 @@
|
||||||
"tags": [
|
"tags": [
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
"summary": "Get one task",
|
"summary": "Get tasks",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "The task ID",
|
"description": "The page number. Used for pagination. If not provided, the first page of results is returned.",
|
||||||
"name": "ID",
|
"name": "page",
|
||||||
"in": "path",
|
"in": "query"
|
||||||
"required": true
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page.",
|
||||||
|
"name": "per_page",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Search tasks by task text.",
|
||||||
|
"name": "s",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, duedate, duedatedesc, duedateasc.",
|
||||||
|
"name": "sort",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "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.",
|
||||||
|
"name": "startdate",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "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.",
|
||||||
|
"name": "enddate",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "The task",
|
"description": "The tasks",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
"$ref": "#/definitions/models.Task"
|
"$ref": "#/definitions/models.Task"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"404": {
|
|
||||||
"description": "Task not found",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/models.Message"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
|
@ -2731,6 +2757,55 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/tasks/{ID}": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"JWTKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Returns one task by its ID",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"summary": "Get one task",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The task ID",
|
||||||
|
"name": "ID",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The task",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Task"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Task not found",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Message"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Message"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/tasks/{id}": {
|
"/tasks/{id}": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@ -4462,6 +4537,14 @@
|
||||||
"description": "The unique, numeric id of this task.",
|
"description": "The unique, numeric id of this task.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The task identifier, based on the list identifier and the task's index",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "The task index, calculated per list",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"description": "An array of labels which are associated with this task.",
|
"description": "An array of labels which are associated with this task.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -4644,6 +4727,12 @@
|
||||||
"description": "The unique, numeric id of this list.",
|
"description": "The unique, numeric id of this list.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The unique list short identifier. Used to build task identifiers.",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 10,
|
||||||
|
"minLength": 0
|
||||||
|
},
|
||||||
"owner": {
|
"owner": {
|
||||||
"description": "The user who created this list.",
|
"description": "The user who created this list.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -4875,6 +4964,14 @@
|
||||||
"description": "The unique, numeric id of this task.",
|
"description": "The unique, numeric id of this task.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The task identifier, based on the list identifier and the task's index",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "The task index, calculated per list",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"description": "An array of labels which are associated with this task.",
|
"description": "An array of labels which are associated with this task.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -4983,6 +5080,14 @@
|
||||||
"description": "The unique, numeric id of this task.",
|
"description": "The unique, numeric id of this task.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"identifier": {
|
||||||
|
"description": "The task identifier, based on the list identifier and the task's index",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"description": "The task index, calculated per list",
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"description": "An array of labels which are associated with this task.",
|
"description": "An array of labels which are associated with this task.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
|
|
@ -84,6 +84,13 @@ definitions:
|
||||||
id:
|
id:
|
||||||
description: The unique, numeric id of this task.
|
description: The unique, numeric id of this task.
|
||||||
type: integer
|
type: integer
|
||||||
|
identifier:
|
||||||
|
description: The task identifier, based on the list identifier and the task's
|
||||||
|
index
|
||||||
|
type: string
|
||||||
|
index:
|
||||||
|
description: The task index, calculated per list
|
||||||
|
type: integer
|
||||||
labels:
|
labels:
|
||||||
description: An array of labels which are associated with this task.
|
description: An array of labels which are associated with this task.
|
||||||
items:
|
items:
|
||||||
|
@ -232,6 +239,11 @@ definitions:
|
||||||
id:
|
id:
|
||||||
description: The unique, numeric id of this list.
|
description: The unique, numeric id of this list.
|
||||||
type: integer
|
type: integer
|
||||||
|
identifier:
|
||||||
|
description: The unique list short identifier. Used to build task identifiers.
|
||||||
|
maxLength: 10
|
||||||
|
minLength: 0
|
||||||
|
type: string
|
||||||
owner:
|
owner:
|
||||||
$ref: '#/definitions/models.User'
|
$ref: '#/definitions/models.User'
|
||||||
description: The user who created this list.
|
description: The user who created this list.
|
||||||
|
@ -413,6 +425,13 @@ definitions:
|
||||||
id:
|
id:
|
||||||
description: The unique, numeric id of this task.
|
description: The unique, numeric id of this task.
|
||||||
type: integer
|
type: integer
|
||||||
|
identifier:
|
||||||
|
description: The task identifier, based on the list identifier and the
|
||||||
|
task's index
|
||||||
|
type: string
|
||||||
|
index:
|
||||||
|
description: The task index, calculated per list
|
||||||
|
type: integer
|
||||||
labels:
|
labels:
|
||||||
description: An array of labels which are associated with this task.
|
description: An array of labels which are associated with this task.
|
||||||
items:
|
items:
|
||||||
|
@ -500,6 +519,13 @@ definitions:
|
||||||
id:
|
id:
|
||||||
description: The unique, numeric id of this task.
|
description: The unique, numeric id of this task.
|
||||||
type: integer
|
type: integer
|
||||||
|
identifier:
|
||||||
|
description: The task identifier, based on the list identifier and the task's
|
||||||
|
index
|
||||||
|
type: string
|
||||||
|
index:
|
||||||
|
description: The task index, calculated per list
|
||||||
|
type: integer
|
||||||
labels:
|
labels:
|
||||||
description: An array of labels which are associated with this task.
|
description: An array of labels which are associated with this task.
|
||||||
items:
|
items:
|
||||||
|
@ -2587,6 +2613,37 @@ paths:
|
||||||
summary: Get an auth token for a share
|
summary: Get an auth token for a share
|
||||||
tags:
|
tags:
|
||||||
- sharing
|
- sharing
|
||||||
|
/tasks/{ID}:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: Returns one task by its ID
|
||||||
|
parameters:
|
||||||
|
- description: The task ID
|
||||||
|
in: path
|
||||||
|
name: ID
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The task
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Task'
|
||||||
|
"404":
|
||||||
|
description: Task not found
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Message'
|
||||||
|
"500":
|
||||||
|
description: Internal error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Message'
|
||||||
|
security:
|
||||||
|
- JWTKeyAuth: []
|
||||||
|
summary: Get one task
|
||||||
|
tags:
|
||||||
|
- task
|
||||||
/tasks/{id}:
|
/tasks/{id}:
|
||||||
delete:
|
delete:
|
||||||
description: Deletes a task from a list. This does not mean "mark it done".
|
description: Deletes a task from a list. This does not mean "mark it done".
|
||||||
|
@ -3241,31 +3298,55 @@ paths:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: Returns one task by its ID
|
description: Returns all tasks on any list the user has access to.
|
||||||
parameters:
|
parameters:
|
||||||
- description: The task ID
|
- description: The page number. Used for pagination. If not provided, the first
|
||||||
in: path
|
page of results is returned.
|
||||||
name: ID
|
in: query
|
||||||
required: true
|
name: page
|
||||||
|
type: integer
|
||||||
|
- description: The maximum number of items per page. Note this parameter is
|
||||||
|
limited by the configured maximum of items per page.
|
||||||
|
in: query
|
||||||
|
name: per_page
|
||||||
|
type: integer
|
||||||
|
- description: Search tasks by task text.
|
||||||
|
in: query
|
||||||
|
name: s
|
||||||
|
type: string
|
||||||
|
- description: The sorting parameter. Possible values to sort by are priority,
|
||||||
|
prioritydesc, priorityasc, duedate, duedatedesc, duedateasc.
|
||||||
|
in: query
|
||||||
|
name: sort
|
||||||
|
type: string
|
||||||
|
- description: 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.
|
||||||
|
in: query
|
||||||
|
name: startdate
|
||||||
|
type: integer
|
||||||
|
- description: 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.
|
||||||
|
in: query
|
||||||
|
name: enddate
|
||||||
type: integer
|
type: integer
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: The task
|
description: The tasks
|
||||||
schema:
|
schema:
|
||||||
|
items:
|
||||||
$ref: '#/definitions/models.Task'
|
$ref: '#/definitions/models.Task'
|
||||||
"404":
|
type: array
|
||||||
description: Task not found
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/models.Message'
|
|
||||||
"500":
|
"500":
|
||||||
description: Internal error
|
description: Internal error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/models.Message'
|
$ref: '#/definitions/models.Message'
|
||||||
security:
|
security:
|
||||||
- JWTKeyAuth: []
|
- JWTKeyAuth: []
|
||||||
summary: Get one task
|
summary: Get tasks
|
||||||
tags:
|
tags:
|
||||||
- task
|
- task
|
||||||
/tasks/bulk:
|
/tasks/bulk:
|
||||||
|
|
Loading…
Reference in a new issue