feat: support search bar on star tab of user profile. (#917)

* feat: support search bar on star tab of user profile.

* fix: update testing.

* fix: Using loadAttributes

* fix: remove empty line.

* remove LOWER

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
tokarchuk/v1.17
Bo-Yi Wu 8 years ago committed by Lunny Xiao
parent 7eb8daffa3
commit 23aba523b5
  1. 30
      models/repo.go
  2. 4
      models/star.go
  3. 4
      models/star_test.go
  4. 121
      routers/user/profile.go
  5. 10
      templates/base/paginate.tmpl
  6. 2
      templates/explore/repo_list.tmpl
  7. 13
      templates/explore/search.tmpl
  8. 1
      templates/user/profile.tmpl

@ -1778,13 +1778,15 @@ type SearchRepoOptions struct {
Searcher *User //ID of the person who's seeking Searcher *User //ID of the person who's seeking
OrderBy string OrderBy string
Private bool // Include private repositories in results Private bool // Include private repositories in results
Starred bool
Page int Page int
PageSize int // Can be smaller than or equal to setting.ExplorePagingNum PageSize int // Can be smaller than or equal to setting.ExplorePagingNum
} }
// SearchRepositoryByName takes keyword and part of repository name to search, // SearchRepositoryByName takes keyword and part of repository name to search,
// it returns results in given range and number of total results. // it returns results in given range and number of total results.
func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int64, _ error) { func SearchRepositoryByName(opts *SearchRepoOptions) (repos RepositoryList, _ int64, _ error) {
var sess *xorm.Session
if len(opts.Keyword) == 0 { if len(opts.Keyword) == 0 {
return repos, 0, nil return repos, 0, nil
} }
@ -1796,9 +1798,17 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int
repos = make([]*Repository, 0, opts.PageSize) repos = make([]*Repository, 0, opts.PageSize)
if opts.Starred && opts.OwnerID > 0 {
sess = x.
Join("INNER", "star", "star.repo_id = repository.id").
Where("star.uid = ?", opts.OwnerID).
And("lower_name LIKE ?", "%"+opts.Keyword+"%")
} else {
sess = x.Where("lower_name LIKE ?", "%"+opts.Keyword+"%")
}
// Append conditions // Append conditions
sess := x.Where("LOWER(lower_name) LIKE ?", "%"+opts.Keyword+"%") if !opts.Starred && opts.OwnerID > 0 {
if opts.OwnerID > 0 {
sess.And("owner_id = ?", opts.OwnerID) sess.And("owner_id = ?", opts.OwnerID)
} }
if !opts.Private { if !opts.Private {
@ -1831,10 +1841,20 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int
return nil, 0, fmt.Errorf("Count: %v", err) return nil, 0, fmt.Errorf("Count: %v", err)
} }
return repos, count, sess. if err = sess.
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize). Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).
OrderBy(opts.OrderBy). OrderBy(opts.OrderBy).
Find(&repos) Find(&repos); err != nil {
return nil, 0, fmt.Errorf("Repo: %v", err)
}
if opts.Starred {
if err = repos.loadAttributes(x); err != nil {
return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
}
}
return repos, count, nil
} }
// DeleteRepositoryArchives deletes all repositories' archives. // DeleteRepositoryArchives deletes all repositories' archives.

