Commit 49bdbf2b authored by kushalpandya's avatar kushalpandya

Changes as per review feedback

parent ebc5997c
/* eslint-disable no-param-reassign, 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 './'; import { ACCESS_LEVELS, LEVEL_TYPES, ACCESS_LEVEL_NONE } from './constants';
export default class ProtectedTagAccessDropdown { export default class ProtectedTagAccessDropdown {
constructor(options) { constructor(options) {
...@@ -33,6 +33,7 @@ export default class ProtectedTagAccessDropdown { ...@@ -33,6 +33,7 @@ export default class ProtectedTagAccessDropdown {
} }
initDropdown() { initDropdown() {
const self = this;
const { onSelect, onHide } = this.options; const { onSelect, onHide } = this.options;
this.$dropdown.glDropdown({ this.$dropdown.glDropdown({
data: this.getData.bind(this), data: this.getData.bind(this),
...@@ -54,29 +55,29 @@ export default class ProtectedTagAccessDropdown { ...@@ -54,29 +55,29 @@ export default class ProtectedTagAccessDropdown {
e.preventDefault(); e.preventDefault();
if ($el.is('.is-active')) { if ($el.is('.is-active')) {
if (this.isAllowedToCreateDropdown) { if (self.isAllowedToCreateDropdown) {
if (item.id === this.noOneObj.id) { if (item.id === self.noOneObj.id) {
this.accessLevelsData.forEach((level) => { self.accessLevelsData.forEach((level) => {
if (level.id !== item.id) { if (level.id !== item.id) {
this.removeSelectedItem(level); self.removeSelectedItem(level);
} }
}); });
this.$wrap.find(`.item-${item.type}`).removeClass('is-active'); self.$wrap.find(`.item-${item.type}`).removeClass('is-active');
} else { } else {
const $noOne = this.$wrap.find(`.is-active-item-${item.type}:contains('No one')`); const $noOne = self.$wrap.find(`.is-active.item-${item.type}[data-role-name="No one"]`);
if ($noOne.length) { if ($noOne.length) {
$noOne.removeClass('is-active'); $noOne.removeClass('is-active');
this.removeSelectedItem(this.noOneObj); self.removeSelectedItem(self.noOneObj);
} }
} }
$el.addClass(`is-active item-${item.type}`); $el.addClass(`is-active item-${item.type}`);
} }
this.addSelectedItem(item); self.addSelectedItem(item);
} else { } else {
this.removeSelectedItem(item); self.removeSelectedItem(item);
} }
if (onSelect) { if (onSelect) {
...@@ -93,15 +94,17 @@ export default class ProtectedTagAccessDropdown { ...@@ -93,15 +94,17 @@ export default class ProtectedTagAccessDropdown {
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() {
...@@ -113,10 +116,9 @@ export default class ProtectedTagAccessDropdown { ...@@ -113,10 +116,9 @@ export default class ProtectedTagAccessDropdown {
} }
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') {
...@@ -135,7 +137,7 @@ export default class ProtectedTagAccessDropdown { ...@@ -135,7 +137,7 @@ export default class ProtectedTagAccessDropdown {
obj.group_id = item.group_id; obj.group_id = item.group_id;
} }
accessLevels.push(obj); return obj;
}); });
return accessLevels; return accessLevels;
...@@ -205,7 +207,8 @@ export default class ProtectedTagAccessDropdown { ...@@ -205,7 +207,8 @@ export default class ProtectedTagAccessDropdown {
index = i; index = i;
} }
return index < 0; // Break once we have index set // 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
...@@ -228,15 +231,15 @@ export default class ProtectedTagAccessDropdown { ...@@ -228,15 +231,15 @@ export default class ProtectedTagAccessDropdown {
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) {
Object.keys(LEVEL_TYPES).forEach((levelType) => { label = Object.keys(LEVEL_TYPES).map((levelType) => {
const typeName = LEVEL_TYPES[levelType]; 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);
...@@ -248,23 +251,26 @@ export default class ProtectedTagAccessDropdown { ...@@ -248,23 +251,26 @@ export default class ProtectedTagAccessDropdown {
} }
getData(query, callback) { getData(query, callback) {
this.getUsers(query).done((usersResponse) => { this.getUsers(query)
if (this.groups.length) { .done((usersResponse) => {
callback(this.consolidateData(usersResponse, this.groups)); if (this.groups.length) {
} else { callback(this.consolidateData(usersResponse, this.groups));
this.getGroups(query).done((groupsResponse) => { } else {
// Cache groups to avoid multiple requests this.getGroups(query)
this.groups = groupsResponse; .done((groupsResponse) => {
callback(this.consolidateData(usersResponse, groupsResponse)); // Cache groups to avoid multiple requests
}).error(() => new Flash('Failed to load groups.')); this.groups = groupsResponse;
} callback(this.consolidateData(usersResponse, groupsResponse));
}).error(() => new Flash('Failed to load users.')); })
.error(() => new Flash('Failed to load groups.'));
}
})
.error(() => new Flash('Failed to load users.'));
} }
consolidateData(usersResponse, groupsResponse) { consolidateData(usersResponse, groupsResponse) {
let consolidatedData = []; let consolidatedData = [];
const map = []; const map = [];
const users = [];
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
...@@ -284,15 +290,18 @@ export default class ProtectedTagAccessDropdown { ...@@ -284,15 +290,18 @@ export default class ProtectedTagAccessDropdown {
/* /*
* Build groups * Build groups
*/ */
const 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
*/ */
const 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;
}); });
...@@ -300,31 +309,32 @@ export default class ProtectedTagAccessDropdown { ...@@ -300,31 +309,32 @@ export default class ProtectedTagAccessDropdown {
/* /*
* Build users * Build users
*/ */
selectedItems.forEach((item) => { const users = selectedItems.map((item) => {
if (item.type !== LEVEL_TYPES.USER) { let user = null;
return; if (item.type === LEVEL_TYPES.USER) {
user = {
id: item.user_id,
name: item.name,
username: item.username,
avatar_url: item.avatar_url,
type: LEVEL_TYPES.USER,
};
// Save identifiers for easy-checking more later
map.push(LEVEL_TYPES.USER + item.user_id);
} }
// Collect selected users return user;
users.push({ }).filter(item => item !== null);
id: item.user_id,
name: item.name,
username: item.username,
avatar_url: item.avatar_url,
type: LEVEL_TYPES.USER,
});
// Save identifiers for easy-checking more later
map.push(LEVEL_TYPES.USER + item.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
usersResponse.forEach((response) => { usersResponse.forEach((response) => {
// Add is it has not been added // Add is it has not been added
if (map.indexOf(LEVEL_TYPES.USER + response.id) === -1) { if (map.indexOf(LEVEL_TYPES.USER + response.id) === -1) {
response.type = LEVEL_TYPES.USER; const user = Object.assign({}, response);
users.push(response); user.type = LEVEL_TYPES.USER;
users.push(user);
} }
}); });
...@@ -350,7 +360,7 @@ export default class ProtectedTagAccessDropdown { ...@@ -350,7 +360,7 @@ export default class ProtectedTagAccessDropdown {
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,
...@@ -364,18 +374,19 @@ export default class ProtectedTagAccessDropdown { ...@@ -364,18 +374,19 @@ export default class ProtectedTagAccessDropdown {
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) {
...@@ -419,19 +430,42 @@ export default class ProtectedTagAccessDropdown { ...@@ -419,19 +430,42 @@ export default class ProtectedTagAccessDropdown {
} }
userRowHtml(user, isActive) { userRowHtml(user, isActive) {
const avatarHtml = `<img src='${user.avatar_url}' class='avatar avatar-inline' width='30'>`; const isActiveClass = isActive ? '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 ? '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 ? 'isActive' : '';
return `
<li>
<a href='#' class='${isActiveClass}' item-${role.type}' data-role-name="${role.text}">
${role.text}
</a>
</li>
`;
} }
} }
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