diff --git a/packages/component-fixture-manager/src/fixtures/fragments.js b/packages/component-fixture-manager/src/fixtures/fragments.js index 9fca41e0ffba404be7fd612dd6feb483e6a23763..77e771572f61bc2219da320f7afa07e660f0bbe3 100644 --- a/packages/component-fixture-manager/src/fixtures/fragments.js +++ b/packages/component-fixture-manager/src/fixtures/fragments.js @@ -71,7 +71,7 @@ const fragments = { }, ], id: chance.guid(), - userId: '1231njfsdknfkjs23', + userId: recReviewer.id, createdOn: chance.timestamp(), updatedOn: chance.timestamp(), submittedOn: chance.timestamp(), @@ -148,7 +148,7 @@ const fragments = { id: chance.guid(), role: 'reviewer', hasAnswer: true, - isAccepted: false, + isAccepted: true, userId: answerReviewer.id, invitedOn: chance.timestamp(), respondedOn: chance.timestamp(), @@ -164,6 +164,16 @@ const fragments = { respondedOn: chance.timestamp(), type: 'invitation', }, + { + id: chance.guid(), + role: 'reviewer', + hasAnswer: true, + isAccepted: true, + userId: recReviewer.id, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }, ], save: jest.fn(() => fragments.fragment), owners: [user.id], diff --git a/packages/component-helper-service/src/services/Fragment.js b/packages/component-helper-service/src/services/Fragment.js index 4b9e5edd4fefe8c3864698ba2ea205be4c3ecbac..9c123ea185f1aa4f473304dbe665fa11a38cccb0 100644 --- a/packages/component-helper-service/src/services/Fragment.js +++ b/packages/component-helper-service/src/services/Fragment.js @@ -1,6 +1,9 @@ const { get, remove } = require('lodash') +const config = require('config') const User = require('./User') +const { recommendations: configRecommendations } = config + class Fragment { constructor({ fragment }) { this.fragment = fragment @@ -146,6 +149,60 @@ class Fragment { rec => rec.recommendationType === 'review' && rec.submittedOn, ) } + + async getReviewersAndEditorsData({ collection, UserModel }) { + const { + invitations = [], + recommendations = [], + submitted = Date.now(), + } = this.fragment + + const revAndEditorData = await Promise.all( + recommendations.map(async rec => { + const user = await UserModel.find(rec.userId) + let assignmentDate, isReviewer + + if (rec.recommendationType === configRecommendations.type.editor) { + if (!collection.handlingEditor) { + throw new Error( + `Collection ${collection.id} does not have a Handling Editor`, + ) + } + if (user.id === collection.handlingEditor.id) { + const editorInvitation = collection.invitations.find( + inv => inv.userId === user.id, + ) + assignmentDate = editorInvitation.respondedOn + } else { + assignmentDate = submitted + } + + isReviewer = false + } else { + const reviewerInvitation = invitations.find( + inv => inv.userId === user.id, + ) + assignmentDate = reviewerInvitation.respondedOn + isReviewer = true + } + + return { + isReviewer, + assignmentDate, + email: user.email, + title: user.title, + recommendation: rec, + country: user.country, + lastName: user.lastName, + firstName: user.firstName, + affiliation: user.affiliation, + submissionDate: rec.createdOn, + } + }), + ) + + return revAndEditorData + } } module.exports = Fragment diff --git a/packages/component-helper-service/src/tests/fragment.test.js b/packages/component-helper-service/src/tests/fragment.test.js index 61e86748001df9b64466c7ed461bd1cf0c27c918..02526753141662501695d100ed8bad8f00174367 100644 --- a/packages/component-helper-service/src/tests/fragment.test.js +++ b/packages/component-helper-service/src/tests/fragment.test.js @@ -6,7 +6,7 @@ const fixturesService = require('pubsweet-component-fixture-service') const Chance = require('chance') const chance = new Chance() -const { fixtures } = fixturesService +const { fixtures, Model } = fixturesService const { Fragment } = require('../Helper') const acceptedReviewerId = chance.guid() @@ -117,9 +117,11 @@ const fragment = { describe('Fragment helper', () => { let testFixtures = {} let testFragment = {} + let models = {} beforeEach(() => { testFixtures = cloneDeep(fixtures) testFragment = cloneDeep(fragment) + models = Model.build(testFixtures) }) describe('hasReviewReport', () => { @@ -237,4 +239,36 @@ describe('Fragment helper', () => { expect(pendingInvitations).toHaveLength(1) }) }) + describe('getReviewersAndEditorsData', () => { + it('should return an array of users (reviewers, editors) that have a connection with the fragment', async () => { + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + const fragmentHelper = new Fragment({ fragment }) + + const fragmentUsers = await fragmentHelper.getReviewersAndEditorsData({ + collection, + UserModel: models.User, + }) + + expect(fragmentUsers.length).toBeGreaterThan(0) + expect(fragmentUsers).toHaveLength(fragment.recommendations.length) + }) + it('should return an error when the collection does not have a handling editor', async () => { + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + const fragmentHelper = new Fragment({ fragment }) + + delete collection.handlingEditor + try { + await fragmentHelper.getReviewersAndEditorsData({ + collection, + UserModel: models.User, + }) + } catch (e) { + expect(e.message).toEqual( + `Collection ${collection.id} does not have a Handling Editor`, + ) + } + }) + }) }) diff --git a/packages/component-manuscript-manager/src/routes/fragments/post.js b/packages/component-manuscript-manager/src/routes/fragments/post.js index 7b541025809ee4dea338b7f5cd6f2136e47dd034..8463b54afefc6d3873350b0ea8d07bdf2bceadfd 100644 --- a/packages/component-manuscript-manager/src/routes/fragments/post.js +++ b/packages/component-manuscript-manager/src/routes/fragments/post.js @@ -13,10 +13,10 @@ const { features = {} } = config const sendMTSPackage = async (collection, fragment) => { const s3Config = get(config, 'pubsweet-component-aws-s3', {}) const mtsConfig = get(config, 'mts-service', {}) - const MTSService = require('pubsweet-component-mts-package') + const { sendPackage } = require('pubsweet-component-mts-package') const { journal, xmlParser, ftp } = mtsConfig - const MTS = new MTSService(journal, xmlParser, s3Config, ftp) + const packageFragment = { ...fragment, metadata: { @@ -25,7 +25,13 @@ const sendMTSPackage = async (collection, fragment) => { }, } - await MTS.sendPackage({ fragment: packageFragment }) + await sendPackage({ + s3Config, + ftpConfig: ftp, + config: journal, + options: xmlParser, + fragment: packageFragment, + }) } module.exports = models => async (req, res) => { diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index 3ab4592d8e7df569c2b9cdafeb32b34c88c35242..e5b462d57c66b24789b7f78de214c1c40ad46e4a 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -2,6 +2,7 @@ const uuid = require('uuid') const { pick, get, set, has, isEmpty, last } = require('lodash') const config = require('config') const { v4 } = require('uuid') +const logger = require('@pubsweet/logger') const { services, @@ -12,24 +13,6 @@ const { const { features = {}, recommendations } = config -const sendMTSPackage = async (collection, fragment, isEQA = false) => { - const s3Config = get(config, 'pubsweet-component-aws-s3', {}) - const mtsConfig = get(config, 'mts-service', {}) - const MTSService = require('pubsweet-component-mts-package') - - const { journal, xmlParser, ftp } = mtsConfig - const MTS = new MTSService(journal, xmlParser, s3Config, ftp) - const packageFragment = { - ...fragment, - metadata: { - ...fragment.metadata, - customId: collection.customId, - }, - } - - await MTS.sendPackage({ fragment: packageFragment, isEQA }) -} - const Notification = require('../../notifications/notification') module.exports = models => async (req, res) => { @@ -71,6 +54,7 @@ module.exports = models => async (req, res) => { error: 'Unauthorized.', }) + const fragmentHelper = new Fragment({ fragment }) if ( recommendationType === recommendations.type.editor && last(collection.fragments) !== fragmentId @@ -106,7 +90,6 @@ module.exports = models => async (req, res) => { collection.handlingEditor && collection.handlingEditor.id === req.user ) { - const fragmentHelper = new Fragment({ fragment }) if (!fragmentHelper.hasReviewReport()) { return res .status(400) @@ -143,7 +126,33 @@ module.exports = models => async (req, res) => { // the manuscript has not yet passed through the EQA process so we need to upload it to the FTP server if (isEditorInChief && recommendation === 'publish' && !hasEQA) { if (features.mts) { - await sendMTSPackage(collection, fragment, true) + await Promise.all( + collection.fragments.map(async fragmentId => { + const fragment = await models.Fragment.find(fragmentId) + const fragmentHelper = new Fragment({ fragment }) + + let fragmentUsers = [] + try { + fragmentUsers = await fragmentHelper.getReviewersAndEditorsData({ + collection, + UserModel: models.User, + }) + + await sendMTSPackage({ + collection, + fragment, + isEQA: true, + fragmentUsers, + }) + } catch (e) { + logger.error(e) + } + }), + ).catch(e => + res.status(500).json({ + error: 'Something went wrong.', + }), + ) } collection.status = 'inQA' @@ -216,3 +225,33 @@ module.exports = models => async (req, res) => { return res.status(200).json(newRecommendation) } + +const sendMTSPackage = async ({ + fragment, + collection, + isEQA = false, + fragmentUsers = [], +}) => { + const s3Config = get(config, 'pubsweet-component-aws-s3', {}) + const mtsConfig = get(config, 'mts-service', {}) + const { sendPackage } = require('pubsweet-component-mts-package') + + const { journal, xmlParser, ftp } = mtsConfig + const packageFragment = { + ...fragment, + metadata: { + ...fragment.metadata, + customId: collection.customId, + }, + } + + await sendPackage({ + isEQA, + s3Config, + fragmentUsers, + ftpConfig: ftp, + config: journal, + options: xmlParser, + fragment: packageFragment, + }) +} diff --git a/packages/component-mts-package/src/MTS.js b/packages/component-mts-package/src/MTS.js index 22d862896b71ffa81a67478a708a0dadcc262974..3f9e503df78bbf5d3273f0e7e19dd4d3c764b1e1 100644 --- a/packages/component-mts-package/src/MTS.js +++ b/packages/component-mts-package/src/MTS.js @@ -1,324 +1,54 @@ -const convert = require('xml-js') -const config = require('config') -const { set, get, reduce, isEmpty, capitalize } = require('lodash') +const { get } = require('lodash') const PackageManager = require('./PackageManager') -const mts = require('./mts-json-template') - -const manuscriptTypes = config.get('journalConfig.manuscriptTypes') const { defaultConfig, - defaultParseXmlOptions, defaultS3Config, defaultFTPConfig, + defaultParseXmlOptions, } = require('../config/default') -class MTS { - constructor( +const { convertToXML, composeJson } = require('./helpers') + +module.exports = { + sendPackage({ + fragment = {}, + isEQA = false, + fragmentUsers = [], config = defaultConfig, - options = defaultParseXmlOptions, s3Config = defaultS3Config, ftpConfig = defaultFTPConfig, - ) { - this.config = config - this.options = options - this.jsonTemplate = mts.getJsonTemplate(config) - this.s3Config = s3Config - this.ftpConfig = ftpConfig - } - - createFileName(id = Date.now()) { - return `${this.config.prefix}${id}` - } - - parseHtml(content = '') { - if (/<\/?[^>]*>/.test(content)) { - return convert.xml2js(content, this.options) - } - return content - } - - convertToXML(json = {}) { - const content = convert.json2xml(json, this.options) - const customId = get( - json, - 'article.front.article-meta.article-id[0]._text', - this.createFileName(), - ) - const name = `${customId}.xml` - return { - name, - content, - } - } - - setMetadata(metadata, jsonTemplate) { - const fileName = this.createFileName(metadata.customId) - const titleGroup = { - 'article-title': this.parseHtml(metadata.title), - } - const articleId = [ - { - _attributes: { - 'pub-id-type': 'publisher-id', - }, - _text: fileName, - }, - { - _attributes: { - 'pub-id-type': 'manuscript', - }, - _text: fileName, - }, - ] - - const articleType = { - 'subj-group': [ - { - _attributes: { - 'subj-group-type': 'Article Type', - }, - subject: { - _text: get( - manuscriptTypes.find(v => v.value === metadata.type), - 'label', - 'Research Article', - ), - }, - }, - ], - } - set(jsonTemplate, 'article.front.article-meta.title-group', titleGroup) - set(jsonTemplate, 'article.front.article-meta.article-id', articleId) - set( - jsonTemplate, - 'article.front.article-meta.article-categories', - articleType, - ) - set(jsonTemplate, 'article.front.article-meta.abstract', metadata.abstract) - - return jsonTemplate - } - - static setHistory(submitted, jsonTemplate) { - const date = new Date(submitted) - const parsedDate = { - date: { - _attributes: { - 'date-type': 'received', - }, - day: { - _text: date.getDate(), - }, - month: { - _text: date.getMonth() + 1, - }, - year: { - _text: date.getFullYear(), - }, - }, - } - set(jsonTemplate, 'article.front.article-meta.history', parsedDate) - - return jsonTemplate - } - - static setFiles(files, jsonTemplate) { - const jsonFiles = reduce( - files, - (result, value, key) => { - value.map(v => - result.push({ - item_type: { - _text: key, - }, - item_description: { - _text: v.originalName, - }, - item_name: { - _text: v.name, - }, - }), - ) - - return result - }, - [], - ) - set(jsonTemplate, 'article.front.files.file', jsonFiles) - - return jsonTemplate - } - - static setQuestions(conflicts, jsonTemplate) { - const { - hasConflicts = 'no', - message = '', - hasDataAvailability = 'no', - dataAvailabilityMessage = '', - hasFunding = 'no', - fundingMessage = '', - } = conflicts - const questions = [] - const funding = isEmpty(hasFunding) ? 'no' : hasFunding - const dataAvailability = isEmpty(hasDataAvailability) - ? 'no' - : hasDataAvailability - - const getQuestionMessage = (selection, message, defaultMessage) => { - if (selection === 'yes') { - return '' - } - return isEmpty(message) ? defaultMessage : message - } - if (!isEmpty(hasConflicts)) { - questions.push({ - _attributes: { - type: 'COI', - }, - answer: { - _text: capitalize(hasConflicts), - }, - statement: { - _text: message, - }, - }) - } - if (!isEmpty(dataAvailability)) { - questions.push({ - _attributes: { - type: 'DA', - }, - answer: { - _text: capitalize(dataAvailability), - }, - statement: { - _text: getQuestionMessage( - dataAvailability, - dataAvailabilityMessage, - 'The authors for this paper did not provide a data availability statement', - ), - }, - }) - } - if (!isEmpty(funding)) { - questions.push({ - _attributes: { - type: 'Fund', - }, - answer: { - _text: capitalize(funding), - }, - statement: { - _text: getQuestionMessage( - funding, - fundingMessage, - 'The authors for this paper did not provide a funding statement', - ), - }, - }) - } - - set(jsonTemplate, 'article.front.questions.question', questions) - return jsonTemplate - } - - static setContributors(authors = [], jsonTemplate) { - const contrib = authors.map((a, i) => ({ - _attributes: { - 'contrib-type': 'author', - corresp: a.isCorresponding ? 'Yes' : 'No', - }, - role: { - _attributes: { - 'content-type': '1', - }, - }, - name: { - surname: { - _text: a.firstName, - }, - 'given-names': { - _text: a.lastName, - }, - prefix: { - _text: a.title || 'Dr.', - }, - }, - email: { - _text: a.email, - }, - xref: { - _attributes: { - 'ref-type': 'aff', - rid: `aff${i + 1}`, - }, - }, - })) - const aff = authors.map((a, i) => ({ - _attributes: { - id: `aff${i + 1}`, - }, - country: a.country || 'UK', - 'addr-line': { - _text: a.affiliation || '', - }, - })) - - set( - jsonTemplate, - 'article.front.article-meta.contrib-group.contrib', - contrib, - ) - set(jsonTemplate, 'article.front.article-meta.contrib-group.aff', aff) - - return jsonTemplate - } - - composeJson(fragment = {}) { - const { - authors = [], - files = [], - metadata = { title: 'untitled', abstract: '' }, - submitted = new Date(), - conflicts = {}, - } = fragment - - return { - ...this.jsonTemplate, - ...this.setMetadata(metadata, this.jsonTemplate), - ...this.constructor.setContributors(authors, this.jsonTemplate), - ...this.constructor.setHistory(submitted, this.jsonTemplate), - ...this.constructor.setFiles(files, this.jsonTemplate), - ...this.constructor.setQuestions(conflicts, this.jsonTemplate), - } - } - - convertFragmentToXML(fragment = {}) { - return this.convertToXML(this.composeJson(fragment)) - } - - sendPackage({ fragment = {}, isEQA = false }) { - const xmlFile = this.convertFragmentToXML(fragment) + options = defaultParseXmlOptions, + }) { + const composedJson = composeJson({ + isEQA, + config, + options, + fragment, + fragmentUsers, + }) + const xmlFile = convertToXML({ + options, + json: composedJson, + prefix: config.prefix, + }) - return PackageManager.createFilesPackage(this.s3Config)({ + return PackageManager.createFilesPackage(s3Config)({ fragment, xmlFile, isEQA, }).then(() => { const packageName = get(xmlFile, 'name', '').replace('.xml', '') const filename = isEQA - ? `ACCEPTED_${packageName}.zip` + ? `ACCEPTED_${packageName}.${fragment.version}.zip` : `${packageName}.zip` return PackageManager.uploadFiles({ filename, - s3Config: this.s3Config, - config: this.ftpConfig, + s3Config, + config: ftpConfig, }) }) - } + }, } - -module.exports = MTS diff --git a/packages/component-mts-package/src/PackageManager.js b/packages/component-mts-package/src/PackageManager.js index cb9b8ea4c9fd644ef72c146706dde13348283cc4..367567b1c36f8f8d528fe60dc1ec5581cb0865f8 100644 --- a/packages/component-mts-package/src/PackageManager.js +++ b/packages/component-mts-package/src/PackageManager.js @@ -22,7 +22,7 @@ const createFilesPackage = (s3Config, archiver = nodeArchiver) => { const { files = {} } = fragment let packageName = get(xmlFile, 'name', '').replace('.xml', '') if (isEQA) { - packageName = `ACCEPTED_${packageName}` + packageName = `ACCEPTED_${packageName}.${fragment.version}` } try { const s3FileIDs = Object.values(files) diff --git a/packages/component-mts-package/src/getJsonTemplate.js b/packages/component-mts-package/src/getJsonTemplate.js new file mode 100644 index 0000000000000000000000000000000000000000..2450cea1b72ec8ef03365016748612f4f9e9abf4 --- /dev/null +++ b/packages/component-mts-package/src/getJsonTemplate.js @@ -0,0 +1,229 @@ +module.exports = { + getJsonTemplate: (config = {}) => ({ + _declaration: { + _attributes: { + version: '1.0', + encoding: 'utf-8', + }, + }, + _doctype: config.doctype, + article: { + _attributes: { + 'dtd-version': config.dtdVersion, + 'article-type': config.articleType, + }, + front: { + 'journal-meta': { + 'journal-id': [ + { + _attributes: { + 'journal-id-type': 'publisher', + }, + _text: config.journalIdPublisher, + }, + { + _attributes: { + 'journal-id-type': 'email', + }, + _text: config.email, + }, + ], + 'journal-title-group': { + 'journal-title': { + _text: config.journalTitle, + }, + }, + issn: [ + { + _attributes: { + 'pub-type': 'ppub', + }, + _text: config.issn, + }, + { + _attributes: { + 'pub-type': 'epub', + }, + }, + ], + }, + 'article-meta': { + 'article-id': [ + { + _attributes: { + 'pub-id-type': 'publisher-id', + }, + _text: 'FARADAY-D-00-00000', + }, + { + _attributes: { + 'pub-id-type': 'manuscript', + }, + _text: 'FARADAY-D-00-00000', + }, + ], + 'article-categories': { + 'subj-group': [ + { + _attributes: { + 'subj-group-type': 'Article Type', + }, + subject: { + _text: 'Research Article', + }, + }, + ], + }, + 'title-group': { + 'article-title': { + _text: 'Untitled Article Title ', + }, + }, + 'contrib-group': { + contrib: { + _attributes: { + 'contrib-type': 'author', + corresp: 'yes', + }, + role: { + _attributes: { + 'content-type': '1', + }, + }, + name: { + surname: { + _text: 'First Name', + }, + 'given-names': { + _text: 'Last Name', + }, + prefix: { + _text: 'Dr.', + }, + }, + email: { + _text: 'faraday@hindawi.com', + }, + xref: { + _attributes: { + 'ref-type': 'aff', + rid: 'aff1', + }, + }, + }, + aff: { + _attributes: { + id: 'aff1', + }, + country: { + _text: 'UNITED STATES', + }, + }, + }, + history: { + date: { + _attributes: { + 'date-type': 'received', + }, + day: { + _text: '01', + }, + month: { + _text: '01', + }, + year: { + _text: '1970', + }, + }, + }, + abstract: { + p: { + _text: 'No abstract provided', + }, + }, + 'funding-group': {}, + }, + files: { + file: [], + }, + questions: { + question: [], + }, + 'rev-group': { + rev: [ + { + _attributes: { + 'rev-type': 'reviewer', + }, + name: { + surname: { + _text: 'Last Name', + }, + 'given-names': { + _text: 'First Name', + }, + prefix: { + _text: 'Dr', + }, + }, + email: { + _text: 'faraday@hindawi.com', + }, + xref: { + _attributes: { + 'ref-type': 'aff', + rid: 'aff1', + }, + }, + date: [ + { + _attributes: { + 'date-type': 'assignment', + }, + day: { + _text: '24', + }, + month: { + _text: '10', + }, + year: { + _text: '2018', + }, + }, + { + _attributes: { + 'date-type': 'submission', + }, + day: { + _text: '24', + }, + month: { + _text: '10', + }, + year: { + _text: '2018', + }, + }, + ], + comment: { + _attributes: { + 'comment-type': 'comment', + }, + _text: + 'This article is really great! well written and does not need any update. Please publish it as such', + }, + }, + ], + aff: { + _attributes: { + id: 'aff1', + }, + 'addr-line': { + _text: 'University of Fort Hare, Alice 5700, South Africa', + }, + }, + }, + }, + }, + }), +} diff --git a/packages/component-mts-package/src/helpers.js b/packages/component-mts-package/src/helpers.js new file mode 100644 index 0000000000000000000000000000000000000000..3490eeb2d7d8b1fa7ddb39f36fe85f1a1d122821 --- /dev/null +++ b/packages/component-mts-package/src/helpers.js @@ -0,0 +1,71 @@ +const convert = require('xml-js') +const { get } = require('lodash') + +const { getJsonTemplate } = require('./getJsonTemplate') + +const { + setFiles, + setHistory, + setMetadata, + setQuestions, + setReviewers, + createFileName, + setContributors, +} = require('./templateSetters') + +module.exports = { + convertToXML: ({ json = {}, options, prefix }) => { + const content = convert.json2xml(json, options) + const customId = get( + json, + 'article.front.article-meta.article-id[0]._text', + createFileName({ prefix }), + ) + const name = `${customId}.xml` + return { + name, + content, + } + }, + composeJson: ({ + config, + options, + isEQA = false, + fragment = {}, + fragmentUsers = [], + }) => { + const { + authors = [], + files = [], + metadata = { title: 'untitled', abstract: '' }, + submitted = new Date(), + conflicts = {}, + } = fragment + + const jsonTemplate = getJsonTemplate(config) + const fileName = createFileName({ + id: metadata.customId, + prefix: config.prefix, + }) + + let composedJson = { + ...jsonTemplate, + ...setMetadata({ + options, + metadata, + fileName, + jsonTemplate, + }), + ...setContributors(authors, jsonTemplate), + ...setHistory(submitted, jsonTemplate), + ...setFiles(files, jsonTemplate), + ...setQuestions(conflicts, jsonTemplate), + } + + if (isEQA) { + composedJson = setReviewers(fragmentUsers, jsonTemplate) + } + + return composedJson + }, +} diff --git a/packages/component-mts-package/src/mts-json-template.js b/packages/component-mts-package/src/mts-json-template.js deleted file mode 100644 index f1fe175dc8ce08040c41cffb49f59b930fb8051f..0000000000000000000000000000000000000000 --- a/packages/component-mts-package/src/mts-json-template.js +++ /dev/null @@ -1,157 +0,0 @@ -const getJsonTemplate = (config = {}) => ({ - _declaration: { - _attributes: { - version: '1.0', - encoding: 'utf-8', - }, - }, - _doctype: config.doctype, - article: { - _attributes: { - 'dtd-version': config.dtdVersion, - 'article-type': config.articleType, - }, - front: { - 'journal-meta': { - 'journal-id': [ - { - _attributes: { - 'journal-id-type': 'publisher', - }, - _text: config.journalIdPublisher, - }, - { - _attributes: { - 'journal-id-type': 'email', - }, - _text: config.email, - }, - ], - 'journal-title-group': { - 'journal-title': { - _text: config.journalTitle, - }, - }, - issn: [ - { - _attributes: { - 'pub-type': 'ppub', - }, - _text: config.issn, - }, - { - _attributes: { - 'pub-type': 'epub', - }, - }, - ], - }, - 'article-meta': { - 'article-id': [ - { - _attributes: { - 'pub-id-type': 'publisher-id', - }, - _text: 'FARADAY-D-00-00000', - }, - { - _attributes: { - 'pub-id-type': 'manuscript', - }, - _text: 'FARADAY-D-00-00000', - }, - ], - 'article-categories': { - 'subj-group': [ - { - _attributes: { - 'subj-group-type': 'Article Type', - }, - subject: { - _text: 'Research Article', - }, - }, - ], - }, - 'title-group': { - 'article-title': { - _text: 'Untitled Article Title ', - }, - }, - 'contrib-group': { - contrib: { - _attributes: { - 'contrib-type': 'author', - corresp: 'yes', - }, - role: { - _attributes: { - 'content-type': '1', - }, - }, - name: { - surname: { - _text: 'First Name', - }, - 'given-names': { - _text: 'Last Name', - }, - prefix: { - _text: 'Dr.', - }, - }, - email: { - _text: 'faraday@hindawi.com', - }, - xref: { - _attributes: { - 'ref-type': 'aff', - rid: 'aff1', - }, - }, - }, - aff: { - _attributes: { - id: 'aff1', - }, - country: { - _text: 'UNITED STATES', - }, - }, - }, - history: { - date: { - _attributes: { - 'date-type': 'received', - }, - day: { - _text: '01', - }, - month: { - _text: '01', - }, - year: { - _text: '1970', - }, - }, - }, - abstract: { - p: { - _text: 'No abstract provided', - }, - }, - 'funding-group': {}, - }, - files: { - file: [], - }, - questions: { - question: [], - }, - }, - }, -}) - -module.exports = { - getJsonTemplate, -} diff --git a/packages/component-mts-package/src/templateSetters.js b/packages/component-mts-package/src/templateSetters.js new file mode 100644 index 0000000000000000000000000000000000000000..31de2d28e374ef4536a8d842be5f7efacc3c638c --- /dev/null +++ b/packages/component-mts-package/src/templateSetters.js @@ -0,0 +1,321 @@ +const config = require('config') +const convert = require('xml-js') + +const { set, get, reduce, isEmpty, capitalize } = require('lodash') + +const manuscriptTypes = config.get('journalConfig.manuscriptTypes') + +module.exports = { + setMetadata: ({ metadata, jsonTemplate, options, fileName }) => { + const titleGroup = { + 'article-title': parseHtml(metadata.title, options), + } + const articleId = [ + { + _attributes: { + 'pub-id-type': 'publisher-id', + }, + _text: fileName, + }, + { + _attributes: { + 'pub-id-type': 'manuscript', + }, + _text: fileName, + }, + ] + + const articleType = { + 'subj-group': [ + { + _attributes: { + 'subj-group-type': 'Article Type', + }, + subject: { + _text: get( + manuscriptTypes.find(v => v.value === metadata.type), + 'label', + 'Research Article', + ), + }, + }, + ], + } + set(jsonTemplate, 'article.front.article-meta.title-group', titleGroup) + set(jsonTemplate, 'article.front.article-meta.article-id', articleId) + set( + jsonTemplate, + 'article.front.article-meta.article-categories', + articleType, + ) + set(jsonTemplate, 'article.front.article-meta.abstract', metadata.abstract) + + return jsonTemplate + }, + setHistory: (submitted, jsonTemplate) => { + const date = new Date(submitted) + const parsedDate = { + date: { + _attributes: { + 'date-type': 'received', + }, + day: { + _text: date.getDate(), + }, + month: { + _text: date.getMonth() + 1, + }, + year: { + _text: date.getFullYear(), + }, + }, + } + set(jsonTemplate, 'article.front.article-meta.history', parsedDate) + + return jsonTemplate + }, + setFiles: (files, jsonTemplate) => { + const jsonFiles = reduce( + files, + (result, value, key) => { + value.map(v => + result.push({ + item_type: { + _text: key, + }, + item_description: { + _text: v.originalName, + }, + item_name: { + _text: v.name, + }, + }), + ) + + return result + }, + [], + ) + set(jsonTemplate, 'article.front.files.file', jsonFiles) + + return jsonTemplate + }, + setQuestions: (conflicts, jsonTemplate) => { + const { + hasConflicts = 'no', + message = '', + hasDataAvailability = 'no', + dataAvailabilityMessage = '', + hasFunding = 'no', + fundingMessage = '', + } = conflicts + const questions = [] + const funding = isEmpty(hasFunding) ? 'no' : hasFunding + const dataAvailability = isEmpty(hasDataAvailability) + ? 'no' + : hasDataAvailability + + const getQuestionMessage = (selection, message, defaultMessage) => { + if (selection === 'yes') { + return '' + } + return isEmpty(message) ? defaultMessage : message + } + if (!isEmpty(hasConflicts)) { + questions.push({ + _attributes: { + type: 'COI', + }, + answer: { + _text: capitalize(hasConflicts), + }, + statement: { + _text: message, + }, + }) + } + if (!isEmpty(dataAvailability)) { + questions.push({ + _attributes: { + type: 'DA', + }, + answer: { + _text: capitalize(dataAvailability), + }, + statement: { + _text: getQuestionMessage( + dataAvailability, + dataAvailabilityMessage, + 'The authors for this paper did not provide a data availability statement', + ), + }, + }) + } + if (!isEmpty(funding)) { + questions.push({ + _attributes: { + type: 'Fund', + }, + answer: { + _text: capitalize(funding), + }, + statement: { + _text: getQuestionMessage( + funding, + fundingMessage, + 'The authors for this paper did not provide a funding statement', + ), + }, + }) + } + + set(jsonTemplate, 'article.front.questions.question', questions) + return jsonTemplate + }, + setContributors: (authors = [], jsonTemplate) => { + const contrib = authors.map((a, i) => ({ + _attributes: { + 'contrib-type': 'author', + corresp: a.isCorresponding ? 'Yes' : 'No', + }, + role: { + _attributes: { + 'content-type': '1', + }, + }, + name: { + surname: { + _text: a.firstName, + }, + 'given-names': { + _text: a.lastName, + }, + prefix: { + _text: a.title || 'Dr.', + }, + }, + email: { + _text: a.email, + }, + xref: { + _attributes: { + 'ref-type': 'aff', + rid: `aff${i + 1}`, + }, + }, + })) + const aff = authors.map((a, i) => ({ + _attributes: { + id: `aff${i + 1}`, + }, + country: a.country || 'UK', + 'addr-line': { + _text: a.affiliation || '', + }, + })) + + set( + jsonTemplate, + 'article.front.article-meta.contrib-group.contrib', + contrib, + ) + set(jsonTemplate, 'article.front.article-meta.contrib-group.aff', aff) + + return jsonTemplate + }, + createFileName: ({ id = Date.now(), prefix }) => `${prefix}${id}`, + setReviewers: (users = [], jsonTemplate) => { + const xmlReviewers = users.map((user, i) => { + const assigmentDate = new Date(user.assignmentDate) + const revType = user.isReviewer ? 'reviewer' : 'editor' + const revObj = { + _attributes: { + 'rev-type': revType, + }, + name: { + surname: { + _text: user.lastName, + }, + 'given-names': { + _text: user.firstName, + }, + prefix: { + _text: user.title || 'Dr.', + }, + }, + email: { + _text: user.email, + }, + xref: { + _attributes: { + 'ref-type': 'aff', + rid: `aff${i + 1}`, + }, + }, + date: [ + { + _attributes: { + 'date-type': 'assignment', + }, + day: { + _text: assigmentDate.getDate(), + }, + month: { + _text: assigmentDate.getMonth() + 1, + }, + year: { + _text: assigmentDate.getFullYear(), + }, + }, + ], + } + + if (user.recommendation) { + const submissionDate = new Date(user.submissionDate) + revObj.date.push({ + _attributes: { + 'date-type': 'submission', + }, + day: { + _text: submissionDate.getDate(), + }, + month: { + _text: submissionDate.getMonth() + 1, + }, + year: { + _text: submissionDate.getFullYear(), + }, + }) + revObj.comment = user.recommendation.comments.map(comm => ({ + _attributes: { + 'comment-type': comm.public ? 'comment' : 'Confidential', + }, + _text: comm.content, + })) + } + + return revObj + }) + const aff = users.map((user, i) => ({ + _attributes: { + id: `aff${i + 1}`, + }, + country: user.country || 'UK', + 'addr-line': { + _text: user.affiliation || '', + }, + })) + + set(jsonTemplate, 'article.front.rev-group.rev', xmlReviewers) + set(jsonTemplate, 'article.front.rev-group.aff', aff) + + return jsonTemplate + }, +} + +const parseHtml = (content = '', options) => { + if (/<\/?[^>]*>/.test(content)) { + return convert.xml2js(content, options) + } + return content +} diff --git a/packages/component-mts-package/tests/MTS.test.js b/packages/component-mts-package/tests/MTS.test.js deleted file mode 100644 index 42c67eafd272402699e9be402e3f9d3f1860e0a6..0000000000000000000000000000000000000000 --- a/packages/component-mts-package/tests/MTS.test.js +++ /dev/null @@ -1,36 +0,0 @@ -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' -process.env.SUPPRESS_NO_CONFIG_WARNING = true - -const MTSService = require('../src/MTS') -const mocks = require('./mocks') - -jest.mock('xml-js', () => ({ - json2xml: jest.fn(), - xml2js: jest.fn(), -})) - -describe('MTS integration', () => { - let MTS - - beforeEach(() => { - MTS = new MTSService(mocks.config.defaultConfig) - }) - - it('should be instantiated', () => { - const result = MTS - expect(result).toBeDefined() - }) - - it('should return basic json for XML parsing', () => { - const result = MTS.composeJson({}) - expect(result).toHaveProperty('article') - }) - - it('should contain configured journal name ', () => { - const result = MTS.composeJson({ fragment: mocks.fragment }) - expect(result).toHaveProperty( - 'article.front.journal-meta.journal-title-group.journal-title._text', - 'Bioinorganic Chemistry and Applications', - ) - }) -}) diff --git a/packages/component-mts-package/tests/helpers.test.js b/packages/component-mts-package/tests/helpers.test.js new file mode 100644 index 0000000000000000000000000000000000000000..501214eb7932ca94cc0dfe95a29ad599fa7155a1 --- /dev/null +++ b/packages/component-mts-package/tests/helpers.test.js @@ -0,0 +1,142 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.SUPPRESS_NO_CONFIG_WARNING = true + +const { cloneDeep } = require('lodash') +const Chance = require('chance') +const fixturesService = require('pubsweet-component-fixture-service') + +const { getJsonTemplate } = require('../src/getJsonTemplate') +const { defaultConfig, defaultParseXmlOptions } = require('../config/default') + +const { convertToXML, composeJson } = require('../src/helpers') + +const { fixtures } = fixturesService +const chance = new Chance() +describe('MTS helpers', () => { + let testFixtures = {} + beforeEach(() => { + testFixtures = cloneDeep(fixtures) + }) + describe('composeJson', () => { + it('should return a json with a rev-group when isEQA is true', async () => { + const { fragment } = testFixtures.fragments + const fragmentUsers = [ + { + isReviewer: true, + assignmentDate: chance.timestamp(), + email: chance.email(), + title: 'Dr', + recommendation: { + id: chance.guid(), + userId: chance.guid(), + comments: [ + { + files: [], + public: true, + content: chance.sentence(), + }, + { + files: [], + public: false, + content: chance.sentence(), + }, + ], + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + recommendation: 'publish', + recommendationType: 'review', + }, + country: chance.country(), + lastName: chance.first(), + firstName: chance.last(), + affiliation: chance.company(), + submissionDate: chance.timestamp(), + }, + { + isReviewer: false, + assignmentDate: chance.timestamp(), + email: chance.email(), + title: 'Dr', + recommendation: { + id: chance.guid(), + userId: chance.guid(), + comments: [ + { + files: [], + public: true, + content: chance.sentence(), + }, + { + files: [], + public: false, + content: chance.sentence(), + }, + ], + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + recommendation: 'publish', + recommendationType: 'editorRecommendation', + }, + country: chance.country(), + lastName: chance.first(), + firstName: chance.last(), + affiliation: chance.company(), + submissionDate: chance.timestamp(), + }, + ] + const composedJson = composeJson({ + fragment, + isEQA: true, + fragmentUsers, + config: defaultConfig, + options: defaultParseXmlOptions, + }) + + expect(composedJson.article.front['rev-group']).toHaveProperty('rev') + expect(composedJson.article.front['rev-group'].rev).toHaveLength( + fragmentUsers.length, + ) + }) + it('should return a json with correct article-meta data', async () => { + const { fragment } = testFixtures.fragments + const composedJson = composeJson({ + fragment, + isEQA: false, + config: defaultConfig, + options: defaultParseXmlOptions, + }) + + expect( + composedJson.article.front['article-meta']['contrib-group'], + ).toHaveProperty('contrib') + expect( + composedJson.article.front['article-meta']['contrib-group'].contrib, + ).toHaveLength(fragment.authors.length) + expect( + composedJson.article.front['article-meta']['title-group'][ + 'article-title' + ], + ).toEqual(fragment.metadata.title) + }) + }) + describe('convertToXML', () => { + it('should return a properly formatted object', async () => { + const jsonTemplate = getJsonTemplate(defaultConfig) + const xmlFile = convertToXML({ + prefix: defaultConfig.prefix, + options: defaultParseXmlOptions, + json: jsonTemplate, + }) + + expect(xmlFile).toHaveProperty('name') + expect(xmlFile).toHaveProperty('content') + expect(xmlFile.content).toContain( + jsonTemplate.article.front['article-meta']['title-group'][ + 'article-title' + ]._text, + ) + }) + }) +}) diff --git a/packages/component-mts-package/tests/mocks.js b/packages/component-mts-package/tests/mocks.js index 20519ab022db5e2c935bd3f65a322275a5b51209..d88427c2a66635c2e3fd58b0a48122dca0e90dcd 100644 --- a/packages/component-mts-package/tests/mocks.js +++ b/packages/component-mts-package/tests/mocks.js @@ -1,90 +1,160 @@ const config = require('../config/default') -const fragment = { - id: '57c7560b-6c1c-480d-a207-cb388d60a213', +const fragmentWithRecommendations = { type: 'fragment', files: { coverLetter: [], manuscripts: [ { id: - '57c7560b-6c1c-480d-a207-cb388d60a213/170ef7b5-bdfd-4637-908d-a693b8c07928', - name: 'Revolut-EUR-Statement-Jan 8, 2018.pdf', - size: 63347, + '9de6c313-1c3e-49eb-bc76-b5d2d045b271/f9916cb6-97a4-4d4c-8a2a-a89b0d10bbdf', + name: 'scimakelatex.2898.adrian+onofrei.pdf', + size: 76051, + originalName: 'scimakelatex.2898.adrian+onofrei.pdf', }, ], - supplementary: [ - { - id: - '57c7560b-6c1c-480d-a207-cb388d60a213/170ef7b5-bdfd-4637-908d-a693b8c07928', - name: 'SUP__Revolut-EUR-Statement-Jan 8, 2018.pdf', - size: 63347, - }, - ], - responseToReviewers: [], + supplementary: [], }, - owners: [ - { - id: '79a35051-7744-49f0-bdfb-388dfe9d7bd3', - username: 'hindawi+auth@thinslices.com', - }, - ], + owners: ['34b0f0be-ea6a-4f5c-81b2-8eca299bdd51'], authors: [ { - id: '79a35051-7744-49f0-bdfb-388dfe9d7bd3', - email: 'hindawi+auth@thinslices.com', + id: '34b0f0be-ea6a-4f5c-81b2-8eca299bdd51', + email: 'adrian.onofrei+auth1@thinslices.com', title: 'mr', - lastName: 'Manuscriptunson', - firstName: 'Author', - affiliation: 'Hindawi', + country: 'AL', + lastName: 'Adi', + firstName: 'Auth', + affiliation: 'TS', isSubmitting: true, isCorresponding: true, }, - { - id: 'd2c4aac6-af51-4421-98c6-cbbc862160d4', - email: 'hindawi+coauthor@thinslices.com', - lastName: 'Southgate', - firstName: 'Gareth 4thplace', - affiliation: 'UK', - isSubmitting: false, - isCorresponding: false, - }, ], - created: '2018-07-20T13:16:39.635Z', + created: '2018-10-18T11:39:40.722Z', version: 1, metadata: { - type: 'clinical-study', - issue: 'regular-issue', - title: '<p>Harry Kane</p>', - journal: 'hindawi-faraday', - abstract: '<p>Golden boot, golden boy.</p>', - customId: '7654321', + customId: '9999999', + type: 'research', + title: 'Approve by he', + journal: 'Bioinorganic Chemistry and Applications', + abstract: 'test', }, - conflicts: { hasConflicts: 'no' }, - submitted: 1532092696032, - collectionId: 'afe691b5-8134-4e5c-b6e3-354a2ed473b5', - declarations: [ - 'has-email', - 'has-manuscript', - 'has-efiles', - 'ok-article-processing', - 'has-orcid', - 'ok-institutional', + conflicts: { + hasFunding: '', + hasConflicts: 'no', + hasDataAvailability: '', + }, + submitted: 1539862801961, + invitations: [ + { + id: '625d7cef-201a-429a-8a91-97404e5e2f31', + role: 'reviewer', + type: 'invitation', + userId: '41ccfd11-9ff8-49b7-a513-58bfede153e8', + hasAnswer: true, + invitedOn: 1539863340777, + isAccepted: true, + respondedOn: 1539863456467, + }, ], + collectionId: '9c9d9cf1-179f-4f7a-87fa-6e70cffbd3f3', + declarations: { + agree: true, + }, fragmentType: 'version', recommendations: [ { - id: '3f86ab07-14c8-4151-8185-d83054cb1c93', - userId: '36319eb1-d245-47d1-b010-4fc1b33d0e41', - createdOn: 1532094805409, - updatedOn: 1532094805409, + id: '9e77f9a8-ad88-4996-ae02-7bd2d7b42a00', + userId: '41ccfd11-9ff8-49b7-a513-58bfede153e8', + comments: [ + { + files: [], + public: true, + content: 'revision pls - rev report', + }, + { + files: [], + public: false, + content: 'Rev confidential note for ET', + }, + ], + createdOn: 1539863473823, + updatedOn: 1539863502691, + submittedOn: 1539863502506, + recommendation: 'major', + recommendationType: 'review', + }, + { + id: 'eb4abe60-6484-40e2-b31e-4bf1f1592278', + userId: '46841a2c-0b37-47c0-8847-9cedcaeeb082', + comments: [ + { + files: [], + public: true, + content: 'Author publish message', + }, + { + files: [], + public: false, + content: 'EiC publish message', + }, + ], + createdOn: 1539863568158, + updatedOn: 1539863568158, recommendation: 'publish', recommendationType: 'editorRecommendation', }, + { + id: '6e8cf67c-a969-48d3-9d90-52d02975a65a', + userId: 'f12e0a14-4b6b-4d22-a506-d03c0ac7562f', + comments: [ + { + public: false, + content: 'HE you have to change this', + }, + ], + createdOn: 1539863677902, + updatedOn: 1539863677902, + recommendation: 'return-to-handling-editor', + recommendationType: 'editorRecommendation', + }, + { + id: '0e48444f-dd21-4e91-9b88-cdcfd9cc84d7', + userId: '46841a2c-0b37-47c0-8847-9cedcaeeb082', + comments: [ + { + files: [], + public: true, + content: 'reject author', + }, + { + files: [], + public: false, + content: 'reject eic', + }, + ], + createdOn: 1539863792764, + updatedOn: 1539863792764, + recommendation: 'reject', + recommendationType: 'editorRecommendation', + }, + { + id: '9730b9b0-fd37-46f6-943c-f3666984e2ab', + userId: 'f12e0a14-4b6b-4d22-a506-d03c0ac7562f', + comments: [ + { + public: true, + content: 'shit man', + }, + ], + createdOn: 1539864067558, + updatedOn: 1539864067558, + recommendation: 'reject', + recommendationType: 'editorRecommendation', + }, ], } module.exports = { - fragment, + fragment: fragmentWithRecommendations, config, } diff --git a/packages/component-mts-package/tests/sampleUpdated.json b/packages/component-mts-package/tests/sampleUpdated.json new file mode 100644 index 0000000000000000000000000000000000000000..760cf8f00cc9453a0e6c61db44a998800592718f --- /dev/null +++ b/packages/component-mts-package/tests/sampleUpdated.json @@ -0,0 +1,182 @@ +{ + "_declaration": { "_attributes": { "version": "1.0", "encoding": "utf-8" } }, + "_doctype": "article SYSTEM \"JATS-archivearticle1-mathml3.dtd\"", + "article": { + "_attributes": { + "dtd-version": "1.1d1", + "article-type": "Research Article" + }, + "front": { + "journal-meta": { + "journal-id": [ + { "_attributes": { "journal-id-type": "publisher" }, "_text": "BCA" }, + { + "_attributes": { "journal-id-type": "email" }, + "_text": "bca.support@hindawi.com" + } + ], + "journal-title-group": { + "journal-title": { + "_text": "Bioinorganic Chemistry and Applications" + } + }, + "issn": [ + { "_attributes": { "pub-type": "ppub" }, "_text": "2474-7394" }, + { "_attributes": { "pub-type": "epub" } } + ] + }, + "article-meta": { + "article-id": [ + { + "_attributes": { "pub-id-type": "publisher-id" }, + "_text": "BCA-5402665" + }, + { + "_attributes": { "pub-id-type": "manuscript" }, + "_text": "BCA-5402665" + } + ], + "article-categories": { + "subj-group": { + "_attributes": { "subj-group-type": "Article Type" }, + "subject": { "_text": "Review Article" } + } + }, + "title-group": { + "article-title": { + "_text": "Advances in iron compounds as biological agents" + } + }, + "contrib-group": { + "contrib": { + "_attributes": { "contrib-type": "author", "corresp": "Yes" }, + "role": { "_attributes": { "content-type": "1" } }, + "name": { + "surname": { "_text": "Ayodele" }, + "given-names": { "_text": "Odularu" }, + "prefix": { "_text": "dr" } + }, + "email": { "_text": "201106223@ufh.ac.za" }, + "xref": { "_attributes": { "ref-type": "aff", "rid": "aff1" } } + }, + "aff": { + "_attributes": { "id": "aff1" }, + "country": { "_text": "ZA" }, + "addr-line": { + "_text": "University of Fort Hare, Alice 5700, South Africa" + } + } + }, + "history": { + "date": { + "_attributes": { "date-type": "received" }, + "day": { "_text": "24" }, + "month": { "_text": "10" }, + "year": { "_text": "2018" } + } + }, + "abstract": { + "_text": + "Abstract\nThis mini review gives a report of the progresses in the use of iron compounds as biological agents. Review entails coordination of ligands in form of pharmaceutical drugs, reagents used directly as supplied, synthesized organic compounds and natural products from plants to iron(II) or iron(III) ions to yield compounds which were applied as antibacterial, iron natural product, antioxidant and anticancer agents. In addition, in the aspect of material chemistry, holistic application of iron nanoparticles was assessed in relation to health. Iron nanoparticles are best approaches to apply as biological agents when compared to bulk materials because of its affordable, biocompatibity, biodegradability, simple approach to synthesis, ease of modification and non-toxic nature.\n\nKeywords: history of iron; chemistry of iron, uses of iron compounds, iron nanoparticles; biological screening techniques\n" + }, + "funding-group": {} + }, + "rev-group": { + "rev": [ + { + "_attributes": { "rev-type": "reviewer" }, + "name": { + "surname": { "_text": "Mohammed" }, + "given-names": { "_text": "Rizk" }, + "prefix": { "_text": "dr" } + }, + "email": { "_text": "mohammed.rizk@hindawi.com" }, + "date": [ + { + "_attributes": { "date-type": "assignment" }, + "day": { "_text": "24" }, + "month": { "_text": "10" }, + "year": { "_text": "2018" } + }, + { + "_attributes": { "date-type": "submission" }, + "day": { "_text": "24" }, + "month": { "_text": "10" }, + "year": { "_text": "2018" } + } + ], + "comment": { + "_attributes": { "comment-type": "" }, + "_text": + "\n This article is really great! well written and does not need any update. Please publish it as such\n " + } + }, + { + "_attributes": { "rev-type": "editor" }, + "name": { + "surname": { "_text": "Matt" }, + "given-names": { "_text": "Green" }, + "prefix": { "_text": "dr" } + }, + "email": { "_text": "matt.green@hindawi.com" }, + "date": [ + { + "_attributes": { "date-type": "assignment" }, + "day": { "_text": "24" }, + "month": { "_text": "10" }, + "year": { "_text": "2018" } + }, + { + "_attributes": { "date-type": "submission" }, + "day": { "_text": "24" }, + "month": { "_text": "10" }, + "year": { "_text": "2018" } + } + ], + "comment": { + "_attributes": { "comment-type": "" }, + "_text": + "\n This article is really great! well written and does not need any update. Please publish it as such\n " + } + } + ], + "aff": { + "_attributes": { "id": "aff1" }, + "country": { "_text": "ZA" }, + "addr-line": { + "_text": "University of Fort Hare, Alice 5700, South Africa" + } + } + }, + "files": { + "file": { + "item_type": { "_text": "manuscripts" }, + "item_description": { "_text": "23 2018.docx" }, + "item_name": { "_text": "23 2018.docx" } + } + }, + "questions": { + "question": [ + { + "_attributes": { "type": "COI" }, + "answer": { "_text": "No" }, + "statement": {} + }, + { + "_attributes": { "type": "DA" }, + "answer": { "_text": "No" }, + "statement": { + "_text": + "The authors for this paper did not provide a data availability statement" + } + }, + { + "_attributes": { "type": "Fund" }, + "answer": { "_text": "Yes" }, + "statement": {} + } + ] + } + } + } +} diff --git a/packages/component-mts-package/tests/sampleUpdated.xml b/packages/component-mts-package/tests/sampleUpdated.xml new file mode 100644 index 0000000000000000000000000000000000000000..ef088637df68cdb076bdebcbe47d6226ca10e35f --- /dev/null +++ b/packages/component-mts-package/tests/sampleUpdated.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE article SYSTEM "JATS-archivearticle1-mathml3.dtd"> +<article dtd-version="1.1d1" article-type="Research Article"> + <front> + <journal-meta> + <journal-id journal-id-type="publisher">BCA</journal-id> + <journal-id journal-id-type="email">bca.support@hindawi.com</journal-id> + <journal-title-group> + <journal-title>Bioinorganic Chemistry and Applications</journal-title> + </journal-title-group> + <issn pub-type="ppub">2474-7394</issn> + <issn pub-type="epub"></issn> + </journal-meta> + <article-meta> + <article-id pub-id-type="publisher-id">BCA-5402665</article-id> + <article-id pub-id-type="manuscript">BCA-5402665</article-id> + <article-categories> + <subj-group subj-group-type="Article Type"> + <subject>Review Article</subject> + </subj-group> + </article-categories> + <title-group> + <article-title>Advances in iron compounds as biological agents</article-title> + </title-group> + <contrib-group> + <contrib contrib-type="author" corresp="Yes"> + <role content-type="1"></role> + <name> + <surname>Ayodele</surname> + <given-names>Odularu</given-names> + <prefix>dr</prefix> + </name> + <email>201106223@ufh.ac.za</email> + <xref ref-type="aff" rid="aff1"></xref> + </contrib> + <aff id="aff1"> + <country>ZA</country> + <addr-line>University of Fort Hare, Alice 5700, South Africa</addr-line> + </aff> + </contrib-group> + <history> + <date date-type="received"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + </history> + <abstract>Abstract +This mini review gives a report of the progresses in the use of iron compounds as biological agents. Review entails coordination of ligands in form of pharmaceutical drugs, reagents used directly as supplied, synthesized organic compounds and natural products from plants to iron(II) or iron(III) ions to yield compounds which were applied as antibacterial, iron natural product, antioxidant and anticancer agents. In addition, in the aspect of material chemistry, holistic application of iron nanoparticles was assessed in relation to health. Iron nanoparticles are best approaches to apply as biological agents when compared to bulk materials because of its affordable, biocompatibity, biodegradability, simple approach to synthesis, ease of modification and non-toxic nature. + +Keywords: history of iron; chemistry of iron, uses of iron compounds, iron nanoparticles; biological screening techniques +</abstract> + <funding-group></funding-group> + </article-meta> + + <rev-group> + <rev rev-type="reviewer"> + + <name> + <surname>Mohammed</surname> + <given-names>Rizk</given-names> + <prefix>dr</prefix> + </name> + <email>mohammed.rizk@hindawi.com</email> + <date date-type="assignment"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <date date-type="submission"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <comment comment-type=""> + This article is really great! well written and does not need any update. Please publish it as such + </comment> + </rev> + <rev rev-type="editor"> + + <name> + <surname>Matt</surname> + <given-names>Green</given-names> + <prefix>dr</prefix> + </name> + <email>matt.green@hindawi.com</email> + <date date-type="assignment"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <date date-type="submission"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <comment comment-type=""> + This article is really great! well written and does not need any update. Please publish it as such + </comment> + + + </rev> + <aff id="aff1"> + <country>ZA</country> + <addr-line>University of Fort Hare, Alice 5700, South Africa</addr-line> + </aff> + </rev-group> + + <files> + <file> + <item_type>manuscripts</item_type> + <item_description>23 2018.docx</item_description> + <item_name>23 2018.docx</item_name> + </file> + </files> + <questions> + <question type="COI"> + <answer>No</answer> + <statement></statement> + </question> + <question type="DA"> + <answer>No</answer> + <statement>The authors for this paper did not provide a data availability statement</statement> + </question> + <question type="Fund"> + <answer>Yes</answer> + <statement></statement> + </question> + </questions> + </front> +</article> \ No newline at end of file diff --git a/packages/component-mts-package/tests/sampleWithReviewers.json b/packages/component-mts-package/tests/sampleWithReviewers.json new file mode 100644 index 0000000000000000000000000000000000000000..6611a93047c9279dcf2079ab4661133e35457d87 --- /dev/null +++ b/packages/component-mts-package/tests/sampleWithReviewers.json @@ -0,0 +1,337 @@ +{ + "_declaration": { + "_attributes": { + "version": "1.0", + "encoding": "utf-8" + } + }, + "_doctype": "article SYSTEM \"JATS-archivearticle1-mathml3.dtd\"", + "article": { + "_attributes": { + "dtd-version": "1.1d1", + "article-type": "Research Article" + }, + "front": { + "journal-meta": { + "journal-id": [ + { + "_attributes": { + "journal-id-type": "publisher" + }, + "_text": "BCA" + }, + { + "_attributes": { + "journal-id-type": "email" + }, + "_text": "bca.support@hindawi.com" + } + ], + "journal-title-group": { + "journal-title": { + "_text": "Bioinorganic Chemistry and Applications" + } + }, + "issn": [ + { + "_attributes": { + "pub-type": "ppub" + }, + "_text": "2474-7394" + }, + { + "_attributes": { + "pub-type": "epub" + } + } + ] + }, + "article-meta": { + "article-id": [ + { + "_attributes": { + "pub-id-type": "publisher-id" + }, + "_text": "BCA-5402665" + }, + { + "_attributes": { + "pub-id-type": "manuscript" + }, + "_text": "BCA-5402665" + } + ], + "article-categories": { + "subj-group": { + "_attributes": { + "subj-group-type": "Article Type" + }, + "subject": { + "_text": "Review Article" + } + } + }, + "title-group": { + "article-title": { + "_text": "Advances in iron compounds as biological agents" + } + }, + "contrib-group": { + "contrib": { + "_attributes": { + "contrib-type": "author", + "corresp": "Yes" + }, + "role": { + "_attributes": { + "content-type": "1" + } + }, + "name": { + "surname": { + "_text": "Ayodele" + }, + "given-names": { + "_text": "Odularu" + }, + "prefix": { + "_text": "dr" + } + }, + "email": { + "_text": "201106223@ufh.ac.za" + }, + "xref": { + "_attributes": { + "ref-type": "aff", + "rid": "aff1" + } + } + }, + "aff": { + "_attributes": { + "id": "aff1" + }, + "country": { + "_text": "ZA" + }, + "addr-line": { + "_text": "University of Fort Hare, Alice 5700, South Africa" + } + } + }, + "history": { + "date": { + "_attributes": { + "date-type": "received" + }, + "day": { + "_text": "24" + }, + "month": { + "_text": "10" + }, + "year": { + "_text": "2018" + } + } + }, + "abstract": { + "_text": "Abstract\nThis mini review gives a report of the progresses in the use of iron compounds as biological agents. Review entails coordination of ligands in form of pharmaceutical drugs, reagents used directly as supplied, synthesized organic compounds and natural products from plants to iron(II) or iron(III) ions to yield compounds which were applied as antibacterial, iron natural product, antioxidant and anticancer agents. In addition, in the aspect of material chemistry, holistic application of iron nanoparticles was assessed in relation to health. Iron nanoparticles are best approaches to apply as biological agents when compared to bulk materials because of its affordable, biocompatibity, biodegradability, simple approach to synthesis, ease of modification and non-toxic nature.\n\nKeywords: history of iron; chemistry of iron, uses of iron compounds, iron nanoparticles; biological screening techniques\n" + }, + "funding-group": {} + }, + "rev-group": { + "rev": [ + { + "_attributes": { + "rev-type": "reviewer" + }, + "name": { + "surname": { + "_text": "Mohammed" + }, + "given-names": { + "_text": "Rizk" + }, + "prefix": { + "_text": "dr" + } + }, + "email": { + "_text": "mohammed.rizk@hindawi.com" + }, + "xref": { + "_attributes": { + "ref-type": "aff", + "rid": "aff1" + } + }, + "date": [ + { + "_attributes": { + "date-type": "assignment" + }, + "day": { + "_text": "24" + }, + "month": { + "_text": "10" + }, + "year": { + "_text": "2018" + } + }, + { + "_attributes": { + "date-type": "submission" + }, + "day": { + "_text": "24" + }, + "month": { + "_text": "10" + }, + "year": { + "_text": "2018" + } + } + ], + "comment": { + "_attributes": { + "comment-type": "" + }, + "_text": "\n This article is really great! well written and does not need any update. Please publish it as such\n " + } + }, + { + "_attributes": { + "rev-type": "editor" + }, + "name": { + "surname": { + "_text": "Matt" + }, + "given-names": { + "_text": "Green" + }, + "prefix": { + "_text": "dr" + } + }, + "email": { + "_text": "matt.green@hindawi.com" + }, + "xref": { + "_attributes": { + "ref-type": "aff", + "rid": "aff1" + } + }, + "date": [ + { + "_attributes": { + "date-type": "assignment" + }, + "day": { + "_text": "24" + }, + "month": { + "_text": "10" + }, + "year": { + "_text": "2018" + } + }, + { + "_attributes": { + "date-type": "submission" + }, + "day": { + "_text": "24" + }, + "month": { + "_text": "10" + }, + "year": { + "_text": "2018" + } + } + ], + "comment": [ + { + "_attributes": { + "comment-type": "comment" + }, + "_text": "\n Public comment for the author.\n " + }, + { + "_attributes": { + "comment-type": "Confidential" + }, + "_text": "\n Internal staff comment.\n " + } + ] + } + ], + "aff": { + "_attributes": { + "id": "aff1" + }, + "country": { + "_text": "ZA" + }, + "addr-line": { + "_text": "University of Fort Hare, Alice 5700, South Africa" + } + } + }, + "files": { + "file": { + "item_type": { + "_text": "manuscripts" + }, + "item_description": { + "_text": "23 2018.docx" + }, + "item_name": { + "_text": "23 2018.docx" + } + } + }, + "questions": { + "question": [ + { + "_attributes": { + "type": "COI" + }, + "answer": { + "_text": "No" + }, + "statement": {} + }, + { + "_attributes": { + "type": "DA" + }, + "answer": { + "_text": "No" + }, + "statement": { + "_text": "The asuthors for this paper did not provide a data availability statement" + } + }, + { + "_attributes": { + "type": "Fund" + }, + "answer": { + "_text": "Yes" + }, + "statement": {} + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/component-mts-package/tests/sampleWithReviewers.xml b/packages/component-mts-package/tests/sampleWithReviewers.xml new file mode 100644 index 0000000000000000000000000000000000000000..2f20d2d52f213c7c667012c07f4f26584d006f12 --- /dev/null +++ b/packages/component-mts-package/tests/sampleWithReviewers.xml @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE article SYSTEM "JATS-archivearticle1-mathml3.dtd"> +<article dtd-version="1.1d1" article-type="Research Article"> + <front> + <journal-meta> + <journal-id journal-id-type="publisher">BCA</journal-id> + <journal-id journal-id-type="email">bca.support@hindawi.com</journal-id> + <journal-title-group> + <journal-title>Bioinorganic Chemistry and Applications</journal-title> + </journal-title-group> + <issn pub-type="ppub">2474-7394</issn> + <issn pub-type="epub"></issn> + </journal-meta> + <article-meta> + <article-id pub-id-type="publisher-id">BCA-5402665</article-id> + <article-id pub-id-type="manuscript">BCA-5402665</article-id> + <article-categories> + <subj-group subj-group-type="Article Type"> + <subject>Review Article</subject> + </subj-group> + </article-categories> + <title-group> + <article-title>Advances in iron compounds as biological agents</article-title> + </title-group> + <contrib-group> + <contrib contrib-type="author" corresp="Yes"> + <role content-type="1"></role> + <name> + <surname>Ayodele</surname> + <given-names>Odularu</given-names> + <prefix>dr</prefix> + </name> + <email>201106223@ufh.ac.za</email> + <xref ref-type="aff" rid="aff1"></xref> + </contrib> + <aff id="aff1"> + <country>ZA</country> + <addr-line>University of Fort Hare, Alice 5700, South Africa</addr-line> + </aff> + </contrib-group> + <history> + <date date-type="received"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + </history> + <abstract> + Abstract This mini review gives a report of the progresses in the use of iron compounds as biological agents. Review entails coordination of ligands in form of pharmaceutical drugs, reagents used directly as supplied, synthesized organic compounds and natural products from plants to iron(II) or iron(III) ions to yield compounds which were applied as antibacterial, iron natural product, antioxidant and anticancer agents. In addition, in the aspect of material chemistry, holistic application of iron nanoparticles was assessed in relation to health. Iron nanoparticles are best approaches to apply as biological agents when compared to bulk materials because of its affordable, biocompatibity, biodegradability, simple approach to synthesis, ease of modification and non-toxic nature. Keywords: history of iron; chemistry of iron, uses of iron compounds, iron nanoparticles; biological screening techniques + </abstract> + <funding-group></funding-group> + </article-meta> + <rev-group> + <rev rev-type="reviewer"> + + <name> + <surname>Mohammed</surname> + <given-names>Rizk</given-names> + <prefix>dr</prefix> + </name> + <email>mohammed.rizk@hindawi.com</email> + <xref ref-type="aff" rid="aff1"></xref> + <date date-type="assignment"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <date date-type="submission"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <comment comment-type=""> + This article is really great! well written and does not need any update. Please publish it as such + </comment> + </rev> + <rev rev-type="editor"> + <name> + <surname>Matt</surname> + <given-names>Green</given-names> + <prefix>dr</prefix> + </name> + <email>matt.green@hindawi.com</email> + <xref ref-type="aff" rid="aff1"></xref> + <date date-type="assignment"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <date date-type="submission"> + <day>24</day> + <month>10</month> + <year>2018</year> + </date> + <comment comment-type="comment"> + Public comment for the author. + </comment> + <comment comment-type="Confidential"> + Internal staff comment. + </comment> + </rev> + <aff id="aff1"> + <country>ZA</country> + <addr-line>University of Fort Hare, Alice 5700, South Africa</addr-line> + </aff> + </rev-group> + + <files> + <file> + <item_type>manuscripts</item_type> + <item_description>23 2018.docx</item_description> + <item_name>23 2018.docx</item_name> + </file> + </files> + <questions> + <question type="COI"> + <answer>No</answer> + <statement></statement> + </question> + <question type="DA"> + <answer>No</answer> + <statement>The authors for this paper did not provide a data availability statement</statement> + </question> + <question type="Fund"> + <answer>Yes</answer> + <statement></statement> + </question> + </questions> + </front> +</article> \ No newline at end of file