diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-11-14 11:41:52 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-11-14 11:41:52 +0300 |
commit | 585826cb22ecea5998a2c2a4675735c94bdeedac (patch) | |
tree | 5b05f0b30d33cef48963609e8a18a4dff260eab3 /app/assets/javascripts/invite_members | |
parent | df221d036e5d0c6c0ee4d55b9c97f481ee05dee8 (diff) |
Add latest changes from gitlab-org/gitlab@16-6-stable-eev16.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/invite_members')
7 files changed, 93 insertions, 19 deletions
diff --git a/app/assets/javascripts/invite_members/components/invite_groups_modal.vue b/app/assets/javascripts/invite_members/components/invite_groups_modal.vue index 4b492e48095..ceb9200dfad 100644 --- a/app/assets/javascripts/invite_members/components/invite_groups_modal.vue +++ b/app/assets/javascripts/invite_members/components/invite_groups_modal.vue @@ -1,7 +1,7 @@ <script> -import * as Sentry from '@sentry/browser'; import { GlAlert } from '@gitlab/ui'; import { uniqueId } from 'lodash'; +import * as Sentry from '~/sentry/sentry_browser_wrapper'; import Api from '~/api'; import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants'; import InviteModalBase from 'ee_else_ce/invite_members/components/invite_modal_base.vue'; 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 509efd31dcd..1a10130e969 100644 --- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue +++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue @@ -1,13 +1,17 @@ <script> -import { GlAlert, GlButton, GlCollapse, GlIcon } from '@gitlab/ui'; +import { GlAlert, GlButton, GlCollapse, GlLink, GlIcon, GlSprintf } from '@gitlab/ui'; import { partition, isString, uniqueId, isEmpty } from 'lodash'; import SafeHtml from '~/vue_shared/directives/safe_html'; import InviteModalBase from 'ee_else_ce/invite_members/components/invite_modal_base.vue'; import Api from '~/api'; import Tracking from '~/tracking'; import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants'; -import { n__, sprintf } from '~/locale'; -import { memberName, triggerExternalAlert } from 'ee_else_ce/invite_members/utils/member_utils'; +import { n__, s__, sprintf } from '~/locale'; +import { + memberName, + triggerExternalAlert, + inviteMembersTrackingOptions, +} from 'ee_else_ce/invite_members/utils/member_utils'; import { captureException } from '~/ci/runner/sentry_utils'; import { USERS_FILTER_ALL, @@ -31,7 +35,9 @@ export default { GlAlert, GlButton, GlCollapse, + GlLink, GlIcon, + GlSprintf, InviteModalBase, MembersTokenSelect, ModalConfetti, @@ -43,6 +49,17 @@ export default { SafeHtml, }, mixins: [Tracking.mixin({ category: INVITE_MEMBER_MODAL_TRACKING_CATEGORY })], + inject: { + isCurrentUserAdmin: { + default: false, + }, + isEmailSignupEnabled: { + default: true, + }, + newUsersUrl: { + default: '', + }, + }, props: { id: { type: String, @@ -122,6 +139,12 @@ export default { isCelebration() { return this.mode === 'celebrate'; }, + baseTrackingDetails() { + return { label: this.source, celebrate: this.isCelebration }; + }, + isTextForAdmin() { + return this.isCurrentUserAdmin && Boolean(this.newUsersUrl); + }, modalTitle() { return this.$options.labels.modal[this.mode].title; }, @@ -131,6 +154,11 @@ export default { labelIntroText() { return this.$options.labels[this.inviteTo][this.mode].introText; }, + labelSearchField() { + return this.isEmailSignupEnabled + ? this.$options.labels.searchField + : s__('InviteMembersModal|Username'); + }, isEmptyInvites() { return Boolean(this.newUsersToInvite.length); }, @@ -144,6 +172,14 @@ export default { this.errorList.length, ); }, + signupDisabledText() { + return s__( + "InviteMembersModal|Administrators can %{linkStart}add new users by email manually%{linkEnd}. After they've been added, you can invite them to this group with their username.", + ); + }, + signupDisabledTitle() { + return s__('InviteMembersModal|Inviting users by email is disabled'); + }, showUserLimitNotification() { return !isEmpty(this.usersLimitDataset.alertVariant); }, @@ -173,8 +209,13 @@ export default { count: this.errorsExpanded.length, }); }, + formGroupDescriptionText() { + return this.isEmailSignupEnabled + ? this.$options.labels.placeHolder + : s__('InviteMembersModal|Select members'); + }, formGroupDescription() { - return this.invalidFeedbackMessage ? null : this.$options.labels.placeHolder; + return this.invalidFeedbackMessage ? null : this.formGroupDescriptionText; }, }, watch: { @@ -218,13 +259,13 @@ export default { this.source = source; this.$root.$emit(BV_SHOW_MODAL, this.modalId); - this.track('render', { label: this.source }); + this.track('render', inviteMembersTrackingOptions(this.baseTrackingDetails)); }, closeModal() { this.$root.$emit(BV_HIDE_MODAL, this.modalId); }, showEmptyInvitesAlert() { - this.invalidFeedbackMessage = this.$options.labels.placeHolder; + this.invalidFeedbackMessage = this.formGroupDescriptionText; this.shouldShowEmptyInvitesAlert = true; this.$refs.alerts.focus(); }, @@ -287,10 +328,10 @@ export default { return this.newUsersToInvite.find((member) => memberName(member) === username)?.name; }, onCancel() { - this.track('click_cancel', { label: this.source }); + this.track('click_cancel', inviteMembersTrackingOptions(this.baseTrackingDetails)); }, onClose() { - this.track('click_x', { label: this.source }); + this.track('click_x', inviteMembersTrackingOptions(this.baseTrackingDetails)); }, resetFields() { this.clearValidation(); @@ -299,7 +340,7 @@ export default { this.newUsersToInvite = []; }, onInviteSuccess() { - this.track('invite_successful', { label: this.source }); + this.track('invite_successful', inviteMembersTrackingOptions(this.baseTrackingDetails)); if (this.reloadPageOnSubmit) { reloadOnInvitationSuccess(); @@ -345,7 +386,7 @@ export default { :default-access-level="defaultAccessLevel" :help-link="helpLink" :label-intro-text="labelIntroText" - :label-search-field="$options.labels.searchField" + :label-search-field="labelSearchField" :form-group-description="formGroupDescription" :invalid-feedback-message="invalidFeedbackMessage" :is-loading="isLoading" @@ -429,6 +470,24 @@ export default { </gl-button> </template> </gl-alert> + <gl-alert + v-if="!isEmailSignupEnabled" + id="signup-disabled-alert" + :dismissible="false" + :title="signupDisabledTitle" + class="gl-mb-4" + variant="warning" + data-testid="email-signup-disabled-alert" + > + <gl-sprintf :message="signupDisabledText"> + <template #link="{ content }"> + <gl-link v-if="isTextForAdmin" :href="newUsersUrl" target="_blank">{{ + content + }}</gl-link> + <span v-else>{{ content }}</span> + </template> + </gl-sprintf> + </gl-alert> <user-limit-notification v-else-if="showUserLimitNotification" class="gl-mb-5" @@ -447,6 +506,7 @@ export default { v-model="newUsersToInvite" class="gl-mb-2" aria-labelledby="empty-invites-alert" + :can-use-email-token="isEmailSignupEnabled" :input-id="inputId" :exception-state="exceptionState" :users-filter="usersFilter" diff --git a/app/assets/javascripts/invite_members/components/invite_modal_base.vue b/app/assets/javascripts/invite_members/components/invite_modal_base.vue index 18d22395104..a14dcd38aa7 100644 --- a/app/assets/javascripts/invite_members/components/invite_modal_base.vue +++ b/app/assets/javascripts/invite_members/components/invite_modal_base.vue @@ -297,7 +297,7 @@ export default { </gl-form-group> <gl-form-group - class="gl-w-half gl-xs-w-full" + class="gl-sm-w-half gl-w-full" :label="$options.ACCESS_LEVEL" :label-for="dropdownId" > @@ -317,7 +317,7 @@ export default { </gl-form-group> <gl-form-group - class="gl-w-half gl-xs-w-full" + class="gl-sm-w-half gl-w-full" :label="$options.ACCESS_EXPIRE_DATE" :label-for="datepickerId" > @@ -338,10 +338,10 @@ export default { <template #modal-footer> <div - class="gl-m-0 gl-xs-w-full gl-display-flex gl-xs-flex-direction-column! gl-flex-direction-row-reverse" + class="gl-m-0 gl-w-full gl-display-flex gl-xs-flex-direction-column! gl-flex-direction-row-reverse" > <gl-button - class="gl-xs-w-full gl-xs-mb-3! gl-sm-ml-3!" + class="gl-w-full gl-sm-w-auto gl-xs-mb-3! gl-sm-ml-3!" data-testid="invite-modal-submit" v-bind="actionPrimary.attributes" @click="onSubmit" @@ -350,7 +350,7 @@ export default { </gl-button> <gl-button - class="gl-xs-w-full" + class="gl-w-full gl-sm-w-auto" data-testid="invite-modal-cancel" v-bind="actionCancel.attributes" @click="onCancel" diff --git a/app/assets/javascripts/invite_members/components/members_token_select.vue b/app/assets/javascripts/invite_members/components/members_token_select.vue index 8493787f075..0be04b7af35 100644 --- a/app/assets/javascripts/invite_members/components/members_token_select.vue +++ b/app/assets/javascripts/invite_members/components/members_token_select.vue @@ -21,6 +21,11 @@ export default { GlSprintf, }, props: { + canUseEmailToken: { + type: Boolean, + required: false, + default: true, + }, placeholder: { type: String, required: false, @@ -68,6 +73,10 @@ export default { }, computed: { emailIsValid() { + if (!this.canUseEmailToken) { + return false; + } + const regex = /^\S+@\S+$/; return this.originalInput.match(regex) !== null; @@ -137,9 +146,8 @@ export default { username: token.username, avatar_url: token.avatar_url, })); - this.loading = false; }) - .catch(() => { + .finally(() => { this.loading = false; }); }, SEARCH_DELAY), diff --git a/app/assets/javascripts/invite_members/components/project_select.vue b/app/assets/javascripts/invite_members/components/project_select.vue index 640df5cdb88..6c2f53afe3c 100644 --- a/app/assets/javascripts/invite_members/components/project_select.vue +++ b/app/assets/javascripts/invite_members/components/project_select.vue @@ -115,7 +115,6 @@ export default { :search-placeholder="$options.i18n.searchPlaceholder" :no-results-text="$options.i18n.emptySearchResult" data-testid="project-select-dropdown" - data-qa-selector="project_select_dropdown" class="gl-collapsible-listbox-w-full" @search="searchTerm = $event" @select="selectProject" diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js index 41ed0179364..8dfe697e2cb 100644 --- a/app/assets/javascripts/invite_members/init_invite_members_modal.js +++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js @@ -25,6 +25,9 @@ export default (function initInviteMembersModal() { name: 'InviteMembersModalRoot', provide: { name: el.dataset.name, + newUsersUrl: el.dataset.newUsersUrl, + isCurrentUserAdmin: parseBoolean(el.dataset.isCurrentUserAdmin), + isEmailSignupEnabled: parseBoolean(el.dataset.isSignupEnabled), }, render: (createElement) => createElement(InviteMembersModal, { diff --git a/app/assets/javascripts/invite_members/utils/member_utils.js b/app/assets/javascripts/invite_members/utils/member_utils.js index 7998cb69445..52fb5e98f27 100644 --- a/app/assets/javascripts/invite_members/utils/member_utils.js +++ b/app/assets/javascripts/invite_members/utils/member_utils.js @@ -6,3 +6,7 @@ export function memberName(member) { export function triggerExternalAlert() { return false; } + +export function inviteMembersTrackingOptions(options) { + return { label: options.label }; +} |