Support pagination of organizations on user settings pages (#16083)
* Add pagination for user setting orgs * Use FindOrgs instead of GetOrgsByUserID * Remove unnecessary functions and fix test * remove unnecessary code
This commit is contained in:
parent
ed23a6c397
commit
c2ab19888f
|
@ -116,7 +116,10 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca
|
|||
Name: username,
|
||||
}).(*models.User)
|
||||
|
||||
orgs, err := models.GetOrgsByUserID(user.ID, true)
|
||||
orgs, err := models.FindOrgs(models.FindOrgOptions{
|
||||
UserID: user.ID,
|
||||
IncludePrivate: true,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
calcOrgCounts := map[string]int{}
|
||||
|
|
|
@ -440,24 +440,6 @@ func getUsersWhoCanCreateOrgRepo(e db.Engine, orgID int64) ([]*User, error) {
|
|||
And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users)
|
||||
}
|
||||
|
||||
func getOrgsByUserID(e db.Engine, userID int64, showAll bool) ([]*Organization, error) {
|
||||
orgs := make([]*Organization, 0, 10)
|
||||
sess := e.Where("`org_user`.uid=?", userID)
|
||||
if !showAll {
|
||||
sess = sess.And("`org_user`.is_public=?", true)
|
||||
}
|
||||
return orgs, sess.
|
||||
Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").
|
||||
Asc("`user`.name").
|
||||
Find(&orgs)
|
||||
}
|
||||
|
||||
// GetOrgsByUserID returns a list of organizations that the given user ID
|
||||
// has joined.
|
||||
func GetOrgsByUserID(userID int64, showAll bool) ([]*Organization, error) {
|
||||
return getOrgsByUserID(db.GetEngine(db.DefaultContext), userID, showAll)
|
||||
}
|
||||
|
||||
// MinimalOrg represents a simple orgnization with only needed columns
|
||||
type MinimalOrg = Organization
|
||||
|
||||
|
@ -519,6 +501,51 @@ func GetUserOrgsList(user *User) ([]*MinimalOrg, error) {
|
|||
return orgs, nil
|
||||
}
|
||||
|
||||
// FindOrgOptions finds orgs options
|
||||
type FindOrgOptions struct {
|
||||
db.ListOptions
|
||||
UserID int64
|
||||
IncludePrivate bool
|
||||
}
|
||||
|
||||
func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
|
||||
var cond = builder.Eq{"uid": userID}
|
||||
if !includePrivate {
|
||||
cond["is_public"] = true
|
||||
}
|
||||
return builder.Select("org_id").From("org_user").Where(cond)
|
||||
}
|
||||
|
||||
func (opts FindOrgOptions) toConds() builder.Cond {
|
||||
var cond = builder.NewCond()
|
||||
if opts.UserID > 0 {
|
||||
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
|
||||
}
|
||||
if !opts.IncludePrivate {
|
||||
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
// FindOrgs returns a list of organizations according given conditions
|
||||
func FindOrgs(opts FindOrgOptions) ([]*Organization, error) {
|
||||
orgs := make([]*Organization, 0, 10)
|
||||
sess := db.GetEngine(db.DefaultContext).
|
||||
Where(opts.toConds()).
|
||||
Asc("`user`.name")
|
||||
if opts.Page > 0 && opts.PageSize > 0 {
|
||||
sess.Limit(opts.PageSize, opts.PageSize*(opts.Page-1))
|
||||
}
|
||||
return orgs, sess.Find(&orgs)
|
||||
}
|
||||
|
||||
// CountOrgs returns total count organizations according options
|
||||
func CountOrgs(opts FindOrgOptions) (int64, error) {
|
||||
return db.GetEngine(db.DefaultContext).
|
||||
Where(opts.toConds()).
|
||||
Count(new(User))
|
||||
}
|
||||
|
||||
func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*User, error) {
|
||||
orgs := make([]*User, 0, 10)
|
||||
return orgs, sess.
|
||||
|
|
|
@ -307,18 +307,31 @@ func TestIsPublicMembership(t *testing.T) {
|
|||
test(unittest.NonexistentID, unittest.NonexistentID, false)
|
||||
}
|
||||
|
||||
func TestGetOrgsByUserID(t *testing.T) {
|
||||
func TestFindOrgs(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
orgs, err := GetOrgsByUserID(4, true)
|
||||
orgs, err := FindOrgs(FindOrgOptions{
|
||||
UserID: 4,
|
||||
IncludePrivate: true,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, orgs, 1) {
|
||||
assert.EqualValues(t, 3, orgs[0].ID)
|
||||
}
|
||||
|
||||
orgs, err = GetOrgsByUserID(4, false)
|
||||
orgs, err = FindOrgs(FindOrgOptions{
|
||||
UserID: 4,
|
||||
IncludePrivate: false,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, orgs, 0)
|
||||
|
||||
total, err := CountOrgs(FindOrgOptions{
|
||||
UserID: 4,
|
||||
IncludePrivate: true,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, total)
|
||||
}
|
||||
|
||||
func TestGetOwnedOrgsByUserID(t *testing.T) {
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/convert"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/user"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
|
@ -20,25 +19,31 @@ import (
|
|||
)
|
||||
|
||||
func listUserOrgs(ctx *context.APIContext, u *models.User) {
|
||||
|
||||
listOptions := utils.GetListOptions(ctx)
|
||||
showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID)
|
||||
|
||||
orgs, err := models.GetOrgsByUserID(u.ID, showPrivate)
|
||||
var opts = models.FindOrgOptions{
|
||||
ListOptions: listOptions,
|
||||
UserID: u.ID,
|
||||
IncludePrivate: showPrivate,
|
||||
}
|
||||
orgs, err := models.FindOrgs(opts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetOrgsByUserID", err)
|
||||
ctx.Error(http.StatusInternalServerError, "FindOrgs", err)
|
||||
return
|
||||
}
|
||||
maxResults, err := models.CountOrgs(opts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CountOrgs", err)
|
||||
return
|
||||
}
|
||||
|
||||
maxResults := len(orgs)
|
||||
orgs, _ = util.PaginateSlice(orgs, listOptions.Page, listOptions.PageSize).([]*models.Organization)
|
||||
|
||||
apiOrgs := make([]*api.Organization, len(orgs))
|
||||
for i := range orgs {
|
||||
apiOrgs[i] = convert.ToOrganization(orgs[i])
|
||||
}
|
||||
|
||||
ctx.SetLinkHeader(maxResults, listOptions.PageSize)
|
||||
ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
|
||||
ctx.SetTotalCountHeader(int64(maxResults))
|
||||
ctx.JSON(http.StatusOK, &apiOrgs)
|
||||
}
|
||||
|
|
|
@ -167,9 +167,12 @@ func Profile(ctx *context.Context) {
|
|||
|
||||
showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID)
|
||||
|
||||
orgs, err := models.GetOrgsByUserID(ctxUser.ID, showPrivate)
|
||||
orgs, err := models.FindOrgs(models.FindOrgOptions{
|
||||
UserID: ctxUser.ID,
|
||||
IncludePrivate: showPrivate,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOrgsByUserIDDesc", err)
|
||||
ctx.ServerError("FindOrgs", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -214,12 +214,34 @@ func DeleteAvatar(ctx *context.Context) {
|
|||
func Organization(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsOrganization"] = true
|
||||
orgs, err := models.GetOrgsByUserID(ctx.User.ID, ctx.IsSigned)
|
||||
|
||||
opts := models.FindOrgOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
PageSize: setting.UI.Admin.UserPagingNum,
|
||||
Page: ctx.FormInt("page"),
|
||||
},
|
||||
UserID: ctx.User.ID,
|
||||
IncludePrivate: ctx.IsSigned,
|
||||
}
|
||||
|
||||
if opts.Page <= 0 {
|
||||
opts.Page = 1
|
||||
}
|
||||
|
||||
orgs, err := models.FindOrgs(opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetOrgsByUserID", err)
|
||||
ctx.ServerError("FindOrgs", err)
|
||||
return
|
||||
}
|
||||
total, err := models.CountOrgs(opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("CountOrgs", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Orgs"] = orgs
|
||||
pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5)
|
||||
pager.SetDefaultParams(ctx)
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.HTML(http.StatusOK, tplSettingsOrganization)
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{template "base/paginate" .}}
|
||||
{{else}}
|
||||
{{.i18n.Tr "settings.orgs_none"}}
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in a new issue