mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 06:25:51 +01:00
(refs #488)Issue label editing is completed
This commit is contained in:
@@ -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()
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>
|
||||||
<span class="pull-right">
|
|
||||||
<input type="button" 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")"/>
|
|
||||||
</span>
|
|
||||||
@if(mode == "edit"){
|
|
||||||
<input type="hidden" name="editLabelId" value="@label.map(_.labelId)"/>
|
|
||||||
}
|
|
||||||
</form>
|
|
||||||
<script>
|
<script>
|
||||||
$(function(){
|
$('div#label-color-@labelId').colorpicker();
|
||||||
@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>
|
</script>
|
||||||
|
<span id="label-error-@labelId" class="error" style="padding-left: 40px;"></span>
|
||||||
|
<span class="pull-right">
|
||||||
|
<input type="button" id="cancel-@labelId" class="btn label-edit-cancel" value="Cancel">
|
||||||
|
<input type="button" id="submit-@labelId" class="btn btn-success" style="margin-bottom: 0px;" value="@(if(labelId == "new") "Create label" else "Save changes")"/>
|
||||||
|
</span>
|
||||||
|
</form>
|
||||||
</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>
|
||||||
}
|
}
|
||||||
|
|||||||
36
src/main/twirl/issues/labels/label.scala.html
Normal file
36
src/main/twirl/issues/labels/label.scala.html
Normal 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>
|
||||||
|
|
||||||
|
<a href="javascript:void(0);" onclick="deleteLabel(@label.labelId)">Delete</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
@@ -11,39 +11,13 @@
|
|||||||
<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">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<a href="@url(repository)/issues/labels/@label.labelId/delete" class="delete">Delete</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
}
|
||||||
@if(labels.isEmpty){
|
@if(labels.isEmpty){
|
||||||
<tr>
|
<tr>
|
||||||
@@ -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){
|
function deleteLabel(labelId){
|
||||||
closeLabelForm();
|
if(confirm('Once you delete this label, there is no going back.\nAre you sure?')){
|
||||||
var labelId = $(this).data('label-id');
|
$.post('@url(repository)/issues/labels/' + labelId + '/delete', function(){
|
||||||
|
$('tr#label-row-' + labelId).remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function editLabel(labelId){
|
||||||
$.get('@url(repository)/issues/labels/' + labelId + '/edit',
|
$.get('@url(repository)/issues/labels/' + labelId + '/edit',
|
||||||
function(data){
|
function(data){
|
||||||
$('#label-' + labelId).hide().parent().append(data);
|
$('#label-' + labelId).hide().parent().append(data);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function closeLabelForm(){
|
|
||||||
// creation form
|
|
||||||
if($('#new-label-area').size() != 0){
|
|
||||||
$('#new-label-table').hide();
|
|
||||||
$('#new-label-area').remove();
|
|
||||||
}
|
|
||||||
// editing form
|
|
||||||
var editingId = $('input[name=editLabelId]').val();
|
|
||||||
if(editingId){
|
|
||||||
$('#edit-label-area').remove();
|
|
||||||
$('#label-' + editingId).show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user