Commit d8151d8f authored by Natalia Tepluhina's avatar Natalia Tepluhina

Create a POC for 'immer' library

parent 8becb68e
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { uniqueId } from 'lodash'; import { uniqueId } from 'lodash';
import produce from 'immer';
import { defaultDataIdFromObject } from 'apollo-cache-inmemory'; import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql'; import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
...@@ -11,12 +12,17 @@ Vue.use(VueApollo); ...@@ -11,12 +12,17 @@ Vue.use(VueApollo);
const resolvers = { const resolvers = {
Mutation: { Mutation: {
updateActiveDiscussion: (_, { id = null, source }, { cache }) => { updateActiveDiscussion: (_, { id = null, source }, { cache }) => {
const data = cache.readQuery({ query: activeDiscussionQuery }); const sourceData = cache.readQuery({ query: activeDiscussionQuery });
data.activeDiscussion = {
__typename: 'ActiveDiscussion', const data = produce(sourceData, draftData => {
id, // eslint-disable-next-line no-param-reassign
source, draftData.activeDiscussion = {
}; __typename: 'ActiveDiscussion',
id,
source,
};
});
cache.writeQuery({ query: activeDiscussionQuery, data }); cache.writeQuery({ query: activeDiscussionQuery, data });
}, },
}, },
...@@ -37,6 +43,7 @@ const defaultClient = createDefaultClient( ...@@ -37,6 +43,7 @@ const defaultClient = createDefaultClient(
}, },
}, },
typeDefs, typeDefs,
assumeImmutableResults: true,
}, },
); );
......
...@@ -281,13 +281,8 @@ export default { ...@@ -281,13 +281,8 @@ export default {
.mutate({ .mutate({
mutation: moveDesignMutation, mutation: moveDesignMutation,
variables: this.designMoveVariables(newIndex, element), variables: this.designMoveVariables(newIndex, element),
update: (store, { data: { designManagementMove } }) => { update: (store, { data: { designManagementMove } }) =>
return updateDesignsOnStoreAfterReorder( updateDesignsOnStoreAfterReorder(store, designManagementMove, this.projectQueryBody),
store,
designManagementMove,
this.projectQueryBody,
);
},
optimisticResponse: moveDesignOptimisticResponse(this.reorderedDesigns), optimisticResponse: moveDesignOptimisticResponse(this.reorderedDesigns),
}) })
.catch(() => { .catch(() => {
......
/* eslint-disable @gitlab/require-i18n-strings */ /* eslint-disable @gitlab/require-i18n-strings */
import { groupBy } from 'lodash'; import { groupBy } from 'lodash';
import produce from 'immer';
import { deprecatedCreateFlash as createFlash } from '~/flash'; import { deprecatedCreateFlash as createFlash } from '~/flash';
import { extractCurrentDiscussion, extractDesign } from './design_management_utils'; import { extractCurrentDiscussion, extractDesign, extractDesigns } from './design_management_utils';
import { import {
ADD_IMAGE_DIFF_NOTE_ERROR, ADD_IMAGE_DIFF_NOTE_ERROR,
UPDATE_IMAGE_DIFF_NOTE_ERROR, UPDATE_IMAGE_DIFF_NOTE_ERROR,
...@@ -10,13 +11,20 @@ import { ...@@ -10,13 +11,20 @@ import {
designDeletionError, designDeletionError,
} from './error_messages'; } from './error_messages';
const designsOf = data => data.project.issue.designCollection.designs;
const isParticipating = (design, username) =>
design.issue.participants.nodes.some(participant => participant.username === username);
const deleteDesignsFromStore = (store, query, selectedDesigns) => { const deleteDesignsFromStore = (store, query, selectedDesigns) => {
const data = store.readQuery(query); const sourceData = store.readQuery(query);
const changedDesigns = data.project.issue.designCollection.designs.nodes.filter( const data = produce(sourceData, draftData => {
node => !selectedDesigns.includes(node.filename), const changedDesigns = designsOf(sourceData).nodes.filter(
); design => !selectedDesigns.includes(design.filename),
data.project.issue.designCollection.designs.nodes = [...changedDesigns]; );
designsOf(draftData).nodes = [...changedDesigns];
});
store.writeQuery({ store.writeQuery({
...query, ...query,
...@@ -33,13 +41,15 @@ const deleteDesignsFromStore = (store, query, selectedDesigns) => { ...@@ -33,13 +41,15 @@ const deleteDesignsFromStore = (store, query, selectedDesigns) => {
*/ */
const addNewVersionToStore = (store, query, version) => { const addNewVersionToStore = (store, query, version) => {
if (!version) return; if (!version) return;
const sourceData = store.readQuery(query);
const data = store.readQuery(query); const data = produce(sourceData, draftData => {
// eslint-disable-next-line no-param-reassign
data.project.issue.designCollection.versions.nodes = [ draftData.project.issue.designCollection.versions.nodes = [
version, version,
...data.project.issue.designCollection.versions.nodes, ...draftData.project.issue.designCollection.versions.nodes,
]; ];
});
store.writeQuery({ store.writeQuery({
...query, ...query,
...@@ -48,46 +58,41 @@ const addNewVersionToStore = (store, query, version) => { ...@@ -48,46 +58,41 @@ const addNewVersionToStore = (store, query, version) => {
}; };
const addDiscussionCommentToStore = (store, createNote, query, queryVariables, discussionId) => { const addDiscussionCommentToStore = (store, createNote, query, queryVariables, discussionId) => {
const data = store.readQuery({ const sourceData = store.readQuery({
query, query,
variables: queryVariables, variables: queryVariables,
}); });
const design = extractDesign(data); const newParticipant = {
const currentDiscussion = extractCurrentDiscussion(design.discussions, discussionId); __typename: 'User',
currentDiscussion.notes.nodes = [...currentDiscussion.notes.nodes, createNote.note]; ...createNote.note.author,
};
design.notesCount += 1;
if ( const data = produce(sourceData, draftData => {
!design.issue.participants.nodes.some( const design = extractDesign(draftData);
participant => participant.username === createNote.note.author.username, const currentDiscussion = extractCurrentDiscussion(design.discussions, discussionId);
) currentDiscussion.notes.nodes = [...currentDiscussion.notes.nodes, createNote.note];
) {
design.issue.participants.nodes = [ if (!isParticipating(design, createNote.note.author.username)) {
...design.issue.participants.nodes, design.issue.participants.nodes = [...design.issue.participants.nodes, newParticipant];
{ }
__typename: 'User',
...createNote.note.author, design.notesCount += 1;
}, });
];
}
store.writeQuery({ store.writeQuery({
query, query,
variables: queryVariables, variables: queryVariables,
data: { data,
...data,
design: {
...design,
},
},
}); });
}; };
const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) => { const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) => {
const data = store.readQuery({ const sourceData = store.readQuery({
query, query,
variables, variables,
}); });
const newDiscussion = { const newDiscussion = {
__typename: 'Discussion', __typename: 'Discussion',
id: createImageDiffNote.note.discussion.id, id: createImageDiffNote.note.discussion.id,
...@@ -101,100 +106,100 @@ const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) = ...@@ -101,100 +106,100 @@ const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) =
nodes: [createImageDiffNote.note], nodes: [createImageDiffNote.note],
}, },
}; };
const design = extractDesign(data);
const notesCount = design.notesCount + 1; const data = produce(sourceData, draftData => {
design.discussions.nodes = [...design.discussions.nodes, newDiscussion]; const design = extractDesign(draftData);
if ( design.notesCount += 1;
!design.issue.participants.nodes.some( design.discussions.nodes = [...design.discussions.nodes, newDiscussion];
participant => participant.username === createImageDiffNote.note.author.username,
) if (
) { !design.issue.participants.nodes.some(
design.issue.participants.nodes = [ participant => participant.username === createImageDiffNote.note.author.username,
...design.issue.participants.nodes, )
{ ) {
__typename: 'User', design.issue.participants.nodes = [
...createImageDiffNote.note.author, ...design.issue.participants.nodes,
}, {
]; __typename: 'User',
} ...createImageDiffNote.note.author,
},
];
}
});
store.writeQuery({ store.writeQuery({
query, query,
variables, variables,
data: { data,
...data,
design: {
...design,
notesCount,
},
},
}); });
}; };
const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables) => { const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables) => {
const data = store.readQuery({ const sourceData = store.readQuery({
query, query,
variables, variables,
}); });
const design = extractDesign(data); const data = produce(sourceData, draftData => {
const discussion = extractCurrentDiscussion( const design = extractDesign(draftData);
design.discussions, const discussion = extractCurrentDiscussion(
updateImageDiffNote.note.discussion.id, design.discussions,
); updateImageDiffNote.note.discussion.id,
);
discussion.notes = {
...discussion.notes, discussion.notes = {
nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)], ...discussion.notes,
}; nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
};
});
store.writeQuery({ store.writeQuery({
query, query,
variables, variables,
data: { data,
...data,
design,
},
}); });
}; };
const addNewDesignToStore = (store, designManagementUpload, query) => { const addNewDesignToStore = (store, designManagementUpload, query) => {
const data = store.readQuery(query); const sourceData = store.readQuery(query);
const currentDesigns = data.project.issue.designCollection.designs.nodes; const data = produce(sourceData, draftData => {
const existingDesigns = groupBy(currentDesigns, 'filename'); const currentDesigns = extractDesigns(draftData);
const newDesigns = currentDesigns.concat( const existingDesigns = groupBy(currentDesigns, 'filename');
designManagementUpload.designs.filter(d => !existingDesigns[d.filename]), const newDesigns = currentDesigns.concat(
); designManagementUpload.designs.filter(d => !existingDesigns[d.filename]),
);
let newVersionNode; let newVersionNode;
const findNewVersions = designManagementUpload.designs.find(design => design.versions); const findNewVersions = designManagementUpload.designs.find(design => design.versions);
if (findNewVersions) { if (findNewVersions) {
const findNewVersionsNodes = findNewVersions.versions.nodes; const findNewVersionsNodes = findNewVersions.versions.nodes;
if (findNewVersionsNodes && findNewVersionsNodes.length) { if (findNewVersionsNodes && findNewVersionsNodes.length) {
newVersionNode = [findNewVersionsNodes[0]]; newVersionNode = [findNewVersionsNodes[0]];
}
} }
}
const newVersions = [ const newVersions = [
...(newVersionNode || []), ...(newVersionNode || []),
...data.project.issue.designCollection.versions.nodes, ...draftData.project.issue.designCollection.versions.nodes,
]; ];
const updatedDesigns = {
__typename: 'DesignCollection',
designs: {
__typename: 'DesignConnection',
nodes: newDesigns,
},
versions: {
__typename: 'DesignVersionConnection',
nodes: newVersions,
},
};
data.project.issue.designCollection = updatedDesigns; const updatedDesigns = {
__typename: 'DesignCollection',
designs: {
__typename: 'DesignConnection',
nodes: newDesigns,
},
versions: {
__typename: 'DesignVersionConnection',
nodes: newVersions,
},
};
// eslint-disable-next-line no-param-reassign
draftData.project.issue.designCollection = updatedDesigns;
});
store.writeQuery({ store.writeQuery({
...query, ...query,
...@@ -203,8 +208,14 @@ const addNewDesignToStore = (store, designManagementUpload, query) => { ...@@ -203,8 +208,14 @@ const addNewDesignToStore = (store, designManagementUpload, query) => {
}; };
const moveDesignInStore = (store, designManagementMove, query) => { const moveDesignInStore = (store, designManagementMove, query) => {
const data = store.readQuery(query); const sourceData = store.readQuery(query);
data.project.issue.designCollection.designs = designManagementMove.designCollection.designs;
const data = produce(sourceData, draftData => {
// eslint-disable-next-line no-param-reassign
draftData.project.issue.designCollection.designs =
designManagementMove.designCollection.designs;
});
store.writeQuery({ store.writeQuery({
...query, ...query,
data, data,
......
---
title: Create a POC for 'immer' library
merge_request: 39738
author:
type: other
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"glob": "^7.1.6", "glob": "^7.1.6",
"graphql": "^14.7.0", "graphql": "^14.7.0",
"graphql-tag": "^2.10.1", "graphql-tag": "^2.10.1",
"immer": "^7.0.7",
"imports-loader": "^0.8.0", "imports-loader": "^0.8.0",
"ipaddr.js": "^1.9.1", "ipaddr.js": "^1.9.1",
"jed": "^1.1.1", "jed": "^1.1.1",
......
...@@ -5954,6 +5954,11 @@ immediate@~3.0.5: ...@@ -5954,6 +5954,11 @@ immediate@~3.0.5:
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
immer@^7.0.7:
version "7.0.7"
resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.7.tgz#9dfe713d49bf871cc59aedfce59b1992fa37a977"
integrity sha512-Q8yYwVADJXrNfp1ZUAh4XDHkcoE3wpdpb4mC5abDSajs2EbW8+cGdPyAnglMyLnm7EF6ojD2xBFX7L5i4TIytw==
import-fresh@^2.0.0: import-fresh@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
......
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