From 5a9a42f1b13da96d8130fd6d55820af82037ac50 Mon Sep 17 00:00:00 2001
From: Jure Triglav <juretriglav@gmail.com>
Date: Tue, 28 Jul 2020 12:30:33 +0200
Subject: [PATCH] fix: adjust how reviews are cached client-side and add
 relations on the server

---
 .../src/components/DecisionPage.js            | 62 ++++++++++++++-----
 .../src/components/decision/DecisionForm.js   | 14 ++---
 server/model-manuscript/src/graphql.js        | 14 +++++
 server/model-review/src/review.js             | 23 +++++++
 4 files changed, 90 insertions(+), 23 deletions(-)

diff --git a/app/components/component-review/src/components/DecisionPage.js b/app/components/component-review/src/components/DecisionPage.js
index a157147ae6..1efa638416 100644
--- a/app/components/component-review/src/components/DecisionPage.js
+++ b/app/components/component-review/src/components/DecisionPage.js
@@ -294,7 +294,7 @@ const decisionSections = ({
 const DecisionPage = ({ match }) => {
   // Hooks from the old world
   const [makeDecision] = useMutation(makeDecisionMutation, {
-    refetchQueries: [query],
+    // refetchQueries: [query],
   })
   const [updateReviewMutation] = useMutation(updateReviewMutationQuery)
 
@@ -356,25 +356,57 @@ const DecisionPage = ({ match }) => {
         id: review.id || undefined,
         input: reviewData,
       },
-      update: (proxy, { data: { updateReview } }) => {
-        const data = proxy.readQuery({
-          query,
-          variables: {
-            id: manuscript.id,
+      update: (cache, { data: { updateReview } }) => {
+        cache.modify({
+          id: cache.identify(manuscript),
+          fields: {
+            reviews(existingReviewRefs = [], { readField }) {
+              const newReviewRef = cache.writeFragment({
+                data: updateReview,
+                fragment: gql`
+                  fragment NewReview on Review {
+                    id
+                  }
+                `,
+              })
+
+              if (
+                existingReviewRefs.some(
+                  ref => readField('id', ref) === updateReview.id,
+                )
+              ) {
+                return existingReviewRefs
+              }
+
+              return [...existingReviewRefs, newReviewRef]
+            },
           },
         })
-        const reviewIndex = data.manuscript.reviews.findIndex(
-          review => review.id === updateReview.id,
-        )
-        if (reviewIndex < 0) {
-          data.manuscript.reviews.push(updateReview)
-        } else {
-          data.manuscript.reviews[reviewIndex] = updateReview
-        }
-        proxy.writeQuery({ query, data })
       },
     })
   }
+  // const manuscriptFragment = cache.readFragment({
+  //   id: cache.identify(manuscript),
+  //   fragment: gql`
+  //     fragment MyManuscript on Manuscript {
+  //       id
+  //       reviews
+  //     }
+  //   `,
+  // })
+
+  // cache.writeFragment()
+
+  // const reviewIndex = data.manuscript.reviews.findIndex(
+  //   review => review.id === updateReview.id,
+  // )
+  // if (reviewIndex < 0) {
+  //   data.manuscript.reviews.push(updateReview)
+  // } else {
+  //   data.manuscript.reviews[reviewIndex] = updateReview
+  // }
+  // cache.writeQuery({ query, data })
+  //   },
   // },
   //   }).then(() => {
   //     history.push('/dashboard')
diff --git a/app/components/component-review/src/components/decision/DecisionForm.js b/app/components/component-review/src/components/decision/DecisionForm.js
index 727250a78b..fb0b035a64 100644
--- a/app/components/component-review/src/components/decision/DecisionForm.js
+++ b/app/components/component-review/src/components/decision/DecisionForm.js
@@ -1,7 +1,7 @@
 import React, { useContext } from 'react'
 import { NoteEditor } from 'xpub-edit'
 import { cloneDeep, omit } from 'lodash'
-import { FieldArray, Field } from 'formik'
+import { Field } from 'formik'
 import {
   Button,
   Flexbox,
@@ -28,16 +28,18 @@ import {
   SectionAction,
 } from '../style'
 
-const NoteDecision = (updateReview, uploadFile) => props => (
+const NoteDecision = ({ updateReview, uploadFile }) => (
   <>
     <Field
       component={NoteInput}
+      key="commentinput"
       name="comments"
       updateReview={updateReview}
       validate={required}
     />
     <Field
       component={AttachmentsInput('note')}
+      key="attachmentinput"
       updateReview={updateReview}
       uploadFile={uploadFile}
     />
@@ -132,17 +134,13 @@ const RecommendationInput = ({
 }
 
 const DecisionForm = ({ handleSubmit, uploadFile, updateReview, isValid }) => (
-  <Container>
+  <Container key="decisionform">
     <form onSubmit={handleSubmit}>
       <SectionHeader>
         <Title>Decision</Title>
       </SectionHeader>
       <SectionRow key="note">
-        <FieldArray
-          component={NoteDecision(updateReview, uploadFile)}
-          key="comments-array"
-          name="comments"
-        />
+        <NoteDecision updateReview={updateReview} uploadFile={uploadFile} />
       </SectionRow>
       <SectionRowGrid>
         <Field
diff --git a/server/model-manuscript/src/graphql.js b/server/model-manuscript/src/graphql.js
index f0b1aca00e..39b107a3d1 100644
--- a/server/model-manuscript/src/graphql.js
+++ b/server/model-manuscript/src/graphql.js
@@ -294,6 +294,20 @@ const resolvers = {
     submission(parent) {
       return JSON.stringify(parent.submission)
     },
+    async reviews(parent, _, ctx) {
+      return parent.reviews
+        ? parent.reviews
+        : (
+            await ctx.models.Manuscript.query().findById(parent.id)
+          ).$relatedQuery('reviews')
+    },
+    async teams(parent, _, ctx) {
+      return parent.teams
+        ? parent.teams
+        : (
+            await ctx.models.Manuscript.query().findById(parent.id)
+          ).$relatedQuery('teams')
+    },
   },
   ManuscriptVersion: {
     submission(parent) {
diff --git a/server/model-review/src/review.js b/server/model-review/src/review.js
index 46c45567ec..bc07009f5a 100644
--- a/server/model-review/src/review.js
+++ b/server/model-review/src/review.js
@@ -51,6 +51,29 @@ class Review extends BaseModel {
     }
   }
 
+  static get relationMappings() {
+    const { Manuscript, User } = require('@pubsweet/models')
+
+    return {
+      manuscript: {
+        relation: BaseModel.BelongsToOneRelation,
+        modelClass: Manuscript,
+        join: {
+          from: 'reviews.manuscriptId',
+          to: 'manuscripts.id',
+        },
+      },
+      user: {
+        relation: BaseModel.BelongsToOneRelation,
+        modelClass: User,
+        join: {
+          from: 'reviews.userId',
+          to: 'users.id',
+        },
+      },
+    }
+  }
+
   async $beforeDelete() {
     const File = require('../../model-file/src/file')
     const files = await File.findByObject({
-- 
GitLab