diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2017-05-22 10:40:33 +0000 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2017-05-22 10:40:33 +0000 |
commit | 3f996024cd2b7c30f8049e4b056a094100ece9f9 (patch) | |
tree | 351d89cd2124c314b2d1a25e59f885d30106ac9d | |
parent | 3c3b17a5a4b4f85f3f81f918a7e0c3a57f469eb7 (diff) | |
parent | 95efe5b3e32775e8b18d1a63f939855a3daa4a4e (diff) | |
download | gitlab-ce-3f996024cd2b7c30f8049e4b056a094100ece9f9.tar.gz |
Merge branch 'issue-edit-inline-locked-warning' into 'issue-edit-inline'
Show warning if realtime data has changed since the form has opened
See merge request !11495
6 files changed, 118 insertions, 3 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index c4154745bf8..c08d3dee755 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -90,12 +90,12 @@ export default { openForm() { if (!this.showForm) { this.showForm = true; - this.store.formState = { + this.store.formState = Object.assign(this.store.formState, { title: this.state.titleText, confidential: this.isConfidential, description: this.state.descriptionText, move_to_project_id: 0, - }; + }); } }, closeForm() { @@ -139,7 +139,14 @@ export default { resource: this.service, method: 'getData', successCallback: (res) => { - this.store.updateState(res.json()); + const data = res.json(); + const shouldUpdate = this.store.stateShouldUpdate(data); + + this.store.updateState(data); + + if (this.showForm && (shouldUpdate.title || shouldUpdate.description)) { + this.store.formState.lockedWarningVisible = true; + } }, errorCallback(err) { throw new Error(err); diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index 1b50b1dcd03..c7fb63365ea 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -1,4 +1,5 @@ <script> + import lockedWarning from './locked_warning.vue'; import titleField from './fields/title.vue'; import descriptionField from './fields/description.vue'; import editActions from './edit_actions.vue'; @@ -33,6 +34,7 @@ }, }, components: { + lockedWarning, titleField, descriptionField, editActions, @@ -44,6 +46,7 @@ <template> <form> + <locked-warning v-if="formState.lockedWarningVisible" /> <title-field :form-state="formState" /> <confidential-checkbox diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issue_show/components/locked_warning.vue new file mode 100644 index 00000000000..1c2789f154a --- /dev/null +++ b/app/assets/javascripts/issue_show/components/locked_warning.vue @@ -0,0 +1,20 @@ +<script> + export default { + computed: { + currentPath() { + return location.pathname; + }, + }, + }; +</script> + +<template> + <div class="alert alert-danger"> + Someone edited the issue at the same time you did. Please check out + <a + :href="currentPath" + target="_blank" + rel="nofollow">the issue</a> + and make sure your changes will not unintentionally remove theirs. + </div> +</template> diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js index 1135bc0bfb5..ea6f4e6a4fa 100644 --- a/app/assets/javascripts/issue_show/stores/index.js +++ b/app/assets/javascripts/issue_show/stores/index.js @@ -16,6 +16,7 @@ export default class Store { title: '', confidential: false, description: '', + lockedWarningVisible: false, move_to_project_id: 0, }; } @@ -28,4 +29,11 @@ export default class Store { this.state.taskStatus = data.task_status; this.state.updatedAt = data.updated_at; } + + stateShouldUpdate(data) { + return { + title: this.state.titleText !== data.title_text, + description: this.state.descriptionText !== data.description_text, + }; + } } diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index 91ae3cfd97c..3247f83d551 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -285,4 +285,36 @@ describe('Issuable output', () => { }); }); }); + + describe('open form', () => { + it('shows locked warning if form is open & data is different', (done) => { + Vue.http.interceptors.push(issueShowInterceptor(issueShowData.initialRequest)); + + Vue.nextTick() + .then(() => new Promise((resolve) => { + setTimeout(resolve); + })) + .then(() => { + vm.openForm(); + + Vue.http.interceptors.push(issueShowInterceptor(issueShowData.secondRequest)); + + return new Promise((resolve) => { + setTimeout(resolve); + }); + }) + .then(() => { + expect( + vm.formState.lockedWarningVisible, + ).toBeTruthy(); + + expect( + vm.$el.querySelector('.alert'), + ).not.toBeNull(); + + done(); + }) + .catch(done.fail); + }); + }); }); diff --git a/spec/javascripts/issue_show/components/form_spec.js b/spec/javascripts/issue_show/components/form_spec.js new file mode 100644 index 00000000000..d91dc3ce1d0 --- /dev/null +++ b/spec/javascripts/issue_show/components/form_spec.js @@ -0,0 +1,45 @@ +import Vue from 'vue'; +import formComponent from '~/issue_show/components/form.vue'; + +describe('Inline edit form component', () => { + let vm; + + beforeEach((done) => { + const Component = Vue.extend(formComponent); + + vm = new Component({ + propsData: { + canDestroy: true, + canMove: true, + formState: { + title: 'b', + description: 'a', + lockedWarningVisible: false, + }, + markdownPreviewUrl: '/', + markdownDocs: '/', + projectsAutocompleteUrl: '/', + }, + }).$mount(); + + Vue.nextTick(done); + }); + + it('hides locked warning by default', () => { + expect( + vm.$el.querySelector('.alert'), + ).toBeNull(); + }); + + it('shows locked warning if formState is different', (done) => { + vm.formState.lockedWarningVisible = true; + + Vue.nextTick(() => { + expect( + vm.$el.querySelector('.alert'), + ).not.toBeNull(); + + done(); + }); + }); +}); |