Commit ef82859d authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'ce-4681-autosave' into 'master'

Autosave description in epics

See merge request gitlab-org/gitlab-ce!27296
parents 224916f8 c23c141e
...@@ -159,9 +159,23 @@ export default { ...@@ -159,9 +159,23 @@ export default {
return !!this.state.updatedAt; return !!this.state.updatedAt;
}, },
issueChanged() { issueChanged() {
const descriptionChanged = this.initialDescriptionText !== this.store.formState.description; const {
const titleChanged = this.initialTitleText !== this.store.formState.title; store: {
return descriptionChanged || titleChanged; formState: { description, title },
},
initialDescriptionText,
initialTitleText,
} = this;
if (initialDescriptionText || description) {
return initialDescriptionText !== description;
}
if (initialTitleText || title) {
return initialTitleText !== title;
}
return false;
}, },
defaultErrorMessage() { defaultErrorMessage() {
return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType }); return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType });
......
...@@ -145,6 +145,7 @@ export default { ...@@ -145,6 +145,7 @@ export default {
></div> ></div>
<textarea <textarea
v-if="descriptionText" v-if="descriptionText"
ref="textarea"
v-model="descriptionText" v-model="descriptionText"
:data-update-url="updateUrl" :data-update-url="updateUrl"
class="hidden js-task-list-field" class="hidden js-task-list-field"
......
...@@ -17,6 +17,7 @@ export default { ...@@ -17,6 +17,7 @@ export default {
<label class="sr-only" for="issuable-title"> Title </label> <label class="sr-only" for="issuable-title"> Title </label>
<input <input
id="issuable-title" id="issuable-title"
ref="input"
v-model="formState.title" v-model="formState.title"
class="form-control qa-title-input" class="form-control qa-title-input"
type="text" type="text"
......
<script> <script>
import $ from 'jquery';
import lockedWarning from './locked_warning.vue'; import lockedWarning from './locked_warning.vue';
import titleField from './fields/title.vue'; import titleField from './fields/title.vue';
import descriptionField from './fields/description.vue'; import descriptionField from './fields/description.vue';
import editActions from './edit_actions.vue'; import editActions from './edit_actions.vue';
import descriptionTemplate from './fields/description_template.vue'; import descriptionTemplate from './fields/description_template.vue';
import Autosave from '~/autosave';
import eventHub from '../event_hub';
export default { export default {
components: { components: {
...@@ -68,6 +71,47 @@ export default { ...@@ -68,6 +71,47 @@ export default {
return this.issuableTemplates.length; 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> </script>
...@@ -89,10 +133,11 @@ export default { ...@@ -89,10 +133,11 @@ export default {
'col-12': !hasIssuableTemplates, 'col-12': !hasIssuableTemplates,
}" }"
> >
<title-field :form-state="formState" :issuable-templates="issuableTemplates" /> <title-field ref="title" :form-state="formState" :issuable-templates="issuableTemplates" />
</div> </div>
</div> </div>
<description-field <description-field
ref="description"
:form-state="formState" :form-state="formState"
:markdown-preview-path="markdownPreviewPath" :markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath" :markdown-docs-path="markdownDocsPath"
......
---
title: Autosave description in epics
merge_request: 27296
author:
type: added
...@@ -470,4 +470,51 @@ describe('Issuable output', () => { ...@@ -470,4 +470,51 @@ describe('Issuable output', () => {
.catch(done.fail); .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);
});
});
}); });
...@@ -63,4 +63,8 @@ describe('Description field component', () => { ...@@ -63,4 +63,8 @@ describe('Description field component', () => {
expect(eventHub.$emit).toHaveBeenCalled(); expect(eventHub.$emit).toHaveBeenCalled();
}); });
it('has a ref named `textarea`', () => {
expect(vm.$refs.textarea).not.toBeNull();
});
}); });
...@@ -41,4 +41,8 @@ describe('Title field component', () => { ...@@ -41,4 +41,8 @@ describe('Title field component', () => {
expect(eventHub.$emit).toHaveBeenCalled(); expect(eventHub.$emit).toHaveBeenCalled();
}); });
it('has a ref named `input`', () => {
expect(vm.$refs.input).not.toBeNull();
});
}); });
import Vue from 'vue'; import Vue from 'vue';
import formComponent from '~/issue_show/components/form.vue'; import formComponent from '~/issue_show/components/form.vue';
import eventHub from '~/issue_show/event_hub';
describe('Inline edit form component', () => { describe('Inline edit form component', () => {
let vm; let vm;
let autosave;
let autosaveObj;
beforeEach(done => { beforeEach(done => {
autosaveObj = { reset: jasmine.createSpy() };
autosave = spyOnDependency(formComponent, 'Autosave').and.returnValue(autosaveObj);
const Component = Vue.extend(formComponent); const Component = Vue.extend(formComponent);
vm = new Component({ vm = new Component({
...@@ -53,4 +60,22 @@ describe('Inline edit form component', () => { ...@@ -53,4 +60,22 @@ describe('Inline edit form component', () => {
done(); 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);
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment