Merge pull request #971 from influxdata/feature/934-ew-admin-delete
EW Admin Delete Confirmation Componentpull/973/head
commit
2a7a010976
|
@ -0,0 +1,57 @@
|
||||||
|
import reducer from 'src/admin/reducers/admin'
|
||||||
|
|
||||||
|
import {
|
||||||
|
loadRoles,
|
||||||
|
deleteRole,
|
||||||
|
deleteUser,
|
||||||
|
} from 'src/admin/actions'
|
||||||
|
|
||||||
|
let state = undefined
|
||||||
|
const r1 = {name: 'role1'}
|
||||||
|
const r2 = {name: 'role2'}
|
||||||
|
const roles = [r1, r2]
|
||||||
|
|
||||||
|
const u1 = {name: 'user1'}
|
||||||
|
const u2 = {name: 'user2'}
|
||||||
|
const users = [u1, u2]
|
||||||
|
|
||||||
|
describe('Admin.Reducers', () => {
|
||||||
|
it('it can load the roles', () => {
|
||||||
|
const actual = reducer(state, loadRoles({roles}))
|
||||||
|
const expected = {
|
||||||
|
roles,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(actual.roles).to.deep.equal(expected.roles)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('it can delete a role', () => {
|
||||||
|
state = {
|
||||||
|
roles: [
|
||||||
|
r1,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const actual = reducer(state, deleteRole(r1))
|
||||||
|
const expected = {
|
||||||
|
roles: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(actual.roles).to.deep.equal(expected.roles)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('it can delete a user', () => {
|
||||||
|
state = {
|
||||||
|
users: [
|
||||||
|
u1,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const actual = reducer(state, deleteUser(u1))
|
||||||
|
const expected = {
|
||||||
|
users: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(actual.users).to.deep.equal(expected.users)
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,4 +1,9 @@
|
||||||
import {getUsers, getRoles} from 'src/admin/apis'
|
import {
|
||||||
|
getUsers,
|
||||||
|
getRoles,
|
||||||
|
deleteRole as deleteRoleAJAX,
|
||||||
|
deleteUser as deleteUserAJAX,
|
||||||
|
} from 'src/admin/apis'
|
||||||
import {killQuery as killQueryProxy} from 'shared/apis/metaQuery'
|
import {killQuery as killQueryProxy} from 'shared/apis/metaQuery'
|
||||||
|
|
||||||
export const loadUsers = ({users}) => ({
|
export const loadUsers = ({users}) => ({
|
||||||
|
@ -29,11 +34,6 @@ export const loadQueries = (queries) => ({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// async actions
|
|
||||||
export const loadUsersAsync = (url) => async (dispatch) => {
|
|
||||||
const {data} = await getUsers(url)
|
|
||||||
dispatch(loadUsers(data))
|
|
||||||
}
|
|
||||||
export const loadRoles = ({roles}) => ({
|
export const loadRoles = ({roles}) => ({
|
||||||
type: 'LOAD_ROLES',
|
type: 'LOAD_ROLES',
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -41,6 +41,26 @@ export const loadRoles = ({roles}) => ({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const deleteRole = (role) => ({
|
||||||
|
type: 'DELETE_ROLE',
|
||||||
|
payload: {
|
||||||
|
role,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const deleteUser = (user) => ({
|
||||||
|
type: 'DELETE_USER',
|
||||||
|
payload: {
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// async actions
|
||||||
|
export const loadUsersAsync = (url) => async (dispatch) => {
|
||||||
|
const {data} = await getUsers(url)
|
||||||
|
dispatch(loadUsers(data))
|
||||||
|
}
|
||||||
|
|
||||||
export const loadRolesAsync = (url) => async (dispatch) => {
|
export const loadRolesAsync = (url) => async (dispatch) => {
|
||||||
const {data} = await getRoles(url)
|
const {data} = await getRoles(url)
|
||||||
dispatch(loadRoles(data))
|
dispatch(loadRoles(data))
|
||||||
|
@ -54,3 +74,19 @@ export const killQueryAsync = (source, queryID) => (dispatch) => {
|
||||||
// kill query on server
|
// kill query on server
|
||||||
killQueryProxy(source, queryID)
|
killQueryProxy(source, queryID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteRoleAsync = (role, addFlashMessage) => (dispatch) => {
|
||||||
|
// optimistic update
|
||||||
|
dispatch(deleteRole(role))
|
||||||
|
|
||||||
|
// delete role on server
|
||||||
|
deleteRoleAJAX(role.links.self, addFlashMessage, role.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteUserAsync = (user, addFlashMessage) => (dispatch) => {
|
||||||
|
// optimistic update
|
||||||
|
dispatch(deleteUser(user))
|
||||||
|
|
||||||
|
// delete user on server
|
||||||
|
deleteUserAJAX(user.links.self, addFlashMessage, user.name)
|
||||||
|
}
|
||||||
|
|
|
@ -21,3 +21,43 @@ export const getRoles = async (url) => {
|
||||||
console.error(error) // eslint-disable-line no-console
|
console.error(error) // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteRole = async (url, addFlashMessage, rolename) => {
|
||||||
|
try {
|
||||||
|
const response = await AJAX({
|
||||||
|
method: 'DELETE',
|
||||||
|
url,
|
||||||
|
})
|
||||||
|
addFlashMessage({
|
||||||
|
type: 'success',
|
||||||
|
text: `${rolename} successfully deleted.`,
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error) // eslint-disable-line no-console
|
||||||
|
addFlashMessage({
|
||||||
|
type: 'error',
|
||||||
|
text: `Error deleting: ${rolename}.`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteUser = async (url, addFlashMessage, username) => {
|
||||||
|
try {
|
||||||
|
const response = await AJAX({
|
||||||
|
method: 'DELETE',
|
||||||
|
url,
|
||||||
|
})
|
||||||
|
addFlashMessage({
|
||||||
|
type: 'success',
|
||||||
|
text: `${username} successfully deleted.`,
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error) // eslint-disable-line no-console
|
||||||
|
addFlashMessage({
|
||||||
|
type: 'error',
|
||||||
|
text: `Error deleting: ${username}.`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ class AdminTabs extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {users, roles, source} = this.props
|
const {users, roles, source, onDeleteRole, onDeleteUser} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs onSelect={this.handleActivateTab}>
|
<Tabs onSelect={this.handleActivateTab}>
|
||||||
|
@ -35,11 +35,13 @@ class AdminTabs extends Component {
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<UsersTable
|
<UsersTable
|
||||||
users={users}
|
users={users}
|
||||||
|
onDelete={onDeleteUser}
|
||||||
/>
|
/>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<RolesTable
|
<RolesTable
|
||||||
roles={roles}
|
roles={roles}
|
||||||
|
onDelete={onDeleteRole}
|
||||||
/>
|
/>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
|
@ -53,6 +55,7 @@ class AdminTabs extends Component {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
arrayOf,
|
arrayOf,
|
||||||
|
func,
|
||||||
shape,
|
shape,
|
||||||
string,
|
string,
|
||||||
} = PropTypes
|
} = PropTypes
|
||||||
|
@ -66,6 +69,8 @@ AdminTabs.propTypes = {
|
||||||
})),
|
})),
|
||||||
source: shape(),
|
source: shape(),
|
||||||
roles: arrayOf(shape()),
|
roles: arrayOf(shape()),
|
||||||
|
onDeleteRole: func.isRequired,
|
||||||
|
onDeleteUser: func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AdminTabs
|
export default AdminTabs
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React, {PropTypes, Component} from 'react'
|
||||||
|
import OnClickOutside from 'shared/components/OnClickOutside'
|
||||||
|
|
||||||
|
const DeleteButton = ({onConfirm}) => (
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-danger admin-table--delete"
|
||||||
|
onClick={onConfirm}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
const ConfirmButtons = ({onDelete, item, onCancel}) => (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-primary"
|
||||||
|
onClick={() => onDelete(item)}
|
||||||
|
>
|
||||||
|
<span className="icon checkmark"></span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-default"
|
||||||
|
onClick={onCancel}
|
||||||
|
>
|
||||||
|
<span className="icon remove"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
class DeleteRow extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
isConfirmed: false,
|
||||||
|
}
|
||||||
|
this.handleConfirm = ::this.handleConfirm
|
||||||
|
this.handleCancel = ::this.handleCancel
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConfirm() {
|
||||||
|
this.setState({isConfirmed: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel() {
|
||||||
|
this.setState({isConfirmed: false})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClickOutside() {
|
||||||
|
this.setState({isConfirmed: false})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {onDelete, item} = this.props
|
||||||
|
const {isConfirmed} = this.state
|
||||||
|
|
||||||
|
if (isConfirmed) {
|
||||||
|
return (
|
||||||
|
<ConfirmButtons
|
||||||
|
onDelete={onDelete}
|
||||||
|
item={item}
|
||||||
|
onCancel={this.handleCancel}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DeleteButton onConfirm={this.handleConfirm} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
func,
|
||||||
|
shape,
|
||||||
|
} = PropTypes
|
||||||
|
|
||||||
|
DeleteButton.propTypes = {
|
||||||
|
onConfirm: func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmButtons.propTypes = {
|
||||||
|
onDelete: func.isRequired,
|
||||||
|
item: shape({}).isRequired,
|
||||||
|
onCancel: func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteRow.propTypes = {
|
||||||
|
item: shape({}),
|
||||||
|
onDelete: func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OnClickOutside(DeleteRow)
|
|
@ -2,6 +2,7 @@ import React, {PropTypes} from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import MultiSelectDropdown from 'shared/components/MultiSelectDropdown'
|
import MultiSelectDropdown from 'shared/components/MultiSelectDropdown'
|
||||||
|
import DeleteRow from 'src/admin/components/DeleteRow'
|
||||||
|
|
||||||
const PERMISSIONS = [
|
const PERMISSIONS = [
|
||||||
"NoPermissions",
|
"NoPermissions",
|
||||||
|
@ -25,7 +26,7 @@ const PERMISSIONS = [
|
||||||
"KapacitorConfigAPI",
|
"KapacitorConfigAPI",
|
||||||
]
|
]
|
||||||
|
|
||||||
const RoleRow = ({role: {name, permissions, users}}) => (
|
const RoleRow = ({role: {name, permissions, users}, role, onDelete}) => (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{name}</td>
|
<td>{name}</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -43,21 +44,22 @@ const RoleRow = ({role: {name, permissions, users}}) => (
|
||||||
{
|
{
|
||||||
users && users.length ?
|
users && users.length ?
|
||||||
<MultiSelectDropdown
|
<MultiSelectDropdown
|
||||||
items={users.map((role) => role.name)}
|
items={users.map((r) => r.name)}
|
||||||
selectedItems={[]}
|
selectedItems={[]}
|
||||||
label={'Select Users'}
|
label={'Select Users'}
|
||||||
onApply={() => '//TODO'}
|
onApply={() => '//TODO'}
|
||||||
/> : '\u2014'
|
/> : '\u2014'
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right">
|
<td className="text-right" style={{width: "85px"}}>
|
||||||
<button className="btn btn-xs btn-danger admin-table--delete">Delete</button>
|
<DeleteRow onDelete={onDelete} item={role} />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
arrayOf,
|
arrayOf,
|
||||||
|
func,
|
||||||
shape,
|
shape,
|
||||||
string,
|
string,
|
||||||
} = PropTypes
|
} = PropTypes
|
||||||
|
@ -72,6 +74,7 @@ RoleRow.propTypes = {
|
||||||
name: string,
|
name: string,
|
||||||
})),
|
})),
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
onDelete: func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RoleRow
|
export default RoleRow
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, {PropTypes} from 'react'
|
||||||
import RoleRow from 'src/admin/components/RoleRow'
|
import RoleRow from 'src/admin/components/RoleRow'
|
||||||
import EmptyRow from 'src/admin/components/EmptyRow'
|
import EmptyRow from 'src/admin/components/EmptyRow'
|
||||||
|
|
||||||
const RolesTable = ({roles}) => (
|
const RolesTable = ({roles, onDelete}) => (
|
||||||
<div className="panel panel-info">
|
<div className="panel panel-info">
|
||||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||||
<div className="users__search-widget input-group admin__search-widget">
|
<div className="users__search-widget input-group admin__search-widget">
|
||||||
|
@ -31,7 +31,7 @@ const RolesTable = ({roles}) => (
|
||||||
{
|
{
|
||||||
roles.length ?
|
roles.length ?
|
||||||
roles.map((role) =>
|
roles.map((role) =>
|
||||||
<RoleRow key={role.name} role={role} />
|
<RoleRow key={role.name} role={role} onDelete={onDelete} />
|
||||||
) : <EmptyRow tableName={'Roles'} />
|
) : <EmptyRow tableName={'Roles'} />
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -42,6 +42,7 @@ const RolesTable = ({roles}) => (
|
||||||
|
|
||||||
const {
|
const {
|
||||||
arrayOf,
|
arrayOf,
|
||||||
|
func,
|
||||||
shape,
|
shape,
|
||||||
string,
|
string,
|
||||||
} = PropTypes
|
} = PropTypes
|
||||||
|
@ -57,6 +58,7 @@ RolesTable.propTypes = {
|
||||||
name: string,
|
name: string,
|
||||||
})),
|
})),
|
||||||
})),
|
})),
|
||||||
|
onDelete: func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RolesTable
|
export default RolesTable
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, {PropTypes} from 'react'
|
import React, {PropTypes} from 'react'
|
||||||
import MultiSelectDropdown from 'shared/components/MultiSelectDropdown'
|
import MultiSelectDropdown from 'shared/components/MultiSelectDropdown'
|
||||||
|
import DeleteRow from 'src/admin/components/DeleteRow'
|
||||||
|
|
||||||
const UserRow = ({user: {name, roles, permissions}}) => (
|
const UserRow = ({user: {name, roles, permissions}, user, onDelete}) => (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{name}</td>
|
<td>{name}</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -26,11 +27,15 @@ const UserRow = ({user: {name, roles, permissions}}) => (
|
||||||
/> : '\u2014'
|
/> : '\u2014'
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
<td className="text-right" style={{width: "85px"}}>
|
||||||
|
<DeleteRow onDelete={onDelete} item={user} />
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
arrayOf,
|
arrayOf,
|
||||||
|
func,
|
||||||
shape,
|
shape,
|
||||||
string,
|
string,
|
||||||
} = PropTypes
|
} = PropTypes
|
||||||
|
@ -45,6 +50,7 @@ UserRow.propTypes = {
|
||||||
name: string,
|
name: string,
|
||||||
})),
|
})),
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
onDelete: func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserRow
|
export default UserRow
|
||||||
|
|
|
@ -2,22 +2,23 @@ import React, {PropTypes} from 'react'
|
||||||
import UserRow from 'src/admin/components/UserRow'
|
import UserRow from 'src/admin/components/UserRow'
|
||||||
import EmptyRow from 'src/admin/components/EmptyRow'
|
import EmptyRow from 'src/admin/components/EmptyRow'
|
||||||
|
|
||||||
const UsersTable = ({users}) => (
|
const UsersTable = ({users, onDelete}) => (
|
||||||
<div className="panel panel-minimal">
|
<div className="panel panel-info">
|
||||||
<div className="panel-body">
|
<div className="panel-body">
|
||||||
<table className="table v-center">
|
<table className="table v-center admin-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>User</th>
|
<th>User</th>
|
||||||
<th>Roles</th>
|
<th>Roles</th>
|
||||||
<th>Permissions</th>
|
<th>Permissions</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
users.length ?
|
users.length ?
|
||||||
users.map((user) =>
|
users.map((user) =>
|
||||||
<UserRow key={user.name} user={user} />
|
<UserRow key={user.name} user={user} onDelete={onDelete} />
|
||||||
) : <EmptyRow tableName={'Users'} />
|
) : <EmptyRow tableName={'Users'} />
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -28,6 +29,7 @@ const UsersTable = ({users}) => (
|
||||||
|
|
||||||
const {
|
const {
|
||||||
arrayOf,
|
arrayOf,
|
||||||
|
func,
|
||||||
shape,
|
shape,
|
||||||
string,
|
string,
|
||||||
} = PropTypes
|
} = PropTypes
|
||||||
|
@ -43,6 +45,7 @@ UsersTable.propTypes = {
|
||||||
scope: string.isRequired,
|
scope: string.isRequired,
|
||||||
})),
|
})),
|
||||||
})),
|
})),
|
||||||
|
onDelete: func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UsersTable
|
export default UsersTable
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
import React, {Component, PropTypes} from 'react'
|
import React, {Component, PropTypes} from 'react'
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux'
|
||||||
import {bindActionCreators} from 'redux';
|
import {bindActionCreators} from 'redux'
|
||||||
import {loadUsersAsync, loadRolesAsync} from 'src/admin/actions'
|
import {
|
||||||
|
loadUsersAsync,
|
||||||
|
loadRolesAsync,
|
||||||
|
deleteRoleAsync,
|
||||||
|
deleteUserAsync,
|
||||||
|
} from 'src/admin/actions'
|
||||||
import AdminTabs from 'src/admin/components/AdminTabs'
|
import AdminTabs from 'src/admin/components/AdminTabs'
|
||||||
|
|
||||||
class AdminPage extends Component {
|
class AdminPage extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
this.handleDeleteRole = ::this.handleDeleteRole
|
||||||
|
this.handleDeleteUser = ::this.handleDeleteUser
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -18,6 +25,14 @@ class AdminPage extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleDeleteRole(role) {
|
||||||
|
this.props.deleteRole(role, this.props.addFlashMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDeleteUser(user) {
|
||||||
|
this.props.deleteUser(user, this.props.addFlashMessage)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {users, roles, source} = this.props
|
const {users, roles, source} = this.props
|
||||||
|
|
||||||
|
@ -36,7 +51,17 @@ class AdminPage extends Component {
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
{users.length ? <AdminTabs users={users} roles={roles} source={source}/> : <span>Loading...</span>}
|
{
|
||||||
|
users.length ?
|
||||||
|
<AdminTabs
|
||||||
|
users={users}
|
||||||
|
roles={roles}
|
||||||
|
source={source}
|
||||||
|
onDeleteRole={this.handleDeleteRole}
|
||||||
|
onDeleteUser={this.handleDeleteUser}
|
||||||
|
/> :
|
||||||
|
<span>Loading...</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,6 +89,9 @@ AdminPage.propTypes = {
|
||||||
roles: arrayOf(shape()),
|
roles: arrayOf(shape()),
|
||||||
loadUsers: func,
|
loadUsers: func,
|
||||||
loadRoles: func,
|
loadRoles: func,
|
||||||
|
deleteRole: func,
|
||||||
|
deleteUser: func,
|
||||||
|
addFlashMessage: func,
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({admin}) => ({
|
const mapStateToProps = ({admin}) => ({
|
||||||
|
@ -74,6 +102,8 @@ const mapStateToProps = ({admin}) => ({
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
loadUsers: bindActionCreators(loadUsersAsync, dispatch),
|
loadUsers: bindActionCreators(loadUsersAsync, dispatch),
|
||||||
loadRoles: bindActionCreators(loadRolesAsync, dispatch),
|
loadRoles: bindActionCreators(loadRolesAsync, dispatch),
|
||||||
|
deleteRole: bindActionCreators(deleteRoleAsync, dispatch),
|
||||||
|
deleteUser: bindActionCreators(deleteUserAsync, dispatch),
|
||||||
})
|
})
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(AdminPage);
|
export default connect(mapStateToProps, mapDispatchToProps)(AdminPage)
|
||||||
|
|
|
@ -17,6 +17,24 @@ export default function admin(state = initialState, action) {
|
||||||
return {...state, ...action.payload}
|
return {...state, ...action.payload}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'DELETE_ROLE': {
|
||||||
|
const {role} = action.payload
|
||||||
|
const newState = {
|
||||||
|
roles: state.roles.filter(r => r.name !== role.name),
|
||||||
|
}
|
||||||
|
|
||||||
|
return {...state, ...newState}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'DELETE_USER': {
|
||||||
|
const {user} = action.payload
|
||||||
|
const newState = {
|
||||||
|
users: state.users.filter(u => u.name !== user.name),
|
||||||
|
}
|
||||||
|
|
||||||
|
return {...state, ...newState}
|
||||||
|
}
|
||||||
|
|
||||||
case 'LOAD_QUERIES': {
|
case 'LOAD_QUERIES': {
|
||||||
return {...state, ...action.payload}
|
return {...state, ...action.payload}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue