aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--models/issue.go62
-rw-r--r--routers/repo/issue.go2
-rw-r--r--routers/user/home.go165
-rw-r--r--templates/user/dashboard/issues.tmpl8
4 files changed, 142 insertions, 95 deletions
diff --git a/models/issue.go b/models/issue.go
index 161ff188..1081695a 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -1069,7 +1069,7 @@ func updateIssueMentions(e Engine, issueID int64, mentions []string) error {
// IssueStats represents issue statistic information.
type IssueStats struct {
OpenCount, ClosedCount int64
- AllCount int64
+ YourRepositoriesCount int64
AssignCount int64
CreateCount int64
MentionCount int64
@@ -1077,7 +1077,7 @@ type IssueStats struct {
// Filter modes.
const (
- FM_ALL = iota
+ FM_YOUR_REPOSITORIES = iota
FM_ASSIGN
FM_CREATE
FM_MENTION
@@ -1129,38 +1129,38 @@ func GetIssueStats(opts *IssueStatsOptions) *IssueStats {
}
switch opts.FilterMode {
- case FM_ALL, FM_ASSIGN:
+ case FM_YOUR_REPOSITORIES, FM_ASSIGN:
stats.OpenCount, _ = countSession(opts).
And("is_closed = ?", false).
- Count(&Issue{})
+ Count(new(Issue))
stats.ClosedCount, _ = countSession(opts).
And("is_closed = ?", true).
- Count(&Issue{})
+ Count(new(Issue))
case FM_CREATE:
stats.OpenCount, _ = countSession(opts).
And("poster_id = ?", opts.UserID).
And("is_closed = ?", false).
- Count(&Issue{})
+ Count(new(Issue))
stats.ClosedCount, _ = countSession(opts).
And("poster_id = ?", opts.UserID).
And("is_closed = ?", true).
- Count(&Issue{})
+ Count(new(Issue))
case FM_MENTION:
stats.OpenCount, _ = countSession(opts).
Join("INNER", "issue_user", "issue.id = issue_user.issue_id").
And("issue_user.uid = ?", opts.UserID).
And("issue_user.is_mentioned = ?", true).
And("issue.is_closed = ?", false).
- Count(&Issue{})
+ Count(new(Issue))
stats.ClosedCount, _ = countSession(opts).
Join("INNER", "issue_user", "issue.id = issue_user.issue_id").
And("issue_user.uid = ?", opts.UserID).
And("issue_user.is_mentioned = ?", true).
And("issue.is_closed = ?", true).
- Count(&Issue{})
+ Count(new(Issue))
}
return stats
}
@@ -1172,38 +1172,48 @@ func GetUserIssueStats(repoID, uid int64, repoIDs []int64, filterMode int, isPul
countSession := func(isClosed, isPull bool, repoID int64, repoIDs []int64) *xorm.Session {
sess := x.Where("issue.is_closed = ?", isClosed).And("issue.is_pull = ?", isPull)
- if repoID > 0 || len(repoIDs) == 0 {
+ if repoID > 0 {
sess.And("repo_id = ?", repoID)
- } else {
+ } else if repoIDs != nil {
sess.In("repo_id", repoIDs)
}
return sess
}
- stats.AssignCount, _ = countSession(false, isPull, repoID, repoIDs).
+ stats.AssignCount, _ = countSession(false, isPull, repoID, nil).
And("assignee_id = ?", uid).
- Count(&Issue{})
+ Count(new(Issue))
- stats.CreateCount, _ = countSession(false, isPull, repoID, repoIDs).
+ stats.CreateCount, _ = countSession(false, isPull, repoID, nil).
And("poster_id = ?", uid).
- Count(&Issue{})
+ Count(new(Issue))
- openCountSession := countSession(false, isPull, repoID, repoIDs)
- closedCountSession := countSession(true, isPull, repoID, repoIDs)
+ stats.YourRepositoriesCount, _ = countSession(false, isPull, repoID, repoIDs).
+ Count(new(Issue))
switch filterMode {
+ case FM_YOUR_REPOSITORIES:
+ stats.OpenCount, _ = countSession(false, isPull, repoID, repoIDs).
+ Count(new(Issue))
+ stats.ClosedCount, _ = countSession(true, isPull, repoID, repoIDs).
+ Count(new(Issue))
case FM_ASSIGN:
- openCountSession.And("assignee_id = ?", uid)
- closedCountSession.And("assignee_id = ?", uid)
+ stats.OpenCount, _ = countSession(false, isPull, repoID, nil).
+ And("assignee_id = ?", uid).
+ Count(new(Issue))
+ stats.ClosedCount, _ = countSession(true, isPull, repoID, nil).
+ And("assignee_id = ?", uid).
+ Count(new(Issue))
case FM_CREATE:
- openCountSession.And("poster_id = ?", uid)
- closedCountSession.And("poster_id = ?", uid)
+ stats.OpenCount, _ = countSession(false, isPull, repoID, nil).
+ And("poster_id = ?", uid).
+ Count(new(Issue))
+ stats.ClosedCount, _ = countSession(true, isPull, repoID, nil).
+ And("poster_id = ?", uid).
+ Count(new(Issue))
}
- stats.OpenCount, _ = openCountSession.Count(&Issue{})
- stats.ClosedCount, _ = closedCountSession.Count(&Issue{})
-
return stats
}
@@ -1229,8 +1239,8 @@ func GetRepoIssueStats(repoID, uid int64, filterMode int, isPull bool) (numOpen
closedCountSession.And("poster_id = ?", uid)
}
- openResult, _ := openCountSession.Count(&Issue{})
- closedResult, _ := closedCountSession.Count(&Issue{})
+ openResult, _ := openCountSession.Count(new(Issue))
+ closedResult, _ := closedCountSession.Count(new(Issue))
return openResult, closedResult
}
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index ad2d1fdf..3f0f6195 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -121,7 +121,7 @@ func Issues(ctx *context.Context) {
assigneeID = ctx.QueryInt64("assignee")
posterID int64
)
- filterMode := models.FM_ALL
+ filterMode := models.FM_YOUR_REPOSITORIES
switch viewType {
case "assigned":
filterMode = models.FM_ASSIGN
diff --git a/routers/user/home.go b/routers/user/home.go
index 83b4b261..df178a93 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -172,35 +172,39 @@ func Issues(ctx *context.Context) {
var (
viewType string
sortType = ctx.Query("sort")
- filterMode = models.FM_ALL
- assigneeID int64
- posterID int64
+ filterMode = models.FM_YOUR_REPOSITORIES
)
if ctxUser.IsOrganization() {
- viewType = "all"
+ viewType = "your_repositories"
} else {
viewType = ctx.Query("type")
- types := []string{"assigned", "created_by"}
+ types := []string{"your_repositories", "assigned", "created_by"}
if !com.IsSliceContainsStr(types, viewType) {
- viewType = "all"
+ viewType = "your_repositories"
}
switch viewType {
+ case "your_repositories":
+ filterMode = models.FM_YOUR_REPOSITORIES
case "assigned":
filterMode = models.FM_ASSIGN
- assigneeID = ctxUser.ID
case "created_by":
filterMode = models.FM_CREATE
- posterID = ctxUser.ID
}
}
+ page := ctx.QueryInt("page")
+ if page <= 1 {
+ page = 1
+ }
+
repoID := ctx.QueryInt64("repo")
isShowClosed := ctx.Query("state") == "closed"
// Get repositories.
var err error
var repos []*models.Repository
+ userRepoIDs := make([]int64, 0, len(repos))
if ctxUser.IsOrganization() {
repos, _, err = ctxUser.GetUserRepositories(ctx.User.ID, 1, ctxUser.NumRepos)
if err != nil {
@@ -215,9 +219,6 @@ func Issues(ctx *context.Context) {
repos = ctxUser.Repos
}
- allCount := 0
- repoIDs := make([]int64, 0, len(repos))
- showRepos := make([]*models.Repository, 0, len(repos))
for _, repo := range repos {
if (isPullList && repo.NumPulls == 0) ||
(!isPullList &&
@@ -225,83 +226,119 @@ func Issues(ctx *context.Context) {
continue
}
- repoIDs = append(repoIDs, repo.ID)
+ userRepoIDs = append(userRepoIDs, repo.ID)
+ }
- if isPullList {
- allCount += repo.NumOpenPulls
- repo.NumOpenIssues = repo.NumOpenPulls
- repo.NumClosedIssues = repo.NumClosedPulls
- } else {
- allCount += repo.NumOpenIssues
+ var issues []*models.Issue
+ switch filterMode {
+ case models.FM_YOUR_REPOSITORIES:
+ // Get all issues from repositories from this user.
+ issues, err = models.Issues(&models.IssuesOptions{
+ RepoIDs: userRepoIDs,
+ RepoID: repoID,
+ Page: page,
+ IsClosed: isShowClosed,
+ IsPull: isPullList,
+ SortType: sortType,
+ })
+
+ case models.FM_ASSIGN:
+ // Get all issues assigned to this user.
+ issues, err = models.Issues(&models.IssuesOptions{
+ RepoID: repoID,
+ AssigneeID: ctxUser.ID,
+ Page: page,
+ IsClosed: isShowClosed,
+ IsPull: isPullList,
+ SortType: sortType,
+ })
+
+ case models.FM_CREATE:
+ // Get all issues created by this user.
+ issues, err = models.Issues(&models.IssuesOptions{
+ RepoID: repoID,
+ PosterID: ctxUser.ID,
+ Page: page,
+ IsClosed: isShowClosed,
+ IsPull: isPullList,
+ SortType: sortType,
+ })
+ }
+
+ if err != nil {
+ ctx.Handle(500, "Issues", err)
+ return
+ }
+
+ showRepos := make([]*models.Repository, 0, len(issues))
+ showReposSet := make(map[int64]bool)
+
+ if repoID > 0 {
+ repo, err := models.GetRepositoryByID(repoID)
+ if err != nil {
+ ctx.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d]%v", repoID, err))
+ return
}
- if filterMode != models.FM_ALL {
- // Calculate repository issue count with filter mode.
- numOpen, numClosed := repo.IssueStats(ctxUser.ID, filterMode, isPullList)
- repo.NumOpenIssues, repo.NumClosedIssues = int(numOpen), int(numClosed)
+ if err = repo.GetOwner(); err != nil {
+ ctx.Handle(500, "GetOwner", fmt.Errorf("[#%d]%v", repoID, err))
+ return
}
- if repo.ID == repoID ||
- (isShowClosed && repo.NumClosedIssues > 0) ||
- (!isShowClosed && repo.NumOpenIssues > 0) {
- showRepos = append(showRepos, repo)
+ // Check if user has access to given repository.
+ if !repo.IsOwnedBy(ctxUser.ID) && !repo.HasAccess(ctxUser) {
+ ctx.Handle(404, "Issues", fmt.Errorf("#%d", repoID))
+ return
}
+
+ showReposSet[repoID] = true
+ showRepos = append(showRepos, repo)
}
- ctx.Data["Repos"] = showRepos
- issueStats := models.GetUserIssueStats(repoID, ctxUser.ID, repoIDs, filterMode, isPullList)
- issueStats.AllCount = int64(allCount)
+ for _, issue := range issues {
+ // Get Repository data.
+ issue.Repo, err = models.GetRepositoryByID(issue.RepoID)
+ if err != nil {
+ ctx.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d]%v", issue.RepoID, err))
+ return
+ }
- page := ctx.QueryInt("page")
- if page <= 1 {
- page = 1
+ // Get Owner data.
+ if err = issue.Repo.GetOwner(); err != nil {
+ ctx.Handle(500, "GetOwner", fmt.Errorf("[#%d]%v", issue.RepoID, err))
+ return
+ }
+
+ // Append repo to list of shown repos
+ if filterMode == models.FM_YOUR_REPOSITORIES {
+ // Use a map to make sure we don't add the same Repository twice.
+ _, ok := showReposSet[issue.RepoID]
+ if !ok {
+ showReposSet[issue.RepoID] = true
+ // Append to list of shown Repositories.
+ showRepos = append(showRepos, issue.Repo)
+ }
+ }
}
+ issueStats := models.GetUserIssueStats(repoID, ctxUser.ID, userRepoIDs, filterMode, isPullList)
+
var total int
if !isShowClosed {
total = int(issueStats.OpenCount)
} else {
total = int(issueStats.ClosedCount)
}
- ctx.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5)
- // Get issues.
- issues, err := models.Issues(&models.IssuesOptions{
- UserID: ctxUser.ID,
- AssigneeID: assigneeID,
- RepoID: repoID,
- PosterID: posterID,
- RepoIDs: repoIDs,
- Page: page,
- IsClosed: isShowClosed,
- IsPull: isPullList,
- SortType: sortType,
- })
- if err != nil {
- ctx.Handle(500, "Issues", err)
- return
- }
-
- // Get posters and repository.
- for i := range issues {
- issues[i].Repo, err = models.GetRepositoryByID(issues[i].RepoID)
- if err != nil {
- ctx.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d]%v", issues[i].ID, err))
- return
- }
-
- if err = issues[i].Repo.GetOwner(); err != nil {
- ctx.Handle(500, "GetOwner", fmt.Errorf("[#%d]%v", issues[i].ID, err))
- return
- }
- }
ctx.Data["Issues"] = issues
-
+ ctx.Data["Repos"] = showRepos
+ ctx.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5)
ctx.Data["IssueStats"] = issueStats
ctx.Data["ViewType"] = viewType
ctx.Data["SortType"] = sortType
ctx.Data["RepoID"] = repoID
ctx.Data["IsShowClosed"] = isShowClosed
+
if isShowClosed {
ctx.Data["State"] = "closed"
} else {
diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl
index 5aae8b4f..1497935a 100644
--- a/templates/user/dashboard/issues.tmpl
+++ b/templates/user/dashboard/issues.tmpl
@@ -5,9 +5,9 @@
<div class="ui grid">
<div class="four wide column">
<div class="ui secondary vertical filter menu">
- <a class="{{if eq .ViewType "all"}}ui basic blue button{{end}} item" href="{{.Link}}?repo={{.RepoID}}&sort={{$.SortType}}&state={{.State}}">
+ <a class="{{if eq .ViewType "your_repositories"}}ui basic blue button{{end}} item" href="{{.Link}}?type=your_repositories&repo={{.RepoID}}&sort={{$.SortType}}&state={{.State}}">
{{.i18n.Tr "home.issues.in_your_repos"}}
- <strong class="ui right">{{.IssueStats.AllCount}}</strong>
+ <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}}">
@@ -22,7 +22,7 @@
<div class="ui divider"></div>
{{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">{{$.ContextUser.Name}}/{{.Name}}</span>
+ <span class="text truncate">{{.FullName}}</span>
<div class="floating ui {{if $.IsShowClosed}}red{{else}}green{{end}} label">{{if $.IsShowClosed}}{{.NumClosedIssues}}{{else}}{{.NumOpenIssues}}{{end}}</div>
</a>
{{end}}
@@ -61,7 +61,7 @@
{{range .Issues}}
{{ $timeStr:= TimeSince .Created $.Lang }}
<li class="item">
- <div class="ui label">{{if not $.RepoID}}{{.Repo.Name}}{{end}}#{{.Index}}</div>
+ <div class="ui label">{{if not $.RepoID}}{{.Repo.FullName}}{{end}}#{{.Index}}</div>
<a class="title has-emoji" href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Title}}</a>
{{if .NumComments}}