All files / app/assets/javascripts/sidebar/components/reviewers collapsed_reviewer_list.vue

90.32% Statements 28/31
77.78% Branches 14/18
100% Functions 13/13
90.32% Lines 28/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109      1x 1x 1x   1x 1x                                   8x     8x     8x     11x     4x       4x     8x   8x     24x   7x   7x 3x           4x     8x 8x 25x   8x 1x     7x       7x   7x       8x           36x                                        
<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 { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import CollapsedReviewer from './collapsed_reviewer.vue';
 
const DEFAULT_MAX_COUNTER = 99;
const DEFAULT_RENDER_COUNT = 5;
 
export default {
  directives: {
    GlTooltip: GlTooltipDirective,
  },
  components: {
    CollapsedReviewer,
    GlIcon,
  },
  props: {
    users: {
      type: Array,
      required: true,
    },
  },
  computed: {
    hasNoUsers() {
      return !this.users.length;
    },
    hasMoreThanOneReviewer() {
      return this.users.length > 1;
    },
    hasMoreThanTwoReviewers() {
      return this.users.length > 2;
    },
    allReviewersCanMerge() {
      return this.users.every((user) => user.can_merge);
    },
    sidebarAvatarCounter() {
I      if (this.users.length > DEFAULT_MAX_COUNTER) {
        return `${DEFAULT_MAX_COUNTER}+`;
      }
 
      return `+${this.users.length - 1}`;
    },
    collapsedUsers() {
      const collapsedLength = this.hasMoreThanTwoReviewers ? 1 : this.users.length;
 
      return this.users.slice(0, collapsedLength);
    },
    tooltipTitleMergeStatus() {
      const mergeLength = this.users.filter((u) => u.can_merge).length;
 
I      if (mergeLength === this.users.length) {
        return '';
      } else if (mergeLength > 0) {
        return sprintf(__('%{mergeLength}/%{usersLength} can merge'), {
          mergeLength,
          usersLength: this.users.length,
        });
      }
 
      return this.users.length === 1 ? __('cannot merge') : __('no one can merge');
    },
    tooltipTitle() {
      const maxRender = Math.min(DEFAULT_RENDER_COUNT, this.users.length);
      const renderUsers = this.users.slice(0, maxRender);
      const names = renderUsers.map((u) => u.name);
 
      if (!this.users.length) {
        return __('Reviewer(s)');
      }
 
I      if (this.users.length > names.length) {
        names.push(sprintf(__('+ %{amount} more'), { amount: this.users.length - names.length }));
      }
 
      const text = names.join(', ');
 
      return this.tooltipTitleMergeStatus ? `${text} (${this.tooltipTitleMergeStatus})` : text;
    },
 
    tooltipOptions() {
      return { container: 'body', placement: 'left', boundary: 'viewport' };
    },
  },
};
</script>
 
<template>
  <div
    v-gl-tooltip="tooltipOptions"
    :class="{ 'multiple-users gl-relative': hasMoreThanOneReviewer }"
    :title="tooltipTitle"
    class="sidebar-collapsed-icon sidebar-collapsed-user"
  >
    <gl-icon v-if="hasNoUsers" name="user" :aria-label="__('None')" />
    <collapsed-reviewer v-for="user in collapsedUsers" :key="user.id" :user="user" />
    <button v-if="hasMoreThanTwoReviewers" class="btn-link" type="button">
      <span class="avatar-counter sidebar-avatar-counter"> {{ sidebarAvatarCounter }} </span>
      <gl-icon
        v-if="!allReviewersCanMerge"
        name="warning-solid"
        aria-hidden="true"
        class="merge-icon"
      />
    </button>
  </div>
</template>