diff --git a/src/main/scala/ScalatraBootstrap.scala b/src/main/scala/ScalatraBootstrap.scala index 0a24e73..1233a28 100644 --- a/src/main/scala/ScalatraBootstrap.scala +++ b/src/main/scala/ScalatraBootstrap.scala @@ -8,6 +8,7 @@ context.mount(new SearchController, "/") context.mount(new FileUploadController, "/upload") context.mount(new SignInController, "/*") + context.mount(new DashboardController, "/*") context.mount(new UserManagementController, "/*") context.mount(new SystemSettingsController, "/*") context.mount(new CreateRepositoryController, "/*") diff --git a/src/main/scala/app/DashboardController.scala b/src/main/scala/app/DashboardController.scala new file mode 100644 index 0000000..02e1668 --- /dev/null +++ b/src/main/scala/app/DashboardController.scala @@ -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) + + } + +} \ No newline at end of file diff --git a/src/main/scala/service/IssuesService.scala b/src/main/scala/service/IssuesService.scala index c0f90e0..25eae21 100644 --- a/src/main/scala/service/IssuesService.scala +++ b/src/main/scala/service/IssuesService.scala @@ -7,7 +7,7 @@ import model._ import util.Implicits._ -import util.StringUtil +import util.StringUtil._ trait IssuesService { import IssuesService._ @@ -247,7 +247,7 @@ */ def searchIssuesByKeyword(owner: String, repository: String, query: String): List[(Issue, Int, String)] = { import scala.slick.driver.H2Driver.likeEncode - val keywords = StringUtil.splitWords(query.toLowerCase) + val keywords = splitWords(query.toLowerCase) // Search Issue val issues = Query(Issues).filter { t => @@ -290,13 +290,13 @@ object IssuesService { import javax.servlet.http.HttpServletRequest - import util.StringUtil._ val IssueLimit = 30 case class IssueSearchCondition( labels: Set[String] = Set.empty, milestoneId: Option[Option[Int]] = None, + repo: Option[String] = None, state: String = "open", sort: String = "created", direction: String = "desc"){ @@ -308,6 +308,7 @@ case Some(x) => x.toString case None => "none" })}, + repo.map("for=" + urlEncode(_)), Some("state=" + urlEncode(state)), Some("sort=" + urlEncode(sort)), Some("direction=" + urlEncode(direction))).flatten.mkString("&") @@ -328,6 +329,7 @@ case "none" => None case x => Some(x.toInt) }), + param(request, "for"), param(request, "state", Seq("open", "closed")).getOrElse("open"), param(request, "sort", Seq("created", "comments", "updated")).getOrElse("created"), param(request, "direction", Seq("asc", "desc")).getOrElse("desc")) diff --git a/src/main/twirl/dashboard/issues.scala.html b/src/main/twirl/dashboard/issues.scala.html new file mode 100644 index 0000000..b1839ab --- /dev/null +++ b/src/main/twirl/dashboard/issues.scala.html @@ -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") +
+
+ +
+ +
+ @listparts +
+} diff --git a/src/main/twirl/issues/list.scala.html b/src/main/twirl/issues/list.scala.html index b028b65..d9ce5fc 100644 --- a/src/main/twirl/issues/list.scala.html +++ b/src/main/twirl/issues/list.scala.html @@ -131,158 +131,8 @@ @_root_.issues.labels.html.edit(None, repository) } -
- @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ - - Clear milestone and label filters - - } -
- @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 7, condition.toURL) -
-
- @openCount Open - @closedCount Closed -
-
- - -
- - @if(issues.isEmpty){ - - - - } else { - @if(hasWritePermission){ - - - - } - } - @issues.map { case (issue, labels, commentCount) => - - - - } -
- No issues to show. - @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ - Clear active filters. - } else { - Create a new issue. - } -
-
- -
- @helper.html.dropdown("Label") { - @labels.map { label => -
  • - - -   - @label.labelName - -
  • - } - } - @helper.html.dropdown("Assignee") { -
  • Clear assignee
  • - @collaborators.map { collaborator => -
  • @avatar(collaborator, 20) @collaborator
  • - } - } - @helper.html.dropdown("Milestone") { -
  • Clear this milestone
  • - @milestones.map { milestone => -
  • - - @milestone.title -
    - @milestone.dueDate.map { dueDate => - @if(isPast(dueDate)){ - Due in @date(dueDate) - } else { - Due in @date(dueDate) - } - }.getOrElse { - No due date - } -
    -
    -
  • - } - } -
    - @if(hasWritePermission){ - -
    -
    - @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL) -
    -
    + @***** show issue list *****@ + @listparts(issues, page, openCount, closedCount, condition, collaborators, milestones, labels, Some(repository), hasWritePermission) @if(hasWritePermission){
    diff --git a/src/main/twirl/issues/listparts.scala.html b/src/main/twirl/issues/listparts.scala.html new file mode 100644 index 0000000..3541dba --- /dev/null +++ b/src/main/twirl/issues/listparts.scala.html @@ -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._ + +
    + @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ + + Clear milestone and label filters + + } + @if(condition.repo.isDefined){ + + Clear filter on @condition.repo + + } +
    + @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 7, condition.toURL) +
    + +
    + + +
    + + @if(issues.isEmpty){ + + + + } else { + @if(hasWritePermission){ + + + + } + } + @issues.map { case (issue, labels, commentCount) => + + + + } +
    + No issues to show. + @if(condition.labels.nonEmpty || condition.milestoneId.isDefined){ + Clear active filters. + } else { + @if(repository.isDefined){ + Create a new issue. + } + } +
    +
    + +
    + @helper.html.dropdown("Label") { + @labels.map { label => +
  • + + +   + @label.labelName + +
  • + } + } + @helper.html.dropdown("Assignee") { +
  • Clear assignee
  • + @collaborators.map { collaborator => +
  • @avatar(collaborator, 20) @collaborator
  • + } + } + @helper.html.dropdown("Milestone") { +
  • Clear this milestone
  • + @milestones.map { milestone => +
  • + + @milestone.title +
    + @milestone.dueDate.map { dueDate => + @if(isPast(dueDate)){ + Due in @date(dueDate) + } else { + Due in @date(dueDate) + } + }.getOrElse { + No due date + } +
    +
    +
  • + } + } +
    + @if(hasWritePermission){ + +
    +
    + @helper.html.paginator(page, (if(condition.state == "open") openCount else closedCount), service.IssuesService.IssueLimit, 10, condition.toURL) +
    +
    +