diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 09:08:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 09:08:42 +0000 |
commit | b76ae638462ab0f673e5915986070518dd3f9ad3 (patch) | |
tree | bdab0533383b52873be0ec0eb4d3c66598ff8b91 /app/assets/javascripts/members/components | |
parent | 434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff) | |
download | gitlab-ce-b76ae638462ab0f673e5915986070518dd3f9ad3.tar.gz |
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/members/components')
5 files changed, 168 insertions, 31 deletions
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 a477aedd233..665e8ee69f7 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 @@ -1,6 +1,6 @@ <script> import { GlButton, GlTooltipDirective } from '@gitlab/ui'; -import { mapState } from 'vuex'; +import { mapActions, mapState } from 'vuex'; export default { name: 'RemoveMemberButton', @@ -45,7 +45,7 @@ export default { oncallSchedules: { type: Object, required: false, - default: () => {}, + default: () => ({}), }, }, computed: { @@ -54,30 +54,35 @@ export default { return state[this.namespace].memberPath; }, }), - computedMemberPath() { - return this.memberPath.replace(':id', this.memberId); - }, - stringifiedSchedules() { - return JSON.stringify(this.oncallSchedules); + modalData() { + return { + isAccessRequest: this.isAccessRequest, + isInvite: this.isInvite, + memberPath: this.memberPath.replace(':id', this.memberId), + memberType: this.memberType, + message: this.message, + oncallSchedules: this.oncallSchedules, + }; }, }, + methods: { + ...mapActions({ + showRemoveMemberModal(dispatch, payload) { + return dispatch(`${this.namespace}/showRemoveMemberModal`, payload); + }, + }), + }, }; </script> <template> <gl-button - v-gl-tooltip.hover - class="js-remove-member-button" + v-gl-tooltip variant="danger" :title="title" :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" + @click="showRemoveMemberModal(modalData)" /> </template> 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 33d86dec767..e9329fb1d88 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 @@ -1,7 +1,12 @@ <script> import { GlFilteredSearchToken } from '@gitlab/ui'; import { mapState } from 'vuex'; -import { getParameterByName, setUrlParams, queryToObject } from '~/lib/utils/url_utility'; +import { + getParameterByName, + setUrlParams, + queryToObject, + redirectTo, +} from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import { SEARCH_TOKEN_TYPE, @@ -122,14 +127,16 @@ export default { const sortParamValue = getParameterByName(SORT_QUERY_PARAM_NAME); const activeTabParamValue = getParameterByName(ACTIVE_TAB_QUERY_PARAM_NAME); - window.location.href = setUrlParams( - { - ...params, - ...(sortParamValue && { [SORT_QUERY_PARAM_NAME]: sortParamValue }), - ...(activeTabParamValue && { [ACTIVE_TAB_QUERY_PARAM_NAME]: activeTabParamValue }), - }, - window.location.href, - true, + redirectTo( + setUrlParams( + { + ...params, + ...(sortParamValue && { [SORT_QUERY_PARAM_NAME]: sortParamValue }), + ...(activeTabParamValue && { [ACTIVE_TAB_QUERY_PARAM_NAME]: activeTabParamValue }), + }, + window.location.href, + true, + ), ); }, }, diff --git a/app/assets/javascripts/members/components/members_tabs.vue b/app/assets/javascripts/members/components/members_tabs.vue index 7c21e33d892..ee4743010cf 100644 --- a/app/assets/javascripts/members/components/members_tabs.vue +++ b/app/assets/javascripts/members/components/members_tabs.vue @@ -1,8 +1,7 @@ <script> -import { GlTabs, GlTab, GlBadge } from '@gitlab/ui'; +import { GlTabs, GlTab, GlBadge, GlButton } from '@gitlab/ui'; import { mapState } from 'vuex'; -// eslint-disable-next-line import/no-deprecated -import { urlParamsToObject } from '~/lib/utils/url_utility'; +import { queryToObject } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import { MEMBER_TYPES, TAB_QUERY_PARAM_VALUES, ACTIVE_TAB_QUERY_PARAM_NAME } from '../constants'; import MembersApp from './app.vue'; @@ -36,8 +35,8 @@ export default { queryParamValue: TAB_QUERY_PARAM_VALUES.accessRequest, }, ], - components: { MembersApp, GlTabs, GlTab, GlBadge }, - inject: ['canManageMembers'], + components: { MembersApp, GlTabs, GlTab, GlBadge, GlButton }, + inject: ['canManageMembers', 'canExportMembers', 'exportCsvPath'], data() { return { selectedTabIndex: 0, @@ -59,8 +58,7 @@ export default { }, }), urlParams() { - // eslint-disable-next-line import/no-deprecated - return Object.keys(urlParamsToObject(window.location.search)); + return Object.keys(queryToObject(window.location.search, { gatherArrays: true })); }, activeTabIndexCalculatedFromUrlParams() { return this.$options.TABS.findIndex(({ namespace }) => { @@ -123,5 +121,15 @@ export default { <members-app :namespace="tab.namespace" :tab-query-param-value="tab.queryParamValue" /> </gl-tab> </template> + <template #tabs-end> + <gl-button + v-if="canExportMembers" + class="gl-align-self-center gl-ml-auto" + icon="export" + :href="exportCsvPath" + > + {{ __('Export as CSV') }} + </gl-button> + </template> </gl-tabs> </template> diff --git a/app/assets/javascripts/members/components/modals/remove_member_modal.vue b/app/assets/javascripts/members/components/modals/remove_member_modal.vue new file mode 100644 index 00000000000..00b6ebf9a73 --- /dev/null +++ b/app/assets/javascripts/members/components/modals/remove_member_modal.vue @@ -0,0 +1,114 @@ +<script> +import { GlFormCheckbox, GlModal } from '@gitlab/ui'; +import { mapActions, mapState } from 'vuex'; +import csrf from '~/lib/utils/csrf'; +import { s__, __ } from '~/locale'; +import OncallSchedulesList from '~/vue_shared/components/oncall_schedules_list.vue'; + +export default { + actionCancel: { + text: __('Cancel'), + }, + csrf, + components: { + GlFormCheckbox, + GlModal, + OncallSchedulesList, + }, + inject: ['namespace'], + computed: { + ...mapState({ + isAccessRequest(state) { + return state[this.namespace].removeMemberModalData.isAccessRequest; + }, + isInvite(state) { + return state[this.namespace].removeMemberModalData.isInvite; + }, + memberPath(state) { + return state[this.namespace].removeMemberModalData.memberPath; + }, + memberType(state) { + return state[this.namespace].removeMemberModalData.memberType; + }, + message(state) { + return state[this.namespace].removeMemberModalData.message; + }, + oncallSchedules(state) { + return state[this.namespace].removeMemberModalData.oncallSchedules ?? {}; + }, + removeMemberModalVisible(state) { + return state[this.namespace].removeMemberModalVisible; + }, + }), + isGroupMember() { + return this.memberType === 'GroupMember'; + }, + actionText() { + if (this.isAccessRequest) { + return __('Deny access request'); + } else if (this.isInvite) { + return s__('Member|Revoke invite'); + } + + return __('Remove member'); + }, + actionPrimary() { + return { + text: this.actionText, + attributes: { + variant: 'danger', + }, + }; + }, + showUnassignIssuablesCheckbox() { + return !this.isAccessRequest && !this.isInvite; + }, + isPartOfOncallSchedules() { + return !this.isAccessRequest && this.oncallSchedules.schedules?.length; + }, + }, + methods: { + ...mapActions({ + hideRemoveMemberModal(dispatch) { + return dispatch(`${this.namespace}/hideRemoveMemberModal`); + }, + }), + submitForm() { + this.$refs.form.submit(); + }, + }, +}; +</script> + +<template> + <gl-modal + ref="modal" + modal-id="remove-member-modal" + :action-cancel="$options.actionCancel" + :action-primary="actionPrimary" + :title="actionText" + :visible="removeMemberModalVisible" + data-qa-selector="remove_member_modal_content" + @primary="submitForm" + @hide="hideRemoveMemberModal" + > + <form ref="form" :action="memberPath" method="post"> + <p>{{ message }}</p> + + <oncall-schedules-list + v-if="isPartOfOncallSchedules" + :schedules="oncallSchedules.schedules" + :user-name="oncallSchedules.name" + /> + + <input ref="method" type="hidden" name="_method" value="delete" /> + <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> + <gl-form-checkbox v-if="isGroupMember" name="remove_sub_memberships"> + {{ __('Also remove direct user membership from subgroups and projects') }} + </gl-form-checkbox> + <gl-form-checkbox v-if="showUnassignIssuablesCheckbox" name="unassign_issuables"> + {{ __('Also unassign this user from related issues and merge requests') }} + </gl-form-checkbox> + </form> + </gl-modal> +</template> diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue index b9c80edbc49..debc3fc31f6 100644 --- a/app/assets/javascripts/members/components/table/members_table.vue +++ b/app/assets/javascripts/members/components/table/members_table.vue @@ -7,6 +7,7 @@ import { mergeUrlParams } from '~/lib/utils/url_utility'; import initUserPopovers from '~/user_popovers'; import { FIELDS, ACTIVE_TAB_QUERY_PARAM_NAME } from '../../constants'; import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue'; +import RemoveMemberModal from '../modals/remove_member_modal.vue'; import CreatedAt from './created_at.vue'; import ExpirationDatepicker from './expiration_datepicker.vue'; import ExpiresAt from './expires_at.vue'; @@ -29,6 +30,7 @@ export default { MemberActionButtons, RoleDropdown, RemoveGroupLinkModal, + RemoveMemberModal, ExpirationDatepicker, LdapOverrideConfirmationModal: () => import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'), @@ -225,6 +227,7 @@ export default { align="center" /> <remove-group-link-modal /> + <remove-member-modal /> <ldap-override-confirmation-modal /> </div> </template> |