Separate milestones from IssuesController / IssuesService.

This commit is contained in:
takezoe
2013-06-24 13:43:35 +09:00
parent 1de2ddf242
commit 2703b22718
5 changed files with 193 additions and 155 deletions

View File

@@ -12,6 +12,7 @@ class ScalatraBootstrap extends LifeCycle {
context.mount(new RepositoryViewerController, "/*")
context.mount(new WikiController, "/*")
context.mount(new IssuesController, "/*")
context.mount(new MilestonesController, "/*")
context.mount(new SettingsController, "/*")
context.addListener(new ServletContextListener(){

View File

@@ -73,101 +73,4 @@ trait IssuesControllerBase extends ControllerBase {
redirect("/%s/%s/issues/%d".format(owner, repository, 1))
})
get("/:owner/:repository/issues/milestones")(readableRepository {
val owner = params("owner")
val repository = params("repository")
val state = params.getOrElse("state", "open")
getRepository(owner, repository, baseUrl) match {
case None => NotFound()
case Some(r) => issues.html.milestones(state, getMilestones(owner, repository),
getMilestoneIssueCounts(owner, repository), r, isWritable(owner, repository, context.loginAccount))
}
})
get("/:owner/:repository/issues/milestones/new")(writableRepository {
val owner = params("owner")
val repository = params("repository")
getRepository(owner, repository, baseUrl) match {
case None => NotFound()
case Some(r) => issues.html.milestoneedit(None, r)
}
})
post("/:owner/:repository/issues/milestones/new", milestoneForm)(writableRepository { form =>
val owner = params("owner")
val repository = params("repository")
createMilestone(owner, repository, form.title, form.description, form.dueDate)
redirect("/%s/%s/issues/milestones".format(owner, repository))
})
get("/:owner/:repository/issues/milestones/:milestoneId/edit")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getRepository(owner, repository, baseUrl) match {
case None => NotFound()
case Some(r) => issues.html.milestoneedit(getMilestone(owner, repository, milestoneId), r)
}
})
post("/:owner/:repository/issues/milestones/:milestoneId/edit", milestoneForm)(writableRepository { form =>
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
updateMilestone(m.copy(title = form.title, description = form.description, dueDate = form.dueDate))
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
get("/:owner/:repository/issues/milestones/:milestoneId/close")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
closeMilestone(m)
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
get("/:owner/:repository/issues/milestones/:milestoneId/open")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
openMilestone(m)
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
get("/:owner/:repository/issues/milestones/:milestoneId/delete")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
deleteMilestone(owner, repository, milestoneId)
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
}

View File

@@ -0,0 +1,122 @@
package app
import jp.sf.amateras.scalatra.forms._
import service._
import util.{WritableRepositoryAuthenticator, ReadableRepositoryAuthenticator, UsersOnlyAuthenticator}
class MilestonesController extends MilestonesControllerBase
with MilestonesService with RepositoryService with AccountService
with ReadableRepositoryAuthenticator with WritableRepositoryAuthenticator
trait MilestonesControllerBase extends ControllerBase {
self: MilestonesService with RepositoryService
with ReadableRepositoryAuthenticator with WritableRepositoryAuthenticator =>
case class MilestoneForm(title: String, description: Option[String], dueDate: Option[java.util.Date])
val milestoneForm = mapping(
"title" -> trim(label("Title", text(required, maxlength(100)))),
"description" -> trim(label("Description", optional(text()))),
"dueDate" -> trim(label("Due Date", optional(date())))
)(MilestoneForm.apply)
get("/:owner/:repository/issues/milestones")(readableRepository {
val owner = params("owner")
val repository = params("repository")
val state = params.getOrElse("state", "open")
getRepository(owner, repository, baseUrl) match {
case None => NotFound()
case Some(r) => issues.html.milestones(state, getMilestones(owner, repository),
getMilestoneIssueCounts(owner, repository), r, isWritable(owner, repository, context.loginAccount))
}
})
get("/:owner/:repository/issues/milestones/new")(writableRepository {
val owner = params("owner")
val repository = params("repository")
getRepository(owner, repository, baseUrl) match {
case None => NotFound()
case Some(r) => issues.html.milestoneedit(None, r)
}
})
post("/:owner/:repository/issues/milestones/new", milestoneForm)(writableRepository { form =>
val owner = params("owner")
val repository = params("repository")
createMilestone(owner, repository, form.title, form.description, form.dueDate)
redirect("/%s/%s/issues/milestones".format(owner, repository))
})
get("/:owner/:repository/issues/milestones/:milestoneId/edit")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getRepository(owner, repository, baseUrl) match {
case None => NotFound()
case Some(r) => issues.html.milestoneedit(getMilestone(owner, repository, milestoneId), r)
}
})
post("/:owner/:repository/issues/milestones/:milestoneId/edit", milestoneForm)(writableRepository { form =>
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
updateMilestone(m.copy(title = form.title, description = form.description, dueDate = form.dueDate))
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
get("/:owner/:repository/issues/milestones/:milestoneId/close")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
closeMilestone(m)
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
get("/:owner/:repository/issues/milestones/:milestoneId/open")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
openMilestone(m)
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
get("/:owner/:repository/issues/milestones/:milestoneId/delete")(writableRepository {
val owner = params("owner")
val repository = params("repository")
val milestoneId = params("milestoneId").toInt
getMilestone(owner, repository, milestoneId) match {
case None => NotFound()
case Some(m) => {
deleteMilestone(owner, repository, milestoneId)
redirect("/%s/%s/issues/milestones".format(owner, repository))
}
}
})
}

View File

@@ -51,62 +51,4 @@ trait IssuesService {
}.map(_.issueId).update(id) > 0
} get
def createMilestone(owner: String, repository: String,
title: String, description: Option[String], dueDate: Option[java.util.Date]) =
Milestones.autoInc insert (owner, repository, title, description, dueDate, None)
def updateMilestone(milestone: Milestone): Unit =
Query(Milestones)
.filter { m => (m.userName is milestone.userName.bind) && (m.repositoryName is milestone.repositoryName.bind) && (m.milestoneId is milestone.milestoneId.bind)}
.map { m => m.title ~ m.description.? ~ m.dueDate.? ~ m.closedDate.? }
.update (
milestone.title,
milestone.description,
milestone.dueDate,
milestone.closedDate)
def openMilestone(milestone: Milestone): Unit = updateMilestone(milestone.copy(closedDate = None))
def closeMilestone(milestone: Milestone): Unit = updateMilestone(milestone.copy(closedDate = Some(currentDate)))
def deleteMilestone(owner: String, repository: String, milestoneId: Int): Unit = {
Query(Issues)
.filter { i => (i.userName is owner.bind) && (i.repositoryName is repository.bind) && (i.milestoneId is milestoneId.bind)}
.map { i => i.milestoneId.? }
.update(None)
Query(Milestones)
.filter { i => (i.userName is owner.bind) && (i.repositoryName is repository.bind) && (i.milestoneId is milestoneId.bind)}
.delete
}
def getMilestone(owner: String, repository: String, milestoneId: Int): Option[Milestone] =
Query(Milestones)
.filter(m => (m.userName is owner.bind) && (m.repositoryName is repository.bind) && (m.milestoneId is milestoneId.bind))
.sortBy(_.milestoneId desc)
.firstOption
def getMilestoneIssueCounts(owner: String, repository: String): Map[(Int, Boolean), Int] = {
import scala.slick.jdbc.GetResult
case class IssueCount(milestoneId: Int, closed: Boolean, count: Int)
implicit val getIssueCount = GetResult(r => IssueCount(r.<<, r.<<, r.<<))
sql"""
select MILESTONE_ID, CLOSED, COUNT(ISSUE_ID)
from ISSUE
where USER_NAME = $owner AND REPOSITORY_NAME = $repository AND MILESTONE_ID IS NOT NULL
group by USER_NAME, REPOSITORY_NAME, MILESTONE_ID, CLOSED"""
.as[IssueCount]
.list
.map { x => (x.milestoneId, x.closed) -> x.count }
.toMap
}
def getMilestones(owner: String, repository: String): List[Milestone] =
Query(Milestones)
.filter(m => (m.userName is owner.bind) && (m.repositoryName is repository.bind))
.sortBy(_.milestoneId desc)
.list
}

