diff --git a/app/components/component-formbuilder/src/components/builderComponents/RadioBox.js b/app/components/component-formbuilder/src/components/builderComponents/RadioBox.js index f0302c923999488e0bff14579e63e136db2ed916..cd1e92ece70b72b6194266ec6cc3ebfa4c365096 100644 --- a/app/components/component-formbuilder/src/components/builderComponents/RadioBox.js +++ b/app/components/component-formbuilder/src/components/builderComponents/RadioBox.js @@ -1,5 +1,10 @@ import React from 'react' -import { RadioGroup } from '@pubsweet/ui' +import styled from 'styled-components' +import { RadioGroup as UnstableRadioGroup } from '@pubsweet/ui' + +const RadioGroup = styled(UnstableRadioGroup)` + position: relative +` const RadioboxFieldBuilder = input => <RadioGroup {...input} /> export default RadioboxFieldBuilder diff --git a/app/components/component-formbuilder/src/components/config/Elements.js b/app/components/component-formbuilder/src/components/config/Elements.js index c46a8e7f2723809ba3fa773e1eb45b7725783dc3..1729f0c0bafcd83aea3c3380908c2b0c1a809188 100644 --- a/app/components/component-formbuilder/src/components/config/Elements.js +++ b/app/components/component-formbuilder/src/components/config/Elements.js @@ -147,6 +147,23 @@ const elements = { ], }, }, + DoiValidation: { + component: 'RadioBox', + props: { + inline: true, + options: [ + { + value: 'true', + label: 'Yes', + }, + { + value: 'false', + label: 'No', + }, + ], + label: 'DOI Validation', + }, + }, }, CheckboxGroup: { id: textfield, diff --git a/app/components/component-submit/src/components/FormTemplate.js b/app/components/component-submit/src/components/FormTemplate.js index 7a80fbf347d9bf5df18c44ba8d19e2c9149ce839..84e52cae8155ccbc98db368e85be9a3f6b8f3a35 100644 --- a/app/components/component-submit/src/components/FormTemplate.js +++ b/app/components/component-submit/src/components/FormTemplate.js @@ -19,6 +19,8 @@ import LinksInput from './LinksInput' import ValidatedFieldFormik from './ValidatedField' import Confirm from './Confirm' import { articleStatuses } from '../../../../globals' +import { VALIDATE_DOI } from '../../../../queries/index' +import { useApolloClient } from '@apollo/client' const Intro = styled.div` font-style: italic; @@ -110,7 +112,7 @@ const createMarkup = encodedHtml => ({ __html: unescape(encodedHtml), }) -const composeValidate = (vld = [], valueField = {}) => value => { +const composeValidate = (vld = [], valueField = {}, fieldName, client) => value => { const validator = vld || [] if (validator.length === 0) return undefined @@ -129,6 +131,20 @@ const composeValidate = (vld = [], valueField = {}) => value => { return validatorFn }) + + if(errors.length === 0 && fieldName === 'submission.articleURL') { + return client.query({ + query: VALIDATE_DOI, + variables: { + articleURL: value + } + }).then(res => { + if (!res.data.validateDOI.isDOIValid) { + return 'DOI is invalid' + } + return undefined + }) + } return errors.length > 0 ? errors[0] : undefined } @@ -150,6 +166,7 @@ const FormTemplate = ({ validateForm, match, }) => { + const client = useApolloClient() const submitButton = text => ( <div> <Button @@ -256,6 +273,8 @@ const FormTemplate = ({ validate={composeValidate( element.validate, element.validateValue, + element.name, + client )} values={values} /> diff --git a/app/queries/index.js b/app/queries/index.js index d4b8427653b96a29005d1b54cfa91eecef90ecaa..8b36453fbb992089937e1b520c04b4836217a40e 100644 --- a/app/queries/index.js +++ b/app/queries/index.js @@ -83,6 +83,18 @@ export const SEARCH_USERS = gql` } ` +export const VALIDATE_DOI = gql` + query Manuscripts( + $articleURL: String + ) { + validateDOI( + articleURL: $articleURL + ){ + isDOIValid + } + } +` + export const GET_MANUSCRIPTS = gql` query Manuscripts( $sort: String diff --git a/app/storage/forms-ncrc/submit.json b/app/storage/forms-ncrc/submit.json index 5a0f0fcb2af05620377097cbfb3a34f3d1348153..cba65b43a009367cf62364c9fdc24bf1b12e3b1a 100644 --- a/app/storage/forms-ncrc/submit.json +++ b/app/storage/forms-ncrc/submit.json @@ -224,7 +224,7 @@ ] } ], - "id": "NCRC Submission Form", + "id": "submit", "name": "NCRC Submission Form", "description": "<p>NCRC Form</p>", "haspopup": "false" diff --git a/config/permissions.js b/config/permissions.js index 27b697bc679d532c8984047d2fec2c72561ee768..a2c154abd0484ee6db92313f30a4a1722dfb5114 100644 --- a/config/permissions.js +++ b/config/permissions.js @@ -307,6 +307,7 @@ const permissions = { getForm: allow, getForms: allow, user: allow, + validateDOI: allow, }, Mutation: { upload: isAuthenticated, diff --git a/server/model-manuscript/src/graphql.js b/server/model-manuscript/src/graphql.js index 2a1726f0144905bebb8ea9a2f236ff254594e5eb..7435cc6b387afa5fc4c5bf695cd154b6c8d12299 100644 --- a/server/model-manuscript/src/graphql.js +++ b/server/model-manuscript/src/graphql.js @@ -507,6 +507,23 @@ const resolvers = { // return ctx.connectors.User.fetchAll(where, ctx, { eager }) }, + + async validateDOI(_, { articleURL }, ctx) { + const DOI = encodeURI(articleURL.split('.org/')[1]) + try { + await axios.get(`https://api.crossref.org/works/${DOI}/agency`) + + return { + isDOIValid: true + } + } catch(err) { + // eslint-disable-next-line + console.log(err) + return { + isDOIValid: false + } + } + } }, // We want submission into to come out as a stringified JSON, so that we don't have to // change our queries if the submission form changes. We still want to store it as JSONB @@ -522,6 +539,7 @@ const typeDefs = ` manuscripts: [Manuscript]! paginatedManuscripts(sort: String, offset: Int, limit: Int, filter: ManuscriptsFilter): PaginatedManuscripts publishedManuscripts(sort:String, offset: Int, limit: Int): PaginatedManuscripts + validateDOI(articleURL: String): validateDOIResponse } input ManuscriptsFilter { @@ -529,6 +547,10 @@ const typeDefs = ` submission: String } + type validateDOIResponse { + isDOIValid: Boolean + } + type PaginatedManuscripts { totalCount: Int manuscripts: [Manuscript]