diff --git a/app/components/App.js b/app/components/App.js index 54590c6a2abc80f84d080aa77f8fec54fac4ddd6..2e36f7cdafd068a888c1fb6f64823b4864482fa1 100644 --- a/app/components/App.js +++ b/app/components/App.js @@ -15,6 +15,10 @@ const getParams = routerPath => { return matchPath(routerPath, path).params } +const MainPage = styled.div` + margin-top: 20px; +` + const Root = styled.div` ${({ disableLinks }) => disableLinks && @@ -39,6 +43,7 @@ const App = ({ const { pathname } = history.location const showLinks = pathname.match(/submit|manuscript/g) let links = [] + const formBuilderLink = `/admin/form-builder` if (showLinks) { const params = getParams(pathname) @@ -75,6 +80,15 @@ const App = ({ Team Manager </Action>, ) + + links.push( + <Action + active={window.location.pathname === formBuilderLink ? 'active' : null} + to={formBuilderLink} + > + Form Builder + </Action>, + ) } return ( @@ -86,7 +100,7 @@ const App = ({ user={currentUser} /> - <div>{children}</div> + <MainPage>{children}</MainPage> </Root> ) } diff --git a/app/routes.js b/app/routes.js index 0412889acf51a7d5d1f0442ed99dd8b239814ecf..aeb51c276710ef2245f9da29f5ee84aadd71f099 100644 --- a/app/routes.js +++ b/app/routes.js @@ -20,6 +20,7 @@ import ReviewPage from 'pubsweet-component-xpub-review/src/components/ReviewPage import TeamPage from 'pubsweet-component-xpub-teams-manager/src/components/TeamsManagerPage' import DecisionPage from 'pubsweet-component-xpub-review/src/components/DecisionPage' import UsersManager from 'pubsweet-component-users-manager/src/UsersManagerContainer' +import FormBuilderPage from 'pubsweet-component-xpub-formbuilder/src/components/FormBuilderPage' import App from './components/App' @@ -48,6 +49,11 @@ const Routes = () => ( path="/projects/:project/versions/:version/submit" /> <PrivateRoute component={TeamPage} exact path="/teams" /> + <PrivateRoute + component={FormBuilderPage} + exact + path="/admin/form-builder" + /> <PrivateRoute component={ManuscriptPage} exact diff --git a/app/storage/forms/submit.json b/app/storage/forms/submit.json new file mode 100644 index 0000000000000000000000000000000000000000..7d4ccda14dbe86ec6f0d7622b2caa4086f10d6eb --- /dev/null +++ b/app/storage/forms/submit.json @@ -0,0 +1 @@ +{"name":"Submission information","id":"submit","children":[{"title":"Title","id":"1531303631370","component":"AbstractEditor","name":"metadata.title","placeholder":"Enter Title...","validate":["required","minChars"],"validateValue":{"minChars":"10"},"order":"1"},{"title":"Abstract","id":"1531303727228","component":"AbstractEditor","name":"metadata.abstract","placeholder":"Enter the abstract...","validate":["required","minChars"],"validateValue":{"minChars":"100"},"order":"2"},{"title":"Authors","id":"1531726163478","component":"AuthorsInput","name":"authors","order":"3"},{"title":"Keywords","id":"1531303777701","component":"TextField","name":"metadata.keywords","placeholder":"Enter keywords...","parse":"split","format":"join","validate":["required"],"validateValue":{"minChars":"10"},"order":"4"},{"title":"Type of article","id":"1531303833528","component":"Menu","name":"metadata.articleType","options":[{"value":"original-research","label":"Original Research Report"},{"label":"Review","value":"review"},{"value":"opinion","label":"Opinion/Commentary"},{"value":"registered-report","label":"Registered Report"}],"validate":["required"],"order":"5"},{"title":"Section","id":"1531304067965","component":"CheckboxGroup","name":"metadata.articleSection","options":[{"value":"cognitive-psychology","label":"Cognitive Psychology"},{"value":"social-psychology","label":"Social Psychology"},{"value":"personality-psychology","label":"Personality Psychology"},{"value":"developmental-psychology","label":"Developmental Psychology"},{"value":"clinical-psychology","label":"Clinical Psychology"},{"value":"organizational-behavior","label":"Organizational Behavior"},{"value":"methodology","label":"Methodology and Research Practice"}],"validate":["required"],"order":"6","placeholder":"test"},{"title":"Data is open ?","id":"1531304241437","component":"RadioGroup","options":[{"value":"Yes","label":"yes"},{"value":"No/Not Applicable","label":"no"}],"description":"<p>The journal requires data be openly available, and our full policy is <a href=\"https://www.collabra.org/about/editorialpolicies/#open-data-open-analytic-methods-code-and-research-materials-transparency\" target=\"_blank\">here</a>. If you have exceptions that need to be considered, please click \"No\" and explain in your cover letter below. Please click N/A if your submission does not feature data.</p>","name":"declarations.openData","inline":"true","sectioncss":"{\"flex-direction\": \"row\", \"wrap\": \"wrap\"}","validate":["required"],"order":"7"},{"title":"Previously submitted ?","id":"1531304409993","component":"RadioGroup","description":"<p>Provide further details in your cover letter below, if necessary.</p>","options":[{"label":"yes","value":"Yes"},{"label":"no","value":"No"}],"name":"declarations.previouslySubmitted","inline":"true","sectioncss":"{\"flex-direction\": \"row\", \"wrap\": \"wrap\"}","validate":["required"],"order":"8"},{"title":"Open peer review ?","id":"1531304483066","component":"RadioGroup","description":"<p>Please read a description of our <a href=\"https://www.collabra.org/about/editorialpolicies/#open-peer-review\" target=\"_blank\">“Open Reviewâ€</a> option and select “Yes†if you choose this process.</p>","options":[{"label":"yes","value":"Yes"},{"label":"no","value":"No"}],"name":"declarations.openPeerReview","sectioncss":"{\"flex-direction\": \"row\", \"wrap\": \"wrap\"}","inline":"true","validate":["required"],"order":"9"},{"title":"Streamlined review ?","id":"1531304541011","component":"RadioGroup","description":"<p>Please read a description of our <a href=\"https://www.collabra.org/about/editorialpolicies/#streamlined-review\" target=\"_blank\">“Streamlined Reviewâ€</a> option and select “Yes†if you choose this process. If “Yesâ€, please upload your ported decision letter and reviews as “Supplementary Files†below, clearly labeled.</p>","options":[{"label":"yes","value":"Yes"},{"label":"no","value":"No"}],"name":"declarations.streamlinedReview","sectioncss":"{\"flex-direction\": \"row\", \"wrap\": \"wrap\"}","inline":"true","validate":["required"],"order":"10"},{"title":"Submitted as part of the <a href=\"https://www.collabra.org/collections/special/\" target=\"_blank\">research nexus</a> ?","id":"1531304591795","component":"RadioGroup","description":"<p>If yes, mention the name of the Research Nexus in your cover letter below.</p>","options":[{"label":"yes","value":"Yes"},{"label":"no","value":"No"}],"name":"declarations.researchNexus","sectioncss":"{\"flex-direction\": \"row\", \"wrap\": \"wrap\"}","inline":"true","validate":["required"],"order":"11"},{"title":"Pre-registered ?","id":"1531304681954","component":"RadioGroup","description":"<p>If any or all elements of your study have been pre-registered, click yes and ensure details are in the Acknowledgements section of your manuscript, following these <a href=\"https://www.collabra.org/about/editorialpolicies/#preregistration-of-studies-and-analysis-plans\" target=\"_blank\">guidelines</a>.</p>","options":[{"label":"yes","value":"Yes"},{"label":"no","value":"No"}],"name":"declarations.preregistered","sectioncss":"{\"flex-direction\": \"row\", \"wrap\": \"wrap\"}","inline":"true","validate":["required"],"order":"12"},{"title":"Suggested reviewers","id":"1531304848635","component":"TextField","placeholder":"Add reviewer names...","name":"suggestions.reviewers.suggested","parse":"split","format":"join","order":"13"},{"title":"Opposed reviewers","id":"1531304933009","component":"TextField","placeholder":"Add reviewer names...","name":"suggestions.reviewers.opposed","parse":"split","format":"join","order":"14"},{"title":"Suggested editors","id":"1531304988723","component":"TextField","placeholder":"Add editor names...","name":"suggestions.editors.suggested","parse":"split","format":"join","order":"15"},{"title":"Opposed Editors","id":"1531305053799","component":"TextField","placeholder":"Add editor names...","name":"suggestions.editors.opposed","parse":"split","format":"join","order":"16"},{"title":"Funding body acknowledgement (required)","id":"1531305101246","component":"AbstractEditor","placeholder":"Enter body acknowledgement ...","description":"<p>Please also specifically state if your work was not supported by funding.</p>","name":"notes.fundingAcknowledgement","validate":["required"],"order":"17"},{"title":"Special instructions (confidential, to Editors only)","id":"1531305179597","component":"AbstractEditor","placeholder":"Enter instructions ...","description":"<p>Please write or paste what you would normally write into a cover letter here, focusing on information that has not been covered by this form, or any further information prompted by your answers to the questions above.</p>","name":"notes.specialInstructions","order":"18"},{"title":"Upload supplementary materials","id":"1531305332347","component":"Supplementary","description":"<p><pre>There are 3 types of item which should be uploaded here:<br /></p><p><ul></p><p><li>Regular figures which should also be be embedded in the manuscript.(These are helpful for the production<br />process,if your article is accepted, in case there are any issues with the embedded versions.)</li></p><p><li>Supplemental items that provide a relevant and useful expansion of the article (Examples include appendices,<br/>very large tables, audios, videos, three-dimensional visualizations, interactive graphics, and so on.)</li></p><p><li>Items that support the peer review process. (Examples are ported reviews and decision letters for use during<br />the Streamlined Review workflow. Also, if you have a long cover letter you would rather upload than paste<br/>into the text box, please also upload it here.)</li></p><p></ul></p><p>Supplemental materials can be named in almost any way, provided that the files are clearly and consistently named,<br />are uploaded in chronological order, and grouped as they are described above. For example, a typical article<br/>might include:</p><p><br /></p><p><ul></p><p><li>Figure 1.jpg</li></p><p><li>Figure 2.jpg</li></p><p><li>Figure 3.jpg</li></p><p><li>Supplemental Table 1.docx</li></p><p><li>Ported Decision Letter and Reviews from Journal X.docx</li></p><p></ul></p><p></pre></p>","name":"files.supplementary","order":"19"}],"description":"<p>We have ingested your manuscript. To access your manuscript in an editor, please ###link###.</p><p>To complete your submission, please answer the following questions.</p><p>The answers will be automatically saved.</p>","haspopup":"true","popuptitle":"By submitting the manuscript, you agree to the following statements.","popupdescription":"<p></p><p>The corresponding author confirms that all co-authors are included, and that everyone listed as a co-author agrees to that role and all the following requirements and acknowledgements.</p><p></p><p>The submission represents original work and that sources are given proper attribution. </p><p>(The journal employs <a href=\"https://www.crossref.org/services/similarity-check/\" rel=\"noopener noreferrer\" target=\"_blank\">CrossCheck</a> to compare submissions against a large and growing database of published scholarly content. If in the judgment of a senior editor a submission is genuinely suspected of plagiarism, it will be returned to the author(s)</p><p>with a request for explanation.)</p><p></p><p>The research was conducted in accordance with ethical principles.</p><p></p><p>There is a Data Accessibility Statement, containing information about the location of open data and materials, in the manuscript.</p><p></p><p>A conflict of interest statement is present in the manuscript, even if</p><p>to state no conflicts of interest.</p>"} \ No newline at end of file diff --git a/config/authsome.js b/config/authsome.js index e8ac923f83864db035f4f759e20f85a20c8c1dfe..8178b26b83c9e5eb2ec7ff9166d455c560b85db5 100644 --- a/config/authsome.js +++ b/config/authsome.js @@ -845,7 +845,7 @@ module.exports = { const mode = new XpubCollabraMode(userId, operation, object, context) return mode.canViewPage() }, - 'can view teams menu': () => false, + 'can view only admin': () => false, create: (userId, operation, object, context) => { const mode = new XpubCollabraMode(userId, operation, object, context) diff --git a/config/components.json b/config/components.json index 3b6124aa105a29e05ddfda44b52802872ad8ab75..d8f03c7ead44d077e16953caa2e5415f97a89446 100644 --- a/config/components.json +++ b/config/components.json @@ -7,5 +7,6 @@ "pubsweet-component-ink-backend", "pubsweet-component-login", "pubsweet-component-signup", - "pubsweet-component-xpub-teams-manager" + "pubsweet-component-xpub-teams-manager", + "pubsweet-component-xpub-formbuilder" ] diff --git a/config/default.js b/config/default.js index 548115258c99b07c61cd775d0308ad394c6b37d8..79837ed41d3186ff2abc3fe88f9dfe4343701b98 100644 --- a/config/default.js +++ b/config/default.js @@ -32,6 +32,10 @@ module.exports = { from: 'dev@example.com', path: `${__dirname}/mailer`, }, + 'pubsweet-component-xpub-formbuilder': { + path: path.resolve(__dirname, '../app/storage/forms'), + components: require(path.resolve(__dirname, 'form-components.json')), + }, 'pubsweet-server': { db: {}, port: 3000, @@ -160,5 +164,6 @@ module.exports = { 'authsome', 'validations', 'pubsweet-component-xpub-dashboard', + 'pubsweet-component-xpub-formbuilder', ], } diff --git a/config/form-components.json b/config/form-components.json new file mode 100644 index 0000000000000000000000000000000000000000..3db9b4ede69de7fe2da57735542d3cb0192257a8 --- /dev/null +++ b/config/form-components.json @@ -0,0 +1,34 @@ +{ + "AuthorsInput": { + "id": { + "component": "TextField" + }, + "title": { + "component": "TextField" + }, + "name": { + "component": "TextField" + }, + "order": { + "component": "TextField" + }, + "validate": { + "component": "Menu", + "props": { + "multi": true, + "options": [{ + "value": "required", + "label": "Required" + }, + { + "value": "minChars", + "label": "minimum Characters" + }, + { + "value": "maxChars", + "label": "maximum Characters" + }] + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 17b4436f682959b4967c7288e8d8513746579ade..6f920781552b4200ca5e8d0672b4b97176edf158 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@pubsweet/coko-theme": "4.0.1", - "@pubsweet/ui": "8.1.0", + "@pubsweet/ui": "8.2.0", "@pubsweet/db-manager": "^1.1.0", "babel-core": "^6.26.0", "config": "^1.26.2", @@ -41,6 +41,7 @@ "pubsweet-component-xpub-review": "^3.1.4", "pubsweet-component-xpub-review-backend": "^0.2.3", "pubsweet-component-xpub-submit": "^4.0.6", + "pubsweet-component-xpub-formbuilder": "^0.1.0", "pubsweet-server": "^7.2.0", "pubsweet-component-xpub-teams-manager": "^0.1.0", "react": "^16.2.0", diff --git a/yarn.lock b/yarn.lock index 440e78928e9e1931ab6897669825a49f9d47cad0..816d938b7c7aa04b197419662b126bfe826bd091 100644 --- a/yarn.lock +++ b/yarn.lock @@ -178,9 +178,9 @@ lodash "^4.17.4" styled-components "^3.2.5" -"@pubsweet/ui@8.1.0", "@pubsweet/ui@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@pubsweet/ui/-/ui-8.1.0.tgz#3c0ac8dc9c03577e933c01a49b4fb51a61d3e075" +"@pubsweet/ui@8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@pubsweet/ui/-/ui-8.2.0.tgz#fbd4b5eb08ceee430c5bfb4287d4c5f0883e31e6" dependencies: "@pubsweet/ui-toolkit" "^1.1.3" babel-jest "^21.2.0" @@ -225,6 +225,30 @@ redux-form "^7.0.3" styled-components "^3.2.5" +"@pubsweet/ui@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@pubsweet/ui/-/ui-8.1.0.tgz#3c0ac8dc9c03577e933c01a49b4fb51a61d3e075" + dependencies: + "@pubsweet/ui-toolkit" "^1.1.3" + babel-jest "^21.2.0" + classnames "^2.2.5" + enzyme "^3.2.0" + enzyme-adapter-react-16 "^1.1.1" + invariant "^2.2.3" + lodash "^4.17.4" + moment "^2.22.1" + prop-types "^15.5.10" + react "^16.2.0" + react-dom "^16.2.0" + react-feather "^1.0.8" + react-redux "^5.0.2" + react-router-dom "^4.2.2" + react-tag-autocomplete "^5.5.0" + recompose "^0.26.0" + redux "^3.6.0" + redux-form "^7.0.3" + styled-components "^3.2.5" + "@pubsweet/ui@^8.2.0", "@pubsweet/ui@^8.3.0": version "8.3.0" resolved "https://registry.yarnpkg.com/@pubsweet/ui/-/ui-8.3.0.tgz#b8da7be8d9110594abdd18476e3808c9606a74b4" @@ -249,6 +273,30 @@ redux-form "^7.0.3" styled-components "^3.2.5" +"@pubsweet/ui@^8.6.0": + version "8.6.0" + resolved "https://registry.yarnpkg.com/@pubsweet/ui/-/ui-8.6.0.tgz#8153cfbd3f2de5b07f04655b6f7b19a7aee5ca1e" + dependencies: + "@pubsweet/ui-toolkit" "^1.2.0" + babel-jest "^21.2.0" + classnames "^2.2.5" + enzyme "^3.2.0" + enzyme-adapter-react-16 "^1.1.1" + invariant "^2.2.3" + lodash "^4.17.4" + moment "^2.22.1" + prop-types "^15.5.10" + react "^16.2.0" + react-dom "^16.2.0" + react-feather "^1.0.8" + react-redux "^5.0.2" + react-router-dom "^4.2.2" + react-tag-autocomplete "^5.5.0" + recompose "^0.26.0" + redux "^3.6.0" + redux-form "^7.0.3" + styled-components "^3.2.5" + "@types/async@2.0.47": version "2.0.47" resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.47.tgz#f49ba1dd1f189486beb6e1d070a850f6ab4bd521" @@ -8109,6 +8157,19 @@ pubsweet-component-xpub-find-reviewers@^0.0.6: react-router-dom "^4.2.2" recompose "^0.26.0" +pubsweet-component-xpub-formbuilder@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/pubsweet-component-xpub-formbuilder/-/pubsweet-component-xpub-formbuilder-0.1.0.tgz#1c6dadfe77146f17cba739ec53c40ec2b9d5eb7c" + dependencies: + "@pubsweet/ui" "^8.6.0" + "@pubsweet/ui-toolkit" "^1.1.3" + prop-types "^15.5.10" + react-dom "^16.2.0" + react-redux "^5.0.6" + recompose "^0.26.0" + redux "^3.7.2" + styled-components "^3.2.5" + pubsweet-component-xpub-manuscript@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/pubsweet-component-xpub-manuscript/-/pubsweet-component-xpub-manuscript-0.4.1.tgz#53052692abe3c50eafd20065a782d5c5957c7372"