diff options
Diffstat (limited to 'app/assets/javascripts/members')
20 files changed, 175 insertions, 40 deletions
diff --git a/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue b/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue index 83f266779f2..00973100e15 100644 --- a/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue +++ b/app/assets/javascripts/members/components/action_buttons/approve_access_request_button.vue @@ -12,6 +12,7 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, + inject: ['namespace'], props: { memberId: { type: Number, @@ -19,7 +20,11 @@ export default { }, }, computed: { - ...mapState(['memberPath']), + ...mapState({ + memberPath(state) { + return state[this.namespace].memberPath; + }, + }), approvePath() { return this.memberPath.replace(/:id$/, `${this.memberId}/approve_access_request`); }, diff --git a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue index 0bcc85157f1..91062c222f4 100644 --- a/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue +++ b/app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue @@ -42,6 +42,7 @@ export default { :member-id="member.id" :message="message" :title="s__('Member|Revoke invite')" + is-invite /> </div> </action-button-group> diff --git a/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue index 3b87c29c1bc..fef7940eaa2 100644 --- a/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue +++ b/app/assets/javascripts/members/components/action_buttons/remove_group_link_button.vue @@ -12,6 +12,7 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, + inject: ['namespace'], props: { groupLink: { type: Object, @@ -19,7 +20,11 @@ export default { }, }, methods: { - ...mapActions(['showRemoveGroupLinkModal']), + ...mapActions({ + showRemoveGroupLinkModal(dispatch, payload) { + return dispatch(`${this.namespace}/showRemoveGroupLinkModal`, payload); + }, + }), }, }; </script> diff --git a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue index cb71be39ebc..a477aedd233 100644 --- a/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue +++ b/app/assets/javascripts/members/components/action_buttons/remove_member_button.vue @@ -8,11 +8,17 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, + inject: ['namespace'], props: { memberId: { type: Number, required: true, }, + memberType: { + type: String, + required: false, + default: null, + }, message: { type: String, required: true, @@ -31,12 +37,29 @@ export default { required: false, default: false, }, + isInvite: { + type: Boolean, + required: false, + default: false, + }, + oncallSchedules: { + type: Object, + required: false, + default: () => {}, + }, }, computed: { - ...mapState(['memberPath']), + ...mapState({ + memberPath(state) { + return state[this.namespace].memberPath; + }, + }), computedMemberPath() { return this.memberPath.replace(':id', this.memberId); }, + stringifiedSchedules() { + return JSON.stringify(this.oncallSchedules); + }, }, }; </script> @@ -50,8 +73,11 @@ export default { :aria-label="title" :icon="icon" :data-member-path="computedMemberPath" + :data-member-type="memberType" :data-is-access-request="isAccessRequest" + :data-is-invite="isInvite" :data-message="message" + :data-oncall-schedules="stringifiedSchedules" data-qa-selector="delete_member_button" /> </template> diff --git a/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue b/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue index 261a6279920..2173974c6f4 100644 --- a/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue +++ b/app/assets/javascripts/members/components/action_buttons/resend_invite_button.vue @@ -12,6 +12,7 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, + inject: ['namespace'], props: { memberId: { type: Number, @@ -19,7 +20,11 @@ export default { }, }, computed: { - ...mapState(['memberPath']), + ...mapState({ + memberPath(state) { + return state[this.namespace].memberPath; + }, + }), resendPath() { return this.memberPath.replace(/:id$/, `${this.memberId}/resend_invite`); }, diff --git a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue index f779d1755a5..1e9f79927ea 100644 --- a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue +++ b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue @@ -33,7 +33,7 @@ export default { if (user) { return sprintf( - s__('Members|Are you sure you want to remove %{usersName} from "%{source}"'), + s__('Members|Are you sure you want to remove %{usersName} from "%{source}"?'), { usersName: user.name, source: source.fullName, @@ -42,12 +42,16 @@ export default { } return sprintf( - s__('Members|Are you sure you want to remove this orphaned member from "%{source}"'), + s__('Members|Are you sure you want to remove this orphaned member from "%{source}"?'), { source: source.fullName, }, ); }, + oncallScheduleUserData() { + const { user: { name, oncallSchedules: schedules } = {} } = this.member; + return { name, schedules }; + }, }, }; </script> @@ -59,6 +63,8 @@ export default { <remove-member-button v-else :member-id="member.id" + :member-type="member.type" + :oncall-schedules="oncallScheduleUserData" :message="message" :title="s__('Member|Remove member')" /> diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue index 27fceb7374e..585fabdf3ff 100644 --- a/app/assets/javascripts/members/components/app.vue +++ b/app/assets/javascripts/members/components/app.vue @@ -9,8 +9,16 @@ import MembersTable from './table/members_table.vue'; export default { name: 'MembersApp', components: { MembersTable, FilterSortContainer, GlAlert }, + inject: ['namespace'], computed: { - ...mapState(['showError', 'errorMessage']), + ...mapState({ + showError(state) { + return state[this.namespace].showError; + }, + errorMessage(state) { + return state[this.namespace].errorMessage; + }, + }), }, watch: { showError(value) { @@ -23,7 +31,9 @@ export default { }, methods: { ...mapMutations({ - hideError: HIDE_ERROR, + hideError(commit) { + return commit(`${this.namespace}/${HIDE_ERROR}`); + }, }), }, }; diff --git a/app/assets/javascripts/members/components/avatars/user_avatar.vue b/app/assets/javascripts/members/components/avatars/user_avatar.vue index 658fb43cecb..9687eacb036 100644 --- a/app/assets/javascripts/members/components/avatars/user_avatar.vue +++ b/app/assets/javascripts/members/components/avatars/user_avatar.vue @@ -5,7 +5,6 @@ import { GlBadge, GlSafeHtmlDirective as SafeHtml, } from '@gitlab/ui'; -import { mapState } from 'vuex'; import { generateBadges } from 'ee_else_ce/members/utils'; import { glEmojiTag } from '~/emoji'; import { __ } from '~/locale'; @@ -24,6 +23,7 @@ export default { directives: { SafeHtml, }, + inject: ['canManageMembers'], props: { member: { type: Object, @@ -35,7 +35,6 @@ export default { }, }, computed: { - ...mapState(['canManageMembers']), user() { return this.member.user; }, diff --git a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue index 812a8626949..419b7b83c0f 100644 --- a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue +++ b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue @@ -6,8 +6,16 @@ import SortDropdown from './sort_dropdown.vue'; export default { name: 'FilterSortContainer', components: { MembersFilteredSearchBar, SortDropdown }, + inject: ['namespace'], computed: { - ...mapState(['filteredSearchBar', 'tableSortableFields']), + ...mapState({ + filteredSearchBar(state) { + return state[this.namespace].filteredSearchBar; + }, + tableSortableFields(state) { + return state[this.namespace].tableSortableFields; + }, + }), showContainer() { return this.filteredSearchBar.show || this.showSortDropdown; }, diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue index 039ee9a0207..cc97d235a9c 100644 --- a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue +++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue @@ -37,13 +37,18 @@ export default { ], }, ], + inject: ['namespace', 'sourceId', 'canManageMembers'], data() { return { initialFilterValue: [], }; }, computed: { - ...mapState(['sourceId', 'filteredSearchBar', 'canManageMembers']), + ...mapState({ + filteredSearchBar(state) { + return state[this.namespace].filteredSearchBar; + }, + }), tokens() { return this.$options.availableTokens.filter((token) => { if ( diff --git a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue index 9fa8772faf4..ce28283ccdf 100644 --- a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue +++ b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue @@ -8,8 +8,16 @@ import { parseSortParam, buildSortHref } from '~/members/utils'; export default { name: 'SortDropdown', components: { GlSorting, GlSortingItem }, + inject: ['namespace'], computed: { - ...mapState(['tableSortableFields', 'filteredSearchBar']), + ...mapState({ + tableSortableFields(state) { + return state[this.namespace].tableSortableFields; + }, + filteredSearchBar(state) { + return state[this.namespace].filteredSearchBar; + }, + }), sort() { return parseSortParam(this.tableSortableFields); }, diff --git a/app/assets/javascripts/members/components/modals/leave_modal.vue b/app/assets/javascripts/members/components/modals/leave_modal.vue index a0f978d85cc..44178981136 100644 --- a/app/assets/javascripts/members/components/modals/leave_modal.vue +++ b/app/assets/javascripts/members/components/modals/leave_modal.vue @@ -3,6 +3,7 @@ import { GlModal, GlForm, GlSprintf, GlTooltipDirective } from '@gitlab/ui'; import { mapState } from 'vuex'; import csrf from '~/lib/utils/csrf'; import { __, s__, sprintf } from '~/locale'; +import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue'; import { LEAVE_MODAL_ID } from '../../constants'; export default { @@ -19,10 +20,11 @@ export default { csrf, modalId: LEAVE_MODAL_ID, modalContent: s__('Members|Are you sure you want to leave "%{source}"?'), - components: { GlModal, GlForm, GlSprintf }, + components: { GlModal, GlForm, GlSprintf, OncallSchedulesList }, directives: { GlTooltip: GlTooltipDirective, }, + inject: ['namespace'], props: { member: { type: Object, @@ -30,13 +32,23 @@ export default { }, }, computed: { - ...mapState(['memberPath']), + ...mapState({ + memberPath(state) { + return state[this.namespace].memberPath; + }, + }), leavePath() { return this.memberPath.replace(/:id$/, 'leave'); }, modalTitle() { return sprintf(s__('Members|Leave "%{source}"'), { source: this.member.source.fullName }); }, + schedules() { + return this.member.user?.oncallSchedules; + }, + isPartOfOnCallSchedules() { + return this.schedules?.length; + }, }, methods: { handlePrimary() { @@ -53,7 +65,6 @@ export default { :title="modalTitle" :action-primary="$options.actionPrimary" :action-cancel="$options.actionCancel" - size="sm" @primary="handlePrimary" > <gl-form ref="form" :action="leavePath" method="post"> @@ -63,6 +74,12 @@ export default { </gl-sprintf> </p> + <oncall-schedules-list + v-if="isPartOfOnCallSchedules" + :schedules="schedules" + :is-current-user="true" + /> + <input type="hidden" name="_method" value="delete" /> <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> </gl-form> diff --git a/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue b/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue index 1ba6bf9aba6..b179ced46e1 100644 --- a/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue +++ b/app/assets/javascripts/members/components/modals/remove_group_link_modal.vue @@ -22,8 +22,19 @@ export default { }, modalId: REMOVE_GROUP_LINK_MODAL_ID, components: { GlModal, GlSprintf, GlForm }, + inject: ['namespace'], computed: { - ...mapState(['memberPath', 'groupLinkToRemove', 'removeGroupLinkModalVisible']), + ...mapState({ + memberPath(state) { + return state[this.namespace].memberPath; + }, + groupLinkToRemove(state) { + return state[this.namespace].groupLinkToRemove; + }, + removeGroupLinkModalVisible(state) { + return state[this.namespace].removeGroupLinkModalVisible; + }, + }), groupLinkPath() { return this.memberPath.replace(/:id$/, this.groupLinkToRemove?.id); }, @@ -35,7 +46,11 @@ export default { }, }, methods: { - ...mapActions(['hideRemoveGroupLinkModal']), + ...mapActions({ + hideRemoveGroupLinkModal(dispatch) { + return dispatch(`${this.namespace}/hideRemoveGroupLinkModal`); + }, + }), handlePrimary() { this.$refs.form.$el.submit(); }, diff --git a/app/assets/javascripts/members/components/table/expiration_datepicker.vue b/app/assets/javascripts/members/components/table/expiration_datepicker.vue index 0a8af81c1d1..9f6e8979102 100644 --- a/app/assets/javascripts/members/components/table/expiration_datepicker.vue +++ b/app/assets/javascripts/members/components/table/expiration_datepicker.vue @@ -7,6 +7,7 @@ import { s__ } from '~/locale'; export default { name: 'ExpirationDatepicker', components: { GlDatepicker }, + inject: ['namespace'], props: { member: { type: Object, @@ -46,7 +47,11 @@ export default { } }, methods: { - ...mapActions(['updateMemberExpiration']), + ...mapActions({ + updateMemberExpiration(dispatch, payload) { + return dispatch(`${this.namespace}/updateMemberExpiration`, payload); + }, + }), handleInput(date) { this.busy = true; this.updateMemberExpiration({ diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue index 9a3edff19ff..236aeaef418 100644 --- a/app/assets/javascripts/members/components/table/members_table.vue +++ b/app/assets/javascripts/members/components/table/members_table.vue @@ -31,8 +31,19 @@ export default { LdapOverrideConfirmationModal: () => import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'), }, + inject: ['namespace', 'currentUserId'], computed: { - ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId']), + ...mapState({ + members(state) { + return state[this.namespace].members; + }, + tableFields(state) { + return state[this.namespace].tableFields; + }, + tableAttrs(state) { + return state[this.namespace].tableAttrs; + }, + }), filteredFields() { return FIELDS.filter( (field) => this.tableFields.includes(field.key) && this.showField(field), diff --git a/app/assets/javascripts/members/components/table/members_table_cell.vue b/app/assets/javascripts/members/components/table/members_table_cell.vue index 1f537740f94..3436bcab2fc 100644 --- a/app/assets/javascripts/members/components/table/members_table_cell.vue +++ b/app/assets/javascripts/members/components/table/members_table_cell.vue @@ -1,5 +1,4 @@ <script> -import { mapState } from 'vuex'; import { MEMBER_TYPES } from '../../constants'; import { isGroup, @@ -12,6 +11,7 @@ import { export default { name: 'MembersTableCell', + inject: ['currentUserId'], props: { member: { type: Object, @@ -19,7 +19,6 @@ export default { }, }, computed: { - ...mapState(['currentUserId']), isGroup() { return isGroup(this.member); }, diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue index 8ad45ab6920..f84ded427cd 100644 --- a/app/assets/javascripts/members/components/table/role_dropdown.vue +++ b/app/assets/javascripts/members/components/table/role_dropdown.vue @@ -11,6 +11,7 @@ export default { GlDropdownItem, LdapDropdownItem: () => import('ee_component/members/components/ldap/ldap_dropdown_item.vue'), }, + inject: ['namespace'], props: { member: { type: Object, @@ -44,7 +45,11 @@ export default { } }, methods: { - ...mapActions(['updateMemberRole']), + ...mapActions({ + updateMemberRole(dispatch, payload) { + return dispatch(`${this.namespace}/updateMemberRole`, payload); + }, + }), handleSelect(value, name) { if (value === this.member.accessLevel.integerValue) { return; diff --git a/app/assets/javascripts/members/index.js b/app/assets/javascripts/members/index.js index fe174d9beb6..6376b3fa75a 100644 --- a/app/assets/javascripts/members/index.js +++ b/app/assets/javascripts/members/index.js @@ -8,6 +8,7 @@ import membersStore from './store'; export const initMembersApp = ( el, { + namespace, tableFields = [], tableAttrs = {}, tableSortableFields = [], @@ -22,22 +23,31 @@ export const initMembersApp = ( Vue.use(Vuex); Vue.use(GlToast); - const store = new Vuex.Store( - membersStore({ - ...parseDataAttributes(el), - currentUserId: gon.current_user_id || null, - tableFields, - tableAttrs, - tableSortableFields, - requestFormatter, - filteredSearchBar, - }), - ); + const { sourceId, canManageMembers, ...vuexStoreAttributes } = parseDataAttributes(el); + + const store = new Vuex.Store({ + modules: { + [namespace]: membersStore({ + ...vuexStoreAttributes, + tableFields, + tableAttrs, + tableSortableFields, + requestFormatter, + filteredSearchBar, + }), + }, + }); return new Vue({ el, components: { App }, store, + provide: { + namespace, + currentUserId: gon.current_user_id || null, + sourceId, + canManageMembers, + }, render: (createElement) => createElement('app'), }); }; diff --git a/app/assets/javascripts/members/store/index.js b/app/assets/javascripts/members/store/index.js index 45f4eefffc9..6c371887a3f 100644 --- a/app/assets/javascripts/members/store/index.js +++ b/app/assets/javascripts/members/store/index.js @@ -3,6 +3,7 @@ import mutations from 'ee_else_ce/members/store/mutations'; import createState from 'ee_else_ce/members/store/state'; export default (initialState) => ({ + namespaced: true, state: createState(initialState), actions, mutations, diff --git a/app/assets/javascripts/members/store/state.js b/app/assets/javascripts/members/store/state.js index 23a7983adcc..4006b4b501d 100644 --- a/app/assets/javascripts/members/store/state.js +++ b/app/assets/javascripts/members/store/state.js @@ -1,8 +1,5 @@ export default ({ members, - sourceId, - currentUserId, - canManageMembers, tableFields, tableAttrs, tableSortableFields, @@ -11,9 +8,6 @@ export default ({ filteredSearchBar, }) => ({ members, - sourceId, - currentUserId, - canManageMembers, tableFields, tableAttrs, tableSortableFields, |