diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-04 12:09:02 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-04 12:09:02 +0300 |
commit | 48640cf76a1ee0cd515e259d8f3eb2de25ba01c3 (patch) | |
tree | 84719b9b1f23a396298b0774ed8920cb401426d6 /app/assets/javascripts/vue_shared/components/user_popover | |
parent | 7d4987ae65374a40ab540ad825da3c33d8bab6df (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/user_popover')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue index 2c09fa71230..01a0b134b7f 100644 --- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue +++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue @@ -6,9 +6,13 @@ import { GlIcon, GlSafeHtmlDirective, GlSprintf, + GlButton, } from '@gitlab/ui'; +import { __ } from '~/locale'; import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue'; import { glEmojiTag } from '~/emoji'; +import createFlash from '~/flash'; +import { followUser, unfollowUser } from '~/rest_api'; import UserAvatarImage from '../user_avatar/user_avatar_image.vue'; const MAX_SKELETON_LINES = 4; @@ -24,6 +28,7 @@ export default { UserAvatarImage, UserNameWithStatus, GlSprintf, + GlButton, }, directives: { SafeHtml: GlSafeHtmlDirective, @@ -44,6 +49,11 @@ export default { default: 'top', }, }, + data() { + return { + toggleFollowLoading: false, + }; + }, computed: { statusHtml() { if (!this.user.status) { @@ -64,6 +74,69 @@ export default { availabilityStatus() { return this.user?.status?.availability || ''; }, + isNotCurrentUser() { + return !this.userIsLoading && this.user.username !== gon.current_username; + }, + shouldRenderToggleFollowButton() { + return ( + /* + * We're using `gon` to access feature flag because this component + * gets initialized dynamically multiple times from `user_popovers.js` + * for each user link present on the page, and using `glFeatureFlagMixin()` + * doesn't inject available feature flags into the component during init. + */ + gon?.features?.followInUserPopover && + this.isNotCurrentUser && + typeof this.user?.isFollowed !== 'undefined' + ); + }, + toggleFollowButtonText() { + if (this.toggleFollowLoading) return null; + + return this.user?.isFollowed ? __('Unfollow') : __('Follow'); + }, + toggleFollowButtonVariant() { + return this.user?.isFollowed ? 'default' : 'confirm'; + }, + }, + methods: { + async toggleFollow() { + if (this.user.isFollowed) { + this.unfollow(); + } else { + this.follow(); + } + }, + async follow() { + this.toggleFollowLoading = true; + try { + await followUser(this.user.id); + this.$emit('follow'); + } catch (error) { + createFlash({ + message: __('An error occurred while trying to follow this user, please try again.'), + error, + captureError: true, + }); + } finally { + this.toggleFollowLoading = false; + } + }, + async unfollow() { + this.toggleFollowLoading = true; + try { + await unfollowUser(this.user.id); + this.$emit('unfollow'); + } catch (error) { + createFlash({ + message: __('An error occurred while trying to unfollow this user, please try again.'), + error, + captureError: true, + }); + } finally { + this.toggleFollowLoading = false; + } + }, }, safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] }, }; @@ -73,10 +146,22 @@ export default { <!-- 200ms delay so not every mouseover triggers Popover --> <gl-popover :target="target" :delay="200" :placement="placement" boundary="viewport"> <div class="gl-p-3 gl-line-height-normal gl-display-flex" data-testid="user-popover"> - <div class="gl-p-2 flex-shrink-1"> + <div + class="gl-p-2 flex-shrink-1 gl-display-flex gl-flex-direction-column align-items-center gl-w-70p" + > <user-avatar-image :img-src="user.avatarUrl" :size="64" css-classes="gl-mr-3!" /> + <div v-if="shouldRenderToggleFollowButton" class="gl-mt-3"> + <gl-button + :variant="toggleFollowButtonVariant" + :loading="toggleFollowLoading" + size="small" + data-testid="toggle-follow-button" + @click="toggleFollow" + >{{ toggleFollowButtonText }}</gl-button + > + </div> </div> - <div class="gl-p-2 gl-w-full gl-min-w-0"> + <div class="gl-w-full gl-min-w-0"> <template v-if="userIsLoading"> <gl-skeleton-loader :lines="$options.maxSkeletonLines" |