@ -73,12 +73,12 @@ func (repo *Repository) GetStargazers(page int) ([]*User, error) {
// GetStarredRepos returns the repos the user starred. // GetStarredRepos returns the repos the user starred.
func (u *User) GetStarredRepos(private bool, page, pageSize int, orderBy string) (repos []*Repository, err error) { func (u *User) GetStarredRepos(private bool, page, pageSize int, orderBy string) (repos []*Repository, err error) {
if len(orderBy) == 0 { if len(orderBy) == 0 {
orderBy = "star.id" orderBy = "updated_unix DESC"
} }
sess := x. sess := x.
Join("INNER", "star", "star.repo_id = repository.id"). Join("INNER", "star", "star.repo_id = repository.id").
Where("star.uid = ?", u.ID). Where("star.uid = ?", u.ID).
Desc(orderBy) OrderBy(orderBy)
if !private { if !private {
sess = sess.And("is_private = ?", false) sess = sess.And("is_private = ?", false)

@ -61,8 +61,8 @@ func TestUser_GetStarredRepos(t *testing.T) {
starred, err = user.GetStarredRepos(true, 1, 10, "") starred, err = user.GetStarredRepos(true, 1, 10, "")
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, starred, 2) assert.Len(t, starred, 2)
assert.Equal(t, int64(4), starred[0].ID) assert.Equal(t, int64(2), starred[0].ID)
assert.Equal(t, int64(2), starred[1].ID) assert.Equal(t, int64(4), starred[1].ID)
} }
func TestUser_GetStarredRepos2(t *testing.T) { func TestUser_GetStarredRepos2(t *testing.T) {

@ -90,6 +90,44 @@ func Profile(ctx *context.Context) {
tab := ctx.Query("tab") tab := ctx.Query("tab")
ctx.Data["TabName"] = tab ctx.Data["TabName"] = tab
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
var (
repos []*models.Repository
count int64
orderBy string
)
ctx.Data["SortType"] = ctx.Query("sort")
switch ctx.Query("sort") {
case "newest":
orderBy = "created_unix DESC"
case "oldest":
orderBy = "created_unix ASC"
case "recentupdate":
orderBy = "updated_unix DESC"
case "leastupdate":
orderBy = "updated_unix ASC"
case "reversealphabetically":
orderBy = "name DESC"
case "alphabetically":
orderBy = "name ASC"
default:
ctx.Data["SortType"] = "recentupdate"
orderBy = "updated_unix DESC"
}
// set default sort value if sort is empty.
if ctx.Query("sort") == "" {
ctx.Data["SortType"] = "recentupdate"
}
keyword := strings.Trim(ctx.Query("q"), " ")
ctx.Data["Keyword"] = keyword
switch tab { switch tab {
case "activity": case "activity":
retrieveFeeds(ctx, ctxUser, -1, 0, !showPrivate) retrieveFeeds(ctx, ctxUser, -1, 0, !showPrivate)
@ -97,66 +135,39 @@ func Profile(ctx *context.Context) {
return return
} }
case "stars": case "stars":
page := ctx.QueryInt("page") ctx.Data["PageIsProfileStarList"] = true
if page <= 0 { if len(keyword) == 0 {
page = 1 repos, err = ctxUser.GetStarredRepos(showPrivate, page, setting.UI.User.RepoPagingNum, orderBy)
} if err != nil {
ctx.Handle(500, "GetStarredRepos", err)
repos, err := ctxUser.GetStarredRepos(showPrivate, page, setting.UI.User.RepoPagingNum, "") return
if err != nil { }
ctx.Handle(500, "GetStarredRepos", err)
return
}
counts, err := ctxUser.GetStarredRepoCount(showPrivate) count, err = ctxUser.GetStarredRepoCount(showPrivate)
if err != nil { if err != nil {
ctx.Handle(500, "GetStarredRepoCount", err) ctx.Handle(500, "GetStarredRepoCount", err)
return return
}
} else {
repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
Keyword: keyword,
OwnerID: ctxUser.ID,
OrderBy: orderBy,
Private: showPrivate,
Page: page,
PageSize: setting.UI.User.RepoPagingNum,
Starred: true,
})
if err != nil {
ctx.Handle(500, "SearchRepositoryByName", err)
return
}
} }
ctx.Data["Repos"] = repos ctx.Data["Repos"] = repos
ctx.Data["Page"] = paginater.New(int(counts), setting.UI.User.RepoPagingNum, page, 5) ctx.Data["Page"] = paginater.New(int(count), setting.UI.User.RepoPagingNum, page, 5)
ctx.Data["Total"] = int(counts) ctx.Data["Total"] = count
ctx.Data["Tabs"] = "stars"
default: default:
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
var (
repos []*models.Repository
count int64
err error
orderBy string
)
ctx.Data["SortType"] = ctx.Query("sort")
switch ctx.Query("sort") {
case "newest":
orderBy = "created_unix DESC"
case "oldest":
orderBy = "created_unix ASC"
case "recentupdate":
orderBy = "updated_unix DESC"
case "leastupdate":
orderBy = "updated_unix ASC"
case "reversealphabetically":
orderBy = "name DESC"
case "alphabetically":
orderBy = "name ASC"
default:
ctx.Data["SortType"] = "recentupdate"
orderBy = "updated_unix DESC"
}
// set default sort value if sort is empty.
if ctx.Query("sort") == "" {
ctx.Data["SortType"] = "recentupdate"
}
keyword := strings.Trim(ctx.Query("q"), " ")
ctx.Data["Keyword"] = keyword
if len(keyword) == 0 { if len(keyword) == 0 {
var total int var total int
repos, err = models.GetUserRepositories(ctxUser.ID, showPrivate, page, setting.UI.User.RepoPagingNum, orderBy) repos, err = models.GetUserRepositories(ctxUser.ID, showPrivate, page, setting.UI.User.RepoPagingNum, orderBy)

@ -2,21 +2,21 @@
{{if gt .TotalPages 1}} {{if gt .TotalPages 1}}
<div class="center page buttons"> <div class="center page buttons">
<div class="ui borderless pagination menu"> <div class="ui borderless pagination menu">
<a class="{{if .IsFirst}}disabled{{end}} item" href="{{$.Link}}?q={{$.Keyword}}"><i class="angle double left icon"></i> {{$.i18n.Tr "admin.first_page"}}</a> <a class="{{if .IsFirst}}disabled{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&tab={{$.TabName}}"><i class="angle double left icon"></i> {{$.i18n.Tr "admin.first_page"}}</a>
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}&q={{$.Keyword}}&tab={{$.Tabs}}"{{end}}> <a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}&q={{$.Keyword}}&tab={{$.TabName}}"{{end}}>
<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} <i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}}
</a> </a>
{{range .Pages}} {{range .Pages}}
{{if eq .Num -1}} {{if eq .Num -1}}
<a class="disabled item">...</a> <a class="disabled item">...</a>
{{else}} {{else}}
<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}&q={{$.Keyword}}&tab={{$.Tabs}}"{{end}}>{{.Num}}</a> <a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}&q={{$.Keyword}}&tab={{$.TabName}}"{{end}}>{{.Num}}</a>
{{end}} {{end}}
{{end}} {{end}}
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}&q={{$.Keyword}}&tab={{$.Tabs}}"{{end}}> <a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}&q={{$.Keyword}}&tab={{$.TabName}}"{{end}}>
{{$.i18n.Tr "repo.issues.next"}}&nbsp;<i class="icon right arrow"></i> {{$.i18n.Tr "repo.issues.next"}}&nbsp;<i class="icon right arrow"></i>
</a> </a>
<a class="{{if .IsLast}}disabled{{end}} item" href="{{$.Link}}?page={{.TotalPages}}&q={{$.Keyword}}&tab={{$.Tabs}}">{{$.i18n.Tr "admin.last_page"}}&nbsp;<i class="angle double right icon"></i></a> <a class="{{if .IsLast}}disabled{{end}} item" href="{{$.Link}}?page={{.TotalPages}}&q={{$.Keyword}}&tab={{$.TabName}}">{{$.i18n.Tr "admin.last_page"}}&nbsp;<i class="angle double right icon"></i></a>
</div> </div>
</div> </div>
{{end}} {{end}}

@ -2,7 +2,7 @@
{{range .Repos}} {{range .Repos}}
<div class="item"> <div class="item">
<div class="ui header"> <div class="ui header">
<a class="name" href="{{AppSubUrl}}/{{if .Owner}}{{.Owner.Name}}{{else if $.Org}}{{$.Org.Name}}{{else}}{{$.Owner.Name}}{{end}}/{{.Name}}">{{if $.PageIsExplore}}{{.Owner.Name}} / {{end}}{{.Name}}</a> <a class="name" href="{{AppSubUrl}}/{{if .Owner}}{{.Owner.Name}}{{else if $.Org}}{{$.Org.Name}}{{else}}{{$.Owner.Name}}{{end}}/{{.Name}}">{{if or $.PageIsExplore $.PageIsProfileStarList }}{{.Owner.Name}} / {{end}}{{.Name}}</a>
{{if .IsPrivate}} {{if .IsPrivate}}
<span class="text gold"><i class="octicon octicon-lock"></i></span> <span class="text gold"><i class="octicon octicon-lock"></i></span>
{{else if .IsFork}} {{else if .IsFork}}

@ -6,18 +6,19 @@
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "newest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if or (eq .SortType "newest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> <a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> <a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div> </div>
</div> </div>
</div> </div>
<form class="ui form" style="max-width: 90%"> <form class="ui form" style="max-width: 90%">
<div class="ui fluid action input"> <div class="ui fluid action input">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus>
<input type="hidden" name="tab" value="{{$.TabName}}">
<button class="ui blue button">{{.i18n.Tr "explore.search"}}</button> <button class="ui blue button">{{.i18n.Tr "explore.search"}}</button>
</div> </div>
</form> </form>

@ -92,6 +92,7 @@
</div> </div>
{{else if eq .TabName "stars"}} {{else if eq .TabName "stars"}}
<div class="stars"> <div class="stars">
{{template "explore/search" .}}
{{template "explore/repo_list" .}} {{template "explore/repo_list" .}}
{{template "base/paginate" .}} {{template "base/paginate" .}}
</div> </div>

Loading…
Cancel
Save