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

246 lines
7 KiB
Vue
Raw Normal View History

2018-03-17 18:26:18 +05:30
<script>
2018-05-09 12:01:36 +05:30
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { escape } from 'underscore';
2019-02-13 22:33:31 +05:30
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
2018-05-09 12:01:36 +05:30
import Flash from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteHeader from './note_header.vue';
import noteActions from './note_actions.vue';
import noteBody from './note_body.vue';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
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: 'NoteableNote',
2018-05-09 12:01:36 +05:30
components: {
userAvatarLink,
noteHeader,
noteActions,
noteBody,
2019-02-13 22:33:31 +05:30
TimelineEntryItem,
2018-05-09 12:01:36 +05:30
},
mixins: [noteable, resolvable],
props: {
note: {
type: Object,
required: true,
2018-03-17 18:26:18 +05:30
},
2019-02-13 22:33:31 +05:30
line: {
type: Object,
required: false,
default: null,
},
helpPagePath: {
type: String,
required: false,
default: '',
},
2018-05-09 12:01:36 +05:30
},
data() {
return {
isEditing: false,
isDeleting: false,
isRequesting: false,
isResolving: false,
};
},
computed: {
2018-11-08 19:23:39 +05:30
...mapGetters(['targetNoteHash', 'getNoteableData', 'getUserData']),
2018-05-09 12:01:36 +05:30
author() {
return this.note.author;
2018-03-17 18:26:18 +05:30
},
2018-05-09 12:01:36 +05:30
classNameBindings() {
2018-03-17 18:26:18 +05:30
return {
2018-11-08 19:23:39 +05:30
[`note-row-${this.note.id}`]: true,
2018-05-09 12:01:36 +05:30
'is-editing': this.isEditing && !this.isRequesting,
'is-requesting being-posted': this.isRequesting,
'disabled-content': this.isDeleting,
2018-11-08 19:23:39 +05:30
target: this.isTarget,
2019-02-13 22:33:31 +05:30
'is-editable': this.note.current_user.can_edit,
2018-03-17 18:26:18 +05:30
};
},
2018-11-08 19:23:39 +05:30
canResolve() {
return this.note.resolvable && !!this.getUserData.id;
},
2018-05-09 12:01:36 +05:30
canReportAsAbuse() {
2018-12-05 23:21:45 +05:30
return !!this.note.report_abuse_path && this.author.id !== this.getUserData.id;
2018-03-17 18:26:18 +05:30
},
2018-05-09 12:01:36 +05:30
noteAnchorId() {
return `note_${this.note.id}`;
2018-03-17 18:26:18 +05:30
},
2018-11-08 19:23:39 +05:30
isTarget() {
return this.targetNoteHash === this.noteAnchorId;
},
2018-05-09 12:01:36 +05:30
},
2018-03-17 18:26:18 +05:30
2018-05-09 12:01:36 +05:30
created() {
eventHub.$on('enterEditMode', ({ noteId }) => {
if (noteId === this.note.id) {
2018-03-17 18:26:18 +05:30
this.isEditing = true;
2018-05-09 12:01:36 +05:30
this.scrollToNoteIfNeeded($(this.$el));
}
});
},
2018-03-17 18:26:18 +05:30
2018-11-08 19:23:39 +05:30
mounted() {
if (this.isTarget) {
this.scrollToNoteIfNeeded($(this.$el));
}
},
2018-05-09 12:01:36 +05:30
methods: {
2018-11-08 19:23:39 +05:30
...mapActions(['deleteNote', 'updateNote', 'toggleResolveNote', 'scrollToNoteIfNeeded']),
2018-05-09 12:01:36 +05:30
editHandler() {
this.isEditing = true;
2018-12-05 23:21:45 +05:30
this.$emit('handleEdit');
2018-05-09 12:01:36 +05:30
},
deleteHandler() {
2018-12-05 23:21:45 +05:30
const typeOfComment = this.note.isDraft ? 'pending comment' : 'comment';
2018-05-09 12:01:36 +05:30
// eslint-disable-next-line no-alert
2018-12-05 23:21:45 +05:30
if (window.confirm(`Are you sure you want to delete this ${typeOfComment}?`)) {
2018-05-09 12:01:36 +05:30
this.isDeleting = true;
2018-11-20 20:47:30 +05:30
this.$emit('handleDeleteNote', this.note);
2018-03-17 18:26:18 +05:30
2018-12-05 23:21:45 +05:30
if (this.note.isDraft) return;
2018-05-09 12:01:36 +05:30
this.deleteNote(this.note)
2018-03-17 18:26:18 +05:30
.then(() => {
2018-05-09 12:01:36 +05:30
this.isDeleting = false;
2018-03-17 18:26:18 +05:30
})
.catch(() => {
2018-11-08 19:23:39 +05:30
Flash('Something went wrong while deleting your note. Please try again.');
2018-05-09 12:01:36 +05:30
this.isDeleting = false;
2018-03-17 18:26:18 +05:30
});
2018-05-09 12:01:36 +05:30
}
},
2018-12-05 23:21:45 +05:30
updateSuccess() {
this.isEditing = false;
this.isRequesting = false;
this.oldContent = null;
$(this.$refs.noteBody.$el).renderGFM();
this.$refs.noteBody.resetAutoSave();
this.$emit('updateSuccess');
},
2018-05-09 12:01:36 +05:30
formUpdateHandler(noteText, parentElement, callback) {
2018-12-05 23:21:45 +05:30
this.$emit('handleUpdateNote', {
note: this.note,
noteText,
callback: () => this.updateSuccess(),
});
2018-05-09 12:01:36 +05:30
const data = {
endpoint: this.note.path,
note: {
2018-11-08 19:23:39 +05:30
target_type: this.getNoteableData.targetType,
2018-05-09 12:01:36 +05:30
target_id: this.note.noteable_id,
note: { note: noteText },
},
};
this.isRequesting = true;
this.oldContent = this.note.note_html;
this.note.note_html = escape(noteText);
this.updateNote(data)
.then(() => {
2018-12-05 23:21:45 +05:30
this.updateSuccess();
2018-05-09 12:01:36 +05:30
callback();
})
.catch(() => {
this.isRequesting = false;
this.isEditing = true;
this.$nextTick(() => {
2018-11-08 19:23:39 +05:30
const msg = 'Something went wrong while editing your comment. Please try again.';
2018-05-09 12:01:36 +05:30
Flash(msg, 'alert', this.$el);
this.recoverNoteContent(noteText);
callback();
});
});
},
formCancelHandler(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
// eslint-disable-next-line no-alert
2018-11-08 19:23:39 +05:30
if (!window.confirm('Are you sure you want to cancel editing this comment?')) return;
2018-05-09 12:01:36 +05:30
}
this.$refs.noteBody.resetAutoSave();
if (this.oldContent) {
this.note.note_html = this.oldContent;
this.oldContent = null;
}
this.isEditing = false;
2018-12-05 23:21:45 +05:30
this.$emit('cancelForm');
2018-05-09 12:01:36 +05:30
},
recoverNoteContent(noteText) {
// we need to do this to prevent noteForm inconsistent content warning
// this is something we intentionally do so we need to recover the content
this.note.note = noteText;
2018-11-08 19:23:39 +05:30
this.$refs.noteBody.note.note = noteText;
2018-03-17 18:26:18 +05:30
},
2018-05-09 12:01:36 +05:30
},
};
2018-03-17 18:26:18 +05:30
</script>
<template>
2019-02-13 22:33:31 +05:30
<timeline-entry-item
2018-03-17 18:26:18 +05:30
:id="noteAnchorId"
:class="classNameBindings"
2018-11-08 19:23:39 +05:30
:data-award-url="note.toggle_award_path"
:data-note-id="note.id"
2019-02-13 22:33:31 +05:30
class="note note-wrapper"
2018-11-08 19:23:39 +05:30
>
2019-02-13 22:33:31 +05:30
<div v-once class="timeline-icon">
<user-avatar-link
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="author.name"
:img-size="40"
>
<slot slot="avatar-badge" name="avatar-badge"></slot>
</user-avatar-link>
</div>
<div class="timeline-content">
<div class="note-header">
<note-header
v-once
:author="author"
:created-at="note.created_at"
:note-id="note.id"
action-text="commented"
/>
<note-actions
:author-id="author.id"
:note-id="note.id"
:note-url="note.noteable_note_url"
:access-level="note.human_access"
:can-edit="note.current_user.can_edit"
:can-award-emoji="note.current_user.can_award_emoji"
:can-delete="note.current_user.can_edit"
:can-report-as-abuse="canReportAsAbuse"
:can-resolve="note.current_user.can_resolve"
:report-abuse-path="note.report_abuse_path"
:resolvable="note.resolvable"
:is-resolved="note.resolved"
:is-resolving="isResolving"
:resolved-by="note.resolved_by"
@handleEdit="editHandler"
@handleDelete="deleteHandler"
@handleResolve="resolveHandler"
/>
2019-01-03 12:48:30 +05:30
</div>
2019-02-13 22:33:31 +05:30
<div class="timeline-discussion-body">
<slot name="discussion-resolved-text"></slot>
2019-01-03 12:48:30 +05:30
<note-body
ref="noteBody"
:note="note"
2019-02-13 22:33:31 +05:30
:line="line"
2018-03-17 18:26:18 +05:30
:can-edit="note.current_user.can_edit"
2019-01-03 12:48:30 +05:30
:is-editing="isEditing"
2019-02-13 22:33:31 +05:30
:help-page-path="helpPagePath"
2019-01-03 12:48:30 +05:30
@handleFormUpdate="formUpdateHandler"
@cancelForm="formCancelHandler"
2018-03-17 18:26:18 +05:30
/>
</div>
</div>
2019-02-13 22:33:31 +05:30
</timeline-entry-item>
2018-03-17 18:26:18 +05:30
</template>