diff --git a/src/main/scala/service/CommitStatusService.scala b/src/main/scala/service/CommitStatusService.scala index 0cc7e22..fc05744 100644 --- a/src/main/scala/service/CommitStatusService.scala +++ b/src/main/scala/service/CommitStatusService.scala @@ -46,4 +46,5 @@ protected def byCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session) = CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) ).sortBy(_.updatedDate desc) + } \ No newline at end of file diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index 582677e..92a30a0 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -84,6 +84,47 @@ .toMap } + def getCommitStatues(issueList:Seq[(String, String, Int)])(implicit s: Session) :Map[(String, String, Int), CommitStatusInfo] ={ + if(issueList.isEmpty){ + Map.empty + }else{ + import scala.slick.jdbc._ + val issueIdQuery = issueList.map(i => "(PR.USER_NAME=? AND PR.REPOSITORY_NAME=? AND PR.ISSUE_ID=?)").mkString(" OR ") + implicit val qset = SetParameter[Seq[(String, String, Int)]] { + case (seq, pp) => + for (a <- seq) { + pp.setString(a._1) + pp.setString(a._2) + pp.setInt(a._3) + } + } + import model.Profile.commitStateColumnType + val query = Q.query[Seq[(String, String, Int)], (String, String, Int, Int, Int, Option[String], Option[model.CommitState], Option[String], Option[String])](s""" + SELECT SUMM.USER_NAME, SUMM.REPOSITORY_NAME, SUMM.ISSUE_ID, CS_ALL, CS_SUCCESS + , CSD.CONTEXT, CSD.STATE, CSD.TARGET_URL, CSD.DESCRIPTION + FROM (SELECT + PR.USER_NAME + , PR.REPOSITORY_NAME + , PR.ISSUE_ID + , COUNT(CS.STATE) AS CS_ALL + , SUM(CS.STATE='success') AS CS_SUCCESS + , PR.COMMIT_ID_TO AS COMMIT_ID + FROM PULL_REQUEST PR + JOIN COMMIT_STATUS CS + ON PR.USER_NAME=CS.USER_NAME + AND PR.REPOSITORY_NAME=CS.REPOSITORY_NAME + AND PR.COMMIT_ID_TO=CS.COMMIT_ID + WHERE $issueIdQuery + GROUP BY PR.USER_NAME, PR.REPOSITORY_NAME, PR.ISSUE_ID) as SUMM + LEFT OUTER JOIN COMMIT_STATUS CSD + ON SUMM.CS_ALL = 1 AND SUMM.COMMIT_ID = CSD.COMMIT_ID"""); + query(issueList).list.map{ + case(userName, repositoryName, issueId, count, successCount, context, state, targetUrl, description) => + (userName, repositoryName, issueId) -> CommitStatusInfo(count, successCount, context, state, targetUrl, description) + }.toMap + } + } + /** * Returns the search result against issues. * @@ -96,9 +137,8 @@ */ def searchIssue(condition: IssueSearchCondition, pullRequest: Boolean, offset: Int, limit: Int, repos: (String, String)*) (implicit s: Session): List[IssueInfo] = { - // get issues and comment count and labels - searchIssueQueryBase(condition, pullRequest, offset, limit, repos) + val result = searchIssueQueryBase(condition, pullRequest, offset, limit, repos) .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 (Milestones) .on { case ((((t1, t2), t3), t4), t5) => t1.byMilestone(t5.userName, t5.repositoryName, t5.milestoneId) } @@ -111,14 +151,17 @@ c1._1.repositoryName == c2._1.repositoryName && c1._1.issueId == c2._1.issueId } - .map { issues => issues.head match { + val status = getCommitStatues(result.map(_.head._1).map(is => (is.userName, is.repositoryName, is.issueId))) + + result.map { issues => issues.head match { case (issue, commentCount, _, _, _, milestone) => IssueInfo(issue, issues.flatMap { t => t._3.map ( Label(issue.userName, issue.repositoryName, _, t._4.get, t._5.get) )} toList, milestone, - commentCount) + commentCount, + status.get(issue.userName, issue.repositoryName, issue.issueId)) }} toList } @@ -490,6 +533,8 @@ } } - case class IssueInfo(issue: Issue, labels: List[Label], milestone: Option[String], commentCount: Int) + case class CommitStatusInfo(count: Int, successCount: Int, context: Option[String], state: Option[model.CommitState], targetUrl: Option[String], description: Option[String]) + + case class IssueInfo(issue: Issue, labels: List[Label], milestone: Option[String], commentCount: Int, status:Option[CommitStatusInfo]) } diff --git a/src/main/twirl/dashboard/issueslist.scala.html b/src/main/twirl/dashboard/issueslist.scala.html index f2afaa0..4bf230b 100644 --- a/src/main/twirl/dashboard/issueslist.scala.html +++ b/src/main/twirl/dashboard/issueslist.scala.html @@ -14,7 +14,7 @@ @dashboard.html.header(openCount, closedCount, condition, groups) - @issues.map { case IssueInfo(issue, labels, milestone, commentCount) => + @issues.map { case IssueInfo(issue, labels, milestone, commentCount, commitStatus) => @if(issue.isPullRequest){ @@ -28,6 +28,7 @@ } else { @issue.title } + @_root_.issues.html.commitstatus(issue, commitStatus) @labels.map { label => @label.labelName } diff --git a/src/main/twirl/issues/commitstatus.scala.html b/src/main/twirl/issues/commitstatus.scala.html new file mode 100644 index 0000000..542b3f3 --- /dev/null +++ b/src/main/twirl/issues/commitstatus.scala.html @@ -0,0 +1,19 @@ +@(issue: model.Issue, statusInfo: Option[service.IssuesService.CommitStatusInfo])(implicit context: app.Context) +@import view.helpers._ +@statusInfo.map{ status => + @if(status.count==1 && status.state.isDefined){ + @if(status.targetUrl.isDefined){ + @commitStateIcon(status.state.get) + }else{ + @commitStateIcon(status.state.get) + } + }else{ + @defining(status.count==status.successCount){ isSuccess => + @if(isSuccess){ + ✔ + }else{ + × + } + } + } +} \ No newline at end of file diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html index 6c93789..5c8f2fe 100644 --- a/src/main/twirl/issues/listparts.scala.html +++ b/src/main/twirl/issues/listparts.scala.html @@ -170,7 +170,7 @@ } - @issues.map { case IssueInfo(issue, labels, milestone, commentCount) => + @issues.map { case IssueInfo(issue, labels, milestone, commentCount, commitStatus) => @if(hasWritePermission){ @@ -185,6 +185,7 @@ } else { @issue.title } + @commitstatus(issue, commitStatus) @labels.map { label => @label.labelName } diff --git a/src/test/scala/service/IssuesServiceSpec.scala b/src/test/scala/service/IssuesServiceSpec.scala new file mode 100644 index 0000000..0fada59 --- /dev/null +++ b/src/test/scala/service/IssuesServiceSpec.scala @@ -0,0 +1,47 @@ +package service + +import org.specs2.mutable.Specification +import java.util.Date +import model._ +import service.IssuesService._ + +class IssuesServiceSpec extends Specification with ServiceSpecBase { + "IssuesService" should { + "getCommitStatues" in { withTestDB { implicit session => + val user1 = generateNewUserWithDBRepository("user1","repo1") + + def getCommitStatues = dummyService.getCommitStatues(List(("user1","repo1",1),("user1","repo1",2))) + + getCommitStatues must_== Map.empty + + val now = new java.util.Date() + val issueId = generateNewIssue("user1","repo1") + issueId must_== 1 + + getCommitStatues must_== Map.empty + + val cs = dummyService.createCommitStatus("user1","repo1","shasha", "default", CommitState.SUCCESS, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) + + getCommitStatues must_== Map.empty + + val (is2, pr2) = generateNewPullRequest("user1/repo1/master","user1/repo1/feature1") + pr2.issueId must_== 2 + + // if there are no statuses, state is none + getCommitStatues must_== Map.empty + + // if there is a status, state is that + val cs2 = dummyService.createCommitStatus("user1","repo1","feature1", "default", CommitState.SUCCESS, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) + getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(1,1,Some("default"),Some(CommitState.SUCCESS),Some("http://exmple.com/ci"),Some("exampleService"))) + + // if there are two statuses, state is none + val cs3 = dummyService.createCommitStatus("user1","repo1","feature1", "pend", CommitState.PENDING, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) + getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(2,1,None,None,None,None)) + + // get only statuses in query issues + val (is3, pr3) = generateNewPullRequest("user1/repo1/master","user1/repo1/feature3") + val cs4 = dummyService.createCommitStatus("user1","repo1","feature3", "none", CommitState.PENDING, None, None, now, user1) + getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(2,1,None,None,None,None)) + } } + } +} \ No newline at end of file diff --git a/src/test/scala/service/ServiceSpecBase.scala b/src/test/scala/service/ServiceSpecBase.scala index cc9dd05..048227f 100644 --- a/src/test/scala/service/ServiceSpecBase.scala +++ b/src/test/scala/service/ServiceSpecBase.scala @@ -30,26 +30,31 @@ AccountService.getAccountByUserName(name).get } - lazy val dummyService = new RepositoryService with AccountService with IssuesService with PullRequestService (){} + lazy val dummyService = new RepositoryService with AccountService with IssuesService with PullRequestService + with CommitStatusService (){} def generateNewUserWithDBRepository(userName:String, repositoryName:String)(implicit s:Session):Account = { val ac = generateNewAccount(userName) dummyService.createRepository(repositoryName, userName, None, false) ac } - def generateNewPullRequest(base:String, request:String)(implicit s:Session):(Issue, PullRequest) = { - val Array(baseUserName, baseRepositoryName, baesBranch)=base.split("/") - val Array(requestUserName, requestRepositoryName, requestBranch)=request.split("/") - val issueId = dummyService.createIssue( - owner = baseUserName, - repository = baseRepositoryName, + + def generateNewIssue(userName:String, repositoryName:String, requestUserName:String="root")(implicit s:Session): Int = { + dummyService.createIssue( + owner = userName, + repository = repositoryName, loginUser = requestUserName, title = "issue title", content = None, assignedUserName = None, milestoneId = None, isPullRequest = true) + } + def generateNewPullRequest(base:String, request:String)(implicit s:Session):(Issue, PullRequest) = { + val Array(baseUserName, baseRepositoryName, baesBranch)=base.split("/") + val Array(requestUserName, requestRepositoryName, requestBranch)=request.split("/") + val issueId = generateNewIssue(baseUserName, baseRepositoryName, requestUserName) dummyService.createPullRequest( originUserName = baseUserName, originRepositoryName = baseRepositoryName,