(refs #1286) Update collaborators setting form

This commit is contained in:
Naoki Takezoe
2016-11-06 16:32:37 +09:00
parent 132bb6bee4
commit dbdee135a3
7 changed files with 110 additions and 64 deletions

View File

@@ -108,12 +108,18 @@ trait IndexControllerBase extends ControllerBase {
*/
get("/_user/proposals")(usersOnly {
contentType = formats("json")
val user = params("user").toBoolean
val group = params("group").toBoolean
org.json4s.jackson.Serialization.write(
Map("options" -> (if(params.get("userOnly").isDefined) {
getAllUsers(false).filter(!_.isGroupAccount).map { t => (t.userName, t.isGroupAccount) }.toArray
} else {
getAllUsers(false).map { t => (t.userName, t.isGroupAccount) }.toArray
}).map { case (userName, groupAccount) => userName + ":" + groupAccount })
Map("options" -> (
getAllUsers(false)
.withFilter { t => (user, group) match {
case (true, true) => true
case (true, false) => !t.isGroupAccount
case (false, true) => t.isGroupAccount
case (false, false) => false
}}.map { t => t.userName }
))
)
})

View File

@@ -42,9 +42,9 @@ trait RepositorySettingsControllerBase extends ControllerBase {
"repositoryName" -> trim(label("Repository Name" , text(required, maxlength(40), identifier, renameRepositoryName))),
"description" -> trim(label("Description" , optional(text()))),
"isPrivate" -> trim(label("Repository Type" , boolean())),
"issuesOption" -> trim(label("Issues Option" , text(required))), // TODO enum check
"issuesOption" -> trim(label("Issues Option" , text(required, featureOption))),
"externalIssuesUrl" -> trim(label("External Issues URL", optional(text(maxlength(200))))),
"wikiOption" -> trim(label("Wiki Option" , text(required))), // TODO enum check
"wikiOption" -> trim(label("Wiki Option" , text(required, featureOption))),
"externalWikiUrl" -> trim(label("External Wiki URL" , optional(text(maxlength(200))))),
"allowFork" -> trim(label("Allow Forking" , boolean()))
)(OptionsForm.apply)
@@ -56,12 +56,12 @@ trait RepositorySettingsControllerBase extends ControllerBase {
"defaultBranch" -> trim(label("Default Branch" , text(required, maxlength(100))))
)(DefaultBranchForm.apply)
// for collaborator addition
case class CollaboratorForm(userName: String)
val collaboratorForm = mapping(
"userName" -> trim(label("Username", text(required, collaborator)))
)(CollaboratorForm.apply)
// // for collaborator addition
// case class CollaboratorForm(userName: String)
//
// val collaboratorForm = mapping(
// "userName" -> trim(label("Username", text(required, collaborator)))
// )(CollaboratorForm.apply)
// for web hook url addition
case class WebHookForm(url: String, events: Set[WebHook.Event], ctype: WebHookContentType, token: Option[String])
@@ -178,7 +178,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
post("/:owner/:repository/settings/collaborators")(ownerOnly { repository =>
val collaborators = params("collaborators")
removeCollaborators(repository.owner, repository.name)
collaborators.split(",").map { collaborator =>
collaborators.split(",").withFilter(_.nonEmpty).map { collaborator =>
val userName :: permission :: Nil = collaborator.split(":").toList
addCollaborator(repository.owner, repository.name, userName, permission)
}
@@ -384,20 +384,20 @@ trait RepositorySettingsControllerBase extends ControllerBase {
}
}
/**
* Provides Constraint to validate the collaborator name.
*/
private def collaborator: Constraint = new Constraint(){
override def validate(name: String, value: String, messages: Messages): Option[String] =
getAccountByUserName(value) match {
case None => Some("User does not exist.")
// case Some(x) if(x.isGroupAccount)
// => Some("User does not exist.")
case Some(x) if(x.userName == params("owner") || getCollaborators(params("owner"), params("repository")).contains(x.userName))
=> Some(value + " is repository owner.") // TODO also group members?
case _ => None
}
}
// /**
// * Provides Constraint to validate the collaborator name.
// */
// private def collaborator: Constraint = new Constraint(){
// override def validate(name: String, value: String, messages: Messages): Option[String] =
// getAccountByUserName(value) match {
// case None => Some("User does not exist.")
//// case Some(x) if(x.isGroupAccount)
//// => Some("User does not exist.")
// case Some(x) if(x.userName == params("owner") || getCollaborators(params("owner"), params("repository")).contains(x.userName))
// => Some(value + " is repository owner.") // TODO also group members?
// case _ => None
// }
// }
/**
* Duplicate check for the rename repository name.
@@ -411,6 +411,15 @@ trait RepositorySettingsControllerBase extends ControllerBase {
}
}
/**
*
*/
private def featureOption: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
if(Seq("DISABLE", "PRIVATE", "PUBLIC").contains(value)) None else Some("Option is invalid.")
}
/**
* Provides Constraint to validate the repository transfer user.
*/

View File

@@ -31,7 +31,7 @@
<label class="strong">Members</label>
<ul id="member-list" class="collaborator">
</ul>
@gitbucket.core.helper.html.account("memberName", 200)
@gitbucket.core.helper.html.account("memberName", 200, true, false)
<input type="button" class="btn btn-default" value="Add" id="addMember"/>
<input type="hidden" id="members" name="members" value="@members.map(member => member.userName + ":" + member.isManager).mkString(",")"/>
<div>

View File

@@ -34,7 +34,7 @@
<label class="strong">Members</label>
<ul id="member-list" class="collaborator">
</ul>
@gitbucket.core.helper.html.account("memberName", 200)
@gitbucket.core.helper.html.account("memberName", 200, true, false)
<input type="button" class="btn btn-default" value="Add" id="addMember"/>
<input type="hidden" id="members" name="members" value="@members.map(member => member.userName + ":" + member.isManager).mkString(",")"/>
<div>

View File

@@ -1,19 +1,19 @@
@(id: String, width: Int, userOnly: Boolean = true)(implicit context: gitbucket.core.controller.Context)
@(id: String, width: Int, user: Boolean, group: Boolean)(implicit context: gitbucket.core.controller.Context)
<span style="margin-right: 0px;">
<input type="text" name="@id" id="@id" class="form-control" autocomplete="off" style="width: @{width}px; margin-bottom: 0px; display: inline; vertical-align: middle;"/>
</span>
<script>
$(function(){
$('#@id').typeahead({
highlighter: function(item) {
var x = item.split(':');
return $('<div><strong>' + x[0] + '</strong>' + (x[1] == 'true' ? ' (group)' : '') + '</div>');
},
updater: function (item) {
return item.split(':')[0];
},
// highlighter: function(item) {
// var x = item.split(':');
// return $('<div><strong>' + x[0] + '</strong>' + (x[1] == 'true' ? ' (group)' : '') + '</div>');
// },
// updater: function (item) {
// return item.split(':')[0];
// },
source: function (query, process) {
return $.get('@context.path/_user/proposals@if(userOnly){?userOnly}', { query: query },
return $.get('@context.path/_user/proposals', { query: query, user: @user, group: @group },
function (data) {
return process(data.options);
});

View File

@@ -6,17 +6,35 @@
@gitbucket.core.html.main("Settings", Some(repository)){
@gitbucket.core.html.menu("settings", repository){
@gitbucket.core.settings.html.menu("collaborators", repository){
<h3>Manage Collaborators</h3>
<form id="form" method="post" action="@helpers.url(repository)/settings/collaborators">
<ul id="collaborator-list" class="collaborator">
</ul>
@gitbucket.core.helper.html.account("userName", 200, false)
<input type="button" class="btn btn-default" value="Add" id="addCollaborator"/>
<input type="hidden" id="collaborators" name="collaborators" value="@collaborators.map(x => x._1.userName + ":" + x._1.permission).mkString(",")"/>
<div>
<span class="error" id="error-collaborators"></span>
<div class="panel panel-default">
<div class="panel-heading strong">Collaborators</div>
<div class="panel-body">
<ul id="collaborator-list" class="collaborator">
</ul>
@gitbucket.core.helper.html.account("userName-collaborator", 200, true, false)
<input type="button" class="btn btn-default add" value="Add" id="addCollaborator"/>
<div>
<span class="error" id="error-collaborator"></span>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading strong">Groups</div>
<div class="panel-body">
<ul id="group-list" class="collaborator">
</ul>
@gitbucket.core.helper.html.account("userName-group", 200, false, true)
<input type="button" class="btn btn-default add" value="Add" id="addGroup"/>
<div>
<span class="error" id="error-group"></span>
</div>
</div>
</div>
<div class="align-right" style="margin-top: 20px;">
<input type="hidden" id="collaborators" name="collaborators" />
<input type="submit" class="btn btn-success" value="Apply changes"/>
</div>
</form>
@@ -26,24 +44,32 @@
<script>
$(function(){
$('input[type=submit]').click(function(){
updateCollaborators();
updateValues();
});
$('#addCollaborator').click(function(){
$('#error-collaborators').text('');
var userName = $('#userName').val();
$('.add').click(function(){
var id = $(this).attr('id') == 'addCollaborator' ? 'collaborator' : 'group';
$('#error-' + id).text('');
var userName = $('#userName-' + id).val();
// check empty
if($.trim(userName) == ''){
return false;
}
// check owner
var owner = '@repository.owner' == userName
if(owner){
$('#error-' + id).text('User is owner of this repository.');
return false;
}
// check duplication
var exists = $('#collaborator-list li').filter(function(){
var exists = $('#' + id + '-list li').filter(function(){
return $(this).data('name') == userName;
}).length > 0;
if(exists){
$('#error-collaborators').text('User has been already added.');
$('#error-' + id).text('User has been already added.');
return false;
}
@@ -51,9 +77,9 @@ $(function(){
$.post('@context.path/_user/existence', { 'userName': userName },
function(data, status){
if(data != ''){
addCollaboratorHTML(userName, '@Permission.ADMIN.name', data == 'group');
addListHTML(userName, '@Permission.ADMIN.name', '#' + id + '-list');
} else {
$('#error-collaborators').text('User does not exist.');
$('#error-' + id).text('User does not exist.');
}
});
});
@@ -63,15 +89,15 @@ $(function(){
});
// Don't submit form by ENTER key
$('#userName').keypress(function(e){
$('#userName-collaborator, #userName-group').keypress(function(e){
return !(e.keyCode == 13);
});
@collaborators.map { case (collaborator, isGroup) =>
addCollaboratorHTML('@collaborator.collaboratorName', '@collaborator.permission', @isGroup);
addListHTML('@collaborator.collaboratorName', '@collaborator.permission', @if(isGroup){'#group-list'}else{'#collaborator-list'});
}
function addCollaboratorHTML(userName, permission, isGroup){
function addListHTML(userName, permission, id){
var adminButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Permission.ADMIN.name" name="' + userName + '">Admin</label>');
if(permission == '@Permission.ADMIN.name'){
adminButton.addClass('active');
@@ -85,24 +111,29 @@ $(function(){
readButton.addClass('active');
}
$('#collaborator-list').append($('<li>')
$(id).append($('<li>')
.data('name', userName)
.append($('<div class="btn-group permission" data-toggle="buttons">')
.append(adminButton)
.append(writeButton)
.append(readButton))
.append(' ')
.append($('<a>').attr('href', '@context.path/' + userName).text(userName))
.append(isGroup ? ' (group)' : '')
.append($('<a target="_blank">').attr('href', '@context.path/' + userName).text(userName))
.append($('<a href="#" class="remove pull-right">(remove)</a>')));
}
function updateCollaborators(){
function updateValues(){
var collaborators = $('#collaborator-list li').map(function(i, e){
var userName = $(e).data('name');
return userName + ':' + $(e).find('label.active input[type=radio]').attr('value');
}).get().join(',');
$('#collaborators').val(collaborators);
var groups = $('#group-list li').map(function(i, e){
var userName = $(e).data('name');
return userName + ':' + $(e).find('label.active input[type=radio]').attr('value');
}).get().join(',');
$('#collaborators').val(collaborators + ',' + groups);
}
});
</script>

View File

@@ -13,7 +13,7 @@
<div>
Transfer this repo to another user or to group.
<div class="pull-right">
@gitbucket.core.helper.html.account("newOwner", 200)
@gitbucket.core.helper.html.account("newOwner", 200, true, true)
<input type="submit" class="btn btn-danger" value="Transfer"/>
<div>
<span id="error-newOwner" class="error"></span>