Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Make multiple repositories selectable @ issues/PR page #6369

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
16222fe
Make repository list @ issues/PR page persist
Mar 19, 2019
14d711a
Enable multiple selections in repo list @ issues/PR page
Mar 19, 2019
95a0853
Remove redundant code
Mar 26, 2019
a555ce6
Merge branch 'master' into master
oscarlofwenhamn Mar 26, 2019
1da7a50
Merge branch 'master' into master
zeripath Mar 26, 2019
0fcd877
Merge branch 'master' into master
lunny Mar 27, 2019
fd7fa02
Merge branch 'master' into master
lunny Mar 27, 2019
6ab937d
Merge branch 'master' into master
techknowlogick Mar 27, 2019
662966b
Merge branch 'master' into master
Apr 1, 2019
070a7d1
Add 'All' button
Apr 1, 2019
827b3ff
Remove redundant variable
Apr 1, 2019
c1c2aab
Add RepoIDs to label link
Apr 5, 2019
f44626b
Merge branch 'master' into master
oscarlofwenhamn Apr 5, 2019
5351328
Merge branch 'master' into master
oscarlofwenhamn Apr 8, 2019
2a2efda
Merge branch 'master' into master
oscarlofwenhamn Apr 12, 2019
097e8d0
Merge branch 'origin/master' into master
May 9, 2019
72d602e
Revert part of code to previous version to troubleshoot build failure
May 9, 2019
ce103d7
Implement old and new pieces of code whilst adhering to multi select
May 9, 2019
1cc586f
Attempt to join the two versions
May 9, 2019
898a7bc
Update tests to desired state
May 9, 2019
11ce5ec
Merge branch 'master' into master
oscarlofwenhamn May 13, 2019
283ed33
Merge remote-tracking branch 'origin/master'
May 13, 2019
f476dc4
Fix pagination implementation and tests
May 13, 2019
5562f9b
Merge branch 'feature/multiselect-issue-repos'
May 13, 2019
6ef65ff
Correct behavior when passing zero to array
May 13, 2019
7038fdf
Merge remote-tracking branch 'origin/master'
May 15, 2019
8695d21
Merge remote-tracking branch 'origin/master'
May 20, 2019
a2179e6
Comment out test url returning 404
May 20, 2019
3fc7bb1
Comment out another test url returning 404
May 20, 2019
847510e
Merge branch 'master' into master
oscarlofwenhamn May 27, 2019
a4580a1
Reenable tests and test fix
May 27, 2019
0e0754b
Drop repo from repo map and total count if permission denied
May 27, 2019
e0f3579
Remove extra parenthesis
May 27, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,7 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) {
type UserIssueStatsOptions struct {
UserID int64
RepoID int64
RepoIDs []int64
UserRepoIDs []int64
FilterMode int
IsPull bool
Expand All @@ -1603,6 +1604,9 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"issue.repo_id": opts.RepoID})
}
if len(opts.RepoIDs) > 0 {
cond = cond.And(builder.In("issue.repo_id", opts.RepoIDs))
}

