2018-03-17 18:26:18 +05:30
|
|
|
<script>
|
2018-05-09 12:01:36 +05:30
|
|
|
import { mapGetters, mapActions } from 'vuex';
|
|
|
|
import eventHub from '../event_hub';
|
|
|
|
import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
|
|
|
|
import markdownField from '../../vue_shared/components/markdown/field.vue';
|
|
|
|
import issuableStateMixin from '../mixins/issuable_state';
|
|
|
|
import resolvable from '../mixins/resolvable';
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
export default {
|
|
|
|
name: 'IssueNoteForm',
|
|
|
|
components: {
|
|
|
|
issueWarning,
|
|
|
|
markdownField,
|
|
|
|
},
|
|
|
|
mixins: [issuableStateMixin, resolvable],
|
|
|
|
props: {
|
|
|
|
noteBody: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
noteId: {
|
|
|
|
type: Number,
|
|
|
|
required: false,
|
|
|
|
default: 0,
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
saveButtonTitle: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: 'Save comment',
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
note: {
|
|
|
|
type: Object,
|
|
|
|
required: false,
|
|
|
|
default: () => ({}),
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
isEditing: {
|
|
|
|
type: Boolean,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
updatedNoteBody: this.noteBody,
|
|
|
|
conflictWhileEditing: false,
|
|
|
|
isSubmitting: false,
|
|
|
|
isResolving: false,
|
|
|
|
resolveAsThread: true,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
...mapGetters([
|
|
|
|
'getDiscussionLastNote',
|
|
|
|
'getNoteableData',
|
|
|
|
'getNoteableDataByProp',
|
|
|
|
'getNotesDataByProp',
|
|
|
|
'getUserDataByProp',
|
|
|
|
]),
|
|
|
|
noteHash() {
|
|
|
|
return `#note_${this.noteId}`;
|
|
|
|
},
|
|
|
|
markdownPreviewPath() {
|
|
|
|
return this.getNoteableDataByProp('preview_note_path');
|
|
|
|
},
|
|
|
|
markdownDocsPath() {
|
|
|
|
return this.getNotesDataByProp('markdownDocsPath');
|
|
|
|
},
|
|
|
|
quickActionsDocsPath() {
|
|
|
|
return !this.isEditing
|
|
|
|
? this.getNotesDataByProp('quickActionsDocsPath')
|
|
|
|
: undefined;
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
currentUserId() {
|
|
|
|
return this.getUserDataByProp('id');
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
isDisabled() {
|
|
|
|
return !this.updatedNoteBody.length || this.isSubmitting;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
noteBody() {
|
|
|
|
if (this.updatedNoteBody === this.noteBody) {
|
|
|
|
this.updatedNoteBody = this.noteBody;
|
|
|
|
} else {
|
|
|
|
this.conflictWhileEditing = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
this.$refs.textarea.focus();
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
...mapActions(['toggleResolveNote']),
|
|
|
|
handleUpdate(shouldResolve) {
|
|
|
|
const beforeSubmitDiscussionState = this.discussionResolved;
|
|
|
|
this.isSubmitting = true;
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
this.$emit(
|
|
|
|
'handleFormUpdate',
|
|
|
|
this.updatedNoteBody,
|
|
|
|
this.$refs.editNoteForm,
|
|
|
|
() => {
|
2018-03-17 18:26:18 +05:30
|
|
|
this.isSubmitting = false;
|
2018-03-27 19:54:05 +05:30
|
|
|
|
|
|
|
if (shouldResolve) {
|
|
|
|
this.resolveHandler(beforeSubmitDiscussionState);
|
|
|
|
}
|
2018-05-09 12:01:36 +05:30
|
|
|
},
|
|
|
|
);
|
|
|
|
},
|
|
|
|
editMyLastNote() {
|
|
|
|
if (this.updatedNoteBody === '') {
|
|
|
|
const lastNoteInDiscussion = this.getDiscussionLastNote(
|
|
|
|
this.updatedNoteBody,
|
|
|
|
);
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
if (lastNoteInDiscussion) {
|
|
|
|
eventHub.$emit('enterEditMode', {
|
|
|
|
noteId: lastNoteInDiscussion.id,
|
|
|
|
});
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
2018-05-09 12:01:36 +05:30
|
|
|
}
|
|
|
|
},
|
|
|
|
cancelHandler(shouldConfirm = false) {
|
|
|
|
// Sends information about confirm message and if the textarea has changed
|
|
|
|
this.$emit(
|
|
|
|
'cancelFormEdition',
|
|
|
|
shouldConfirm,
|
|
|
|
this.noteBody !== this.updatedNoteBody,
|
|
|
|
);
|
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>
|
|
|
|
<div
|
|
|
|
ref="editNoteForm"
|
|
|
|
class="note-edit-form current-note-edit-form">
|
|
|
|
<div
|
|
|
|
v-if="conflictWhileEditing"
|
|
|
|
class="js-conflict-edit-warning alert alert-danger">
|
|
|
|
This comment has changed since you started editing, please review the
|
|
|
|
<a
|
|
|
|
:href="noteHash"
|
|
|
|
target="_blank"
|
|
|
|
rel="noopener noreferrer">
|
|
|
|
updated comment
|
|
|
|
</a>
|
|
|
|
to ensure information is not lost.
|
|
|
|
</div>
|
|
|
|
<div class="flash-container timeline-content"></div>
|
|
|
|
<form class="edit-note common-note-form js-quick-submit gfm-form">
|
|
|
|
|
|
|
|
<issue-warning
|
|
|
|
v-if="hasWarning(getNoteableData)"
|
|
|
|
:is-locked="isLocked(getNoteableData)"
|
|
|
|
:is-confidential="isConfidential(getNoteableData)"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<markdown-field
|
|
|
|
:markdown-preview-path="markdownPreviewPath"
|
|
|
|
:markdown-docs-path="markdownDocsPath"
|
|
|
|
:quick-actions-docs-path="quickActionsDocsPath"
|
|
|
|
:add-spacing-classes="false">
|
|
|
|
<textarea
|
|
|
|
id="note_note"
|
|
|
|
name="note[note]"
|
|
|
|
class="note-textarea js-gfm-input
|
|
|
|
js-autosize markdown-area js-vue-issue-note-form js-vue-textarea"
|
|
|
|
:data-supports-quick-actions="!isEditing"
|
|
|
|
aria-label="Description"
|
2018-03-27 19:54:05 +05:30
|
|
|
v-model="updatedNoteBody"
|
2018-03-17 18:26:18 +05:30
|
|
|
ref="textarea"
|
|
|
|
slot="textarea"
|
|
|
|
placeholder="Write a comment or drag your files here..."
|
|
|
|
@keydown.meta.enter="handleUpdate()"
|
|
|
|
@keydown.ctrl.enter="handleUpdate()"
|
|
|
|
@keydown.up="editMyLastNote()"
|
|
|
|
@keydown.esc="cancelHandler(true)">
|
|
|
|
</textarea>
|
|
|
|
</markdown-field>
|
|
|
|
<div class="note-form-actions clearfix">
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
@click="handleUpdate()"
|
|
|
|
:disabled="isDisabled"
|
|
|
|
class="js-vue-issue-save btn btn-save">
|
|
|
|
{{ saveButtonTitle }}
|
|
|
|
</button>
|
2018-03-27 19:54:05 +05:30
|
|
|
<button
|
|
|
|
v-if="note.resolvable"
|
|
|
|
@click.prevent="handleUpdate(true)"
|
|
|
|
class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
|
|
|
|
>
|
|
|
|
{{ resolveButtonTitle }}
|
|
|
|
</button>
|
2018-03-17 18:26:18 +05:30
|
|
|
<button
|
|
|
|
@click="cancelHandler()"
|
|
|
|
class="btn btn-cancel note-edit-cancel"
|
|
|
|
type="button">
|
|
|
|
Cancel
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</template>
|