mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-12 00:15:50 +01:00
Separate milestones from IssuesController / IssuesService.
This commit is contained in:
@@ -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(){
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
122
src/main/scala/app/MilestonesController.scala
Normal file
122
src/main/scala/app/MilestonesController.scala
Normal 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))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
70
src/main/scala/service/MilestonesService.scala
Normal file
70
src/main/scala/service/MilestonesService.scala
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user