mirror of
https://github.com/go-gitea/gitea.git
synced 2025-10-27 05:55:21 +08:00
Compare commits
4 Commits
a0cfdba312
...
96caadc99b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96caadc99b | ||
|
|
bc50431e8b | ||
|
|
2a6af15448 | ||
|
|
fc4b73eac9 |
2
go.mod
2
go.mod
@ -109,7 +109,7 @@ require (
|
||||
github.com/ulikunitz/xz v0.5.15
|
||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha6
|
||||
github.com/urfave/cli/v3 v3.4.1
|
||||
github.com/wneessen/go-mail v0.7.1
|
||||
github.com/wneessen/go-mail v0.7.2
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/yohcop/openid-go v1.0.1
|
||||
github.com/yuin/goldmark v1.7.13
|
||||
|
||||
4
go.sum
4
go.sum
@ -768,8 +768,8 @@ github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZ
|
||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/wneessen/go-mail v0.7.1 h1:rvy63sp14N06/kdGqCYwW8Na5gDCXjTQM1E7So4PuKk=
|
||||
github.com/wneessen/go-mail v0.7.1/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
|
||||
github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8=
|
||||
github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
|
||||
@ -559,6 +559,74 @@ func (issues IssueList) LoadDiscussComments(ctx context.Context) error {
|
||||
return issues.loadComments(ctx, builder.Eq{"comment.type": CommentTypeComment})
|
||||
}
|
||||
|
||||
// GetBlockedByCounts returns a map of issue ID to number of open issues that are blocking it
|
||||
func (issues IssueList) GetBlockedByCount(ctx context.Context) (map[int64]int64, error) {
|
||||
type BlockedByCount struct {
|
||||
IssueID int64
|
||||
Count int64
|
||||
}
|
||||
|
||||
bCounts := make([]*BlockedByCount, len(issues))
|
||||
ids := make([]int64, len(issues))
|
||||
for i, issue := range issues {
|
||||
ids[i] = issue.ID
|
||||
}
|
||||
|
||||
sess := db.GetEngine(ctx).In("issue_id", ids)
|
||||
err := sess.Select("issue_id, count(issue_dependency.id) as `count`").
|
||||
Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
|
||||
Where("is_closed = ?", false).
|
||||
GroupBy("issue_id").
|
||||
OrderBy("issue_id").
|
||||
Table("issue_dependency").
|
||||
Find(&bCounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockedByCountMap := make(map[int64]int64, len(issues))
|
||||
for _, c := range bCounts {
|
||||
if c != nil {
|
||||
blockedByCountMap[c.IssueID] = c.Count
|
||||
}
|
||||
}
|
||||
|
||||
return blockedByCountMap, nil
|
||||
}
|
||||
|
||||
// GetBlockingCounts returns a map of issue ID to number of issues that are blocked by it
|
||||
func (issues IssueList) GetBlockingCount(ctx context.Context) (map[int64]int64, error) {
|
||||
type BlockingCount struct {
|
||||
IssueID int64
|
||||
Count int64
|
||||
}
|
||||
|
||||
bCounts := make([]*BlockingCount, 0, len(issues))
|
||||
ids := make([]int64, len(issues))
|
||||
for i, issue := range issues {
|
||||
ids[i] = issue.ID
|
||||
}
|
||||
|
||||
sess := db.GetEngine(ctx).In("dependency_id", ids)
|
||||
err := sess.Select("dependency_id as `issue_id`, count(id) as `count`").
|
||||
GroupBy("dependency_id").
|
||||
OrderBy("dependency_id").
|
||||
Table("issue_dependency").
|
||||
Find(&bCounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockingCountMap := make(map[int64]int64, len(issues))
|
||||
for _, c := range bCounts {
|
||||
if c != nil {
|
||||
blockingCountMap[c.IssueID] = c.Count
|
||||
}
|
||||
}
|
||||
|
||||
return blockingCountMap, nil
|
||||
}
|
||||
|
||||
// GetApprovalCounts returns a map of issue ID to slice of approval counts
|
||||
// FIXME: only returns official counts due to double counting of non-official approvals
|
||||
func (issues IssueList) GetApprovalCounts(ctx context.Context) (map[int64][]*ReviewCount, error) {
|
||||
|
||||
@ -3586,6 +3586,7 @@ variables.update.success=Proměnná byla upravena.
|
||||
logs.always_auto_scroll=Vždy automaticky posouvat logy
|
||||
logs.always_expand_running=Vždy rozšířit běžící logy
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Odstraněný projekt
|
||||
type-1.display_name=Samostatný projekt
|
||||
|
||||
@ -3645,6 +3645,7 @@ variables.update.success=Die Variable wurde bearbeitet.
|
||||
logs.always_auto_scroll=Autoscroll für Logs immer aktivieren
|
||||
logs.always_expand_running=Laufende Logs immer erweitern
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Gelöschtes Projekt
|
||||
type-1.display_name=Individuelles Projekt
|
||||
|
||||
@ -3280,6 +3280,7 @@ variables.update.failed=Αποτυχία επεξεργασίας μεταβλη
|
||||
variables.update.success=Η μεταβλητή έχει τροποποιηθεί.
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
type-1.display_name=Ατομικό Έργο
|
||||
type-2.display_name=Έργο Αποθετηρίου
|
||||
|
||||
@ -1806,6 +1806,10 @@ issues.dependency.add_error_dep_not_exist = Dependency does not exist.
|
||||
issues.dependency.add_error_dep_exists = Dependency already exists.
|
||||
issues.dependency.add_error_cannot_create_circular = You cannot create a dependency with two issues that block each other.
|
||||
issues.dependency.add_error_dep_not_same_repo = Both issues must be in the same repository.
|
||||
issues.dependency.blocking_count_1 = "This issue is blocking %d other issue."
|
||||
issues.dependency.blocking_count_n = "This issue is blocking %d other issues."
|
||||
issues.dependency.blocked_by_count_1 = "This issue is blocked by %d issue."
|
||||
issues.dependency.blocked_by_count_n = "This issue is blocked by %d issues."
|
||||
issues.review.self.approval = You cannot approve your own pull request.
|
||||
issues.review.self.rejection = You cannot request changes on your own pull request.
|
||||
issues.review.approve = "approved these changes %s"
|
||||
|
||||
@ -3257,6 +3257,7 @@ variables.update.failed=Error al editar la variable.
|
||||
variables.update.success=La variable ha sido editada.
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
type-1.display_name=Proyecto individual
|
||||
type-2.display_name=Proyecto repositorio
|
||||
|
||||
@ -2446,6 +2446,7 @@ runs.commit=کامیت
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -1693,6 +1693,7 @@ runs.commit=Commit
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -3906,6 +3906,7 @@ variables.update.success=La variable a bien été modifiée.
|
||||
logs.always_auto_scroll=Toujours faire défiler les journaux automatiquement
|
||||
logs.always_expand_running=Toujours développer les journaux en cours
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Projet supprimé
|
||||
type-1.display_name=Projet personnel
|
||||
|
||||
@ -3914,6 +3914,7 @@ variables.update.success=Tá an t-athróg curtha in eagar.
|
||||
logs.always_auto_scroll=Logchomhaid scrollaithe uathoibríoch i gcónaí
|
||||
logs.always_expand_running=Leathnaigh logs reatha i gcónaí
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Tionscadal scriosta
|
||||
type-1.display_name=Tionscadal Aonair
|
||||
|
||||
@ -1605,6 +1605,7 @@ runs.commit=Commit
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -1428,6 +1428,7 @@ variables.update.failed=Gagal mengedit variabel.
|
||||
variables.update.success=Variabel telah diedit.
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
type-1.display_name=Proyek Individu
|
||||
type-2.display_name=Proyek Repositori
|
||||
|
||||
@ -1334,6 +1334,7 @@ runs.commit=Framlag
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -2706,6 +2706,7 @@ runs.commit=Commit
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -3910,6 +3910,7 @@ variables.update.success=変数を更新しました。
|
||||
logs.always_auto_scroll=常にログを自動スクロール
|
||||
logs.always_expand_running=常に実行中のログを展開
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=削除されたプロジェクト
|
||||
type-1.display_name=個人プロジェクト
|
||||
|
||||
@ -1554,6 +1554,7 @@ runs.commit=커밋
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -3282,6 +3282,7 @@ variables.update.failed=Neizdevās labot mainīgo.
|
||||
variables.update.success=Mainīgais tika labots.
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
type-1.display_name=Individuālais projekts
|
||||
type-2.display_name=Repozitorija projekts
|
||||
|
||||
@ -2458,6 +2458,7 @@ runs.commit=Commit
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -2347,6 +2347,7 @@ runs.commit=Commit
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -3615,6 +3615,7 @@ variables.update.failed=Falha ao editar a variável.
|
||||
variables.update.success=A variável foi editada.
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Excluir Projeto
|
||||
type-1.display_name=Projeto Individual
|
||||
|
||||
@ -3914,6 +3914,7 @@ variables.update.success=A variável foi editada.
|
||||
logs.always_auto_scroll=Rolar registos de forma automática e permanente
|
||||
logs.always_expand_running=Expandir sempre os registos que vão rolando
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Planeamento eliminado
|
||||
type-1.display_name=Planeamento individual
|
||||
|
||||
@ -3225,6 +3225,7 @@ variables.update.failed=Не удалось изменить переменну
|
||||
variables.update.success=Переменная изменена.
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
type-1.display_name=Индивидуальный проект
|
||||
type-2.display_name=Проект репозитория
|
||||
|
||||
@ -2391,6 +2391,7 @@ runs.commit=කැප
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -1292,6 +1292,7 @@ runners.labels=Štítky
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -1968,6 +1968,7 @@ runs.commit=Commit
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -3907,6 +3907,7 @@ variables.update.success=Değişken düzenlendi.
|
||||
logs.always_auto_scroll=Günlükleri her zaman otomatik kaydır
|
||||
logs.always_expand_running=Çalıştırma günlüklerini her zaman genişlet
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Silinmiş Proje
|
||||
type-1.display_name=Kişisel Proje
|
||||
|
||||
@ -3428,6 +3428,7 @@ variables.update.success=Змінну відредаговано.
|
||||
logs.always_auto_scroll=Завжди автоматично прокручувати журнали
|
||||
logs.always_expand_running=Завжди розгортати поточні журнали
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=Видалений проєкт
|
||||
type-1.display_name=Індивідуальний проєкт
|
||||
|
||||
@ -3911,6 +3911,7 @@ variables.update.success=变量已编辑。
|
||||
logs.always_auto_scroll=总是自动滚动日志
|
||||
logs.always_expand_running=总是展开运行日志
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=已删除项目
|
||||
type-1.display_name=个人项目
|
||||
|
||||
@ -980,6 +980,7 @@ runners.task_list.repository=儲存庫
|
||||
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
|
||||
[git.filemode]
|
||||
|
||||
@ -3554,6 +3554,7 @@ variables.update.failed=編輯變數失敗。
|
||||
variables.update.success=已編輯變數。
|
||||
|
||||
|
||||
|
||||
[projects]
|
||||
deleted.display_name=已刪除的專案
|
||||
type-1.display_name=個人專案
|
||||
|
||||
@ -654,6 +654,18 @@ func prepareIssueFilterAndList(ctx *context.Context, milestoneID, projectID int6
|
||||
return
|
||||
}
|
||||
|
||||
blockingCounts, err := issues.GetBlockingCount(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("BlockingCounts", err)
|
||||
return
|
||||
}
|
||||
|
||||
blockedByCounts, err := issues.GetBlockedByCount(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("BlockedByCounts", err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.IsSigned {
|
||||
if err := issues.LoadIsRead(ctx, ctx.Doer.ID); err != nil {
|
||||
ctx.ServerError("LoadIsRead", err)
|
||||
@ -718,6 +730,21 @@ func prepareIssueFilterAndList(ctx *context.Context, milestoneID, projectID int6
|
||||
return 0
|
||||
}
|
||||
|
||||
ctx.Data["BlockingCounts"] = func(issueID int64) int64 {
|
||||
counts, ok := blockingCounts[issueID]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return counts
|
||||
}
|
||||
ctx.Data["BlockedByCounts"] = func(issueID int64) int64 {
|
||||
counts, ok := blockedByCounts[issueID]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
retrieveProjectsForIssueList(ctx, repo)
|
||||
if ctx.Written() {
|
||||
return
|
||||
|
||||
@ -627,6 +627,33 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
blockingCounts, err := issues.GetBlockingCount(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("BlockingCounts", err)
|
||||
return
|
||||
}
|
||||
|
||||
blockedByCounts, err := issues.GetBlockedByCount(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("BlockedByCounts", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["BlockingCounts"] = func(issueID int64) int64 {
|
||||
counts, ok := blockingCounts[issueID]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return counts
|
||||
}
|
||||
ctx.Data["BlockedByCounts"] = func(issueID int64) int64 {
|
||||
counts, ok := blockedByCounts[issueID]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
ctx.Data["CommitLastStatus"] = lastStatus
|
||||
ctx.Data["CommitStatuses"] = commitStatuses
|
||||
ctx.Data["IssueStats"] = issueStats
|
||||
|
||||
@ -279,6 +279,32 @@ func NotificationSubscriptions(ctx *context.Context) {
|
||||
return 0
|
||||
}
|
||||
|
||||
blockingCounts, err := issues.GetBlockingCount(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("BlockingCounts", err)
|
||||
return
|
||||
}
|
||||
|
||||
blockedByCounts, err := issues.GetBlockedByCount(ctx)
|
||||
if err != nil {
|
||||
ctx.ServerError("BlockedByCounts", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["BlockingCounts"] = func(issueID int64) int64 {
|
||||
counts, ok := blockingCounts[issueID]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return counts
|
||||
}
|
||||
ctx.Data["BlockedByCounts"] = func(issueID int64) int64 {
|
||||
counts, ok := blockedByCounts[issueID]
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
ctx.Data["Status"] = 1
|
||||
ctx.Data["Title"] = ctx.Tr("notification.subscriptions")
|
||||
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
<div id="issue-list" class="flex-list">
|
||||
{{$approvalCounts := .ApprovalCounts}}
|
||||
{{$blockedByCounts := .BlockedByCounts}}
|
||||
{{$blockingCounts := .BlockingCounts}}
|
||||
{{range .Issues}}
|
||||
{{$blockedByCount := call $blockedByCounts .ID}}
|
||||
{{$blockingCount := call $blockingCounts .ID}}
|
||||
<div class="flex-item">
|
||||
|
||||
<div class="flex-item-leading">
|
||||
@ -22,6 +26,22 @@
|
||||
{{template "repo/commit_statuses" dict "Status" (index $.CommitLastStatus .PullRequest.ID) "Statuses" (index $.CommitStatuses .PullRequest.ID)}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if gt $blockedByCount 0}}
|
||||
<div class="ui label label-blocking">
|
||||
<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">
|
||||
{{svg "octicon-blocked" 16}}
|
||||
{{$blockedByCount}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if and (gt $blockingCount 0) (not .IsClosed)}}
|
||||
<div class="ui label label-blocking">
|
||||
<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">
|
||||
{{svg "octicon-report" 16}}
|
||||
{{$blockingCount}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
<span class="labels-list">
|
||||
{{range .Labels}}
|
||||
<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>
|
||||
|
||||
@ -56,3 +56,10 @@
|
||||
top: 10px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.label-blocking {
|
||||
border: 1px solid var(--color-secondary) !important;
|
||||
background: none transparent !important;
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user