diff options
author | Douwe Maan <douwe@selenight.nl> | 2019-02-11 05:03:51 +0300 |
---|---|---|
committer | Douwe Maan <douwe@selenight.nl> | 2019-05-05 23:20:53 +0300 |
commit | 5f6719cdaf4d0e71bb2589ceb61b57af47c2d18d (patch) | |
tree | f879cc110bfe15449986d8b8d29e39b403f2b9f3 /app | |
parent | a6928459c82f59fad86d8fdde3d1dbcd96247e4a (diff) |
Move Autosave setup to MarkdownField
Diffstat (limited to 'app')
8 files changed, 72 insertions, 73 deletions
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue index 41670b45798..476eabab241 100644 --- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue +++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue @@ -3,14 +3,13 @@ import { mapState, mapGetters, mapActions } from 'vuex'; import { s__ } from '~/locale'; import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form'; import noteForm from '../../notes/components/note_form.vue'; -import autosave from '../../notes/mixins/autosave'; import { DIFF_NOTE_TYPE } from '../constants'; export default { components: { noteForm, }, - mixins: [autosave, diffLineNoteFormMixin], + mixins: [diffLineNoteFormMixin], props: { diffFileHash: { type: String, @@ -55,18 +54,20 @@ export default { diffFile() { return this.getDiffFileByHash(this.diffFileHash); }, - }, - mounted() { - if (this.isLoggedIn) { - const keys = [ + autosaveKey() { + if (!this.isLoggedIn) return []; + + return [ + 'Note', + this.noteableType, + this.noteableData.id, + 'new', this.noteableData.diff_head_sha, DIFF_NOTE_TYPE, this.noteableData.source_project_id, this.line.line_code, ]; - - this.initAutoSave(this.noteableData, keys); - } + }, }, methods: { ...mapActions('diffs', ['cancelCommentForm', 'assignDiscussionsToDiff', 'saveDiffDiscussion']), @@ -80,13 +81,12 @@ export default { } } + this.$refs.noteForm.clearDraft(); + this.cancelCommentForm({ lineCode: this.line.line_code, fileHash: this.diffFileHash, }); - this.$nextTick(() => { - this.resetAutoSave(); - }); }, handleSaveNote(note) { return this.saveDiffDiscussion({ note, formData: this.formData }).then(() => @@ -108,6 +108,7 @@ export default { :diff-file="diffFile" save-button-title="Comment" class="diff-comment-form" + :autosave-key="autosaveKey" @handleFormUpdateAddToReview="addToReview" @cancelForm="handleCancelCommentForm" @handleFormUpdate="handleSaveNote" diff --git a/app/assets/javascripts/lib/utils/autosave.js b/app/assets/javascripts/lib/utils/autosave.js index 023c336db02..5633c5bacde 100644 --- a/app/assets/javascripts/lib/utils/autosave.js +++ b/app/assets/javascripts/lib/utils/autosave.js @@ -1,8 +1,8 @@ -import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; +const autosaveStorageKey = autosaveKey => ['autosave', ...autosaveKey].join('/'); export const clearDraft = autosaveKey => { try { - window.localStorage.removeItem(`autosave/${autosaveKey}`); + window.localStorage.removeItem(autosaveStorageKey(autosaveKey)); } catch (e) { // eslint-disable-next-line no-console console.error(e); @@ -11,7 +11,7 @@ export const clearDraft = autosaveKey => { export const getDraft = autosaveKey => { try { - return window.localStorage.getItem(`autosave/${autosaveKey}`); + return window.localStorage.getItem(autosaveStorageKey(autosaveKey)); } catch (e) { // eslint-disable-next-line no-console console.error(e); @@ -21,12 +21,9 @@ export const getDraft = autosaveKey => { export const updateDraft = (autosaveKey, text) => { try { - window.localStorage.setItem(`autosave/${autosaveKey}`, text); + window.localStorage.setItem(autosaveStorageKey(autosaveKey), text); } catch (e) { // eslint-disable-next-line no-console console.error(e); } }; - -export const getDiscussionReplyKey = (noteableType, discussionId) => - ['Note', capitalizeFirstCharacter(noteableType), discussionId, 'Reply'].join('/'); diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index cf6e9a75bdb..6348441f692 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -6,10 +6,8 @@ import Autosize from 'autosize'; import { __, sprintf } from '~/locale'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import Flash from '../../flash'; -import Autosave from '../../autosave'; import { capitalizeFirstCharacter, - convertToCamelCase, splitCamelCase, slugifyWithUnderscore, } from '../../lib/utils/text_utility'; @@ -133,6 +131,11 @@ export default { trackingLabel() { return slugifyWithUnderscore(`${this.commentButtonTitle} button`); }, + autosaveKey() { + if (!this.isLoggedIn) return []; + + return ['Note', this.noteableType, this.getNoteableData.id, 'new']; + }, }, watch: { note(newNote) { @@ -147,8 +150,6 @@ export default { $(document).on('issuable:change', (e, isClosed) => { this.toggleIssueLocalState(isClosed ? constants.CLOSED : constants.REOPENED); }); - - this.initAutoSave(); }, methods: { ...mapActions([ @@ -278,8 +279,6 @@ Please check your network connection and try again.`; // `focus` is needed to remain cursor in the textarea. this.$nextTick(() => field.focus()); - - this.autosave.reset(); }, setNoteType(type) { this.noteType = type; @@ -293,17 +292,6 @@ Please check your network connection and try again.`; }); } }, - initAutoSave() { - if (this.isLoggedIn) { - const noteableType = capitalizeFirstCharacter(convertToCamelCase(this.noteableType)); - - this.autosave = new Autosave($(this.$refs.textarea), [ - 'Note', - noteableType, - this.getNoteableData.id, - ]); - } - }, resizeTextarea() { this.$nextTick(() => { Autosize.update(this.$refs.textarea); @@ -346,6 +334,7 @@ Please check your network connection and try again.`; :markdown-docs-path="markdownDocsPath" :quick-actions-docs-path="quickActionsDocsPath" :add-spacing-classes="false" + :autosave-key="autosaveKey" textarea-id="note-body" textarea-name="note[note]" textarea-class="js-note-text qa-comment-input" diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue index 8ddd5b8514a..1a4b258dc60 100644 --- a/app/assets/javascripts/notes/components/note_body.vue +++ b/app/assets/javascripts/notes/components/note_body.vue @@ -6,7 +6,6 @@ import noteEditedText from './note_edited_text.vue'; import noteAwardsList from './note_awards_list.vue'; import noteAttachment from './note_attachment.vue'; import noteForm from './note_form.vue'; -import autosave from '../mixins/autosave'; import Suggestions from '~/vue_shared/components/markdown/suggestions.vue'; export default { @@ -17,7 +16,7 @@ export default { noteForm, Suggestions, }, - mixins: [autosave, getDiscussion], + mixins: [getDiscussion], props: { note: { type: Object, @@ -53,27 +52,21 @@ export default { lineType() { return this.line ? this.line.type : null; }, + autosaveKey() { + return ['Note', this.note.id, 'edit']; + }, }, mounted() { this.renderGFM(); - - if (this.isEditing) { - this.initAutoSave(this.note); - } }, updated() { this.renderGFM(); - - if (this.isEditing) { - if (!this.autosave) { - this.initAutoSave(this.note); - } else { - this.setAutoSave(); - } - } }, methods: { ...mapActions(['submitSuggestion']), + clearDraft() { + this.$refs.noteForm.clearDraft(); + }, renderGFM() { $(this.$refs['note-body']).renderGFM(); }, @@ -114,6 +107,7 @@ export default { :help-page-path="helpPagePath" :discussion="discussion" :resolve-discussion="note.resolve_discussion" + :autosave-key="autosaveKey" @handleFormUpdate="handleFormUpdate" @cancelForm="formCancelHandler" /> diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index 5556d37d43b..c8792568744 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -7,7 +7,6 @@ import markdownField from '../../vue_shared/components/markdown/field.vue'; import issuableStateMixin from '../mixins/issuable_state'; import resolvable from '../mixins/resolvable'; import { __ } from '~/locale'; -import { getDraft, updateDraft } from '~/lib/utils/autosave'; import noteFormMixin from 'ee_else_ce/notes/mixins/note_form'; export default { @@ -73,20 +72,14 @@ export default { default: '', }, autosaveKey: { - type: String, + type: Array, required: false, - default: '', + default: () => [], }, }, data() { - let updatedNoteBody = this.noteBody; - - if (!updatedNoteBody && this.autosaveKey) { - updatedNoteBody = getDraft(this.autosaveKey) || ''; - } - return { - updatedNoteBody, + updatedNoteBody: this.noteBody, conflictWhileEditing: false, isSubmitting: false, isResolving: this.resolveDiscussion, @@ -184,6 +177,9 @@ export default { }, methods: { ...mapActions(['toggleResolveNote']), + clearDraft() { + this.$refs.markdownField.clearDraft(); + }, shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState) { // shouldBeResolved() checks the actual resolution state, // considering batchComments (EEP), if applicable/enabled. @@ -209,12 +205,6 @@ export default { // Sends information about confirm message and if the textarea has changed this.$emit('cancelForm', shouldConfirm, this.noteBody !== this.updatedNoteBody); }, - onInput() { - if (this.autosaveKey) { - const { autosaveKey, updatedNoteBody: text } = this; - updateDraft(autosaveKey, text); - } - }, }, }; </script> @@ -245,6 +235,7 @@ export default { :can-suggest="canSuggest" :add-spacing-classes="false" :help-page-path="helpPagePath" + :autosave-key="autosaveKey" textarea-id="note_note" textarea-name="note[note]" textarea-class="js-vue-issue-note-form js-note-text qa-reply-input" @@ -254,7 +245,6 @@ export default { @save="handleKeySubmit()" @edit-previous="editMyLastNote()" @cancel="cancelHandler(true)" - @input="onInput" /> <div class="note-form-actions clearfix"> <template v-if="showBatchCommentsActions"> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 2c549e7abdd..b7b983d650e 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -4,7 +4,6 @@ import { mapActions, mapGetters } from 'vuex'; import { GlTooltipDirective } from '@gitlab/ui'; import { truncateSha } from '~/lib/utils/text_utility'; import { s__, __, sprintf } from '~/locale'; -import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave'; import icon from '~/vue_shared/components/icon.vue'; import diffLineNoteFormMixin from 'ee_else_ce/notes/mixins/diff_line_note_form'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; @@ -92,7 +91,7 @@ export default { return this.firstNote.author; }, autosaveKey() { - return getDiscussionReplyKey(this.firstNote.noteable_type, this.discussion.id); + return ['Note', 'Discussion', this.discussion.id, 'reply']; }, newNotePath() { return this.getNoteableData.create_note_path; @@ -246,7 +245,7 @@ export default { } this.isReplying = false; - clearDraft(this.autosaveKey); + this.$refs.noteForm.clearDraft(); }, saveReply(noteText, form, callback) { const postData = { @@ -272,7 +271,8 @@ export default { this.isReplying = false; this.saveNote(replyData) .then(() => { - clearDraft(this.autosaveKey); + // TODO: TypeError: "_this.$refs.noteForm is undefined", because `isReplying = false` + this.$refs.noteForm.clearDraft(); callback(); }) .catch(err => { @@ -282,6 +282,8 @@ export default { const msg = `Your comment could not be submitted! Please check your network connection and try again.`; Flash(msg, 'alert', this.$el); + // TODO: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "note" + // TODO: Invalid prop: type check failed for prop "note". Expected Object, got String with value "foo". this.$refs.noteForm.note = noteText; callback(err); }); diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 47d74c2f892..4441b84ae81 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -151,7 +151,7 @@ export default { this.isRequesting = false; this.oldContent = null; $(this.$refs.noteBody.$el).renderGFM(); - this.$refs.noteBody.resetAutoSave(); + this.$refs.noteBody.clearDraft(); this.$emit('updateSuccess'); }, formUpdateHandler(noteText, parentElement, callback, resolveDiscussion) { @@ -197,7 +197,7 @@ export default { // eslint-disable-next-line no-alert if (!window.confirm('Are you sure you want to cancel editing this comment?')) return; } - this.$refs.noteBody.resetAutoSave(); + this.$refs.noteBody.clearDraft(); if (this.oldContent) { this.note.note_html = this.oldContent; this.oldContent = null; diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index ffbe78b99bc..49d941a7763 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -1,6 +1,7 @@ <script> import $ from 'jquery'; import _ from 'underscore'; +import { getDraft, updateDraft, clearDraft } from '~/lib/utils/autosave'; import { __ } from '~/locale'; import { stripHtml } from '~/lib/utils/text_utility'; import Flash from '../../../flash'; @@ -78,6 +79,11 @@ export default { required: false, default: true, }, + autosaveKey: { + type: Array, + required: false, + default: () => [], + }, textareaId: { type: String, required: false, @@ -185,6 +191,11 @@ export default { value() { this.setCurrentValue(this.value, { emitEvent: false }); }, + currentValue() { + if (this.autosaveKey.length) { + updateDraft(this.autosaveKey, this.currentValue); + } + }, }, mounted() { /* @@ -200,6 +211,14 @@ export default { labels: this.enableAutocomplete, snippets: this.enableAutocomplete, }); + + if (this.autosaveKey.length) { + const draft = getDraft(this.autosaveKey); + + if (draft && draft.length) { + this.setCurrentValue(draft); + } + } }, beforeDestroy() { const glForm = $(this.$refs['gl-form']).data('glForm'); @@ -228,9 +247,16 @@ export default { clear() { this.setCurrentValue(''); + this.clearDraft(); this.switchToEditor(); }, + clearDraft() { + if (this.autosaveKey.length) { + clearDraft(this.autosaveKey); + } + }, + switchToEditor() { if (this.modeIsPreview) { this.setMode('markdown'); |