diff options
-rw-r--r-- | app/assets/javascripts/issue_show/components/app.vue | 18 | ||||
-rw-r--r-- | spec/javascripts/issue_show/components/app_spec.js | 33 |
2 files changed, 51 insertions, 0 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index f85d66e9b1d..e87a8ed7fea 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -152,6 +152,13 @@ hasUpdated() { return !!this.state.updatedAt; }, + issueChanged() { + const descriptionChanged = + this.initialDescriptionText !== this.store.formState.description; + const titleChanged = + this.initialTitleText !== this.store.formState.title; + return descriptionChanged || titleChanged; + }, }, created() { this.service = new Service(this.endpoint); @@ -176,6 +183,8 @@ } }); + window.addEventListener('beforeunload', this.handleBeforeUnloadEvent); + eventHub.$on('delete.issuable', this.deleteIssuable); eventHub.$on('update.issuable', this.updateIssuable); eventHub.$on('close.form', this.closeForm); @@ -186,8 +195,17 @@ eventHub.$off('update.issuable', this.updateIssuable); eventHub.$off('close.form', this.closeForm); eventHub.$off('open.form', this.openForm); + window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent); }, methods: { + handleBeforeUnloadEvent(e) { + const event = e; + if (this.showForm && this.issueChanged) { + event.returnValue = 'Are you sure you want to lose your issue information?'; + } + return undefined; + }, + openForm() { if (!this.showForm) { this.showForm = true; diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index 1454ca52018..9280db072b3 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -218,6 +218,39 @@ describe('Issuable output', () => { }); }); + describe('shows dialog when issue has unsaved changed', () => { + it('confirms on title change', (done) => { + vm.showForm = true; + vm.state.titleText = 'title has changed'; + const e = { returnValue: null }; + vm.handleBeforeUnloadEvent(e); + Vue.nextTick(() => { + expect(e.returnValue).not.toBeNull(); + done(); + }); + }); + + it('confirms on description change', (done) => { + vm.showForm = true; + vm.state.descriptionText = 'description has changed'; + const e = { returnValue: null }; + vm.handleBeforeUnloadEvent(e); + Vue.nextTick(() => { + expect(e.returnValue).not.toBeNull(); + done(); + }); + }); + + it('does nothing when nothing has changed', (done) => { + const e = { returnValue: null }; + vm.handleBeforeUnloadEvent(e); + Vue.nextTick(() => { + expect(e.returnValue).toBeNull(); + done(); + }); + }); + }); + describe('error when updating', () => { beforeEach(() => { spyOn(window, 'Flash').and.callThrough(); |