Skip to content
Snippets Groups Projects
Commit 464afe38 authored by Bogdan Cochior's avatar Bogdan Cochior
Browse files

feat(admin): add activate/deactivate user

parent eb791fd2
No related branches found
No related tags found
1 merge request!14Sprint #15
......@@ -4,36 +4,34 @@ import { connect } from 'react-redux'
import { actions } from 'pubsweet-client'
import { ConnectPage } from 'xpub-connect'
import { withJournal } from 'xpub-journal'
import { Icon, Menu, th } from '@pubsweet/ui'
import { Icon, th } from '@pubsweet/ui'
import { withRouter, Link } from 'react-router-dom'
import styled, { withTheme } from 'styled-components'
import { compose, withState, withHandlers } from 'recompose'
import {
withModal,
ConfirmationModal,
} from 'pubsweet-component-modal/src/components'
import { Pagination } from './'
import { updateUserStatusModal } from './utils'
const TableRow = ({
toggleUser,
selected,
id,
email,
roles,
username,
title = '',
firstName = '',
lastName = '',
isActive = true,
affiliation,
isConfirmed,
editorInChief,
handlingEditor,
admin,
roleOptions,
toggleUserStatus,
getStatusLabel,
}) => (
<Row>
<td>
<Input checked={selected} onClick={toggleUser} type="checkbox" />
</td>
<td>{email}</td>
<td>{`${firstName} ${lastName}`}</td>
<td>{email}</td>
<td>{affiliation}</td>
<td>
<Role>{`Author${isEqual(editorInChief, true) ? ', Editor in Chief' : ''}${
......@@ -41,25 +39,28 @@ const TableRow = ({
}${isEqual(admin, true) ? ', Admin' : ''}`}</Role>
</td>
<td>
<Tag>{isConfirmed ? 'Confirmed' : 'Invited'}</Tag>
<Tag>{getStatusLabel()}</Tag>
</td>
<td>
<TD>
<Action to={`/admin/users/edit/${id}`}>Edit</Action>
</td>
<ActionButton onClick={toggleUserStatus}>
{isActive ? 'Deactivate' : 'Activate'}
</ActionButton>
</TD>
</Row>
)
const Users = ({
users,
toggleUser,
toggleAllUsers,
incrementPage,
decrementPage,
page,
itemsPerPage,
users,
theme,
history,
journal,
theme,
itemsPerPage,
incrementPage,
decrementPage,
getStatusLabel,
toggleUserStatus,
}) => {
const slicedUsers = users.slice(
page * itemsPerPage,
......@@ -83,32 +84,6 @@ const Users = ({
</AddButton>
</Header>
<SubHeader>
<div>
<span>Bulk actions: </span>
<Menu
inline
onChange={value => value}
options={[
{ value: 'deactivate', label: 'Deactivate' },
{ value: 'activate', label: 'Activate' },
]}
value="activate"
/>
<Menu
inline
onChange={value => value}
options={[
{ value: 'sort', label: 'SORT' },
{ value: 'unsort', label: 'UNSORT' },
]}
value="sort"
/>
<Icon color={theme.colorPrimary} size={4}>
search
</Icon>
</div>
<Pagination
decrementPage={decrementPage}
hasMore={itemsPerPage * (page + 1) < users.length}
......@@ -122,19 +97,12 @@ const Users = ({
<Table>
<thead>
<tr>
<td>
<Input
checked={users.every(u => u.selected)}
onClick={toggleAllUsers}
type="checkbox"
/>
</td>
<td>Email</td>
<td>Full name</td>
<td>Email</td>
<td>Affiliation</td>
<td width="220">Roles</td>
<td>Status</td>
<td width="50" />
<td width="125" />
</tr>
</thead>
<tbody>
......@@ -142,8 +110,9 @@ const Users = ({
<TableRow
key={u.id}
{...u}
getStatusLabel={getStatusLabel(u)}
roleOptions={journal.roles}
toggleUser={toggleUser(u)}
toggleUserStatus={toggleUserStatus(u)}
/>
))}
</tbody>
......@@ -157,10 +126,10 @@ export default compose(
withRouter,
withJournal,
withTheme,
connect(state => ({ currentUsers: get(state, 'users.users') })),
withState('users', 'setUsers', props =>
props.currentUsers.map(u => ({ ...u, selected: false })),
),
withModal(props => ({
modalComponent: ConfirmationModal,
})),
connect(state => ({ users: get(state, 'users.users') })),
withState('itemsPerPage', 'setItemsPerPage', 20),
withState('page', 'setPage', 0),
withHandlers({
......@@ -172,13 +141,25 @@ export default compose(
decrementPage: ({ setPage }) => () => {
setPage(p => (p > 0 ? p - 1 : p))
},
toggleUser: ({ setUsers }) => user => () => {
setUsers(prev =>
prev.map(u => (u.id === user.id ? { ...u, selected: !u.selected } : u)),
)
getStatusLabel: () => ({ isConfirmed, isActive = true }) => () => {
if (isConfirmed) {
return isActive ? 'Active' : 'Inactive'
}
return 'Invited'
},
toggleAllUsers: ({ setUsers }) => () => {
setUsers(users => users.map(u => ({ ...u, selected: !u.selected })))
toggleUserStatus: ({
dispatch,
showModal,
hideModal,
setModalError,
}) => user => () => {
updateUserStatusModal({
dispatch,
showModal,
hideModal,
setModalError,
user,
})
},
}),
)(Users)
......@@ -282,7 +263,8 @@ const Row = styled.tr`
text-align: left;
&:hover {
background-color: ${th('backgroundColorReverse')};
a {
a,
i {
display: block;
}
}
......@@ -312,10 +294,18 @@ const Action = styled(Link)`
color: ${th('colorPrimary')};
display: none;
`
const TD = styled.td`
display: inline-flex;
width: 100%;
min-height: 20px;
`
const Input = styled.input`
height: 20px;
width: 20px;
const ActionButton = styled.i`
cursor: pointer;
display: none;
font-style: unset;
text-decoration: underline;
margin: 0 calc(${th('subGridUnit')} * 2);
`
// #endregion
import { actions } from 'pubsweet-client'
import { SubmissionError } from 'redux-form'
import { pick, map, omit, get } from 'lodash'
import { update } from 'pubsweet-client/src/helpers/api'
import { pick, map, omit, get, isBoolean, replace } from 'lodash'
import { handleError } from '../utils'
const generatePasswordHash = () =>
Array.from({ length: 4 }, () =>
......@@ -40,6 +44,8 @@ export const parseUpdateUser = values => {
'roles',
'editorInChief',
'handlingEditor',
'isActive',
'username',
]
return pick(values, valuesToSave)
......@@ -55,3 +61,50 @@ export const handleFormError = error => {
})
}
}
const toggleUserStatus = user => {
const { isActive, username } = user
let newState = true
let newUsername = ''
if (!isBoolean(isActive) || isActive) {
newState = false
newUsername = `invalid***${username}`
} else {
newState = true
newUsername = replace(username, 'invalid***', '')
}
return {
...user,
isActive: newState,
username: newUsername,
}
}
export const updateUserStatus = user => {
const updatedUser = toggleUserStatus(user)
return update(`/users/${user.id}`, parseUpdateUser(updatedUser))
}
export const updateUserStatusModal = ({
user,
showModal,
hideModal,
setModalError,
dispatch,
}) =>
showModal({
title: 'Are you sure?',
subtitle: `${user.isActive === false ? 'Activate ' : 'Deactivate '}${
user.email
}.`,
confirmText: 'Confirm',
onConfirm: () => {
updateUserStatus(user).then(() => {
dispatch(actions.getUsers())
hideModal()
}, handleError(setModalError))
},
onCancel: hideModal,
})
......@@ -133,6 +133,8 @@ export const parseUpdateUser = values => {
'roles',
'editorInChief',
'handlingEditor',
'isActive',
'username',
]
return pick(values, valuesToSave)
......
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