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 @@ ...@@ -470,7 +470,9 @@
} else { } else {
if (!selected) { if (!selected) {
value = this.options.id ? this.options.id(data) : data.id; 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 + "']"); field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']");
if (field.length) { if (field.length) {
selected = true; selected = true;
...@@ -533,7 +535,7 @@ ...@@ -533,7 +535,7 @@
GitLabDropdown.prototype.rowClicked = function(el) { GitLabDropdown.prototype.rowClicked = function(el) {
var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value; var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value;
fieldName = this.options.fieldName; // fieldName = this.options.fieldName;
isInput = $(this.el).is('input'); isInput = $(this.el).is('input');
if (this.renderedData) { if (this.renderedData) {
groupName = el.data('group'); groupName = el.data('group');
...@@ -545,6 +547,7 @@ ...@@ -545,6 +547,7 @@
selectedObject = this.renderedData[selectedIndex]; 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; value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
if (isInput) { if (isInput) {
field = $(this.el); field = $(this.el);
...@@ -570,7 +573,7 @@ ...@@ -570,7 +573,7 @@
field.remove(); field.remove();
} }
if (!field.length && fieldName) { if (!field.length && fieldName) {
this.addInput(fieldName, value); this.addInput(fieldName, value, selectedObject);
} }
return selectedObject; return selectedObject;
} else { } else {
...@@ -589,7 +592,7 @@ ...@@ -589,7 +592,7 @@
} }
if (value != null) { if (value != null) {
if (!field.length && fieldName) { if (!field.length && fieldName) {
this.addInput(fieldName, value); this.addInput(fieldName, value, selectedObject);
} else { } else {
field.val(value).trigger('change'); field.val(value).trigger('change');
} }
...@@ -598,12 +601,15 @@ ...@@ -598,12 +601,15 @@
} }
}; };
GitLabDropdown.prototype.addInput = function(fieldName, value) { GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) {
var $input; var $input;
$input = $('<input>').attr('type', 'hidden').attr('name', fieldName).val(value); $input = $('<input>').attr('type', 'hidden').attr('name', fieldName).val(value);
if (this.options.inputId != null) { if (this.options.inputId != null) {
$input.attr('id', this.options.inputId); $input.attr('id', this.options.inputId);
} }
if (selectedObject.type) {
$input.attr('data-type', selectedObject.type);
}
return this.dropdown.before($input); return this.dropdown.before($input);
}; };
......
...@@ -4,21 +4,124 @@ ...@@ -4,21 +4,124 @@
gl.ProtectedBranchAccessDropdown = class { gl.ProtectedBranchAccessDropdown = class {
constructor(options) { constructor(options) {
const { $dropdown, data, onSelect } = options; const { $dropdown, data, onSelect } = options;
const self = this;
this.$dropdown = $dropdown;
this.usersPath = '/autocomplete/users.json';
this.inputCount = 0;
$dropdown.glDropdown({ $dropdown.glDropdown({
data: data,
selectable: true, selectable: true,
filterable: true,
filterRemote: true,
inputId: $dropdown.data('input-id'), inputId: $dropdown.data('input-id'),
fieldName: $dropdown.data('field-name'), data: this.getData.bind(this),
toggleLabel(item) { multiSelect: $dropdown.hasClass('js-multiselect'),
return item.text; renderRow: this.renderRow.bind(this),
toggleLabel: this.toggleLabel.bind(this),
fieldName: this.fieldName.bind(this),
setActiveIds() {
this.activeIds = self.getActiveIds();
}, },
clicked(item, $el, e) { clicked(item, $el, e) {
e.preventDefault(); e.preventDefault();
self.inputCount++;
onSelect(); 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); })(window);
...@@ -15,14 +15,14 @@ ...@@ -15,14 +15,14 @@
this.onSelectCallback = this.onSelect.bind(this); this.onSelectCallback = this.onSelect.bind(this);
// Allowed to Merge dropdown // Allowed to Merge dropdown
new gl.ProtectedBranchAccessDropdown({ new gl.allowedToMergeDropdown({
$dropdown: $allowedToMergeDropdown, $dropdown: $allowedToMergeDropdown,
data: gon.merge_access_levels, data: gon.merge_access_levels,
onSelect: this.onSelectCallback onSelect: this.onSelectCallback
}); });
// Allowed to Push dropdown // Allowed to Push dropdown
new gl.ProtectedBranchAccessDropdown({ new gl.allowedToPushDropdown({
$dropdown: $allowedToPushDropdown, $dropdown: $allowedToPushDropdown,
data: gon.push_access_levels, data: gon.push_access_levels,
onSelect: this.onSelectCallback onSelect: this.onSelectCallback
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
$allowedToMergeDropdown.data('glDropdown').selectRowAtIndex(0); $allowedToMergeDropdown.data('glDropdown').selectRowAtIndex(0);
// Protected branch dropdown // Protected branch dropdown
new ProtectedBranchDropdown({ new gl.ProtectedBranchDropdown({
$dropdown: this.$wrap.find('.js-protected-branch-select'), $dropdown: this.$wrap.find('.js-protected-branch-select'),
onSelect: this.onSelectCallback onSelect: this.onSelectCallback
}); });
...@@ -44,10 +44,12 @@ ...@@ -44,10 +44,12 @@
// Enable submit button // Enable submit button
const $branchInput = this.$wrap.find('input[name="protected_branch[name]"]'); 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 $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][0][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()){ if ($branchInput.val() && $allowedToMergeInput.val() && $allowedToPushInput.val()){
console.log('onSelect');
this.$form.find('input[type="submit"]').removeAttr('disabled'); this.$form.find('input[type="submit"]').removeAttr('disabled');
} }
} }
......
class ProtectedBranchDropdown { (global => {
constructor(options) { global.gl = global.gl || {};
this.onSelect = options.onSelect;
this.$dropdown = options.$dropdown;
this.$dropdownContainer = this.$dropdown.parent();
this.$dropdownFooter = this.$dropdownContainer.find('.dropdown-footer');
this.$protectedBranch = this.$dropdownContainer.find('.create-new-protected-branch');
this.buildDropdown(); class ProtectedBranchDropdown {
this.bindEvents(); constructor(options) {
this.onSelect = options.onSelect;
this.$dropdown = options.$dropdown;
this.$dropdownContainer = this.$dropdown.parent();
this.$dropdownFooter = this.$dropdownContainer.find('.dropdown-footer');
this.$protectedBranch = this.$dropdownContainer.find('.create-new-protected-branch');
// Hide footer this.buildDropdown();
this.$dropdownFooter.addClass('hidden'); this.bindEvents();
}
buildDropdown() {
this.$dropdown.glDropdown({
data: this.getProtectedBranches.bind(this),
filterable: true,
remote: false,
search: {
fields: ['title']
},
selectable: true,
toggleLabel(selected) {
return (selected && 'id' in selected) ? selected.title : 'Protected Branch';
},
fieldName: 'protected_branch[name]',
text(protectedBranch) {
return _.escape(protectedBranch.title);
},
id(protectedBranch) {
return _.escape(protectedBranch.id);
},
onFilter: this.toggleCreateNewButton.bind(this),
clicked: (item, $el, e) => {
e.preventDefault();
this.onSelect();
}
});
}
bindEvents() { // Hide footer
this.$protectedBranch.on('click', this.onClickCreateWildcard.bind(this)); this.$dropdownFooter.addClass('hidden');
} }
onClickCreateWildcard() { buildDropdown() {
this.$dropdown.data('glDropdown').remote.execute(); this.$dropdown.glDropdown({
this.$dropdown.data('glDropdown').selectRowAtIndex(0); data: this.getProtectedBranches.bind(this),
} filterable: true,
remote: false,
search: {
fields: ['title']
},
selectable: true,
toggleLabel(selected) {
return (selected && 'id' in selected) ? selected.title : 'Protected Branch';
},
fieldName: 'protected_branch[name]',
text(protectedBranch) {
return _.escape(protectedBranch.title);
},
id(protectedBranch) {
return _.escape(protectedBranch.id);
},
onFilter: this.toggleCreateNewButton.bind(this),
clicked: (item, $el, e) => {
e.preventDefault();
this.onSelect();
}
});
}
getProtectedBranches(term, callback) { bindEvents() {
if (this.selectedBranch) { this.$protectedBranch.on('click', this.onClickCreateWildcard.bind(this));
callback(gon.open_branches.concat(this.selectedBranch));
} else {
callback(gon.open_branches);
} }
}
toggleCreateNewButton(branchName) { onClickCreateWildcard() {
this.selectedBranch = { this.$dropdown.data('glDropdown').remote.execute();
title: branchName, this.$dropdown.data('glDropdown').selectRowAtIndex(0);
id: branchName, }
text: branchName
};
if (branchName) { getProtectedBranches(term, callback) {
this.$dropdownContainer if (this.selectedBranch) {
.find('.create-new-protected-branch code') callback(gon.open_branches.concat(this.selectedBranch));
.text(branchName); } else {
callback(gon.open_branches);
}
} }
this.$dropdownFooter.toggleClass('hidden', !branchName); toggleCreateNewButton(branchName) {
this.selectedBranch = {
title: branchName,
id: branchName,
text: branchName
};
if (branchName) {
this.$dropdownContainer
.find('.create-new-protected-branch code')
.text(branchName);
}
this.$dropdownFooter.toggleClass('hidden', !branchName);
}
} }
}
global.gl.ProtectedBranchDropdown = ProtectedBranchDropdown;
})(window);
...@@ -23,15 +23,15 @@ ...@@ -23,15 +23,15 @@
Allowed to merge: Allowed to merge:
.col-md-10 .col-md-10
= dropdown_tag('Select', = dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-merge wide', options: { toggle_class: 'js-allowed-to-merge wide js-multiselect js-multiselect', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable', filter: true,
data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }}) data: { input_id: 'merge_access_levels_attributes' }})
.form-group .form-group
%label.col-md-2.text-right{ for: 'push_access_levels_attributes' } %label.col-md-2.text-right{ for: 'push_access_levels_attributes' }
Allowed to push: Allowed to push:
.col-md-10 .col-md-10
= dropdown_tag('Select', = dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-push wide', options: { toggle_class: 'js-allowed-to-push wide js-multiselect js-multiselect', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable', filter: true,
data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }}) data: { input_id: 'push_access_levels_attributes' }})
.panel-footer .panel-footer
= f.submit 'Protect', class: 'btn-create btn', disabled: true = 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