switch opts.FilterMode {
case FilterModeAll:
Expand Down
55 changes: 18 additions & 37 deletions routers/user/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ package user

import (
"bytes"
"fmt"
"sort"
"strconv"
"strings"

"code.gitea.io/gitea/models"
Expand Down Expand Up @@ -190,7 +190,15 @@ func Issues(ctx *context.Context) {
page = 1
}

repoID := ctx.QueryInt64("repo")
repoIDStrings := ctx.QueryStrings("repos[]")
var repoIDs []int64
for _, IDString := range repoIDStrings {
IDint64, err := strconv.ParseInt(IDString, 10, 64)
if err == nil {
repoIDs = append(repoIDs, IDint64)
}
}

isShowClosed := ctx.Query("state") == "closed"

// Get repositories.
Expand Down Expand Up @@ -228,14 +236,10 @@ func Issues(ctx *context.Context) {
SortType: sortType,
}

if repoID > 0 {
opts.RepoIDs = []int64{repoID}
}

switch filterMode {
case models.FilterModeAll:
if repoID > 0 {
if !com.IsSliceContainsInt64(userRepoIDs, repoID) {
if len(repoIDs) == 1 {
if !com.IsSliceContainsInt64(userRepoIDs, repoIDs[0]) {
// force an empty result
opts.RepoIDs = []int64{-1}
}
Expand Down Expand Up @@ -269,6 +273,10 @@ func Issues(ctx *context.Context) {
}
opts.LabelIDs = labelIDs

if len(repoIDs) > 0 {
opts.RepoIDs = repoIDs
}

issues, err := models.Issues(opts)
if err != nil {
ctx.ServerError("Issues", err)
Expand All @@ -285,33 +293,6 @@ func Issues(ctx *context.Context) {
showReposMap[repoID] = repo
}

if repoID > 0 {
if _, ok := showReposMap[repoID]; !ok {
repo, err := models.GetRepositoryByID(repoID)
if models.IsErrRepoNotExist(err) {
ctx.NotFound("GetRepositoryByID", err)
return
} else if err != nil {
ctx.ServerError("GetRepositoryByID", fmt.Errorf("[%d]%v", repoID, err))
return
}
showReposMap[repoID] = repo
}

repo := showReposMap[repoID]

// Check if user has access to given repository.
perm, err := models.GetUserRepoPermission(repo, ctxUser)
if err != nil {
ctx.ServerError("GetUserRepoPermission", fmt.Errorf("[%d]%v", repoID, err))
return
}
if !perm.CanRead(models.UnitTypeIssues) {
ctx.Status(404)
return
}
}

showRepos := models.RepositoryListOfMap(showReposMap)
sort.Sort(showRepos)
if err = showRepos.LoadAttributes(); err != nil {
Expand All @@ -325,7 +306,7 @@ func Issues(ctx *context.Context) {

issueStats, err := models.GetUserIssueStats(models.UserIssueStatsOptions{
UserID: ctxUser.ID,
RepoID: repoID,
RepoIDs: repoIDs,
UserRepoIDs: userRepoIDs,
FilterMode: filterMode,
IsPull: isPullList,
Expand All @@ -350,7 +331,7 @@ func Issues(ctx *context.Context) {
ctx.Data["IssueStats"] = issueStats
ctx.Data["ViewType"] = viewType
ctx.Data["SortType"] = sortType
ctx.Data["RepoID"] = repoID
ctx.Data["RepoIDs"] = repoIDs
ctx.Data["IsShowClosed"] = isShowClosed

if isShowClosed {
Expand Down
63 changes: 41 additions & 22 deletions templates/user/dashboard/issues.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,55 @@
<div class="ui stackable grid">
<div class="four wide column">
<div class="ui secondary vertical filter menu">
<a class="{{if eq .ViewType "your_repositories"}}ui basic blue button{{end}} item" href="{{.Link}}?type=your_repositories&repo={{.RepoID}}&sort={{$.SortType}}&state={{.State}}">
<a class="{{if eq .ViewType "your_repositories"}}ui basic blue button{{end}} item" href="{{.Link}}?type=your_repositories{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort={{$.SortType}}&state={{.State}}">
{{.i18n.Tr "home.issues.in_your_repos"}}
<strong class="ui right">{{.IssueStats.YourRepositoriesCount}}</strong>
</a>
{{if not .ContextUser.IsOrganization}}
<a class="{{if eq .ViewType "assigned"}}ui basic blue button{{end}} item" href="{{.Link}}?type=assigned&repo={{.RepoID}}&sort={{$.SortType}}&state={{.State}}">
<a class="{{if eq .ViewType "assigned"}}ui basic blue button{{end}} item" href="{{.Link}}?type=assigned{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort={{$.SortType}}&state={{.State}}">
{{.i18n.Tr "repo.issues.filter_type.assigned_to_you"}}
<strong class="ui right">{{.IssueStats.AssignCount}}</strong>
</a>
<a class="{{if eq .ViewType "created_by"}}ui basic blue button{{end}} item" href="{{.Link}}?type=created_by&repo={{.RepoID}}&sort={{$.SortType}}&state={{.State}}">
<a class="{{if eq .ViewType "created_by"}}ui basic blue button{{end}} item" href="{{.Link}}?type=created_by{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort={{$.SortType}}&state={{.State}}">
{{.i18n.Tr "repo.issues.filter_type.created_by_you"}}
<strong class="ui right">{{.IssueStats.CreateCount}}</strong>
</a>
{{end}}
<div class="ui divider"></div>
<a class="{{if not $.RepoIDs}}ui basic blue button{{end}} repo name item" href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}">
<span class="text truncate">All</span>
<div class="floating ui {{if $.IsShowClosed}}red{{else}}green{{end}} label">{{len .Repos}}</div>
</a>
{{range .Repos}}
<a class="{{if eq $.RepoID .ID}}ui basic blue button{{end}} repo name item" href="{{$.Link}}?type={{$.ViewType}}{{if not (eq $.RepoID .ID)}}&repo={{.ID}}{{end}}&sort={{$.SortType}}&state={{$.State}}">
<span class="text truncate">{{.FullName}}</span>
<div class="floating ui {{if $.IsShowClosed}}red{{else}}green{{end}} label">{{index $.Counts .ID}}</div>
</a>
{{with $Repo := .}}
<a class="{{range $.RepoIDs}}{{if eq . $Repo.ID}}ui basic blue button{{end}}{{end}} repo name item" href="{{$.Link}}?type={{$.ViewType}}
{{with $include := true}}
{{range $.RepoIDs}}
{{if eq . $Repo.ID}}
{{$include = false}}
{{else}}
&repos[]={{.}}
{{end}}
{{end}}
{{if eq $include true}}
&repos[]={{$Repo.ID}}
{{end}}
{{end}}
&sort={{$.SortType}}&state={{$.State}}">
<span class="text truncate">{{$Repo.FullName}}</span>
<div class="floating ui {{if $.IsShowClosed}}red{{else}}green{{end}} label">{{index $.Counts $Repo.ID}}</div>
</a>
{{end}}
{{end}}
</div>
</div>
<div class="twelve wide column content">
<div class="ui tiny basic status buttons">
<a class="ui {{if not .IsShowClosed}}green active{{end}} basic button" href="{{.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort={{$.SortType}}&state=open">
<a class="ui {{if not .IsShowClosed}}green active{{end}} basic button" href="{{.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort={{$.SortType}}&state=open">
<i class="octicon octicon-issue-opened"></i>
{{.i18n.Tr "repo.issues.open_tab" .IssueStats.OpenCount}}
</a>
<a class="ui {{if .IsShowClosed}}red active{{end}} basic button" href="{{.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort={{$.SortType}}&state=closed">
<a class="ui {{if .IsShowClosed}}red active{{end}} basic button" href="{{.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort={{$.SortType}}&state=closed">
<i class="octicon octicon-issue-closed"></i>
{{.i18n.Tr "repo.issues.close_tab" .IssueStats.ClosedCount}}
</a>
Expand All @@ -47,14 +66,14 @@
<i class="dropdown icon"></i>
</span>
<div class="menu">
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=latest&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=oldest&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=recentupdate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=leastupdate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=mostcomment&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=leastcomment&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=nearduedate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}&repo={{.RepoID}}&sort=farduedate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.farduedate"}}</a>
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=latest&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=oldest&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=recentupdate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=leastupdate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=mostcomment&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=leastcomment&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=nearduedate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active{{end}} item" href="{{$.Link}}?type={{$.ViewType}}{{range $.RepoIDs}}&repos[]={{.}}{{end}}&sort=farduedate&state={{$.State}}">{{.i18n.Tr "repo.issues.filter_sort.farduedate"}}</a>
</div>
</div>
</div>
Expand All @@ -63,7 +82,7 @@
{{range .Issues}}
{{ $timeStr:= TimeSinceUnix .CreatedUnix $.Lang }}
<li class="item">
<div class="ui label">{{if not $.RepoID}}{{.Repo.FullName}}{{end}}#{{.Index}}</div>
<div class="ui label">{{.Repo.FullName}}#{{.Index}}</div>
<a class="title has-emoji" href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Title}}</a>

{{with .Labels}}
Expand All @@ -73,7 +92,7 @@
especially on mobile views. */}}
<span style="line-height: 2.5">
{{range .}}
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&repo={{$.RepoID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
{{end}}
</span>
{{end}}
Expand Down Expand Up @@ -111,17 +130,17 @@
{{if gt .TotalPages 1}}
<div class="center page buttons">
<div class="ui borderless pagination menu">
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?type={{$.ViewType}}&repo={{$.RepoID}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&page={{.Previous}}"{{end}}>
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&page={{.Previous}}"{{end}}>
<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}}
</a>
{{range .Pages}}
{{if eq .Num -1}}
<a class="disabled item">...</a>
{{else}}
<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?type={{$.ViewType}}&repo={{$.RepoID}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&page={{.Num}}"{{end}}>{{.Num}}</a>
<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&page={{.Num}}"{{end}}>{{.Num}}</a>
{{end}}
{{end}}
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?type={{$.ViewType}}&repo={{$.RepoID}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&page={{.Next}}"{{end}}>
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{$.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&page={{.Next}}"{{end}}>
{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i>
</a>
</div>
Expand Down