Skip to content

Commit 84b5ab0

Browse files
committed
Display badge on blocked & blocking issues
1 parent 4e10adc commit 84b5ab0

File tree

6 files changed

+172
-0
lines changed

6 files changed

+172
-0
lines changed

models/issues/issue_list.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,74 @@ func (issues IssueList) LoadDiscussComments(ctx context.Context) error {
559559
return issues.loadComments(ctx, builder.Eq{"comment.type": CommentTypeComment})
560560
}
561561

562+
// GetBlockedByCounts returns a map of issue ID to number of open issues that are blocking it
563+
func (issues IssueList) GetBlockedByCount(ctx context.Context) (map[int64]int64, error) {
564+
type BlockedByCount struct {
565+
IssueID int64
566+
Count int64
567+
}
568+
569+
bCounts := make([]*BlockedByCount, len(issues))
570+
ids := make([]int64, len(issues))
571+
for i, issue := range issues {
572+
ids[i] = issue.ID
573+
}
574+
575+
sess := db.GetEngine(ctx).In("issue_id", ids)
576+
err := sess.Select("issue_id, count(issue_dependency.id) as `count`").
577+
Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
578+
Where("is_closed = ?", false).
579+
GroupBy("issue_id").
580+
OrderBy("issue_id").
581+
Table("issue_dependency").
582+
Find(&bCounts)
583+
if err != nil {
584+
return nil, err
585+
}
586+
587+
blockedByCountMap := make(map[int64]int64, len(issues))
588+
for _, c := range bCounts {
589+
if c != nil {
590+
blockedByCountMap[c.IssueID] = c.Count
591+
}
592+
}
593+
594+
return blockedByCountMap, nil
595+
}
596+
597+
// GetBlockingCounts returns a map of issue ID to number of issues that are blocked by it
598+
func (issues IssueList) GetBlockingCount(ctx context.Context) (map[int64]int64, error) {
599+
type BlockingCount struct {
600+
IssueID int64
601+
Count int64
602+
}
603+
604+
bCounts := make([]*BlockingCount, 0, len(issues))
605+
ids := make([]int64, len(issues))
606+
for i, issue := range issues {
607+
ids[i] = issue.ID
608+
}
609+
610+
sess := db.GetEngine(ctx).In("dependency_id", ids)
611+
err := sess.Select("dependency_id as `issue_id`, count(id) as `count`").
612+
GroupBy("dependency_id").
613+
OrderBy("dependency_id").
614+
Table("issue_dependency").
615+
Find(&bCounts)
616+
if err != nil {
617+
return nil, err
618+
}
619+
620+
blockingCountMap := make(map[int64]int64, len(issues))
621+
for _, c := range bCounts {
622+
if c != nil {
623+
blockingCountMap[c.IssueID] = c.Count
624+
}
625+
}
626+
627+
return blockingCountMap, nil
628+
}
629+
562630
// GetApprovalCounts returns a map of issue ID to slice of approval counts
563631
// FIXME: only returns official counts due to double counting of non-official approvals
564632
func (issues IssueList) GetApprovalCounts(ctx context.Context) (map[int64][]*ReviewCount, error) {

options/locale/locale_en-US.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,6 +1793,10 @@ issues.dependency.add_error_dep_not_exist = Dependency does not exist.
17931793
issues.dependency.add_error_dep_exists = Dependency already exists.
17941794
issues.dependency.add_error_cannot_create_circular = You cannot create a dependency with two issues blocking each other.
17951795
issues.dependency.add_error_dep_not_same_repo = Both issues must be in the same repository.
1796+
issues.dependency.blocking_count_1 = "This issue is blocking %d other issue."
1797+
issues.dependency.blocking_count_n = "This issue is blocking %d other issues."
1798+
issues.dependency.blocked_by_count_1 = "This issue is blocked by %d issue."
1799+
issues.dependency.blocked_by_count_n = "This issue is blocked by %d issues."
17961800
issues.review.self.approval = You cannot approve your own pull request.
17971801
issues.review.self.rejection = You cannot request changes on your own pull request.
17981802
issues.review.approve = "approved these changes %s"

routers/web/repo/issue_list.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,18 @@ func prepareIssueFilterAndList(ctx *context.Context, milestoneID, projectID int6
654654
return
655655
}
656656

657+
blockingCounts, err := issues.GetBlockingCount(ctx)
658+
if err != nil {
659+
ctx.ServerError("BlockingCounts", err)
660+
return
661+
}
662+
663+
blockedByCounts, err := issues.GetBlockedByCount(ctx)
664+
if err != nil {
665+
ctx.ServerError("BlockedByCounts", err)
666+
return
667+
}
668+
657669
if ctx.IsSigned {
658670
if err := issues.LoadIsRead(ctx, ctx.Doer.ID); err != nil {
659671
ctx.ServerError("LoadIsRead", err)
@@ -718,6 +730,21 @@ func prepareIssueFilterAndList(ctx *context.Context, milestoneID, projectID int6
718730
return 0
719731
}
720732

733+
ctx.Data["BlockingCounts"] = func(issueID int64) int64 {
734+
counts, ok := blockingCounts[issueID]
735+
if !ok {
736+
return 0
737+
}
738+
return counts
739+
}
740+
ctx.Data["BlockedByCounts"] = func(issueID int64) int64 {
741+
counts, ok := blockedByCounts[issueID]
742+
if !ok {
743+
return 0
744+
}
745+
return counts
746+
}
747+
721748
retrieveProjectsForIssueList(ctx, repo)
722749
if ctx.Written() {
723750
return

routers/web/user/home.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,33 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
627627
}
628628
return 0
629629
}
630+
631+
blockingCounts, err := issues.GetBlockingCount(ctx)
632+
if err != nil {
633+
ctx.ServerError("BlockingCounts", err)
634+
return
635+
}
636+
637+
blockedByCounts, err := issues.GetBlockedByCount(ctx)
638+
if err != nil {
639+
ctx.ServerError("BlockedByCounts", err)
640+
return
641+
}
642+
ctx.Data["BlockingCounts"] = func(issueID int64) int64 {
643+
counts, ok := blockingCounts[issueID]
644+
if !ok {
645+
return 0
646+
}
647+
return counts
648+
}
649+
ctx.Data["BlockedByCounts"] = func(issueID int64) int64 {
650+
counts, ok := blockedByCounts[issueID]
651+
if !ok {
652+
return 0
653+
}
654+
return counts
655+
}
656+
630657
ctx.Data["CommitLastStatus"] = lastStatus
631658
ctx.Data["CommitStatuses"] = commitStatuses
632659
ctx.Data["IssueStats"] = issueStats

routers/web/user/notification.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,32 @@ func NotificationSubscriptions(ctx *context.Context) {
311311
return 0
312312
}
313313

314+
blockingCounts, err := issues.GetBlockingCount(ctx)
315+
if err != nil {
316+
ctx.ServerError("BlockingCounts", err)
317+
return
318+
}
319+
320+
blockedByCounts, err := issues.GetBlockedByCount(ctx)
321+
if err != nil {
322+
ctx.ServerError("BlockedByCounts", err)
323+
return
324+
}
325+
ctx.Data["BlockingCounts"] = func(issueID int64) int64 {
326+
counts, ok := blockingCounts[issueID]
327+
if !ok {
328+
return 0
329+
}
330+
return counts
331+
}
332+
ctx.Data["BlockedByCounts"] = func(issueID int64) int64 {
333+
counts, ok := blockedByCounts[issueID]
334+
if !ok {
335+
return 0
336+
}
337+
return counts
338+
}
339+
314340
ctx.Data["Status"] = 1
315341
ctx.Data["Title"] = ctx.Tr("notification.subscriptions")
316342

templates/shared/issuelist.tmpl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<div id="issue-list" class="flex-list">
22
{{$approvalCounts := .ApprovalCounts}}
3+
{{$blockedByCounts := .BlockedByCounts}}
4+
{{$blockingCounts := .BlockingCounts}}
35
{{range .Issues}}
6+
{{$blockedByCount := call $blockedByCounts .ID}}
7+
{{$blockingCount := call $blockingCounts .ID}}
48
<div class="flex-item">
59

610
<div class="flex-item-leading">
@@ -22,6 +26,22 @@
2226
{{template "repo/commit_statuses" dict "Status" (index $.CommitLastStatus .PullRequest.ID) "Statuses" (index $.CommitStatuses .PullRequest.ID)}}
2327
{{end}}
2428
{{end}}
29+
{{if gt $blockedByCount 0}}
30+
<div class="ui label tw-mx-1 tw-border tw-border-secondary" style="background: none;">
31+
<span data-tooltip-content="{{ctx.Locale.TrN $blockedByCount "repo.issues.dependency.blocked_by_count_1" "repo.issues.dependency.blocked_by_count_n" $blockedByCount}}" class="text red flex-text-block">
32+
{{svg "octicon-blocked" 16}}
33+
{{$blockedByCount}}
34+
</span>
35+
</div>
36+
{{end}}
37+
{{if and (gt $blockingCount 0) (not .IsClosed)}}
38+
<div class="ui label tw-mx-1 tw-border tw-border-secondary" style="background: none;">
39+
<span data-tooltip-content="{{ctx.Locale.TrN $blockingCount "repo.issues.dependency.blocking_count_1" "repo.issues.dependency.blocking_count_n" $blockingCount}}" class="text red flex-text-block">
40+
{{svg "octicon-report" 16}}
41+
{{$blockingCount}}
42+
</span>
43+
</div>
44+
{{end}}
2545
<span class="labels-list">
2646
{{range .Labels}}
2747
<a href="?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}{{if ne $.listType "milestone"}}&milestone={{$.MilestoneID}}{{end}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}{{if $.ShowArchivedLabels}}&archived=true{{end}}">{{ctx.RenderUtils.RenderLabel .}}</a>

0 commit comments

Comments
 (0)