Commit 8a6822ba authored by Stan Hu's avatar Stan Hu

Merge branch '228675-separate-filtering-users-from-sorting-users-setup-app-options' into 'master'

Setup Vuex state needed for group members filter bar

See merge request gitlab-org/gitlab!48403
parents 6c4f3e6b c7eb80e4
...@@ -5,7 +5,16 @@ import { parseDataAttributes } from 'ee_else_ce/groups/members/utils'; ...@@ -5,7 +5,16 @@ import { parseDataAttributes } from 'ee_else_ce/groups/members/utils';
import App from './components/app.vue'; import App from './components/app.vue';
import membersStore from '~/members/store'; import membersStore from '~/members/store';
export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatter) => { export const initGroupMembersApp = (
el,
{
tableFields = [],
tableAttrs = {},
tableSortableFields = [],
requestFormatter = () => {},
filteredSearchBar = { show: false },
},
) => {
if (!el) { if (!el) {
return () => {}; return () => {};
} }
...@@ -19,7 +28,9 @@ export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatte ...@@ -19,7 +28,9 @@ export const initGroupMembersApp = (el, tableFields, tableAttrs, requestFormatte
currentUserId: gon.current_user_id || null, currentUserId: gon.current_user_id || null,
tableFields, tableFields,
tableAttrs, tableAttrs,
tableSortableFields,
requestFormatter, requestFormatter,
filteredSearchBar,
}), }),
); );
......
import { isUndefined } from 'lodash'; import { isUndefined } from 'lodash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
import { import {
GROUP_MEMBER_BASE_PROPERTY_NAME, GROUP_MEMBER_BASE_PROPERTY_NAME,
GROUP_MEMBER_ACCESS_LEVEL_PROPERTY_NAME, GROUP_MEMBER_ACCESS_LEVEL_PROPERTY_NAME,
...@@ -8,12 +8,13 @@ import { ...@@ -8,12 +8,13 @@ import {
} from './constants'; } from './constants';
export const parseDataAttributes = el => { export const parseDataAttributes = el => {
const { members, groupId, memberPath } = el.dataset; const { members, groupId, memberPath, canManageMembers } = el.dataset;
return { return {
members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }), members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }),
sourceId: parseInt(groupId, 10), sourceId: parseInt(groupId, 10),
memberPath, memberPath,
canManageMembers: parseBoolean(canManageMembers),
}; };
}; };
......
...@@ -2,18 +2,24 @@ export default ({ ...@@ -2,18 +2,24 @@ export default ({
members, members,
sourceId, sourceId,
currentUserId, currentUserId,
canManageMembers,
tableFields, tableFields,
tableAttrs, tableAttrs,
tableSortableFields,
memberPath, memberPath,
requestFormatter, requestFormatter,
filteredSearchBar,
}) => ({ }) => ({
members, members,
sourceId, sourceId,
currentUserId, currentUserId,
canManageMembers,
tableFields, tableFields,
tableAttrs, tableAttrs,
tableSortableFields,
memberPath, memberPath,
requestFormatter, requestFormatter,
filteredSearchBar,
showError: false, showError: false,
errorMessage: '', errorMessage: '',
removeGroupLinkModalVisible: false, removeGroupLinkModalVisible: false,
......
...@@ -6,6 +6,7 @@ import groupsSelect from '~/groups_select'; ...@@ -6,6 +6,7 @@ import groupsSelect from '~/groups_select';
import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue'; import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
import { initGroupMembersApp } from '~/groups/members'; import { initGroupMembersApp } from '~/groups/members';
import { memberRequestFormatter, groupLinkRequestFormatter } from '~/groups/members/utils'; import { memberRequestFormatter, groupLinkRequestFormatter } from '~/groups/members/utils';
import { __ } from '~/locale';
function mountRemoveMemberModal() { function mountRemoveMemberModal() {
const el = document.querySelector('.js-remove-member-modal'); const el = document.querySelector('.js-remove-member-modal');
...@@ -22,30 +23,43 @@ function mountRemoveMemberModal() { ...@@ -22,30 +23,43 @@ function mountRemoveMemberModal() {
} }
const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions']; const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions'];
initGroupMembersApp(
document.querySelector('.js-group-members-list'), initGroupMembersApp(document.querySelector('.js-group-members-list'), {
SHARED_FIELDS.concat(['source', 'granted']), tableFields: SHARED_FIELDS.concat(['source', 'granted']),
{ tr: { 'data-qa-selector': 'member_row' } }, tableAttrs: { tr: { 'data-qa-selector': 'member_row' } },
memberRequestFormatter, tableSortableFields: ['account', 'granted', 'maxRole', 'lastSignIn'],
); requestFormatter: memberRequestFormatter,
initGroupMembersApp( filteredSearchBar: {
document.querySelector('.js-group-linked-list'), show: true,
SHARED_FIELDS.concat('granted'), tokens: ['two_factor', 'with_inherited_permissions'],
{ table: { 'data-qa-selector': 'groups_list' }, tr: { 'data-qa-selector': 'group_row' } }, searchParam: 'search',
groupLinkRequestFormatter, placeholder: __('Members|Filter members'),
); recentSearchesStorageKey: 'group_members',
initGroupMembersApp( },
document.querySelector('.js-group-invited-members-list'), });
SHARED_FIELDS.concat('invited'), initGroupMembersApp(document.querySelector('.js-group-linked-list'), {
{}, tableFields: SHARED_FIELDS.concat('granted'),
memberRequestFormatter, tableAttrs: {
); table: { 'data-qa-selector': 'groups_list' },
initGroupMembersApp( tr: { 'data-qa-selector': 'group_row' },
document.querySelector('.js-group-access-requests-list'), },
SHARED_FIELDS.concat('requested'), requestFormatter: groupLinkRequestFormatter,
{}, });
memberRequestFormatter, initGroupMembersApp(document.querySelector('.js-group-invited-members-list'), {
); tableFields: SHARED_FIELDS.concat('invited'),
requestFormatter: memberRequestFormatter,
filteredSearchBar: {
show: true,
tokens: [],
searchParam: 'search_invited',
placeholder: __('Members|Search invited'),
recentSearchesStorageKey: 'group_invited_members',
},
});
initGroupMembersApp(document.querySelector('.js-group-access-requests-list'), {
tableFields: SHARED_FIELDS.concat('requested'),
requestFormatter: memberRequestFormatter,
});
groupsSelect(); groupsSelect();
memberExpirationDate(); memberExpirationDate();
......
...@@ -26,7 +26,8 @@ module Groups::GroupMembersHelper ...@@ -26,7 +26,8 @@ module Groups::GroupMembersHelper
{ {
members: members_data_json(group, members), members: members_data_json(group, members),
member_path: group_group_member_path(group, ':id'), member_path: group_group_member_path(group, ':id'),
group_id: group.id group_id: group.id,
can_manage_members: can?(current_user, :admin_group_member, group).to_s
} }
end end
......
...@@ -6,7 +6,7 @@ describe('initGroupMembersApp', () => { ...@@ -6,7 +6,7 @@ describe('initGroupMembersApp', () => {
let vm; let vm;
const createVm = () => { const createVm = () => {
vm = initGroupMembersApp(el, ['account'], {}, () => ({})); vm = initGroupMembersApp(el, {});
}; };
beforeEach(() => { beforeEach(() => {
......
...@@ -9,6 +9,7 @@ describe('group member utils', () => { ...@@ -9,6 +9,7 @@ describe('group member utils', () => {
el = document.createElement('div'); el = document.createElement('div');
el.setAttribute('data-members', membersJsonString); el.setAttribute('data-members', membersJsonString);
el.setAttribute('data-group-id', '234'); el.setAttribute('data-group-id', '234');
el.setAttribute('data-can-manage-members', 'true');
el.setAttribute('data-ldap-override-path', '/groups/ldap-group/-/group_members/:id/override'); el.setAttribute('data-ldap-override-path', '/groups/ldap-group/-/group_members/:id/override');
}); });
...@@ -20,6 +21,7 @@ describe('group member utils', () => { ...@@ -20,6 +21,7 @@ describe('group member utils', () => {
expect(parseDataAttributes(el)).toEqual({ expect(parseDataAttributes(el)).toEqual({
members: membersParsed, members: membersParsed,
sourceId: 234, sourceId: 234,
canManageMembers: true,
ldapOverridePath: '/groups/ldap-group/-/group_members/:id/override', ldapOverridePath: '/groups/ldap-group/-/group_members/:id/override',
}); });
}); });
......
...@@ -6,6 +6,11 @@ RSpec.describe Groups::GroupMembersHelper do ...@@ -6,6 +6,11 @@ RSpec.describe Groups::GroupMembersHelper do
include MembersPresentation include MembersPresentation
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:current_user) { create(:user) }
before do
allow(helper).to receive(:current_user).and_return(current_user)
end
describe '.group_member_select_options' do describe '.group_member_select_options' do
before do before do
...@@ -18,14 +23,12 @@ RSpec.describe Groups::GroupMembersHelper do ...@@ -18,14 +23,12 @@ RSpec.describe Groups::GroupMembersHelper do
end end
describe '#members_data' do describe '#members_data' do
let(:current_user) { create(:user) }
let(:group_member) { create(:group_member, group: group, created_by: current_user) } let(:group_member) { create(:group_member, group: group, created_by: current_user) }
subject { helper.send('members_data', group, present_members([group_member])) } subject { helper.send('members_data', group, present_members([group_member])) }
before do before do
allow(helper).to receive(:can?).with(current_user, :owner_access, group).and_return(true) allow(helper).to receive(:can?).with(current_user, :owner_access, group).and_return(true)
allow(helper).to receive(:current_user).and_return(current_user)
end end
it 'adds `using_license` property to hash' do it 'adds `using_license` property to hash' do
...@@ -51,6 +54,7 @@ RSpec.describe Groups::GroupMembersHelper do ...@@ -51,6 +54,7 @@ RSpec.describe Groups::GroupMembersHelper do
before do before do
allow(helper).to receive(:override_group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id/override') allow(helper).to receive(:override_group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id/override')
allow(helper).to receive(:group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id') allow(helper).to receive(:group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id')
allow(helper).to receive(:can?).with(current_user, :admin_group_member, group).and_return(true)
end end
it 'adds `ldap_override_path` to returned hash' do it 'adds `ldap_override_path` to returned hash' do
......
...@@ -16848,6 +16848,9 @@ msgstr "" ...@@ -16848,6 +16848,9 @@ msgstr ""
msgid "Members|Expired" msgid "Members|Expired"
msgstr "" msgstr ""
msgid "Members|Filter members"
msgstr ""
msgid "Members|LDAP override enabled." msgid "Members|LDAP override enabled."
msgstr "" msgstr ""
...@@ -16872,6 +16875,9 @@ msgstr "" ...@@ -16872,6 +16875,9 @@ msgstr ""
msgid "Members|Role updated successfully." msgid "Members|Role updated successfully."
msgstr "" msgstr ""
msgid "Members|Search invited"
msgstr ""
msgid "Members|in %{time}" msgid "Members|in %{time}"
msgstr "" msgstr ""
......
...@@ -9,12 +9,13 @@ describe('initGroupMembersApp', () => { ...@@ -9,12 +9,13 @@ describe('initGroupMembersApp', () => {
let wrapper; let wrapper;
const setup = () => { const setup = () => {
vm = initGroupMembersApp( vm = initGroupMembersApp(el, {
el, tableFields: ['account'],
['account'], tableAttrs: { table: { 'data-qa-selector': 'members_list' } },
{ table: { 'data-qa-selector': 'members_list' } }, tableSortableFields: ['account'],
() => ({}), requestFormatter: () => ({}),
); filteredSearchBar: { show: false },
});
wrapper = createWrapper(vm); wrapper = createWrapper(vm);
}; };
...@@ -22,6 +23,7 @@ describe('initGroupMembersApp', () => { ...@@ -22,6 +23,7 @@ describe('initGroupMembersApp', () => {
el = document.createElement('div'); el = document.createElement('div');
el.setAttribute('data-members', membersJsonString); el.setAttribute('data-members', membersJsonString);
el.setAttribute('data-group-id', '234'); el.setAttribute('data-group-id', '234');
el.setAttribute('data-can-manage-members', 'true');
el.setAttribute('data-member-path', '/groups/foo-bar/-/group_members/:id'); el.setAttribute('data-member-path', '/groups/foo-bar/-/group_members/:id');
window.gon = { current_user_id: 123 }; window.gon = { current_user_id: 123 };
...@@ -61,6 +63,12 @@ describe('initGroupMembersApp', () => { ...@@ -61,6 +63,12 @@ describe('initGroupMembersApp', () => {
expect(vm.$store.state.sourceId).toBe(234); expect(vm.$store.state.sourceId).toBe(234);
}); });
it('parses and sets `data-can-manage-members` as `canManageMembers` in Vuex store', () => {
setup();
expect(vm.$store.state.canManageMembers).toBe(true);
});
it('parses and sets `members` in Vuex store', () => { it('parses and sets `members` in Vuex store', () => {
setup(); setup();
...@@ -79,12 +87,24 @@ describe('initGroupMembersApp', () => { ...@@ -79,12 +87,24 @@ describe('initGroupMembersApp', () => {
expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } }); expect(vm.$store.state.tableAttrs).toEqual({ table: { 'data-qa-selector': 'members_list' } });
}); });
it('sets `tableSortableFields` in Vuex store', () => {
setup();
expect(vm.$store.state.tableSortableFields).toEqual(['account']);
});
it('sets `requestFormatter` in Vuex store', () => { it('sets `requestFormatter` in Vuex store', () => {
setup(); setup();
expect(vm.$store.state.requestFormatter()).toEqual({}); expect(vm.$store.state.requestFormatter()).toEqual({});
}); });
it('sets `filteredSearchBar` in Vuex store', () => {
setup();
expect(vm.$store.state.filteredSearchBar).toEqual({ show: false });
});
it('sets `memberPath` in Vuex store', () => { it('sets `memberPath` in Vuex store', () => {
setup(); setup();
......
...@@ -13,6 +13,7 @@ describe('group member utils', () => { ...@@ -13,6 +13,7 @@ describe('group member utils', () => {
el = document.createElement('div'); el = document.createElement('div');
el.setAttribute('data-members', membersJsonString); el.setAttribute('data-members', membersJsonString);
el.setAttribute('data-group-id', '234'); el.setAttribute('data-group-id', '234');
el.setAttribute('data-can-manage-members', 'true');
}); });
afterEach(() => { afterEach(() => {
...@@ -23,6 +24,7 @@ describe('group member utils', () => { ...@@ -23,6 +24,7 @@ describe('group member utils', () => {
expect(parseDataAttributes(el)).toEqual({ expect(parseDataAttributes(el)).toEqual({
members: membersParsed, members: membersParsed,
sourceId: 234, sourceId: 234,
canManageMembers: true,
}); });
}); });
}); });
......
...@@ -74,13 +74,15 @@ RSpec.describe Groups::GroupMembersHelper do ...@@ -74,13 +74,15 @@ RSpec.describe Groups::GroupMembersHelper do
before do before do
allow(helper).to receive(:group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id') allow(helper).to receive(:group_group_member_path).with(group, ':id').and_return('/groups/foo-bar/-/group_members/:id')
allow(helper).to receive(:can?).with(current_user, :admin_group_member, group).and_return(true)
end end
it 'returns expected hash' do it 'returns expected hash' do
expect(helper.group_members_list_data_attributes(group, present_members([group_member]))).to include({ expect(helper.group_members_list_data_attributes(group, present_members([group_member]))).to include({
members: helper.members_data_json(group, present_members([group_member])), members: helper.members_data_json(group, present_members([group_member])),
member_path: '/groups/foo-bar/-/group_members/:id', member_path: '/groups/foo-bar/-/group_members/:id',
group_id: group.id group_id: group.id,
can_manage_members: 'true'
}) })
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