diff options
author | Kushal Pandya <kushalspandya@gmail.com> | 2019-04-16 08:20:38 +0000 |
---|---|---|
committer | Kushal Pandya <kushalspandya@gmail.com> | 2019-04-16 08:20:38 +0000 |
commit | ef82859d7d8ea70b29f600193fc18bdf5aea895e (patch) | |
tree | e712f858aaf35f4a0fa694bb8aec792420b76faf | |
parent | 224916f843d3cc7beff383217d199a8cabfec263 (diff) | |
parent | c23c141e872d3a8a2f32f3fd6ed7901eaef88465 (diff) | |
download | gitlab-ce-ef82859d7d8ea70b29f600193fc18bdf5aea895e.tar.gz |
Merge branch 'ce-4681-autosave' into 'master'
Autosave description in epics
See merge request gitlab-org/gitlab-ce!27296
9 files changed, 150 insertions, 4 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index bd757a76ee7..ab0b4231255 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -159,9 +159,23 @@ export default { return !!this.state.updatedAt; }, issueChanged() { - const descriptionChanged = this.initialDescriptionText !== this.store.formState.description; - const titleChanged = this.initialTitleText !== this.store.formState.title; - return descriptionChanged || titleChanged; + const { + store: { + formState: { description, title }, + }, + initialDescriptionText, + initialTitleText, + } = this; + + if (initialDescriptionText || description) { + return initialDescriptionText !== description; + } + + if (initialTitleText || title) { + return initialTitleText !== title; + } + + return false; }, defaultErrorMessage() { return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType }); diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue index 732184dc782..385e9543973 100644 --- a/app/assets/javascripts/issue_show/components/description.vue +++ b/app/assets/javascripts/issue_show/components/description.vue @@ -145,6 +145,7 @@ export default { ></div> <textarea v-if="descriptionText" + ref="textarea" v-model="descriptionText" :data-update-url="updateUrl" class="hidden js-task-list-field" diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue index c3d7ba4907f..a3371cb9614 100644 --- a/app/assets/javascripts/issue_show/components/fields/title.vue +++ b/app/assets/javascripts/issue_show/components/fields/title.vue @@ -17,6 +17,7 @@ export default { <label class="sr-only" for="issuable-title"> Title </label> <input id="issuable-title" + ref="input" v-model="formState.title" class="form-control qa-title-input" type="text" diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index eade31f1d14..528ccb77efc 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -1,9 +1,12 @@ <script> +import $ from 'jquery'; import lockedWarning from './locked_warning.vue'; import titleField from './fields/title.vue'; import descriptionField from './fields/description.vue'; import editActions from './edit_actions.vue'; import descriptionTemplate from './fields/description_template.vue'; +import Autosave from '~/autosave'; +import eventHub from '../event_hub'; export default { components: { @@ -68,6 +71,47 @@ export default { return this.issuableTemplates.length; }, }, + created() { + eventHub.$on('delete.issuable', this.resetAutosave); + eventHub.$on('update.issuable', this.resetAutosave); + eventHub.$on('close.form', this.resetAutosave); + }, + mounted() { + this.initAutosave(); + }, + beforeDestroy() { + eventHub.$off('delete.issuable', this.resetAutosave); + eventHub.$off('update.issuable', this.resetAutosave); + eventHub.$off('close.form', this.resetAutosave); + }, + methods: { + initAutosave() { + const { + description: { + $refs: { textarea }, + }, + title: { + $refs: { input }, + }, + } = this.$refs; + + this.autosaveDescription = new Autosave($(textarea), [ + document.location.pathname, + document.location.search, + 'description', + ]); + + this.autosaveTitle = new Autosave($(input), [ + document.location.pathname, + document.location.search, + 'title', + ]); + }, + resetAutosave() { + this.autosaveDescription.reset(); + this.autosaveTitle.reset(); + }, + }, }; </script> @@ -89,10 +133,11 @@ export default { 'col-12': !hasIssuableTemplates, }" > - <title-field :form-state="formState" :issuable-templates="issuableTemplates" /> + <title-field ref="title" :form-state="formState" :issuable-templates="issuableTemplates" /> </div> </div> <description-field + ref="description" :form-state="formState" :markdown-preview-path="markdownPreviewPath" :markdown-docs-path="markdownDocsPath" diff --git a/changelogs/unreleased/ce-4681-autosave.yml b/changelogs/unreleased/ce-4681-autosave.yml new file mode 100644 index 00000000000..029954ec92b --- /dev/null +++ b/changelogs/unreleased/ce-4681-autosave.yml @@ -0,0 +1,5 @@ +--- +title: Autosave description in epics +merge_request: 27296 +author: +type: added diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index dfc889773c1..2770743937e 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -470,4 +470,51 @@ describe('Issuable output', () => { .catch(done.fail); }); }); + + describe('issueChanged', () => { + beforeEach(() => { + vm.store.formState.title = ''; + vm.store.formState.description = ''; + vm.initialDescriptionText = ''; + vm.initialTitleText = ''; + }); + + it('returns true when title is changed', () => { + vm.store.formState.title = 'RandomText'; + + expect(vm.issueChanged).toBe(true); + }); + + it('returns false when title is empty null', () => { + vm.store.formState.title = null; + + expect(vm.issueChanged).toBe(false); + }); + + it('returns false when `initialTitleText` is null and `formState.title` is empty string', () => { + vm.store.formState.title = ''; + vm.initialTitleText = null; + + expect(vm.issueChanged).toBe(false); + }); + + it('returns true when description is changed', () => { + vm.store.formState.description = 'RandomText'; + + expect(vm.issueChanged).toBe(true); + }); + + it('returns false when description is empty null', () => { + vm.store.formState.title = null; + + expect(vm.issueChanged).toBe(false); + }); + + it('returns false when `initialDescriptionText` is null and `formState.description` is empty string', () => { + vm.store.formState.description = ''; + vm.initialDescriptionText = null; + + expect(vm.issueChanged).toBe(false); + }); + }); }); diff --git a/spec/javascripts/issue_show/components/fields/description_spec.js b/spec/javascripts/issue_show/components/fields/description_spec.js index 2c3efc8d4d4..f5f87a6bfbf 100644 --- a/spec/javascripts/issue_show/components/fields/description_spec.js +++ b/spec/javascripts/issue_show/components/fields/description_spec.js @@ -63,4 +63,8 @@ describe('Description field component', () => { expect(eventHub.$emit).toHaveBeenCalled(); }); + + it('has a ref named `textarea`', () => { + expect(vm.$refs.textarea).not.toBeNull(); + }); }); diff --git a/spec/javascripts/issue_show/components/fields/title_spec.js b/spec/javascripts/issue_show/components/fields/title_spec.js index 4b96a1feb29..62dff983250 100644 --- a/spec/javascripts/issue_show/components/fields/title_spec.js +++ b/spec/javascripts/issue_show/components/fields/title_spec.js @@ -41,4 +41,8 @@ describe('Title field component', () => { expect(eventHub.$emit).toHaveBeenCalled(); }); + + it('has a ref named `input`', () => { + expect(vm.$refs.input).not.toBeNull(); + }); }); diff --git a/spec/javascripts/issue_show/components/form_spec.js b/spec/javascripts/issue_show/components/form_spec.js index 523954013cf..b0f4ab2b12d 100644 --- a/spec/javascripts/issue_show/components/form_spec.js +++ b/spec/javascripts/issue_show/components/form_spec.js @@ -1,10 +1,17 @@ import Vue from 'vue'; import formComponent from '~/issue_show/components/form.vue'; +import eventHub from '~/issue_show/event_hub'; describe('Inline edit form component', () => { let vm; + let autosave; + let autosaveObj; beforeEach(done => { + autosaveObj = { reset: jasmine.createSpy() }; + + autosave = spyOnDependency(formComponent, 'Autosave').and.returnValue(autosaveObj); + const Component = Vue.extend(formComponent); vm = new Component({ @@ -53,4 +60,22 @@ describe('Inline edit form component', () => { done(); }); }); + + it('initialized Autosave on mount', () => { + expect(autosave).toHaveBeenCalledTimes(2); + }); + + it('calls reset on autosave when eventHub emits appropriate events', () => { + eventHub.$emit('close.form'); + + expect(autosaveObj.reset).toHaveBeenCalledTimes(2); + + eventHub.$emit('delete.issuable'); + + expect(autosaveObj.reset).toHaveBeenCalledTimes(4); + + eventHub.$emit('update.issuable'); + + expect(autosaveObj.reset).toHaveBeenCalledTimes(6); + }); }); |