mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-02 03:26:06 +01:00
Support multiple assignees for Issues and Pull requests (#3055)
This commit is contained in:
@@ -28,4 +28,26 @@
|
||||
<addPrimaryKey constraintName="IDX_ISSUE_CUSTOM_FIELD_PK" tableName="ISSUE_CUSTOM_FIELD" columnNames="USER_NAME, REPOSITORY_NAME, ISSUE_ID, FIELD_ID"/>
|
||||
<addForeignKeyConstraint constraintName="IDX_ISSUE_CUSTOM_FIELD_FK0" baseTableName="ISSUE_CUSTOM_FIELD" baseColumnNames="USER_NAME, REPOSITORY_NAME, ISSUE_ID" referencedTableName="ISSUE" referencedColumnNames="USER_NAME, REPOSITORY_NAME, ISSUE_ID"/>
|
||||
<addForeignKeyConstraint constraintName="IDX_ISSUE_CUSTOM_FIELD_FK1" baseTableName="ISSUE_CUSTOM_FIELD" baseColumnNames="USER_NAME, REPOSITORY_NAME, FIELD_ID" referencedTableName="CUSTOM_FIELD" referencedColumnNames="USER_NAME, REPOSITORY_NAME, FIELD_ID"/>
|
||||
|
||||
<!--================================================================================================-->
|
||||
<!-- ISSUE_ASSIGNEE -->
|
||||
<!--================================================================================================-->
|
||||
<createTable tableName="ISSUE_ASSIGNEE">
|
||||
<column name="USER_NAME" type="varchar(100)" nullable="false"/>
|
||||
<column name="REPOSITORY_NAME" type="varchar(100)" nullable="false"/>
|
||||
<column name="ISSUE_ID" type="int" nullable="false"/>
|
||||
<column name="ASSIGNEE_USER_NAME" type="varchar(100)" nullable="false"/>
|
||||
</createTable>
|
||||
<addPrimaryKey constraintName="IDX_ISSUE_ASSIGNEE_PK" tableName="ISSUE_ASSIGNEE" columnNames="USER_NAME, REPOSITORY_NAME, ISSUE_ID, ASSIGNEE_USER_NAME"/>
|
||||
<addForeignKeyConstraint constraintName="IDX_ISSUE_ASSIGNEE_FK0" baseTableName="ISSUE_ASSIGNEE" baseColumnNames="USER_NAME, REPOSITORY_NAME, ISSUE_ID" referencedTableName="ISSUE" referencedColumnNames="USER_NAME, REPOSITORY_NAME, ISSUE_ID"/>
|
||||
<!--
|
||||
<addForeignKeyConstraint constraintName="IDX_ISSUE_ASSIGNEE_FK1" baseTableName="ISSUE_ASSIGNEE" baseColumnNames="ASSIGNEE_USER_NAME" referencedTableName="ACCOUNT" referencedColumnNames="USER_NAME"/>
|
||||
-->
|
||||
|
||||
<sql>
|
||||
INSERT INTO ISSUE_ASSIGNEE (USER_NAME, REPOSITORY_NAME, ISSUE_ID, ASSIGNEE_USER_NAME)
|
||||
SELECT USER_NAME, REPOSITORY_NAME, ISSUE_ID, ASSIGNED_USER_NAME FROM ISSUE WHERE ASSIGNED_USER_NAME IS NOT NULL
|
||||
</sql>
|
||||
|
||||
<dropColumn tableName="ISSUE" columnName="ASSIGNED_USER_NAME"/>
|
||||
</changeSet>
|
||||
|
||||
@@ -12,7 +12,7 @@ case class ApiIssue(
|
||||
number: Int,
|
||||
title: String,
|
||||
user: ApiUser,
|
||||
assignee: Option[ApiUser],
|
||||
assignees: List[ApiUser],
|
||||
labels: List[ApiLabel],
|
||||
state: String,
|
||||
created_at: Date,
|
||||
@@ -21,7 +21,7 @@ case class ApiIssue(
|
||||
milestone: Option[ApiMilestone]
|
||||
)(repositoryName: RepositoryName, isPullRequest: Boolean) {
|
||||
val id = 0 // dummy id
|
||||
val assignees = List(assignee).flatten
|
||||
val assignee = assignees.headOption
|
||||
val comments_url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/issues/${number}/comments")
|
||||
val html_url = ApiPath(s"/${repositoryName.fullName}/${if (isPullRequest) { "pull" } else { "issues" }}/${number}")
|
||||
val pull_request = if (isPullRequest) {
|
||||
@@ -43,7 +43,7 @@ object ApiIssue {
|
||||
issue: Issue,
|
||||
repositoryName: RepositoryName,
|
||||
user: ApiUser,
|
||||
assignee: Option[ApiUser],
|
||||
assignees: List[ApiUser],
|
||||
labels: List[ApiLabel],
|
||||
milestone: Option[ApiMilestone]
|
||||
): ApiIssue =
|
||||
@@ -51,7 +51,7 @@ object ApiIssue {
|
||||
number = issue.issueId,
|
||||
title = issue.title,
|
||||
user = user,
|
||||
assignee = assignee,
|
||||
assignees = assignees,
|
||||
labels = labels,
|
||||
milestone = milestone,
|
||||
state = if (issue.closed) { "closed" } else { "open" },
|
||||
|
||||
@@ -21,10 +21,11 @@ case class ApiPullRequest(
|
||||
body: String,
|
||||
user: ApiUser,
|
||||
labels: List[ApiLabel],
|
||||
assignee: Option[ApiUser],
|
||||
assignees: List[ApiUser],
|
||||
draft: Option[Boolean]
|
||||
) {
|
||||
val id = 0 // dummy id
|
||||
val assignee = assignees.headOption
|
||||
val html_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}")
|
||||
//val diff_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}.diff")
|
||||
//val patch_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}.patch")
|
||||
@@ -45,7 +46,7 @@ object ApiPullRequest {
|
||||
baseRepo: ApiRepository,
|
||||
user: ApiUser,
|
||||
labels: List[ApiLabel],
|
||||
assignee: Option[ApiUser],
|
||||
assignees: List[ApiUser],
|
||||
mergedComment: Option[(IssueComment, Account)]
|
||||
): ApiPullRequest =
|
||||
ApiPullRequest(
|
||||
@@ -63,7 +64,7 @@ object ApiPullRequest {
|
||||
body = issue.content.getOrElse(""),
|
||||
user = user,
|
||||
labels = labels,
|
||||
assignee = assignee,
|
||||
assignees = assignees,
|
||||
draft = Some(pullRequest.isDraft)
|
||||
)
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
case class IssueCreateForm(
|
||||
title: String,
|
||||
content: Option[String],
|
||||
assignedUserName: Option[String],
|
||||
assigneeUserNames: Option[String],
|
||||
milestoneId: Option[Int],
|
||||
priorityId: Option[Int],
|
||||
labelNames: Option[String]
|
||||
@@ -64,7 +64,7 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
val issueCreateForm = mapping(
|
||||
"title" -> trim(label("Title", text(required))),
|
||||
"content" -> trim(optional(text())),
|
||||
"assignedUserName" -> trim(optional(text())),
|
||||
"assigneeUserNames" -> trim(optional(text())),
|
||||
"milestoneId" -> trim(optional(number())),
|
||||
"priorityId" -> trim(optional(number())),
|
||||
"labelNames" -> trim(optional(text()))
|
||||
@@ -107,6 +107,7 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
issue,
|
||||
getComments(repository.owner, repository.name, issueId.toInt),
|
||||
getIssueLabels(repository.owner, repository.name, issueId.toInt),
|
||||
getIssueAssignees(repository.owner, repository.name, issueId.toInt),
|
||||
getAssignableUserNames(repository.owner, repository.name),
|
||||
getMilestonesWithIssueCount(repository.owner, repository.name),
|
||||
getPriorities(repository.owner, repository.name),
|
||||
@@ -145,7 +146,7 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
repository,
|
||||
form.title,
|
||||
form.content,
|
||||
form.assignedUserName,
|
||||
form.assigneeUserNames.toSeq.flatMap(_.split(",")),
|
||||
form.milestoneId,
|
||||
form.priorityId,
|
||||
form.labelNames.toSeq.flatMap(_.split(",")),
|
||||
@@ -356,15 +357,16 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
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"),
|
||||
true
|
||||
)
|
||||
Ok("updated")
|
||||
ajaxPost("/:owner/:repository/issues/:id/assignee/new")(writableUsersOnly { repository =>
|
||||
val issueId = params("id").toInt
|
||||
registerIssueAssignee(repository.owner, repository.name, issueId, params("assigneeUserName"), true)
|
||||
Ok()
|
||||
})
|
||||
|
||||
ajaxPost("/:owner/:repository/issues/:id/assignee/delete")(writableUsersOnly { repository =>
|
||||
val issueId = params("id").toInt
|
||||
deleteIssueAssignee(repository.owner, repository.name, issueId, params("assigneeUserName"), true)
|
||||
Ok()
|
||||
})
|
||||
|
||||
ajaxPost("/:owner/:repository/issues/:id/milestone")(writableUsersOnly { repository =>
|
||||
@@ -455,7 +457,13 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
post("/:owner/:repository/issues/batchedit/assign")(writableUsersOnly { repository =>
|
||||
val value = assignedUserName("value")
|
||||
executeBatch(repository) {
|
||||
updateAssignedUserName(repository.owner, repository.name, _, value, true)
|
||||
//updateAssignedUserName(repository.owner, repository.name, _, value, true)
|
||||
value match {
|
||||
case Some(assignedUserName) =>
|
||||
registerIssueAssignee(repository.owner, repository.name, _, assignedUserName, true)
|
||||
case None =>
|
||||
deleteAllIssueAssignees(repository.owner, repository.name, _, true)
|
||||
}
|
||||
}
|
||||
if (params("uri").nonEmpty) {
|
||||
redirect(params("uri"))
|
||||
|
||||
@@ -44,7 +44,7 @@ trait LabelsControllerBase extends ControllerBase {
|
||||
get("/:owner/:repository/issues/labels")(referrersOnly { repository =>
|
||||
html.list(
|
||||
getLabels(repository.owner, repository.name),
|
||||
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty),
|
||||
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()),
|
||||
repository,
|
||||
hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
|
||||
)
|
||||
@@ -59,7 +59,7 @@ trait LabelsControllerBase extends ControllerBase {
|
||||
html.label(
|
||||
getLabel(repository.owner, repository.name, labelId).get,
|
||||
// TODO futility
|
||||
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty),
|
||||
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()),
|
||||
repository,
|
||||
hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
|
||||
)
|
||||
@@ -76,7 +76,7 @@ trait LabelsControllerBase extends ControllerBase {
|
||||
html.label(
|
||||
getLabel(repository.owner, repository.name, params("labelId").toInt).get,
|
||||
// TODO futility
|
||||
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty),
|
||||
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()),
|
||||
repository,
|
||||
hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
|
||||
)
|
||||
|
||||
@@ -92,7 +92,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
commitIdFrom: String,
|
||||
commitIdTo: String,
|
||||
isDraft: Boolean,
|
||||
assignedUserName: Option[String],
|
||||
assignedUserNames: Option[String],
|
||||
milestoneId: Option[Int],
|
||||
priorityId: Option[Int],
|
||||
labelNames: Option[String]
|
||||
@@ -131,6 +131,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
getPullRequestComments(repository.owner, repository.name, issue.issueId, commits.flatten),
|
||||
diffs.size,
|
||||
getIssueLabels(repository.owner, repository.name, issueId),
|
||||
getIssueAssignees(repository.owner, repository.name, issueId),
|
||||
getAssignableUserNames(repository.owner, repository.name),
|
||||
getMilestonesWithIssueCount(repository.owner, repository.name),
|
||||
getPriorities(repository.owner, repository.name),
|
||||
@@ -571,7 +572,6 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
loginUser = loginAccount.userName,
|
||||
title = form.title,
|
||||
content = form.content,
|
||||
assignedUserName = if (manageable) form.assignedUserName else None,
|
||||
milestoneId = if (manageable) form.milestoneId else None,
|
||||
priorityId = if (manageable) form.priorityId else None,
|
||||
isPullRequest = true
|
||||
@@ -591,8 +591,14 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
settings = context.settings
|
||||
)
|
||||
|
||||
// insert labels
|
||||
if (manageable) {
|
||||
// insert assignees
|
||||
form.assignedUserNames.foreach { value =>
|
||||
value.split(",").foreach { userName =>
|
||||
registerIssueAssignee(repository.owner, repository.name, issueId, userName)
|
||||
}
|
||||
}
|
||||
// insert labels
|
||||
form.labelNames.foreach { value =>
|
||||
val labels = getLabels(repository.owner, repository.name)
|
||||
value.split(",").foreach { labelName =>
|
||||
|
||||
@@ -679,7 +679,6 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
loginUser = loginAccount.userName,
|
||||
title = requestBranch,
|
||||
content = commitMessage,
|
||||
assignedUserName = None,
|
||||
milestoneId = None,
|
||||
priorityId = None,
|
||||
isPullRequest = true
|
||||
|
||||
@@ -29,9 +29,9 @@ trait ApiIssueControllerBase extends ControllerBase {
|
||||
val page = IssueSearchCondition.page(request)
|
||||
// TODO: more api spec condition
|
||||
val condition = IssueSearchCondition(request)
|
||||
val baseOwner = getAccountByUserName(repository.owner).get
|
||||
//val baseOwner = getAccountByUserName(repository.owner).get
|
||||
|
||||
val issues: List[(Issue, Account, Option[Account])] =
|
||||
val issues: List[(Issue, Account, List[Account])] =
|
||||
searchIssueByApi(
|
||||
condition = condition,
|
||||
offset = (page - 1) * PullRequestLimit,
|
||||
@@ -40,12 +40,12 @@ trait ApiIssueControllerBase extends ControllerBase {
|
||||
)
|
||||
|
||||
JsonFormat(issues.map {
|
||||
case (issue, issueUser, assignedUser) =>
|
||||
case (issue, issueUser, assigneeUsers) =>
|
||||
ApiIssue(
|
||||
issue = issue,
|
||||
repositoryName = RepositoryName(repository),
|
||||
user = ApiUser(issueUser),
|
||||
assignee = assignedUser.map(ApiUser(_)),
|
||||
assignees = assigneeUsers.map(ApiUser(_)),
|
||||
labels = getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(repository))),
|
||||
issue.milestoneId.flatMap { getApiMilestone(repository, _) }
|
||||
@@ -61,7 +61,8 @@ trait ApiIssueControllerBase extends ControllerBase {
|
||||
(for {
|
||||
issueId <- params("id").toIntOpt
|
||||
issue <- getIssue(repository.owner, repository.name, issueId.toString)
|
||||
users = getAccountsByUserNames(Set(issue.openedUserName) ++ issue.assignedUserName, Set())
|
||||
assigneeUsers = getIssueAssignees(repository.owner, repository.name, issueId)
|
||||
users = getAccountsByUserNames(Set(issue.openedUserName) ++ assigneeUsers.map(_.assigneeUserName), Set())
|
||||
openedUser <- users.get(issue.openedUserName)
|
||||
} yield {
|
||||
JsonFormat(
|
||||
@@ -69,7 +70,7 @@ trait ApiIssueControllerBase extends ControllerBase {
|
||||
issue,
|
||||
RepositoryName(repository),
|
||||
ApiUser(openedUser),
|
||||
issue.assignedUserName.flatMap(users.get(_)).map(ApiUser(_)),
|
||||
assigneeUsers.flatMap(x => users.get(x.assigneeUserName)).map(ApiUser(_)),
|
||||
getIssueLabels(repository.owner, repository.name, issue.issueId).map(ApiLabel(_, RepositoryName(repository))),
|
||||
issue.milestoneId.flatMap { getApiMilestone(repository, _) }
|
||||
)
|
||||
@@ -92,7 +93,7 @@ trait ApiIssueControllerBase extends ControllerBase {
|
||||
repository,
|
||||
data.title,
|
||||
data.body,
|
||||
data.assignees.headOption,
|
||||
data.assignees,
|
||||
milestone.map(_.milestoneId),
|
||||
None,
|
||||
data.labels,
|
||||
@@ -103,7 +104,9 @@ trait ApiIssueControllerBase extends ControllerBase {
|
||||
issue,
|
||||
RepositoryName(repository),
|
||||
ApiUser(loginAccount),
|
||||
issue.assignedUserName.flatMap(getAccountByUserName(_)).map(ApiUser(_)),
|
||||
getIssueAssignees(repository.owner, repository.name, issue.issueId)
|
||||
.flatMap(x => getAccountByUserName(x.assigneeUserName, false))
|
||||
.map(ApiUser.apply),
|
||||
getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(repository))),
|
||||
issue.milestoneId.flatMap { getApiMilestone(repository, _) }
|
||||
|
||||
@@ -40,7 +40,7 @@ trait ApiPullRequestControllerBase extends ControllerBase {
|
||||
val condition = IssueSearchCondition(request)
|
||||
val baseOwner = getAccountByUserName(repository.owner).get
|
||||
|
||||
val issues: List[(Issue, Account, Int, PullRequest, Repository, Account, Option[Account])] =
|
||||
val issues: List[(Issue, Account, Int, PullRequest, Repository, Account, List[Account])] =
|
||||
searchPullRequestByApi(
|
||||
condition = condition,
|
||||
offset = (page - 1) * PullRequestLimit,
|
||||
@@ -49,7 +49,7 @@ trait ApiPullRequestControllerBase extends ControllerBase {
|
||||
)
|
||||
|
||||
JsonFormat(issues.map {
|
||||
case (issue, issueUser, commentCount, pullRequest, headRepo, headOwner, assignee) =>
|
||||
case (issue, issueUser, commentCount, pullRequest, headRepo, headOwner, assignees) =>
|
||||
ApiPullRequest(
|
||||
issue = issue,
|
||||
pullRequest = pullRequest,
|
||||
@@ -58,7 +58,7 @@ trait ApiPullRequestControllerBase extends ControllerBase {
|
||||
user = ApiUser(issueUser),
|
||||
labels = getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(repository))),
|
||||
assignee = assignee.map(ApiUser.apply),
|
||||
assignees = assignees.map(ApiUser.apply),
|
||||
mergedComment = getMergedComment(repository.owner, repository.name, issue.issueId)
|
||||
)
|
||||
})
|
||||
@@ -99,7 +99,6 @@ trait ApiPullRequestControllerBase extends ControllerBase {
|
||||
loginUser = context.loginAccount.get.userName,
|
||||
title = createPullReq.title,
|
||||
content = createPullReq.body,
|
||||
assignedUserName = None,
|
||||
milestoneId = None,
|
||||
priorityId = None,
|
||||
isPullRequest = true
|
||||
@@ -319,8 +318,8 @@ trait ApiPullRequestControllerBase extends ControllerBase {
|
||||
baseOwner <- users.get(repository.owner)
|
||||
headOwner <- users.get(pullRequest.requestUserName)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
assignee = issue.assignedUserName.flatMap { userName =>
|
||||
getAccountByUserName(userName, false)
|
||||
assignees = getIssueAssignees(repository.owner, repository.name, issueId).flatMap { assignedUser =>
|
||||
getAccountByUserName(assignedUser.assigneeUserName, false)
|
||||
}
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName)
|
||||
} yield {
|
||||
@@ -332,7 +331,7 @@ trait ApiPullRequestControllerBase extends ControllerBase {
|
||||
user = ApiUser(issueUser),
|
||||
labels = getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(repository))),
|
||||
assignee = assignee.map(ApiUser.apply),
|
||||
assignees = assignees.map(ApiUser.apply),
|
||||
mergedComment = getMergedComment(repository.owner, repository.name, issue.issueId)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ trait IssueComponent extends TemplateComponent { self: Profile =>
|
||||
with MilestoneTemplate
|
||||
with PriorityTemplate {
|
||||
val openedUserName = column[String]("OPENED_USER_NAME")
|
||||
val assignedUserName = column[String]("ASSIGNED_USER_NAME")
|
||||
val title = column[String]("TITLE")
|
||||
val content = column[String]("CONTENT")
|
||||
val closed = column[Boolean]("CLOSED")
|
||||
@@ -42,7 +41,6 @@ trait IssueComponent extends TemplateComponent { self: Profile =>
|
||||
openedUserName,
|
||||
milestoneId.?,
|
||||
priorityId.?,
|
||||
assignedUserName.?,
|
||||
title,
|
||||
content.?,
|
||||
closed,
|
||||
@@ -62,7 +60,6 @@ case class Issue(
|
||||
openedUserName: String,
|
||||
milestoneId: Option[Int],
|
||||
priorityId: Option[Int],
|
||||
assignedUserName: Option[String],
|
||||
title: String,
|
||||
content: Option[String],
|
||||
closed: Boolean,
|
||||
|
||||
26
src/main/scala/gitbucket/core/model/IssueAssignee.scala
Normal file
26
src/main/scala/gitbucket/core/model/IssueAssignee.scala
Normal file
@@ -0,0 +1,26 @@
|
||||
package gitbucket.core.model
|
||||
|
||||
trait IssueAssigneeComponent extends TemplateComponent { self: Profile =>
|
||||
import profile.api._
|
||||
import self._
|
||||
|
||||
lazy val IssueAssignees = TableQuery[IssueAssignees]
|
||||
|
||||
class IssueAssignees(tag: Tag) extends Table[IssueAssignee](tag, "ISSUE_ASSIGNEE") with IssueTemplate {
|
||||
val assigneeUserName = column[String]("ASSIGNEE_USER_NAME")
|
||||
def * =
|
||||
(userName, repositoryName, issueId, assigneeUserName)
|
||||
.<>(IssueAssignee.tupled, IssueAssignee.unapply)
|
||||
|
||||
def byPrimaryKey(owner: String, repository: String, issueId: Int, assigneeUserName: String) = {
|
||||
byIssue(owner, repository, issueId) && this.assigneeUserName === assigneeUserName.bind
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case class IssueAssignee(
|
||||
userName: String,
|
||||
repositoryName: String,
|
||||
issueId: Int,
|
||||
assigneeUserName: String
|
||||
)
|
||||
@@ -74,5 +74,6 @@ trait CoreProfile
|
||||
with AccountPreferenceComponent
|
||||
with CustomFieldComponent
|
||||
with IssueCustomFieldComponent
|
||||
with IssueAssigneeComponent
|
||||
|
||||
object Profile extends CoreProfile
|
||||
|
||||
@@ -16,7 +16,7 @@ trait IssueCreationService {
|
||||
repository: RepositoryInfo,
|
||||
title: String,
|
||||
body: Option[String],
|
||||
assignee: Option[String],
|
||||
assignees: Seq[String],
|
||||
milestoneId: Option[Int],
|
||||
priorityId: Option[Int],
|
||||
labelNames: Seq[String],
|
||||
@@ -35,16 +35,19 @@ trait IssueCreationService {
|
||||
userName,
|
||||
title,
|
||||
body,
|
||||
if (manageable) assignee else None,
|
||||
if (manageable) milestoneId else None,
|
||||
if (manageable) priorityId else None
|
||||
)
|
||||
val issue: Issue = getIssue(owner, name, issueId.toString).get
|
||||
|
||||
// insert labels
|
||||
if (manageable) {
|
||||
// insert assignees
|
||||
assignees.foreach { assignee =>
|
||||
registerIssueAssignee(owner, name, issueId, assignee)
|
||||
}
|
||||
// insert labels
|
||||
val labels = getLabels(owner, name)
|
||||
labelNames.map { labelName =>
|
||||
labelNames.foreach { labelName =>
|
||||
labels.find(_.labelName == labelName).map { label =>
|
||||
registerIssueLabel(owner, name, issueId, label.labelId)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,17 @@ import gitbucket.core.util.StringUtil._
|
||||
import gitbucket.core.util.Implicits._
|
||||
import gitbucket.core.util.SyntaxSugars._
|
||||
import gitbucket.core.controller.Context
|
||||
import gitbucket.core.model.{Account, Issue, IssueComment, IssueLabel, Label, PullRequest, Repository, Role}
|
||||
import gitbucket.core.model.{
|
||||
Account,
|
||||
Issue,
|
||||
IssueAssignee,
|
||||
IssueComment,
|
||||
IssueLabel,
|
||||
Label,
|
||||
PullRequest,
|
||||
Repository,
|
||||
Role
|
||||
}
|
||||
import gitbucket.core.model.Profile._
|
||||
import gitbucket.core.model.Profile.profile._
|
||||
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||
@@ -118,8 +128,7 @@ trait IssuesService {
|
||||
def countIssueGroupByLabels(
|
||||
owner: String,
|
||||
repository: String,
|
||||
condition: IssueSearchCondition,
|
||||
filterUser: Map[String, String]
|
||||
condition: IssueSearchCondition
|
||||
)(implicit s: Session): Map[String, Int] = {
|
||||
|
||||
searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), IssueSearchOption.Issues)
|
||||
@@ -244,20 +253,31 @@ trait IssuesService {
|
||||
}
|
||||
|
||||
/** for api
|
||||
* @return (issue, issueUser, assignedUser)
|
||||
* @return (issue, issueUser, Seq(assigneeUsers))
|
||||
*/
|
||||
def searchIssueByApi(condition: IssueSearchCondition, offset: Int, limit: Int, repos: (String, String)*)(
|
||||
implicit s: Session
|
||||
): List[(Issue, Account, Option[Account])] = {
|
||||
): List[(Issue, Account, List[Account])] = {
|
||||
// get issues and comment count and labels
|
||||
searchIssueQueryBase(condition, IssueSearchOption.Issues, offset, limit, repos)
|
||||
.join(Accounts)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 => t3.userName === t1.openedUserName }
|
||||
.joinLeft(IssueAssignees)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 => t4.byIssue(t1.userName, t1.repositoryName, t1.issueId) }
|
||||
.joinLeft(Accounts)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 => t4.userName === t1.assignedUserName }
|
||||
.sortBy { case t1 ~ t2 ~ i ~ t3 ~ t4 => i asc }
|
||||
.map { case t1 ~ t2 ~ i ~ t3 ~ t4 => (t1, t3, t4) }
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 => t5.userName === t4.map(_.assigneeUserName) }
|
||||
.sortBy { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 => i asc }
|
||||
.map { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 => (t1, t3, t5) }
|
||||
.list
|
||||
.groupBy {
|
||||
case (issue, account, assignedUsers) =>
|
||||
(issue, account)
|
||||
}
|
||||
.map {
|
||||
case (_, values) =>
|
||||
(values.head._1, values.head._2, values.flatMap(_._3))
|
||||
}
|
||||
.toList
|
||||
}
|
||||
|
||||
/** for api
|
||||
@@ -265,7 +285,7 @@ trait IssuesService {
|
||||
*/
|
||||
def searchPullRequestByApi(condition: IssueSearchCondition, offset: Int, limit: Int, repos: (String, String)*)(
|
||||
implicit s: Session
|
||||
): List[(Issue, Account, Int, PullRequest, Repository, Account, Option[Account])] = {
|
||||
): List[(Issue, Account, Int, PullRequest, Repository, Account, List[Account])] = {
|
||||
// get issues and comment count and labels
|
||||
searchIssueQueryBase(condition, IssueSearchOption.PullRequests, offset, limit, repos)
|
||||
.join(PullRequests)
|
||||
@@ -276,11 +296,30 @@ trait IssuesService {
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 => t5.userName === t1.openedUserName }
|
||||
.join(Accounts)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 => t6.userName === t4.userName }
|
||||
.joinLeft(IssueAssignees)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 => t7.byIssue(t1.userName, t1.repositoryName, t1.issueId) }
|
||||
.joinLeft(Accounts)
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 => t7.userName === t1.assignedUserName }
|
||||
.sortBy { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 => i asc }
|
||||
.map { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 => (t1, t5, t2.commentCount, t3, t4, t6, t7) }
|
||||
.on { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 ~ t8 => t8.userName === t7.map(_.assigneeUserName) }
|
||||
.sortBy { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 ~ t8 => i asc }
|
||||
.map { case t1 ~ t2 ~ i ~ t3 ~ t4 ~ t5 ~ t6 ~ t7 ~ t8 => (t1, t5, t2.commentCount, t3, t4, t6, t8) }
|
||||
.list
|
||||
.groupBy {
|
||||
case (issue, openedUser, commentCount, pullRequest, repository, account, assignedUser) =>
|
||||
(issue, openedUser, commentCount, pullRequest, repository, account)
|
||||
}
|
||||
.map {
|
||||
case (_, values) =>
|
||||
(
|
||||
values.head._1,
|
||||
values.head._2,
|
||||
values.head._3,
|
||||
values.head._4,
|
||||
values.head._5,
|
||||
values.head._6,
|
||||
values.flatMap(_._7)
|
||||
)
|
||||
}
|
||||
.toList
|
||||
}
|
||||
|
||||
private def searchIssueQueryBase(
|
||||
@@ -347,7 +386,7 @@ trait IssuesService {
|
||||
case _ => t1.closed === true || t1.closed === false
|
||||
}).&&(t1.milestoneId.? isEmpty, condition.milestone == Some(None))
|
||||
.&&(t1.priorityId.? isEmpty, condition.priority == Some(None))
|
||||
.&&(t1.assignedUserName.? isEmpty, condition.assigned == Some(None))
|
||||
//.&&(t1.assignedUserName.? isEmpty, condition.assigned == Some(None))
|
||||
.&&(t1.openedUserName === condition.author.get.bind, condition.author.isDefined) &&
|
||||
(searchOption match {
|
||||
case IssueSearchOption.Issues => t1.pullRequest === false
|
||||
@@ -371,7 +410,13 @@ trait IssuesService {
|
||||
condition.priority.flatten.isDefined
|
||||
)
|
||||
// Assignee filter
|
||||
.&&(t1.assignedUserName === condition.assigned.get.get.bind, condition.assigned.flatten.isDefined)
|
||||
.&&(
|
||||
IssueAssignees filter { a =>
|
||||
a.byIssue(t1.userName, t1.repositoryName, t1.issueId) &&
|
||||
a.assigneeUserName === condition.assigned.get.get.bind
|
||||
} exists,
|
||||
condition.assigned.flatten.isDefined
|
||||
)
|
||||
// Label filter
|
||||
.&&(
|
||||
IssueLabels filter { t2 =>
|
||||
@@ -396,7 +441,9 @@ trait IssuesService {
|
||||
.&&(t1.userName inSetBind condition.groups, condition.groups.nonEmpty)
|
||||
// Mentioned filter
|
||||
.&&(
|
||||
(t1.openedUserName === condition.mentioned.get.bind) || t1.assignedUserName === condition.mentioned.get.bind ||
|
||||
(t1.openedUserName === condition.mentioned.get.bind) || (IssueAssignees filter { t1 =>
|
||||
t1.byIssue(t1.userName, t1.repositoryName, t1.issueId) && t1.assigneeUserName === condition.mentioned.get.bind
|
||||
} exists) ||
|
||||
(IssueComments filter { t2 =>
|
||||
(t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) && (t2.commentedUserName === condition.mentioned.get.bind)
|
||||
} exists),
|
||||
@@ -410,7 +457,6 @@ trait IssuesService {
|
||||
loginUser: String,
|
||||
title: String,
|
||||
content: Option[String],
|
||||
assignedUserName: Option[String],
|
||||
milestoneId: Option[Int],
|
||||
priorityId: Option[Int],
|
||||
isPullRequest: Boolean = false
|
||||
@@ -427,7 +473,6 @@ trait IssuesService {
|
||||
loginUser,
|
||||
milestoneId,
|
||||
priorityId,
|
||||
assignedUserName,
|
||||
title,
|
||||
content,
|
||||
false,
|
||||
@@ -542,35 +587,91 @@ trait IssuesService {
|
||||
.update(true)
|
||||
}
|
||||
|
||||
def updateAssignedUserName(
|
||||
def getIssueAssignees(owner: String, repository: String, issueId: Int)(
|
||||
implicit s: Session
|
||||
): List[IssueAssignee] = {
|
||||
IssueAssignees.filter(_.byIssue(owner, repository, issueId)).sortBy(_.assigneeUserName).list
|
||||
}
|
||||
|
||||
def registerIssueAssignee(
|
||||
owner: String,
|
||||
repository: String,
|
||||
issueId: Int,
|
||||
assignedUserName: Option[String],
|
||||
assigneeUserName: String,
|
||||
insertComment: Boolean = false
|
||||
)(implicit context: Context, s: Session): Int = {
|
||||
val oldAssigned = getIssue(owner, repository, s"${issueId}").get.assignedUserName
|
||||
val assigned = assignedUserName
|
||||
)(
|
||||
implicit context: Context,
|
||||
s: Session
|
||||
): Int = {
|
||||
val assigner = context.loginAccount.map(_.userName)
|
||||
if (insertComment) {
|
||||
IssueComments insert IssueComment(
|
||||
userName = owner,
|
||||
repositoryName = repository,
|
||||
issueId = issueId,
|
||||
action = "assign",
|
||||
action = "add_assignee",
|
||||
commentedUserName = assigner.getOrElse("Unknown user"),
|
||||
content = s"""${oldAssigned.getOrElse("Not assigned")}:${assigned.getOrElse("Not assigned")}""",
|
||||
content = assigneeUserName,
|
||||
registeredDate = currentDate,
|
||||
updatedDate = currentDate
|
||||
)
|
||||
}
|
||||
for (issue <- getIssue(owner, repository, issueId.toString); repo <- getRepository(owner, repository)) {
|
||||
PluginRegistry().getIssueHooks.foreach(_.assigned(issue, repo, assigner, assigned, oldAssigned))
|
||||
PluginRegistry().getIssueHooks.foreach(_.assigned(issue, repo, assigner, Some(assigneeUserName), None))
|
||||
}
|
||||
Issues
|
||||
.filter(_.byPrimaryKey(owner, repository, issueId))
|
||||
.map(t => (t.assignedUserName ?, t.updatedDate))
|
||||
.update(assignedUserName, currentDate)
|
||||
IssueAssignees insert IssueAssignee(owner, repository, issueId, assigneeUserName)
|
||||
}
|
||||
|
||||
def deleteIssueAssignee(
|
||||
owner: String,
|
||||
repository: String,
|
||||
issueId: Int,
|
||||
assigneeUserName: String,
|
||||
insertComment: Boolean = false
|
||||
)(
|
||||
implicit context: Context,
|
||||
s: Session
|
||||
): Int = {
|
||||
val assigner = context.loginAccount.map(_.userName)
|
||||
if (insertComment) {
|
||||
IssueComments insert IssueComment(
|
||||
userName = owner,
|
||||
repositoryName = repository,
|
||||
issueId = issueId,
|
||||
action = "delete_assignee",
|
||||
commentedUserName = assigner.getOrElse("Unknown user"),
|
||||
content = assigneeUserName,
|
||||
registeredDate = currentDate,
|
||||
updatedDate = currentDate
|
||||
)
|
||||
}
|
||||
|
||||
// TODO Notify plugins of unassignment as doing in registerIssueAssignee()?
|
||||
|
||||
IssueAssignees filter (_.byPrimaryKey(owner, repository, issueId, assigneeUserName)) delete
|
||||
}
|
||||
|
||||
def deleteAllIssueAssignees(owner: String, repository: String, issueId: Int, insertComment: Boolean = false)(
|
||||
implicit context: Context,
|
||||
s: Session
|
||||
): Int = {
|
||||
val assigner = context.loginAccount.map(_.userName)
|
||||
if (insertComment) {
|
||||
IssueComments insert IssueComment(
|
||||
userName = owner,
|
||||
repositoryName = repository,
|
||||
issueId = issueId,
|
||||
action = "delete_assign",
|
||||
commentedUserName = assigner.getOrElse("Unknown user"),
|
||||
content = "All assignees",
|
||||
registeredDate = currentDate,
|
||||
updatedDate = currentDate
|
||||
)
|
||||
}
|
||||
|
||||
// TODO Notify plugins of unassignment as doing in registerIssueAssignee()?
|
||||
|
||||
IssueAssignees filter (_.byIssue(owner, repository, issueId)) delete
|
||||
}
|
||||
|
||||
def updateMilestoneId(
|
||||
|
||||
@@ -379,8 +379,12 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
settings: SystemSettings
|
||||
)(implicit s: Session, context: JsonFormat.Context): Unit = {
|
||||
callWebHookOf(repository.owner, repository.name, WebHook.Issues, settings) {
|
||||
val assigneeUsers = getIssueAssignees(repository.owner, repository.name, issue.issueId)
|
||||
val users =
|
||||
getAccountsByUserNames(Set(repository.owner, issue.openedUserName) ++ issue.assignedUserName, Set(sender))
|
||||
getAccountsByUserNames(
|
||||
Set(repository.owner, issue.openedUserName) ++ assigneeUsers.map(_.assigneeUserName),
|
||||
Set(sender)
|
||||
)
|
||||
for {
|
||||
repoOwner <- users.get(repository.owner)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
@@ -393,7 +397,7 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
issue,
|
||||
RepositoryName(repository),
|
||||
ApiUser(issueUser),
|
||||
issue.assignedUserName.flatMap(users.get(_)).map(ApiUser(_)),
|
||||
assigneeUsers.flatMap(x => users.get(x.assigneeUserName)).map(ApiUser(_)),
|
||||
getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(repository))),
|
||||
getApiMilestone(repository, issue.milestoneId getOrElse (0))
|
||||
@@ -415,16 +419,15 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
callWebHookOf(repository.owner, repository.name, WebHook.PullRequest, settings) {
|
||||
for {
|
||||
(issue, pullRequest) <- getPullRequest(repository.owner, repository.name, issueId)
|
||||
assignees = getIssueAssignees(repository.owner, repository.name, issueId)
|
||||
users = getAccountsByUserNames(
|
||||
Set(repository.owner, pullRequest.requestUserName, issue.openedUserName),
|
||||
Set(repository.owner, pullRequest.requestUserName, issue.openedUserName) ++ assignees.map(_.assigneeUserName),
|
||||
Set(sender)
|
||||
)
|
||||
baseOwner <- users.get(repository.owner)
|
||||
headOwner <- users.get(pullRequest.requestUserName)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
assignee = issue.assignedUserName.flatMap { userName =>
|
||||
getAccountByUserName(userName, false)
|
||||
}
|
||||
assigneeUsers = assignees.flatMap(x => users.get(x.assigneeUserName))
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName)
|
||||
labels = getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(repository)))
|
||||
@@ -433,7 +436,7 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
action = action,
|
||||
issue = issue,
|
||||
issueUser = issueUser,
|
||||
assignee = assignee,
|
||||
assignees = assigneeUsers,
|
||||
pullRequest = pullRequest,
|
||||
headRepository = headRepo,
|
||||
headOwner = headOwner,
|
||||
@@ -481,8 +484,8 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
requestRepository.name,
|
||||
requestBranch
|
||||
)
|
||||
assignee = issue.assignedUserName.flatMap { userName =>
|
||||
getAccountByUserName(userName, false)
|
||||
assignees = getIssueAssignees(requestRepository.owner, requestRepository.name, issue.issueId).flatMap { x =>
|
||||
getAccountByUserName(x.assigneeUserName, false)
|
||||
}
|
||||
baseRepo <- getRepository(pullRequest.userName, pullRequest.repositoryName)
|
||||
labels = getIssueLabels(pullRequest.userName, pullRequest.repositoryName, issue.issueId)
|
||||
@@ -492,7 +495,7 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
action = action,
|
||||
issue = issue,
|
||||
issueUser = issueUser,
|
||||
assignee = assignee,
|
||||
assignees = assignees,
|
||||
pullRequest = pullRequest,
|
||||
headRepository = requestRepository,
|
||||
headOwner = headOwner,
|
||||
@@ -522,15 +525,17 @@ trait WebHookPullRequestReviewCommentService extends WebHookService {
|
||||
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
||||
import WebHookService._
|
||||
callWebHookOf(repository.owner, repository.name, WebHook.PullRequestReviewComment, settings) {
|
||||
val assignees = getIssueAssignees(repository.owner, pullRequest.requestUserName, issue.issueId)
|
||||
val users =
|
||||
getAccountsByUserNames(Set(repository.owner, pullRequest.requestUserName, issue.openedUserName), Set(sender))
|
||||
getAccountsByUserNames(
|
||||
Set(repository.owner, pullRequest.requestUserName, issue.openedUserName) ++ assignees.map(_.assigneeUserName),
|
||||
Set(sender)
|
||||
)
|
||||
for {
|
||||
baseOwner <- users.get(repository.owner)
|
||||
headOwner <- users.get(pullRequest.requestUserName)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
assignee = issue.assignedUserName.flatMap { userName =>
|
||||
getAccountByUserName(userName, false)
|
||||
}
|
||||
assigneeUsers = assignees.flatMap(x => users.get(x.assigneeUserName))
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName)
|
||||
labels = getIssueLabels(pullRequest.userName, pullRequest.repositoryName, issue.issueId)
|
||||
.map(ApiLabel(_, RepositoryName(pullRequest.userName, pullRequest.repositoryName)))
|
||||
@@ -540,7 +545,7 @@ trait WebHookPullRequestReviewCommentService extends WebHookService {
|
||||
comment = comment,
|
||||
issue = issue,
|
||||
issueUser = issueUser,
|
||||
assignee = assignee,
|
||||
assignees = assigneeUsers,
|
||||
pullRequest = pullRequest,
|
||||
headRepository = headRepo,
|
||||
headOwner = headOwner,
|
||||
@@ -569,14 +574,17 @@ trait WebHookIssueCommentService extends WebHookPullRequestService {
|
||||
callWebHookOf(repository.owner, repository.name, WebHook.IssueComment, settings) {
|
||||
for {
|
||||
issueComment <- getComment(repository.owner, repository.name, issueCommentId.toString())
|
||||
assignees = getIssueAssignees(repository.owner, repository.name, issue.issueId)
|
||||
users = getAccountsByUserNames(
|
||||
Set(issue.openedUserName, repository.owner, issueComment.commentedUserName) ++ issue.assignedUserName,
|
||||
Set(issue.openedUserName, repository.owner, issueComment.commentedUserName) ++ assignees.map(
|
||||
_.assigneeUserName
|
||||
),
|
||||
Set(sender)
|
||||
)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
repoOwner <- users.get(repository.owner)
|
||||
commenter <- users.get(issueComment.commentedUserName)
|
||||
assignedUser = issue.assignedUserName.flatMap(users.get(_))
|
||||
assigneeUsers = assignees.flatMap(x => users.get(x.assigneeUserName))
|
||||
labels = getIssueLabels(repository.owner, repository.name, issue.issueId)
|
||||
milestone = getApiMilestone(repository, issue.milestoneId getOrElse (0))
|
||||
} yield {
|
||||
@@ -587,7 +595,7 @@ trait WebHookIssueCommentService extends WebHookPullRequestService {
|
||||
commentUser = commenter,
|
||||
repository = repository,
|
||||
repositoryUser = repoOwner,
|
||||
assignedUser = assignedUser,
|
||||
assignees = assigneeUsers,
|
||||
sender = sender,
|
||||
labels = labels,
|
||||
milestone = milestone
|
||||
@@ -710,7 +718,7 @@ object WebHookService {
|
||||
action: String,
|
||||
issue: Issue,
|
||||
issueUser: Account,
|
||||
assignee: Option[Account],
|
||||
assignees: List[Account],
|
||||
pullRequest: PullRequest,
|
||||
headRepository: RepositoryInfo,
|
||||
headOwner: Account,
|
||||
@@ -731,7 +739,7 @@ object WebHookService {
|
||||
baseRepo = baseRepoPayload,
|
||||
user = ApiUser(issueUser),
|
||||
labels = labels,
|
||||
assignee = assignee.map(ApiUser.apply),
|
||||
assignees = assignees.map(ApiUser.apply),
|
||||
mergedComment = mergedComment
|
||||
)
|
||||
|
||||
@@ -762,7 +770,7 @@ object WebHookService {
|
||||
commentUser: Account,
|
||||
repository: RepositoryInfo,
|
||||
repositoryUser: Account,
|
||||
assignedUser: Option[Account],
|
||||
assignees: List[Account],
|
||||
sender: Account,
|
||||
labels: List[Label],
|
||||
milestone: Option[ApiMilestone]
|
||||
@@ -774,7 +782,7 @@ object WebHookService {
|
||||
issue,
|
||||
RepositoryName(repository),
|
||||
ApiUser(issueUser),
|
||||
assignedUser.map(ApiUser(_)),
|
||||
assignees.map(ApiUser(_)),
|
||||
labels.map(ApiLabel(_, RepositoryName(repository))),
|
||||
milestone
|
||||
),
|
||||
@@ -799,7 +807,7 @@ object WebHookService {
|
||||
comment: CommitComment,
|
||||
issue: Issue,
|
||||
issueUser: Account,
|
||||
assignee: Option[Account],
|
||||
assignees: List[Account],
|
||||
pullRequest: PullRequest,
|
||||
headRepository: RepositoryInfo,
|
||||
headOwner: Account,
|
||||
@@ -828,7 +836,7 @@ object WebHookService {
|
||||
baseRepo = baseRepoPayload,
|
||||
user = ApiUser(issueUser),
|
||||
labels = labels,
|
||||
assignee = assignee.map(ApiUser.apply),
|
||||
assignees = assignees.map(ApiUser.apply),
|
||||
mergedComment = mergedComment
|
||||
),
|
||||
repository = baseRepoPayload,
|
||||
|
||||
@@ -33,9 +33,11 @@
|
||||
<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 =>
|
||||
@helpers.avatar(userName, 20, tooltip = true)
|
||||
}
|
||||
*@
|
||||
@if(commentCount > 0){
|
||||
<a href="@context.path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-comment-count">
|
||||
<i class="octicon octicon-comment active"></i> @commentCount
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-tag"></i></span>
|
||||
@helpers.avatarLink(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
add the <code>@comment.content</code> label
|
||||
added the <code>@comment.content</code> label
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
@@ -222,7 +222,7 @@
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-flame"></i></span>
|
||||
@helpers.avatarLink(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
change priority from <code>@comment.content.split(":")(0)</code> to <code>@comment.content.split(":")(1)</code>
|
||||
changed priority from <code>@comment.content.split(":")(0)</code> to <code>@comment.content.split(":")(1)</code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
@@ -233,18 +233,40 @@
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-milestone"></i></span>
|
||||
@helpers.avatarLink(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
change milestone from <code>@comment.content.split(":")(0)</code> to <code>@comment.content.split(":")(1)</code>
|
||||
changed milestone from <code>@comment.content.split(":")(0)</code> to <code>@comment.content.split(":")(1)</code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
case "assign" => {
|
||||
case "assign" => { @* for backward compatibility *@
|
||||
<div class="discussion-item discussion-item-assign">
|
||||
<div class="discussion-item-header">
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-person"></i></span>
|
||||
@helpers.avatarLink(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
change assignee from <code>@comment.content.split(":")(0)</code> to <code>@comment.content.split(":")(1)</code>
|
||||
changed assignee from <code>@comment.content.split(":")(0)</code> to <code>@comment.content.split(":")(1)</code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
case "add_assignee" => {
|
||||
<div class="discussion-item discussion-item-assign">
|
||||
<div class="discussion-item-header">
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-person"></i></span>
|
||||
@helpers.avatarLink(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
assigned <code>@comment.content</code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
case "delete_assignee" => {
|
||||
<div class="discussion-item discussion-item-assign">
|
||||
<div class="discussion-item-header">
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-person"></i></span>
|
||||
@helpers.avatarLink(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
unassigned <code>@comment.content</code></code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
@@ -255,7 +277,7 @@
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-pencil"></i></span>
|
||||
@helpers.avatar(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
change title from <code>@convertLineSeparator(comment.content, "LF").split("\n")(0)</code> to <code>@convertLineSeparator(comment.content, "LF").split("\n")(1)</code>
|
||||
changed title from <code>@convertLineSeparator(comment.content, "LF").split("\n")(0)</code> to <code>@convertLineSeparator(comment.content, "LF").split("\n")(1)</code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,7 +288,7 @@
|
||||
<span class="discussion-item-icon"><i class="octicon octicon-pencil"></i></span>
|
||||
@helpers.avatar(comment.commentedUserName, 16)
|
||||
@helpers.user(comment.commentedUserName, styleClass="username strong")
|
||||
change base branch from <code>@convertLineSeparator(comment.content, "LF").split("\n")(0)</code> to <code>@convertLineSeparator(comment.content, "LF").split("\n")(1)</code>
|
||||
changed base branch from <code>@convertLineSeparator(comment.content, "LF").split("\n")(0)</code> to <code>@convertLineSeparator(comment.content, "LF").split("\n")(1)</code>
|
||||
@gitbucket.core.helper.html.datetimeago(comment.registeredDate)
|
||||
</div>
|
||||
</div>
|
||||
@@ -328,9 +350,9 @@
|
||||
$(function(){
|
||||
@if(issue.isDefined){
|
||||
$('.issue-comment-box i.octicon-pencil').click(function(){
|
||||
var id = $(this).closest('a').data('comment-id');
|
||||
var url = '@helpers.url(repository)/issue_comments/_data/' + id;
|
||||
var $content = $('#commentContent-' + id);
|
||||
let id = $(this).closest('a').data('comment-id');
|
||||
let url = '@helpers.url(repository)/issue_comments/_data/' + id;
|
||||
let $content = $('#commentContent-' + id);
|
||||
|
||||
if(!id){
|
||||
id = $(this).closest('a').data('issue-id');
|
||||
@@ -345,7 +367,7 @@ $(function(){
|
||||
});
|
||||
$('.issue-comment-box i.octicon-x').click(function(){
|
||||
if(confirm('Are you sure you want to delete this?')) {
|
||||
var id = $(this).closest('a').data('comment-id');
|
||||
const id = $(this).closest('a').data('comment-id');
|
||||
$.post('@helpers.url(repository)/issue_comments/delete/' + id, function(data){
|
||||
if(data > 0) {
|
||||
$('#comment-' + id).remove();
|
||||
@@ -356,9 +378,9 @@ $(function(){
|
||||
});
|
||||
}
|
||||
$(document).on('click', '.commit-comment-box i.octicon-pencil', function(){
|
||||
var id = $(this).closest('a').data('comment-id');
|
||||
var url = '@helpers.url(repository)/commit_comments/_data/' + id;
|
||||
var $content = $('.commit-commentContent-' + id, $(this).closest('.commit-comment-box'));
|
||||
const id = $(this).closest('a').data('comment-id');
|
||||
const url = '@helpers.url(repository)/commit_comments/_data/' + id;
|
||||
const $content = $('.commit-commentContent-' + id, $(this).closest('.commit-comment-box'));
|
||||
|
||||
$.get(url, { dataType : 'html' }, function(data){
|
||||
$content.empty().html(data);
|
||||
@@ -369,14 +391,14 @@ $(function(){
|
||||
|
||||
$(document).on('click', '.commit-comment-box i.octicon-x', function(){
|
||||
if(confirm('Are you sure you want to delete this?')) {
|
||||
var id = $(this).closest('a').data('comment-id');
|
||||
const id = $(this).closest('a').data('comment-id');
|
||||
$.post('@helpers.url(repository)/commit_comments/delete/' + id,
|
||||
function(data){
|
||||
if(data > 0) {
|
||||
var comment = $('.commit-comment-' + id);
|
||||
const comment = $('.commit-comment-' + id);
|
||||
|
||||
// diff view
|
||||
var tr = comment.closest('.not-diff');
|
||||
const tr = comment.closest('.not-diff');
|
||||
if(tr.length > 0){
|
||||
if(tr.prev('.not-diff').length == 0){
|
||||
tr.next('.not-diff:has(.reply-comment)').remove();
|
||||
@@ -385,7 +407,7 @@ $(function(){
|
||||
}
|
||||
|
||||
// comment list view
|
||||
var panel = comment.closest('div.panel:has(.commit-comment-box)');
|
||||
const panel = comment.closest('div.panel:has(.commit-comment-box)');
|
||||
if(panel.length > 0){
|
||||
comment.parent('.commit-comment-box').remove();
|
||||
if(panel.has('.commit-comment-box').length == 0){
|
||||
@@ -401,7 +423,7 @@ $(function(){
|
||||
});
|
||||
|
||||
$('div[class*=commit-commentContent-]').on('click', ':checkbox', function(ev){
|
||||
var $commentContent = $(ev.target).parents('div[class*=commit-commentContent-]'),
|
||||
const $commentContent = $(ev.target).parents('div[class*=commit-commentContent-]'),
|
||||
commentId = $commentContent.attr('class').match(/commit-commentContent-.+/)[0].replace(/commit-commentContent-/, ''),
|
||||
checkboxes = $commentContent.find(':checkbox');
|
||||
$.get('@helpers.url(repository)/commit_comments/_data/' + commentId, { dataType : 'html' },
|
||||
@@ -421,9 +443,9 @@ $(function(){
|
||||
);
|
||||
});
|
||||
|
||||
@if(issue.isDefined){
|
||||
@if(issue.isDefined){
|
||||
$('#issueContent').on('click', ':checkbox', function(ev){
|
||||
var checkboxes = $('#issueContent :checkbox');
|
||||
const checkboxes = $('#issueContent :checkbox');
|
||||
$.get('@helpers.url(repository)/issues/_data/@issue.get.issueId', { dataType : 'html' },
|
||||
function(responseContent){
|
||||
$.ajax({
|
||||
@@ -439,7 +461,7 @@ $(function(){
|
||||
});
|
||||
|
||||
$('div[id^=commentContent-]').on('click', ':checkbox', function(ev){
|
||||
var $commentContent = $(ev.target).parents('div[id^=commentContent-]'),
|
||||
const $commentContent = $(ev.target).parents('div[id^=commentContent-]'),
|
||||
commentId = $commentContent.attr('id').replace(/commentContent-/, ''),
|
||||
checkboxes = $commentContent.find(':checkbox');
|
||||
$.get('@helpers.url(repository)/issue_comments/_data/' + commentId, { dataType : 'html' },
|
||||
@@ -455,9 +477,7 @@ $(function(){
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
issue = None,
|
||||
comments = Nil,
|
||||
issueLabels = Nil,
|
||||
issueAssignees = Nil,
|
||||
collaborators = collaborators,
|
||||
milestones = milestones.map(x => (x, 0, 0)),
|
||||
priorities= priorities,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@(issue: gitbucket.core.model.Issue,
|
||||
comments: List[gitbucket.core.model.IssueComment],
|
||||
issueLabels: List[gitbucket.core.model.Label],
|
||||
issueAssignees: List[gitbucket.core.model.IssueAssignee],
|
||||
collaborators: List[String],
|
||||
milestones: List[(gitbucket.core.model.Milestone, Int, Int)],
|
||||
priorities: List[gitbucket.core.model.Priority],
|
||||
@@ -61,6 +62,7 @@
|
||||
issue = Some(issue),
|
||||
comments = comments,
|
||||
issueLabels = issueLabels,
|
||||
issueAssignees = issueAssignees,
|
||||
collaborators = collaborators,
|
||||
milestones = milestones,
|
||||
priorities = priorities,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
@(issue: Option[gitbucket.core.model.Issue],
|
||||
comments: List[gitbucket.core.model.Comment],
|
||||
issueLabels: List[gitbucket.core.model.Label],
|
||||
issueAssignees: List[gitbucket.core.model.IssueAssignee],
|
||||
collaborators: List[String],
|
||||
milestones: List[(gitbucket.core.model.Milestone, Int, Int)],
|
||||
priorities: List[gitbucket.core.model.Priority],
|
||||
@@ -127,11 +128,10 @@
|
||||
@if(isManageable){
|
||||
<div class="pull-right">
|
||||
@gitbucket.core.helper.html.dropdown("Edit", right = true, filter = ("assignee", "Filter Assignee")) {
|
||||
<li><a href="javascript:void(0);" class="assign" data-name=""><i class="octicon octicon-x"></i> Clear assignee</a></li>
|
||||
@collaborators.map { collaborator =>
|
||||
<li>
|
||||
<a href="javascript:void(0);" class="assign" data-name="@collaborator">
|
||||
@gitbucket.core.helper.html.checkicon(issue.exists(_.assignedUserName.exists(_ == collaborator)))@helpers.avatar(collaborator, 20) @collaborator
|
||||
<a href="javascript:void(0);" class="toggle-assign" data-name="@collaborator">
|
||||
@gitbucket.core.helper.html.checkicon(issueAssignees.exists(_.assigneeUserName == collaborator))@helpers.avatar(collaborator, 20) @collaborator
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
@@ -140,14 +140,15 @@
|
||||
}
|
||||
</div>
|
||||
<span id="label-assigned">
|
||||
@issue.flatMap(_.assignedUserName).map { userName =>
|
||||
@helpers.avatarLink(userName, 20) @helpers.user(userName, styleClass="username strong small")
|
||||
}.getOrElse{
|
||||
<span class="muted small">No one</span>
|
||||
@issueAssignees.map { asignee =>
|
||||
@helpers.avatarLink(asignee.assigneeUserName, 20) @helpers.user(asignee.assigneeUserName, styleClass="username strong small")
|
||||
}
|
||||
@if(issueAssignees.isEmpty) {
|
||||
<span class="muted small">No one assigned</span>
|
||||
}
|
||||
</span>
|
||||
@if(issue.isEmpty){
|
||||
<input type="hidden" name="assignedUserName" value=""/>
|
||||
<input type="hidden" name="assigneeUserNames" value=""/>
|
||||
}
|
||||
|
||||
@customFields.map { case (field, value) =>
|
||||
@@ -188,7 +189,7 @@
|
||||
$(function(){
|
||||
@issue.map { issue =>
|
||||
$('a.toggle-label').click(function(){
|
||||
const path = switchLabel($(this));
|
||||
const path = switchToggleOptions($(this));
|
||||
$.post('@helpers.url(repository)/issues/@issue.issueId/label/' + path,
|
||||
{ labelId : $(this).data('label-id') },
|
||||
function(data){
|
||||
@@ -223,19 +224,25 @@ $(function(){
|
||||
);
|
||||
});
|
||||
|
||||
$('a.assign').click(function(){
|
||||
const $this = $(this);
|
||||
const userName = $this.data('name');
|
||||
$.post('@helpers.url(repository)/issues/@issue.issueId/assign',
|
||||
{ assignedUserName: userName },
|
||||
function(){
|
||||
displayAssignee($this, userName);
|
||||
$('a.toggle-assign').click(function(){
|
||||
const path = switchToggleOptions($(this));
|
||||
$.post('@helpers.url(repository)/issues/@issue.issueId/assignee/' + path,
|
||||
{ assigneeUserName : $(this).data('name') },
|
||||
function(data){
|
||||
const assignees = Array();
|
||||
$('a.toggle-assign').each(function(i, e){
|
||||
if($(e).children('i').hasClass('octicon-check') == true){
|
||||
assignees.push($(e).text().trim());
|
||||
}
|
||||
});
|
||||
displayAssignee(assignees);
|
||||
}
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}.getOrElse {
|
||||
$('a.toggle-label').click(function(){
|
||||
switchLabel($(this));
|
||||
switchToggleOptions($(this));
|
||||
const labelNames = Array();
|
||||
$('a.toggle-label').each(function(i, e){
|
||||
if($(e).children('i').hasClass('octicon-check') == true){
|
||||
@@ -269,15 +276,20 @@ $(function(){
|
||||
$('input[name=priorityId]').val(priorityId);
|
||||
});
|
||||
|
||||
$('a.assign').click(function(){
|
||||
const $this = $(this);
|
||||
const userName = $this.data('name');
|
||||
displayAssignee($this, userName);
|
||||
$('input[name=assignedUserName]').val(userName);
|
||||
$('a.toggle-assign').click(function(){
|
||||
switchToggleOptions($(this));
|
||||
const assignees = Array();
|
||||
$('a.toggle-assign').each(function(i, e){
|
||||
if($(e).children('i').hasClass('octicon-check') == true){
|
||||
assignees.push($(e).text().trim());
|
||||
}
|
||||
});
|
||||
$('input[name=assigneeUserNames]').val(assignees.join(','));
|
||||
displayAssignee(assignees);
|
||||
});
|
||||
}
|
||||
|
||||
function switchLabel($this){
|
||||
function switchToggleOptions($this){
|
||||
const i = $this.children('i');
|
||||
if(i.hasClass('octicon-check')){
|
||||
i.removeClass('octicon-check');
|
||||
@@ -320,15 +332,18 @@ $(function(){
|
||||
}
|
||||
}
|
||||
|
||||
function displayAssignee($this, userName){
|
||||
function displayAssignee(assignees){
|
||||
$('a.assign i.octicon-check').removeClass('octicon-check');
|
||||
if(userName == ''){
|
||||
$('#label-assigned').html($('<span class="muted small">').text('No one'));
|
||||
if(assignees.length == 0){
|
||||
$('#label-assigned').html($('<span class="muted small">').text('No one assigned'));
|
||||
} else {
|
||||
$('#label-assigned').empty()
|
||||
.append($this.find('img.avatar-mini').clone(false)).append(' ')
|
||||
.append($('<a class="username strong small">').attr('href', '@context.path/' + userName).text(userName));
|
||||
$('a.assign[data-name=' + jqSelectorEscape(userName.toString()) + '] i').addClass('octicon-check');
|
||||
$('#label-assigned').empty();
|
||||
for (const userName of assignees) {
|
||||
$('#label-assigned').append($('<div>').append(
|
||||
$('a.toggle-assign').parent().find("img.avatar-mini[alt='@@" + userName + "']").clone(false),
|
||||
' ',
|
||||
$('<a class="username strong small">').attr('href', '@context.path/' + userName).text(userName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -230,9 +230,11 @@
|
||||
<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 small">
|
||||
@*
|
||||
@issue.assignedUserName.map { userName =>
|
||||
@helpers.avatar(userName, 20, tooltip = true)
|
||||
}
|
||||
*@
|
||||
@if(commentCount > 0){
|
||||
<a href="@context.path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-comment-count">
|
||||
<i class="octicon octicon-comment active"></i> @commentCount
|
||||
|
||||
@@ -90,9 +90,11 @@
|
||||
<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 small">
|
||||
@*
|
||||
@issue.assignedUserName.map { userName =>
|
||||
@helpers.avatar(userName, 20, tooltip = true)
|
||||
}
|
||||
*@
|
||||
@if(commentCount > 0){
|
||||
<a href="@context.path/@issue.userName/@issue.repositoryName/issues/@issue.issueId" class="issue-comment-count">
|
||||
<i class="octicon octicon-comment active"></i> @commentCount
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
issue = None,
|
||||
comments = Nil,
|
||||
issueLabels = Nil,
|
||||
issueAssignees = Nil,
|
||||
collaborators = collaborators,
|
||||
milestones = milestones.map((_, 0, 0)),
|
||||
priorities = priorities,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
comments: Seq[gitbucket.core.model.Comment],
|
||||
changedFileSize: Int,
|
||||
issueLabels: List[gitbucket.core.model.Label],
|
||||
issueAsignees: List[gitbucket.core.model.IssueAssignee],
|
||||
collaborators: List[String],
|
||||
milestones: List[(gitbucket.core.model.Milestone, Int, Int)],
|
||||
priorities: List[gitbucket.core.model.Priority],
|
||||
@@ -55,6 +56,7 @@
|
||||
Some(issue),
|
||||
comments.toList,
|
||||
issueLabels,
|
||||
issueAsignees,
|
||||
collaborators,
|
||||
milestones,
|
||||
priorities,
|
||||
|
||||
@@ -116,7 +116,6 @@ object ApiSpecModels {
|
||||
openedUserName = "bear",
|
||||
milestoneId = None,
|
||||
priorityId = None,
|
||||
assignedUserName = None,
|
||||
title = "Found a bug",
|
||||
content = Some("I'm having a problem with this."),
|
||||
closed = false,
|
||||
@@ -226,7 +225,7 @@ object ApiSpecModels {
|
||||
issue = issue,
|
||||
repositoryName = repo1Name,
|
||||
user = apiUser,
|
||||
assignee = Some(apiUser),
|
||||
assignees = List(apiUser),
|
||||
labels = List(apiLabel),
|
||||
milestone = Some(apiMilestone)
|
||||
)
|
||||
@@ -235,7 +234,7 @@ object ApiSpecModels {
|
||||
issue = issue,
|
||||
repositoryName = repo1Name,
|
||||
user = apiUser,
|
||||
assignee = None,
|
||||
assignees = List.empty,
|
||||
labels = List(apiLabel),
|
||||
milestone = Some(apiMilestone)
|
||||
)
|
||||
@@ -244,7 +243,7 @@ object ApiSpecModels {
|
||||
issue = issuePR,
|
||||
repositoryName = repo1Name,
|
||||
user = apiUser,
|
||||
assignee = Some(apiUser),
|
||||
assignees = List(apiUser),
|
||||
labels = List(apiLabel),
|
||||
milestone = Some(apiMilestone)
|
||||
)
|
||||
@@ -272,7 +271,7 @@ object ApiSpecModels {
|
||||
baseRepo = apiRepository,
|
||||
user = apiUser,
|
||||
labels = List(apiLabel),
|
||||
assignee = Some(apiUser),
|
||||
assignees = List(apiUser),
|
||||
mergedComment = Some((issueComment, account))
|
||||
)
|
||||
|
||||
@@ -540,7 +539,7 @@ object ApiSpecModels {
|
||||
|"number":1347,
|
||||
|"title":"Found a bug",
|
||||
|"user":$jsonUser,
|
||||
|"assignee":$jsonUser,
|
||||
|"assignees":[$jsonUser],
|
||||
|"labels":[$jsonLabel],
|
||||
|"state":"open",
|
||||
|"created_at":"2011-04-14T16:00:49Z",
|
||||
@@ -548,7 +547,7 @@ object ApiSpecModels {
|
||||
|"body":"I'm having a problem with this.",
|
||||
|"milestone":$jsonMilestone,
|
||||
|"id":0,
|
||||
|"assignees":[$jsonUser],
|
||||
|"assignee":$jsonUser,
|
||||
|"comments_url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/issues/1347/comments",
|
||||
|"html_url":"http://gitbucket.exmple.com/octocat/Hello-World/issues/1347"
|
||||
|}""".stripMargin
|
||||
@@ -557,6 +556,7 @@ object ApiSpecModels {
|
||||
|"number":1347,
|
||||
|"title":"Found a bug",
|
||||
|"user":$jsonUser,
|
||||
|"assignees":[],
|
||||
|"labels":[$jsonLabel],
|
||||
|"state":"open",
|
||||
|"created_at":"2011-04-14T16:00:49Z",
|
||||
@@ -564,7 +564,6 @@ object ApiSpecModels {
|
||||
|"body":"I'm having a problem with this.",
|
||||
|"milestone":$jsonMilestone,
|
||||
|"id":0,
|
||||
|"assignees":[],
|
||||
|"comments_url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/issues/1347/comments",
|
||||
|"html_url":"http://gitbucket.exmple.com/octocat/Hello-World/issues/1347"
|
||||
|}""".stripMargin
|
||||
@@ -573,7 +572,7 @@ object ApiSpecModels {
|
||||
|"number":1347,
|
||||
|"title":"new-feature",
|
||||
|"user":$jsonUser,
|
||||
|"assignee":$jsonUser,
|
||||
|"assignees":[$jsonUser],
|
||||
|"labels":[$jsonLabel],
|
||||
|"state":"closed",
|
||||
|"created_at":"2011-04-14T16:00:49Z",
|
||||
@@ -581,12 +580,12 @@ object ApiSpecModels {
|
||||
|"body":"Please pull these awesome changes",
|
||||
|"milestone":$jsonMilestone,
|
||||
|"id":0,
|
||||
|"assignees":[$jsonUser],
|
||||
|"assignee":$jsonUser,
|
||||
|"comments_url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/issues/1347/comments",
|
||||
|"html_url":"http://gitbucket.exmple.com/octocat/Hello-World/pull/1347",
|
||||
|"pull_request":{
|
||||
|"url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/pulls/1347",
|
||||
|"html_url":"http://gitbucket.exmple.com/octocat/Hello-World/pull/1347"}
|
||||
|"url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/pulls/1347",
|
||||
|"html_url":"http://gitbucket.exmple.com/octocat/Hello-World/pull/1347"}
|
||||
|}""".stripMargin
|
||||
|
||||
val jsonPullRequest = s"""{
|
||||
@@ -603,9 +602,10 @@ object ApiSpecModels {
|
||||
|"body":"Please pull these awesome changes",
|
||||
|"user":$jsonUser,
|
||||
|"labels":[$jsonLabel],
|
||||
|"assignee":$jsonUser,
|
||||
|"assignees":[$jsonUser],
|
||||
|"draft":true,
|
||||
|"id":0,
|
||||
|"assignee":$jsonUser,
|
||||
|"html_url":"http://gitbucket.exmple.com/octocat/Hello-World/pull/1347",
|
||||
|"url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/pulls/1347",
|
||||
|"commits_url":"http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/pulls/1347/commits",
|
||||
|
||||
@@ -142,7 +142,6 @@ trait ServiceSpecBase {
|
||||
loginUser = loginUser,
|
||||
title = "issue title",
|
||||
content = None,
|
||||
assignedUserName = None,
|
||||
milestoneId = None,
|
||||
priorityId = None,
|
||||
isPullRequest = true
|
||||
|
||||
@@ -91,7 +91,7 @@ class WebHookJsonFormatSpec extends AnyFunSuite {
|
||||
action = "closed",
|
||||
issue = issuePR,
|
||||
issueUser = account,
|
||||
assignee = Some(account),
|
||||
assignees = List(account),
|
||||
pullRequest = pullRequest,
|
||||
headRepository = repositoryInfo,
|
||||
headOwner = account,
|
||||
@@ -119,7 +119,7 @@ class WebHookJsonFormatSpec extends AnyFunSuite {
|
||||
commentUser = account,
|
||||
repository = repositoryInfo,
|
||||
repositoryUser = account,
|
||||
assignedUser = Some(account),
|
||||
assignees = List(account),
|
||||
sender = account,
|
||||
labels = List(label),
|
||||
milestone = Some(apiMilestone)
|
||||
@@ -140,7 +140,7 @@ class WebHookJsonFormatSpec extends AnyFunSuite {
|
||||
comment = commitComment,
|
||||
issue = issuePR,
|
||||
issueUser = account,
|
||||
assignee = Some(account),
|
||||
assignees = List(account),
|
||||
pullRequest = pullRequest,
|
||||
headRepository = repositoryInfo,
|
||||
headOwner = account,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package gitbucket.core.view
|
||||
|
||||
import gitbucket.core.util.SyntaxSugars
|
||||
import org.scalatest.funspec.AnyFunSpec
|
||||
|
||||
class PaginationSpec extends AnyFunSpec {
|
||||
|
||||
Reference in New Issue
Block a user