Skip to content
Snippets Groups Projects
Commit 148ce617 authored by Sebastian's avatar Sebastian
Browse files

Merge branch 'master' of gitlab.coko.foundation:xpub/xpub-faraday

parents 9abc6e45 86d06c98
No related branches found
No related tags found
No related merge requests found
Showing
with 743 additions and 154 deletions
<?xml version="1.0" encoding="UTF-8"?>
<TestCaseEntity>
<description></description>
<name>Cancel manuscript</name>
<tag></tag>
<comment></comment>
<testCaseGuid>41408538-3127-4056-bc4b-6392ed067097</testCaseGuid>
</TestCaseEntity>
<?xml version="1.0" encoding="UTF-8"?>
<TestSuiteEntity>
<description></description>
<name>LoginFilterManuscripts</name>
<tag></tag>
<isRerun>false</isRerun>
<lastRun>2018-03-27T10:29:15</lastRun>
<mailRecipient></mailRecipient>
<numberOfRerun>0</numberOfRerun>
<pageLoadTimeout>30</pageLoadTimeout>
<pageLoadTimeoutDefault>true</pageLoadTimeoutDefault>
<rerunFailedTestCasesOnly>false</rerunFailedTestCasesOnly>
<testSuiteGuid>f7689c40-b779-426d-a6f2-b6f69a10260a</testSuiteGuid>
<testCaseLink>
<guid>1b907c6a-c9d2-4e04-a075-bfc80a44abfb</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Sign In/Sign In flow</testCaseId>
</testCaseLink>
<testCaseLink>
<guid>1664bf22-f681-4f48-8f70-cb3d86df5328</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Filter Manuscripts/Filter the manuscripts</testCaseId>
</testCaseLink>
</TestSuiteEntity>
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.checkpoint.CheckpointFactory as CheckpointFactory
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testcase.TestCaseFactory as TestCaseFactory
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testdata.TestDataFactory as TestDataFactory
import com.kms.katalon.core.testobject.ObjectRepository as ObjectRepository
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import internal.GlobalVariable as GlobalVariable
import com.kms.katalon.core.annotation.SetUp
import com.kms.katalon.core.annotation.SetupTestCase
import com.kms.katalon.core.annotation.TearDown
import com.kms.katalon.core.annotation.TearDownTestCase
/**
* Some methods below are samples for using SetUp/TearDown in a test suite.
*/
/**
* Setup test suite environment.
*/
@SetUp(skipped = true) // Please change skipped to be false to activate this method.
def setUp() {
// Put your code here.
}
/**
* Clean test suites environment.
*/
@TearDown(skipped = true) // Please change skipped to be false to activate this method.
def tearDown() {
// Put your code here.
}
/**
* Run before each test case starts.
*/
@SetupTestCase(skipped = true) // Please change skipped to be false to activate this method.
def setupTestCase() {
// Put your code here.
}
/**
* Run after each test case ends.
*/
@TearDownTestCase(skipped = true) // Please change skipped to be false to activate this method.
def tearDownTestCase() {
// Put your code here.
}
/**
* References:
* Groovy tutorial page: http://docs.groovy-lang.org/next/html/documentation/
*/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<TestSuiteEntity>
<description></description>
<name>LoginNewManuscript</name>
<tag></tag>
<isRerun>false</isRerun>
<lastRun>2018-03-27T10:26:57</lastRun>
<mailRecipient></mailRecipient>
<numberOfRerun>0</numberOfRerun>
<pageLoadTimeout>30</pageLoadTimeout>
<pageLoadTimeoutDefault>true</pageLoadTimeoutDefault>
<rerunFailedTestCasesOnly>false</rerunFailedTestCasesOnly>
<testSuiteGuid>0bd4d69a-2e5f-4628-a1f6-58318bc57b05</testSuiteGuid>
<testCaseLink>
<guid>c0a987c5-6a97-44c2-b0b9-4642a4a6b0da</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Sign In/Sign In flow</testCaseId>
</testCaseLink>
<testCaseLink>
<guid>725bd536-5fee-431d-bd1e-7ec5f3a21912</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Add new manuscript/Add a new manuscript</testCaseId>
<variableLink>
<testDataLinkId></testDataLinkId>
<type>DEFAULT</type>
<value></value>
<variableId>30a84231-84ba-44cb-9eec-26ad7d97acd5</variableId>
</variableLink>
</testCaseLink>
</TestSuiteEntity>
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.checkpoint.CheckpointFactory as CheckpointFactory
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testcase.TestCaseFactory as TestCaseFactory
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testdata.TestDataFactory as TestDataFactory
import com.kms.katalon.core.testobject.ObjectRepository as ObjectRepository
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import internal.GlobalVariable as GlobalVariable
import com.kms.katalon.core.annotation.SetUp
import com.kms.katalon.core.annotation.SetupTestCase
import com.kms.katalon.core.annotation.TearDown
import com.kms.katalon.core.annotation.TearDownTestCase
/**
* Some methods below are samples for using SetUp/TearDown in a test suite.
*/
/**
* Setup test suite environment.
*/
@SetUp(skipped = true) // Please change skipped to be false to activate this method.
def setUp() {
// Put your code here.
}
/**
* Clean test suites environment.
*/
@TearDown(skipped = true) // Please change skipped to be false to activate this method.
def tearDown() {
// Put your code here.
}
/**
* Run before each test case starts.
*/
@SetupTestCase(skipped = true) // Please change skipped to be false to activate this method.
def setupTestCase() {
// Put your code here.
}
/**
* Run after each test case ends.
*/
@TearDownTestCase(skipped = true) // Please change skipped to be false to activate this method.
def tearDownTestCase() {
// Put your code here.
}
/**
* References:
* Groovy tutorial page: http://docs.groovy-lang.org/next/html/documentation/
*/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<TestSuiteEntity>
<description></description>
<name>LoginNewManuscriptResume</name>
<tag></tag>
<isRerun>false</isRerun>
<lastRun>2018-03-27T10:28:02</lastRun>
<mailRecipient></mailRecipient>
<numberOfRerun>0</numberOfRerun>
<pageLoadTimeout>30</pageLoadTimeout>
<pageLoadTimeoutDefault>true</pageLoadTimeoutDefault>
<rerunFailedTestCasesOnly>false</rerunFailedTestCasesOnly>
<testSuiteGuid>c9b522d2-676a-4476-a82b-7656686190c7</testSuiteGuid>
<testCaseLink>
<guid>80073546-f048-4282-a7ab-5596415a6405</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Sign In/Sign In flow</testCaseId>
</testCaseLink>
<testCaseLink>
<guid>e9ab62a4-f041-4f4f-9e59-0dcb31fc00e7</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Add new manuscript/Add a new manuscript</testCaseId>
<variableLink>
<testDataLinkId></testDataLinkId>
<type>DEFAULT</type>
<value></value>
<variableId>30a84231-84ba-44cb-9eec-26ad7d97acd5</variableId>
</variableLink>
</testCaseLink>
<testCaseLink>
<guid>2ac440cf-7be0-47d5-acb5-dc9a9f2bba0d</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Resume Manuscript/Resume submission Redirect</testCaseId>
</testCaseLink>
</TestSuiteEntity>
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.checkpoint.CheckpointFactory as CheckpointFactory
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testcase.TestCaseFactory as TestCaseFactory
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testdata.TestDataFactory as TestDataFactory
import com.kms.katalon.core.testobject.ObjectRepository as ObjectRepository
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import internal.GlobalVariable as GlobalVariable
import com.kms.katalon.core.annotation.SetUp
import com.kms.katalon.core.annotation.SetupTestCase
import com.kms.katalon.core.annotation.TearDown
import com.kms.katalon.core.annotation.TearDownTestCase
/**
* Some methods below are samples for using SetUp/TearDown in a test suite.
*/
/**
* Setup test suite environment.
*/
@SetUp(skipped = true) // Please change skipped to be false to activate this method.
def setUp() {
// Put your code here.
}
/**
* Clean test suites environment.
*/
@TearDown(skipped = true) // Please change skipped to be false to activate this method.
def tearDown() {
// Put your code here.
}
/**
* Run before each test case starts.
*/
@SetupTestCase(skipped = true) // Please change skipped to be false to activate this method.
def setupTestCase() {
// Put your code here.
}
/**
* Run after each test case ends.
*/
@TearDownTestCase(skipped = true) // Please change skipped to be false to activate this method.
def tearDownTestCase() {
// Put your code here.
}
/**
* References:
* Groovy tutorial page: http://docs.groovy-lang.org/next/html/documentation/
*/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<TestSuiteEntity>
<description></description>
<name>LoginNewUser</name>
<tag></tag>
<isRerun>false</isRerun>
<lastRun>2018-03-27T10:30:26</lastRun>
<mailRecipient></mailRecipient>
<numberOfRerun>0</numberOfRerun>
<pageLoadTimeout>30</pageLoadTimeout>
<pageLoadTimeoutDefault>true</pageLoadTimeoutDefault>
<rerunFailedTestCasesOnly>false</rerunFailedTestCasesOnly>
<testSuiteGuid>412ac6b0-c8f5-42d9-a052-24135a303581</testSuiteGuid>
<testCaseLink>
<guid>de5c81e9-d20b-4524-8a68-f66419d349d6</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Sign In/Sign In flow</testCaseId>
</testCaseLink>
<testCaseLink>
<guid>40e52837-54d7-4f45-964b-9bdb44338181</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Add a new user/Add a new user</testCaseId>
<variableLink>
<testDataLinkId></testDataLinkId>
<type>DEFAULT</type>
<value></value>
<variableId>559661af-7235-48dc-b100-0a83f129e278</variableId>
</variableLink>
</testCaseLink>
</TestSuiteEntity>
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.checkpoint.CheckpointFactory as CheckpointFactory
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testcase.TestCaseFactory as TestCaseFactory
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testdata.TestDataFactory as TestDataFactory
import com.kms.katalon.core.testobject.ObjectRepository as ObjectRepository
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import internal.GlobalVariable as GlobalVariable
import com.kms.katalon.core.annotation.SetUp
import com.kms.katalon.core.annotation.SetupTestCase
import com.kms.katalon.core.annotation.TearDown
import com.kms.katalon.core.annotation.TearDownTestCase
/**
* Some methods below are samples for using SetUp/TearDown in a test suite.
*/
/**
* Setup test suite environment.
*/
@SetUp(skipped = true) // Please change skipped to be false to activate this method.
def setUp() {
// Put your code here.
}
/**
* Clean test suites environment.
*/
@TearDown(skipped = true) // Please change skipped to be false to activate this method.
def tearDown() {
// Put your code here.
}
/**
* Run before each test case starts.
*/
@SetupTestCase(skipped = true) // Please change skipped to be false to activate this method.
def setupTestCase() {
// Put your code here.
}
/**
* Run after each test case ends.
*/
@TearDownTestCase(skipped = true) // Please change skipped to be false to activate this method.
def tearDownTestCase() {
// Put your code here.
}
/**
* References:
* Groovy tutorial page: http://docs.groovy-lang.org/next/html/documentation/
*/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<TestSuiteEntity>
<description></description>
<name>firstTS</name>
<name>LoginNewUserEdit</name>
<tag></tag>
<isRerun>false</isRerun>
<lastRun>2018-03-27T10:32:42</lastRun>
<mailRecipient></mailRecipient>
<numberOfRerun>0</numberOfRerun>
<pageLoadTimeout>30</pageLoadTimeout>
<pageLoadTimeoutDefault>true</pageLoadTimeoutDefault>
<rerunFailedTestCasesOnly>false</rerunFailedTestCasesOnly>
<testSuiteGuid>f13b4374-3272-420a-8e20-e8751334e62d</testSuiteGuid>
<testSuiteGuid>ac25d364-2189-4258-a4d5-aef08e0d6e12</testSuiteGuid>
<testCaseLink>
<guid>c5aca06b-7f12-45b7-9d7f-d23808dba3af</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Sign In/Sign In flow</testCaseId>
</testCaseLink>
<testCaseLink>
<guid>d5a7124a-16b0-458d-9be2-50e24b4b9799</guid>
<isReuseDriver>false</isReuseDriver>
<isRun>true</isRun>
<testCaseId>Test Cases/Edit a new user/Edit new user</testCaseId>
</testCaseLink>
</TestSuiteEntity>
......@@ -8,7 +8,6 @@ import { reduxForm, formValueSelector, SubmissionError } from 'redux-form'
import WizardStep from './WizardStep'
import { autosaveRequest } from '../redux/autosave'
let cachedVersion = ''
const wizardSelector = formValueSelector('wizard')
const onChange = (
......@@ -20,13 +19,11 @@ const onChange = (
const prev = pick(prevValues, formSectionKeys)
const newValues = pick(values, formSectionKeys)
// TODO: fix this if it sucks down the road
if (!isEqual(prev, newValues) && cachedVersion !== version.rev) {
cachedVersion = version.rev
if (!isEqual(prev, newValues)) {
dispatch(autosaveRequest())
dispatch(
actions.updateFragment(project, {
id: version.id,
rev: version.rev,
...newValues,
}),
)
......@@ -44,7 +41,6 @@ const submitManuscript = (
dispatch(
actions.updateFragment(project, {
id: version.id,
rev: version.rev,
submitted: new Date(),
...values,
}),
......@@ -53,7 +49,6 @@ const submitManuscript = (
dispatch(
actions.updateCollection({
id: project.id,
rev: project.rev,
status: 'submitted',
}),
),
......
......@@ -10,8 +10,9 @@ import {
} from 'pubsweet-component-modal/src/components'
import ZipFiles from './ZipFiles'
import { parseVersion, parseJournalIssue, mapStatusToLabel } from './utils'
import EditorInChiefActions from './EditorInChiefActions'
import HandlingEditorActions from './HandlingEditorActions'
import { parseVersion, parseJournalIssue, mapStatusToLabel } from './utils'
const DashboardCard = ({
deleteProject,
......@@ -22,6 +23,7 @@ const DashboardCard = ({
journal,
showConfirmationModal,
theme,
currentUser,
...rest
}) => {
const { submitted, title, type } = parseVersion(version)
......@@ -34,6 +36,7 @@ const DashboardCard = ({
const manuscriptMeta = `${type} - ${
journalIssueType ? journalIssueType.label : 'N/A'
}`
// console.log('Dashboard card', version, project, currentUser)
return version ? (
<Card data-test={customId}>
<ListView>
......@@ -134,7 +137,14 @@ const DashboardCard = ({
<Bottom>
<LeftDetails flex="5">
<HEText>Handling Editor</HEText>
<HandlingEditorActions project={project} />
{get(currentUser, 'admin') ||
(get(currentUser, 'editorInChief') && (
<EditorInChiefActions project={project} />
))}
{get(currentUser, 'handlingEditor') &&
status === 'he-invited' && (
<HandlingEditorActions project={project} />
)}
</LeftDetails>
</Bottom>
</DetailsView>
......@@ -144,7 +154,7 @@ const DashboardCard = ({
}
export default compose(
getContext({ journal: PropTypes.object }),
getContext({ journal: PropTypes.object, currentUser: PropTypes.object }),
withTheme,
withModal({
modalKey: 'cancelManuscript',
......
......@@ -90,7 +90,8 @@ export default compose(
withContext(
{
journal: PropTypes.object,
currentUser: PropTypes.object,
},
({ journal }) => ({ journal }),
({ journal, currentUser }) => ({ journal, currentUser }),
),
)(Dashboard)
import React from 'react'
import { get, head } from 'lodash'
import { connect } from 'react-redux'
import { actions } from 'pubsweet-client'
import { Icon, Button, th } from '@pubsweet/ui'
import { compose, withHandlers } from 'recompose'
import styled, { css, withTheme } from 'styled-components'
import {
withModal,
ConfirmationModal,
SuccessModal,
} from 'pubsweet-component-modal/src/components'
import { revokeHandlingEditor, assignHandlingEditor } from '../../redux/editors'
import HEModal from './AssignHEModal'
const EditorInChiefActions = ({
project,
theme,
getHandlingEditor,
showConfirmModal,
showHEModal,
}) => {
const handlingEditor = getHandlingEditor()
return (
<Root>
<HEActions>
{handlingEditor ? (
<HEActions>
<HEName>{get(handlingEditor, 'name')}</HEName>
{!handlingEditor.hasAnswer && (
<HEActions>
<div onClick={showConfirmModal('resend')}>
<Icon color={theme.colorPrimary}>refresh-cw</Icon>
</div>
<div onClick={showConfirmModal('cancel')}>
<Icon color={theme.colorPrimary}>x-circle</Icon>
</div>
</HEActions>
)}
</HEActions>
) : (
<AssignButton onClick={showHEModal}>Assign</AssignButton>
)}
</HEActions>
</Root>
)
}
const CardModal = ({ type, ...rest }) => {
switch (type) {
case 'confirmation':
return <ConfirmationModal {...rest} />
case 'success':
return <SuccessModal {...rest} />
case 'he-modal':
default:
return <HEModal {...rest} />
}
}
const handleError = fn => e => {
fn(get(JSON.parse(e.response), 'error') || 'Oops! Something went wrong!')
}
export default compose(
connect(null, {
revokeHandlingEditor,
assignHandlingEditor,
updateCollection: actions.updateCollection,
getCollections: actions.getCollections,
}),
withTheme,
withModal({
modalKey: 'confirmHE',
modalComponent: CardModal,
}),
withHandlers({
getHandlingEditor: ({ project }) => () => {
const assignedEditors = get(project, 'assignedPeople')
if (assignedEditors && assignedEditors.length) {
return head(
assignedEditors.filter(
editor =>
!editor.hasAnswer || (editor.hasAnswer && editor.isAccepted),
),
)
}
return null
},
}),
withHandlers({
showConfirmModal: ({
showModal,
project,
revokeHandlingEditor,
assignHandlingEditor,
getHandlingEditor,
hideModal,
setModalError,
updateCollection,
getCollections,
}) => actionType => {
const editor = getHandlingEditor()
const resendConfig = {
title: 'Resend Invitation?',
subtitle: '',
confirmText: 'Resend',
onConfirm: () =>
assignHandlingEditor(get(editor, 'email'), project.id, true).then(
() => {
hideModal()
showModal({
type: 'success',
title: 'Invite resent',
})
},
handleError(setModalError),
),
}
const revokeConfig = {
title: 'Revoke Handling Editor Assignation?',
subtitle: `Clicking 'Revoke' will allow you to invite a different person.`,
confirmText: 'Revoke invite',
onConfirm: () =>
revokeHandlingEditor(get(editor, 'id'), project.id).then(() => {
updateCollection({
id: project.id,
status: 'submitted',
}).then(() => {
getCollections()
hideModal()
showModal({
type: 'success',
title: 'Handling Editor Assignation Revoked',
})
})
}, handleError(setModalError)),
}
return () => {
const cfg = actionType === 'resend' ? resendConfig : revokeConfig
showModal({ ...cfg, type: 'confirmation' })
}
},
showHEModal: ({ showModal, project }) => () => {
showModal({ type: 'he-modal', collectionId: project.id, showModal })
},
}),
)(EditorInChiefActions)
// #region styled-components
const defaultText = css`
color: ${th('colorText')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
`
const Root = styled.div`
margin-left: ${th('gridUnit')};
`
const HEName = styled.div``
const HEActions = styled.div`
${defaultText};
text-transform: uppercase;
display: flex;
align-items: center;
cursor: pointer;
margin-left: ${th('subGridUnit')};
span {
margin-left: ${th('subGridUnit')};
&:hover {
svg {
opacity: 0.8;
}
}
}
`
const AssignButton = styled(Button)`
${defaultText};
align-items: center;
background-color: ${th('colorPrimary')};
color: ${th('colorTextReverse')};
text-align: center;
height: calc(${th('subGridUnit')}*5);
`
// #endregion
import React from 'react'
import { get, head } from 'lodash'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { th, Button } from '@pubsweet/ui'
import { actions } from 'pubsweet-client'
import { Icon, Button, th } from '@pubsweet/ui'
import { compose, withHandlers } from 'recompose'
import styled, { css, withTheme } from 'styled-components'
import { withHandlers, compose, withState } from 'recompose'
import {
withModal,
ConfirmationModal,
SuccessModal,
} from 'pubsweet-component-modal/src/components'
import { revokeHandlingEditor, assignHandlingEditor } from '../../redux/editors'
import { handlingEditorDecision } from '../../redux/editors'
import HEModal from './AssignHEModal'
const DeclineModal = compose(
withState('reason', 'setReason', ''),
withHandlers({
changeReason: ({ setReason }) => e => {
setReason(e.target.value)
},
}),
)(({ reason, changeReason, hideModal, onConfirm }) => (
<DeclineRoot>
<span>Decline handling editor role</span>
<textarea
onChange={changeReason}
placeholder="Decline reason (optional)"
value={reason}
/>
<div>
<Button onClick={hideModal}>Cancel</Button>
<Button onClick={onConfirm(reason)} primary>
Decline
</Button>
</div>
</DeclineRoot>
))
const HandlingEditorActions = ({
project,
theme,
getHandlingEditor,
showConfirmModal,
showHEModal,
}) => {
const handlingEditor = getHandlingEditor()
return (
<Root>
<HEActions>
{handlingEditor ? (
<HEActions>
<HEName>{get(handlingEditor, 'name')}</HEName>
{!handlingEditor.hasAnswer && (
<HEActions>
<div onClick={showConfirmModal('resend')}>
<Icon color={theme.colorPrimary}>refresh-cw</Icon>
</div>
<div onClick={showConfirmModal('cancel')}>
<Icon color={theme.colorPrimary}>x-circle</Icon>
</div>
</HEActions>
)}
</HEActions>
) : (
<AssignButton onClick={showHEModal}>Assign</AssignButton>
)}
</HEActions>
</Root>
const ModalComponent = ({ type, ...rest }) =>
type === 'decline' ? (
<DeclineModal {...rest} />
) : (
<ConfirmationModal {...rest} />
)
}
const CardModal = ({ type, ...rest }) => {
switch (type) {
case 'confirmation':
return <ConfirmationModal {...rest} />
case 'success':
return <SuccessModal {...rest} />
case 'he-modal':
default:
return <HEModal {...rest} />
}
}
const handleError = fn => e => {
fn(get(JSON.parse(e.response), 'error') || 'Oops! Something went wrong!')
}
const HandlingEditorActions = ({ showHEModal }) => (
<Root>
<Button onClick={showHEModal('decline')}>DECLINE</Button>
<Button onClick={showHEModal()} primary>
AGREE
</Button>
</Root>
)
export default compose(
connect(null, {
revokeHandlingEditor,
assignHandlingEditor,
updateCollection: actions.updateCollection,
getCollections: actions.getCollections,
updateCollection: actions.updateCollection,
}),
withTheme,
withModal({
modalKey: 'confirmHE',
modalComponent: CardModal,
modalKey: 'he-action',
modalComponent: ModalComponent,
}),
withHandlers({
getHandlingEditor: ({ project }) => () => {
const assignedEditors = get(project, 'assignedPeople')
if (assignedEditors && assignedEditors.length) {
return head(
assignedEditors.filter(
editor =>
!editor.hasAnswer || (editor.hasAnswer && editor.isAccepted),
),
)
}
return null
},
}),
withHandlers({
showConfirmModal: ({
showHEModal: ({
showModal,
project,
revokeHandlingEditor,
assignHandlingEditor,
getHandlingEditor,
hideModal,
setModalError,
updateCollection,
project,
getCollections,
}) => actionType => {
const editor = getHandlingEditor()
const resendConfig = {
title: 'Resend Invitation?',
subtitle: '',
confirmText: 'Resend',
onConfirm: () =>
assignHandlingEditor(get(editor, 'email'), project.id, true).then(
() => {
updateCollection,
}) => modalType => {
const agreeConfig = {
type: modalType,
title: 'Agree to handling editor assignment',
subtitle: `Clicking "Agree" will assign you as Handling Editor for this Manuscript.`,
onConfirm: () => {
handlingEditorDecision(project.id, true).then(() => {
updateCollection({
id: project.id,
status: 'under-review',
}).then(() => {
getCollections()
hideModal()
showModal({
type: 'success',
title: 'Invite resent',
})
},
handleError(setModalError),
),
})
}, hideModal)
},
}
const revokeConfig = {
title: 'Revoke Handling Editor Assignation?',
subtitle: `Clicking 'Revoke' will allow you to invite a different person.`,
confirmText: 'Revoke invite',
onConfirm: () =>
revokeHandlingEditor(get(editor, 'id'), project.id).then(() => {
const declineConfig = {
type: modalType,
title: 'Decline handling editor role',
subtitle: `Clicking "Agree" will assign you as Handling Editor for this Manuscript.`,
onConfirm: reason => () => {
handlingEditorDecision(project.id, true, reason).then(() => {
updateCollection({
id: project.id,
status: 'submitted',
}).then(() => {
getCollections()
hideModal()
showModal({
type: 'success',
title: 'Handling Editor Assignation Revoked',
})
})
}, handleError(setModalError)),
}, hideModal)
},
}
return () => {
const cfg = actionType === 'resend' ? resendConfig : revokeConfig
showModal({ ...cfg, type: 'confirmation' })
const cfg = modalType === 'decline' ? declineConfig : agreeConfig
showModal(cfg)
}
},
showHEModal: ({ showModal, project }) => () => {
showModal({ type: 'he-modal', collectionId: project.id, showModal })
},
}),
)(HandlingEditorActions)
// #region styled-components
const defaultText = css`
color: ${th('colorText')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
`
const DeclineRoot = styled.div`
align-items: center;
background-color: ${th('backgroundColor')};
display: flex;
flex-direction: column;
justify-content: space-between;
height: calc(${th('gridUnit')} * 13);
padding: calc(${th('subGridUnit')} * 7);
width: calc(${th('gridUnit')} * 24);
const Root = styled.div`
margin-left: ${th('gridUnit')};
`
& span {
color: ${th('colorPrimary')};
font-size: ${th('fontSizeHeading5')};
font-family: ${th('fontHeading')};
margin-bottom: 25px;
}
const HEName = styled.div``
& textarea {
height: 100%;
width: 100%;
}
const HEActions = styled.div`
${defaultText};
text-transform: uppercase;
display: flex;
align-items: center;
cursor: pointer;
margin-left: ${th('subGridUnit')};
span {
margin-left: ${th('subGridUnit')};
&:hover {
svg {
opacity: 0.8;
}
}
& textarea:focus,
& textarea:active {
outline: none;
}
& div {
display: flex;
justify-content: space-evenly;
margin: ${th('gridUnit')} auto 0;
width: 100%;
}
`
const AssignButton = styled(Button)`
${defaultText};
align-items: center;
background-color: ${th('colorPrimary')};
color: ${th('colorTextReverse')};
text-align: center;
height: calc(${th('subGridUnit')}*5);
const Root = styled.div`
margin-left: ${th('gridUnit')};
`
// #endregion
......@@ -57,7 +57,7 @@ const FileSection = ({
over={isFileOver || (isOver && canDrop)}
>
<Header>
<PickerContainer>
<PickerContainer data-test={`upload-${listId}`}>
<Title>{title}</Title>
{!isFetching[listId] ? (
<FilePicker
......
......@@ -28,6 +28,13 @@ export const assignHandlingEditor = (
export const revokeHandlingEditor = (userId, collectionId) => dispatch =>
remove(`/collections/${collectionId}/users/${userId}?role=handlingEditor`)
export const handlingEditorDecision = (collectionId, accept, reason) =>
create(`/collections/${collectionId}/users`, {
type: 'handlingEditor',
accept,
reason,
})
const initialState = []
export default (state = initialState, action = {}) => {
switch (action.type) {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment