From 0692f437b6e9e22399f84adc0f8bad15e9341e09 Mon Sep 17 00:00:00 2001
From: IT-AlexKor <101557941+IT-AlexKor@users.noreply.github.com>
Date: Wed, 25 May 2022 16:33:35 +0300
Subject: [PATCH] Show source/target branches on PR's list (#19747)

Add ability to show source/target branches for Pull Request's list. It can be useful to see which branches are used in each PR right in the list.

Co-authored-by: Alexey Korobkov <akorobkov@cian.ru>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lauris BH <lauris@nix.lv>
---
 models/issue_list.go               | 14 +++++++++-----
 templates/shared/issuelist.tmpl    | 21 +++++++++++++++++++++
 web_src/less/shared/issuelist.less | 17 +++++++++++++++++
 3 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/models/issue_list.go b/models/issue_list.go
index 4a8f72a48b..31588c02a4 100644
--- a/models/issue_list.go
+++ b/models/issue_list.go
@@ -25,15 +25,16 @@ const (
 	defaultMaxInSize = 50
 )
 
+// get the repo IDs to be loaded later, these IDs are for issue.Repo and issue.PullRequest.HeadRepo
 func (issues IssueList) getRepoIDs() []int64 {
 	repoIDs := make(map[int64]struct{}, len(issues))
 	for _, issue := range issues {
-		if issue.Repo != nil {
-			continue
-		}
-		if _, ok := repoIDs[issue.RepoID]; !ok {
+		if issue.Repo == nil {
 			repoIDs[issue.RepoID] = struct{}{}
 		}
+		if issue.PullRequest != nil && issue.PullRequest.HeadRepo == nil {
+			repoIDs[issue.PullRequest.HeadRepoID] = struct{}{}
+		}
 	}
 	return container.KeysInt64(repoIDs)
 }
@@ -67,8 +68,11 @@ func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Rep
 		} else {
 			repoMaps[issue.RepoID] = issue.Repo
 		}
-		if issue.PullRequest != nil && issue.PullRequest.BaseRepo == nil {
+		if issue.PullRequest != nil {
 			issue.PullRequest.BaseRepo = issue.Repo
+			if issue.PullRequest.HeadRepo == nil {
+				issue.PullRequest.HeadRepo = repoMaps[issue.PullRequest.HeadRepoID]
+			}
 		}
 	}
 	return valuesRepository(repoMaps), nil
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl
index 23fb76d500..5392365dd1 100644
--- a/templates/shared/issuelist.tmpl
+++ b/templates/shared/issuelist.tmpl
@@ -59,6 +59,27 @@
 					{{else}}
 						{{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
 					{{end}}
+					{{if .IsPull}}
+						<div class="branches">
+							<div class="branch">
+								<a class="bold" href="{{.PullRequest.BaseRepo.HTMLURL}}/src/branch/{{PathEscapeSegments .PullRequest.BaseBranch}}">
+									{{/* inline to remove the spaces between spans */}}
+									{{if ne .RepoID .PullRequest.BaseRepoID}}<span class="truncated-name">{{.PullRequest.BaseRepo.OwnerName}}</span>:{{end}}<span class="truncated-name">{{.PullRequest.BaseBranch}}</span>
+								</a>
+							</div>
+
+							&laquo;
+
+							{{if .PullRequest.HeadRepo}}
+							<div class="branch">
+								<a class="bold" href="{{.PullRequest.HeadRepo.HTMLURL}}/src/branch/{{PathEscapeSegments .PullRequest.HeadBranch}}">
+									{{/* inline to remove the spaces between spans */}}
+									{{if ne .RepoID .PullRequest.HeadRepoID}}<span class="truncated-name">{{.PullRequest.HeadRepo.OwnerName}}</span>:{{end}}<span class="truncated-name">{{.PullRequest.HeadBranch}}</span>
+								</a>
+							</div>
+							{{end}}
+						</div>
+					{{end}}
 					{{if and .Milestone (ne $.listType "milestone")}}
 						<a class="milestone" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{.Repo.Link}}/milestone/{{.Milestone.ID}}"{{end}}>
 							{{svg "octicon-milestone" 14 "mr-2"}}{{.Milestone.Name}}
diff --git a/web_src/less/shared/issuelist.less b/web_src/less/shared/issuelist.less
index 32fd206827..775fc98478 100644
--- a/web_src/less/shared/issuelist.less
+++ b/web_src/less/shared/issuelist.less
@@ -119,6 +119,23 @@
     }
   }
 
+  .branches {
+    display: inline-flex;
+    padding: 0 6px;
+
+    .branch {
+      background-color: var(--color-secondary);
+      border-radius: 3px;
+    }
+
+    .truncated-name {
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      max-width: 10em;
+    }
+  }
+
   > .item + .item {
     border-top: 1px solid var(--color-secondary);
   }