(refs #488)Issue label editing is completed

This commit is contained in:
takezoe
2014-10-05 15:37:09 +09:00
parent c92e71bb7a
commit 836913482b
7 changed files with 135 additions and 111 deletions

View File

@@ -5,6 +5,7 @@ import service._
import util.{ReferrerAuthenticator, CollaboratorsAuthenticator} import util.{ReferrerAuthenticator, CollaboratorsAuthenticator}
import util.Implicits._ import util.Implicits._
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
import org.scalatra.Ok
class LabelsController extends LabelsControllerBase class LabelsController extends LabelsControllerBase
with LabelsService with IssuesService with RepositoryService with AccountService with LabelsService with IssuesService with RepositoryService with AccountService
@@ -16,14 +17,9 @@ trait LabelsControllerBase extends ControllerBase {
case class LabelForm(labelName: String, color: String) case class LabelForm(labelName: String, color: String)
val newForm = mapping( val labelForm = mapping(
"newLabelName" -> trim(label("Label name", text(required, labelName, maxlength(100)))), "labelName" -> trim(label("Label name", text(required, labelName, maxlength(100)))),
"newColor" -> trim(label("Color", text(required, color))) "labelColor" -> trim(label("Color", text(required, color)))
)(LabelForm.apply)
val editForm = mapping(
"editLabelName" -> trim(label("Label name", text(required, labelName, maxlength(100)))),
"editColor" -> trim(label("Color", text(required, color)))
)(LabelForm.apply) )(LabelForm.apply)
get("/:owner/:repository/issues/labels")(referrersOnly { repository => get("/:owner/:repository/issues/labels")(referrersOnly { repository =>
@@ -38,9 +34,14 @@ trait LabelsControllerBase extends ControllerBase {
issues.labels.html.edit(None, repository) issues.labels.html.edit(None, repository)
}) })
post("/:owner/:repository/issues/labels/new", newForm)(collaboratorsOnly { (form, repository) => ajaxPost("/:owner/:repository/issues/labels/new", labelForm)(collaboratorsOnly { (form, repository) =>
createLabel(repository.owner, repository.name, form.labelName, form.color.substring(1)) val labelId = createLabel(repository.owner, repository.name, form.labelName, form.color.substring(1))
redirect(s"/${repository.owner}/${repository.name}/issues/labels") issues.labels.html.label(
getLabel(repository.owner, repository.name, labelId).get,
// TODO futility
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()),
repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
}) })
ajaxGet("/:owner/:repository/issues/labels/:labelId/edit")(collaboratorsOnly { repository => ajaxGet("/:owner/:repository/issues/labels/:labelId/edit")(collaboratorsOnly { repository =>
@@ -49,14 +50,19 @@ trait LabelsControllerBase extends ControllerBase {
} getOrElse NotFound() } getOrElse NotFound()
}) })
post("/:owner/:repository/issues/labels/:labelId/edit", editForm)(collaboratorsOnly { (form, repository) => ajaxPost("/:owner/:repository/issues/labels/:labelId/edit", labelForm)(collaboratorsOnly { (form, repository) =>
updateLabel(repository.owner, repository.name, params("labelId").toInt, form.labelName, form.color.substring(1)) updateLabel(repository.owner, repository.name, params("labelId").toInt, form.labelName, form.color.substring(1))
redirect(s"/${repository.owner}/${repository.name}/issues/labels") issues.labels.html.label(
getLabel(repository.owner, repository.name, params("labelId").toInt).get,
// TODO futility
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition()),
repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
}) })
get("/:owner/:repository/issues/labels/:labelId/delete")(collaboratorsOnly { repository => ajaxPost("/:owner/:repository/issues/labels/:labelId/delete")(collaboratorsOnly { repository =>
deleteLabel(repository.owner, repository.name, params("labelId").toInt) deleteLabel(repository.owner, repository.name, params("labelId").toInt)
redirect(s"/${repository.owner}/${repository.name}/issues/labels") Ok()
}) })
/** /**

View File

@@ -29,9 +29,9 @@ case class Label(
val b = color.substring(4, 6) val b = color.substring(4, 6)
if(Integer.parseInt(r, 16) + Integer.parseInt(g, 16) + Integer.parseInt(b, 16) > 408){ if(Integer.parseInt(r, 16) + Integer.parseInt(g, 16) + Integer.parseInt(b, 16) > 408){
"000000" "black"
} else { } else {
"FFFFFF" "white"
} }
} }
} }

View File

@@ -12,8 +12,8 @@ trait LabelsService {
def getLabel(owner: String, repository: String, labelId: Int)(implicit s: Session): Option[Label] = def getLabel(owner: String, repository: String, labelId: Int)(implicit s: Session): Option[Label] =
Labels.filter(_.byPrimaryKey(owner, repository, labelId)).firstOption Labels.filter(_.byPrimaryKey(owner, repository, labelId)).firstOption
def createLabel(owner: String, repository: String, labelName: String, color: String)(implicit s: Session): Unit = def createLabel(owner: String, repository: String, labelName: String, color: String)(implicit s: Session): Int =
Labels insert Label( Labels returning Labels.map(_.labelId) += Label(
userName = owner, userName = owner,
repositoryName = repository, repositoryName = repository,
labelName = labelName, labelName = labelName,

View File

@@ -1,41 +1,61 @@
@(label: Option[model.Label], repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context) @(label: Option[model.Label], repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
@import context._ @import context._
@import view.helpers._ @import view.helpers._
@defining(if(label.isEmpty) "new" else "edit"){ mode => @defining(label.map(_.labelId).getOrElse("new")){ labelId =>
<div id="@(mode)-label-area"> <div id="edit-label-area-@labelId">
<form method="POST" id="edit-label-form" validate="true" style="margin-bottom: 0px;" <form style="margin-bottom: 0px;">
action="@url(repository)/issues/labels/@{if(mode == "new") "new" else label.get.labelId + "/edit"}"> <input type="text" id="labelName-@labelId" style="width: 300px; margin-bottom: 0px;" value="@label.map(_.labelName)"@if(labelId == "new"){ placeholder="New label name"}/>
<span id="error-@(mode)LabelName" class="error"></span> <div id="label-color-@labelId" class="input-append color bscp" data-color="#@label.map(_.color).getOrElse("888888")" data-color-format="hex" style="width: 100px; margin-bottom: 0px;">
<input type="text" name="@(mode)LabelName" id="@(mode)LabelName" style="width: 300px; margin-bottom: 0px;" value="@label.map(_.labelName)"@if(mode == "new"){ placeholder="New label name"}/> <input type="text" class="span3" id="labelColor-@labelId" value="#@label.map(_.color)" readonly style="width: 100px;">
<span id="error-@(mode)Color" class="error"></span>
<div class="input-append color bscp" data-color="#@label.map(_.color).getOrElse("888888")" data-color-format="hex" id="@(mode)Color" style="width: 100px; margin-bottom: 0px;">
<input type="text" class="span3" name="@(mode)Color" value="#@label.map(_.color)" readonly style="width: 100px;">
<span class="add-on"><i style="background-color: #@label.map(_.color).getOrElse("888888");"></i></span> <span class="add-on"><i style="background-color: #@label.map(_.color).getOrElse("888888");"></i></span>
</div> </div>
<script>
$('div#label-color-@labelId').colorpicker();
</script>
<span id="label-error-@labelId" class="error" style="padding-left: 40px;"></span>
<span class="pull-right"> <span class="pull-right">
<input type="button" class="btn label-edit-cancel" value="Cancel"> <input type="button" id="cancel-@labelId" class="btn label-edit-cancel" value="Cancel">
<input type="submit" class="btn btn-success" style="margin-bottom: 0px;" value="@(if(mode == "new") "Create label" else "Save changes")"/> <input type="button" id="submit-@labelId" class="btn btn-success" style="margin-bottom: 0px;" value="@(if(labelId == "new") "Create label" else "Save changes")"/>
</span> </span>
@if(mode == "edit"){
<input type="hidden" name="editLabelId" value="@label.map(_.labelId)"/>
}
</form> </form>
<script>
$(function(){
@if(mode == "new"){
$('#newColor').colorpicker();
} else {
$('#editColor').colorpicker();
}
$.each($('form[validate=true]'), function(i, form){
$(form).submit(validate);
});
$('.label-edit-cancel').click(function(e){
closeLabelForm();
});
});
</script>
</div> </div>
<script>
$(function(){
$('#submit-@labelId').click(function(e){
$.post('@url(repository)/issues/labels/@{if(labelId == "new") "new" else labelId + "/edit"}', {
'labelName' : $('#labelName-@labelId').val(),
'labelColor': $('#labelColor-@labelId').val()
}, function(data, status){
$('div#edit-label-area-@labelId').remove();
@if(labelId == "new"){
$('#new-label-table').hide();
// Insert row into the top of table
$('#label-row-header').after(data);
} else {
// Replace table row
$('#label-row-@labelId').after(data).remove();
}
}).fail(function(xhr, status, error){
var errors = JSON.parse(xhr.responseText);
if(errors.labelName){
$('span#label-error-@labelId').text(errors.labelName);
} else if(errors.labelColor){
$('span#label-error-@labelId').text(errors.labelColor);
} else {
$('span#label-error-@labelId').text('error');
}
});
return false;
});
$('#cancel-@labelId').click(function(e){
$('div#edit-label-area-@labelId').remove();
@if(labelId == "new"){
$('#new-label-table').hide();
} else {
$('#label-@labelId').show();
}
});
});
</script>
} }

View File

@@ -0,0 +1,36 @@
@(label: model.Label,
counts: Map[String, Int],
repository: service.RepositoryService.RepositoryInfo,
hasWritePermission: Boolean)(implicit context: app.Context)
@import context._
@import view.helpers._
<tr id="label-row-@label.labelId">
<td style="padding-top: 15px; padding-bottom: 15px;">
<div class="milestone row-fluid" id="label-@label.labelId">
<div class="span8">
<div style="margin-top: 6px">
<a href="@url(repository)/issues?labels=@urlEncode(label.labelName)" id="label-row-content-@label.labelId">
<span style="background-color: #@label.color; color: @label.fontColor; padding: 8px; font-size: 120%; border-radius: 4px;">
<img src="@assets/common/images/label_@(label.fontColor).png" style="width: 12px;"/>
@label.labelName
</span>
</a>
</div>
</div>
<div class="@if(hasWritePermission){span2} else {span4}">
<div class="pull-right">
<span class="muted">@counts.get(label.labelName).getOrElse(0) open issues</span>
</div>
</div>
@if(hasWritePermission){
<div class="span2">
<div class="pull-right">
<a href="javascript:void(0);" onclick="editLabel(@label.labelId)">Edit</a>
&nbsp;&nbsp;
<a href="javascript:void(0);" onclick="deleteLabel(@label.labelId)">Delete</a>
</div>
</div>
}
</div>
</td>
</tr>

View File

@@ -11,41 +11,15 @@
<tr><td></td></tr> <tr><td></td></tr>
</table> </table>
<table class="table table-bordered table-hover table-issues"> <table class="table table-bordered table-hover table-issues">
<tr> <tr id="label-row-header">
<th style="background-color: #eee;"> <th style="background-color: #eee;">
<span class="small">@labels.size labels</span> <span class="small">@labels.size labels</span>
</th> </th>
</tr> </tr>
@labels.map { label => @labels.map { label =>
<tr> @_root_.issues.labels.html.label(label, counts, repository, hasWritePermission)
<td style="padding-top: 15px; padding-bottom: 15px;"> }
<div class="milestone row-fluid" id="label-@label.labelId"> @if(labels.isEmpty){
<div class="span8">
<div style="margin-top: 6px">
<a href="@url(repository)/issues?labels=@urlEncode(label.labelName)">
<span style="background-color: #@label.color; color: #@label.fontColor; padding: 8px; font-size: 120%; border-radius: 4px;">@label.labelName</span>
</a>
</div>
</div>
<div class="@if(hasWritePermission){span2} else {span4}">
<div class="pull-right">
<span class="muted">@counts.get(label.labelName).getOrElse(0) open issues</span>
</div>
</div>
@if(hasWritePermission){
<div class="span2">
<div class="pull-right">
<a href="javascript:void(0);" class="label-edit-link" data-label-id="@label.labelId">Edit</a>
&nbsp;&nbsp;
<a href="@url(repository)/issues/labels/@label.labelId/delete" class="delete">Delete</a>
</div>
</div>
}
</div>
</td>
</tr>
}
@if(labels.isEmpty){
<tr> <tr>
<td style="padding: 20px; background-color: #eee; text-align: center;"> <td style="padding: 20px; background-color: #eee; text-align: center;">
No labels to show. No labels to show.
@@ -60,15 +34,11 @@
} }
<script> <script>
$(function(){ $(function(){
$('a.delete').click(function(){
return confirm('Once you delete this label, there is no going back.\nAre you sure?');
});
$('#new-label-button').click(function(e){ $('#new-label-button').click(function(e){
if($('#new-label-area').size() != 0){ if($('#new-label-area').size() != 0){
closeLabelForm(); $('#new-label-table').hide();
$('#new-label-area').remove();
} else { } else {
closeLabelForm();
$.get('@url(repository)/issues/labels/new', $.get('@url(repository)/issues/labels/new',
function(data){ function(data){
$('#new-label-table').show().find('tr td').append(data); $('#new-label-table').show().find('tr td').append(data);
@@ -76,29 +46,21 @@ $(function(){
); );
} }
}); });
$('a.label-edit-link').click(function(e){
closeLabelForm();
var labelId = $(this).data('label-id');
$.get('@url(repository)/issues/labels/' + labelId + '/edit',
function(data){
$('#label-' + labelId).hide().parent().append(data);
}
);
});
}); });
function closeLabelForm(){ function deleteLabel(labelId){
// creation form if(confirm('Once you delete this label, there is no going back.\nAre you sure?')){
if($('#new-label-area').size() != 0){ $.post('@url(repository)/issues/labels/' + labelId + '/delete', function(){
$('#new-label-table').hide(); $('tr#label-row-' + labelId).remove();
$('#new-label-area').remove(); });
}
// editing form
var editingId = $('input[name=editLabelId]').val();
if(editingId){
$('#edit-label-area').remove();
$('#label-' + editingId).show();
} }
} }
function editLabel(labelId){
$.get('@url(repository)/issues/labels/' + labelId + '/edit',
function(data){
$('#label-' + labelId).hide().parent().append(data);
}
);
}
</script> </script>

View File

@@ -12,16 +12,16 @@
<div class="btn-group"> <div class="btn-group">
@if(newButton){ @if(newButton){
@if(active == "issues"){ @if(active == "issues"){
<a class="btn btn-small btn-success" href="@url(repository)/issues/new">New issue</a> <a class="btn btn-success" href="@url(repository)/issues/new">New issue</a>
} }
@if(active == "pulls"){ @if(active == "pulls"){
<a class="btn btn-small btn-success" href="@url(repository)/compare">New pull request</a> <a class="btn btn-success" href="@url(repository)/compare">New pull request</a>
} }
@if(active == "labels"){ @if(active == "labels"){
<a class="btn btn-small btn-success" href="javascript:void(0);" id="new-label-button">New label</a> <a class="btn btn-success" href="javascript:void(0);" id="new-label-button">New label</a>
} }
@if(active == "milestones"){ @if(active == "milestones"){
<a class="btn btn-small btn-success" href="@url(repository)/issues/milestones/new">New milestone</a> <a class="btn btn-success" href="@url(repository)/issues/milestones/new">New milestone</a>
} }
} }
</div> </div>