View File

@@ -0,0 +1,70 @@
package service
import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession
import scala.slick.jdbc.{StaticQuery => Q}
import Q.interpolation
import model._
import Milestones._
trait MilestonesService {
def createMilestone(owner: String, repository: String,
title: String, description: Option[String], dueDate: Option[java.util.Date]) =
Milestones.autoInc insert (owner, repository, title, description, dueDate, None)
def updateMilestone(milestone: Milestone): Unit =
Query(Milestones)
.filter { m => (m.userName is milestone.userName.bind) && (m.repositoryName is milestone.repositoryName.bind) && (m.milestoneId is milestone.milestoneId.bind)}
.map { m => m.title ~ m.description.? ~ m.dueDate.? ~ m.closedDate.? }
.update (
milestone.title,
milestone.description,
milestone.dueDate,
milestone.closedDate)
def openMilestone(milestone: Milestone): Unit = updateMilestone(milestone.copy(closedDate = None))
def closeMilestone(milestone: Milestone): Unit = updateMilestone(milestone.copy(closedDate = Some(currentDate)))
def deleteMilestone(owner: String, repository: String, milestoneId: Int): Unit = {
Query(Issues)
.filter { i => (i.userName is owner.bind) && (i.repositoryName is repository.bind) && (i.milestoneId is milestoneId.bind)}
.map { i => i.milestoneId.? }
.update(None)
Query(Milestones)
.filter { i => (i.userName is owner.bind) && (i.repositoryName is repository.bind) && (i.milestoneId is milestoneId.bind)}
.delete
}
def getMilestone(owner: String, repository: String, milestoneId: Int): Option[Milestone] =
Query(Milestones)
.filter(m => (m.userName is owner.bind) && (m.repositoryName is repository.bind) && (m.milestoneId is milestoneId.bind))
.sortBy(_.milestoneId desc)
.firstOption
def getMilestoneIssueCounts(owner: String, repository: String): Map[(Int, Boolean), Int] = {
import scala.slick.jdbc.GetResult
case class IssueCount(milestoneId: Int, closed: Boolean, count: Int)
implicit val getIssueCount = GetResult(r => IssueCount(r.<<, r.<<, r.<<))
sql"""
select MILESTONE_ID, CLOSED, COUNT(ISSUE_ID)
from ISSUE
where USER_NAME = $owner AND REPOSITORY_NAME = $repository AND MILESTONE_ID IS NOT NULL
group by USER_NAME, REPOSITORY_NAME, MILESTONE_ID, CLOSED"""
.as[IssueCount]
.list
.map { x => (x.milestoneId, x.closed) -> x.count }
.toMap
}
def getMilestones(owner: String, repository: String): List[Milestone] =
Query(Milestones)
.filter(m => (m.userName is owner.bind) && (m.repositoryName is repository.bind))
.sortBy(_.milestoneId desc)
.list
}