debian-mirror-gitlab/app/assets/javascripts/notes/components/noteable_discussion.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

356 lines
10 KiB
Vue
Raw Normal View History

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';
2023-05-27 22:25:52 +05:30
import { createAlert } from '~/alert';
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-10-11 01:57:18 +05:30
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
2023-06-20 00:43:36 +05:30
import { containsSensitiveToken, confirmSensitiveAction } from '~/lib/utils/secret_detection';
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';
2022-10-11 01:57:18 +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';
2022-10-11 01:57:18 +05:30
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,
2022-10-11 01:57:18 +05:30
UserAvatarLink,
DiffDiscussionHeader,
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,
},
2023-01-13 00:05:48 +05:30
shouldScrollToNote: {
type: Boolean,
required: false,
default: true,
},
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() {
2022-10-11 01:57:18 +05:30
return this.discussion.internal ? __('internal note') : __('comment');
2022-07-16 23:28:13 +05:30
},
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() {
2022-10-11 01:57:18 +05:30
return this.discussion.internal ? __('Reply internally') : __('Reply');
2022-07-16 23:28:13 +05:30
},
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() {
2022-10-11 01:57:18 +05:30
return this.shouldRenderDiffs ? DiffWithNote : 'div';
2018-11-08 19:23:39 +05:30
},
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
}),
2023-06-20 00:43:36 +05:30
async saveReply(noteText, form, callback) {
2019-09-30 21:07:59 +05:30
if (!noteText) {
this.cancelReplyForm();
callback();
return;
}
2023-06-20 00:43:36 +05:30
if (containsSensitiveToken(noteText)) {
const confirmed = await confirmSensitiveAction();
if (!confirmed) {
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) => {
2023-03-04 22:38:38 +05:30
if (res.hasAlert !== true) {
2020-01-01 13:55:28 +05:30
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.',
);
2022-11-25 23:54:43 +05:30
createAlert({
2022-01-26 12:08:38 +05:30
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"
2022-10-11 01:57:18 +05:30
:data-discussion-resolved="discussion.resolved"
2019-12-21 20:55:43 +05:30
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"
2023-01-13 00:05:48 +05:30
:should-scroll-to-note="shouldScrollToNote"
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
/>
2023-03-04 22:38:38 +05:30
<li
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" />
2023-03-04 22:38:38 +05:30
</li>
2019-07-31 22:56:46 +05:30
</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>