From af5f914309f3fc9812bdd79619169621e0714834 Mon Sep 17 00:00:00 2001
From: Audrey Hamelers <hamelers@ebi.ac.uk>
Date: Mon, 4 Mar 2019 17:18:44 +0000
Subject: [PATCH] #239

---
 .../ResolveDuplicates.jsx                     | 88 +++++++++++++------
 app/components/operations.js                  | 15 ++++
 app/components/submission-wizard/Submit.jsx   | 25 ++++--
 .../submission-wizard/SubmitPage.jsx          |  3 +-
 .../submission-wizard/operations.js           | 15 ----
 .../entities/manuscript/data-access.js        |  6 +-
 .../xpub-model/entities/manuscript/index.js   |  2 +-
 7 files changed, 96 insertions(+), 58 deletions(-)
 rename app/components/{submission-wizard => }/ResolveDuplicates.jsx (73%)

diff --git a/app/components/submission-wizard/ResolveDuplicates.jsx b/app/components/ResolveDuplicates.jsx
similarity index 73%
rename from app/components/submission-wizard/ResolveDuplicates.jsx
rename to app/components/ResolveDuplicates.jsx
index cf80f7b9c..e96148528 100644
--- a/app/components/submission-wizard/ResolveDuplicates.jsx
+++ b/app/components/ResolveDuplicates.jsx
@@ -3,10 +3,10 @@ import { withRouter } from 'react-router'
 import { Mutation } from 'react-apollo'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
