summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
blob: 5b4a43399caa08ad4489c268f85b3cc2cedbebfe (plain)
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
110
111
112
113
114
115
116
117
118
119
120
121
<script>
import { __, sprintf } from '~/locale';
import { GlTooltipDirective } from '@gitlab/ui';
import CollapsedAssignee from './collapsed_assignee.vue';

const DEFAULT_MAX_COUNTER = 99;
const DEFAULT_RENDER_COUNT = 5;

export default {
  directives: {
    GlTooltip: GlTooltipDirective,
  },
  components: {
    CollapsedAssignee,
  },
  props: {
    users: {
      type: Array,
      required: true,
    },
    issuableType: {
      type: String,
      required: false,
      default: 'issue',
    },
  },
  computed: {
    isMergeRequest() {
      return this.issuableType === 'merge_request';
    },
    hasNoUsers() {
      return !this.users.length;
    },
    hasMoreThanOneAssignee() {
      return this.users.length > 1;
    },
    hasMoreThanTwoAssignees() {
      return this.users.length > 2;
    },
    allAssigneesCanMerge() {
      return this.users.every(user => user.can_merge);
    },
    sidebarAvatarCounter() {
      if (this.users.length > DEFAULT_MAX_COUNTER) {
        return `${DEFAULT_MAX_COUNTER}+`;
      }

      return `+${this.users.length - 1}`;
    },
    collapsedUsers() {
      const collapsedLength = this.hasMoreThanTwoAssignees ? 1 : this.users.length;

      return this.users.slice(0, collapsedLength);
    },
    tooltipTitleMergeStatus() {
      if (!this.isMergeRequest) {
        return '';
      }

      const mergeLength = this.users.filter(u => u.can_merge).length;

      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 __('Assignee(s)');
      }

      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': hasMoreThanOneAssignee }"
    :title="tooltipTitle"
    class="sidebar-collapsed-icon sidebar-collapsed-user"
  >
    <i v-if="hasNoUsers" :aria-label="__('None')" class="fa fa-user"> </i>
    <collapsed-assignee
      v-for="user in collapsedUsers"
      :key="user.id"
      :user="user"
      :issuable-type="issuableType"
    />
    <button v-if="hasMoreThanTwoAssignees" class="btn-link" type="button">
      <span class="avatar-counter sidebar-avatar-counter"> {{ sidebarAvatarCounter }} </span>
      <i
        v-if="isMergeRequest && !allAssigneesCanMerge"
        aria-hidden="true"
        class="fa fa-exclamation-triangle merge-icon"
      ></i>
    </button>
  </div>
</template>