diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala index 7186d40..2728b5e 100644 --- a/src/main/scala/app/DashboardController.scala +++ b/src/main/scala/app/DashboardController.scala @@ -32,26 +32,26 @@ else IssueSearchCondition(request) session.put(sessionKey, condition) - + val userName = context.loginAccount.get.userName val repositories = getUserRepositories(userName, baseUrl).map(repo => repo.owner -> repo.name) val filterUser = Map(filter -> userName) - val page = IssueSearchCondition.page(request) + val page = IssueSearchCondition.page(request) // dashboard.html.issues( issues.html.listparts( - searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, repositories: _*), + searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, repositories: _*), page, - countIssue(condition.copy(state = "open"), filterUser, repositories: _*), - countIssue(condition.copy(state = "closed"), filterUser, repositories: _*), + countIssue(condition.copy(state = "open"), filterUser, false, repositories: _*), + countIssue(condition.copy(state = "closed"), filterUser, false, repositories: _*), condition), - countIssue(condition, Map.empty, repositories: _*), - countIssue(condition, Map("assigned" -> userName), repositories: _*), - countIssue(condition, Map("created_by" -> userName), repositories: _*), + countIssue(condition, Map.empty, false, repositories: _*), + countIssue(condition, Map("assigned" -> userName), false, repositories: _*), + countIssue(condition, Map("created_by" -> userName), false, repositories: _*), countIssueGroupByRepository(condition, filterUser, repositories: _*), condition, filter) } -} +} diff --git a/src/main/scala/app/IssuesController.scala b/src/main/scala/app/IssuesController.scala index af8da84..bccd939 100644 --- a/src/main/scala/app/IssuesController.scala +++ b/src/main/scala/app/IssuesController.scala @@ -313,16 +313,16 @@ session.put(sessionKey, condition) issues.html.list( - searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, owner -> repoName), + searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName), page, (getCollaborators(owner, repoName) :+ owner).sorted, getMilestones(owner, repoName), getLabels(owner, repoName), - countIssue(condition.copy(state = "open"), filterUser, owner -> repoName), - countIssue(condition.copy(state = "closed"), filterUser, owner -> repoName), - countIssue(condition, Map.empty, owner -> repoName), - context.loginAccount.map(x => countIssue(condition, Map("assigned" -> x.userName), owner -> repoName)), - context.loginAccount.map(x => countIssue(condition, Map("created_by" -> x.userName), owner -> repoName)), + countIssue(condition.copy(state = "open"), filterUser, false, owner -> repoName), + countIssue(condition.copy(state = "closed"), filterUser, false, owner -> repoName), + countIssue(condition, Map.empty, false, 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), false, owner -> repoName)), countIssueGroupByLabels(owner, repoName, condition, filterUser), condition, filter, diff --git a/src/main/scala/app/PullRequestsController.scala b/src/main/scala/app/PullRequestsController.scala index f221f83..922227d 100644 --- a/src/main/scala/app/PullRequestsController.scala +++ b/src/main/scala/app/PullRequestsController.scala @@ -3,16 +3,19 @@ import util.{LockUtil, CollaboratorsAuthenticator, JGitUtil, ReferrerAuthenticator} import util.Directory._ import util.Implicits._ -import util.JGitUtil.{DiffInfo, CommitInfo} import service._ import org.eclipse.jgit.api.Git import jp.sf.amateras.scalatra.forms._ import org.eclipse.jgit.transport.RefSpec import org.apache.commons.io.FileUtils import scala.collection.JavaConverters._ -import service.RepositoryService.RepositoryTreeNode import org.eclipse.jgit.lib.PersonIdent 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 with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with ActivityService @@ -50,10 +53,14 @@ case class MergeForm(message: String) 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 name = repository.name val issueId = params("id").toInt @@ -86,7 +93,7 @@ } 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"){ val issueId = params("id").toInt @@ -143,7 +150,7 @@ } } - redirect(s"/${repository.owner}/${repository.name}/pulls/${issueId}") + redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}") } finally { git.getRepository.close @@ -188,7 +195,7 @@ } } - get("/:owner/:repository/pulls/compare")(collaboratorsOnly { forkedRepository => + get("/:owner/:repository/compare")(collaboratorsOnly { forkedRepository => (forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match { case (Some(originUserName), Some(originRepositoryName)) => { getRepository(originUserName, originRepositoryName, baseUrl).map { originRepository => @@ -199,20 +206,20 @@ val oldBranch = JGitUtil.getDefaultBranch(oldGit, originRepository).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 } case _ => { JGitUtil.withGit(getRepositoryDir(forkedRepository.owner, forkedRepository.name)){ git => 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 (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, repository.owner) val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, repository.owner) @@ -361,4 +368,29 @@ } } + 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)) + } + } diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 3e44c6c..46706d0 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -44,14 +44,16 @@ * * @param condition the search condition * @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 * @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. // But it does not work on Slick 1.0.1 (worked on Slick 1.0.0). // 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. @@ -65,7 +67,7 @@ def countIssueGroupByLabels(owner: String, repository: String, condition: IssueSearchCondition, 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) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) } @@ -89,9 +91,9 @@ * @param repos Tuple of the repository owner and the repository name * @return list which contains issue count for each repository */ - def countIssueGroupByRepository(condition: IssueSearchCondition, filterUser: Map[String, String], - repos: (String, String)*): List[(String, String, Int)] = { - searchIssueQuery(repos, condition.copy(repo = None), filterUser) + def countIssueGroupByRepository( + condition: IssueSearchCondition, filterUser: Map[String, String], repos: (String, String)*): List[(String, String, Int)] = { + searchIssueQuery(repos, condition.copy(repo = None), filterUser, false) .groupBy { t => t.userName ~ t.repositoryName } @@ -107,16 +109,17 @@ * * @param condition the search condition * @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 limit the limit for pagination * @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) */ - 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)] = { // 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) } .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) } @@ -156,7 +159,8 @@ /** * 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 => condition.repo .map { _.split('/') match { case array => Seq(array(0) -> array(1)) } } @@ -168,6 +172,7 @@ (t1.milestoneId isNull, condition.milestoneId == Some(None)) && (t1.assignedUserName is filterUser("assigned").bind, filterUser.get("assigned").isDefined) && (t1.openedUserName is filterUser("created_by").bind, filterUser.get("created_by").isDefined) && + (t1.pullRequest is true.bind, onlyPullRequest) && (IssueLabels filter { t2 => (t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) && (t2.labelId in diff --git a/src/main/scala/service/PullRequestService.scala b/src/main/scala/service/PullRequestService.scala index 1013ee6..f909f13 100644 --- a/src/main/scala/service/PullRequestService.scala +++ b/src/main/scala/service/PullRequestService.scala @@ -31,12 +31,4 @@ commitIdFrom, 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) -// } - } diff --git a/src/main/scala/view/helpers.scala b/src/main/scala/view/helpers.scala index 615ffab..86aef26 100644 --- a/src/main/scala/view/helpers.scala +++ b/src/main/scala/view/helpers.scala @@ -54,7 +54,7 @@ def activityMessage(message: String)(implicit context: app.Context): Html = Html(message .replaceAll("\\[issue:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""$$1/$$2#$$3""") - .replaceAll("\\[pullreq:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""$$1/$$2#$$3""") + .replaceAll("\\[pullreq:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""$$1/$$2#$$3""") .replaceAll("\\[repo:([^\\s]+?)/([^\\s]+?)\\]" , s"""$$1/$$2""") .replaceAll("\\[branch:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]", s"""$$3""") .replaceAll("\\[tag:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]" , s"""$$3""") diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html index 3c03198..ac698fa 100644 --- a/src/main/twirl/issues/listparts.scala.html +++ b/src/main/twirl/issues/listparts.scala.html @@ -149,7 +149,7 @@ @issue.repositoryName ・ } @if(issue.isPullRequest){ - @issue.title + @issue.title } else { @issue.title } diff --git a/src/main/twirl/pulls/compare.scala.html b/src/main/twirl/pulls/compare.scala.html index 35b559c..fef6a61 100644 --- a/src/main/twirl/pulls/compare.scala.html +++ b/src/main/twirl/pulls/compare.scala.html @@ -159,11 +159,11 @@ e.parents('div.btn-group').find('button strong').text(e.text()); @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.forked-branch').data('name')); } 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-branch').data('name')) + '...' + $.trim($('i.icon-ok').parents('a.forked-owner' ).data('name')) + ':' + diff --git a/src/main/twirl/pulls/discussion.scala.html b/src/main/twirl/pulls/discussion.scala.html index b2d5ab9..ae3c702 100644 --- a/src/main/twirl/pulls/discussion.scala.html +++ b/src/main/twirl/pulls/discussion.scala.html @@ -149,7 +149,7 @@