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
This commit is contained in:
Filipa Lacerda 2017-05-22 10:40:33 +00:00
commit 3f996024cd
6 changed files with 118 additions and 3 deletions

View file

@ -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);

View file

@ -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

View file

@ -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>

View file

@ -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,
};
}
}

View file

@ -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);
});
});
});

View file

@ -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();
});
});
});