diff options
Diffstat (limited to 'app/assets/javascripts/members')
25 files changed, 198 insertions, 63 deletions
diff --git a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue index fcb70dd45a6..35966be7363 100644 --- a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue +++ b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue @@ -1,8 +1,8 @@ <script> +import { s__, sprintf } from '~/locale'; import ActionButtonGroup from './action_button_group.vue'; -import RemoveMemberButton from './remove_member_button.vue'; import ApproveAccessRequestButton from './approve_access_request_button.vue'; -import { s__, sprintf } from '~/locale'; +import RemoveMemberButton from './remove_member_button.vue'; export default { name: 'AccessRequestActionButtons', 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 e8a53ff173d..83f266779f2 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 @@ -1,6 +1,6 @@ <script> -import { mapState } from 'vuex'; import { GlButton, GlForm, GlTooltipDirective } from '@gitlab/ui'; +import { mapState } from 'vuex'; import csrf from '~/lib/utils/csrf'; import { __ } from '~/locale'; 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 9a27348f146..0bcc85157f1 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 @@ -1,8 +1,8 @@ <script> +import { s__, sprintf } from '~/locale'; import ActionButtonGroup from './action_button_group.vue'; import RemoveMemberButton from './remove_member_button.vue'; import ResendInviteButton from './resend_invite_button.vue'; -import { s__, sprintf } from '~/locale'; export default { name: 'InviteActionButtons', diff --git a/app/assets/javascripts/members/components/action_buttons/leave_button.vue b/app/assets/javascripts/members/components/action_buttons/leave_button.vue index 443a962e0cf..f600a207b8d 100644 --- a/app/assets/javascripts/members/components/action_buttons/leave_button.vue +++ b/app/assets/javascripts/members/components/action_buttons/leave_button.vue @@ -1,8 +1,8 @@ <script> import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui'; import { __ } from '~/locale'; -import LeaveModal from '../modals/leave_modal.vue'; import { LEAVE_MODAL_ID } from '../../constants'; +import LeaveModal from '../modals/leave_modal.vue'; export default { name: 'LeaveButton', 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 9d89cb40676..3b87c29c1bc 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 @@ -1,6 +1,6 @@ <script> -import { mapActions } from 'vuex'; import { GlButton, GlTooltipDirective } from '@gitlab/ui'; +import { mapActions } from 'vuex'; import { s__ } from '~/locale'; export default { @@ -31,6 +31,7 @@ export default { :title="$options.i18n.buttonTitle" :aria-label="$options.i18n.buttonTitle" icon="remove" + data-qa-selector="delete_group_access_link" @click="showRemoveGroupLinkModal(groupLink)" /> </template> 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 b0b7ff4ce9a..cb71be39ebc 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 { mapState } from 'vuex'; import { GlButton, GlTooltipDirective } from '@gitlab/ui'; +import { mapState } from 'vuex'; export default { name: 'RemoveMemberButton', 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 1cc3fd17e98..261a6279920 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 @@ -1,6 +1,6 @@ <script> -import { mapState } from 'vuex'; import { GlButton, GlTooltipDirective } from '@gitlab/ui'; +import { mapState } from 'vuex'; import csrf from '~/lib/utils/csrf'; import { __ } from '~/locale'; 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 0e5df961782..f779d1755a5 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 @@ -1,8 +1,8 @@ <script> +import { s__, sprintf } from '~/locale'; import ActionButtonGroup from './action_button_group.vue'; -import RemoveMemberButton from './remove_member_button.vue'; import LeaveButton from './leave_button.vue'; -import { s__, sprintf } from '~/locale'; +import RemoveMemberButton from './remove_member_button.vue'; export default { name: 'UserActionButtons', diff --git a/app/assets/javascripts/members/components/app.vue b/app/assets/javascripts/members/components/app.vue new file mode 100644 index 00000000000..27fceb7374e --- /dev/null +++ b/app/assets/javascripts/members/components/app.vue @@ -0,0 +1,40 @@ +<script> +import { GlAlert } from '@gitlab/ui'; +import { mapState, mapMutations } from 'vuex'; +import { scrollToElement } from '~/lib/utils/common_utils'; +import { HIDE_ERROR } from '../store/mutation_types'; +import FilterSortContainer from './filter_sort/filter_sort_container.vue'; +import MembersTable from './table/members_table.vue'; + +export default { + name: 'MembersApp', + components: { MembersTable, FilterSortContainer, GlAlert }, + computed: { + ...mapState(['showError', 'errorMessage']), + }, + watch: { + showError(value) { + if (value) { + this.$nextTick(() => { + scrollToElement(this.$refs.errorAlert.$el); + }); + } + }, + }, + methods: { + ...mapMutations({ + hideError: HIDE_ERROR, + }), + }, +}; +</script> + +<template> + <div> + <gl-alert v-if="showError" ref="errorAlert" variant="danger" @dismiss="hideError">{{ + errorMessage + }}</gl-alert> + <filter-sort-container /> + <members-table /> + </div> +</template> diff --git a/app/assets/javascripts/members/components/avatars/user_avatar.vue b/app/assets/javascripts/members/components/avatars/user_avatar.vue index e2264085e67..79dda3c1379 100644 --- a/app/assets/javascripts/members/components/avatars/user_avatar.vue +++ b/app/assets/javascripts/members/components/avatars/user_avatar.vue @@ -6,9 +6,9 @@ import { GlSafeHtmlDirective as SafeHtml, } from '@gitlab/ui'; import { generateBadges } from 'ee_else_ce/members/utils'; +import { glEmojiTag } from '~/emoji'; import { __ } from '~/locale'; import { AVATAR_SIZE } from '../../constants'; -import { glEmojiTag } from '~/emoji'; export default { name: 'UserAvatar', @@ -69,7 +69,10 @@ export default { > <template #meta> <div v-if="statusEmoji" class="gl-p-1"> - <span v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)"></span> + <span + v-safe-html:[$options.safeHtmlConfig]="glEmojiTag(statusEmoji)" + class="user-status-emoji gl-mr-0" + ></span> </div> <div v-for="badge in badges" :key="badge.text" class="gl-p-1"> <gl-badge size="sm" :variant="badge.variant"> 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 f869ecd392f..812a8626949 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 @@ -19,7 +19,7 @@ export default { </script> <template> - <div v-if="showContainer" class="gl-bg-gray-10 gl-p-3 gl-display-md-flex"> + <div v-if="showContainer" class="gl-bg-gray-10 gl-p-3 gl-md-display-flex"> <members-filtered-search-bar v-if="filteredSearchBar.show" class="gl-p-3 gl-flex-grow-1" /> <sort-dropdown v-if="showSortDropdown" class="gl-p-3 gl-flex-shrink-0" /> </div> 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 cf7501d84fa..039ee9a0207 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,11 +1,11 @@ <script> -import { mapState } from 'vuex'; import { GlFilteredSearchToken } from '@gitlab/ui'; -import { setUrlParams, queryToObject } from '~/lib/utils/url_utility'; +import { mapState } from 'vuex'; import { getParameterByName } from '~/lib/utils/common_utils'; +import { setUrlParams, queryToObject } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; -import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; import { SEARCH_TOKEN_TYPE, SORT_PARAM } from '~/members/constants'; +import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; export default { name: 'MembersFilteredSearchBar', 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 bcfe559768d..9fa8772faf4 100644 --- a/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue +++ b/app/assets/javascripts/members/components/filter_sort/sort_dropdown.vue @@ -1,9 +1,9 @@ <script> -import { mapState } from 'vuex'; import { GlSorting, GlSortingItem } from '@gitlab/ui'; +import { mapState } from 'vuex'; import { visitUrl } from '~/lib/utils/url_utility'; -import { parseSortParam, buildSortHref } from '~/members/utils'; import { FIELDS } from '~/members/constants'; +import { parseSortParam, buildSortHref } from '~/members/utils'; export default { name: 'SortDropdown', diff --git a/app/assets/javascripts/members/components/modals/leave_modal.vue b/app/assets/javascripts/members/components/modals/leave_modal.vue index d231c7eabfa..a0f978d85cc 100644 --- a/app/assets/javascripts/members/components/modals/leave_modal.vue +++ b/app/assets/javascripts/members/components/modals/leave_modal.vue @@ -1,6 +1,6 @@ <script> -import { mapState } from 'vuex'; import { GlModal, GlForm, GlSprintf, GlTooltipDirective } from '@gitlab/ui'; +import { mapState } from 'vuex'; import csrf from '~/lib/utils/csrf'; import { __, s__, sprintf } from '~/locale'; import { LEAVE_MODAL_ID } from '../../constants'; 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 231d014a4ec..1ba6bf9aba6 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 @@ -1,6 +1,6 @@ <script> -import { mapState, mapActions } from 'vuex'; import { GlModal, GlSprintf, GlForm } from '@gitlab/ui'; +import { mapState, mapActions } from 'vuex'; import csrf from '~/lib/utils/csrf'; import { __, s__, sprintf } from '~/locale'; import { REMOVE_GROUP_LINK_MODAL_ID } from '../../constants'; @@ -52,6 +52,7 @@ export default { :action-primary="$options.actionPrimary" :action-cancel="$options.actionCancel" size="sm" + data-qa-selector="remove_group_link_modal_content" @primary="handlePrimary" @hide="hideRemoveGroupLinkModal" > diff --git a/app/assets/javascripts/members/components/table/member_action_buttons.vue b/app/assets/javascripts/members/components/table/member_action_buttons.vue index c61ebec33bd..6f15f079d2d 100644 --- a/app/assets/javascripts/members/components/table/member_action_buttons.vue +++ b/app/assets/javascripts/members/components/table/member_action_buttons.vue @@ -1,9 +1,9 @@ <script> -import UserActionButtons from '../action_buttons/user_action_buttons.vue'; +import { MEMBER_TYPES } from '../../constants'; +import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue'; import GroupActionButtons from '../action_buttons/group_action_buttons.vue'; import InviteActionButtons from '../action_buttons/invite_action_buttons.vue'; -import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue'; -import { MEMBER_TYPES } from '../../constants'; +import UserActionButtons from '../action_buttons/user_action_buttons.vue'; export default { name: 'MemberActionButtons', diff --git a/app/assets/javascripts/members/components/table/member_avatar.vue b/app/assets/javascripts/members/components/table/member_avatar.vue index a1f98d4008a..92b757ffcba 100644 --- a/app/assets/javascripts/members/components/table/member_avatar.vue +++ b/app/assets/javascripts/members/components/table/member_avatar.vue @@ -1,8 +1,8 @@ <script> import { kebabCase } from 'lodash'; -import UserAvatar from '../avatars/user_avatar.vue'; -import InviteAvatar from '../avatars/invite_avatar.vue'; import GroupAvatar from '../avatars/group_avatar.vue'; +import InviteAvatar from '../avatars/invite_avatar.vue'; +import UserAvatar from '../avatars/user_avatar.vue'; export default { name: 'MemberAvatar', diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue index 16e0cd5ad4e..9a3edff19ff 100644 --- a/app/assets/javascripts/members/components/table/members_table.vue +++ b/app/assets/javascripts/members/components/table/members_table.vue @@ -1,18 +1,18 @@ <script> -import { mapState } from 'vuex'; import { GlTable, GlBadge } from '@gitlab/ui'; +import { mapState } from 'vuex'; import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue'; import { canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils'; -import { FIELDS } from '../../constants'; import initUserPopovers from '~/user_popovers'; -import MemberAvatar from './member_avatar.vue'; -import MemberSource from './member_source.vue'; +import { FIELDS } from '../../constants'; +import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue'; import CreatedAt from './created_at.vue'; +import ExpirationDatepicker from './expiration_datepicker.vue'; import ExpiresAt from './expires_at.vue'; import MemberActionButtons from './member_action_buttons.vue'; +import MemberAvatar from './member_avatar.vue'; +import MemberSource from './member_source.vue'; import RoleDropdown from './role_dropdown.vue'; -import RemoveGroupLinkModal from '../modals/remove_group_link_modal.vue'; -import ExpirationDatepicker from './expiration_datepicker.vue'; export default { name: 'MembersTable', @@ -32,7 +32,7 @@ export default { import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'), }, computed: { - ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId', 'sourceId']), + ...mapState(['members', 'tableFields', 'tableAttrs', 'currentUserId']), filteredFields() { return FIELDS.filter( (field) => this.tableFields.includes(field.key) && this.showField(field), @@ -55,9 +55,9 @@ export default { methods: { hasActionButtons(member) { return ( - canRemove(member, this.sourceId) || + canRemove(member) || canResend(member) || - canUpdate(member, this.currentUserId, this.sourceId) || + canUpdate(member, this.currentUserId) || canOverride(member) ); }, @@ -80,7 +80,7 @@ export default { return 'col-actions'; } - return ['col-actions', 'gl-display-none!', 'gl-display-lg-table-cell!']; + return ['col-actions', 'gl-display-none!', 'gl-lg-display-table-cell!']; }, tbodyTrAttr(member) { return { 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 20aa01b96bc..1f537740f94 100644 --- a/app/assets/javascripts/members/components/table/members_table_cell.vue +++ b/app/assets/javascripts/members/components/table/members_table_cell.vue @@ -19,7 +19,7 @@ export default { }, }, computed: { - ...mapState(['sourceId', 'currentUserId']), + ...mapState(['currentUserId']), isGroup() { return isGroup(this.member); }, @@ -41,19 +41,19 @@ export default { return MEMBER_TYPES.user; }, isDirectMember() { - return isDirectMember(this.member, this.sourceId); + return isDirectMember(this.member); }, isCurrentUser() { return isCurrentUser(this.member, this.currentUserId); }, canRemove() { - return canRemove(this.member, this.sourceId); + return canRemove(this.member); }, canResend() { return canResend(this.member); }, canUpdate() { - return canUpdate(this.member, this.currentUserId, this.sourceId); + return canUpdate(this.member, this.currentUserId); }, }, render() { diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js index 77cb150bff6..f68a8814fee 100644 --- a/app/assets/javascripts/members/constants.js +++ b/app/assets/javascripts/members/constants.js @@ -98,3 +98,8 @@ export const REMOVE_GROUP_LINK_MODAL_ID = 'remove-group-link-modal-id'; export const SEARCH_TOKEN_TYPE = 'filtered-search-term'; export const SORT_PARAM = 'sort'; + +export const MEMBER_ACCESS_LEVEL_PROPERTY_NAME = 'access_level'; + +export const GROUP_LINK_BASE_PROPERTY_NAME = 'group_link'; +export const GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME = 'group_access'; diff --git a/app/assets/javascripts/members/index.js b/app/assets/javascripts/members/index.js new file mode 100644 index 00000000000..fe174d9beb6 --- /dev/null +++ b/app/assets/javascripts/members/index.js @@ -0,0 +1,43 @@ +import { GlToast } from '@gitlab/ui'; +import Vue from 'vue'; +import Vuex from 'vuex'; +import { parseDataAttributes } from 'ee_else_ce/members/utils'; +import App from './components/app.vue'; +import membersStore from './store'; + +export const initMembersApp = ( + el, + { + tableFields = [], + tableAttrs = {}, + tableSortableFields = [], + requestFormatter = () => {}, + filteredSearchBar = { show: false }, + }, +) => { + if (!el) { + return () => {}; + } + + 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, + }), + ); + + return new Vue({ + el, + components: { App }, + store, + render: (createElement) => createElement('app'), + }); +}; diff --git a/app/assets/javascripts/members/store/actions.js b/app/assets/javascripts/members/store/actions.js index 4c31b3c9744..7b191dd85d0 100644 --- a/app/assets/javascripts/members/store/actions.js +++ b/app/assets/javascripts/members/store/actions.js @@ -1,6 +1,6 @@ -import * as types from './mutation_types'; import axios from '~/lib/utils/axios_utils'; import { formatDate } from '~/lib/utils/datetime_utility'; +import * as types from './mutation_types'; export const updateMemberRole = async ({ state, commit }, { memberId, accessLevel }) => { try { @@ -11,7 +11,7 @@ export const updateMemberRole = async ({ state, commit }, { memberId, accessLeve commit(types.RECEIVE_MEMBER_ROLE_SUCCESS, { memberId, accessLevel }); } catch (error) { - commit(types.RECEIVE_MEMBER_ROLE_ERROR); + commit(types.RECEIVE_MEMBER_ROLE_ERROR, { error }); throw error; } @@ -37,7 +37,7 @@ export const updateMemberExpiration = async ({ state, commit }, { memberId, expi expiresAt: expiresAt ? formatDate(expiresAt, 'isoUtcDateTime') : null, }); } catch (error) { - commit(types.RECEIVE_MEMBER_EXPIRATION_ERROR); + commit(types.RECEIVE_MEMBER_EXPIRATION_ERROR, { error }); throw error; } diff --git a/app/assets/javascripts/members/store/index.js b/app/assets/javascripts/members/store/index.js index 34c102999d2..45f4eefffc9 100644 --- a/app/assets/javascripts/members/store/index.js +++ b/app/assets/javascripts/members/store/index.js @@ -1,6 +1,6 @@ -import createState from 'ee_else_ce/members/store/state'; -import mutations from 'ee_else_ce/members/store/mutations'; import * as actions from 'ee_else_ce/members/store/actions'; +import mutations from 'ee_else_ce/members/store/mutations'; +import createState from 'ee_else_ce/members/store/state'; export default (initialState) => ({ state: createState(initialState), diff --git a/app/assets/javascripts/members/store/mutations.js b/app/assets/javascripts/members/store/mutations.js index 2415e744290..f4aac1571d6 100644 --- a/app/assets/javascripts/members/store/mutations.js +++ b/app/assets/javascripts/members/store/mutations.js @@ -13,10 +13,10 @@ export default { Vue.set(member, 'accessLevel', accessLevel); }, - [types.RECEIVE_MEMBER_ROLE_ERROR](state) { - state.errorMessage = s__( - "Members|An error occurred while updating the member's role, please try again.", - ); + [types.RECEIVE_MEMBER_ROLE_ERROR](state, { error }) { + state.errorMessage = + error.response?.data?.message || + s__("Members|An error occurred while updating the member's role, please try again."); state.showError = true; }, [types.RECEIVE_MEMBER_EXPIRATION_SUCCESS](state, { memberId, expiresAt }) { @@ -28,10 +28,12 @@ export default { Vue.set(member, 'expiresAt', expiresAt); }, - [types.RECEIVE_MEMBER_EXPIRATION_ERROR](state) { - state.errorMessage = s__( - "Members|An error occurred while updating the member's expiration date, please try again.", - ); + [types.RECEIVE_MEMBER_EXPIRATION_ERROR](state, { error }) { + state.errorMessage = + error.response?.data?.message || + s__( + "Members|An error occurred while updating the member's expiration date, please try again.", + ); state.showError = true; }, [types.HIDE_ERROR](state) { diff --git a/app/assets/javascripts/members/utils.js b/app/assets/javascripts/members/utils.js index 780b5a9df57..4de2dadb490 100644 --- a/app/assets/javascripts/members/utils.js +++ b/app/assets/javascripts/members/utils.js @@ -1,7 +1,17 @@ -import { __ } from '~/locale'; -import { getParameterByName } from '~/lib/utils/common_utils'; +import { isUndefined } from 'lodash'; +import { + getParameterByName, + convertObjectPropsToCamelCase, + parseBoolean, +} from '~/lib/utils/common_utils'; import { setUrlParams } from '~/lib/utils/url_utility'; -import { FIELDS, DEFAULT_SORT } from './constants'; +import { __ } from '~/locale'; +import { + FIELDS, + DEFAULT_SORT, + GROUP_LINK_BASE_PROPERTY_NAME, + GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME, +} from './constants'; export const generateBadges = (member, isCurrentUser) => [ { @@ -25,26 +35,24 @@ export const isGroup = (member) => { return Boolean(member.sharedWithGroup); }; -export const isDirectMember = (member, sourceId) => { - return isGroup(member) || member.source?.id === sourceId; +export const isDirectMember = (member) => { + return isGroup(member) || member.isDirectMember; }; export const isCurrentUser = (member, currentUserId) => { return member.user?.id === currentUserId; }; -export const canRemove = (member, sourceId) => { - return isDirectMember(member, sourceId) && member.canRemove; +export const canRemove = (member) => { + return isDirectMember(member) && member.canRemove; }; export const canResend = (member) => { return Boolean(member.invite?.canResend); }; -export const canUpdate = (member, currentUserId, sourceId) => { - return ( - !isCurrentUser(member, currentUserId) && isDirectMember(member, sourceId) && member.canUpdate - ); +export const canUpdate = (member, currentUserId) => { + return !isCurrentUser(member, currentUserId) && isDirectMember(member) && member.canUpdate; }; export const parseSortParam = (sortableFields) => { @@ -95,3 +103,35 @@ export const buildSortHref = ({ // Defined in `ee/app/assets/javascripts/vue_shared/components/members/utils.js` export const canOverride = () => false; + +export const parseDataAttributes = (el) => { + const { members, sourceId, memberPath, canManageMembers } = el.dataset; + + return { + members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }), + sourceId: parseInt(sourceId, 10), + memberPath, + canManageMembers: parseBoolean(canManageMembers), + }; +}; + +export const baseRequestFormatter = (basePropertyName, accessLevelPropertyName) => ({ + accessLevel, + ...otherProperties +}) => { + const accessLevelProperty = !isUndefined(accessLevel) + ? { [accessLevelPropertyName]: accessLevel } + : {}; + + return { + [basePropertyName]: { + ...accessLevelProperty, + ...otherProperties, + }, + }; +}; + +export const groupLinkRequestFormatter = baseRequestFormatter( + GROUP_LINK_BASE_PROPERTY_NAME, + GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME, +); |