Newer
Older
import React from 'react'
import { get } from 'lodash'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { Icon, Menu } from '@pubsweet/ui'
import { actions } from 'pubsweet-client'
import { ConnectPage } from 'xpub-connect'
import { withJournal } from 'xpub-journal'
import { withRouter } from 'react-router-dom'
import { compose, withState, withHandlers } from 'recompose'
const TableRow = ({
toggleUser,
selected,
email,
roles,
username,
firstName = '',
lastName = '',
affiliation,
isConfirmed,
<Row>
<td>
<Input checked={selected} onClick={toggleUser} type="checkbox" />
</td>
<td>{email}</td>
<td>{`${firstName} ${lastName}`}</td>
<td>{affiliation}</td>
<td>
{roles &&
roles.map((r, i, arr) => (
<Role key={r}>{`${roleOptions[r]}${
i !== arr.length - 1 ? ', ' : ''
}`}</Role>
))}
</td>
<td>
<Tag>{isConfirmed ? 'Confirmed' : 'Invited'}</Tag>
</td>
<td>
<Action href={`/admin/users/edit/${id}`}>Edit</Action>
</td>
users,
toggleUser,
toggleAllUsers,
incrementPage,
decrementPage,
page,
itemsPerPage,
}) => {
const slicedUsers = users.slice(
page * itemsPerPage,
itemsPerPage * (page + 1),
)
return (
<div>
<Header>
<BreadCrumbs>
<span>Admin Dashboard</span>
<span>Users</span>
</BreadCrumbs>
<AddButton onClick={() => history.push('/admin/users/add')}>
<Icon color="#667080">plus-circle</Icon>
Add User
</AddButton>
</Header>
<SubHeader>
<div>
<span>Bulk actions: </span>
<Menu
onChange={value => value}
options={[
{ value: 'deactivate', label: 'Deactivate' },
{ value: 'activate', label: 'Activate' },
]}
value="activate"
/>
<Menu
onChange={value => value}
options={[
{ value: 'sort', label: 'SORT' },
{ value: 'unsort', label: 'UNSORT' },
]}
value="sort"
/>
<Icon color="#667080" size={24}>
search
</Icon>
</div>
<Pagination
decrementPage={decrementPage}
hasMore={itemsPerPage * (page + 1) < users.length}
incrementPage={incrementPage}
itemsPerPage={itemsPerPage}
maxLength={users.length}
page={page}
/>
</SubHeader>
<Table>
<thead>
<tr>
<td>
<Input
checked={users.every(u => u.selected)}
onClick={toggleAllUsers}
type="checkbox"
/>
</td>
<td>Email</td>
<td>Full name</td>
<td>Affiliation</td>
<td width="200">Roles</td>
<td>Status</td>
<td width="50" />
</tr>
</thead>
<tbody>
{slicedUsers.map(u => (
<TableRow
key={u.id}
{...u}
roleOptions={journal.roles}
toggleUser={toggleUser(u)}
))}
</tbody>
</Table>
</div>
)
}
export default compose(
ConnectPage(() => [actions.getUsers()]),
withRouter,
connect(state => ({ currentUsers: get(state, 'users.users') })),
withState('users', 'setUsers', props =>
props.currentUsers.map(u => ({ ...u, selected: false })),
),
withState('itemsPerPage', 'setItemsPerPage', 20),
withState('page', 'setPage', 0),
withHandlers({
incrementPage: ({ setPage, page, itemsPerPage, users }) => () => {
if (page * itemsPerPage + itemsPerPage < users.length) {
setPage(p => p + 1)
}
},
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)),
)
},
toggleAllUsers: ({ setUsers }) => () => {
setUsers(users => users.map(u => ({ ...u, selected: !u.selected })))
},
}),
)(Users)
// #region styled-components
const AddButton = styled.button`
align-items: center;
border: none;
cursor: pointer;
display: flex;
font-family: Helvetica;
font-size: 12px;
text-align: left;
color: #667080;
&:active,
&:focus {
outline: none;
}
`
const Header = styled.div`
flex-direction: row;
align-items: center;
const BreadCrumbs = styled.div`
font-size: 17px;
text-align: left;
color: #667080;
&:after {
content: '>';
padding: 0 10px;
}
&:last-child {
font-size: 24px;
font-weight: bold;
&:after {
content: '';
}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
}
`
const SubHeader = styled.div`
align-items: center;
border-bottom: 1px solid #667080;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 20px;
padding-bottom: 10px;
> div:first-child {
display: flex;
align-items: center;
}
span {
font-family: Helvetica;
font-size: 14px;
text-align: left;
color: #667080;
}
`
const Table = styled.table`
border-spacing: 0;
border-collapse: collapse;
margin-top: 10px;
& thead tr {
height: 40px;
border-bottom: 1px solid #667080;
font-family: Helvetica;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #667080;
}
`
const Row = styled.tr`
border-bottom: 1px solid #667080;
color: #667080;
font-family: Helvetica;
font-size: 14px;
height: 40px;
text-align: left;
&:hover {
background-color: #e6e7e9;
a {
display: block;
}
}
const Tag = styled.span`
border: solid 1px #667080;
text-transform: uppercase;
font-family: Helvetica;
font-size: 12px;
font-weight: bold;
text-align: left;
color: #667080;
padding: 2px 10px;
margin-right: 5px;
`
const Role = styled.span`
height: 17px;
font-size: 14px;
text-align: left;
color: #667080;
text-transform: uppercase;
`
const Action = styled.a`
color: #667080;
display: none;
`
const Input = styled.input`
height: 20px;
width: 20px;