2018-03-17 18:26:18 +05:30
|
|
|
<script>
|
2020-11-24 15:15:51 +05:30
|
|
|
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
|
2021-03-11 19:13:27 +05:30
|
|
|
import { mapActions, mapGetters } from 'vuex';
|
|
|
|
import DraftNote from '~/batch_comments/components/draft_note.vue';
|
2021-09-30 23:02:18 +05:30
|
|
|
import createFlash from '~/flash';
|
2019-07-07 11:18:12 +05:30
|
|
|
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
|
2021-09-30 23:02:18 +05:30
|
|
|
import { isLoggedIn } from '~/lib/utils/common_utils';
|
2022-04-04 11:22:00 +05:30
|
|
|
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
|
2022-05-07 20:08:51 +05:30
|
|
|
import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
|
2022-07-16 23:28:13 +05:30
|
|
|
import { s__, __, sprintf } from '~/locale';
|
2021-03-11 19:13:27 +05:30
|
|
|
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
|
2019-02-15 15:39:39 +05:30
|
|
|
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
2022-06-21 17:19:12 +05:30
|
|
|
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
2021-03-11 19:13:27 +05:30
|
|
|
import eventHub from '../event_hub';
|
2018-05-09 12:01:36 +05:30
|
|
|
import noteable from '../mixins/noteable';
|
|
|
|
import resolvable from '../mixins/resolvable';
|
2021-03-11 19:13:27 +05:30
|
|
|
import diffDiscussionHeader from './diff_discussion_header.vue';
|
|
|
|
import diffWithNote from './diff_with_note.vue';
|
2019-07-31 22:56:46 +05:30
|
|
|
import DiscussionActions from './discussion_actions.vue';
|
2021-03-11 19:13:27 +05:30
|
|
|
import DiscussionNotes from './discussion_notes.vue';
|
|
|
|
import noteForm from './note_form.vue';
|
|
|
|
import noteSignedOutWidget from './note_signed_out_widget.vue';
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
export default {
|
2018-11-08 19:23:39 +05:30
|
|
|
name: 'NoteableDiscussion',
|
2018-05-09 12:01:36 +05:30
|
|
|
components: {
|
2020-11-24 15:15:51 +05:30
|
|
|
GlIcon,
|
2018-05-09 12:01:36 +05:30
|
|
|
userAvatarLink,
|
2019-12-26 22:10:19 +05:30
|
|
|
diffDiscussionHeader,
|
2018-05-09 12:01:36 +05:30
|
|
|
noteSignedOutWidget,
|
|
|
|
noteForm,
|
2020-06-23 00:09:42 +05:30
|
|
|
DraftNote,
|
2019-02-15 15:39:39 +05:30
|
|
|
TimelineEntryItem,
|
2019-07-31 22:56:46 +05:30
|
|
|
DiscussionNotes,
|
|
|
|
DiscussionActions,
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
|
|
|
directives: {
|
2019-02-15 15:39:39 +05:30
|
|
|
GlTooltip: GlTooltipDirective,
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
mixins: [noteable, resolvable, diffLineNoteFormMixin],
|
2018-05-09 12:01:36 +05:30
|
|
|
props: {
|
2018-11-08 19:23:39 +05:30
|
|
|
discussion: {
|
2018-05-09 12:01:36 +05:30
|
|
|
type: Object,
|
|
|
|
required: true,
|
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
line: {
|
|
|
|
type: Object,
|
|
|
|
required: false,
|
|
|
|
default: null,
|
|
|
|
},
|
2018-11-08 19:23:39 +05:30
|
|
|
renderDiffFile: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: true,
|
|
|
|
},
|
|
|
|
alwaysExpanded: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2018-11-18 11:00:15 +05:30
|
|
|
discussionsByDiffOrder: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
helpPagePath: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
2021-11-18 22:05:49 +05:30
|
|
|
isOverviewTab: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
isReplying: false,
|
|
|
|
isResolving: false,
|
|
|
|
resolveAsThread: true,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
...mapGetters([
|
2019-07-07 11:18:12 +05:30
|
|
|
'convertedDisscussionIds',
|
2018-05-09 12:01:36 +05:30
|
|
|
'getNoteableData',
|
2019-07-31 22:56:46 +05:30
|
|
|
'userCanReply',
|
2019-02-15 15:39:39 +05:30
|
|
|
'showJumpToNextDiscussion',
|
2019-09-04 21:01:54 +05:30
|
|
|
'getUserData',
|
2018-05-09 12:01:36 +05:30
|
|
|
]),
|
2019-09-04 21:01:54 +05:30
|
|
|
currentUser() {
|
|
|
|
return this.getUserData;
|
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
isLoggedIn() {
|
2021-09-30 23:02:18 +05:30
|
|
|
return isLoggedIn();
|
2020-03-13 15:44:24 +05:30
|
|
|
},
|
2022-07-16 23:28:13 +05:30
|
|
|
commentType() {
|
|
|
|
return this.discussion.confidential ? __('internal note') : __('comment');
|
|
|
|
},
|
2019-07-07 11:18:12 +05:30
|
|
|
autosaveKey() {
|
|
|
|
return getDiscussionReplyKey(this.firstNote.noteable_type, this.discussion.id);
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
|
|
|
newNotePath() {
|
|
|
|
return this.getNoteableData.create_note_path;
|
|
|
|
},
|
2019-07-07 11:18:12 +05:30
|
|
|
firstNote() {
|
2018-12-13 13:39:08 +05:30
|
|
|
return this.discussion.notes.slice(0, 1)[0];
|
|
|
|
},
|
2022-07-16 23:28:13 +05:30
|
|
|
saveButtonTitle() {
|
|
|
|
return this.discussion.confidential ? __('Reply internally') : __('Comment');
|
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
shouldShowJumpToNextDiscussion() {
|
2019-09-30 21:07:59 +05:30
|
|
|
return this.showJumpToNextDiscussion(this.discussionsByDiffOrder ? 'diff' : 'discussion');
|
2018-11-18 11:00:15 +05:30
|
|
|
},
|
2018-11-08 19:23:39 +05:30
|
|
|
shouldRenderDiffs() {
|
2019-02-15 15:39:39 +05:30
|
|
|
return this.discussion.diff_discussion && this.renderDiffFile;
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
shouldGroupReplies() {
|
2019-09-30 21:07:59 +05:30
|
|
|
return !this.shouldRenderDiffs;
|
2018-12-13 13:39:08 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
wrapperComponent() {
|
2018-11-08 19:23:39 +05:30
|
|
|
return this.shouldRenderDiffs ? diffWithNote : 'div';
|
|
|
|
},
|
|
|
|
wrapperComponentProps() {
|
|
|
|
if (this.shouldRenderDiffs) {
|
2019-02-15 15:39:39 +05:30
|
|
|
return { discussion: this.discussion };
|
2018-11-08 19:23:39 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
2019-07-07 11:18:12 +05:30
|
|
|
isExpanded() {
|
|
|
|
return this.discussion.expanded || this.alwaysExpanded;
|
|
|
|
},
|
|
|
|
shouldHideDiscussionBody() {
|
|
|
|
return this.shouldRenderDiffs && !this.isExpanded;
|
2018-12-13 13:39:08 +05:30
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
diffLine() {
|
2019-03-02 22:35:43 +05:30
|
|
|
if (this.line) {
|
|
|
|
return this.line;
|
|
|
|
}
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
if (this.discussion.diff_discussion && this.discussion.truncated_diff_lines) {
|
|
|
|
return this.discussion.truncated_diff_lines.slice(-1)[0];
|
|
|
|
}
|
|
|
|
|
2019-03-02 22:35:43 +05:30
|
|
|
return null;
|
|
|
|
},
|
2019-07-07 11:18:12 +05:30
|
|
|
resolveWithIssuePath() {
|
2019-07-31 22:56:46 +05:30
|
|
|
return !this.discussionResolved ? this.discussion.resolve_with_issue_path : '';
|
2019-05-30 16:15:17 +05:30
|
|
|
},
|
2021-09-04 01:27:46 +05:30
|
|
|
canShowReplyActions() {
|
|
|
|
if (this.shouldRenderDiffs && !this.discussion.diff_file.diff_refs) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
2019-05-18 00:54:41 +05:30
|
|
|
},
|
2019-07-07 11:18:12 +05:30
|
|
|
created() {
|
|
|
|
eventHub.$on('startReplying', this.onStartReplying);
|
|
|
|
},
|
|
|
|
beforeDestroy() {
|
|
|
|
eventHub.$off('startReplying', this.onStartReplying);
|
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
methods: {
|
|
|
|
...mapActions([
|
|
|
|
'saveNote',
|
|
|
|
'removePlaceholderNotes',
|
|
|
|
'toggleResolveNote',
|
2019-07-07 11:18:12 +05:30
|
|
|
'removeConvertedDiscussion',
|
2020-10-24 23:57:45 +05:30
|
|
|
'expandDiscussion',
|
2018-05-09 12:01:36 +05:30
|
|
|
]),
|
|
|
|
showReplyForm() {
|
|
|
|
this.isReplying = true;
|
2020-10-24 23:57:45 +05:30
|
|
|
|
|
|
|
if (!this.discussion.expanded) {
|
|
|
|
this.expandDiscussion({ discussionId: this.discussion.id });
|
|
|
|
}
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
2022-05-07 20:08:51 +05:30
|
|
|
cancelReplyForm: ignoreWhilePending(async function cancelReplyForm(shouldConfirm, isDirty) {
|
2018-11-18 11:00:15 +05:30
|
|
|
if (shouldConfirm && isDirty) {
|
2022-07-16 23:28:13 +05:30
|
|
|
const msg = sprintf(
|
|
|
|
s__('Notes|Are you sure you want to cancel creating this %{commentType}?'),
|
|
|
|
{ commentType: this.commentType },
|
|
|
|
);
|
2018-11-18 11:00:15 +05:30
|
|
|
|
2022-07-16 23:28:13 +05:30
|
|
|
const confirmed = await confirmAction(msg, {
|
|
|
|
primaryBtnText: __('Discard changes'),
|
|
|
|
cancelBtnText: __('Continue editing'),
|
|
|
|
});
|
2022-04-04 11:22:00 +05:30
|
|
|
|
|
|
|
if (!confirmed) {
|
2018-05-09 12:01:36 +05:30
|
|
|
return;
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
2018-05-09 12:01:36 +05:30
|
|
|
}
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
if (this.convertedDisscussionIds.includes(this.discussion.id)) {
|
|
|
|
this.removeConvertedDiscussion(this.discussion.id);
|
|
|
|
}
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
this.isReplying = false;
|
2019-07-07 11:18:12 +05:30
|
|
|
clearDraft(this.autosaveKey);
|
2022-05-07 20:08:51 +05:30
|
|
|
}),
|
2018-05-09 12:01:36 +05:30
|
|
|
saveReply(noteText, form, callback) {
|
2019-09-30 21:07:59 +05:30
|
|
|
if (!noteText) {
|
|
|
|
this.cancelReplyForm();
|
|
|
|
callback();
|
|
|
|
return;
|
|
|
|
}
|
2018-11-08 19:23:39 +05:30
|
|
|
const postData = {
|
|
|
|
in_reply_to_discussion_id: this.discussion.reply_id,
|
|
|
|
target_type: this.getNoteableData.targetType,
|
|
|
|
note: { note: noteText },
|
|
|
|
};
|
|
|
|
|
2019-07-07 11:18:12 +05:30
|
|
|
if (this.convertedDisscussionIds.includes(this.discussion.id)) {
|
|
|
|
postData.return_discussion = true;
|
|
|
|
}
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
if (this.discussion.for_commit) {
|
|
|
|
postData.note_project_id = this.discussion.project_id;
|
|
|
|
}
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
const replyData = {
|
|
|
|
endpoint: this.newNotePath,
|
|
|
|
flashContainer: this.$el,
|
2018-11-08 19:23:39 +05:30
|
|
|
data: postData,
|
2018-05-09 12:01:36 +05:30
|
|
|
};
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
this.saveNote(replyData)
|
2021-03-08 18:12:59 +05:30
|
|
|
.then((res) => {
|
2020-01-01 13:55:28 +05:30
|
|
|
if (res.hasFlash !== true) {
|
|
|
|
this.isReplying = false;
|
|
|
|
clearDraft(this.autosaveKey);
|
|
|
|
}
|
2018-05-09 12:01:36 +05:30
|
|
|
callback();
|
|
|
|
})
|
2021-03-08 18:12:59 +05:30
|
|
|
.catch((err) => {
|
2018-05-09 12:01:36 +05:30
|
|
|
this.removePlaceholderNotes();
|
2022-01-26 12:08:38 +05:30
|
|
|
this.handleSaveError(err); // The 'err' parameter is being used in JH, don't remove it
|
2020-01-01 13:55:28 +05:30
|
|
|
this.$refs.noteForm.note = noteText;
|
|
|
|
callback(err);
|
2018-05-09 12:01:36 +05:30
|
|
|
});
|
|
|
|
},
|
2022-01-26 12:08:38 +05:30
|
|
|
handleSaveError() {
|
|
|
|
const msg = __(
|
|
|
|
'Your comment could not be submitted! Please check your network connection and try again.',
|
|
|
|
);
|
|
|
|
createFlash({
|
|
|
|
message: msg,
|
|
|
|
parent: this.$el,
|
|
|
|
});
|
|
|
|
},
|
2018-11-20 20:47:30 +05:30
|
|
|
deleteNoteHandler(note) {
|
|
|
|
this.$emit('noteDeleted', this.discussion, note);
|
|
|
|
},
|
2019-07-07 11:18:12 +05:30
|
|
|
onStartReplying(discussionId) {
|
|
|
|
if (this.discussion.id === discussionId) {
|
|
|
|
this.showReplyForm();
|
|
|
|
}
|
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
|
|
|
};
|
2018-03-17 18:26:18 +05:30
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2019-09-30 21:07:59 +05:30
|
|
|
<timeline-entry-item class="note note-discussion">
|
2019-02-15 15:39:39 +05:30
|
|
|
<div class="timeline-content">
|
2019-12-21 20:55:43 +05:30
|
|
|
<div
|
|
|
|
:data-discussion-id="discussion.id"
|
|
|
|
class="discussion js-discussion-container"
|
|
|
|
data-qa-selector="discussion_content"
|
|
|
|
>
|
2019-12-26 22:10:19 +05:30
|
|
|
<diff-discussion-header v-if="shouldRenderDiffs" :discussion="discussion" />
|
2019-07-07 11:18:12 +05:30
|
|
|
<div v-if="!shouldHideDiscussionBody" class="discussion-body">
|
2019-02-15 15:39:39 +05:30
|
|
|
<component
|
|
|
|
:is="wrapperComponent"
|
|
|
|
v-bind="wrapperComponentProps"
|
|
|
|
class="card discussion-wrapper"
|
|
|
|
>
|
2019-07-31 22:56:46 +05:30
|
|
|
<discussion-notes
|
|
|
|
:discussion="discussion"
|
|
|
|
:diff-line="diffLine"
|
|
|
|
:help-page-path="helpPagePath"
|
|
|
|
:is-expanded="isExpanded"
|
|
|
|
:line="line"
|
|
|
|
:should-group-replies="shouldGroupReplies"
|
2021-11-18 22:05:49 +05:30
|
|
|
:is-overview-tab="isOverviewTab"
|
2019-07-31 22:56:46 +05:30
|
|
|
@startReplying="showReplyForm"
|
|
|
|
@deleteNote="deleteNoteHandler"
|
|
|
|
>
|
2021-09-30 23:02:18 +05:30
|
|
|
<template #avatar-badge>
|
|
|
|
<slot name="avatar-badge"></slot>
|
|
|
|
</template>
|
2019-07-31 22:56:46 +05:30
|
|
|
<template #footer="{ showReplies }">
|
|
|
|
<draft-note
|
|
|
|
v-if="showDraft(discussion.reply_id)"
|
|
|
|
:key="`draft_${discussion.id}`"
|
|
|
|
:draft="draftForDiscussion(discussion.reply_id)"
|
2022-01-26 12:08:38 +05:30
|
|
|
:line="line"
|
2019-07-31 22:56:46 +05:30
|
|
|
/>
|
|
|
|
<div
|
2021-09-04 01:27:46 +05:30
|
|
|
v-else-if="canShowReplyActions && showReplies"
|
2019-07-31 22:56:46 +05:30
|
|
|
:class="{ 'is-replying': isReplying }"
|
2021-03-11 19:13:27 +05:30
|
|
|
class="discussion-reply-holder gl-border-t-0! clearfix"
|
2019-07-31 22:56:46 +05:30
|
|
|
>
|
|
|
|
<discussion-actions
|
|
|
|
v-if="!isReplying && userCanReply"
|
|
|
|
:discussion="discussion"
|
|
|
|
:is-resolving="isResolving"
|
|
|
|
:resolve-button-title="resolveButtonTitle"
|
|
|
|
:resolve-with-issue-path="resolveWithIssuePath"
|
|
|
|
:should-show-jump-to-next-discussion="shouldShowJumpToNextDiscussion"
|
|
|
|
@showReplyForm="showReplyForm"
|
|
|
|
@resolve="resolveHandler"
|
2019-02-15 15:39:39 +05:30
|
|
|
/>
|
2021-03-11 19:13:27 +05:30
|
|
|
<note-form
|
|
|
|
v-if="isReplying"
|
|
|
|
ref="noteForm"
|
|
|
|
:discussion="discussion"
|
|
|
|
:line="diffLine"
|
2022-07-16 23:28:13 +05:30
|
|
|
:save-button-title="saveButtonTitle"
|
2021-03-11 19:13:27 +05:30
|
|
|
:autosave-key="autosaveKey"
|
|
|
|
@handleFormUpdateAddToReview="addReplyToReview"
|
|
|
|
@handleFormUpdate="saveReply"
|
|
|
|
@cancelForm="cancelReplyForm"
|
|
|
|
/>
|
2020-03-13 15:44:24 +05:30
|
|
|
<note-signed-out-widget v-if="!isLoggedIn" />
|
2019-07-31 22:56:46 +05:30
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</discussion-notes>
|
2019-02-15 15:39:39 +05:30
|
|
|
</component>
|
2018-03-17 18:26:18 +05:30
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-02-15 15:39:39 +05:30
|
|
|
</timeline-entry-item>
|
2018-03-17 18:26:18 +05:30
|
|
|
</template>
|