diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 241c773fe..b983d711f 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -894,8 +894,9 @@ paths: get: summary: Get repositories accompany with relevant project and repo name. description: > - This endpoint let user search repositories accompanying with relevant - project ID and repo name. + This endpoint lets user search repositories accompanying with relevant + project ID and repo name. Repositories can be sorted by repo name, creation_time, + update_time in either ascending or descending order. parameters: - name: project_id in: query @@ -908,6 +909,13 @@ paths: type: string required: false description: Repo name for filtering results. + - name: sort + in: query + type: string + required: false + description: > + Sort method, valid values include: 'name', '-name', 'creation_time', '-creation_time', + 'update_time', '-update_time'. Here '-' stands for descending order. - name: label_id in: query type: integer diff --git a/src/common/dao/repository.go b/src/common/dao/repository.go index 8142ed4ff..df50d3eb2 100644 --- a/src/common/dao/repository.go +++ b/src/common/dao/repository.go @@ -22,6 +22,18 @@ import ( "github.com/goharbor/harbor/src/common/models" ) +var orderMap = map[string]string{ + "name": "name asc", + "+name": "name asc", + "-name": "name desc", + "creation_time": "creation_time asc", + "+creation_time": "creation_time asc", + "-creation_time": "creation_time desc", + "update_time": "update_time asc", + "+update_time": "update_time asc", + "-update_time": "update_time desc", +} + // AddRepository adds a repo to the database. func AddRepository(repo models.RepoRecord) error { if repo.ProjectID == 0 { @@ -116,10 +128,16 @@ func GetTotalOfRepositories(query ...*models.RepositoryQuery) (int64, error) { // GetRepositories ... func GetRepositories(query ...*models.RepositoryQuery) ([]*models.RepoRecord, error) { repositories := []*models.RepoRecord{} + order := "name asc" + if len(query) > 0 && query[0] != nil { + if s, ok := orderMap[query[0].Sort]; ok { + order = s + } + } - sql, params := repositoryQueryConditions(query...) - sql = `select r.repository_id, r.name, r.project_id, r.description, r.pull_count, - r.star_count, r.creation_time, r.update_time ` + sql + `order by r.name ` + condition, params := repositoryQueryConditions(query...) + sql := fmt.Sprintf(`select r.repository_id, r.name, r.project_id, r.description, r.pull_count, + r.star_count, r.creation_time, r.update_time %s order by r.%s `, condition, order) if len(query) > 0 && query[0] != nil { page, size := query[0].Page, query[0].Size if size > 0 { diff --git a/src/common/models/project.go b/src/common/models/project.go index 8e6305362..63dfd595e 100644 --- a/src/common/models/project.go +++ b/src/common/models/project.go @@ -125,7 +125,7 @@ type ProjectQueryParam struct { ProjectIDs []int64 // project ID list } -// MemberQuery fitler by member's username and role +// MemberQuery filter by member's username and role type MemberQuery struct { Name string // the username of member Role int // the role of the member has to the project @@ -138,6 +138,11 @@ type Pagination struct { Size int64 } +// Sorting sort by given field, ascending or descending +type Sorting struct { + Sort string // in format [+-]?, e.g. '+creation_time', '-creation_time' +} + // BaseProjectCollection contains the query conditions which can be used // to get a project collection. The collection can be used as the base to // do other filter diff --git a/src/common/models/repo.go b/src/common/models/repo.go index 9d1e36aeb..1540e1282 100644 --- a/src/common/models/repo.go +++ b/src/common/models/repo.go @@ -45,4 +45,5 @@ type RepositoryQuery struct { ProjectName string LabelID int64 Pagination + Sorting } diff --git a/src/ui/api/repository.go b/src/ui/api/repository.go index b6fed739c..4e17f5e47 100644 --- a/src/ui/api/repository.go +++ b/src/ui/api/repository.go @@ -19,6 +19,7 @@ import ( "fmt" "io/ioutil" "net/http" + "sort" "strconv" "strings" "time" @@ -49,6 +50,7 @@ type RepositoryAPI struct { type repoResp struct { ID int64 `json:"id"` + Index int `json:"-"` Name string `json:"name"` ProjectID int64 `json:"project_id"` Description string `json:"description"` @@ -60,6 +62,20 @@ type repoResp struct { UpdateTime time.Time `json:"update_time"` } +type reposSorter []*repoResp + +func (r reposSorter) Len() int { + return len(r) +} + +func (r reposSorter) Swap(i, j int) { + r[i], r[j] = r[j], r[i] +} + +func (r reposSorter) Less(i, j int) bool { + return r[i].Index < r[j].Index +} + type tagDetail struct { Digest string `json:"digest"` Name string `json:"name"` @@ -129,6 +145,7 @@ func (ra *RepositoryAPI) Get() { LabelID: labelID, } query.Page, query.Size = ra.GetPaginationParams() + query.Sort = ra.GetString("sort") total, err := dao.GetTotalOfRepositories(query) if err != nil { @@ -159,8 +176,8 @@ func getRepositories(query *models.RepositoryQuery) ([]*repoResp, error) { func assembleReposInParallel(repositories []*models.RepoRecord) []*repoResp { c := make(chan *repoResp) - for _, repository := range repositories { - go assembleRepo(c, repository) + for i, repository := range repositories { + go assembleRepo(c, i, repository) } result := []*repoResp{} var item *repoResp @@ -171,11 +188,14 @@ func assembleReposInParallel(repositories []*models.RepoRecord) []*repoResp { } result = append(result, item) } + sort.Sort(reposSorter(result)) + return result } -func assembleRepo(c chan *repoResp, repository *models.RepoRecord) { +func assembleRepo(c chan *repoResp, index int, repository *models.RepoRecord) { repo := &repoResp{ + Index: index, ID: repository.RepositoryID, Name: repository.Name, ProjectID: repository.ProjectID,