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