mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-07 14:05:52 +01:00
(refs #2)Implementing pull request list.
This commit is contained in:
@@ -40,14 +40,14 @@ trait DashboardControllerBase extends ControllerBase {
|
|||||||
//
|
//
|
||||||
dashboard.html.issues(
|
dashboard.html.issues(
|
||||||
issues.html.listparts(
|
issues.html.listparts(
|
||||||
searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, repositories: _*),
|
searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, repositories: _*),
|
||||||
page,
|
page,
|
||||||
countIssue(condition.copy(state = "open"), filterUser, repositories: _*),
|
countIssue(condition.copy(state = "open"), filterUser, false, repositories: _*),
|
||||||
countIssue(condition.copy(state = "closed"), filterUser, repositories: _*),
|
countIssue(condition.copy(state = "closed"), filterUser, false, repositories: _*),
|
||||||
condition),
|
condition),
|
||||||
countIssue(condition, Map.empty, repositories: _*),
|
countIssue(condition, Map.empty, false, repositories: _*),
|
||||||
countIssue(condition, Map("assigned" -> userName), repositories: _*),
|
countIssue(condition, Map("assigned" -> userName), false, repositories: _*),
|
||||||
countIssue(condition, Map("created_by" -> userName), repositories: _*),
|
countIssue(condition, Map("created_by" -> userName), false, repositories: _*),
|
||||||
countIssueGroupByRepository(condition, filterUser, repositories: _*),
|
countIssueGroupByRepository(condition, filterUser, repositories: _*),
|
||||||
condition,
|
condition,
|
||||||
filter)
|
filter)
|
||||||
|
|||||||
@@ -313,16 +313,16 @@ trait IssuesControllerBase extends ControllerBase {
|
|||||||
session.put(sessionKey, condition)
|
session.put(sessionKey, condition)
|
||||||
|
|
||||||
issues.html.list(
|
issues.html.list(
|
||||||
searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
||||||
page,
|
page,
|
||||||
(getCollaborators(owner, repoName) :+ owner).sorted,
|
(getCollaborators(owner, repoName) :+ owner).sorted,
|
||||||
getMilestones(owner, repoName),
|
getMilestones(owner, repoName),
|
||||||
getLabels(owner, repoName),
|
getLabels(owner, repoName),
|
||||||
countIssue(condition.copy(state = "open"), filterUser, owner -> repoName),
|
countIssue(condition.copy(state = "open"), filterUser, false, owner -> repoName),
|
||||||
countIssue(condition.copy(state = "closed"), filterUser, owner -> repoName),
|
countIssue(condition.copy(state = "closed"), filterUser, false, owner -> repoName),
|
||||||
countIssue(condition, Map.empty, owner -> repoName),
|
countIssue(condition, Map.empty, false, owner -> repoName),
|
||||||
context.loginAccount.map(x => countIssue(condition, Map("assigned" -> x.userName), owner -> repoName)),
|
context.loginAccount.map(x => countIssue(condition, Map("assigned" -> x.userName), false, owner -> repoName)),
|
||||||
context.loginAccount.map(x => countIssue(condition, Map("created_by" -> x.userName), owner -> repoName)),
|
context.loginAccount.map(x => countIssue(condition, Map("created_by" -> x.userName), false, owner -> repoName)),
|
||||||
countIssueGroupByLabels(owner, repoName, condition, filterUser),
|
countIssueGroupByLabels(owner, repoName, condition, filterUser),
|
||||||
condition,
|
condition,
|
||||||
filter,
|
filter,
|
||||||
|
|||||||
@@ -3,16 +3,19 @@ package app
|
|||||||
import util.{LockUtil, CollaboratorsAuthenticator, JGitUtil, ReferrerAuthenticator}
|
import util.{LockUtil, CollaboratorsAuthenticator, JGitUtil, ReferrerAuthenticator}
|
||||||
import util.Directory._
|
import util.Directory._
|
||||||
import util.Implicits._
|
import util.Implicits._
|
||||||
import util.JGitUtil.{DiffInfo, CommitInfo}
|
|
||||||
import service._
|
import service._
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import jp.sf.amateras.scalatra.forms._
|
import jp.sf.amateras.scalatra.forms._
|
||||||
import org.eclipse.jgit.transport.RefSpec
|
import org.eclipse.jgit.transport.RefSpec
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
import service.RepositoryService.RepositoryTreeNode
|
|
||||||
import org.eclipse.jgit.lib.PersonIdent
|
import org.eclipse.jgit.lib.PersonIdent
|
||||||
import org.eclipse.jgit.api.MergeCommand.FastForwardMode
|
import org.eclipse.jgit.api.MergeCommand.FastForwardMode
|
||||||
|
import service.IssuesService._
|
||||||
|
import util.JGitUtil.DiffInfo
|
||||||
|
import scala.Some
|
||||||
|
import service.RepositoryService.RepositoryTreeNode
|
||||||
|
import util.JGitUtil.CommitInfo
|
||||||
|
|
||||||
class PullRequestsController extends PullRequestsControllerBase
|
class PullRequestsController extends PullRequestsControllerBase
|
||||||
with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with ActivityService
|
with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with ActivityService
|
||||||
@@ -50,10 +53,14 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
case class MergeForm(message: String)
|
case class MergeForm(message: String)
|
||||||
|
|
||||||
get("/:owner/:repository/pulls")(referrersOnly { repository =>
|
get("/:owner/:repository/pulls")(referrersOnly { repository =>
|
||||||
pulls.html.list(repository)
|
searchPullRequests(None, repository)
|
||||||
})
|
})
|
||||||
|
|
||||||
get("/:owner/:repository/pulls/:id")(referrersOnly { repository =>
|
get("/:owner/:repository/pulls/:userName")(referrersOnly { repository =>
|
||||||
|
searchPullRequests(Some(params("userName")), repository)
|
||||||
|
})
|
||||||
|
|
||||||
|
get("/:owner/:repository/pull/:id")(referrersOnly { repository =>
|
||||||
val owner = repository.owner
|
val owner = repository.owner
|
||||||
val name = repository.name
|
val name = repository.name
|
||||||
val issueId = params("id").toInt
|
val issueId = params("id").toInt
|
||||||
@@ -86,7 +93,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
} getOrElse NotFound
|
} getOrElse NotFound
|
||||||
})
|
})
|
||||||
|
|
||||||
post("/:owner/:repository/pulls/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) =>
|
post("/:owner/:repository/pull/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) =>
|
||||||
LockUtil.lock(s"${repository.owner}/${repository.name}/merge"){
|
LockUtil.lock(s"${repository.owner}/${repository.name}/merge"){
|
||||||
val issueId = params("id").toInt
|
val issueId = params("id").toInt
|
||||||
|
|
||||||
@@ -143,7 +150,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redirect(s"/${repository.owner}/${repository.name}/pulls/${issueId}")
|
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
git.getRepository.close
|
git.getRepository.close
|
||||||
@@ -188,7 +195,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get("/:owner/:repository/pulls/compare")(collaboratorsOnly { forkedRepository =>
|
get("/:owner/:repository/compare")(collaboratorsOnly { forkedRepository =>
|
||||||
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
||||||
case (Some(originUserName), Some(originRepositoryName)) => {
|
case (Some(originUserName), Some(originRepositoryName)) => {
|
||||||
getRepository(originUserName, originRepositoryName, baseUrl).map { originRepository =>
|
getRepository(originUserName, originRepositoryName, baseUrl).map { originRepository =>
|
||||||
@@ -199,20 +206,20 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
val oldBranch = JGitUtil.getDefaultBranch(oldGit, originRepository).get._2
|
val oldBranch = JGitUtil.getDefaultBranch(oldGit, originRepository).get._2
|
||||||
val newBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository).get._2
|
val newBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository).get._2
|
||||||
|
|
||||||
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/pulls/compare/${originUserName}:${oldBranch}...${newBranch}")
|
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/compare/${originUserName}:${oldBranch}...${newBranch}")
|
||||||
}
|
}
|
||||||
} getOrElse NotFound
|
} getOrElse NotFound
|
||||||
}
|
}
|
||||||
case _ => {
|
case _ => {
|
||||||
JGitUtil.withGit(getRepositoryDir(forkedRepository.owner, forkedRepository.name)){ git =>
|
JGitUtil.withGit(getRepositoryDir(forkedRepository.owner, forkedRepository.name)){ git =>
|
||||||
val defaultBranch = JGitUtil.getDefaultBranch(git, forkedRepository).get._2
|
val defaultBranch = JGitUtil.getDefaultBranch(git, forkedRepository).get._2
|
||||||
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/pulls/compare/${defaultBranch}...${defaultBranch}")
|
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/compare/${defaultBranch}...${defaultBranch}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
get("/:owner/:repository/pulls/compare/*...*")(collaboratorsOnly { repository =>
|
get("/:owner/:repository/compare/*...*")(collaboratorsOnly { repository =>
|
||||||
val Seq(origin, forked) = multiParams("splat")
|
val Seq(origin, forked) = multiParams("splat")
|
||||||
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, repository.owner)
|
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, repository.owner)
|
||||||
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, repository.owner)
|
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, repository.owner)
|
||||||
@@ -361,4 +368,29 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def searchPullRequests(userName: Option[String], repository: RepositoryService.RepositoryInfo) = {
|
||||||
|
val owner = repository.owner
|
||||||
|
val repoName = repository.name
|
||||||
|
val filterUser = userName.map { x => Map("created_by" -> x) } getOrElse Map("all" -> "")
|
||||||
|
val page = IssueSearchCondition.page(request)
|
||||||
|
val sessionKey = s"${owner}/${repoName}/pulls"
|
||||||
|
|
||||||
|
// retrieve search condition
|
||||||
|
val condition = if(request.getQueryString == null){
|
||||||
|
session.get(sessionKey).getOrElse(IssueSearchCondition()).asInstanceOf[IssueSearchCondition]
|
||||||
|
} else IssueSearchCondition(request)
|
||||||
|
|
||||||
|
session.put(sessionKey, condition)
|
||||||
|
|
||||||
|
pulls.html.list(
|
||||||
|
searchIssue(condition, filterUser, true, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
||||||
|
userName,
|
||||||
|
page,
|
||||||
|
countIssue(condition.copy(state = "open"), filterUser, true, owner -> repoName),
|
||||||
|
countIssue(condition.copy(state = "closed"), filterUser, true, owner -> repoName),
|
||||||
|
condition,
|
||||||
|
repository,
|
||||||
|
hasWritePermission(owner, repoName, context.loginAccount))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,14 +44,16 @@ trait IssuesService {
|
|||||||
*
|
*
|
||||||
* @param condition the search condition
|
* @param condition the search condition
|
||||||
* @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
|
* @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
|
||||||
|
* @param onlyPullRequest if true then counts only pull request, false then counts both of issue and pull request.
|
||||||
* @param repos Tuple of the repository owner and the repository name
|
* @param repos Tuple of the repository owner and the repository name
|
||||||
* @return the count of the search result
|
* @return the count of the search result
|
||||||
*/
|
*/
|
||||||
def countIssue(condition: IssueSearchCondition, filterUser: Map[String, String], repos: (String, String)*): Int = {
|
def countIssue(condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean,
|
||||||
|
repos: (String, String)*): Int = {
|
||||||
// TODO It must be _.length instead of map (_.issueId) list).length.
|
// TODO It must be _.length instead of map (_.issueId) list).length.
|
||||||
// But it does not work on Slick 1.0.1 (worked on Slick 1.0.0).
|
// But it does not work on Slick 1.0.1 (worked on Slick 1.0.0).
|
||||||
// https://github.com/slick/slick/issues/170
|
// https://github.com/slick/slick/issues/170
|
||||||
(searchIssueQuery(repos, condition, filterUser) map (_.issueId) list).length
|
(searchIssueQuery(repos, condition, filterUser, onlyPullRequest) map (_.issueId) list).length
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Returns the Map which contains issue count for each labels.
|
* Returns the Map which contains issue count for each labels.
|
||||||
@@ -65,7 +67,7 @@ trait IssuesService {
|
|||||||
def countIssueGroupByLabels(owner: String, repository: String, condition: IssueSearchCondition,
|
def countIssueGroupByLabels(owner: String, repository: String, condition: IssueSearchCondition,
|
||||||
filterUser: Map[String, String]): Map[String, Int] = {
|
filterUser: Map[String, String]): Map[String, Int] = {
|
||||||
|
|
||||||
searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), filterUser)
|
searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), filterUser, false)
|
||||||
.innerJoin(IssueLabels).on { (t1, t2) =>
|
.innerJoin(IssueLabels).on { (t1, t2) =>
|
||||||
t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
|
t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
|
||||||
}
|
}
|
||||||
@@ -89,9 +91,9 @@ trait IssuesService {
|
|||||||
* @param repos Tuple of the repository owner and the repository name
|
* @param repos Tuple of the repository owner and the repository name
|
||||||
* @return list which contains issue count for each repository
|
* @return list which contains issue count for each repository
|
||||||
*/
|
*/
|
||||||
def countIssueGroupByRepository(condition: IssueSearchCondition, filterUser: Map[String, String],
|
def countIssueGroupByRepository(
|
||||||
repos: (String, String)*): List[(String, String, Int)] = {
|
condition: IssueSearchCondition, filterUser: Map[String, String], repos: (String, String)*): List[(String, String, Int)] = {
|
||||||
searchIssueQuery(repos, condition.copy(repo = None), filterUser)
|
searchIssueQuery(repos, condition.copy(repo = None), filterUser, false)
|
||||||
.groupBy { t =>
|
.groupBy { t =>
|
||||||
t.userName ~ t.repositoryName
|
t.userName ~ t.repositoryName
|
||||||
}
|
}
|
||||||
@@ -107,16 +109,17 @@ trait IssuesService {
|
|||||||
*
|
*
|
||||||
* @param condition the search condition
|
* @param condition the search condition
|
||||||
* @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
|
* @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
|
||||||
|
* @param onlyPullRequest if true then returns only pull request, false then returns both of issue and pull request.
|
||||||
* @param offset the offset for pagination
|
* @param offset the offset for pagination
|
||||||
* @param limit the limit for pagination
|
* @param limit the limit for pagination
|
||||||
* @param repos Tuple of the repository owner and the repository name
|
* @param repos Tuple of the repository owner and the repository name
|
||||||
* @return the search result (list of tuples which contain issue, labels and comment count)
|
* @return the search result (list of tuples which contain issue, labels and comment count)
|
||||||
*/
|
*/
|
||||||
def searchIssue(condition: IssueSearchCondition, filterUser: Map[String, String],
|
def searchIssue(condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean,
|
||||||
offset: Int, limit: Int, repos: (String, String)*): List[(Issue, List[Label], Int)] = {
|
offset: Int, limit: Int, repos: (String, String)*): List[(Issue, List[Label], Int)] = {
|
||||||
|
|
||||||
// get issues and comment count and labels
|
// get issues and comment count and labels
|
||||||
searchIssueQuery(repos, condition, filterUser)
|
searchIssueQuery(repos, condition, filterUser, onlyPullRequest)
|
||||||
.innerJoin(IssueOutline).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) }
|
.innerJoin(IssueOutline).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) }
|
||||||
.leftJoin (IssueLabels) .on { case ((t1, t2), t3) => t1.byIssue(t3.userName, t3.repositoryName, t3.issueId) }
|
.leftJoin (IssueLabels) .on { case ((t1, t2), t3) => t1.byIssue(t3.userName, t3.repositoryName, t3.issueId) }
|
||||||
.leftJoin (Labels) .on { case (((t1, t2), t3), t4) => t3.byLabel(t4.userName, t4.repositoryName, t4.labelId) }
|
.leftJoin (Labels) .on { case (((t1, t2), t3), t4) => t3.byLabel(t4.userName, t4.repositoryName, t4.labelId) }
|
||||||
@@ -156,7 +159,8 @@ trait IssuesService {
|
|||||||
/**
|
/**
|
||||||
* Assembles query for conditional issue searching.
|
* Assembles query for conditional issue searching.
|
||||||
*/
|
*/
|
||||||
private def searchIssueQuery(repos: Seq[(String, String)], condition: IssueSearchCondition, filterUser: Map[String, String]) =
|
private def searchIssueQuery(repos: Seq[(String, String)], condition: IssueSearchCondition,
|
||||||
|
filterUser: Map[String, String], onlyPullRequest: Boolean) =
|
||||||
Query(Issues) filter { t1 =>
|
Query(Issues) filter { t1 =>
|
||||||
condition.repo
|
condition.repo
|
||||||
.map { _.split('/') match { case array => Seq(array(0) -> array(1)) } }
|
.map { _.split('/') match { case array => Seq(array(0) -> array(1)) } }
|
||||||
@@ -168,6 +172,7 @@ trait IssuesService {
|
|||||||
(t1.milestoneId isNull, condition.milestoneId == Some(None)) &&
|
(t1.milestoneId isNull, condition.milestoneId == Some(None)) &&
|
||||||
(t1.assignedUserName is filterUser("assigned").bind, filterUser.get("assigned").isDefined) &&
|
(t1.assignedUserName is filterUser("assigned").bind, filterUser.get("assigned").isDefined) &&
|
||||||
(t1.openedUserName is filterUser("created_by").bind, filterUser.get("created_by").isDefined) &&
|
(t1.openedUserName is filterUser("created_by").bind, filterUser.get("created_by").isDefined) &&
|
||||||
|
(t1.pullRequest is true.bind, onlyPullRequest) &&
|
||||||
(IssueLabels filter { t2 =>
|
(IssueLabels filter { t2 =>
|
||||||
(t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) &&
|
(t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) &&
|
||||||
(t2.labelId in
|
(t2.labelId in
|
||||||
|
|||||||
@@ -31,12 +31,4 @@ trait PullRequestService { self: IssuesService =>
|
|||||||
commitIdFrom,
|
commitIdFrom,
|
||||||
commitIdTo))
|
commitIdTo))
|
||||||
|
|
||||||
// def mergePullRequest(originUserName: String, originRepositoryName: String, issueId: Int,
|
|
||||||
// mergeStartId: String, mergeEndId: String): Unit = {
|
|
||||||
// Query(PullRequests)
|
|
||||||
// .filter(_.byPrimaryKey(originUserName, originRepositoryName, issueId))
|
|
||||||
// .map(t => t.mergeStartId ~ t.mergeEndId)
|
|
||||||
// .update(mergeStartId, mergeEndId)
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
|||||||
def activityMessage(message: String)(implicit context: app.Context): Html =
|
def activityMessage(message: String)(implicit context: app.Context): Html =
|
||||||
Html(message
|
Html(message
|
||||||
.replaceAll("\\[issue:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/issues/$$3">$$1/$$2#$$3</a>""")
|
.replaceAll("\\[issue:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/issues/$$3">$$1/$$2#$$3</a>""")
|
||||||
.replaceAll("\\[pullreq:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/pulls/$$3">$$1/$$2#$$3</a>""")
|
.replaceAll("\\[pullreq:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/pull/$$3">$$1/$$2#$$3</a>""")
|
||||||
.replaceAll("\\[repo:([^\\s]+?)/([^\\s]+?)\\]" , s"""<a href="${context.path}/$$1/$$2\">$$1/$$2</a>""")
|
.replaceAll("\\[repo:([^\\s]+?)/([^\\s]+?)\\]" , s"""<a href="${context.path}/$$1/$$2\">$$1/$$2</a>""")
|
||||||
.replaceAll("\\[branch:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]", s"""<a href="${context.path}/$$1/$$2/tree/$$3">$$3</a>""")
|
.replaceAll("\\[branch:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]", s"""<a href="${context.path}/$$1/$$2/tree/$$3">$$3</a>""")
|
||||||
.replaceAll("\\[tag:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]" , s"""<a href="${context.path}/$$1/$$2/tree/$$3">$$3</a>""")
|
.replaceAll("\\[tag:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]" , s"""<a href="${context.path}/$$1/$$2/tree/$$3">$$3</a>""")
|
||||||
|
|||||||
@@ -149,7 +149,7 @@
|
|||||||
<a href="@path/@issue.userName/@issue.repositoryName">@issue.repositoryName</a> ・
|
<a href="@path/@issue.userName/@issue.repositoryName">@issue.repositoryName</a> ・
|
||||||
}
|
}
|
||||||
@if(issue.isPullRequest){
|
@if(issue.isPullRequest){
|
||||||
<a href="@path/@issue.userName/@issue.repositoryName/pulls/@issue.issueId" class="issue-title">@issue.title</a>
|
<a href="@path/@issue.userName/@issue.repositoryName/pull/@issue.issueId" class="issue-title">@issue.title</a>
|
||||||
} else {
|
} else {
|
||||||
<a href="@path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-title">@issue.title</a>
|
<a href="@path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-title">@issue.title</a>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,11 +159,11 @@ $(function(){
|
|||||||
e.parents('div.btn-group').find('button strong').text(e.text());
|
e.parents('div.btn-group').find('button strong').text(e.text());
|
||||||
|
|
||||||
@if(members.isEmpty){
|
@if(members.isEmpty){
|
||||||
location.href = '@url(repository)/pulls/compare/' +
|
location.href = '@url(repository)/compare/' +
|
||||||
$.trim($('i.icon-ok').parents('a.origin-branch').data('name')) + '...' +
|
$.trim($('i.icon-ok').parents('a.origin-branch').data('name')) + '...' +
|
||||||
$.trim($('i.icon-ok').parents('a.forked-branch').data('name'));
|
$.trim($('i.icon-ok').parents('a.forked-branch').data('name'));
|
||||||
} else {
|
} else {
|
||||||
location.href = '@url(repository)/pulls/compare/' +
|
location.href = '@url(repository)/compare/' +
|
||||||
$.trim($('i.icon-ok').parents('a.origin-owner' ).data('name')) + ':' +
|
$.trim($('i.icon-ok').parents('a.origin-owner' ).data('name')) + ':' +
|
||||||
$.trim($('i.icon-ok').parents('a.origin-branch').data('name')) + '...' +
|
$.trim($('i.icon-ok').parents('a.origin-branch').data('name')) + '...' +
|
||||||
$.trim($('i.icon-ok').parents('a.forked-owner' ).data('name')) + ':' +
|
$.trim($('i.icon-ok').parents('a.forked-owner' ).data('name')) + ':' +
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ git push origin @{pullreq.branch}</pre>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="confirm-merge-form" style="display: none;">
|
<div id="confirm-merge-form" style="display: none;">
|
||||||
<form method="POST" action="@url(repository)/pulls/@issue.issueId/merge">
|
<form method="POST" action="@url(repository)/pull/@issue.issueId/merge">
|
||||||
<div>
|
<div>
|
||||||
<strong>Merge pull request #@issue.issueId from @{pullreq.requestUserName}/@{pullreq.requestBranch}</strong>
|
<strong>Merge pull request #@issue.issueId from @{pullreq.requestUserName}/@{pullreq.requestBranch}</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,132 @@
|
|||||||
@(repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
|
@(issues: List[(model.Issue, List[model.Label], Int)],
|
||||||
|
filter: Option[String],
|
||||||
|
page: Int,
|
||||||
|
openCount: Int,
|
||||||
|
closedCount: Int,
|
||||||
|
condition: service.IssuesService.IssueSearchCondition,
|
||||||
|
repository: service.RepositoryService.RepositoryInfo,
|
||||||
|
hasWritePermission: Boolean)(implicit context: app.Context)
|
||||||
@import context._
|
@import context._
|
||||||
@import view.helpers._
|
@import view.helpers._
|
||||||
@html.main("Pull Requests - " + repository.owner + "/" + repository.name){
|
@html.main("Pull Requests - " + repository.owner + "/" + repository.name){
|
||||||
@html.header("pulls", repository)
|
@html.header("pulls", repository)
|
||||||
<a href="@url(repository)/pulls/compare" class="btn btn-success">New pull request</a>
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<ul class="nav nav-pills nav-stacked">
|
||||||
|
<li@if(filter.isEmpty){ class="active"}>
|
||||||
|
<a href="@url(repository)/pulls">
|
||||||
|
<span class="count-right">@(openCount + closedCount)</span>
|
||||||
|
All Requests
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@if(loginAccount.isDefined){
|
||||||
|
<li@if(filter.isDefined && filter.get == loginAccount.get.userName){ class="active"}>
|
||||||
|
<a href="@url(repository)/pulls/@loginAccount.map(_.userName)">
|
||||||
|
<span class="count-right">0</span>
|
||||||
|
Yours
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="span9">
|
||||||
|
@if(hasWritePermission){
|
||||||
|
<div class="pull-right">
|
||||||
|
<a href="@url(repository)/compare" class="btn btn-success">New pull request</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn@if(condition.state == "open"){ active}" href="@condition.copy(state = "open").toURL">@openCount Open</a>
|
||||||
|
<a class="btn@if(condition.state == "closed"){ active}" href="@condition.copy(state = "closed").toURL">@closedCount Closed</a>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||||
|
Sort:
|
||||||
|
<strong>
|
||||||
|
@if(condition.sort == "created" && condition.direction == "desc"){ Newest }
|
||||||
|
@if(condition.sort == "created" && condition.direction == "asc" ){ Oldest }
|
||||||
|
@if(condition.sort == "comments" && condition.direction == "desc"){ Most commented }
|
||||||
|
@if(condition.sort == "comments" && condition.direction == "asc" ){ Least commented }
|
||||||
|
@if(condition.sort == "updated" && condition.direction == "desc"){ Recently updated }
|
||||||
|
@if(condition.sort == "updated" && condition.direction == "asc" ){ Least recently updated }
|
||||||
|
</strong>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="created", direction="desc").toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "created" && condition.direction == "desc") Newest
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="created", direction="asc" ).toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "created" && condition.direction == "asc") Oldest
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="comments", direction="desc").toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "comments" && condition.direction == "desc") Most commented
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="comments", direction="asc" ).toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "comments" && condition.direction == "asc") Least commented
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="updated", direction="desc").toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "updated" && condition.direction == "desc") Recently updated
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="updated", direction="asc" ).toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "updated" && condition.direction == "asc") Least recently updated
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<table class="table table-bordered table-hover table-issues">
|
||||||
|
@if(issues.isEmpty){
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 20px; background-color: #eee; text-align: center;">
|
||||||
|
No pull requests to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
@issues.map { case (issue, labels, commentCount) =>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
@if(hasWritePermission){
|
||||||
|
<label class="checkbox" style="cursor: default;">
|
||||||
|
<input type="checkbox" value="@issue.issueId"/>
|
||||||
|
}
|
||||||
|
<a href="@path/@issue.userName/@issue.repositoryName/pull/@issue.issueId" class="issue-title">@issue.title</a>
|
||||||
|
@labels.map { label =>
|
||||||
|
<span class="label-color small" style="background-color: #@label.color; color: #@label.fontColor; padding-left: 4px; padding-right: 4px">@label.labelName</span>
|
||||||
|
}
|
||||||
|
<span class="pull-right muted">
|
||||||
|
@issue.assignedUserName.map { userName =>
|
||||||
|
@avatar(userName, 20, tooltip = true)
|
||||||
|
}
|
||||||
|
#@issue.issueId
|
||||||
|
</span>
|
||||||
|
<div class="small muted">
|
||||||
|
Opened by <a href="@url(issue.openedUserName)" class="username">@issue.openedUserName</a> @datetime(issue.registeredDate)
|
||||||
|
@if(commentCount > 0){
|
||||||
|
<i class="icon-comment"></i><a href="@path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-comment-count">@commentCount @plural(commentCount, "comment")</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
@if(hasWritePermission){
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</table>
|
||||||
|
<div class="pull-right">
|
||||||
|
@helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user