note_header.vue 5.9 KB
Newer Older
1
<script>
F
Fatih Acet 已提交
2
import { mapActions } from 'vuex';
3
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
4 5
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import GitlabTeamMemberBadge from '~/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue';
6

F
Fatih Acet 已提交
7 8 9
export default {
  components: {
    timeAgoTooltip,
10
    GitlabTeamMemberBadge,
11 12 13 14
    GlIcon,
  },
  directives: {
    GlTooltip: GlTooltipDirective,
F
Fatih Acet 已提交
15 16 17 18
  },
  props: {
    author: {
      type: Object,
19 20
      required: false,
      default: () => ({}),
F
Filipa Lacerda 已提交
21
    },
F
Fatih Acet 已提交
22 23
    createdAt: {
      type: String,
24 25
      required: false,
      default: null,
26
    },
F
Fatih Acet 已提交
27 28 29 30
    actionText: {
      type: String,
      required: false,
      default: '',
31
    },
F
Fatih Acet 已提交
32
    noteId: {
33 34 35
      type: [String, Number],
      required: false,
      default: null,
F
Fatih Acet 已提交
36 37 38 39 40 41 42 43 44 45 46
    },
    includeToggle: {
      type: Boolean,
      required: false,
      default: false,
    },
    expanded: {
      type: Boolean,
      required: false,
      default: true,
    },
47 48 49 50 51
    showSpinner: {
      type: Boolean,
      required: false,
      default: true,
    },
52 53 54 55 56
    isConfidential: {
      type: Boolean,
      required: false,
      default: false,
    },
F
Fatih Acet 已提交
57
  },
58 59 60 61 62 63 64
  data() {
    return {
      isUsernameLinkHovered: false,
      emojiTitle: '',
      authorStatusHasTooltip: false,
    };
  },
F
Fatih Acet 已提交
65 66 67 68 69
  computed: {
    toggleChevronClass() {
      return this.expanded ? 'fa-chevron-up' : 'fa-chevron-down';
    },
    noteTimestampLink() {
70
      return this.noteId ? `#note_${this.noteId}` : undefined;
F
Fatih Acet 已提交
71
    },
F
Fatih Acet 已提交
72 73 74
    hasAuthor() {
      return this.author && Object.keys(this.author).length;
    },
75 76 77
    showGitlabTeamMemberBadge() {
      return this.author?.is_gitlab_employee;
    },
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    authorLinkClasses() {
      return {
        hover: this.isUsernameLinkHovered,
        'text-underline': this.isUsernameLinkHovered,
        'author-name-link': true,
        'js-user-link': true,
      };
    },
    authorStatus() {
      return this.author.status_tooltip_html;
    },
    emojiElement() {
      return this.$refs?.authorStatus?.querySelector('gl-emoji');
    },
  },
  mounted() {
    this.emojiTitle = this.emojiElement ? this.emojiElement.getAttribute('title') : '';

    const authorStatusTitle = this.$refs?.authorStatus
      ?.querySelector('.user-status-emoji')
      ?.getAttribute('title');
    this.authorStatusHasTooltip = authorStatusTitle && authorStatusTitle !== '';
F
Fatih Acet 已提交
100 101 102 103 104 105 106
  },
  methods: {
    ...mapActions(['setTargetNoteHash']),
    handleToggle() {
      this.$emit('toggleHandler');
    },
    updateTargetNoteHash() {
107 108 109
      if (this.$store) {
        this.setTargetNoteHash(this.noteTimestampLink);
      }
F
Fatih Acet 已提交
110
    },
111 112 113 114 115 116 117 118 119 120 121 122 123 124
    removeEmojiTitle() {
      this.emojiElement.removeAttribute('title');
    },
    addEmojiTitle() {
      this.emojiElement.setAttribute('title', this.emojiTitle);
    },
    handleUsernameMouseEnter() {
      this.$refs.authorNameLink.dispatchEvent(new Event('mouseenter'));
      this.isUsernameLinkHovered = true;
    },
    handleUsernameMouseLeave() {
      this.$refs.authorNameLink.dispatchEvent(new Event('mouseleave'));
      this.isUsernameLinkHovered = false;
    },
F
Fatih Acet 已提交
125 126
  },
};
127 128 129 130
</script>

<template>
  <div class="note-header-info">
131
    <div v-if="includeToggle" ref="discussionActions" class="discussion-actions">
132 133
      <button
        class="note-action-button discussion-toggle-button js-vue-toggle-button"
134
        type="button"
M
Mike Greiling 已提交
135 136
        @click="handleToggle"
      >
137
        <i ref="chevronIcon" :class="toggleChevronClass" class="fa" aria-hidden="true"></i>
138
        {{ __('Toggle thread') }}
139 140
      </button>
    </div>
141 142
    <template v-if="hasAuthor">
      <a
143
        ref="authorNameLink"
144
        :href="author.path"
145
        :class="authorLinkClasses"
146 147 148 149 150 151
        :data-user-id="author.id"
        :data-username="author.username"
      >
        <slot name="note-header-info"></slot>
        <span class="note-header-author-name bold">{{ author.name }}</span>
      </a>
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
      <span
        v-if="authorStatus"
        ref="authorStatus"
        v-on="
          authorStatusHasTooltip ? { mouseenter: removeEmojiTitle, mouseleave: addEmojiTitle } : {}
        "
        v-html="authorStatus"
      ></span>
      <span class="text-nowrap author-username">
        <a
          ref="authorUsernameLink"
          class="author-username-link"
          :href="author.path"
          @mouseenter="handleUsernameMouseEnter"
          @mouseleave="handleUsernameMouseLeave"
          ><span class="note-headline-light">@{{ author.username }}</span>
        </a>
        <gitlab-team-member-badge v-if="showGitlabTeamMemberBadge" />
      </span>
171
    </template>
172
    <span v-else>{{ __('A deleted user') }}</span>
173
    <span class="note-headline-light note-headline-meta d-inline-flex align-items-center">
174 175
      <span class="system-note-message"> <slot></slot> </span>
      <template v-if="createdAt">
176
        <span ref="actionText" class="system-note-separator">
177 178 179
          <template v-if="actionText">{{ actionText }}</template>
        </span>
        <a
180 181
          v-if="noteTimestampLink"
          ref="noteTimestampLink"
182 183 184 185 186 187
          :href="noteTimestampLink"
          class="note-timestamp system-note-separator"
          @click="updateTargetNoteHash"
        >
          <time-ago-tooltip :time="createdAt" tooltip-placement="bottom" />
        </a>
188
        <time-ago-tooltip v-else ref="noteTimestamp" :time="createdAt" tooltip-placement="bottom" />
189
      </template>
190 191 192 193 194 195 196 197 198
      <gl-icon
        v-if="isConfidential"
        ref="confidentialIndicator"
        v-gl-tooltip:tooltipcontainer.bottom
        name="eye-slash"
        :size="14"
        :title="__('Private comments are accessible by internal staff only')"
        class="ml-1 gl-text-gray-800"
      />
199
      <slot name="extra-controls"></slot>
200
      <i
201 202
        v-if="showSpinner"
        ref="spinner"
203
        class="fa fa-spinner fa-spin editing-spinner"
204
        :aria-label="__('Comment is being updated')"
205 206
        aria-hidden="true"
      ></i>
207 208 209
    </span>
  </div>
</template>