Merge pull request #721 from ywk253100/page

Add pagination support for listing projects
This commit is contained in:
Wenkai Yin 2016-08-29 11:37:20 +08:00 committed by GitHub
commit 4977a2c77e
7 changed files with 152 additions and 70 deletions

View File

@ -154,13 +154,15 @@ func (p *ProjectAPI) Get() {
// List ... // List ...
func (p *ProjectAPI) List() { func (p *ProjectAPI) List() {
var projectList []models.Project var total int64
projectName := p.GetString("project_name")
if len(projectName) > 0 {
projectName = "%" + projectName + "%"
}
var public int var public int
var err error var err error
page, pageSize := p.getPaginationParams()
var projectList []models.Project
projectName := p.GetString("project_name")
isPublic := p.GetString("is_public") isPublic := p.GetString("is_public")
if len(isPublic) > 0 { if len(isPublic) > 0 {
public, err = strconv.Atoi(isPublic) public, err = strconv.Atoi(isPublic)
@ -171,7 +173,16 @@ func (p *ProjectAPI) List() {
} }
isAdmin := false isAdmin := false
if public == 1 { if public == 1 {
projectList, err = dao.GetPublicProjects(projectName) total, err = dao.GetTotalOfProjects(projectName, 1)
if err != nil {
log.Errorf("failed to get total of projects: %v", err)
p.CustomAbort(http.StatusInternalServerError, "")
}
projectList, err = dao.GetProjects(projectName, 1, pageSize, pageSize*(page-1))
if err != nil {
log.Errorf("failed to get projects: %v", err)
p.CustomAbort(http.StatusInternalServerError, "")
}
} else { } else {
//if the request is not for public projects, user must login or provide credential //if the request is not for public projects, user must login or provide credential
p.userID = p.ValidateUser() p.userID = p.ValidateUser()
@ -181,15 +192,30 @@ func (p *ProjectAPI) List() {
p.CustomAbort(http.StatusInternalServerError, "Internal error.") p.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if isAdmin { if isAdmin {
projectList, err = dao.GetAllProjects(projectName) total, err = dao.GetTotalOfProjects(projectName)
} else {
projectList, err = dao.GetUserRelevantProjects(p.userID, projectName)
}
}
if err != nil { if err != nil {
log.Errorf("Error occured in get projects info, error: %v", err) log.Errorf("failed to get total of projects: %v", err)
p.CustomAbort(http.StatusInternalServerError, "Internal error.") p.CustomAbort(http.StatusInternalServerError, "")
} }
projectList, err = dao.GetProjects(projectName, pageSize, pageSize*(page-1))
if err != nil {
log.Errorf("failed to get projects: %v", err)
p.CustomAbort(http.StatusInternalServerError, "")
}
} else {
total, err = dao.GetTotalOfUserRelevantProjects(p.userID, projectName)
if err != nil {
log.Errorf("failed to get total of projects: %v", err)
p.CustomAbort(http.StatusInternalServerError, "")
}
projectList, err = dao.GetUserRelevantProjects(p.userID, projectName, pageSize, pageSize*(page-1))
if err != nil {
log.Errorf("failed to get projects: %v", err)
p.CustomAbort(http.StatusInternalServerError, "")
}
}
}
for i := 0; i < len(projectList); i++ { for i := 0; i < len(projectList); i++ {
if public != 1 { if public != 1 {
if isAdmin { if isAdmin {
@ -201,6 +227,8 @@ func (p *ProjectAPI) List() {
} }
projectList[i].RepoCount = getRepoCountByProject(projectList[i].Name) projectList[i].RepoCount = getRepoCountByProject(projectList[i].Name)
} }
p.setPaginationHeader(total, page, pageSize)
p.Data["json"] = projectList p.Data["json"] = projectList
p.ServeJSON() p.ServeJSON()
} }

View File

@ -55,7 +55,7 @@ func (s *SearchAPI) Get() {
var projects []models.Project var projects []models.Project
if isSysAdmin { if isSysAdmin {
projects, err = dao.GetAllProjects("") projects, err = dao.GetProjects("")
if err != nil { if err != nil {
log.Errorf("failed to get all projects: %v", err) log.Errorf("failed to get all projects: %v", err)
s.CustomAbort(http.StatusInternalServerError, "internal error") s.CustomAbort(http.StatusInternalServerError, "internal error")

View File

@ -45,7 +45,7 @@ func (s *StatisticAPI) Get() {
} }
var projectList []models.Project var projectList []models.Project
if isAdmin { if isAdmin {
projectList, err = dao.GetAllProjects("") projectList, err = dao.GetProjects("")
} else { } else {
projectList, err = dao.GetUserRelevantProjects(s.userID, "") projectList, err = dao.GetUserRelevantProjects(s.userID, "")
} }
@ -59,7 +59,7 @@ func (s *StatisticAPI) Get() {
proMap["public_project_count"] = 0 proMap["public_project_count"] = 0
proMap["public_repo_count"] = 0 proMap["public_repo_count"] = 0
var publicProjects []models.Project var publicProjects []models.Project
publicProjects, err = dao.GetPublicProjects("") publicProjects, err = dao.GetProjects("", 1)
if err != nil { if err != nil {
log.Errorf("Error occured in QueryPublicProject, error: %v", err) log.Errorf("Error occured in QueryPublicProject, error: %v", err)
s.CustomAbort(http.StatusInternalServerError, "Internal error.") s.CustomAbort(http.StatusInternalServerError, "Internal error.")

View File

@ -609,6 +609,17 @@ func TestProjectPermission(t *testing.T) {
} }
} }
func TestGetTotalOfUserRelevantProjects(t *testing.T) {
total, err := GetTotalOfUserRelevantProjects(currentUser.UserID, "")
if err != nil {
t.Fatalf("failed to get total of user relevant projects: %v", err)
}
if total != 1 {
t.Errorf("unexpected total: %d != 1", total)
}
}
func TestGetUserRelevantProjects(t *testing.T) { func TestGetUserRelevantProjects(t *testing.T) {
projects, err := GetUserRelevantProjects(currentUser.UserID, "") projects, err := GetUserRelevantProjects(currentUser.UserID, "")
if err != nil { if err != nil {
@ -622,8 +633,19 @@ func TestGetUserRelevantProjects(t *testing.T) {
} }
} }
func TestGetAllProjects(t *testing.T) { func TestGetTotalOfProjects(t *testing.T) {
projects, err := GetAllProjects("") total, err := GetTotalOfProjects("")
if err != nil {
t.Fatalf("failed to get total of projects: %v", err)
}
if total != 2 {
t.Errorf("unexpected total: %d != 2", total)
}
}
func TestGetProjects(t *testing.T) {
projects, err := GetProjects("")
if err != nil { if err != nil {
t.Errorf("Error occurred in GetAllProjects: %v", err) t.Errorf("Error occurred in GetAllProjects: %v", err)
} }
@ -636,7 +658,7 @@ func TestGetAllProjects(t *testing.T) {
} }
func TestGetPublicProjects(t *testing.T) { func TestGetPublicProjects(t *testing.T) {
projects, err := GetPublicProjects("") projects, err := GetProjects("", 1)
if err != nil { if err != nil {
t.Errorf("Error occurred in getProjects: %v", err) t.Errorf("Error occurred in getProjects: %v", err)
} }

View File

@ -182,66 +182,98 @@ func SearchProjects(userID int) ([]models.Project, error) {
return projects, nil return projects, nil
} }
// GetUserRelevantProjects returns the projects of the user which are not deleted and name like projectName //GetTotalOfUserRelevantProjects returns the total count of
func GetUserRelevantProjects(userID int, projectName string) ([]models.Project, error) { // user relevant projects
func GetTotalOfUserRelevantProjects(userID int, projectName string,
public ...int) (int64, error) {
o := GetOrmer() o := GetOrmer()
sql := `select distinct sql := `select count(*) from project p
p.project_id, p.owner_id, p.name,p.creation_time, p.update_time, p.public, pm.role role left join project_member pm
from project p on p.project_id = pm.project_id
left join project_member pm on p.project_id = pm.project_id
where p.deleted = 0 and pm.user_id= ?` where p.deleted = 0 and pm.user_id= ?`
queryParam := make([]interface{}, 1) queryParam := []interface{}{}
queryParam = append(queryParam, userID) queryParam = append(queryParam, userID)
if projectName != "" { if projectName != "" {
sql += " and p.name like ? " sql += " and p.name like ? "
queryParam = append(queryParam, projectName) queryParam = append(queryParam, "%"+projectName+"%")
} }
sql += " order by p.name "
var r []models.Project var total int64
_, err := o.Raw(sql, queryParam).QueryRows(&r) err := o.Raw(sql, queryParam).QueryRow(&total)
if err != nil {
return nil, err return total, err
}
return r, nil
} }
//GetPublicProjects returns all public projects whose name like projectName // GetUserRelevantProjects returns the user relevant projects
func GetPublicProjects(projectName string) ([]models.Project, error) { // args[0]: public, args[1]: limit, args[2]: offset
publicProjects, err := getProjects(1, projectName) func GetUserRelevantProjects(userID int, projectName string, args ...int64) ([]models.Project, error) {
if err != nil { return getProjects(userID, projectName, args...)
return nil, err
}
return publicProjects, nil
} }
// GetAllProjects returns all projects which are not deleted and name like projectName // GetTotalOfProjects returns the total count of projects
func GetAllProjects(projectName string) ([]models.Project, error) { func GetTotalOfProjects(name string, public ...int) (int64, error) {
allProjects, err := getProjects(0, projectName) qs := GetOrmer().
if err != nil { QueryTable(new(models.Project)).
return nil, err Filter("Deleted", 0)
if len(name) > 0 {
qs = qs.Filter("Name__icontains", name)
} }
return allProjects, nil
if len(public) > 0 {
qs = qs.Filter("Public", public[0])
}
return qs.Count()
} }
func getProjects(public int, projectName string) ([]models.Project, error) { // GetProjects returns project list
// args[0]: public, args[1]: limit, args[2]: offset
func GetProjects(name string, args ...int64) ([]models.Project, error) {
return getProjects(0, name, args...)
}
func getProjects(userID int, name string, args ...int64) ([]models.Project, error) {
projects := []models.Project{}
o := GetOrmer() o := GetOrmer()
sql := `select project_id, owner_id, creation_time, update_time, name, public sql := ""
from project queryParam := []interface{}{}
where deleted = 0`
queryParam := make([]interface{}, 1) if userID != 0 { //get user's projects
if public == 1 { sql = `select distinct p.project_id, p.owner_id, p.name,
sql += " and public = ? " p.creation_time, p.update_time, p.public, pm.role role
queryParam = append(queryParam, public) from project p
left join project_member pm
on p.project_id = pm.project_id
where p.deleted = 0 and pm.user_id= ?`
queryParam = append(queryParam, userID)
} else { // get all projects
sql = `select * from project p where p.deleted = 0 `
} }
if len(projectName) > 0 {
sql += " and name like ? " if name != "" {
queryParam = append(queryParam, projectName) sql += ` and p.name like ? `
queryParam = append(queryParam, "%"+name+"%")
} }
sql += " order by name "
var projects []models.Project switch len(args) {
if _, err := o.Raw(sql, queryParam).QueryRows(&projects); err != nil { case 1:
return nil, err sql += ` and p.public = ?`
queryParam = append(queryParam, args[0])
sql += ` order by p.name `
case 2:
sql += ` order by p.name `
sql = paginateForRawSQL(sql, args[0], args[1])
case 3:
sql += ` and p.public = ?`
queryParam = append(queryParam, args[0])
sql += ` order by p.name `
sql = paginateForRawSQL(sql, args[1], args[2])
} }
return projects, nil
_, err := o.Raw(sql, queryParam).QueryRows(&projects)
return projects, err
} }

View File

@ -336,13 +336,13 @@ func FilterRepJobs(policyID int64, repository, status string, startTime,
qs = qs.Filter("CreationTime__lte", endTime) qs = qs.Filter("CreationTime__lte", endTime)
} }
qs = qs.OrderBy("-UpdateTime")
total, err := qs.Count() total, err := qs.Count()
if err != nil { if err != nil {
return jobs, 0, err return jobs, 0, err
} }
qs = qs.OrderBy("-UpdateTime")
_, err = qs.Limit(limit).Offset(offset).All(&jobs) _, err = qs.Limit(limit).Offset(offset).All(&jobs)
if err != nil { if err != nil {
return jobs, 0, err return jobs, 0, err

View File

@ -25,17 +25,17 @@ type Project struct {
OwnerID int `orm:"column(owner_id)" json:"owner_id"` OwnerID int `orm:"column(owner_id)" json:"owner_id"`
Name string `orm:"column(name)" json:"name"` Name string `orm:"column(name)" json:"name"`
CreationTime time.Time `orm:"column(creation_time)" json:"creation_time"` CreationTime time.Time `orm:"column(creation_time)" json:"creation_time"`
CreationTimeStr string `json:"creation_time_str"` CreationTimeStr string `orm:"-" json:"creation_time_str"`
Deleted int `orm:"column(deleted)" json:"deleted"` Deleted int `orm:"column(deleted)" json:"deleted"`
//UserID int `json:"UserId"` //UserID int `json:"UserId"`
OwnerName string `json:"owner_name"` OwnerName string `orm:"-" json:"owner_name"`
Public int `orm:"column(public)" json:"public"` Public int `orm:"column(public)" json:"public"`
//This field does not have correspondent column in DB, this is just for UI to disable button //This field does not have correspondent column in DB, this is just for UI to disable button
Togglable bool Togglable bool `orm:"-"`
UpdateTime time.Time `orm:"update_time" json:"update_time"` UpdateTime time.Time `orm:"update_time" json:"update_time"`
Role int `json:"current_user_role_id"` Role int `orm:"-" json:"current_user_role_id"`
RepoCount int `json:"repo_count"` RepoCount int `orm:"-" json:"repo_count"`
} }
// ProjectSorter holds an array of projects // ProjectSorter holds an array of projects