Skip to content
Snippets Groups Projects
Commit 8ccb0c6b authored by Alexandru Munteanu's avatar Alexandru Munteanu
Browse files

chore(he-invite): add loaders for handling editor invite/revoke

parent 30c1efd5
No related branches found
No related tags found
1 merge request!6Agree/Decline to work on a manuscript
...@@ -4,11 +4,15 @@ import React from 'react' ...@@ -4,11 +4,15 @@ import React from 'react'
import { get } from 'lodash' import { get } from 'lodash'
import { compose } from 'recompose' import { compose } from 'recompose'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { th, Icon } from '@pubsweet/ui'
import { actions } from 'pubsweet-client' import { actions } from 'pubsweet-client'
import { th, Icon, Spinner } from '@pubsweet/ui'
import styled, { withTheme } from 'styled-components' import styled, { withTheme } from 'styled-components'
import { handlingEditors, assignHandlingEditor } from '../../redux/editors' import {
selectHandlingEditors,
selectFetching,
assignHandlingEditor,
} from '../../redux/editors'
class AssignHEModal extends React.Component { class AssignHEModal extends React.Component {
state = { state = {
...@@ -57,7 +61,7 @@ class AssignHEModal extends React.Component { ...@@ -57,7 +61,7 @@ class AssignHEModal extends React.Component {
render() { render() {
const { searchInput } = this.state const { searchInput } = this.state
const { editors, hideModal, theme } = this.props const { editors, hideModal, theme, isFetching } = this.props
const filteredEditors = this.filterEditors(editors) const filteredEditors = this.filterEditors(editors)
return ( return (
<RootModal> <RootModal>
...@@ -66,7 +70,10 @@ class AssignHEModal extends React.Component { ...@@ -66,7 +70,10 @@ class AssignHEModal extends React.Component {
</CloseIcon> </CloseIcon>
<ModalTitle>Assign Handling Editor</ModalTitle> <ModalTitle>Assign Handling Editor</ModalTitle>
<ModalHeader> <ModalHeader>
<span>HANDLING EDITORS</span> <SubtitleRow>
<span>HANDLING EDITORS</span>
{isFetching && <Spinner size={3} />}
</SubtitleRow>
<SearchInput <SearchInput
data-test="he-search" data-test="he-search"
onChange={this.changeInput} onChange={this.changeInput}
...@@ -86,12 +93,14 @@ class AssignHEModal extends React.Component { ...@@ -86,12 +93,14 @@ class AssignHEModal extends React.Component {
<span>{`${firstName} ${lastName}`}</span> <span>{`${firstName} ${lastName}`}</span>
<span>{email}</span> <span>{email}</span>
</EditorDetails> </EditorDetails>
<AssignButton {!isFetching && (
data-test={`assign-${email}`} <AssignButton
onClick={this.assignEditor(email)} data-test={`assign-${email}`}
> onClick={this.assignEditor(email)}
ASSIGN >
</AssignButton> ASSIGN
</AssignButton>
)}
</SuggestedEditor> </SuggestedEditor>
))} ))}
</ModalContent> </ModalContent>
...@@ -104,7 +113,8 @@ class AssignHEModal extends React.Component { ...@@ -104,7 +113,8 @@ class AssignHEModal extends React.Component {
export default compose( export default compose(
connect( connect(
state => ({ state => ({
editors: handlingEditors(state), isFetching: selectFetching(state),
editors: selectHandlingEditors(state),
}), }),
{ {
assignHandlingEditor, assignHandlingEditor,
...@@ -116,6 +126,18 @@ export default compose( ...@@ -116,6 +126,18 @@ export default compose(
)(AssignHEModal) )(AssignHEModal)
// #region styled-components // #region styled-components
const SubtitleRow = styled.div`
display: flex;
justify-content: space-between;
& span {
color: ${th('colorPrimary')};
font-size: ${th('fontSizeBase')};
font-family: ${th('fontReading')};
margin-bottom: ${th('subGridUnit')};
}
`
const CloseIcon = styled.div` const CloseIcon = styled.div`
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
...@@ -182,13 +204,6 @@ const ModalHeader = styled.div` ...@@ -182,13 +204,6 @@ const ModalHeader = styled.div`
align-self: stretch; align-self: stretch;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
& span {
color: ${th('colorPrimary')};
font-size: ${th('fontSizeBase')};
font-family: ${th('fontReading')};
margin-bottom: ${th('subGridUnit')};
}
` `
const SearchInput = styled.input` const SearchInput = styled.input`
......
...@@ -12,7 +12,11 @@ import { ...@@ -12,7 +12,11 @@ import {
} from 'pubsweet-component-modal/src/components' } from 'pubsweet-component-modal/src/components'
import { handleError } from './../utils' import { handleError } from './../utils'
import { revokeHandlingEditor, assignHandlingEditor } from '../../redux/editors' import {
revokeHandlingEditor,
assignHandlingEditor,
selectFetching,
} from '../../redux/editors'
import HEModal from './AssignHEModal' import HEModal from './AssignHEModal'
...@@ -49,17 +53,19 @@ const EditorInChiefActions = ({ ...@@ -49,17 +53,19 @@ const EditorInChiefActions = ({
) )
} }
const CardModal = ({ type, ...rest }) => { const CardModal = connect(state => ({
isFetching: selectFetching(state),
}))(({ type, isFetching, ...rest }) => {
switch (type) { switch (type) {
case 'confirmation': case 'confirmation':
return <ConfirmationModal {...rest} /> return <ConfirmationModal {...rest} isFetching={isFetching} />
case 'success': case 'success':
return <SuccessModal {...rest} /> return <SuccessModal {...rest} />
case 'he-modal': case 'he-modal':
default: default:
return <HEModal {...rest} /> return <HEModal {...rest} />
} }
} })
export default compose( export default compose(
connect(null, { connect(null, {
......
import { get, create, remove, update } from 'pubsweet-client/src/helpers/api' import { get } from 'lodash'
import {
get as apiGet,
create,
remove,
update,
} from 'pubsweet-client/src/helpers/api'
const EDITORS_REQUEST = 'EDITORS_REQUEST'
const EDITORS_DONE = 'EDITORS_DONE'
const SET_HANDLING_EDITORS = 'SET_HANDLING_EDITORS' const SET_HANDLING_EDITORS = 'SET_HANDLING_EDITORS'
const setHandlingEditors = editors => ({ const setHandlingEditors = editors => ({
type: SET_HANDLING_EDITORS, type: SET_HANDLING_EDITORS,
editors, payload: { editors },
}) })
export const handlingEditors = state => state.editors export const selectFetching = state => get(state, 'editors.isFetching')
export const selectHandlingEditors = state => get(state, 'editors.editors')
const editorsRequest = () => ({ type: EDITORS_REQUEST })
const editorsDone = () => ({ type: EDITORS_DONE })
export const getHandlingEditors = () => dispatch => export const getHandlingEditors = () => dispatch =>
get(`/users?handlingEditor=true`).then(res => { apiGet(`/users?handlingEditor=true`).then(res =>
dispatch(setHandlingEditors(res.users)) dispatch(setHandlingEditors(res.users)),
}) )
export const assignHandlingEditor = (email, collectionId) => dispatch => export const assignHandlingEditor = (email, collectionId) => dispatch => {
create(`/collections/${collectionId}/invitations`, { dispatch(editorsRequest())
return create(`/collections/${collectionId}/invitations`, {
email, email,
role: 'handlingEditor', role: 'handlingEditor',
}) }).then(
res => {
dispatch(editorsDone())
return res
},
err => {
dispatch(editorsDone())
return err
},
)
}
export const revokeHandlingEditor = (invitationId, collectionId) => dispatch => export const revokeHandlingEditor = (
remove(`/collections/${collectionId}/invitations/${invitationId}`) invitationId,
collectionId,
) => dispatch => {
dispatch(editorsRequest())
return remove(
`/collections/${collectionId}/invitations/${invitationId}`,
).then(
res => {
dispatch(editorsDone())
return res
},
err => {
dispatch(editorsDone())
return err
},
)
}
export const handlingEditorDecision = ( export const handlingEditorDecision = (
invitationId, invitationId,
...@@ -34,11 +73,28 @@ export const handlingEditorDecision = ( ...@@ -34,11 +73,28 @@ export const handlingEditorDecision = (
reason, reason,
}) })
const initialState = [] const initialState = {
isFetching: false,
editors: [],
}
export default (state = initialState, action = {}) => { export default (state = initialState, action = {}) => {
switch (action.type) { switch (action.type) {
case EDITORS_REQUEST:
return {
...state,
isFetching: true,
}
case EDITORS_DONE:
return {
...state,
isFetching: false,
}
case SET_HANDLING_EDITORS: case SET_HANDLING_EDITORS:
return action.editors return {
...state,
editors: action.payload.editors,
}
default: default:
return state return state
} }
......
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