Add query param to get all lists including archived ones
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
kolaente 2020-03-15 21:46:59 +01:00
parent dbe726e1a2
commit b8b2c04c83
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
4 changed files with 56 additions and 16 deletions

View File

@ -42,8 +42,8 @@ func TestList(t *testing.T) {
assert.Contains(t, rec.Body.String(), `Test3`) // Shared directly via users_list
assert.Contains(t, rec.Body.String(), `Test4`) // Shared via namespace
assert.NotContains(t, rec.Body.String(), `Test5`)
assert.NotContains(t, rec.Body.String(), `Test21`)
assert.NotContains(t, rec.Body.String(), `Test22`)
assert.NotContains(t, rec.Body.String(), `Test21`) // Archived through namespace
assert.NotContains(t, rec.Body.String(), `Test22`) // Archived directly
})
t.Run("Search", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"s": []string{"Test1"}}, nil)
@ -54,6 +54,17 @@ func TestList(t *testing.T) {
assert.NotContains(t, rec.Body.String(), `Test4`)
assert.NotContains(t, rec.Body.String(), `Test5`)
})
t.Run("Normal with archived lists", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"is_archived": []string{"true"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `Test1`)
assert.NotContains(t, rec.Body.String(), `Test2"`)
assert.Contains(t, rec.Body.String(), `Test3`) // Shared directly via users_list
assert.Contains(t, rec.Body.String(), `Test4`) // Shared via namespace
assert.NotContains(t, rec.Body.String(), `Test5`)
assert.Contains(t, rec.Body.String(), `Test21`) // Archived through namespace
assert.Contains(t, rec.Body.String(), `Test22`) // Archived directly
})
})
t.Run("ReadOne", func(t *testing.T) {
t.Run("Normal", func(t *testing.T) {

View File

@ -203,7 +203,10 @@ func getLabelByIDSimple(labelID int64) (*Label, error) {
func getUserTaskIDs(u *user.User) (taskIDs []int64, err error) {
// Get all lists
lists, _, _, err := getRawListsForUser("", u, -1, 0)
lists, _, _, err := getRawListsForUser(&listOptions{
user: u,
page: -1,
})
if err != nil {
return nil, err
}

View File

@ -21,6 +21,7 @@ import (
"code.vikunja.io/api/pkg/timeutil"
"code.vikunja.io/api/pkg/user"
"code.vikunja.io/web"
"xorm.io/builder"
)
// List represents a list of tasks
@ -44,7 +45,7 @@ type List struct {
Tasks []*Task `xorm:"-" json:"-"`
// Whether or not a list is archived.
IsArchived bool `xorm:"not null default false" json:"is_archived"`
IsArchived bool `xorm:"not null default false" json:"is_archived" query:"is_archived"`
// A timestamp when this list was created. You cannot change this value.
Created timeutil.TimeStamp `xorm:"created not null" json:"created"`
@ -97,6 +98,7 @@ func GetListsByNamespaceID(nID int64, doer *user.User) (lists []*List, err error
// @Param page query int false "The page number. Used for pagination. If not provided, the first page of results is returned."
// @Param per_page query int false "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page."
// @Param s query string false "Search lists by title."
// @Param is_archived query bool false "If true, also returns all archived lists."
// @Security JWTKeyAuth
// @Success 200 {array} models.List "The lists"
// @Failure 403 {object} code.vikunja.io/web.HTTPError "The user does not have access to the list"
@ -116,7 +118,13 @@ func (l *List) ReadAll(a web.Auth, search string, page int, perPage int) (result
return lists, 0, 0, err
}
lists, resultCount, totalItems, err := getRawListsForUser(search, &user.User{ID: a.GetID()}, page, perPage)
lists, resultCount, totalItems, err := getRawListsForUser(&listOptions{
search: search,
user: &user.User{ID: a.GetID()},
page: page,
perPage: perPage,
isArchived: l.IsArchived,
})
if err != nil {
return nil, 0, 0, err
}
@ -188,13 +196,30 @@ func GetListSimplByTaskID(taskID int64) (l *List, err error) {
return &list, nil
}
type listOptions struct {
search string
user *user.User
page int
perPage int
isArchived bool
}
// Gets the lists only, without any tasks or so
func getRawListsForUser(search string, u *user.User, page int, perPage int) (lists []*List, resultCount int, totalItems int64, err error) {
fullUser, err := user.GetUserByID(u.ID)
func getRawListsForUser(opts *listOptions) (lists []*List, resultCount int, totalItems int64, err error) {
fullUser, err := user.GetUserByID(opts.user.ID)
if err != nil {
return nil, 0, 0, err
}
// Adding a 1=1 condition by default here because xorm always needs a condition and cannot handle nil conditions
var isArchivedCond builder.Cond = builder.Eq{"1": 1}
if !opts.isArchived {
isArchivedCond = builder.And(
builder.Eq{"l.is_archived": false},
builder.Eq{"n.is_archived": false},
)
}
// Gets all Lists where the user is either owner or in a team which has access to the list
// Or in a team which has namespace read access
err = x.Select("l.*").
@ -213,10 +238,9 @@ func getRawListsForUser(search string, u *user.User, page int, perPage int) (lis
Or("ul.user_id = ?", fullUser.ID).
Or("un.user_id = ?", fullUser.ID).
GroupBy("l.id").
Limit(getLimitFromPageIndex(page, perPage)).
Where("l.title LIKE ?", "%"+search+"%").
Where("l.is_archived = false").
Where("n.is_archived = false").
Limit(getLimitFromPageIndex(opts.page, opts.perPage)).
Where("l.title LIKE ?", "%"+opts.search+"%").
Where(isArchivedCond).
Find(&lists)
if err != nil {
return nil, 0, 0, err
@ -238,10 +262,9 @@ func getRawListsForUser(search string, u *user.User, page int, perPage int) (lis
Or("ul.user_id = ?", fullUser.ID).
Or("un.user_id = ?", fullUser.ID).
GroupBy("l.id").
Limit(getLimitFromPageIndex(page, perPage)).
Where("l.title LIKE ?", "%"+search+"%").
Where("l.is_archived = false").
Where("n.is_archived = false").
Limit(getLimitFromPageIndex(opts.page, opts.perPage)).
Where("l.title LIKE ?", "%"+opts.search+"%").
Where(isArchivedCond).
Count(&List{})
return lists, len(lists), totalItems, err
}

View File

@ -109,7 +109,10 @@ func (tf *TaskCollection) ReadAll(a web.Auth, search string, page int, perPage i
// If the list ID is not set, we get all tasks for the user.
// This allows to use this function in Task.ReadAll with a possibility to deprecate the latter at some point.
if tf.ListID == 0 {
tf.Lists, _, _, err = getRawListsForUser("", &user.User{ID: a.GetID()}, -1, 0)
tf.Lists, _, _, err = getRawListsForUser(&listOptions{
user: &user.User{ID: a.GetID()},
page: -1,
})
if err != nil {
return nil, 0, 0, err
}