mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-09 23:15:49 +01:00
Milestone completed.
This commit is contained in:
@@ -71,7 +71,8 @@ trait IssuesControllerBase extends ControllerBase {
|
|||||||
|
|
||||||
getRepository(owner, repository, baseUrl) match {
|
getRepository(owner, repository, baseUrl) match {
|
||||||
case None => NotFound()
|
case None => NotFound()
|
||||||
case Some(r) => issues.html.milestones(state, getMilestones(owner, repository), r, isWritable(owner, repository, context.loginAccount))
|
case Some(r) => issues.html.milestones(state, getMilestones(owner, repository),
|
||||||
|
getMilestoneIssueCounts(owner, repository), r, isWritable(owner, repository, context.loginAccount))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,24 @@ trait IssuesService {
|
|||||||
.sortBy(_.milestoneId desc)
|
.sortBy(_.milestoneId desc)
|
||||||
.firstOption
|
.firstOption
|
||||||
|
|
||||||
|
def getMilestoneIssueCounts(owner: String, repository: String): Map[(Int, Boolean), Int] = {
|
||||||
|
import scala.slick.jdbc.{GetResult, StaticQuery}
|
||||||
|
import StaticQuery.interpolation
|
||||||
|
|
||||||
|
case class IssueCount(userName: String, repositoryName: String, milestoneId: Int, closed: Boolean, count: Int)
|
||||||
|
implicit val getIssueCount = GetResult(r => IssueCount(r.<<, r.<<, r.<<, r.<<, r.<<))
|
||||||
|
|
||||||
|
sql"""
|
||||||
|
select USER_NAME, REPOSITORY_NAME, 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] =
|
def getMilestones(owner: String, repository: String): List[Milestone] =
|
||||||
Query(Milestones)
|
Query(Milestones)
|
||||||
.filter(m => (m.userName is owner.bind) && (m.repositoryName is repository.bind))
|
.filter(m => (m.userName is owner.bind) && (m.repositoryName is repository.bind))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@(state: String, milestones: List[model.Milestone], repository: service.RepositoryService.RepositoryInfo, isWritable: Boolean)(implicit context: app.Context)
|
@(state: String, milestones: List[model.Milestone], counts: Map[(Int, Boolean), Int], repository: service.RepositoryService.RepositoryInfo, isWritable: Boolean)(implicit context: app.Context)
|
||||||
@import context._
|
@import context._
|
||||||
@import view.helpers
|
@import view.helpers
|
||||||
@html.main("Milestones - " + repository.owner + "/" + repository.name){
|
@html.main("Milestones - " + repository.owner + "/" + repository.name){
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
|
@defining((counts.getOrElse((milestone.milestoneId, true), 0), counts.getOrElse((milestone.milestoneId, false), 0))) { case (closedCount, openCount) =>
|
||||||
<div class="milestone-menu">
|
<div class="milestone-menu">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
@if(isWritable){
|
@if(isWritable){
|
||||||
@@ -58,11 +59,23 @@
|
|||||||
}
|
}
|
||||||
<a href="">Browse issues</a>
|
<a href="">Browse issues</a>
|
||||||
</div>
|
</div>
|
||||||
<span class="description">0 closed - 0 open</span>
|
<span class="description">@closedCount closed - @openCount open</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="milestone-progress">10%</div>
|
<div class="milestone-progress">
|
||||||
|
@if(closedCount > 0){
|
||||||
|
<span class="milestone-progress" style="width: @((closedCount.toDouble / (openCount + closedCount).toDouble * 100).toInt)%;"></span>
|
||||||
|
}
|
||||||
|
<span class="milestone-percentage">
|
||||||
|
@if(closedCount == 0){
|
||||||
|
0%
|
||||||
|
} else {
|
||||||
|
@((closedCount.toDouble / (openCount + closedCount).toDouble * 100).toInt)%
|
||||||
|
}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@if(milestone.description.isDefined){
|
@if(milestone.description.isDefined){
|
||||||
<div class="milestone-description">
|
<div class="milestone-description">
|
||||||
@helpers.markdown(milestone.description.get, repository, false, false, false)
|
@helpers.markdown(milestone.description.get, repository, false, false, false)
|
||||||
@@ -93,39 +106,3 @@ $(function(){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style type="text/css">
|
|
||||||
a.milestone-title {
|
|
||||||
font-size: 120%;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
div.milestone-description {
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.milestone-menu {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.milestone-menu a {
|
|
||||||
margin-left: 8px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.milestone-menu a.delete {
|
|
||||||
color: #b00;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.milestone-progress {
|
|
||||||
color: white;
|
|
||||||
padding-left: 4px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 12px;
|
|
||||||
text-shadow: 0px 0px 5px #444;
|
|
||||||
background-color: silver;
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -238,6 +238,56 @@ ul.collaborator a.remove {
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.milestone-title {
|
||||||
|
font-size: 120%;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.milestone-description {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.milestone-menu {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.milestone-menu a {
|
||||||
|
margin-left: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.milestone-menu a.delete {
|
||||||
|
color: #b00;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.milestone-progress {
|
||||||
|
position: relative;
|
||||||
|
height: 20px;
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
text-shadow: 0px 0px 5px #444;
|
||||||
|
background-color: silver;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.milestone-progress {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
background-color: green;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.milestone-percentage {
|
||||||
|
position: absolute;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
div.markdown-body table {
|
div.markdown-body table {
|
||||||
/*width: 100%;*/
|
/*width: 100%;*/
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|||||||
Reference in New Issue
Block a user