-import { H3, H4, Button, Icon, Link } from '@pubsweet/ui'
-import { B, Buttons, Close, CloseButton, Portal, Notification } from '../ui'
-import { States, timeSince } from '../dashboard'
-import Citation from './Citation'
+import { Action, H3, H4, Button, Icon, Link } from '@pubsweet/ui'
+import { B, Buttons, Close, CloseButton, Portal, Notification } from './ui'
+import { States, timeSince } from './dashboard'
+import Citation from './submission-wizard/Citation'
 import { REPLACE_MANUSCRIPT, CHECK_DUPES } from './operations'
 
 const Columns = styled.div`
@@ -19,6 +19,9 @@ const Columns = styled.div`
   }
   h4 {
     margin: 0;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
   }
   button {
     display: flex;
@@ -54,24 +57,52 @@ const FlexP = styled.div`
 `
 class ResolveDuplicates extends React.Component {
   state = {
-    error: false,
+    error: null,
     duplicates: this.props.duplicates,
   }
-  unsetDupe = () => {
-    const { duplicates } = this.state
-    const { current } = this.props
-    if (
-      current.meta.articleIds.find(id => id.pubIdType === 'pmid').id ===
-      duplicates[0].meta.articleIds.find(id => id.pubIdType === 'pmid').id
-    ) {
-      this.setState({ error: true })
+  unsetDupe = dupe => {
+    const { manuscript: current, note, duplicates } = this.props
+    const dList = dupe.meta.articleIds ? dupe.meta.articleIds : []
+    const cList = current.meta.articleIds ? current.meta.articleIds : []
+    const badId = cList.find(aid => dList.includes(aid.id))
+    if (badId) {
+      this.setState({ error: badId.pubIdType })
     } else {
-      duplicates.shift()
+      const dNote = dupe.notes
+        ? dupe.notes.find(n => n.notesType === 'notDuplicates')
+        : null
+      if (note) {
+        const array = JSON.parse(note.content)
+        this.props.changeNote({
+          id: note.id,
+          content: JSON.stringify(array.push(dupe.id)),
+        })
+      } else {
+        this.props.newNote({
+          manuscriptId: current.id,
+          notesType: 'notDuplicates',
+          content: JSON.stringify([dupe.id]),
+        })
+      }
+      if (dNote) {
+        const array = JSON.parse(note.content)
+        this.props.changeNote({
+          id: dNote.id,
+          content: JSON.stringify(array.push(current.id)),
+        })
+      } else {
+        this.props.newNote({
+          manuscriptId: dupe.id,
+          notesType: 'notDuplicates',
+          content: JSON.stringify([current.id]),
+        })
+      }
+      duplicates.filter(d => d.id !== dupe.id)
       this.setState({ duplicates })
     }
   }
   render() {
-    const { close, current } = this.props
+    const { close, manuscript: current } = this.props
     const { duplicates, error } = this.state
     return (
       <Mutation
@@ -118,7 +149,7 @@ class ResolveDuplicates extends React.Component {
                 {error && (
                   <div style={{ flex: '0 0 100%' }}>
                     <Notification type="error">
-                      Two articles cannot have the same PMID.
+                      Two articles cannot have the same {error.toUpperCase()}.
                     </Notification>
                   </div>
                 )}
@@ -130,7 +161,7 @@ class ResolveDuplicates extends React.Component {
                       <B>Status:</B> {current.status}
                     </span>
                     <span>
-                      <B>Last updated:</B> {timeSince(current.updated)}
+                      <B>Updated:</B> {timeSince(current.updated)} ago
                     </span>
                   </FlexP>
                   <p>
@@ -154,7 +185,16 @@ class ResolveDuplicates extends React.Component {
                 {duplicates.map((dupe, i) => (
                   <React.Fragment key={dupe.id}>
                     <Dupes>
-                      <H4>{dupe.id}</H4>
+                      <H4>
+                        {dupe.id}
+                        <Action
+                          onClick={() => this.unsetDupe(dupe)}
+                          style={{ float: 'right' }}
+                        >
+                          <Icon color="currentColor">x</Icon>
+                          Not a duplicate!
+                        </Action>
+                      </H4>
                       <Link
                         target="_blank"
                         to={`/submission/${dupe.id}/${
@@ -168,7 +208,7 @@ class ResolveDuplicates extends React.Component {
                           <B>Status:</B> {dupe.status}
                         </span>
                         <span>
-                          <B>Last updated:</B> {timeSince(dupe.updated)}
+                          <B>Updated:</B> {timeSince(dupe.updated)} ago
                         </span>
                       </FlexP>
                       <p>
@@ -189,16 +229,6 @@ class ResolveDuplicates extends React.Component {
                         Transfer grants &amp; remove this
                       </Button>
                     </Dupes>
-                    {/* i === 0 && (
-                      <p style={{ flex: '0 0 100%', textAlign: 'center' }}>
-                        <Button
-                          onClick={() => this.unsetDupe()}
-                          style={{ margin: '0 auto' }}
-                        >
-                          These two are not duplicates!
-                        </Button>
-                      </p>
-                    ) */}
                     {i !== duplicates.length - 1 && <br />}
                   </React.Fragment>
                 ))}
diff --git a/app/components/operations.js b/app/components/operations.js
index 8cc81602e..d13f458e8 100644
--- a/app/components/operations.js
+++ b/app/components/operations.js
@@ -129,3 +129,18 @@ export const UPDATE_NOTE = gql`
     }
   }
 `
+
+export const CHECK_DUPES = gql`
+  query($id: ID!, $articleIds: [String], $title: String!) {
+    checkDuplicates(id: $id, articleIds: $articleIds, title: $title) {
+      ...ManuscriptFragment
+    }
+  }
+  ${ManuscriptFragment}
+`
+
+export const REPLACE_MANUSCRIPT = gql`
+  mutation ReplaceManuscript($keepId: ID!, $throwId: ID!) {
+    replaceManuscript(keepId: $keepId, throwId: $throwId)
+  }
+`
diff --git a/app/components/submission-wizard/Submit.jsx b/app/components/submission-wizard/Submit.jsx
index aa7e91c0d..3aabe5719 100644
--- a/app/components/submission-wizard/Submit.jsx
+++ b/app/components/submission-wizard/Submit.jsx
@@ -24,8 +24,8 @@ import { FileThumbnails } from '../preview-files'
 import ManuscriptPreview from '../ManuscriptPreview'
 import { NoteMutations } from '../SubmissionMutations'
 import GrantSearch from '../GrantSearch'
+import ResolveDuplicates from '../ResolveDuplicates'
 import Citation from './Citation'
-import ResolveDuplicates from './ResolveDuplicates'
 import SelectReviewer from './SelectReviewer'
 import SubmitForm from './SubmitForm'
 import SubmitHighlights from './SubmitHighlights'
@@ -52,6 +52,7 @@ const ErrorMessage = styled.p`
 `
 const ReviewerWithMutations = NoteMutations(SelectReviewer)
 const PubMedWithMutations = NoteMutations(PubMedSearch)
+const DuplicatesWithMutations = NoteMutations(ResolveDuplicates)
 
 class Submit extends React.Component {
   constructor(props) {
@@ -81,7 +82,7 @@ class Submit extends React.Component {
   formatName = name =>
     `${name.title ? `${name.title} ` : ''}${name.givenNames} ${name.surname}`
   render() {
-    const { currentUser, manuscript, duplicates } = this.props
+    const { currentUser, manuscript, duplicates: checkDupes } = this.props
     const {
       id: mId,
       meta,
@@ -132,7 +133,14 @@ class Submit extends React.Component {
         teams && teams.find(team => team.role === 'submitter')
           ? teams.find(team => team.role === 'submitter').teamMembers[0]
           : null
-
+      let notDupes = []
+      const dupeNote = notes
+        ? notes.find(n => n.notesType === 'notDuplicates')
+        : null
+      if (dupeNote) {
+        notDupes = JSON.parse(dupeNote.content)
+      }
+      const duplicates = checkDupes.filter(d => !notDupes.includes(d.id))
       const citationInformation = {
         title: 'Citation',
         content: <Citation journal={journal} metadata={meta} />,
@@ -147,7 +155,7 @@ class Submit extends React.Component {
         ),
         error:
           (currentUser.admin && status === 'submitted' && unmatchedJournal) ||
-          duplicates ? (
+          duplicates.length > 0 ? (
             <React.Fragment>
               {unmatchedJournal && (
                 <ErrorMessage>
@@ -157,7 +165,7 @@ class Submit extends React.Component {
                   Journal is not in the NLM Catalog.
                 </ErrorMessage>
               )}
-              {duplicates && (
+              {duplicates.length > 0 && (
                 <React.Fragment>
                   <Button
                     onClick={() => this.setState({ prune: true })}
@@ -425,11 +433,12 @@ class Submit extends React.Component {
               </PanelContent>
             </div>
           </EditPanel>
-          {duplicates && prune && (
-            <ResolveDuplicates
+          {duplicates.length > 0 && prune && (
+            <DuplicatesWithMutations
               close={() => this.setState({ prune: false })}
-              current={manuscript}
               duplicates={duplicates}
+              manuscript={manuscript}
+              note={dupeNote && dupeNote.id}
             />
           )}
         </PreviewPage>
diff --git a/app/components/submission-wizard/SubmitPage.jsx b/app/components/submission-wizard/SubmitPage.jsx
index 950751284..cbc7f4014 100755
--- a/app/components/submission-wizard/SubmitPage.jsx
+++ b/app/components/submission-wizard/SubmitPage.jsx
@@ -4,8 +4,7 @@ import { Query } from 'react-apollo'
 import { Loading, LoadingIcon } from '../ui'
 import SubmissionHeader from '../SubmissionHeader'
 import { ManuscriptMutations } from '../SubmissionMutations'
-import { GET_MANUSCRIPT } from '../operations'
-import { CHECK_DUPES } from './operations'
+import { GET_MANUSCRIPT, CHECK_DUPES } from '../operations'
 import Submit from './Submit'
 
 const SubmitWithMutations = ManuscriptMutations(Submit)
diff --git a/app/components/submission-wizard/operations.js b/app/components/submission-wizard/operations.js
index a49070839..6a5373f30 100644
--- a/app/components/submission-wizard/operations.js
+++ b/app/components/submission-wizard/operations.js
@@ -39,21 +39,6 @@ export const CREATE_MANUSCRIPT = gql`
   }
 `
 
-export const CHECK_DUPES = gql`
-  query($id: ID!, $articleIds: [String], $title: String!) {
-    checkDuplicates(id: $id, articleIds: $articleIds, title: $title) {
-      ...ManuscriptFragment
-    }
-  }
-  ${ManuscriptFragment}
-`
-
-export const REPLACE_MANUSCRIPT = gql`
-  mutation ReplaceManuscript($keepId: ID!, $throwId: ID!) {
-    replaceManuscript(keepId: $keepId, throwId: $throwId)
-  }
-`
-
 export const SUBMIT_MANUSCRIPT = gql`
   mutation SubmitManuscript($data: ManuscriptInput!) {
     submitManuscript(data: $data) {
diff --git a/server/xpub-model/entities/manuscript/data-access.js b/server/xpub-model/entities/manuscript/data-access.js
index 5da28aae7..b8fe93964 100644
--- a/server/xpub-model/entities/manuscript/data-access.js
+++ b/server/xpub-model/entities/manuscript/data-access.js
@@ -372,12 +372,12 @@ class Manuscript extends EpmcBaseModel {
       ? await Manuscript.query()
           .whereJsonSupersetOf('meta,article_ids', [{ id }])
           .whereNull('manuscript.deleted')
-          .eager('journal')
+          .eager('[journal, notes]')
       : await Manuscript.query()
           .whereJsonSupersetOf('meta,article_ids', [{ id }])
           .whereIn('id', manuscriptIds)
           .whereNull('manuscript.deleted')
-          .eager('journal')
+          .eager('[journal, notes]')
     return manuscripts
   }
 
@@ -385,7 +385,7 @@ class Manuscript extends EpmcBaseModel {
     const manuscripts = await Manuscript.query()
       .distinct('manuscript.id')
       .select('manuscript.*')
-      .eager('[teams.users, claiming, journal]')
+      .eager('[teams.users, claiming, journal, notes]')
       .whereNull('manuscript.deleted')
       .where(
         raw(`(? ilike concat("meta,title", '%') or "meta,title" ilike ?)`, [
diff --git a/server/xpub-model/entities/manuscript/index.js b/server/xpub-model/entities/manuscript/index.js
index 55d211643..bb9b47130 100755
--- a/server/xpub-model/entities/manuscript/index.js
+++ b/server/xpub-model/entities/manuscript/index.js
@@ -92,7 +92,7 @@ const Manuscript = {
 
   checkDuplicates: async (id, articleIds, title, user) => {
     let manuscripts = []
-    if (articleIds.length > 0) {
+    if (articleIds && articleIds.length > 0) {
       const idMatches = []
       const matchLists = articleIds.map(aid =>
         ManuscriptAccess.searchArticleIds(aid, user),
-- 
GitLab