mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-06 21:45:50 +01:00
(refs #26) Add Dashboard controller. Uses a common design at issue.
This commit is contained in:
@@ -8,6 +8,7 @@ class ScalatraBootstrap extends LifeCycle {
|
|||||||
context.mount(new SearchController, "/")
|
context.mount(new SearchController, "/")
|
||||||
context.mount(new FileUploadController, "/upload")
|
context.mount(new FileUploadController, "/upload")
|
||||||
context.mount(new SignInController, "/*")
|
context.mount(new SignInController, "/*")
|
||||||
|
context.mount(new DashboardController, "/*")
|
||||||
context.mount(new UserManagementController, "/*")
|
context.mount(new UserManagementController, "/*")
|
||||||
context.mount(new SystemSettingsController, "/*")
|
context.mount(new SystemSettingsController, "/*")
|
||||||
context.mount(new CreateRepositoryController, "/*")
|
context.mount(new CreateRepositoryController, "/*")
|
||||||
|
|||||||
49
src/main/scala/app/DashboardController.scala
Normal file
49
src/main/scala/app/DashboardController.scala
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import service._
|
||||||
|
import util.UsersAuthenticator
|
||||||
|
|
||||||
|
class DashboardController extends DashboardControllerBase
|
||||||
|
with IssuesService with RepositoryService with AccountService
|
||||||
|
with UsersAuthenticator
|
||||||
|
|
||||||
|
trait DashboardControllerBase extends ControllerBase {
|
||||||
|
self: IssuesService with RepositoryService with UsersAuthenticator =>
|
||||||
|
|
||||||
|
get("/dashboard/issues/repos")(usersOnly {
|
||||||
|
searchIssues("all")
|
||||||
|
})
|
||||||
|
|
||||||
|
get("/dashboard/issues/assigned")(usersOnly {
|
||||||
|
searchIssues("assigned")
|
||||||
|
})
|
||||||
|
|
||||||
|
get("/dashboard/issues/created_by")(usersOnly {
|
||||||
|
searchIssues("created_by")
|
||||||
|
})
|
||||||
|
|
||||||
|
private def searchIssues(filter: String) = {
|
||||||
|
import IssuesService._
|
||||||
|
|
||||||
|
// condition
|
||||||
|
val sessionKey = "dashboard/issues"
|
||||||
|
val condition = if(request.getQueryString == null)
|
||||||
|
session.get(sessionKey).getOrElse(IssueSearchCondition()).asInstanceOf[IssueSearchCondition]
|
||||||
|
else IssueSearchCondition(request)
|
||||||
|
|
||||||
|
session.put(sessionKey, condition)
|
||||||
|
|
||||||
|
val repositories = getAccessibleRepositories(context.loginAccount, baseUrl)
|
||||||
|
//
|
||||||
|
dashboard.html.issues(
|
||||||
|
issues.html.listparts(Nil, 0, 0, 0, condition),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
repositories,
|
||||||
|
condition,
|
||||||
|
filter)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import Q.interpolation
|
|||||||
|
|
||||||
import model._
|
import model._
|
||||||
import util.Implicits._
|
import util.Implicits._
|
||||||
import util.StringUtil
|
import util.StringUtil._
|
||||||
|
|
||||||
trait IssuesService {
|
trait IssuesService {
|
||||||
import IssuesService._
|
import IssuesService._
|
||||||
@@ -247,7 +247,7 @@ trait IssuesService {
|
|||||||
*/
|
*/
|
||||||
def searchIssuesByKeyword(owner: String, repository: String, query: String): List[(Issue, Int, String)] = {
|
def searchIssuesByKeyword(owner: String, repository: String, query: String): List[(Issue, Int, String)] = {
|
||||||
import scala.slick.driver.H2Driver.likeEncode
|
import scala.slick.driver.H2Driver.likeEncode
|
||||||
val keywords = StringUtil.splitWords(query.toLowerCase)
|
val keywords = splitWords(query.toLowerCase)
|
||||||
|
|
||||||
// Search Issue
|
// Search Issue
|
||||||
val issues = Query(Issues).filter { t =>
|
val issues = Query(Issues).filter { t =>
|
||||||
@@ -290,13 +290,13 @@ trait IssuesService {
|
|||||||
|
|
||||||
object IssuesService {
|
object IssuesService {
|
||||||
import javax.servlet.http.HttpServletRequest
|
import javax.servlet.http.HttpServletRequest
|
||||||
import util.StringUtil._
|
|
||||||
|
|
||||||
val IssueLimit = 30
|
val IssueLimit = 30
|
||||||
|
|
||||||
case class IssueSearchCondition(
|
case class IssueSearchCondition(
|
||||||
labels: Set[String] = Set.empty,
|
labels: Set[String] = Set.empty,
|
||||||
milestoneId: Option[Option[Int]] = None,
|
milestoneId: Option[Option[Int]] = None,
|
||||||
|
repo: Option[String] = None,
|
||||||
state: String = "open",
|
state: String = "open",
|
||||||
sort: String = "created",
|
sort: String = "created",
|
||||||
direction: String = "desc"){
|
direction: String = "desc"){
|
||||||
@@ -308,6 +308,7 @@ object IssuesService {
|
|||||||
case Some(x) => x.toString
|
case Some(x) => x.toString
|
||||||
case None => "none"
|
case None => "none"
|
||||||
})},
|
})},
|
||||||
|
repo.map("for=" + urlEncode(_)),
|
||||||
Some("state=" + urlEncode(state)),
|
Some("state=" + urlEncode(state)),
|
||||||
Some("sort=" + urlEncode(sort)),
|
Some("sort=" + urlEncode(sort)),
|
||||||
Some("direction=" + urlEncode(direction))).flatten.mkString("&")
|
Some("direction=" + urlEncode(direction))).flatten.mkString("&")
|
||||||
@@ -328,6 +329,7 @@ object IssuesService {
|
|||||||
case "none" => None
|
case "none" => None
|
||||||
case x => Some(x.toInt)
|
case x => Some(x.toInt)
|
||||||
}),
|
}),
|
||||||
|
param(request, "for"),
|
||||||
param(request, "state", Seq("open", "closed")).getOrElse("open"),
|
param(request, "state", Seq("open", "closed")).getOrElse("open"),
|
||||||
param(request, "sort", Seq("created", "comments", "updated")).getOrElse("created"),
|
param(request, "sort", Seq("created", "comments", "updated")).getOrElse("created"),
|
||||||
param(request, "direction", Seq("asc", "desc")).getOrElse("desc"))
|
param(request, "direction", Seq("asc", "desc")).getOrElse("desc"))
|
||||||
|
|||||||
48
src/main/twirl/dashboard/issues.scala.html
Normal file
48
src/main/twirl/dashboard/issues.scala.html
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
@(listparts: twirl.api.Html,
|
||||||
|
allCount: Int,
|
||||||
|
assignedCount: Int,
|
||||||
|
createdByCount: Int,
|
||||||
|
repositories: List[service.RepositoryService.RepositoryInfo],
|
||||||
|
condition: service.IssuesService.IssueSearchCondition,
|
||||||
|
filter: String)(implicit context: app.Context)
|
||||||
|
@import context._
|
||||||
|
@import view.helpers._
|
||||||
|
@html.main("Your Issues"){
|
||||||
|
@dashboard.html.tab("issues")
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span3">
|
||||||
|
<ul class="nav nav-pills nav-stacked">
|
||||||
|
<li@if(filter == "all"){ class="active"}>
|
||||||
|
<a href="/dashboard/issues/repos@condition.toURL">
|
||||||
|
<span class="count-right">@allCount</span>
|
||||||
|
In your repositories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li@if(filter == "assigned"){ class="active"}>
|
||||||
|
<a href="/dashboard/issues/assigned@condition.toURL">
|
||||||
|
<span class="count-right">@assignedCount</span>
|
||||||
|
Assigned to you
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li@if(filter == "created_by"){ class="active"}>
|
||||||
|
<a href="/dashboard/issues/created_by@condition.toURL">
|
||||||
|
<span class="count-right">@createdByCount</span>
|
||||||
|
Created by you
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
<ul class="nav nav-pills nav-stacked small">
|
||||||
|
@repositories.map { repository =>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(repo = Some(repository.owner + "/" + repository.name)).toURL">
|
||||||
|
<span class="count-right">0</span>
|
||||||
|
@repository.owner/@repository.name
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@listparts
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@@ -131,158 +131,8 @@
|
|||||||
@_root_.issues.labels.html.edit(None, repository)
|
@_root_.issues.labels.html.edit(None, repository)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="span9">
|
@***** show issue list *****@
|
||||||
@if(condition.labels.nonEmpty || condition.milestoneId.isDefined){
|
@listparts(issues, page, openCount, closedCount, condition, collaborators, milestones, labels, Some(repository), hasWritePermission)
|
||||||
<a href="@condition.copy(labels = Set.empty, milestoneId = None).toURL" id="clear-filter">
|
|
||||||
<i class="icon-remove-circle"></i> Clear milestone and label filters
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
<div class="pull-right">
|
|
||||||
@helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 7, condition.toURL)
|
|
||||||
</div>
|
|
||||||
<div class="btn-group">
|
|
||||||
<a class="btn@if(condition.state == "open"){ active}" href="@condition.copy(state = "open").toURL">@openCount Open</a>
|
|
||||||
<a class="btn@if(condition.state == "closed"){ active}" href="@condition.copy(state = "closed").toURL">@closedCount Closed</a>
|
|
||||||
</div>
|
|
||||||
<div class="btn-group">
|
|
||||||
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
|
||||||
Sort:
|
|
||||||
<strong>
|
|
||||||
@if(condition.sort == "created" && condition.direction == "desc"){ Newest }
|
|
||||||
@if(condition.sort == "created" && condition.direction == "asc" ){ Oldest }
|
|
||||||
@if(condition.sort == "comments" && condition.direction == "desc"){ Most commented }
|
|
||||||
@if(condition.sort == "comments" && condition.direction == "asc" ){ Least commented }
|
|
||||||
@if(condition.sort == "updated" && condition.direction == "desc"){ Recently updated }
|
|
||||||
@if(condition.sort == "updated" && condition.direction == "asc" ){ Least recently updated }
|
|
||||||
</strong>
|
|
||||||
<span class="caret"></span>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li>
|
|
||||||
<a href="@condition.copy(sort="created", direction="desc").toURL">
|
|
||||||
@helper.html.checkicon(condition.sort == "created" && condition.direction == "desc") Newest
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="@condition.copy(sort="created", direction="asc" ).toURL">
|
|
||||||
@helper.html.checkicon(condition.sort == "created" && condition.direction == "asc") Oldest
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="@condition.copy(sort="comments", direction="desc").toURL">
|
|
||||||
@helper.html.checkicon(condition.sort == "comments" && condition.direction == "desc") Most commented
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="@condition.copy(sort="comments", direction="asc" ).toURL">
|
|
||||||
@helper.html.checkicon(condition.sort == "comments" && condition.direction == "asc") Least commented
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="@condition.copy(sort="updated", direction="desc").toURL">
|
|
||||||
@helper.html.checkicon(condition.sort == "updated" && condition.direction == "desc") Recently updated
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="@condition.copy(sort="updated", direction="asc" ).toURL">
|
|
||||||
@helper.html.checkicon(condition.sort == "updated" && condition.direction == "asc") Least recently updated
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<table class="table table-bordered table-hover table-issues">
|
|
||||||
@if(issues.isEmpty){
|
|
||||||
<tr>
|
|
||||||
<td style="padding: 20px; background-color: #eee; text-align: center;">
|
|
||||||
No issues to show.
|
|
||||||
@if(condition.labels.nonEmpty || condition.milestoneId.isDefined){
|
|
||||||
<a href="@condition.copy(labels = Set.empty, milestoneId = None).toURL">Clear active filters.</a>
|
|
||||||
} else {
|
|
||||||
<a href="@url(repository)/issues/new">Create a new issue.</a>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
} else {
|
|
||||||
@if(hasWritePermission){
|
|
||||||
<tr>
|
|
||||||
<td style="background-color: #eee;">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button class="btn btn-mini" id="state"><strong>@{if(condition.state == "open") "Close" else "Reopen"}</strong></button>
|
|
||||||
</div>
|
|
||||||
@helper.html.dropdown("Label") {
|
|
||||||
@labels.map { label =>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0);" class="toggle-label" data-id="@label.labelId">
|
|
||||||
<i class="icon-white"></i>
|
|
||||||
<span class="label" style="background-color: #@label.color;"> </span>
|
|
||||||
@label.labelName
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@helper.html.dropdown("Assignee") {
|
|
||||||
<li><a href="javascript:void(0);" class="toggle-assign" data-name=""><i class="icon-remove-circle"></i> Clear assignee</a></li>
|
|
||||||
@collaborators.map { collaborator =>
|
|
||||||
<li><a href="javascript:void(0);" class="toggle-assign" data-name="@collaborator"><i class="icon-white"></i>@avatar(collaborator, 20) @collaborator</a></li>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@helper.html.dropdown("Milestone") {
|
|
||||||
<li><a href="javascript:void(0);" class="toggle-milestone" data-id=""><i class="icon-remove-circle"></i> Clear this milestone</a></li>
|
|
||||||
@milestones.map { milestone =>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0);" class="toggle-milestone" data-id="@milestone.milestoneId">
|
|
||||||
<i class="icon-white"></i> @milestone.title
|
|
||||||
<div class="small" style="padding-left: 20px;">
|
|
||||||
@milestone.dueDate.map { dueDate =>
|
|
||||||
@if(isPast(dueDate)){
|
|
||||||
<img src="@assets/common/images/alert_mono.png"/>Due in @date(dueDate)
|
|
||||||
} else {
|
|
||||||
<span class="muted">Due in @date(dueDate)</span>
|
|
||||||
}
|
|
||||||
}.getOrElse {
|
|
||||||
<span class="muted">No due date</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@issues.map { case (issue, labels, commentCount) =>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
@if(hasWritePermission){
|
|
||||||
<label class="checkbox" style="cursor: default;">
|
|
||||||
<input type="checkbox" value="@issue.issueId"/>
|
|
||||||
}
|
|
||||||
<a href="@url(repository)/issues/@issue.issueId" class="issue-title">@issue.title</a>
|
|
||||||
@labels.map { label =>
|
|
||||||
<span class="label-color small" style="background-color: #@label.color; color: #@label.fontColor; padding-left: 4px; padding-right: 4px">@label.labelName</span>
|
|
||||||
}
|
|
||||||
<span class="pull-right muted">
|
|
||||||
@issue.assignedUserName.map { userName =>
|
|
||||||
<a href="@url(userName)">@avatar(userName, 20, tooltip = true)</a>
|
|
||||||
}
|
|
||||||
#@issue.issueId
|
|
||||||
</span>
|
|
||||||
<div class="small muted">
|
|
||||||
Opened by <a href="@url(issue.openedUserName)" class="username">@issue.openedUserName</a> @datetime(issue.registeredDate)
|
|
||||||
@if(commentCount > 0){
|
|
||||||
<i class="icon-comment"></i><a href="@url(repository)/issues/@issue.issueId" class="issue-comment-count">@commentCount @plural(commentCount, "comment")</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
<div class="pull-right">
|
|
||||||
@helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@if(hasWritePermission){
|
@if(hasWritePermission){
|
||||||
<form id="batcheditForm" method="POST">
|
<form id="batcheditForm" method="POST">
|
||||||
|
|||||||
176
src/main/twirl/issues/listparts.scala.html
Normal file
176
src/main/twirl/issues/listparts.scala.html
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
@(issues: List[(model.Issue, List[model.Label], Int)],
|
||||||
|
page: Int,
|
||||||
|
openCount: Int,
|
||||||
|
closedCount: Int,
|
||||||
|
condition: service.IssuesService.IssueSearchCondition,
|
||||||
|
collaborators: List[String] = Nil,
|
||||||
|
milestones: List[model.Milestone] = Nil,
|
||||||
|
labels: List[model.Label] = Nil,
|
||||||
|
repository: Option[service.RepositoryService.RepositoryInfo] = None,
|
||||||
|
hasWritePermission: Boolean = false)(implicit context: app.Context)
|
||||||
|
@import context._
|
||||||
|
@import view.helpers._
|
||||||
|
|
||||||
|
<div class="span9">
|
||||||
|
@if(condition.labels.nonEmpty || condition.milestoneId.isDefined){
|
||||||
|
<a href="@condition.copy(labels = Set.empty, milestoneId = None).toURL" id="clear-filter">
|
||||||
|
<i class="icon-remove-circle"></i> Clear milestone and label filters
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
@if(condition.repo.isDefined){
|
||||||
|
<a href="@condition.copy(repo = None).toURL" id="clear-filter">
|
||||||
|
<i class="icon-remove-circle"></i> Clear filter on @condition.repo
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
<div class="pull-right">
|
||||||
|
@helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 7, condition.toURL)
|
||||||
|
</div>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn@if(condition.state == "open"){ active}" href="@condition.copy(state = "open").toURL">@openCount Open</a>
|
||||||
|
<a class="btn@if(condition.state == "closed"){ active}" href="@condition.copy(state = "closed").toURL">@closedCount Closed</a>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||||
|
Sort:
|
||||||
|
<strong>
|
||||||
|
@if(condition.sort == "created" && condition.direction == "desc"){ Newest }
|
||||||
|
@if(condition.sort == "created" && condition.direction == "asc" ){ Oldest }
|
||||||
|
@if(condition.sort == "comments" && condition.direction == "desc"){ Most commented }
|
||||||
|
@if(condition.sort == "comments" && condition.direction == "asc" ){ Least commented }
|
||||||
|
@if(condition.sort == "updated" && condition.direction == "desc"){ Recently updated }
|
||||||
|
@if(condition.sort == "updated" && condition.direction == "asc" ){ Least recently updated }
|
||||||
|
</strong>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="created", direction="desc").toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "created" && condition.direction == "desc") Newest
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="created", direction="asc" ).toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "created" && condition.direction == "asc") Oldest
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="comments", direction="desc").toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "comments" && condition.direction == "desc") Most commented
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="comments", direction="asc" ).toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "comments" && condition.direction == "asc") Least commented
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="updated", direction="desc").toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "updated" && condition.direction == "desc") Recently updated
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="@condition.copy(sort="updated", direction="asc" ).toURL">
|
||||||
|
@helper.html.checkicon(condition.sort == "updated" && condition.direction == "asc") Least recently updated
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<table class="table table-bordered table-hover table-issues">
|
||||||
|
@if(issues.isEmpty){
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 20px; background-color: #eee; text-align: center;">
|
||||||
|
No issues to show.
|
||||||
|
@if(condition.labels.nonEmpty || condition.milestoneId.isDefined){
|
||||||
|
<a href="@condition.copy(labels = Set.empty, milestoneId = None).toURL">Clear active filters.</a>
|
||||||
|
} else {
|
||||||
|
@if(repository.isDefined){
|
||||||
|
<a href="@url(repository.get)/issues/new">Create a new issue.</a>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
} else {
|
||||||
|
@if(hasWritePermission){
|
||||||
|
<tr>
|
||||||
|
<td style="background-color: #eee;">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-mini" id="state"><strong>@{if(condition.state == "open") "Close" else "Reopen"}</strong></button>
|
||||||
|
</div>
|
||||||
|
@helper.html.dropdown("Label") {
|
||||||
|
@labels.map { label =>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="toggle-label" data-id="@label.labelId">
|
||||||
|
<i class="icon-white"></i>
|
||||||
|
<span class="label" style="background-color: #@label.color;"> </span>
|
||||||
|
@label.labelName
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@helper.html.dropdown("Assignee") {
|
||||||
|
<li><a href="javascript:void(0);" class="toggle-assign" data-name=""><i class="icon-remove-circle"></i> Clear assignee</a></li>
|
||||||
|
@collaborators.map { collaborator =>
|
||||||
|
<li><a href="javascript:void(0);" class="toggle-assign" data-name="@collaborator"><i class="icon-white"></i>@avatar(collaborator, 20) @collaborator</a></li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@helper.html.dropdown("Milestone") {
|
||||||
|
<li><a href="javascript:void(0);" class="toggle-milestone" data-id=""><i class="icon-remove-circle"></i> Clear this milestone</a></li>
|
||||||
|
@milestones.map { milestone =>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="toggle-milestone" data-id="@milestone.milestoneId">
|
||||||
|
<i class="icon-white"></i> @milestone.title
|
||||||
|
<div class="small" style="padding-left: 20px;">
|
||||||
|
@milestone.dueDate.map { dueDate =>
|
||||||
|
@if(isPast(dueDate)){
|
||||||
|
<img src="@assets/common/images/alert_mono.png"/>Due in @date(dueDate)
|
||||||
|
} else {
|
||||||
|
<span class="muted">Due in @date(dueDate)</span>
|
||||||
|
}
|
||||||
|
}.getOrElse {
|
||||||
|
<span class="muted">No due date</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@issues.map { case (issue, labels, commentCount) =>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
@if(hasWritePermission){
|
||||||
|
<label class="checkbox" style="cursor: default;">
|
||||||
|
<input type="checkbox" value="@issue.issueId"/>
|
||||||
|
}
|
||||||
|
@if(repository.isEmpty){
|
||||||
|
<a href="@path/@issue.userName/@issue.repositoryName">@issue.repositoryName</a> ・
|
||||||
|
}
|
||||||
|
<a href="@path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-title">@issue.title</a>
|
||||||
|
@labels.map { label =>
|
||||||
|
<span class="label-color small" style="background-color: #@label.color; color: #@label.fontColor; padding-left: 4px; padding-right: 4px">@label.labelName</span>
|
||||||
|
}
|
||||||
|
<span class="pull-right muted">
|
||||||
|
@issue.assignedUserName.map { userName =>
|
||||||
|
@avatar(userName, 20, tooltip = true)
|
||||||
|
}
|
||||||
|
#@issue.issueId
|
||||||
|
</span>
|
||||||
|
<div class="small muted">
|
||||||
|
Opened by <a href="@url(issue.openedUserName)" class="username">@issue.openedUserName</a> @datetime(issue.registeredDate)
|
||||||
|
@if(commentCount > 0){
|
||||||
|
<i class="icon-comment"></i><a href="@path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-comment-count">@commentCount @plural(commentCount, "comment")</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</table>
|
||||||
|
<div class="pull-right">
|
||||||
|
@helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
Reference in New Issue
Block a user