diff --git a/packages/components-faraday/src/components/Admin/AdminUsers.js b/packages/components-faraday/src/components/Admin/AdminUsers.js index ead06f97a1cd69e06bd4c5125f185613e2cca280..ad6bbcd4cf568576516f55e287e1f102c7b93193 100644 --- a/packages/components-faraday/src/components/Admin/AdminUsers.js +++ b/packages/components-faraday/src/components/Admin/AdminUsers.js @@ -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 diff --git a/packages/components-faraday/src/components/Admin/utils.js b/packages/components-faraday/src/components/Admin/utils.js index 1029db45e7ae91d1919fa005dbb927398badd507..99ea13817d8fe002597127d1a0d315c739482ec9 100644 --- a/packages/components-faraday/src/components/Admin/utils.js +++ b/packages/components-faraday/src/components/Admin/utils.js @@ -1,5 +1,9 @@ +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, + }) diff --git a/packages/components-faraday/src/components/utils.js b/packages/components-faraday/src/components/utils.js index b6f31756513a0ac1ed01748b36126eec7ec912d9..b09e279905facba7e1d5b9bf7db2521395be22f0 100644 --- a/packages/components-faraday/src/components/utils.js +++ b/packages/components-faraday/src/components/utils.js @@ -133,6 +133,8 @@ export const parseUpdateUser = values => { 'roles', 'editorInChief', 'handlingEditor', + 'isActive', + 'username', ] return pick(values, valuesToSave)