mirror of
				https://github.com/gitbucket/gitbucket.git
				synced 2025-11-03 20:15:59 +01:00 
			
		
		
		
	(refs #26) Implements the dashboard issue display.
This commit is contained in:
		@@ -33,13 +33,21 @@ trait DashboardControllerBase extends ControllerBase {
 | 
			
		||||
 | 
			
		||||
    session.put(sessionKey, condition)
 | 
			
		||||
 | 
			
		||||
    val repositories = getAccessibleRepositories(context.loginAccount, baseUrl)
 | 
			
		||||
    val userName = context.loginAccount.get.userName
 | 
			
		||||
    val repositories = getUserRepositories(userName, baseUrl).map(repo => repo.owner -> repo.name)
 | 
			
		||||
    val filterUser = Map(filter -> userName)
 | 
			
		||||
    val page = IssueSearchCondition.page(request)
 | 
			
		||||
    // 
 | 
			
		||||
    dashboard.html.issues(
 | 
			
		||||
        issues.html.listparts(Nil, 0, 0, 0, condition),
 | 
			
		||||
        0,
 | 
			
		||||
        0,
 | 
			
		||||
        0,
 | 
			
		||||
        issues.html.listparts(
 | 
			
		||||
            searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, repositories: _*),
 | 
			
		||||
            page,
 | 
			
		||||
            countIssue(condition.copy(state = "open"), filterUser, repositories: _*),
 | 
			
		||||
            countIssue(condition.copy(state = "closed"), filterUser, repositories: _*),
 | 
			
		||||
            condition),
 | 
			
		||||
        countIssue(condition, Map.empty, repositories: _*),
 | 
			
		||||
        countIssue(condition, Map("assigned" -> userName), repositories: _*),
 | 
			
		||||
        countIssue(condition, Map("created_by" -> userName), repositories: _*),
 | 
			
		||||
        repositories,
 | 
			
		||||
        condition,
 | 
			
		||||
        filter)    
 | 
			
		||||
 
 | 
			
		||||
@@ -301,16 +301,10 @@ trait IssuesControllerBase extends ControllerBase {
 | 
			
		||||
  private def searchIssues(filter: String, repository: RepositoryService.RepositoryInfo) = {
 | 
			
		||||
    val owner      = repository.owner
 | 
			
		||||
    val repoName   = repository.name
 | 
			
		||||
    val userName   = if(filter != "all") Some(params("userName")) else None
 | 
			
		||||
    val filterUser = Map(filter -> params.getOrElse("userName", ""))
 | 
			
		||||
    val page = IssueSearchCondition.page(request)
 | 
			
		||||
    val sessionKey = s"${owner}/${repoName}/issues"
 | 
			
		||||
 | 
			
		||||
    val page = try {
 | 
			
		||||
      val i = params.getOrElse("page", "1").toInt
 | 
			
		||||
      if(i <= 0) 1 else i
 | 
			
		||||
    } catch {
 | 
			
		||||
      case e: NumberFormatException => 1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // retrieve search condition
 | 
			
		||||
    val condition = if(request.getQueryString == null){
 | 
			
		||||
      session.get(sessionKey).getOrElse(IssueSearchCondition()).asInstanceOf[IssueSearchCondition]
 | 
			
		||||
@@ -319,17 +313,17 @@ trait IssuesControllerBase extends ControllerBase {
 | 
			
		||||
    session.put(sessionKey, condition)
 | 
			
		||||
 | 
			
		||||
    issues.html.list(
 | 
			
		||||
        searchIssue(owner, repoName, condition, filter, userName, (page - 1) * IssueLimit, IssueLimit),
 | 
			
		||||
        searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
 | 
			
		||||
        page,
 | 
			
		||||
        (getCollaborators(owner, repoName) :+ owner).sorted,
 | 
			
		||||
        getMilestones(owner, repoName),
 | 
			
		||||
        getLabels(owner, repoName),
 | 
			
		||||
        countIssue(owner, repoName, condition.copy(state = "open"), filter, userName),
 | 
			
		||||
        countIssue(owner, repoName, condition.copy(state = "closed"), filter, userName),
 | 
			
		||||
        countIssue(owner, repoName, condition, "all", None),
 | 
			
		||||
        context.loginAccount.map(x => countIssue(owner, repoName, condition, "assigned", Some(x.userName))),
 | 
			
		||||
        context.loginAccount.map(x => countIssue(owner, repoName, condition, "created_by", Some(x.userName))),
 | 
			
		||||
        countIssueGroupByLabels(owner, repoName, condition, filter, userName),
 | 
			
		||||
        countIssue(condition.copy(state = "open"), filterUser, owner -> repoName),
 | 
			
		||||
        countIssue(condition.copy(state = "closed"), filterUser, owner -> repoName),
 | 
			
		||||
        countIssue(condition, Map.empty, owner -> repoName),
 | 
			
		||||
        context.loginAccount.map(x => countIssue(condition, Map("assigned" -> x.userName), owner -> repoName)),
 | 
			
		||||
        context.loginAccount.map(x => countIssue(condition, Map("created_by" -> x.userName), owner -> repoName)),
 | 
			
		||||
        countIssueGroupByLabels(owner, repoName, condition, filterUser),
 | 
			
		||||
        condition,
 | 
			
		||||
        filter,
 | 
			
		||||
        repository,
 | 
			
		||||
 
 | 
			
		||||
@@ -42,18 +42,16 @@ trait IssuesService {
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns the count of the search result against  issues.
 | 
			
		||||
   *
 | 
			
		||||
   * @param owner the repository owner
 | 
			
		||||
   * @param repository the repository name
 | 
			
		||||
   * @param condition the search condition
 | 
			
		||||
   * @param filter the filter type ("all", "assigned" or "created_by")
 | 
			
		||||
   * @param userName the filter user name required for "assigned" and "created_by"
 | 
			
		||||
   * @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
 | 
			
		||||
   * @param repos Tuple of the repository owner and the repository name
 | 
			
		||||
   * @return the count of the search result
 | 
			
		||||
   */
 | 
			
		||||
  def countIssue(owner: String, repository: String, condition: IssueSearchCondition, filter: String, userName: Option[String]): Int = {
 | 
			
		||||
  def countIssue(condition: IssueSearchCondition, filterUser: Map[String, String], repos: (String, String)*): Int = {
 | 
			
		||||
    // TODO It must be _.length instead of map (_.issueId) list).length.
 | 
			
		||||
    //       But it does not work on Slick 1.0.1 (worked on Slick 1.0.0).
 | 
			
		||||
    //       https://github.com/slick/slick/issues/170
 | 
			
		||||
    (searchIssueQuery(owner, repository, condition, filter, userName) map (_.issueId) list).length
 | 
			
		||||
    (searchIssueQuery(repos, condition, filterUser) map (_.issueId) list).length
 | 
			
		||||
  }
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns the Map which contains issue count for each labels.
 | 
			
		||||
@@ -61,14 +59,13 @@ trait IssuesService {
 | 
			
		||||
   * @param owner the repository owner
 | 
			
		||||
   * @param repository the repository name
 | 
			
		||||
   * @param condition the search condition
 | 
			
		||||
   * @param filter the filter type ("all", "assigned" or "created_by")
 | 
			
		||||
   * @param userName the filter user name required for "assigned" and "created_by"
 | 
			
		||||
   * @return the Map which contains issue count for each labels (key is label name, value is issue count),
 | 
			
		||||
   * @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
 | 
			
		||||
   * @return the Map which contains issue count for each labels (key is label name, value is issue count)
 | 
			
		||||
   */
 | 
			
		||||
  def countIssueGroupByLabels(owner: String, repository: String, condition: IssueSearchCondition,
 | 
			
		||||
                              filter: String, userName: Option[String]): Map[String, Int] = {
 | 
			
		||||
                              filterUser: Map[String, String]): Map[String, Int] = {
 | 
			
		||||
 | 
			
		||||
    searchIssueQuery(owner, repository, condition.copy(labels = Set.empty), filter, userName)
 | 
			
		||||
    searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), filterUser)
 | 
			
		||||
      .innerJoin(IssueLabels).on { (t1, t2) =>
 | 
			
		||||
        t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
 | 
			
		||||
      }
 | 
			
		||||
@@ -87,20 +84,18 @@ trait IssuesService {
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns the search result against  issues.
 | 
			
		||||
   *
 | 
			
		||||
   * @param owner the repository owner
 | 
			
		||||
   * @param repository the repository name
 | 
			
		||||
   * @param condition the search condition
 | 
			
		||||
   * @param filter the filter type ("all", "assigned" or "created_by")
 | 
			
		||||
   * @param userName the filter user name required for "assigned" and "created_by"
 | 
			
		||||
   * @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
 | 
			
		||||
   * @param offset the offset for pagination
 | 
			
		||||
   * @param limit the limit for pagination
 | 
			
		||||
   * @param repos Tuple of the repository owner and the repository name
 | 
			
		||||
   * @return the search result (list of tuples which contain issue, labels and comment count)
 | 
			
		||||
   */
 | 
			
		||||
  def searchIssue(owner: String, repository: String, condition: IssueSearchCondition,
 | 
			
		||||
                  filter: String, userName: Option[String], offset: Int, limit: Int): List[(Issue, List[Label], Int)] = {
 | 
			
		||||
  def searchIssue(condition: IssueSearchCondition, filterUser: Map[String, String],
 | 
			
		||||
                  offset: Int, limit: Int, repos: (String, String)*): List[(Issue, List[Label], Int)] = {
 | 
			
		||||
 | 
			
		||||
    // get issues and comment count and labels
 | 
			
		||||
    searchIssueQuery(owner, repository, condition, filter, userName)
 | 
			
		||||
    searchIssueQuery(repos, condition, filterUser)
 | 
			
		||||
        .innerJoin(IssueOutline).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) }
 | 
			
		||||
        .leftJoin (IssueLabels) .on { case ((t1, t2), t3) => t1.byIssue(t3.userName, t3.repositoryName, t3.issueId) }
 | 
			
		||||
        .leftJoin (Labels)      .on { case (((t1, t2), t3), t4) => t3.byLabel(t4.userName, t4.repositoryName, t4.labelId) }
 | 
			
		||||
@@ -136,14 +131,14 @@ trait IssuesService {
 | 
			
		||||
  /**
 | 
			
		||||
   * Assembles query for conditional issue searching.
 | 
			
		||||
   */
 | 
			
		||||
  private def searchIssueQuery(owner: String, repository: String, condition: IssueSearchCondition, filter: String, userName: Option[String]) =
 | 
			
		||||
  private def searchIssueQuery(repos: Seq[(String, String)], condition: IssueSearchCondition, filterUser: Map[String, String]) =
 | 
			
		||||
    Query(Issues) filter { t1 =>
 | 
			
		||||
      (t1.byRepository(owner, repository)) &&
 | 
			
		||||
      (repos.map { case (owner, repository) => t1.byRepository(owner, repository) } reduceLeft ( _ || _ ) ) &&
 | 
			
		||||
      (t1.closed           is (condition.state == "closed").bind) &&
 | 
			
		||||
      (t1.milestoneId      is condition.milestoneId.get.get.bind, condition.milestoneId.flatten.isDefined) &&
 | 
			
		||||
      (t1.milestoneId      isNull, condition.milestoneId == Some(None)) &&
 | 
			
		||||
      (t1.assignedUserName is userName.get.bind, filter == "assigned") &&
 | 
			
		||||
      (t1.openedUserName   is userName.get.bind, filter == "created_by") &&
 | 
			
		||||
      (t1.assignedUserName is filterUser("assigned").bind, filterUser.get("assigned").isDefined) &&
 | 
			
		||||
      (t1.openedUserName   is filterUser("created_by").bind, filterUser.get("created_by").isDefined) &&
 | 
			
		||||
      (IssueLabels filter { t2 =>
 | 
			
		||||
        (t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) &&
 | 
			
		||||
        (t2.labelId in
 | 
			
		||||
@@ -329,6 +324,13 @@ object IssuesService {
 | 
			
		||||
        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"))
 | 
			
		||||
 | 
			
		||||
    def page(request: HttpServletRequest) = try {
 | 
			
		||||
      val i = param(request, "page").getOrElse("1").toInt
 | 
			
		||||
      if(i <= 0) 1 else i
 | 
			
		||||
    } catch {
 | 
			
		||||
      case e: NumberFormatException => 1
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
  allCount: Int,
 | 
			
		||||
  assignedCount: Int,
 | 
			
		||||
  createdByCount: Int,
 | 
			
		||||
  repositories: List[service.RepositoryService.RepositoryInfo],
 | 
			
		||||
  repositories: List[(String, String)],
 | 
			
		||||
  condition: service.IssuesService.IssueSearchCondition,
 | 
			
		||||
  filter: String)(implicit context: app.Context)
 | 
			
		||||
@import context._
 | 
			
		||||
@@ -33,11 +33,11 @@
 | 
			
		||||
    </ul>
 | 
			
		||||
    <hr/>
 | 
			
		||||
    <ul class="nav nav-pills nav-stacked small">
 | 
			
		||||
      @repositories.map { repository =>
 | 
			
		||||
      @repositories.map { case (owner, name) =>
 | 
			
		||||
      <li>
 | 
			
		||||
        <a href="@condition.copy(repo = Some(repository.owner + "/" + repository.name)).toURL">
 | 
			
		||||
        <a href="@condition.copy(repo = Some(owner + "/" + name)).toURL">
 | 
			
		||||
          <span class="count-right">0</span>
 | 
			
		||||
          @repository.owner/@repository.name
 | 
			
		||||
          @owner/@name
 | 
			
		||||
        </a>
 | 
			
		||||
      </li>
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -146,7 +146,7 @@
 | 
			
		||||
              <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">@issue.repositoryName</a> ・
 | 
			
		||||
              }
 | 
			
		||||
              <a href="@path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-title">@issue.title</a>
 | 
			
		||||
              @labels.map { label =>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user