mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	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:
		@@ -116,7 +116,10 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca
 | 
				
			|||||||
			Name: username,
 | 
								Name: username,
 | 
				
			||||||
		}).(*models.User)
 | 
							}).(*models.User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		orgs, err := models.GetOrgsByUserID(user.ID, true)
 | 
							orgs, err := models.FindOrgs(models.FindOrgOptions{
 | 
				
			||||||
 | 
								UserID:         user.ID,
 | 
				
			||||||
 | 
								IncludePrivate: true,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		calcOrgCounts := map[string]int{}
 | 
							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)
 | 
							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
 | 
					// MinimalOrg represents a simple orgnization with only needed columns
 | 
				
			||||||
type MinimalOrg = Organization
 | 
					type MinimalOrg = Organization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -519,6 +501,51 @@ func GetUserOrgsList(user *User) ([]*MinimalOrg, error) {
 | 
				
			|||||||
	return orgs, nil
 | 
						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) {
 | 
					func getOwnedOrgsByUserID(sess db.Engine, userID int64) ([]*User, error) {
 | 
				
			||||||
	orgs := make([]*User, 0, 10)
 | 
						orgs := make([]*User, 0, 10)
 | 
				
			||||||
	return orgs, sess.
 | 
						return orgs, sess.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -307,18 +307,31 @@ func TestIsPublicMembership(t *testing.T) {
 | 
				
			|||||||
	test(unittest.NonexistentID, unittest.NonexistentID, false)
 | 
						test(unittest.NonexistentID, unittest.NonexistentID, false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestGetOrgsByUserID(t *testing.T) {
 | 
					func TestFindOrgs(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, unittest.PrepareTestDatabase())
 | 
						assert.NoError(t, unittest.PrepareTestDatabase())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	orgs, err := GetOrgsByUserID(4, true)
 | 
						orgs, err := FindOrgs(FindOrgOptions{
 | 
				
			||||||
 | 
							UserID:         4,
 | 
				
			||||||
 | 
							IncludePrivate: true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	if assert.Len(t, orgs, 1) {
 | 
						if assert.Len(t, orgs, 1) {
 | 
				
			||||||
		assert.EqualValues(t, 3, orgs[0].ID)
 | 
							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.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, orgs, 0)
 | 
						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) {
 | 
					func TestGetOwnedOrgsByUserID(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,6 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/convert"
 | 
						"code.gitea.io/gitea/modules/convert"
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
					 | 
				
			||||||
	"code.gitea.io/gitea/modules/web"
 | 
						"code.gitea.io/gitea/modules/web"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/api/v1/user"
 | 
						"code.gitea.io/gitea/routers/api/v1/user"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
						"code.gitea.io/gitea/routers/api/v1/utils"
 | 
				
			||||||
@@ -20,25 +19,31 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func listUserOrgs(ctx *context.APIContext, u *models.User) {
 | 
					func listUserOrgs(ctx *context.APIContext, u *models.User) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	listOptions := utils.GetListOptions(ctx)
 | 
						listOptions := utils.GetListOptions(ctx)
 | 
				
			||||||
	showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID)
 | 
						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 {
 | 
						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
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	maxResults := len(orgs)
 | 
					 | 
				
			||||||
	orgs, _ = util.PaginateSlice(orgs, listOptions.Page, listOptions.PageSize).([]*models.Organization)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiOrgs := make([]*api.Organization, len(orgs))
 | 
						apiOrgs := make([]*api.Organization, len(orgs))
 | 
				
			||||||
	for i := range orgs {
 | 
						for i := range orgs {
 | 
				
			||||||
		apiOrgs[i] = convert.ToOrganization(orgs[i])
 | 
							apiOrgs[i] = convert.ToOrganization(orgs[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.SetLinkHeader(maxResults, listOptions.PageSize)
 | 
						ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
 | 
				
			||||||
	ctx.SetTotalCountHeader(int64(maxResults))
 | 
						ctx.SetTotalCountHeader(int64(maxResults))
 | 
				
			||||||
	ctx.JSON(http.StatusOK, &apiOrgs)
 | 
						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)
 | 
						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 {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("GetOrgsByUserIDDesc", err)
 | 
							ctx.ServerError("FindOrgs", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -214,12 +214,34 @@ func DeleteAvatar(ctx *context.Context) {
 | 
				
			|||||||
func Organization(ctx *context.Context) {
 | 
					func Organization(ctx *context.Context) {
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("settings")
 | 
						ctx.Data["Title"] = ctx.Tr("settings")
 | 
				
			||||||
	ctx.Data["PageIsSettingsOrganization"] = true
 | 
						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 {
 | 
						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
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["Orgs"] = orgs
 | 
						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)
 | 
						ctx.HTML(http.StatusOK, tplSettingsOrganization)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@
 | 
				
			|||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					{{end}}
 | 
										{{end}}
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 | 
									{{template "base/paginate" .}}
 | 
				
			||||||
			{{else}}
 | 
								{{else}}
 | 
				
			||||||
				{{.i18n.Tr "settings.orgs_none"}}
 | 
									{{.i18n.Tr "settings.orgs_none"}}
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user