summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/invite_members/components/invite_members_modal.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/invite_members/components/invite_members_modal.vue')
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue79
1 files changed, 57 insertions, 22 deletions
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index 84c8594c6b6..4aab1123af9 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -1,5 +1,6 @@
<script>
import {
+ GlFormGroup,
GlModal,
GlDropdown,
GlDropdownItem,
@@ -12,16 +13,21 @@ import {
import { partition, isString } from 'lodash';
import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
-import GroupSelect from '~/invite_members/components/group_select.vue';
-import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { s__, sprintf } from '~/locale';
import { INVITE_MEMBERS_IN_COMMENT, GROUP_FILTERS } from '../constants';
import eventHub from '../event_hub';
+import {
+ responseMessageFromError,
+ responseMessageFromSuccess,
+} from '../utils/response_message_parser';
+import GroupSelect from './group_select.vue';
+import MembersTokenSelect from './members_token_select.vue';
export default {
name: 'InviteMembersModal',
components: {
+ GlFormGroup,
GlDatepicker,
GlLink,
GlModal,
@@ -79,9 +85,13 @@ export default {
selectedDate: undefined,
groupToBeSharedWith: {},
source: 'unknown',
+ invalidFeedbackMessage: '',
};
},
computed: {
+ validationState() {
+ return this.invalidFeedbackMessage === '' ? null : false;
+ },
isInviteGroup() {
return this.inviteeType === 'group';
},
@@ -142,6 +152,7 @@ export default {
this.$root.$emit(BV_SHOW_MODAL, this.modalId);
},
closeModal() {
+ this.resetFields();
this.$root.$emit(BV_HIDE_MODAL, this.modalId);
},
sendInvite() {
@@ -150,7 +161,6 @@ export default {
} else {
this.submitInviteMembers();
}
- this.closeModal();
},
trackInvite() {
if (this.source === INVITE_MEMBERS_IN_COMMENT) {
@@ -158,12 +168,12 @@ export default {
tracking.event('comment_invite_success');
}
},
- cancelInvite() {
+ resetFields() {
this.selectedAccessLevel = this.defaultAccessLevel;
this.selectedDate = undefined;
this.newUsersToInvite = [];
this.groupToBeSharedWith = {};
- this.closeModal();
+ this.invalidFeedbackMessage = '';
},
changeSelectedItem(item) {
this.selectedAccessLevel = item;
@@ -175,9 +185,11 @@ export default {
apiShareWithGroup(this.id, this.shareWithGroupPostData(this.groupToBeSharedWith.id))
.then(this.showToastMessageSuccess)
- .catch(this.showToastMessageError);
+ .catch(this.showInvalidFeedbackMessage);
},
submitInviteMembers() {
+ this.invalidFeedbackMessage = '';
+
const [usersToInviteByEmail, usersToAddById] = this.partitionNewUsersToInvite();
const promises = [];
@@ -196,10 +208,11 @@ export default {
promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
}
-
this.trackInvite();
- Promise.all(promises).then(this.showToastMessageSuccess).catch(this.showToastMessageError);
+ Promise.all(promises)
+ .then(this.conditionallyShowToastSuccess)
+ .catch(this.showInvalidFeedbackMessage);
},
inviteByEmailPostData(usersToInviteByEmail) {
return {
@@ -224,13 +237,27 @@ export default {
group_access: this.selectedAccessLevel,
};
},
+ conditionallyShowToastSuccess(response) {
+ const message = responseMessageFromSuccess(response);
+
+ if (message === '') {
+ this.showToastMessageSuccess();
+
+ return;
+ }
+
+ this.invalidFeedbackMessage = message;
+ },
showToastMessageSuccess() {
this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
+ this.closeModal();
},
- showToastMessageError(error) {
- const message = error.response.data.message || this.$options.labels.toastMessageUnsuccessful;
-
- this.$toast.show(message, this.toastOptions);
+ showInvalidFeedbackMessage(response) {
+ this.invalidFeedbackMessage =
+ responseMessageFromError(response) || this.$options.labels.invalidFeedbackMessageDefault;
+ },
+ handleMembersTokenSelectClear() {
+ this.invalidFeedbackMessage = '';
},
},
labels: {
@@ -267,8 +294,8 @@ export default {
accessLevel: s__('InviteMembersModal|Select a role'),
accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
- toastMessageUnsuccessful: s__('InviteMembersModal|Some of the members could not be added'),
- readMoreText: s__(`InviteMembersModal|%{linkStart}Learn more%{linkEnd} about roles.`),
+ invalidFeedbackMessageDefault: s__('InviteMembersModal|Something went wrong'),
+ readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
inviteButtonText: s__('InviteMembersModal|Invite'),
cancelButtonText: s__('InviteMembersModal|Cancel'),
headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
@@ -283,6 +310,7 @@ export default {
data-qa-selector="invite_members_modal_content"
:title="$options.labels[inviteeType].modalTitle"
:header-close-label="$options.labels.headerCloseLabel"
+ @close="resetFields"
>
<div>
<p ref="introText">
@@ -293,15 +321,22 @@ export default {
</gl-sprintf>
</p>
- <label :id="$options.membersTokenSelectLabelId" class="gl-font-weight-bold gl-mt-5">{{
- $options.labels[inviteeType].searchField
- }}</label>
- <div class="gl-mt-2">
+ <gl-form-group
+ class="gl-mt-2"
+ :invalid-feedback="invalidFeedbackMessage"
+ :state="validationState"
+ :description="$options.labels[inviteeType].placeHolder"
+ data-testid="members-form-group"
+ >
+ <label :id="$options.membersTokenSelectLabelId" class="col-form-label">{{
+ $options.labels[inviteeType].searchField
+ }}</label>
<members-token-select
v-if="!isInviteGroup"
v-model="newUsersToInvite"
+ :validation-state="validationState"
:aria-labelledby="$options.membersTokenSelectLabelId"
- :placeholder="$options.labels[inviteeType].placeHolder"
+ @clear="handleMembersTokenSelectClear"
/>
<group-select
v-if="isInviteGroup"
@@ -309,7 +344,7 @@ export default {
:groups-filter="groupSelectFilter"
:parent-group-id="groupSelectParentId"
/>
- </div>
+ </gl-form-group>
<label class="gl-font-weight-bold gl-mt-3">{{ $options.labels.accessLevel }}</label>
<div class="gl-mt-2 gl-w-half gl-xs-w-full">
@@ -364,15 +399,15 @@ export default {
<template #modal-footer>
<div class="gl-display-flex gl-flex-direction-row gl-justify-content-end gl-flex-wrap gl-m-0">
- <gl-button ref="cancelButton" @click="cancelInvite">
+ <gl-button data-testid="cancel-button" @click="closeModal">
{{ $options.labels.cancelButtonText }}
</gl-button>
<div class="gl-mr-3"></div>
<gl-button
- ref="inviteButton"
:disabled="inviteDisabled"
variant="success"
data-qa-selector="invite_button"
+ data-testid="invite-button"
@click="sendInvite"
>{{ $options.labels.inviteButtonText }}</gl-button
>