(refs #11) Implemented the batch update.

This commit is contained in:
shimamoto
2013-07-11 13:43:42 +09:00
parent 46b3807f21
commit b81a30ef12
3 changed files with 84 additions and 8 deletions

View File

@@ -222,6 +222,53 @@ trait IssuesControllerBase extends ControllerBase {
Ok("updated") Ok("updated")
}) })
post("/:owner/:repository/issues/batchedit/state")(collaboratorsOnly { repository =>
val owner = repository.owner
val name = repository.name
val userName = context.loginAccount.get.userName
params.get("value") collect {
case s if s == "close" => (s.capitalize, Some(s), true)
case s if s == "reopen" => (s.capitalize, Some(s), false)
} map { case (content, action, closed) =>
params("checked").split(',') foreach { issueId =>
createComment(owner, name, userName, issueId.toInt, content, action)
updateClosed(owner, name, issueId.toInt, closed)
}
redirect("/%s/%s/issues".format(owner, name))
} getOrElse NotFound
})
post("/:owner/:repository/issues/batchedit/label")(collaboratorsOnly { repository =>
val owner = repository.owner
val name = repository.name
params.get("value").map(_.toInt) map { labelId =>
params("checked").split(',') foreach { issueId =>
getIssueLabel(owner, name, issueId.toInt, labelId) getOrElse {
registerIssueLabel(owner, name, issueId.toInt, labelId)
}
}
redirect("/%s/%s/issues".format(owner, name))
} getOrElse NotFound
})
post("/:owner/:repository/issues/batchedit/assign")(collaboratorsOnly { repository =>
params("checked").split(',') foreach { issueId =>
updateAssignedUserName(repository.owner, repository.name, issueId.toInt,
params.get("value") filter (_.trim != ""))
}
redirect("/%s/%s/issues".format(repository.owner, repository.name))
})
post("/:owner/:repository/issues/batchedit/milestone")(collaboratorsOnly { repository =>
params("checked").split(',') foreach { issueId =>
updateMilestoneId(repository.owner, repository.name, issueId.toInt,
params.get("value") collect { case x if x.trim != "" => x.toInt })
}
redirect("/%s/%s/issues".format(repository.owner, repository.name))
})
private def isEditable(owner: String, repository: String, author: String)(implicit context: app.Context): Boolean = private def isEditable(owner: String, repository: String, author: String)(implicit context: app.Context): Boolean =
hasWritePermission(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName hasWritePermission(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
@@ -248,8 +295,9 @@ trait IssuesControllerBase extends ControllerBase {
issues.html.list( issues.html.list(
searchIssue(owner, repoName, condition, filter, userName, (page - 1) * IssueLimit, IssueLimit), searchIssue(owner, repoName, condition, filter, userName, (page - 1) * IssueLimit, IssueLimit),
page, page,
getLabels(owner, repoName), (getCollaborators(owner, repoName) :+ owner).sorted,
getMilestones(owner, repoName).filter(_.closedDate.isEmpty), getMilestones(owner, repoName).filter(_.closedDate.isEmpty),
getLabels(owner, repoName),
countIssue(owner, repoName, condition.copy(state = "open"), filter, userName), countIssue(owner, repoName, condition.copy(state = "open"), filter, userName),
countIssue(owner, repoName, condition.copy(state = "closed"), filter, userName), countIssue(owner, repoName, condition.copy(state = "closed"), filter, userName),
countIssue(owner, repoName, condition, "all", None), countIssue(owner, repoName, condition, "all", None),

View File

@@ -35,6 +35,9 @@ trait IssuesService {
.map ( _._2 ) .map ( _._2 )
.list .list
def getIssueLabel(owner: String, repository: String, issueId: Int, labelId: Int) =
Query(IssueLabels) filter (_.byPrimaryKey(owner, repository, issueId, labelId)) firstOption
/** /**
* Returns the count of the search result against issues. * Returns the count of the search result against issues.
* *

View File

@@ -1,7 +1,8 @@
@(issues: List[(model.Issue, List[model.Label], Int)], @(issues: List[(model.Issue, List[model.Label], Int)],
page: Int, page: Int,
labels: List[model.Label], collaborators: List[String],
milestones: List[model.Milestone], milestones: List[model.Milestone],
labels: List[model.Label],
openCount: Int, openCount: Int,
closedCount: Int, closedCount: Int,
allCount: Int, allCount: Int,
@@ -181,12 +182,12 @@
<tr> <tr>
<td style="background-color: #eee;"> <td style="background-color: #eee;">
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-mini"><strong>@if(condition.state == "open"){ Close } else { Reopen }</strong></button> <button class="btn btn-mini" id="state"><strong>@{if(condition.state == "open") "Close" else "Reopen"}</strong></button>
</div> </div>
@helper.html.dropdown("Label") { @helper.html.dropdown("Label") {
@labels.map { label => @labels.map { label =>
<li> <li>
<a href="javascript:void(0);" class="toggle-label" data-label-id="@label.labelId"> <a href="javascript:void(0);" class="toggle-label" data-id="@label.labelId">
<i class="icon-white"></i> <i class="icon-white"></i>
<span class="label" style="background-color: #@label.color;">&nbsp;</span> <span class="label" style="background-color: #@label.color;">&nbsp;</span>
@label.labelName @label.labelName
@@ -195,14 +196,17 @@
} }
} }
@helper.html.dropdown("Assignee") { @helper.html.dropdown("Assignee") {
<li><a href="javascript:void(0);" class="assign" data-name=""><i class="icon-remove-circle"></i> Clear assignee</a></li> <li><a href="javascript:void(0);" class="toggle-assign" data-name=""><i class="icon-remove-circle"></i> Clear assignee</a></li>
<li class="divider"></li> <li class="divider"></li>
@collaborators.map { collaborator =>
<li><a href="javascript:void(0);" class="toggle-assign" data-name="@collaborator"><i class="icon-white"></i>@avatar(collaborator, 20) @collaborator</a></li>
}
} }
@helper.html.dropdown("Milestone") { @helper.html.dropdown("Milestone") {
<li><a href="javascript:void(0);" class="milestone" data-id=""><i class="icon-remove-circle"></i> Clear this milestone</a></li> <li><a href="javascript:void(0);" class="toggle-milestone" data-id=""><i class="icon-remove-circle"></i> Clear this milestone</a></li>
<li class="divider"></li> <li class="divider"></li>
@milestones.map { milestone => @milestones.map { milestone =>
<li><a href="javascript:void(0);" class="milestone" data-id="@milestone.milestoneId"><i class="icon-white"></i> @milestone.title</a></li> <li><a href="javascript:void(0);" class="toggle-milestone" data-id="@milestone.milestoneId"><i class="icon-white"></i> @milestone.title</a></li>
} }
} }
</td> </td>
@@ -257,7 +261,28 @@ $(function(){
$('.table-issues input[type=checkbox]').change(function(){ $('.table-issues input[type=checkbox]').change(function(){
$('.table-issues button').prop('disabled', $('.table-issues button').prop('disabled',
!$('.table-issues input[type=checkbox]').filter(':checked').length); !$('.table-issues input[type=checkbox]').filter(':checked').length);
}).change(); }).filter(':first').change();
var submitBatchEdit = function(action, value) {
var checked = $('.table-issues input[type=checkbox]').filter(':checked').map(function(){ return this.value; }).get().join();
$('<form>').attr({action : action, method : 'POST'})
.append($('<input type="hidden">').attr('name', 'value').val(value))
.append($('<input type="hidden">').attr('name', 'checked').val(checked))
.submit();
};
$('#state').click(function(){
submitBatchEdit('@url(repository)/issues/batchedit/state', $(this).text().toLowerCase());
});
$('a.toggle-label').click(function(){
submitBatchEdit('@url(repository)/issues/batchedit/label', $(this).data('id'));
});
$('a.toggle-assign').click(function(){
submitBatchEdit('@url(repository)/issues/batchedit/assign', $(this).data('name'));
});
$('a.toggle-milestone').click(function(){
submitBatchEdit('@url(repository)/issues/batchedit/milestone', $(this).data('id'));
});
}); });
</script> </script>
} }