From 18694a0fd695d89e41a3f945239c452356acba90 Mon Sep 17 00:00:00 2001
From: Giannis Kopanas <jkopanas@gmail.com>
Date: Wed, 5 Sep 2018 05:40:15 -0400
Subject: [PATCH] Create form builder

---
 app/components/App.js         | 16 ++++++++-
 app/routes.js                 |  6 ++++
 app/storage/forms/submit.json |  1 +
 config/authsome.js            |  2 +-
 config/components.json        |  3 +-
 config/default.js             |  5 +++
 config/form-components.json   | 34 ++++++++++++++++++
 package.json                  |  3 +-
 yarn.lock                     | 67 +++++++++++++++++++++++++++++++++--
 9 files changed, 130 insertions(+), 7 deletions(-)
 create mode 100644 app/storage/forms/submit.json
 create mode 100644 config/form-components.json

diff --git a/app/components/App.js b/app/components/App.js
index 54590c6a2a..2e36f7cdaf 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 0412889acf..aeb51c2767 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 0000000000..7d4ccda14d
--- /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 &lt;a href=\"https://www.collabra.org/about/editorialpolicies/#open-data-open-analytic-methods-code-and-research-materials-transparency\" target=\"_blank\"&gt;here&lt;/a&gt;. 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 &lt;a href=\"https://www.collabra.org/about/editorialpolicies/#open-peer-review\" target=\"_blank\"&gt;“Open Review”&lt;/a&gt; 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 &lt;a href=\"https://www.collabra.org/about/editorialpolicies/#streamlined-review\" target=\"_blank\"&gt;“Streamlined Review”&lt;/a&gt; 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 &lt;a href=\"https://www.collabra.org/about/editorialpolicies/#preregistration-of-studies-and-analysis-plans\" target=\"_blank\"&gt;guidelines&lt;/a&gt;.</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>&lt;pre&gt;There are 3 types of item which should be uploaded here:&lt;br /&gt;</p><p>&lt;ul&gt;</p><p>&lt;li&gt;Regular figures which should also be be embedded in the manuscript.(These are helpful for the production&lt;br /&gt;process,if your article is accepted, in case there are any issues with the embedded versions.)&lt;/li&gt;</p><p>&lt;li&gt;Supplemental items that provide a relevant and useful expansion of the article (Examples include appendices,&lt;br/&gt;very large tables, audios, videos, three-dimensional visualizations, interactive graphics, and so on.)&lt;/li&gt;</p><p>&lt;li&gt;Items that support the peer review process. (Examples are ported reviews and decision letters for use during&lt;br /&gt;the Streamlined Review workflow. Also, if you have a long cover letter you would rather upload than paste&lt;br/&gt;into the text box, please also upload it here.)&lt;/li&gt;</p><p>&lt;/ul&gt;</p><p>Supplemental materials can be named in almost any way, provided that the files are clearly and consistently named,&lt;br /&gt;are uploaded in chronological order, and grouped as they are described above. For example, a typical article&lt;br/&gt;might include:</p><p>&lt;br /&gt;</p><p>&lt;ul&gt;</p><p>&lt;li&gt;Figure 1.jpg&lt;/li&gt;</p><p>&lt;li&gt;Figure 2.jpg&lt;/li&gt;</p><p>&lt;li&gt;Figure 3.jpg&lt;/li&gt;</p><p>&lt;li&gt;Supplemental Table 1.docx&lt;/li&gt;</p><p>&lt;li&gt;Ported Decision Letter and Reviews from Journal X.docx&lt;/li&gt;</p><p>&lt;/ul&gt;</p><p>&lt;/pre&gt;</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 &lt;a href=\"https://www.crossref.org/services/similarity-check/\" rel=\"noopener noreferrer\" target=\"_blank\"&gt;CrossCheck&lt;/a&gt; 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 e8ac923f83..8178b26b83 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 3b6124aa10..d8f03c7ead 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 548115258c..79837ed41d 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 0000000000..3db9b4ede6
--- /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 17b4436f68..6f92078155 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 440e78928e..816d938b7c 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"
-- 
GitLab