diff options
Diffstat (limited to 'app/assets/javascripts/sidebar/components/reviewers')
4 files changed, 80 insertions, 66 deletions
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue index b1b04564a62..87780888c2f 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue @@ -76,8 +76,8 @@ export default { class="d-inline-block" > <!-- use d-flex so that slot can be appropriately styled --> - <span class="d-flex"> - <reviewer-avatar :user="user" :img-size="32" :issuable-type="issuableType" /> + <span class="gl-display-flex gl-align-items-center"> + <reviewer-avatar :user="user" :img-size="24" :issuable-type="issuableType" /> <slot :user="user"></slot> </span> </gl-link> diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue index cd62fe5be0f..2c52d7142f7 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue @@ -46,6 +46,9 @@ export default { assignSelf() { this.$emit('assign-self'); }, + requestReview(data) { + this.$emit('request-review', data); + }, }, }; </script> @@ -56,7 +59,7 @@ export default { <div class="value hide-collapsed"> <template v-if="hasNoUsers"> - <span class="assign-yourself no-value qa-assign-yourself"> + <span class="assign-yourself no-value"> {{ __('None') }} </span> </template> @@ -66,6 +69,7 @@ export default { :users="sortedReviewers" :root-path="rootPath" :issuable-type="issuableType" + @request-review="requestReview" /> </div> </div> diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue index 1a2473e5f6c..b5cf5df4957 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue @@ -1,14 +1,14 @@ <script> // NOTE! For the first iteration, we are simply copying the implementation of Assignees // It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736 -import { deprecatedCreateFlash as Flash } from '~/flash'; import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; +import { deprecatedCreateFlash as Flash } from '~/flash'; +import { __ } from '~/locale'; import eventHub from '~/sidebar/event_hub'; import Store from '~/sidebar/stores/sidebar_store'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import ReviewerTitle from './reviewer_title.vue'; import Reviewers from './reviewers.vue'; -import { __ } from '~/locale'; export default { name: 'SidebarReviewers', @@ -83,6 +83,9 @@ export default { return new Flash(__('Error occurred when saving reviewers')); }); }, + requestReview(data) { + this.mediator.requestReview(data); + }, }, }; </script> @@ -101,6 +104,7 @@ export default { :editable="store.editable" :issuable-type="issuableType" class="value" + @request-review="requestReview" /> </div> </template> diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue index e82a271d007..cbd68f2513a 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue @@ -1,15 +1,19 @@ <script> -// NOTE! For the first iteration, we are simply copying the implementation of Assignees -// It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736 -import { __, sprintf } from '~/locale'; +import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import ReviewerAvatarLink from './reviewer_avatar_link.vue'; -const DEFAULT_RENDER_COUNT = 5; +const LOADING_STATE = 'loading'; +const SUCCESS_STATE = 'success'; export default { components: { + GlButton, + GlIcon, ReviewerAvatarLink, }, + directives: { + GlTooltip: GlTooltipDirective, + }, props: { users: { type: Array, @@ -28,76 +32,78 @@ export default { data() { return { showLess: true, + loadingStates: {}, }; }, - computed: { - firstUser() { - return this.users[0]; - }, - hasOneUser() { - return this.users.length === 1; - }, - hiddenReviewersLabel() { - const { numberOfHiddenReviewers } = this; - return sprintf(__('+ %{numberOfHiddenReviewers} more'), { numberOfHiddenReviewers }); - }, - renderShowMoreSection() { - return this.users.length > DEFAULT_RENDER_COUNT; - }, - numberOfHiddenReviewers() { - return this.users.length - DEFAULT_RENDER_COUNT; - }, - uncollapsedUsers() { - const uncollapsedLength = this.showLess - ? Math.min(this.users.length, DEFAULT_RENDER_COUNT) - : this.users.length; - return this.showLess ? this.users.slice(0, uncollapsedLength) : this.users; - }, - username() { - return `@${this.firstUser.username}`; + watch: { + users: { + handler(users) { + this.loadingStates = users.reduce( + (acc, user) => ({ + ...acc, + [user.id]: acc[user.id] || null, + }), + this.loadingStates, + ); + }, + immediate: true, }, }, methods: { toggleShowLess() { this.showLess = !this.showLess; }, + reRequestReview(userId) { + this.loadingStates[userId] = LOADING_STATE; + this.$emit('request-review', { userId, callback: this.requestReviewComplete }); + }, + requestReviewComplete(userId, success) { + if (success) { + this.loadingStates[userId] = SUCCESS_STATE; + + setTimeout(() => { + this.loadingStates[userId] = null; + }, 1500); + } else { + this.loadingStates[userId] = null; + } + }, }, + LOADING_STATE, + SUCCESS_STATE, }; </script> <template> - <reviewer-avatar-link - v-if="hasOneUser" - #default="{ user }" - tooltip-placement="left" - :tooltip-has-name="false" - :user="firstUser" - :root-path="rootPath" - :issuable-type="issuableType" - > - <div class="gl-ml-3 gl-line-height-normal"> - <div class="author">{{ user.name }}</div> - <div class="username">{{ username }}</div> - </div> - </reviewer-avatar-link> - <div v-else> - <div class="user-list"> - <div v-for="user in uncollapsedUsers" :key="user.id" class="user-item"> - <reviewer-avatar-link :user="user" :root-path="rootPath" :issuable-type="issuableType" /> - </div> - </div> - <div v-if="renderShowMoreSection" class="user-list-more"> - <button - type="button" - class="btn-link" - data-qa-selector="more_reviewers_link" - @click="toggleShowLess" - > - <template v-if="showLess"> - {{ hiddenReviewersLabel }} - </template> - <template v-else>{{ __('- show less') }}</template> - </button> + <div> + <div + v-for="(user, index) in users" + :key="user.id" + :class="{ 'gl-mb-3': index !== users.length - 1 }" + data-testid="reviewer" + > + <reviewer-avatar-link :user="user" :root-path="rootPath" :issuable-type="issuableType"> + <div class="gl-ml-3">@{{ user.username }}</div> + </reviewer-avatar-link> + <gl-icon + v-if="loadingStates[user.id] === $options.SUCCESS_STATE" + :size="24" + name="check" + class="float-right gl-text-green-500" + data-testid="re-request-success" + /> + <gl-button + v-else-if="user.can_update_merge_request && user.reviewed" + v-gl-tooltip.left + :title="__('Re-request review')" + :loading="loadingStates[user.id] === $options.LOADING_STATE" + class="float-right gl-text-gray-500!" + size="small" + icon="redo" + variant="link" + data-testid="re-request-button" + @click="reRequestReview(user.id)" + /> </div> </div> </template> |