Commit 455a60db authored by Tom Quirk's avatar Tom Quirk Committed by Natalia Tepluhina

Refactor addDiscussionComment for immutability

- As per best practice, prefer immutability over destructive updates
when writing updates to Apollo store
-  Additionally, use computed value for mutation payload
parent c7e7a041
......@@ -56,7 +56,7 @@ export default {
</script>
<template>
<ApolloMutation
<apollo-mutation
v-slot="{ mutate, loading, error }"
:mutation="$options.destroyDesignMutation"
:variables="{
......@@ -69,5 +69,5 @@ export default {
v-on="$listeners"
>
<slot v-bind="{ mutate, loading, error }"></slot>
</ApolloMutation>
</apollo-mutation>
</template>
<script>
import { ApolloMutation } from 'vue-apollo';
import { s__ } from '~/locale';
import createFlash from '~/flash';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
......@@ -11,6 +12,7 @@ import { extractCurrentDiscussion } from '../../utils/design_management_utils';
export default {
components: {
ApolloMutation,
DesignNote,
ReplyPlaceholder,
DesignReplyForm,
......@@ -43,58 +45,61 @@ export default {
return {
discussionComment: '',
isFormRendered: false,
isNoteSaving: false,
};
},
computed: {
isSubmitButtonDisabled() {
return this.discussionComment.trim().length === 0;
mutationPayload() {
return {
noteableId: this.noteableId,
body: this.discussionComment,
discussionId: this.discussion.id,
};
},
},
methods: {
addDiscussionComment() {
this.isNoteSaving = true;
return this.$apollo
.mutate({
mutation: createNoteMutation,
variables: {
input: {
noteableId: this.noteableId,
body: this.discussionComment,
discussionId: this.discussion.id,
},
},
update: (store, { data: { createNote } }) => {
const data = store.readQuery({
query: getDesignQuery,
variables: {
id: this.designId,
version: this.designsVersion,
},
});
const currentDiscussion = extractCurrentDiscussion(
data.design.discussions,
this.discussion.id,
);
currentDiscussion.node.notes.edges.push({
__typename: 'NoteEdge',
node: createNote.note,
});
data.design.notesCount += 1;
store.writeQuery({ query: getDesignQuery, data });
addDiscussionComment(
store,
{
data: { createNote },
},
) {
const data = store.readQuery({
query: getDesignQuery,
variables: {
id: this.designId,
version: this.designsVersion,
},
});
const currentDiscussion = extractCurrentDiscussion(
data.design.discussions,
this.discussion.id,
);
currentDiscussion.node.notes.edges = [
...currentDiscussion.node.notes.edges,
{
__typename: 'NoteEdge',
node: createNote.note,
},
];
store.writeQuery({
query: getDesignQuery,
data: {
...data,
design: {
...data.design,
notesCount: data.design.notesCount + 1,
},
})
.then(() => {
this.discussionComment = '';
this.hideForm();
})
.catch(e => {
createFlash(s__('DesignManagement|Could not add a new comment. Please try again'));
throw e;
})
.finally(() => {
this.isNoteSaving = false;
});
},
});
},
onDone() {
this.discussionComment = '';
this.hideForm();
},
onError(e) {
createFlash(s__('DesignManagement|Could not add a new comment. Please try again'));
throw e;
},
hideForm() {
this.isFormRendered = false;
......@@ -103,6 +108,7 @@ export default {
this.isFormRendered = true;
},
},
createNoteMutation,
};
</script>
......@@ -121,14 +127,25 @@ export default {
:button-text="__('Reply...')"
@onClick="showForm"
/>
<design-reply-form
<apollo-mutation
v-else
v-model="discussionComment"
:is-saving="isNoteSaving"
:markdown-preview-path="markdownPreviewPath"
@submitForm="addDiscussionComment"
@cancelForm="hideForm"
/>
v-slot="{ mutate, loading, error }"
:mutation="$options.createNoteMutation"
:variables="{
input: mutationPayload,
}"
:update="addDiscussionComment"
@done="onDone"
@error="onError"
>
<design-reply-form
v-model="discussionComment"
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
@submitForm="mutate"
@cancelForm="hideForm"
/>
</apollo-mutation>
</div>
</div>
</div>
......
import { shallowMount } from '@vue/test-utils';
import { ApolloMutation } from 'vue-apollo';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import DesignDiscussion from 'ee/design_management/components/design_notes/design_discussion.vue';
import DesignNote from 'ee/design_management/components/design_notes/design_note.vue';
......@@ -49,6 +50,7 @@ describe('Design discussions component', () => {
},
stubs: {
ReplyPlaceholder,
ApolloMutation,
},
mocks: { $apollo },
});
......@@ -92,7 +94,7 @@ describe('Design discussions component', () => {
expect(mutate).toHaveBeenCalledWith(mutationVariables);
return wrapper.vm.addDiscussionComment();
return mutate({ variables: mutationVariables });
})
.then(() => {
expect(findReplyForm().exists()).toBe(false);
......
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