2017-06-13 13:01:59 -04:00
|
|
|
<script>
|
2020-06-16 17:08:20 -04:00
|
|
|
import { __ } from '~/locale';
|
2018-03-16 16:16:21 -04:00
|
|
|
import { mapGetters } from 'vuex';
|
2018-11-09 04:44:07 -05:00
|
|
|
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
|
2020-06-01 02:08:21 -04:00
|
|
|
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
|
2019-12-11 07:08:10 -05:00
|
|
|
import Icon from '~/vue_shared/components/icon.vue';
|
2019-02-06 05:31:46 -05:00
|
|
|
import ReplyButton from './note_actions/reply_button.vue';
|
2020-06-16 17:08:20 -04:00
|
|
|
import eventHub from '~/sidebar/event_hub';
|
|
|
|
import Api from '~/api';
|
|
|
|
import flash from '~/flash';
|
2017-06-13 13:01:59 -04:00
|
|
|
|
2018-03-16 16:16:21 -04:00
|
|
|
export default {
|
|
|
|
name: 'NoteActions',
|
2018-10-06 13:16:40 -04:00
|
|
|
components: {
|
|
|
|
Icon,
|
2019-02-06 05:31:46 -05:00
|
|
|
ReplyButton,
|
2018-11-07 05:06:15 -05:00
|
|
|
GlLoadingIcon,
|
2018-10-06 13:16:40 -04:00
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
directives: {
|
2018-11-09 04:44:07 -05:00
|
|
|
GlTooltip: GlTooltipDirective,
|
2018-03-16 16:16:21 -04:00
|
|
|
},
|
2019-05-01 08:58:52 -04:00
|
|
|
mixins: [resolvedStatusMixin],
|
2018-03-16 16:16:21 -04:00
|
|
|
props: {
|
2020-06-16 17:08:20 -04:00
|
|
|
author: {
|
|
|
|
type: Object,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
authorId: {
|
|
|
|
type: Number,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
noteId: {
|
2018-10-06 13:16:40 -04:00
|
|
|
type: [String, Number],
|
2018-03-16 16:16:21 -04:00
|
|
|
required: true,
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
noteUrl: {
|
|
|
|
type: String,
|
2018-09-07 09:39:20 -04:00
|
|
|
required: false,
|
|
|
|
default: '',
|
2018-06-21 08:22:40 -04:00
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
accessLevel: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
|
|
|
reportAbusePath: {
|
|
|
|
type: String,
|
2018-10-06 13:16:40 -04:00
|
|
|
required: false,
|
|
|
|
default: null,
|
2018-03-16 16:16:21 -04:00
|
|
|
},
|
2019-02-06 05:31:46 -05:00
|
|
|
showReply: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
canEdit: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-04-06 14:19:37 -04:00
|
|
|
canAwardEmoji: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
canDelete: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
2018-06-21 08:22:40 -04:00
|
|
|
canResolve: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
resolvable: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
isResolved: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
isResolving: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
|
|
|
resolvedBy: {
|
|
|
|
type: Object,
|
|
|
|
required: false,
|
|
|
|
default: () => ({}),
|
|
|
|
},
|
|
|
|
canReportAsAbuse: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
computed: {
|
2020-06-16 17:08:20 -04:00
|
|
|
...mapGetters(['getUserDataByProp', 'getNoteableData']),
|
2018-03-16 16:16:21 -04:00
|
|
|
shouldShowActionsDropdown() {
|
|
|
|
return this.currentUserId && (this.canEdit || this.canReportAsAbuse);
|
|
|
|
},
|
2018-10-06 13:16:40 -04:00
|
|
|
showDeleteAction() {
|
|
|
|
return this.canDelete && !this.canReportAsAbuse && !this.noteUrl;
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
isAuthoredByCurrentUser() {
|
|
|
|
return this.authorId === this.currentUserId;
|
|
|
|
},
|
|
|
|
currentUserId() {
|
|
|
|
return this.getUserDataByProp('id');
|
|
|
|
},
|
2020-06-16 17:08:20 -04:00
|
|
|
isUserAssigned() {
|
|
|
|
return this.assignees && this.assignees.some(({ id }) => id === this.author.id);
|
|
|
|
},
|
|
|
|
displayAssignUserText() {
|
|
|
|
return this.isUserAssigned
|
|
|
|
? __('Unassign from commenting user')
|
|
|
|
: __('Assign to commenting user');
|
|
|
|
},
|
|
|
|
sidebarAction() {
|
|
|
|
return this.isUserAssigned ? 'sidebar.addAssignee' : 'sidebar.removeAssignee';
|
|
|
|
},
|
|
|
|
targetType() {
|
|
|
|
return this.getNoteableData.targetType;
|
|
|
|
},
|
|
|
|
assignees() {
|
|
|
|
return this.getNoteableData.assignees || [];
|
|
|
|
},
|
|
|
|
isIssue() {
|
|
|
|
return this.targetType === 'issue';
|
|
|
|
},
|
2020-06-30 05:08:37 -04:00
|
|
|
canAssign() {
|
|
|
|
return this.getNoteableData.current_user?.can_update && this.isIssue;
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
onEdit() {
|
|
|
|
this.$emit('handleEdit');
|
|
|
|
},
|
|
|
|
onDelete() {
|
|
|
|
this.$emit('handleDelete');
|
|
|
|
},
|
|
|
|
onResolve() {
|
|
|
|
this.$emit('handleResolve');
|
|
|
|
},
|
2019-01-09 18:46:43 -05:00
|
|
|
closeTooltip() {
|
|
|
|
this.$nextTick(() => {
|
|
|
|
this.$root.$emit('bv::hide::tooltip');
|
|
|
|
});
|
|
|
|
},
|
2020-06-16 17:08:20 -04:00
|
|
|
handleAssigneeUpdate(assignees) {
|
|
|
|
this.$emit('updateAssignees', assignees);
|
|
|
|
eventHub.$emit(this.sidebarAction, this.author);
|
|
|
|
eventHub.$emit('sidebar.saveAssignees');
|
|
|
|
},
|
|
|
|
assignUser() {
|
|
|
|
let { assignees } = this;
|
|
|
|
const { project_id, iid } = this.getNoteableData;
|
|
|
|
|
|
|
|
if (this.isUserAssigned) {
|
|
|
|
assignees = assignees.filter(assignee => assignee.id !== this.author.id);
|
|
|
|
} else {
|
|
|
|
assignees.push({ id: this.author.id });
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.targetType === 'issue') {
|
|
|
|
Api.updateIssue(project_id, iid, {
|
|
|
|
assignee_ids: assignees.map(assignee => assignee.id),
|
|
|
|
})
|
|
|
|
.then(() => this.handleAssigneeUpdate(assignees))
|
|
|
|
.catch(() => flash(__('Something went wrong while updating assignees')));
|
|
|
|
}
|
|
|
|
},
|
2018-03-16 16:16:21 -04:00
|
|
|
},
|
|
|
|
};
|
2017-06-13 13:01:59 -04:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div class="note-actions">
|
2018-11-09 04:44:07 -05:00
|
|
|
<span v-if="accessLevel" class="note-role user-access-role">{{ accessLevel }}</span>
|
2018-11-16 15:07:38 -05:00
|
|
|
<div v-if="canResolve" class="note-actions-item">
|
2018-02-27 19:10:43 -05:00
|
|
|
<button
|
2019-02-08 09:13:01 -05:00
|
|
|
ref="resolveButton"
|
2018-11-09 04:44:07 -05:00
|
|
|
v-gl-tooltip
|
2018-02-27 19:10:43 -05:00
|
|
|
:class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
|
|
|
|
:title="resolveButtonTitle"
|
|
|
|
:aria-label="resolveButtonTitle"
|
|
|
|
type="button"
|
2018-06-11 05:49:47 -04:00
|
|
|
class="line-resolve-btn note-action-button"
|
2018-11-16 15:07:38 -05:00
|
|
|
@click="onResolve"
|
|
|
|
>
|
2018-02-27 19:10:43 -05:00
|
|
|
<template v-if="!isResolving">
|
2019-05-22 21:12:30 -04:00
|
|
|
<icon :name="isResolved ? 'check-circle-filled' : 'check-circle'" />
|
2018-02-27 19:10:43 -05:00
|
|
|
</template>
|
2018-11-16 15:07:38 -05:00
|
|
|
<gl-loading-icon v-else inline />
|
2018-02-27 19:10:43 -05:00
|
|
|
</button>
|
|
|
|
</div>
|
2018-11-16 15:07:38 -05:00
|
|
|
<div v-if="canAwardEmoji" class="note-actions-item">
|
2017-08-17 19:07:29 -04:00
|
|
|
<a
|
2018-08-15 07:37:24 -04:00
|
|
|
v-gl-tooltip
|
2017-08-17 19:07:29 -04:00
|
|
|
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
|
|
|
|
class="note-action-button note-emoji-button js-add-award js-note-emoji"
|
|
|
|
href="#"
|
2018-01-04 19:18:35 -05:00
|
|
|
title="Add reaction"
|
2019-05-31 08:45:37 -04:00
|
|
|
data-position="right"
|
2018-01-04 19:18:35 -05:00
|
|
|
>
|
2019-10-02 17:06:22 -04:00
|
|
|
<icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
|
|
|
|
<icon class="link-highlight award-control-icon-positive" name="smiley" />
|
|
|
|
<icon class="link-highlight award-control-icon-super-positive" name="smiley" />
|
2017-08-17 19:07:29 -04:00
|
|
|
</a>
|
|
|
|
</div>
|
2019-02-06 05:31:46 -05:00
|
|
|
<reply-button
|
2019-04-02 22:00:18 -04:00
|
|
|
v-if="showReply"
|
2019-02-06 05:31:46 -05:00
|
|
|
ref="replyButton"
|
|
|
|
class="js-reply-button"
|
2019-02-18 04:43:13 -05:00
|
|
|
@startReplying="$emit('startReplying')"
|
2019-02-06 05:31:46 -05:00
|
|
|
/>
|
2018-11-16 15:07:38 -05:00
|
|
|
<div v-if="canEdit" class="note-actions-item">
|
2017-08-17 19:07:29 -04:00
|
|
|
<button
|
2018-08-15 07:37:24 -04:00
|
|
|
v-gl-tooltip
|
2017-08-17 19:07:29 -04:00
|
|
|
type="button"
|
|
|
|
title="Edit comment"
|
2019-07-10 09:49:28 -04:00
|
|
|
class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
|
2018-11-16 15:07:38 -05:00
|
|
|
@click="onEdit"
|
|
|
|
>
|
2019-10-02 17:06:22 -04:00
|
|
|
<icon name="pencil" class="link-highlight" />
|
2017-08-17 19:07:29 -04:00
|
|
|
</button>
|
|
|
|
</div>
|
2018-11-16 15:07:38 -05:00
|
|
|
<div v-if="showDeleteAction" class="note-actions-item">
|
2018-10-06 13:16:40 -04:00
|
|
|
<button
|
2018-08-15 07:37:24 -04:00
|
|
|
v-gl-tooltip
|
2018-10-06 13:16:40 -04:00
|
|
|
type="button"
|
|
|
|
title="Delete comment"
|
|
|
|
class="note-action-button js-note-delete btn btn-transparent"
|
|
|
|
@click="onDelete"
|
|
|
|
>
|
2018-11-16 15:07:38 -05:00
|
|
|
<icon name="remove" class="link-highlight" />
|
2018-10-06 13:16:40 -04:00
|
|
|
</button>
|
|
|
|
</div>
|
2018-11-16 15:07:38 -05:00
|
|
|
<div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions note-actions-item">
|
2017-06-13 13:01:59 -04:00
|
|
|
<button
|
2018-08-15 07:37:24 -04:00
|
|
|
v-gl-tooltip
|
2017-06-13 13:01:59 -04:00
|
|
|
type="button"
|
|
|
|
title="More actions"
|
2017-07-26 12:26:07 -04:00
|
|
|
class="note-action-button more-actions-toggle btn btn-transparent"
|
2017-06-13 13:01:59 -04:00
|
|
|
data-toggle="dropdown"
|
2019-01-09 18:46:43 -05:00
|
|
|
@click="closeTooltip"
|
2018-11-16 15:07:38 -05:00
|
|
|
>
|
2019-10-02 17:06:22 -04:00
|
|
|
<icon class="icon" name="ellipsis_v" />
|
2017-06-13 13:01:59 -04:00
|
|
|
</button>
|
|
|
|
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
|
2017-07-03 19:04:58 -04:00
|
|
|
<li v-if="canReportAsAbuse">
|
2019-06-06 06:05:42 -04:00
|
|
|
<a :href="reportAbusePath">{{ __('Report abuse to admin') }}</a>
|
2017-06-13 13:01:59 -04:00
|
|
|
</li>
|
2018-09-07 09:39:20 -04:00
|
|
|
<li v-if="noteUrl">
|
2018-06-21 08:22:40 -04:00
|
|
|
<button
|
|
|
|
:data-clipboard-text="noteUrl"
|
|
|
|
type="button"
|
2018-09-07 09:39:20 -04:00
|
|
|
class="btn-default btn-transparent js-btn-copy-note-link"
|
2018-06-21 08:22:40 -04:00
|
|
|
>
|
2018-11-07 06:24:36 -05:00
|
|
|
{{ __('Copy link') }}
|
2018-06-21 08:22:40 -04:00
|
|
|
</button>
|
|
|
|
</li>
|
2020-06-30 05:08:37 -04:00
|
|
|
<li v-if="canAssign">
|
2020-06-16 17:08:20 -04:00
|
|
|
<button
|
|
|
|
class="btn-default btn-transparent"
|
|
|
|
data-testid="assign-user"
|
|
|
|
type="button"
|
|
|
|
@click="assignUser"
|
|
|
|
>
|
|
|
|
{{ displayAssignUserText }}
|
|
|
|
</button>
|
|
|
|
</li>
|
2020-06-26 08:08:51 -04:00
|
|
|
<li v-if="canEdit">
|
|
|
|
<button
|
|
|
|
class="btn btn-transparent js-note-delete js-note-delete"
|
|
|
|
type="button"
|
|
|
|
@click.prevent="onDelete"
|
|
|
|
>
|
|
|
|
<span class="text-danger">{{ __('Delete comment') }}</span>
|
|
|
|
</button>
|
|
|
|
</li>
|
2017-06-13 13:01:59 -04:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|