Commit 1de21943 authored by Tim Zallmann's avatar Tim Zallmann

Merge branch 'ee-31031-convert-protected-branches-es6' into 'master'

EE - Convert Protected Branches feature JS code to ES6

See merge request !2481
parents 69067637 1067010e
export const ACCESS_LEVELS = {
MERGE: 'merge_access_levels',
PUSH: 'push_access_levels',
};
export const LEVEL_TYPES = {
ROLE: 'role',
USER: 'user',
GROUP: 'group',
};
export const LEVEL_ID_PROP = {
ROLE: 'access_level',
USER: 'user_id',
GROUP: 'group_id',
};
export const ACCESS_LEVEL_NONE = 0;
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
import './protected_branch_access_dropdown';
import './protected_branch_create'; import ProtectedBranchCreate from './protected_branch_create';
import './protected_branch_dropdown'; import ProtectedBranchEditList from './protected_branch_edit_list';
import './protected_branch_edit';
import './protected_branch_edit_list';
$(() => { $(() => {
const protectedBranchCreate = new gl.ProtectedBranchCreate(); const protectedBranchCreate = new ProtectedBranchCreate();
const protectedBranchEditList = new gl.ProtectedBranchEditList(); const protectedBranchEditList = new ProtectedBranchEditList();
}); });
/* eslint-disable arrow-parens, no-param-reassign, object-shorthand, no-else-return, comma-dangle, no-underscore-dangle, no-continue, no-restricted-syntax, guard-for-in, no-new, class-methods-use-this, consistent-return, max-len */ /* eslint-disable no-underscore-dangle, class-methods-use-this */
/* global Flash */ /* global Flash */
(global => { import { LEVEL_TYPES, LEVEL_ID_PROP, ACCESS_LEVEL_NONE } from './constants';
global.gl = global.gl || {};
const PUSH_ACCESS_LEVEL = 'push_access_levels'; export default class ProtectedBranchAccessDropdown {
const LEVEL_TYPES = {
ROLE: 'role',
USER: 'user',
GROUP: 'group'
};
gl.ProtectedBranchAccessDropdown = class {
constructor(options) { constructor(options) {
const self = this;
const { const {
$dropdown, $dropdown,
onSelect,
onHide,
accessLevel, accessLevel,
accessLevelsData accessLevelsData,
} = options; } = options;
this.options = options;
this.isAllowedToPushDropdown = false;
this.groups = []; this.groups = [];
this.accessLevel = accessLevel; this.accessLevel = accessLevel;
this.accessLevelsData = accessLevelsData.roles; this.accessLevelsData = accessLevelsData.roles;
this.$dropdown = $dropdown; this.$dropdown = $dropdown;
this.$wrap = this.$dropdown.closest(`.${this.accessLevel}-container`); this.$wrap = this.$dropdown.closest(`.${this.accessLevel}-container`);
this.$protectedTagsContainer = $('.js-protected-branches-container');
this.usersPath = '/autocomplete/users.json'; this.usersPath = '/autocomplete/users.json';
this.groupsPath = '/autocomplete/project_groups.json'; this.groupsPath = '/autocomplete/project_groups.json';
this.defaultLabel = this.$dropdown.data('defaultLabel'); this.defaultLabel = this.$dropdown.data('defaultLabel');
...@@ -35,17 +24,19 @@ ...@@ -35,17 +24,19 @@
this.setSelectedItems([]); this.setSelectedItems([]);
this.persistPreselectedItems(); this.persistPreselectedItems();
if (PUSH_ACCESS_LEVEL === this.accessLevel) { this.noOneObj = this.accessLevelsData.find(level => level.id === ACCESS_LEVEL_NONE);
this.isAllowedToPushDropdown = true;
this.noOneObj = this.accessLevelsData[2]; this.initDropdown();
} }
$dropdown.glDropdown({ initDropdown() {
const { onSelect, onHide } = this.options;
this.$dropdown.glDropdown({
data: this.getData.bind(this),
selectable: true, selectable: true,
filterable: true, filterable: true,
filterRemote: true, filterRemote: true,
data: this.getData.bind(this), multiSelect: this.$dropdown.hasClass('js-multiselect'),
multiSelect: $dropdown.hasClass('js-multiselect'),
renderRow: this.renderRow.bind(this), renderRow: this.renderRow.bind(this),
toggleLabel: this.toggleLabel.bind(this), toggleLabel: this.toggleLabel.bind(this),
hidden() { hidden() {
...@@ -53,69 +44,69 @@ ...@@ -53,69 +44,69 @@
onHide(); onHide();
} }
}, },
clicked(opts) { clicked: (options) => {
const { $el, e } = opts; const { $el, e } = options;
const item = opts.selectedObj; const item = options.selectedObj;
e.preventDefault(); e.preventDefault();
if ($el.is('.is-active')) { if ($el.is('.is-active')) {
if (self.isAllowedToPushDropdown) { if (item.id === this.noOneObj.id) {
if (item.id === self.noOneObj.id) {
// remove all others selected items // remove all others selected items
self.accessLevelsData.forEach((level) => { this.accessLevelsData.forEach((level) => {
if (level.id !== item.id) { if (level.id !== item.id) {
self.removeSelectedItem(level); this.removeSelectedItem(level);
} }
}); });
// remove selected item visually // remove selected item visually
self.$wrap.find(`.item-${item.type}`).removeClass('is-active'); this.$wrap.find(`.item-${item.type}`).removeClass('is-active');
} else { } else {
const $noOne = self.$wrap.find(`.is-active.item-${item.type}:contains('No one')`); const $noOne = this.$wrap.find(`.is-active.item-${item.type}[data-role-id="${this.noOneObj.id}"]`);
if ($noOne.length) { if ($noOne.length) {
$noOne.removeClass('is-active'); $noOne.removeClass('is-active');
self.removeSelectedItem(self.noOneObj); this.removeSelectedItem(this.noOneObj);
} }
} }
// make element active right away // make element active right away
$el.addClass(`is-active item-${item.type}`); $el.addClass(`is-active item-${item.type}`);
}
// Add "No one" // Add "No one"
self.addSelectedItem(item); this.addSelectedItem(item);
} else { } else {
self.removeSelectedItem(item); this.removeSelectedItem(item);
} }
if (onSelect) { if (onSelect) {
onSelect(item, $el, self); onSelect(item, $el, this);
}
} }
},
}); });
} }
persistPreselectedItems() { persistPreselectedItems() {
const itemsToPreselect = this.$dropdown.data('preselectedItems'); const itemsToPreselect = this.$dropdown.data('preselectedItems');
if (typeof itemsToPreselect === 'undefined' || !itemsToPreselect.length) { if (!itemsToPreselect || !itemsToPreselect.length) {
return; return;
} }
itemsToPreselect.forEach((item) => { const persistedItems = itemsToPreselect.map((item) => {
item.persisted = true; const persistedItem = Object.assign({}, item);
persistedItem.persisted = true;
return persistedItem;
}); });
this.setSelectedItems(itemsToPreselect); this.setSelectedItems(persistedItems);
} }
setSelectedItems(items) { setSelectedItems(items = []) {
this.items = items.length ? items : []; this.items = items;
} }
getSelectedItems() { getSelectedItems() {
return this.items.filter((item) => !item._destroy); return this.items.filter(item => !item._destroy);
} }
getAllSelectedItems() { getAllSelectedItems() {
...@@ -124,10 +115,9 @@ ...@@ -124,10 +115,9 @@
// Return dropdown as input data ready to submit // Return dropdown as input data ready to submit
getInputData() { getInputData() {
const accessLevels = [];
const selectedItems = this.getAllSelectedItems(); const selectedItems = this.getAllSelectedItems();
selectedItems.forEach((item) => { const accessLevels = selectedItems.map((item) => {
const obj = {}; const obj = {};
if (typeof item.id !== 'undefined') { if (typeof item.id !== 'undefined') {
...@@ -146,7 +136,7 @@ ...@@ -146,7 +136,7 @@
obj.group_id = item.group_id; obj.group_id = item.group_id;
} }
accessLevels.push(obj); return obj;
}); });
return accessLevels; return accessLevels;
...@@ -159,12 +149,27 @@ ...@@ -159,12 +149,27 @@
let index = -1; let index = -1;
const selectedItems = this.getAllSelectedItems(); const selectedItems = this.getAllSelectedItems();
for (let i = 0; i < selectedItems.length; i += 1) { // Compare IDs based on selectedItem.type
if (selectedItem.id === selectedItems[i].access_level) { selectedItems.forEach((item, i) => {
let comparator;
switch (selectedItem.type) {
case LEVEL_TYPES.ROLE:
comparator = LEVEL_ID_PROP.ROLE;
break;
case LEVEL_TYPES.GROUP:
comparator = LEVEL_ID_PROP.GROUP;
break;
case LEVEL_TYPES.USER:
comparator = LEVEL_ID_PROP.USER;
break;
default:
break;
}
if (selectedItem.id === item[comparator]) {
index = i; index = i;
continue;
}
} }
});
if (index !== -1 && selectedItems[index]._destroy) { if (index !== -1 && selectedItems[index]._destroy) {
delete selectedItems[index]._destroy; delete selectedItems[index]._destroy;
...@@ -179,17 +184,17 @@ ...@@ -179,17 +184,17 @@
name: selectedItem.name || '_name1', name: selectedItem.name || '_name1',
username: selectedItem.username || '_username1', username: selectedItem.username || '_username1',
avatar_url: selectedItem.avatar_url || '_avatar_url1', avatar_url: selectedItem.avatar_url || '_avatar_url1',
type: LEVEL_TYPES.USER type: LEVEL_TYPES.USER,
}; };
} else if (selectedItem.type === LEVEL_TYPES.ROLE) { } else if (selectedItem.type === LEVEL_TYPES.ROLE) {
itemToAdd = { itemToAdd = {
access_level: selectedItem.id, access_level: selectedItem.id,
type: LEVEL_TYPES.ROLE type: LEVEL_TYPES.ROLE,
}; };
} else if (selectedItem.type === LEVEL_TYPES.GROUP) { } else if (selectedItem.type === LEVEL_TYPES.GROUP) {
itemToAdd = { itemToAdd = {
group_id: selectedItem.id, group_id: selectedItem.id,
type: LEVEL_TYPES.GROUP type: LEVEL_TYPES.GROUP,
}; };
} }
...@@ -201,23 +206,25 @@ ...@@ -201,23 +206,25 @@
const selectedItems = this.getAllSelectedItems(); const selectedItems = this.getAllSelectedItems();
// To find itemToDelete on selectedItems, first we need the index // To find itemToDelete on selectedItems, first we need the index
for (let i = 0; i < selectedItems.length; i += 1) { selectedItems.every((item, i) => {
const currentItem = selectedItems[i]; if (item.type !== itemToDelete.type) {
return true;
if (currentItem.type !== itemToDelete.type) {
continue;
} }
if (currentItem.type === LEVEL_TYPES.USER && currentItem.user_id === itemToDelete.id) { if (item.type === LEVEL_TYPES.USER &&
item.user_id === itemToDelete.id) {
index = i; index = i;
} else if (currentItem.type === LEVEL_TYPES.ROLE && currentItem.access_level === itemToDelete.id) { } else if (item.type === LEVEL_TYPES.ROLE &&
item.access_level === itemToDelete.id) {
index = i; index = i;
} else if (currentItem.type === LEVEL_TYPES.GROUP && currentItem.group_id === itemToDelete.id) { } else if (item.type === LEVEL_TYPES.GROUP &&
item.group_id === itemToDelete.id) {
index = i; index = i;
} }
if (index > -1) { break; } // Break once we have index set
} return !(index > -1);
});
// if ItemToDelete is not really selected do nothing // if ItemToDelete is not really selected do nothing
if (index === -1) { if (index === -1) {
...@@ -238,17 +245,17 @@ ...@@ -238,17 +245,17 @@
toggleLabel() { toggleLabel() {
const currentItems = this.getSelectedItems(); const currentItems = this.getSelectedItems();
const types = _.groupBy(currentItems, (item) => item.type); const types = _.groupBy(currentItems, item => item.type);
const label = []; let label = [];
if (currentItems.length) { if (currentItems.length) {
for (const LEVEL_TYPE in LEVEL_TYPES) { label = Object.keys(LEVEL_TYPES).map((levelType) => {
const typeName = LEVEL_TYPES[LEVEL_TYPE]; const typeName = LEVEL_TYPES[levelType];
const numberOfTypes = types[typeName] ? types[typeName].length : 0; const numberOfTypes = types[typeName] ? types[typeName].length : 0;
const text = numberOfTypes === 1 ? typeName : `${typeName}s`; const text = numberOfTypes === 1 ? typeName : `${typeName}s`;
label.push(`${numberOfTypes} ${text}`); return `${numberOfTypes} ${text}`;
} });
} else { } else {
label.push(this.defaultLabel); label.push(this.defaultLabel);
} }
...@@ -259,27 +266,25 @@ ...@@ -259,27 +266,25 @@
} }
getData(query, callback) { getData(query, callback) {
this.getUsers(query).done((usersResponse) => { this.getUsers(query)
.done((usersResponse) => {
if (this.groups.length) { if (this.groups.length) {
callback(this.consolidateData(usersResponse, this.groups)); callback(this.consolidateData(usersResponse, this.groups));
} else { } else {
this.getGroups(query).done((groupsResponse) => { this.getGroups(query)
.done((groupsResponse) => {
// Cache groups to avoid multiple requests // Cache groups to avoid multiple requests
this.groups = groupsResponse; this.groups = groupsResponse;
callback(this.consolidateData(usersResponse, groupsResponse)); callback(this.consolidateData(usersResponse, groupsResponse));
}); })
.error(() => new Flash('Failed to load groups.'));
} }
}).error(() => { }).error(() => new Flash('Failed to load users.'));
new Flash('Failed to load users.');
});
} }
consolidateData(usersResponse, groupsResponse) { consolidateData(usersResponse, groupsResponse) {
let consolidatedData = []; let consolidatedData = [];
const map = []; const map = [];
let roles = [];
const users = [];
let groups = [];
const selectedItems = this.getSelectedItems(); const selectedItems = this.getSelectedItems();
// ID property is handled differently locally from the server // ID property is handled differently locally from the server
...@@ -299,15 +304,18 @@ ...@@ -299,15 +304,18 @@
/* /*
* Build groups * Build groups
*/ */
groups = groupsResponse.map((group) => { const groups = groupsResponse.map(group => ({ ...group, type: LEVEL_TYPES.GROUP }));
group.type = LEVEL_TYPES.GROUP;
return group;
});
/* /*
* Build roles * Build roles
*/ */
roles = this.accessLevelsData.map((level) => { const roles = this.accessLevelsData.map((level) => {
/* eslint-disable no-param-reassign */
// This re-assignment is intentional as
// level.type property is being used in removeSelectedItem()
// for comparision, and accessLevelsData is provided by
// gon.create_access_levels which doesn't have `type` included.
// See this discussion https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1629#note_31285823
level.type = LEVEL_TYPES.ROLE; level.type = LEVEL_TYPES.ROLE;
return level; return level;
}); });
...@@ -315,38 +323,32 @@ ...@@ -315,38 +323,32 @@
/* /*
* Build users * Build users
*/ */
for (let x = 0; x < selectedItems.length; x += 1) { const users = selectedItems.filter(item => item.type === LEVEL_TYPES.USER).map((item) => {
const current = selectedItems[x]; // Save identifiers for easy-checking more later
map.push(LEVEL_TYPES.USER + item.user_id);
if (current.type !== LEVEL_TYPES.USER) { continue; }
// Collect selected users return {
users.push({ id: item.user_id,
id: current.user_id, name: item.name,
name: current.name, username: item.username,
username: current.username, avatar_url: item.avatar_url,
avatar_url: current.avatar_url,
type: LEVEL_TYPES.USER, type: LEVEL_TYPES.USER,
};
}); });
// Save identifiers for easy-checking more later
map.push(LEVEL_TYPES.USER + current.user_id);
}
// Has to be checked against server response // Has to be checked against server response
// because the selected item can be in filter results // because the selected item can be in filter results
for (let i = 0; i < usersResponse.length; i += 1) { usersResponse.forEach((response) => {
const u = usersResponse[i];
// Add is it has not been added // Add is it has not been added
if (map.indexOf(LEVEL_TYPES.USER + u.id) === -1) { if (map.indexOf(LEVEL_TYPES.USER + response.id) === -1) {
u.type = LEVEL_TYPES.USER; const user = Object.assign({}, response);
users.push(u); user.type = LEVEL_TYPES.USER;
} users.push(user);
} }
});
if (roles.length) { if (roles.length) {
consolidatedData = consolidatedData.concat([{ header: 'Roles', }], roles); consolidatedData = consolidatedData.concat([{ header: 'Roles' }], roles);
} }
if (groups.length) { if (groups.length) {
...@@ -354,11 +356,11 @@ ...@@ -354,11 +356,11 @@
consolidatedData = consolidatedData.concat(['divider']); consolidatedData = consolidatedData.concat(['divider']);
} }
consolidatedData = consolidatedData.concat([{ header: 'Groups', }], groups); consolidatedData = consolidatedData.concat([{ header: 'Groups' }], groups);
} }
if (users.length) { if (users.length) {
consolidatedData = consolidatedData.concat(['divider'], [{ header: 'Users', }], users); consolidatedData = consolidatedData.concat(['divider'], [{ header: 'Users' }], users);
} }
return consolidatedData; return consolidatedData;
...@@ -367,73 +369,112 @@ ...@@ -367,73 +369,112 @@
getUsers(query) { getUsers(query) {
return $.ajax({ return $.ajax({
dataType: 'json', dataType: 'json',
url: this.buildUrl(this.usersPath), url: this.buildUrl(gon.relative_url_root, this.usersPath),
data: { data: {
search: query, search: query,
per_page: 20, per_page: 20,
active: true, active: true,
project_id: gon.current_project_id, project_id: gon.current_project_id,
push_code: true, push_code: true,
} },
}); });
} }
getGroups() { getGroups() {
return $.ajax({ return $.ajax({
dataType: 'json', dataType: 'json',
url: this.buildUrl(this.groupsPath), url: this.buildUrl(gon.relative_url_root, this.groupsPath),
data: { data: {
project_id: gon.current_project_id project_id: gon.current_project_id,
} },
}); });
} }
buildUrl(url) { buildUrl(urlRoot, url) {
if (gon.relative_url_root != null) { let newUrl;
url = gon.relative_url_root.replace(/\/$/, '') + url; if (urlRoot != null) {
newUrl = urlRoot.replace(/\/$/, '') + url;
} }
return url; return newUrl;
} }
renderRow(item) { renderRow(item) {
let criteria = {}; let criteria = {};
let groupRowEl;
// Dectect if the current item is already saved so we can add // Dectect if the current item is already saved so we can add
// the `is-active` class so the item looks as marked // the `is-active` class so the item looks as marked
if (item.type === LEVEL_TYPES.USER) { switch (item.type) {
case LEVEL_TYPES.USER:
criteria = { user_id: item.id }; criteria = { user_id: item.id };
} else if (item.type === LEVEL_TYPES.ROLE) { break;
case LEVEL_TYPES.ROLE:
criteria = { access_level: item.id }; criteria = { access_level: item.id };
} else if (item.type === LEVEL_TYPES.GROUP) { break;
case LEVEL_TYPES.GROUP:
criteria = { group_id: item.id }; criteria = { group_id: item.id };
break;
default:
break;
} }
const isActive = _.findWhere(this.getSelectedItems(), criteria) ? 'is-active' : ''; const isActive = _.findWhere(this.getSelectedItems(), criteria) ? 'is-active' : '';
if (item.type === LEVEL_TYPES.USER) { switch (item.type) {
return this.userRowHtml(item, isActive); case LEVEL_TYPES.USER:
} else if (item.type === LEVEL_TYPES.ROLE) { groupRowEl = this.userRowHtml(item, isActive);
return this.roleRowHtml(item, isActive); break;
} else if (item.type === LEVEL_TYPES.GROUP) { case LEVEL_TYPES.ROLE:
return this.groupRowHtml(item, isActive); groupRowEl = this.roleRowHtml(item, isActive);
break;
case LEVEL_TYPES.GROUP:
groupRowEl = this.groupRowHtml(item, isActive);
break;
default:
groupRowEl = '';
break;
} }
return groupRowEl;
} }
userRowHtml(user, isActive) { userRowHtml(user, isActive) {
const avatarHtml = `<img src='${user.avatar_url}' class='avatar avatar-inline' width='30'>`; const isActiveClass = isActive || '';
const nameHtml = `<strong class='dropdown-menu-user-full-name'>${user.name}</strong>`;
const usernameHtml = `<span class='dropdown-menu-user-username'>${user.username}</span>`; return `
return `<li><a href='#' class='${isActive ? 'is-active' : ''}'>${avatarHtml} ${nameHtml} ${usernameHtml}</a></li>`; <li>
<a href="#" class="${isActiveClass}">
<img src="${user.avatar_url}" class="avatar avatar-inline" width="30">
<strong class="dropdown-menu-user-full-name">${user.name}</strong>
<span class="dropdown-menu-user-username">${user.username}</span>
</a>
</li>
`;
} }
groupRowHtml(group, isActive) { groupRowHtml(group, isActive) {
const avatarHtml = group.avatar_url ? `<img src='${group.avatar_url}' class='avatar avatar-inline' width='30'>` : ''; const isActiveClass = isActive || '';
const groupnameHtml = `<span class='dropdown-menu-group-groupname'>${group.name}</span>`; const avatarEl = group.avatar_url ? `<img src="${group.avatar_url}" class="avatar avatar-inline" width="30">` : '';
return `<li><a href='#' class='${isActive ? 'is-active' : ''}'>${avatarHtml} ${groupnameHtml}</a></li>`;
return `
<li>
<a href="#" class="${isActiveClass}">
${avatarEl}
<span class="dropdown-menu-group-groupname">${group.name}</span>
</a>
</li>
`;
} }
roleRowHtml(role, isActive) { roleRowHtml(role, isActive) {
return `<li><a href='#' class='${isActive ? 'is-active' : ''} item-${role.type}'>${role.text}</a></li>`; const isActiveClass = isActive || '';
return `
<li>
<a href="#" class="${isActiveClass} item-${role.type}" data-role-id="${role.id}">
${role.text}
</a>
</li>
`;
} }
}; }
})(window);
/* eslint-disable no-new, arrow-parens, no-param-reassign, comma-dangle, guard-for-in, no-restricted-syntax, max-len */
/* global ProtectedBranchDropdown */
/* global Flash */ /* global Flash */
(global => { import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
global.gl = global.gl || {}; import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown';
import ProtectedBranchDropdown from './protected_branch_dropdown';
const ACCESS_LEVELS = { export default class ProtectedBranchCreate {
MERGE: 'merge_access_levels',
PUSH: 'push_access_levels',
};
const LEVEL_TYPES = {
ROLE: 'role',
USER: 'user',
GROUP: 'group'
};
gl.ProtectedBranchCreate = class {
constructor() { constructor() {
this.$wrap = this.$form = $('.js-new-protected-branch'); this.$form = $('.js-new-protected-branch');
this.buildDropdowns(); this.buildDropdowns();
this.$branchInput = this.$wrap.find('input[name="protected_branch[name]"]'); this.$branchInput = this.$form.find('input[name="protected_branch[name]"]');
this.bindEvents(); this.bindEvents();
} }
...@@ -29,32 +17,31 @@ ...@@ -29,32 +17,31 @@
} }
buildDropdowns() { buildDropdowns() {
const $allowedToMergeDropdown = this.$wrap.find('.js-allowed-to-merge'); const $allowedToMergeDropdown = this.$form.find('.js-allowed-to-merge');
const $allowedToPushDropdown = this.$wrap.find('.js-allowed-to-push'); const $allowedToPushDropdown = this.$form.find('.js-allowed-to-push');
// Cache callback // Cache callback
this.onSelectCallback = this.onSelect.bind(this); this.onSelectCallback = this.onSelect.bind(this);
// Allowed to Merge dropdown // Allowed to Merge dropdown
this[`${ACCESS_LEVELS.MERGE}_dropdown`] = new gl.ProtectedBranchAccessDropdown({ this[`${ACCESS_LEVELS.MERGE}_dropdown`] = new ProtectedBranchAccessDropdown({
$dropdown: $allowedToMergeDropdown, $dropdown: $allowedToMergeDropdown,
accessLevelsData: gon.merge_access_levels, accessLevelsData: gon.merge_access_levels,
onSelect: this.onSelectCallback, onSelect: this.onSelectCallback,
accessLevel: ACCESS_LEVELS.MERGE accessLevel: ACCESS_LEVELS.MERGE,
}); });
// Allowed to Push dropdown // Allowed to Push dropdown
this[`${ACCESS_LEVELS.PUSH}_dropdown`] = new gl.ProtectedBranchAccessDropdown({ this[`${ACCESS_LEVELS.PUSH}_dropdown`] = new ProtectedBranchAccessDropdown({
$dropdown: $allowedToPushDropdown, $dropdown: $allowedToPushDropdown,
accessLevelsData: gon.push_access_levels, accessLevelsData: gon.push_access_levels,
onSelect: this.onSelectCallback, onSelect: this.onSelectCallback,
accessLevel: ACCESS_LEVELS.PUSH accessLevel: ACCESS_LEVELS.PUSH,
}); });
// Protected branch dropdown this.protectedBranchDropdown = new ProtectedBranchDropdown({
new window.ProtectedBranchDropdown({ $dropdown: this.$form.find('.js-protected-branch-select'),
$dropdown: this.$wrap.find('.js-protected-branch-select'), onSelect: this.onSelectCallback,
onSelect: this.onSelectCallback
}); });
} }
...@@ -62,7 +49,7 @@ ...@@ -62,7 +49,7 @@
onSelect() { onSelect() {
const $allowedToMerge = this[`${ACCESS_LEVELS.MERGE}_dropdown`].getSelectedItems(); const $allowedToMerge = this[`${ACCESS_LEVELS.MERGE}_dropdown`].getSelectedItems();
const $allowedToPush = this[`${ACCESS_LEVELS.PUSH}_dropdown`].getSelectedItems(); const $allowedToPush = this[`${ACCESS_LEVELS.PUSH}_dropdown`].getSelectedItems();
const toggle = !(this.$wrap.find('input[name="protected_branch[name]"]').val() && $allowedToMerge.length && $allowedToPush.length); const toggle = !(this.$form.find('input[name="protected_branch[name]"]').val() && $allowedToMerge.length && $allowedToPush.length);
this.$form.find('input[type="submit"]').attr('disabled', toggle); this.$form.find('input[type="submit"]').attr('disabled', toggle);
} }
...@@ -71,34 +58,33 @@ ...@@ -71,34 +58,33 @@
const formData = { const formData = {
authenticity_token: this.$form.find('input[name="authenticity_token"]').val(), authenticity_token: this.$form.find('input[name="authenticity_token"]').val(),
protected_branch: { protected_branch: {
name: this.$wrap.find('input[name="protected_branch[name]"]').val(), name: this.$form.find('input[name="protected_branch[name]"]').val(),
} },
}; };
for (const ACCESS_LEVEL in ACCESS_LEVELS) { Object.keys(ACCESS_LEVELS).forEach((level) => {
const selectedItems = this[`${ACCESS_LEVELS[ACCESS_LEVEL]}_dropdown`].getSelectedItems(); const accessLevel = ACCESS_LEVELS[level];
const selectedItems = this[`${accessLevel}_dropdown`].getSelectedItems();
const levelAttributes = []; const levelAttributes = [];
for (let i = 0; i < selectedItems.length; i += 1) { selectedItems.forEach((item) => {
const current = selectedItems[i]; if (item.type === LEVEL_TYPES.USER) {
if (current.type === LEVEL_TYPES.USER) {
levelAttributes.push({ levelAttributes.push({
user_id: selectedItems[i].user_id user_id: item.user_id,
}); });
} else if (current.type === LEVEL_TYPES.ROLE) { } else if (item.type === LEVEL_TYPES.ROLE) {
levelAttributes.push({ levelAttributes.push({
access_level: selectedItems[i].access_level access_level: item.access_level,
}); });
} else if (current.type === LEVEL_TYPES.GROUP) { } else if (item.type === LEVEL_TYPES.GROUP) {
levelAttributes.push({ levelAttributes.push({
group_id: selectedItems[i].group_id group_id: item.group_id,
}); });
} }
} });
formData.protected_branch[`${ACCESS_LEVELS[ACCESS_LEVEL]}_attributes`] = levelAttributes; formData.protected_branch[`${accessLevel}_attributes`] = levelAttributes;
} });
return formData; return formData;
} }
...@@ -109,14 +95,11 @@ ...@@ -109,14 +95,11 @@
$.ajax({ $.ajax({
url: this.$form.attr('action'), url: this.$form.attr('action'),
method: this.$form.attr('method'), method: this.$form.attr('method'),
data: this.getFormData() data: this.getFormData(),
}) })
.success(() => { .success(() => {
location.reload(); location.reload();
}) })
.fail(() => { .fail(() => new Flash('Failed to protect the branch'));
new Flash('Failed to protect the branch');
});
} }
}; }
})(window);
/* eslint-disable comma-dangle, no-unused-vars */ export default class ProtectedBranchDropdown {
/**
class ProtectedBranchDropdown { * @param {Object} options containing
* `$dropdown` target element
* `onSelect` event callback
* $dropdown must be an element created using `dropdown_tag()` rails helper
*/
constructor(options) { constructor(options) {
this.onSelect = options.onSelect; this.onSelect = options.onSelect;
this.$dropdown = options.$dropdown; this.$dropdown = options.$dropdown;
...@@ -12,7 +16,7 @@ class ProtectedBranchDropdown { ...@@ -12,7 +16,7 @@ class ProtectedBranchDropdown {
this.bindEvents(); this.bindEvents();
// Hide footer // Hide footer
this.$dropdownFooter.addClass('hidden'); this.toggleFooter(true);
} }
buildDropdown() { buildDropdown() {
...@@ -21,7 +25,7 @@ class ProtectedBranchDropdown { ...@@ -21,7 +25,7 @@ class ProtectedBranchDropdown {
filterable: true, filterable: true,
remote: false, remote: false,
search: { search: {
fields: ['title'] fields: ['title'],
}, },
selectable: true, selectable: true,
toggleLabel(selected) { toggleLabel(selected) {
...@@ -36,10 +40,9 @@ class ProtectedBranchDropdown { ...@@ -36,10 +40,9 @@ class ProtectedBranchDropdown {
}, },
onFilter: this.toggleCreateNewButton.bind(this), onFilter: this.toggleCreateNewButton.bind(this),
clicked: (options) => { clicked: (options) => {
const { $el, e } = options; options.e.preventDefault();
e.preventDefault();
this.onSelect(); this.onSelect();
} },
}); });
} }
...@@ -64,20 +67,22 @@ class ProtectedBranchDropdown { ...@@ -64,20 +67,22 @@ class ProtectedBranchDropdown {
} }
toggleCreateNewButton(branchName) { toggleCreateNewButton(branchName) {
if (branchName) {
this.selectedBranch = { this.selectedBranch = {
title: branchName, title: branchName,
id: branchName, id: branchName,
text: branchName text: branchName,
}; };
if (branchName) {
this.$dropdownContainer this.$dropdownContainer
.find('.js-create-new-protected-branch code') .find('.js-create-new-protected-branch code')
.text(branchName); .text(branchName);
} }
this.$dropdownFooter.toggleClass('hidden', !branchName); this.toggleFooter(!branchName);
} }
}
window.ProtectedBranchDropdown = ProtectedBranchDropdown; toggleFooter(toggleState) {
this.$dropdownFooter.toggleClass('hidden', toggleState);
}
}
/* eslint-disable no-new, arrow-parens, no-param-reassign, comma-dangle, dot-notation, no-unused-vars, no-restricted-syntax, guard-for-in, max-len */ /* eslint-disable no-new */
/* global Flash */ /* global Flash */
(global => { import { ACCESS_LEVELS, LEVEL_TYPES } from './constants';
global.gl = global.gl || {}; import ProtectedBranchAccessDropdown from './protected_branch_access_dropdown';
const ACCESS_LEVELS = { export default class ProtectedBranchEdit {
MERGE: 'merge_access_levels',
PUSH: 'push_access_levels',
};
const LEVEL_TYPES = {
ROLE: 'role',
USER: 'user',
GROUP: 'group'
};
gl.ProtectedBranchEdit = class {
constructor(options) { constructor(options) {
this.$wraps = {}; this.$wraps = {};
this.hasChanges = false; this.hasChanges = false;
...@@ -31,44 +20,46 @@ ...@@ -31,44 +20,46 @@
buildDropdowns() { buildDropdowns() {
// Allowed to merge dropdown // Allowed to merge dropdown
this['merge_access_levels_dropdown'] = new gl.ProtectedBranchAccessDropdown({ this[`${ACCESS_LEVELS.MERGE}_dropdown`] = new ProtectedBranchAccessDropdown({
accessLevel: ACCESS_LEVELS.MERGE, accessLevel: ACCESS_LEVELS.MERGE,
accessLevelsData: gon.merge_access_levels, accessLevelsData: gon.merge_access_levels,
$dropdown: this.$allowedToMergeDropdown, $dropdown: this.$allowedToMergeDropdown,
onSelect: this.onSelectOption.bind(this), onSelect: this.onSelectOption.bind(this),
onHide: this.onDropdownHide.bind(this) onHide: this.onDropdownHide.bind(this),
}); });
// Allowed to push dropdown // Allowed to push dropdown
this['push_access_levels_dropdown'] = new gl.ProtectedBranchAccessDropdown({ this[`${ACCESS_LEVELS.PUSH}_dropdown`] = new ProtectedBranchAccessDropdown({
accessLevel: ACCESS_LEVELS.PUSH, accessLevel: ACCESS_LEVELS.PUSH,
accessLevelsData: gon.push_access_levels, accessLevelsData: gon.push_access_levels,
$dropdown: this.$allowedToPushDropdown, $dropdown: this.$allowedToPushDropdown,
onSelect: this.onSelectOption.bind(this), onSelect: this.onSelectOption.bind(this),
onHide: this.onDropdownHide.bind(this) onHide: this.onDropdownHide.bind(this),
}); });
} }
onSelectOption(item, $el, dropdownInstance) { onSelectOption() {
this.hasChanges = true; this.hasChanges = true;
} }
onDropdownHide() { onDropdownHide() {
if (!this.hasChanges) return; if (!this.hasChanges) {
return;
}
this.hasChanges = true; this.hasChanges = true;
this.updatePermissions(); this.updatePermissions();
} }
updatePermissions() { updatePermissions() {
const formData = {}; const formData = Object.keys(ACCESS_LEVELS).reduce((acc, level) => {
/* eslint-disable no-param-reassign */
const accessLevelName = ACCESS_LEVELS[level];
const inputData = this[`${accessLevelName}_dropdown`].getInputData(accessLevelName);
acc[`${accessLevelName}_attributes`] = inputData;
for (const ACCESS_LEVEL in ACCESS_LEVELS) { return acc;
const accessLevelName = ACCESS_LEVELS[ACCESS_LEVEL]; }, {});
formData[`${accessLevelName}_attributes`] = this[`${accessLevelName}_dropdown`].getInputData(accessLevelName);
}
return $.ajax({ return $.ajax({
type: 'POST', type: 'POST',
...@@ -76,22 +67,21 @@ ...@@ -76,22 +67,21 @@
dataType: 'json', dataType: 'json',
data: { data: {
_method: 'PATCH', _method: 'PATCH',
protected_branch: formData protected_branch: formData,
}, },
success: (response) => { success: (response) => {
this.hasChanges = false; this.hasChanges = false;
for (const ACCESS_LEVEL in ACCESS_LEVELS) { Object.keys(ACCESS_LEVELS).forEach((level) => {
const accessLevelName = ACCESS_LEVELS[ACCESS_LEVEL]; const accessLevelName = ACCESS_LEVELS[level];
// The data coming from server will be the new persisted *state* for each dropdown // The data coming from server will be the new persisted *state* for each dropdown
this.setSelectedItemsToDropdown(response[accessLevelName], `${accessLevelName}_dropdown`); this.setSelectedItemsToDropdown(response[accessLevelName], `${accessLevelName}_dropdown`);
} });
}, },
error() { error() {
$.scrollTo(0); new Flash('Failed to update branch!', null, $('.js-protected-branches-list'));
new Flash('Failed to update branch!'); },
}
}).always(() => { }).always(() => {
this.$allowedToMergeDropdown.enable(); this.$allowedToMergeDropdown.enable();
this.$allowedToPushDropdown.enable(); this.$allowedToPushDropdown.enable();
...@@ -99,47 +89,39 @@ ...@@ -99,47 +89,39 @@
} }
setSelectedItemsToDropdown(items = [], dropdownName) { setSelectedItemsToDropdown(items = [], dropdownName) {
const itemsToAdd = []; const itemsToAdd = items.map((currentItem) => {
for (let i = 0; i < items.length; i += 1) {
let itemToAdd;
const currentItem = items[i];
if (currentItem.user_id) { if (currentItem.user_id) {
// Do this only for users for now // Do this only for users for now
// get the current data for selected items // get the current data for selected items
const selectedItems = this[dropdownName].getSelectedItems(); const selectedItems = this[dropdownName].getSelectedItems();
const currentSelectedItem = _.findWhere(selectedItems, { user_id: currentItem.user_id }); const currentSelectedItem = _.findWhere(selectedItems, { user_id: currentItem.user_id });
itemToAdd = { return {
id: currentItem.id, id: currentItem.id,
user_id: currentItem.user_id, user_id: currentItem.user_id,
type: LEVEL_TYPES.USER, type: LEVEL_TYPES.USER,
persisted: true, persisted: true,
name: currentSelectedItem.name, name: currentSelectedItem.name,
username: currentSelectedItem.username, username: currentSelectedItem.username,
avatar_url: currentSelectedItem.avatar_url avatar_url: currentSelectedItem.avatar_url,
}; };
} else if (currentItem.group_id) { } else if (currentItem.group_id) {
itemToAdd = { return {
id: currentItem.id, id: currentItem.id,
group_id: currentItem.group_id, group_id: currentItem.group_id,
type: LEVEL_TYPES.GROUP, type: LEVEL_TYPES.GROUP,
persisted: true persisted: true,
}; };
} else { }
itemToAdd = {
return {
id: currentItem.id, id: currentItem.id,
access_level: currentItem.access_level, access_level: currentItem.access_level,
type: LEVEL_TYPES.ROLE, type: LEVEL_TYPES.ROLE,
persisted: true persisted: true,
}; };
} });
itemsToAdd.push(itemToAdd);
}
this[dropdownName].setSelectedItems(itemsToAdd); this[dropdownName].setSelectedItems(itemsToAdd);
} }
}; }
})(window);
/* eslint-disable arrow-parens, no-param-reassign, no-new, comma-dangle */ /* eslint-disable no-new */
(global => { import ProtectedBranchEdit from './protected_branch_edit';
global.gl = global.gl || {};
gl.ProtectedBranchEditList = class { export default class ProtectedBranchEditList {
constructor() { constructor() {
this.$wrap = $('.protected-branches-list'); this.$wrap = $('.protected-branches-list');
this.initEditForm();
}
initEditForm() {
// Build edit forms // Build edit forms
this.$wrap.find('.js-protected-branch-edit-form').each((i, el) => { this.$wrap.find('.js-protected-branch-edit-form').each((i, el) => {
new gl.ProtectedBranchEdit({ new ProtectedBranchEdit({
$wrap: $(el) $wrap: $(el),
}); });
}); });
} }
}; }
})(window);
...@@ -8,4 +8,10 @@ export const LEVEL_TYPES = { ...@@ -8,4 +8,10 @@ export const LEVEL_TYPES = {
GROUP: 'group', GROUP: 'group',
}; };
export const LEVEL_ID_PROP = {
ROLE: 'access_level',
USER: 'user_id',
GROUP: 'group_id',
};
export const ACCESS_LEVEL_NONE = 0; export const ACCESS_LEVEL_NONE = 0;
/* eslint-disable no-underscore-dangle, class-methods-use-this */ /* eslint-disable no-underscore-dangle, class-methods-use-this */
/* global Flash */ /* global Flash */
import { ACCESS_LEVELS, LEVEL_TYPES, ACCESS_LEVEL_NONE } from './constants'; import { LEVEL_TYPES, LEVEL_ID_PROP, ACCESS_LEVEL_NONE } from './constants';
export default class ProtectedTagAccessDropdown { export default class ProtectedTagAccessDropdown {
constructor(options) { constructor(options) {
...@@ -11,7 +11,6 @@ export default class ProtectedTagAccessDropdown { ...@@ -11,7 +11,6 @@ export default class ProtectedTagAccessDropdown {
accessLevelsData, accessLevelsData,
} = options; } = options;
this.options = options; this.options = options;
this.isAllowedToCreateDropdown = false;
this.groups = []; this.groups = [];
this.accessLevel = accessLevel; this.accessLevel = accessLevel;
this.accessLevelsData = accessLevelsData.roles; this.accessLevelsData = accessLevelsData.roles;
...@@ -25,10 +24,7 @@ export default class ProtectedTagAccessDropdown { ...@@ -25,10 +24,7 @@ export default class ProtectedTagAccessDropdown {
this.setSelectedItems([]); this.setSelectedItems([]);
this.persistPreselectedItems(); this.persistPreselectedItems();
if (ACCESS_LEVELS.CREATE === this.accessLevel) {
this.isAllowedToCreateDropdown = true;
this.noOneObj = this.accessLevelsData.find(level => level.id === ACCESS_LEVEL_NONE); this.noOneObj = this.accessLevelsData.find(level => level.id === ACCESS_LEVEL_NONE);
}
this.initDropdown(); this.initDropdown();
} }
...@@ -56,7 +52,6 @@ export default class ProtectedTagAccessDropdown { ...@@ -56,7 +52,6 @@ export default class ProtectedTagAccessDropdown {
e.preventDefault(); e.preventDefault();
if ($el.is('.is-active')) { if ($el.is('.is-active')) {
if (self.isAllowedToCreateDropdown) {
if (item.id === self.noOneObj.id) { if (item.id === self.noOneObj.id) {
self.accessLevelsData.forEach((level) => { self.accessLevelsData.forEach((level) => {
if (level.id !== item.id) { if (level.id !== item.id) {
...@@ -74,7 +69,6 @@ export default class ProtectedTagAccessDropdown { ...@@ -74,7 +69,6 @@ export default class ProtectedTagAccessDropdown {
} }
$el.addClass(`is-active item-${item.type}`); $el.addClass(`is-active item-${item.type}`);
}
self.addSelectedItem(item); self.addSelectedItem(item);
} else { } else {
...@@ -151,8 +145,24 @@ export default class ProtectedTagAccessDropdown { ...@@ -151,8 +145,24 @@ export default class ProtectedTagAccessDropdown {
let index = -1; let index = -1;
const selectedItems = this.getAllSelectedItems(); const selectedItems = this.getAllSelectedItems();
// Compare IDs based on selectedItem.type
selectedItems.forEach((item, i) => { selectedItems.forEach((item, i) => {
if (selectedItem.id === item.access_level) { let comparator;
switch (selectedItem.type) {
case LEVEL_TYPES.ROLE:
comparator = LEVEL_ID_PROP.ROLE;
break;
case LEVEL_TYPES.GROUP:
comparator = LEVEL_ID_PROP.GROUP;
break;
case LEVEL_TYPES.USER:
comparator = LEVEL_ID_PROP.USER;
break;
default:
break;
}
if (selectedItem.id === item[comparator]) {
index = i; index = i;
} }
}); });
......
...@@ -8,7 +8,7 @@ export default class ProtectedTagCreate { ...@@ -8,7 +8,7 @@ export default class ProtectedTagCreate {
constructor() { constructor() {
this.$form = $('.js-new-protected-tag'); this.$form = $('.js-new-protected-tag');
this.buildDropdowns(); this.buildDropdowns();
this.$branchTag = this.$form.find('input[name="protected_tag[name]"]'); this.$tagInput = this.$form.find('input[name="protected_tag[name]"]');
this.bindEvents(); this.bindEvents();
} }
......
...@@ -110,7 +110,7 @@ describe 'Branches' do ...@@ -110,7 +110,7 @@ describe 'Branches' do
project.add_user(user, :developer) project.add_user(user, :developer)
end end
it 'does not allow devleoper to removes protected branch', js: true do it 'does not allow devleoper to remove protected branch', js: true do
visit project_branches_path(project) visit project_branches_path(project)
fill_in 'branch-search', with: 'fix' fill_in 'branch-search', with: 'fix'
......
...@@ -2,7 +2,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -2,7 +2,7 @@ shared_examples "protected branches > access control > EE" do
[['merge', ProtectedBranch::MergeAccessLevel], ['push', ProtectedBranch::PushAccessLevel]].each do |git_operation, access_level_class| [['merge', ProtectedBranch::MergeAccessLevel], ['push', ProtectedBranch::PushAccessLevel]].each do |git_operation, access_level_class|
# Need to set a default for the `git_operation` access level that _isn't_ being tested # Need to set a default for the `git_operation` access level that _isn't_ being tested
other_git_operation = git_operation == 'merge' ? 'push' : 'merge' other_git_operation = git_operation == 'merge' ? 'push' : 'merge'
roles = git_operation == 'merge' ? access_level_class.human_access_levels : access_level_class.human_access_levels.except(0) roles_except_noone = access_level_class.human_access_levels.except(0)
let(:users) { create_list(:user, 5) } let(:users) { create_list(:user, 5) }
let(:groups) { create_list(:group, 5) } let(:groups) { create_list(:group, 5) }
...@@ -22,7 +22,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -22,7 +22,7 @@ shared_examples "protected branches > access control > EE" do
set_protected_branch_name('master') set_protected_branch_name('master')
set_allowed_to(git_operation, users.map(&:name)) set_allowed_to(git_operation, users.map(&:name))
set_allowed_to(git_operation, groups.map(&:name)) set_allowed_to(git_operation, groups.map(&:name))
set_allowed_to(git_operation, roles.values) roles_except_noone.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name) }
set_allowed_to(other_git_operation) set_allowed_to(other_git_operation)
click_on "Protect" click_on "Protect"
...@@ -31,7 +31,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -31,7 +31,7 @@ shared_examples "protected branches > access control > EE" do
expect(ProtectedBranch.count).to eq(1) expect(ProtectedBranch.count).to eq(1)
access_levels = last_access_levels(git_operation) access_levels = last_access_levels(git_operation)
roles.each { |(access_type_id, _)| expect(access_levels.map(&:access_level)).to include(access_type_id) } roles_except_noone.each { |(access_type_id, _)| expect(access_levels.map(&:access_level)).to include(access_type_id) }
users.each { |user| expect(access_levels.map(&:user_id)).to include(user.id) } users.each { |user| expect(access_levels.map(&:user_id)).to include(user.id) }
groups.each { |group| expect(access_levels.map(&:group_id)).to include(group.id) } groups.each { |group| expect(access_levels.map(&:group_id)).to include(group.id) }
end end
...@@ -46,14 +46,14 @@ shared_examples "protected branches > access control > EE" do ...@@ -46,14 +46,14 @@ shared_examples "protected branches > access control > EE" do
set_allowed_to(git_operation, users.map(&:name), form: ".js-protected-branch-edit-form") set_allowed_to(git_operation, users.map(&:name), form: ".js-protected-branch-edit-form")
set_allowed_to(git_operation, groups.map(&:name), form: ".js-protected-branch-edit-form") set_allowed_to(git_operation, groups.map(&:name), form: ".js-protected-branch-edit-form")
set_allowed_to(git_operation, roles.values, form: ".js-protected-branch-edit-form") roles_except_noone.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name, form: ".js-protected-branch-edit-form") }
wait_for_requests wait_for_requests
expect(ProtectedBranch.count).to eq(1) expect(ProtectedBranch.count).to eq(1)
access_levels = last_access_levels(git_operation) access_levels = last_access_levels(git_operation)
roles.each { |(access_type_id, _)| expect(access_levels.map(&:access_level)).to include(access_type_id) } roles_except_noone.each { |(access_type_id, _)| expect(access_levels.map(&:access_level)).to include(access_type_id) }
users.each { |user| expect(access_levels.map(&:user_id)).to include(user.id) } users.each { |user| expect(access_levels.map(&:user_id)).to include(user.id) }
groups.each { |group| expect(access_levels.map(&:group_id)).to include(group.id) } groups.each { |group| expect(access_levels.map(&:group_id)).to include(group.id) }
end end
...@@ -63,7 +63,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -63,7 +63,7 @@ shared_examples "protected branches > access control > EE" do
set_protected_branch_name('master') set_protected_branch_name('master')
users.each { |user| set_allowed_to(git_operation, user.name) } users.each { |user| set_allowed_to(git_operation, user.name) }
roles.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name) } roles_except_noone.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name) }
groups.each { |group| set_allowed_to(git_operation, group.name) } groups.each { |group| set_allowed_to(git_operation, group.name) }
set_allowed_to(other_git_operation) set_allowed_to(other_git_operation)
...@@ -71,7 +71,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -71,7 +71,7 @@ shared_examples "protected branches > access control > EE" do
users.each { |user| set_allowed_to(git_operation, user.name, form: ".js-protected-branch-edit-form") } users.each { |user| set_allowed_to(git_operation, user.name, form: ".js-protected-branch-edit-form") }
groups.each { |group| set_allowed_to(git_operation, group.name, form: ".js-protected-branch-edit-form") } groups.each { |group| set_allowed_to(git_operation, group.name, form: ".js-protected-branch-edit-form") }
roles.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name, form: ".js-protected-branch-edit-form") } roles_except_noone.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name, form: ".js-protected-branch-edit-form") }
wait_for_requests wait_for_requests
...@@ -89,7 +89,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -89,7 +89,7 @@ shared_examples "protected branches > access control > EE" do
# Create Protected Branch # Create Protected Branch
set_protected_branch_name('master') set_protected_branch_name('master')
set_allowed_to(git_operation, roles.values) roles_except_noone.each { |(_, access_type_name)| set_allowed_to(git_operation, access_type_name) }
set_allowed_to(other_git_operation) set_allowed_to(other_git_operation)
click_on 'Protect' click_on 'Protect'
...@@ -119,7 +119,7 @@ shared_examples "protected branches > access control > EE" do ...@@ -119,7 +119,7 @@ shared_examples "protected branches > access control > EE" do
expect(ProtectedBranch.count).to eq(1) expect(ProtectedBranch.count).to eq(1)
access_levels = last_access_levels(git_operation) access_levels = last_access_levels(git_operation)
roles.each { |(access_type_id, _)| expect(access_levels.map(&:access_level)).to include(access_type_id) } roles_except_noone.each { |(access_type_id, _)| expect(access_levels.map(&:access_level)).to include(access_type_id) }
expect(access_levels.map(&:user_id)).to include(users.last.id) expect(access_levels.map(&:user_id)).to include(users.last.id)
end end
end end
......
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