Commit 74c2fe9e authored by Alfredo Sumaran's avatar Alfredo Sumaran

Be able to select roles and users when creating a protected branch

parent b61128e5
/*= require protected_branch_access_dropdown */
(global => {
global.gl = global.gl || {};
class allowedToMergeDropdown extends gl.ProtectedBranchAccessDropdown {
fieldName(selectedItem) {
// Role by default
let fieldName = `protected_branch[merge_access_levels_attributes][${this.inputCount}][access_level]`;
if (selectedItem.type === 'user') {
fieldName = `protected_branch[merge_access_levels_attributes][${this.inputCount}][user_id]`;
}
return fieldName;
}
}
global.gl.allowedToMergeDropdown = allowedToMergeDropdown;
})(window);
/*= require protected_branch_access_dropdown */
(global => {
global.gl = global.gl || {};
class allowedToPushDropdown extends gl.ProtectedBranchAccessDropdown {
fieldName(selectedItem) {
// Role by default
let fieldName = `protected_branch[push_access_levels_attributes][${this.inputCount}][access_level]`;
if (selectedItem.type === 'user') {
fieldName = `protected_branch[push_access_levels_attributes][${this.inputCount}][user_id]`;
}
return fieldName;
}
}
global.gl.allowedToPushDropdown = allowedToPushDropdown;
})(window);
......@@ -470,7 +470,9 @@
} else {
if (!selected) {
value = this.options.id ? this.options.id(data) : data.id;
fieldName = this.options.fieldName;
// fieldName = this.options.fieldName;
fieldName = _.isFunction(this.options.fieldName) ? this.options.fieldName() : this.options.fieldName;
field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']");
if (field.length) {
selected = true;
......@@ -533,7 +535,7 @@
GitLabDropdown.prototype.rowClicked = function(el) {
var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value;
fieldName = this.options.fieldName;
// fieldName = this.options.fieldName;
isInput = $(this.el).is('input');
if (this.renderedData) {
groupName = el.data('group');
......@@ -545,6 +547,7 @@
selectedObject = this.renderedData[selectedIndex];
}
}
fieldName = _.isFunction(this.options.fieldName) ? this.options.fieldName(selectedObject) : this.options.fieldName;
value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
if (isInput) {
field = $(this.el);
......@@ -570,7 +573,7 @@
field.remove();
}
if (!field.length && fieldName) {
this.addInput(fieldName, value);
this.addInput(fieldName, value, selectedObject);
}
return selectedObject;
} else {
......@@ -589,7 +592,7 @@
}
if (value != null) {
if (!field.length && fieldName) {
this.addInput(fieldName, value);
this.addInput(fieldName, value, selectedObject);
} else {
field.val(value).trigger('change');
}
......@@ -598,12 +601,15 @@
}
};
GitLabDropdown.prototype.addInput = function(fieldName, value) {
GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) {
var $input;
$input = $('<input>').attr('type', 'hidden').attr('name', fieldName).val(value);
if (this.options.inputId != null) {
$input.attr('id', this.options.inputId);
}
if (selectedObject.type) {
$input.attr('data-type', selectedObject.type);
}
return this.dropdown.before($input);
};
......
......@@ -4,21 +4,124 @@
gl.ProtectedBranchAccessDropdown = class {
constructor(options) {
const { $dropdown, data, onSelect } = options;
const self = this;
this.$dropdown = $dropdown;
this.usersPath = '/autocomplete/users.json';
this.inputCount = 0;
$dropdown.glDropdown({
data: data,
selectable: true,
filterable: true,
filterRemote: true,
inputId: $dropdown.data('input-id'),
fieldName: $dropdown.data('field-name'),
toggleLabel(item) {
return item.text;
data: this.getData.bind(this),
multiSelect: $dropdown.hasClass('js-multiselect'),
renderRow: this.renderRow.bind(this),
toggleLabel: this.toggleLabel.bind(this),
fieldName: this.fieldName.bind(this),
setActiveIds() {
this.activeIds = self.getActiveIds();
},
clicked(item, $el, e) {
e.preventDefault();
self.inputCount++;
onSelect();
return;
}
});
}
fieldName() {
throw new Error('No fieldName method defined');
}
toggleLabel(selectedItem, el) {
let currentItems = this.$dropdown.siblings('.dropdown-menu').find('.is-active');
let types = _.groupBy(currentItems, (item) => { return item.dataset.type; });
let label = [];
_.allKeys(types).map((type) => {
label.push(`${types[type].length} ${type}`);
});
return label.join(' and ');
}
getData(query, callback) {
this.getUsers(query).done((response) => {
let data = this.consolidateData(response);
callback(data);
});
}
consolidateData(response, callback) {
let consolidatedData;
// This probably should come from the backend already formatted
let users = response.map((user) => {
user.type = 'user';
return user;
});
let mergeAccessLevels = gon.merge_access_levels.map((level) => {
level.type = 'role';
return level;
});
consolidatedData = mergeAccessLevels;
if (users.length) {
consolidatedData = mergeAccessLevels.concat(['divider'], users);
}
return consolidatedData;
}
getUsers(query) {
return $.ajax({
dataType: 'json',
url: this.buildUrl(this.usersPath),
data: {
search: query,
per_page: 20,
active: true,
project_id: gon.current_project_id,
push_code: true,
}
});
}
buildUrl(url) {
if (gon.relative_url_root != null) {
url = gon.relative_url_root.replace(/\/$/, '') + url;
}
return url;
}
renderRow(item, instance) {
if (item.type === 'user') {
return this.userRowHtml(item);
} else if (item.type === 'role') {
return this.roleRowHtml(item);
}
}
userRowHtml(user) {
const avatarHtml = `<img src='${user.avatar_url}' class='avatar avatar-inline' width='30'>`;
const nameHtml = `<strong class='dropdown-menu-user-full-name'>${user.name}</strong>`;
const usernameHtml = `<span class='dropdown-menu-user-username'>${user.username}</span>`;
return `<li><a href='#' data-type='${user.type}'>${avatarHtml} ${nameHtml} ${usernameHtml}</a></li>`;
}
roleRowHtml(role) {
return `<li><a href='#' data-type='${role.type}'>${role.text}</a></li>`;
}
getActiveIds() {
console.log('getActiveIds');
}
}
})(window);
......@@ -15,14 +15,14 @@
this.onSelectCallback = this.onSelect.bind(this);
// Allowed to Merge dropdown
new gl.ProtectedBranchAccessDropdown({
new gl.allowedToMergeDropdown({
$dropdown: $allowedToMergeDropdown,
data: gon.merge_access_levels,
onSelect: this.onSelectCallback
});
// Allowed to Push dropdown
new gl.ProtectedBranchAccessDropdown({
new gl.allowedToPushDropdown({
$dropdown: $allowedToPushDropdown,
data: gon.push_access_levels,
onSelect: this.onSelectCallback
......@@ -33,7 +33,7 @@
$allowedToMergeDropdown.data('glDropdown').selectRowAtIndex(0);
// Protected branch dropdown
new ProtectedBranchDropdown({
new gl.ProtectedBranchDropdown({
$dropdown: this.$wrap.find('.js-protected-branch-select'),
onSelect: this.onSelectCallback
});
......@@ -44,10 +44,12 @@
// Enable submit button
const $branchInput = this.$wrap.find('input[name="protected_branch[name]"]');
const $allowedToMergeInput = this.$wrap.find('input[name="protected_branch[merge_access_levels_attributes][0][access_level]"]');
const $allowedToPushInput = this.$wrap.find('input[name="protected_branch[push_access_levels_attributes][0][access_level]"]');
const $allowedToMergeInput = this.$wrap.find('input[name="protected_branch[merge_access_levels_attributes][][access_level]"]');
const $allowedToPushInput = this.$wrap.find('input[name="protected_branch[push_access_levels_attributes][][access_level]"]');
console.log('onSelect');
if ($branchInput.val() && $allowedToMergeInput.val() && $allowedToPushInput.val()){
console.log('onSelect');
this.$form.find('input[type="submit"]').removeAttr('disabled');
}
}
......
class ProtectedBranchDropdown {
(global => {
global.gl = global.gl || {};
class ProtectedBranchDropdown {
constructor(options) {
this.onSelect = options.onSelect;
this.$dropdown = options.$dropdown;
......@@ -72,4 +75,7 @@ class ProtectedBranchDropdown {
this.$dropdownFooter.toggleClass('hidden', !branchName);
}
}
}
global.gl.ProtectedBranchDropdown = ProtectedBranchDropdown;
})(window);
......@@ -23,15 +23,15 @@
Allowed to merge:
.col-md-10
= dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-merge wide',
data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }})
options: { toggle_class: 'js-allowed-to-merge wide js-multiselect js-multiselect', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable', filter: true,
data: { input_id: 'merge_access_levels_attributes' }})
.form-group
%label.col-md-2.text-right{ for: 'push_access_levels_attributes' }
Allowed to push:
.col-md-10
= dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-push wide',
data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }})
options: { toggle_class: 'js-allowed-to-push wide js-multiselect js-multiselect', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable', filter: true,
data: { input_id: 'push_access_levels_attributes' }})
.panel-footer
= f.submit 'Protect', class: 'btn-create btn', disabled: true
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment