diff --git a/doc/comment_action.md b/doc/comment_action.md index d56bd7e..5e306e8 100644 --- a/doc/comment_action.md +++ b/doc/comment_action.md @@ -6,17 +6,22 @@ To determine if it was any operation, you see the `ACTION` column. And in the case of some actions, `CONTENT` column value contains additional information. -|ACTION |CONTENT | -|---------------|-----------------| -|comment |comment | -|close_comment |comment | -|reopen_comment |comment | -|close |"Close" | -|reopen |"Reopen" | -|commit |comment commitId | -|merge |comment | -|delete_branch |branchName | -|refer |issueId:title | +|ACTION |CONTENT | +|-------------------|------------------------| +|comment |comment | +|close_comment |comment | +|reopen_comment |comment | +|close |"Close" | +|reopen |"Reopen" | +|commit |comment commitId | +|merge |comment | +|delete_branch |branchName | +|refer |issueId:title | +|add_label |labelName | +|delete_label |labelName | +|change_priority |oldPriority:priority | +|change_milestone|oldMilestone:milestone| +|assign |oldAssigned:assigned | ### comment @@ -54,3 +59,23 @@ This value is saved when other issue or issue comment contains reference to the issue like `#issueId`. At the same time, store id and title of the referrer issue as `id:title`. + +### add_label + +This value is saved when users have added the label. + +### delete_label + +This value is saved when users have deleted the label. + +### change_priority + +This value is saved when users have changed the priority. + +### change_milestone + +This value is saved when users have changed the milestone. + +### assign + +This value is saved when users have assign issue/PR to user or remove the assign. diff --git a/src/main/scala/gitbucket/core/controller/DashboardController.scala b/src/main/scala/gitbucket/core/controller/DashboardController.scala index 81e3085..f422ba5 100644 --- a/src/main/scala/gitbucket/core/controller/DashboardController.scala +++ b/src/main/scala/gitbucket/core/controller/DashboardController.scala @@ -8,7 +8,7 @@ class DashboardController extends DashboardControllerBase with IssuesService with PullRequestService with RepositoryService with AccountService with CommitsService - with UsersAuthenticator + with LabelsService with PrioritiesService with MilestonesService with UsersAuthenticator trait DashboardControllerBase extends ControllerBase { self: IssuesService with PullRequestService with RepositoryService with AccountService diff --git a/src/main/scala/gitbucket/core/controller/IssuesController.scala b/src/main/scala/gitbucket/core/controller/IssuesController.scala index 4472863..ba23f9d 100644 --- a/src/main/scala/gitbucket/core/controller/IssuesController.scala +++ b/src/main/scala/gitbucket/core/controller/IssuesController.scala @@ -271,25 +271,25 @@ ajaxPost("/:owner/:repository/issues/:id/label/new")(writableUsersOnly { repository => defining(params("id").toInt){ issueId => - registerIssueLabel(repository.owner, repository.name, issueId, params("labelId").toInt) + registerIssueLabel(repository.owner, repository.name, issueId, params("labelId").toInt, true) html.labellist(getIssueLabels(repository.owner, repository.name, issueId)) } }) ajaxPost("/:owner/:repository/issues/:id/label/delete")(writableUsersOnly { repository => defining(params("id").toInt){ issueId => - deleteIssueLabel(repository.owner, repository.name, issueId, params("labelId").toInt) + deleteIssueLabel(repository.owner, repository.name, issueId, params("labelId").toInt, true) html.labellist(getIssueLabels(repository.owner, repository.name, issueId)) } }) ajaxPost("/:owner/:repository/issues/:id/assign")(writableUsersOnly { repository => - updateAssignedUserName(repository.owner, repository.name, params("id").toInt, assignedUserName("assignedUserName")) + updateAssignedUserName(repository.owner, repository.name, params("id").toInt, assignedUserName("assignedUserName"), true) Ok("updated") }) ajaxPost("/:owner/:repository/issues/:id/milestone")(writableUsersOnly { repository => - updateMilestoneId(repository.owner, repository.name, params("id").toInt, milestoneId("milestoneId")) + updateMilestoneId(repository.owner, repository.name, params("id").toInt, milestoneId("milestoneId"), true) milestoneId("milestoneId").map { milestoneId => getMilestonesWithIssueCount(repository.owner, repository.name) .find(_._1.milestoneId == milestoneId).map { case (_, openCount, closeCount) => @@ -299,7 +299,8 @@ }) ajaxPost("/:owner/:repository/issues/:id/priority")(writableUsersOnly { repository => - updatePriorityId(repository.owner, repository.name, params("id").toInt, priorityId("priorityId")) + val priority = priorityId("priorityId") + updatePriorityId(repository.owner, repository.name, params("id").toInt, priority, true) Ok("updated") }) diff --git a/src/main/scala/gitbucket/core/controller/LabelsController.scala b/src/main/scala/gitbucket/core/controller/LabelsController.scala index 4f42475..9ab083e 100644 --- a/src/main/scala/gitbucket/core/controller/LabelsController.scala +++ b/src/main/scala/gitbucket/core/controller/LabelsController.scala @@ -1,7 +1,7 @@ package gitbucket.core.controller import gitbucket.core.issues.labels.html -import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService} +import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService, MilestonesService, PrioritiesService} import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.Implicits._ import gitbucket.core.util.SyntaxSugars._ @@ -10,8 +10,9 @@ import org.scalatra.Ok class LabelsController extends LabelsControllerBase - with LabelsService with IssuesService with RepositoryService with AccountService -with ReferrerAuthenticator with WritableUsersAuthenticator + with IssuesService with RepositoryService with AccountService + with LabelsService with PrioritiesService with MilestonesService + with ReferrerAuthenticator with WritableUsersAuthenticator trait LabelsControllerBase extends ControllerBase { self: LabelsService with IssuesService with RepositoryService diff --git a/src/main/scala/gitbucket/core/controller/PrioritiesController.scala b/src/main/scala/gitbucket/core/controller/PrioritiesController.scala index dee6cbb..2141ffe 100644 --- a/src/main/scala/gitbucket/core/controller/PrioritiesController.scala +++ b/src/main/scala/gitbucket/core/controller/PrioritiesController.scala @@ -1,7 +1,7 @@ package gitbucket.core.controller import gitbucket.core.issues.priorities.html -import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, PrioritiesService} +import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService, MilestonesService, PrioritiesService} import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.Implicits._ import gitbucket.core.util.SyntaxSugars._ @@ -10,8 +10,9 @@ import org.scalatra.Ok class PrioritiesController extends PrioritiesControllerBase - with PrioritiesService with IssuesService with RepositoryService with AccountService -with ReferrerAuthenticator with WritableUsersAuthenticator + with IssuesService with RepositoryService with AccountService + with LabelsService with PrioritiesService with MilestonesService + with ReferrerAuthenticator with WritableUsersAuthenticator trait PrioritiesControllerBase extends ControllerBase { self: PrioritiesService with IssuesService with RepositoryService diff --git a/src/main/scala/gitbucket/core/service/IssuesService.scala b/src/main/scala/gitbucket/core/service/IssuesService.scala index 2283c17..f081d9c 100644 --- a/src/main/scala/gitbucket/core/service/IssuesService.scala +++ b/src/main/scala/gitbucket/core/service/IssuesService.scala @@ -4,6 +4,7 @@ import gitbucket.core.util.StringUtil._ import gitbucket.core.util.Implicits._ import gitbucket.core.util.SyntaxSugars._ +import gitbucket.core.controller.Context import gitbucket.core.model.{Issue, PullRequest, IssueComment, IssueLabel, Label, Account, Repository, CommitState, Role} import gitbucket.core.model.Profile._ import gitbucket.core.model.Profile.profile._ @@ -11,7 +12,7 @@ import gitbucket.core.model.Profile.dateColumnType trait IssuesService { - self: AccountService with RepositoryService => + self: AccountService with RepositoryService with LabelsService with PrioritiesService with MilestonesService => import IssuesService._ def getIssue(owner: String, repository: String, issueId: String)(implicit s: Session) = @@ -321,11 +322,35 @@ } get } - def registerIssueLabel(owner: String, repository: String, issueId: Int, labelId: Int)(implicit s: Session): Int = { + def registerIssueLabel(owner: String, repository: String, issueId: Int, labelId: Int, insertComment: Boolean = false)(implicit context: Context, s: Session): Int = { + if (insertComment) { + IssueComments insert IssueComment( + userName = owner, + repositoryName = repository, + issueId = issueId, + action = "add_label", + commentedUserName = context.loginAccount.map(_.userName).getOrElse("Unknown user"), + content = getLabel(owner, repository, labelId).map(_.labelName).getOrElse("Unknown label"), + registeredDate = currentDate, + updatedDate = currentDate + ) + } IssueLabels insert IssueLabel(owner, repository, issueId, labelId) } - def deleteIssueLabel(owner: String, repository: String, issueId: Int, labelId: Int)(implicit s: Session): Int = { + def deleteIssueLabel(owner: String, repository: String, issueId: Int, labelId: Int, insertComment: Boolean = false)(implicit context: Context, s: Session): Int = { + if (insertComment) { + IssueComments insert IssueComment( + userName = owner, + repositoryName = repository, + issueId = issueId, + action = "delete_label", + commentedUserName = context.loginAccount.map(_.userName).getOrElse("Unknown user"), + content = getLabel(owner, repository, labelId).map(_.labelName).getOrElse("Unknown label"), + registeredDate = currentDate, + updatedDate = currentDate + ) + } IssueLabels filter(_.byPrimaryKey(owner, repository, issueId, labelId)) delete } @@ -350,15 +375,57 @@ .update(title, content, currentDate) } - def updateAssignedUserName(owner: String, repository: String, issueId: Int, assignedUserName: Option[String])(implicit s: Session): Int = { + def updateAssignedUserName(owner: String, repository: String, issueId: Int, assignedUserName: Option[String], insertComment: Boolean = false)(implicit context: Context, s: Session): Int = { + if (insertComment) { + val oldAssigned = getIssue(owner, repository, s"${issueId}").get.assignedUserName.getOrElse("Not assigned") + val assigned = assignedUserName.getOrElse("Not assigned") + IssueComments insert IssueComment( + userName = owner, + repositoryName = repository, + issueId = issueId, + action = "assign", + commentedUserName = context.loginAccount.map(_.userName).getOrElse("Unknown user"), + content = s"${oldAssigned}:${assigned}", + registeredDate = currentDate, + updatedDate = currentDate + ) + } Issues.filter(_.byPrimaryKey(owner, repository, issueId)).map(t => (t.assignedUserName?, t.updatedDate)).update(assignedUserName, currentDate) } - def updateMilestoneId(owner: String, repository: String, issueId: Int, milestoneId: Option[Int])(implicit s: Session): Int = { + def updateMilestoneId(owner: String, repository: String, issueId: Int, milestoneId: Option[Int], insertComment: Boolean = false)(implicit context: Context, s: Session): Int = { + if (insertComment) { + val oldMilestoneName = getIssue(owner, repository, s"${issueId}").get.milestoneId.map(getMilestone(owner, repository, _).map(_.title).getOrElse("Unknown milestone")).getOrElse("No milestone") + val milestoneName = milestoneId.map(getMilestone(owner, repository, _).map(_.title).getOrElse("Unknown milestone")).getOrElse("No milestone") + IssueComments insert IssueComment( + userName = owner, + repositoryName = repository, + issueId = issueId, + action = "change_milestone", + commentedUserName = context.loginAccount.map(_.userName).getOrElse("Unknown user"), + content = s"${oldMilestoneName}:${milestoneName}", + registeredDate = currentDate, + updatedDate = currentDate + ) + } Issues.filter(_.byPrimaryKey(owner, repository, issueId)).map(t => (t.milestoneId?, t.updatedDate)).update(milestoneId, currentDate) } - def updatePriorityId(owner: String, repository: String, issueId: Int, priorityId: Option[Int])(implicit s: Session): Int = { + def updatePriorityId(owner: String, repository: String, issueId: Int, priorityId: Option[Int], insertComment: Boolean = false)(implicit context: Context, s: Session): Int = { + if (insertComment) { + val oldPriorityName = getIssue(owner, repository, s"${issueId}").get.priorityId.map(getPriority(owner, repository, _).map(_.priorityName).getOrElse("Unknown priority")).getOrElse("No priority") + val priorityName = priorityId.map(getPriority(owner, repository, _).map(_.priorityName).getOrElse("Unknown priority")).getOrElse("No priority") + IssueComments insert IssueComment( + userName = owner, + repositoryName = repository, + issueId = issueId, + action = "change_priority", + commentedUserName = context.loginAccount.map(_.userName).getOrElse("Unknown user"), + content = s"${oldPriorityName}:${priorityName}", + registeredDate = currentDate, + updatedDate = currentDate + ) + } Issues.filter(_.byPrimaryKey(owner, repository, issueId)).map(t => (t.priorityId?, t.updatedDate)).update(priorityId, currentDate) } diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index 1583e76..eac61a0 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -185,7 +185,8 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String, sshUrl: Option[String]) extends PostReceiveHook with PreReceiveHook with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService - with WebHookPullRequestService with CommitsService { + with LabelsService with PrioritiesService with MilestonesService + with WebHookPullRequestService with CommitsService { private val logger = LoggerFactory.getLogger(classOf[CommitLogHook]) private var existIds: Seq[String] = Nil diff --git a/src/main/twirl/gitbucket/core/issues/commentlist.scala.html b/src/main/twirl/gitbucket/core/issues/commentlist.scala.html index 6f913c9..fe7d81f 100644 --- a/src/main/twirl/gitbucket/core/issues/commentlist.scala.html +++ b/src/main/twirl/gitbucket/core/issues/commentlist.scala.html @@ -34,32 +34,185 @@ @comments.map { case comment: gitbucket.core.model.IssueComment => { - @if(comment.action != "close" && comment.action != "reopen" && comment.action != "delete_branch" - && comment.action != "commit" && comment.action != "refer"){ -
-
- @helpers.avatar(comment.commentedUserName, 20) - @helpers.user(comment.commentedUserName, styleClass="username strong") - - @if(comment.action == "comment"){ - commented - } else { - referenced the @issueOrPullRequest() - } - + @comment.action match { + case "close" => { + } + case "commit" => { + @defining({ + val (content, id) = " ([a-f0-9]{40})$".r.findFirstMatchIn(comment.content) + .map(m => (m.before.toString -> Some(m.group(1)))) + .getOrElse(comment.content -> None) + val head = content.take(100).takeWhile(_ != '\n') + (id, head, if(head == content){ None }else{ Some(content.drop(head.length).dropWhile(_ == '\n')) }.filter(_.nonEmpty)) + }){ case (commitId, head, rest) => +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + added a commit that referenced this @issueOrPullRequest() @gitbucket.core.helper.html.datetimeago(comment.registeredDate) - - - @if(comment.action != "commit" && comment.action != "merge" && comment.action != "refer" - && (isManageable || context.loginAccount.map(_.userName == comment.commentedUserName).getOrElse(false))){ - -   - - - } +
+
+ @commitId.map{ id => + @id.substring(0, 7) + } + + @helpers.link(head, repository) + @rest.map{ content => + ... + + } +
-
- @helpers.markdown( + } + } + case "refer" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + referenced the @issueOrPullRequest() + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ @defining(comment.content.split(":")){ case Array(issueId, rest @ _*) => + @helpers.issueLink(repository, issueId.toInt): @rest.mkString(":") + } +
+
+ } + case "merge" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + merged commit + @pullreq.map(_.commitIdTo.substring(0, 7)) into + @if(pullreq.get.requestUserName == repository.owner){ + @pullreq.map(_.branch) from @pullreq.map(_.requestBranch) + } else { + @pullreq.map(_.userName):@pullreq.map(_.branch) from @pullreq.map(_.requestUserName):@pullreq.map(_.requestBranch) + } + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "close" | "close_comment" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + closed this @issueOrPullRequest() + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "reopen" | "reopen_comment" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + reopened the @issueOrPullRequest() + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "delete_branch" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + deleted the @pullreq.map(_.requestBranch) branch + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "add_label" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + add the @comment.content label + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "delete_label" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + removed the @comment.content label + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "change_priority" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + change priority from @comment.content.split(":")(0) to @comment.content.split(":")(1) + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "change_milestone" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + change milestone from @comment.content.split(":")(0) to @comment.content.split(":")(1) + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case "assign" => { +
+
+ + @helpers.avatar(comment.commentedUserName, 16) + @helpers.user(comment.commentedUserName, styleClass="username strong") + change assignee from @comment.content.split(":")(0) to @comment.content.split(":")(1) + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) +
+
+ } + case _ => { +
+
+ @helpers.avatar(comment.commentedUserName, 20) + @helpers.user(comment.commentedUserName, styleClass="username strong") + + @if(comment.action == "comment"){ + commented + } else { + referenced the @issueOrPullRequest() + } + + @gitbucket.core.helper.html.datetimeago(comment.registeredDate) + + + @if(comment.action != "commit" && comment.action != "merge" && comment.action != "refer" + && (isManageable || context.loginAccount.map(_.userName == comment.commentedUserName).getOrElse(false))){ + +   + + + } +
+
+ @helpers.markdown( markdown = comment.content, repository = repository, enableWikiLink = false, @@ -67,106 +220,11 @@ enableLineBreaks = true, enableTaskList = true, hasWritePermission = isManageable - ) -
-
- } - @if(comment.action == "commit"){ - @defining({ - val (content, id) = " ([a-f0-9]{40})$".r.findFirstMatchIn(comment.content) - .map(m => (m.before.toString -> Some(m.group(1)))) - .getOrElse(comment.content -> None) - val head = content.take(100).takeWhile(_ != '\n') - (id, head, if(head == content){ None }else{ Some(content.drop(head.length).dropWhile(_ == '\n')) }.filter(_.nonEmpty)) - }){ case (commitId, head, rest) => -
-
- - @helpers.avatar(comment.commentedUserName, 16) - @helpers.user(comment.commentedUserName, styleClass="username strong") - added a commit that referenced this @issueOrPullRequest() - @gitbucket.core.helper.html.datetimeago(comment.registeredDate) -
-
- @commitId.map{ id => - @id.substring(0, 7) - } - - @helpers.link(head, repository) - @rest.map{ content => - ... - - } + )
} } - @if(comment.action == "refer"){ -
-
- - @helpers.avatar(comment.commentedUserName, 16) - @helpers.user(comment.commentedUserName, styleClass="username strong") - referenced the @issueOrPullRequest() - @gitbucket.core.helper.html.datetimeago(comment.registeredDate) -
-
- @defining(comment.content.split(":")){ case Array(issueId, rest @ _*) => - @helpers.issueLink(repository, issueId.toInt): @rest.mkString(":") - } -
-
- } - @if(comment.action == "merge"){ -
-
- - @helpers.avatar(comment.commentedUserName, 16) - @helpers.user(comment.commentedUserName, styleClass="username strong") - merged commit - @pullreq.map(_.commitIdTo.substring(0, 7)) into - @if(pullreq.get.requestUserName == repository.owner){ - @pullreq.map(_.branch) from @pullreq.map(_.requestBranch) - } else { - @pullreq.map(_.userName):@pullreq.map(_.branch) from @pullreq.map(_.requestUserName):@pullreq.map(_.requestBranch) - } - @gitbucket.core.helper.html.datetimeago(comment.registeredDate) -
-
- } - @if(comment.action == "close" || comment.action == "close_comment"){ -
-
- - @helpers.avatar(comment.commentedUserName, 16) - @helpers.user(comment.commentedUserName, styleClass="username strong") - closed this @issueOrPullRequest() - @gitbucket.core.helper.html.datetimeago(comment.registeredDate) -
-
- } - @if(comment.action == "reopen" || comment.action == "reopen_comment"){ -
-
- - @helpers.avatar(comment.commentedUserName, 16) - @helpers.user(comment.commentedUserName, styleClass="username strong") - reopened the @issueOrPullRequest() - @gitbucket.core.helper.html.datetimeago(comment.registeredDate) -
-
- } - @if(comment.action == "delete_branch"){ -
-
- - @helpers.avatar(comment.commentedUserName, 16) - @helpers.user(comment.commentedUserName, styleClass="username strong") - deleted the @pullreq.map(_.requestBranch) branch - @gitbucket.core.helper.html.datetimeago(comment.registeredDate) -
-
- } } case comment: CommitComment => { @gitbucket.core.helper.html.commitcomment(comment, isManageable, repository, pullreq.map(_.commitIdTo))