Skip to content

Commit 4321886

Browse files
committed
Merge branch 'feature/admin-system' into dev
2 parents 1613ea6 + c5b0009 commit 4321886

File tree

9 files changed

+176
-11
lines changed

9 files changed

+176
-11
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import Navbar from 'react-bootstrap/lib/Navbar';
3+
import Grid from 'react-bootstrap/lib/Grid';
4+
import Row from 'react-bootstrap/lib/Row';
5+
import Col from 'react-bootstrap/lib/Col';
6+
import Nav from 'react-bootstrap/lib/Nav';
7+
import NavItem from 'react-bootstrap/lib/NavItem';
8+
import ErrorList from '../utils/ErrorList';
9+
10+
const AdminPageLayout = ({ children, ...rest }) => (
11+
<div>
12+
<Navbar fluid>
13+
<Navbar.Header>
14+
<Navbar.Brand>
15+
<a href="/admin">Express-React-HMR-Boilerplate Admin System</a>
16+
</Navbar.Brand>
17+
<Navbar.Toggle />
18+
</Navbar.Header>
19+
<Navbar.Collapse>
20+
</Navbar.Collapse>
21+
</Navbar>
22+
<Grid fluid>
23+
<Row>
24+
<Col md={2}>
25+
<Nav bsStyle="pills" stacked activeKey={1}>
26+
<NavItem eventKey={1} href="/admin/user">User</NavItem>
27+
<NavItem eventKey={2} href="/">Go back to site</NavItem>
28+
</Nav>
29+
</Col>
30+
<Col md={10} {...rest}>
31+
<ErrorList />
32+
{children}
33+
</Col>
34+
</Row>
35+
</Grid>
36+
</div>
37+
);
38+
39+
export default AdminPageLayout;

src/common/components/layouts/AppLayout.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import React from 'react';
22
import Head from '../widgets/Head';
3-
import Navigation from '../utils/Navigation';
4-
import ErrorList from '../utils/ErrorList';
53

64
const AppLayout = ({ children }) => (
75
<div>
@@ -15,20 +13,14 @@ const AppLayout = ({ children }) => (
1513
},
1614
]}
1715
links={[
18-
// jscs:disable
1916
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css',
2017
'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css',
2118
'/css/main.css',
22-
// jscs:enable
2319
]}
2420
scripts={[
25-
// jscs:disable
2621
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js',
27-
// jscs:enable
2822
]}
2923
/>
30-
<Navigation />
31-
<ErrorList />
3224
{children}
3325
</div>
3426
);
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import React from 'react';
22
import Grid from 'react-bootstrap/lib/Grid';
3+
import Navigation from '../utils/Navigation';
4+
import ErrorList from '../utils/ErrorList';
35

46
const PageLayout = ({ children, ...rest }) => (
5-
<Grid {...rest}>
6-
{children}
7-
</Grid>
7+
<div>
8+
<Navigation />
9+
<ErrorList />
10+
<Grid {...rest}>
11+
{children}
12+
</Grid>
13+
</div>
814
);
915

1016
export default PageLayout;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React, { Component } from 'react';
2+
import { connect } from 'react-redux';
3+
import { withRouter } from 'react-router';
4+
import PageHeader from 'react-bootstrap/lib/PageHeader';
5+
import Table from 'react-bootstrap/lib/Table';
6+
import Resources from '../../../../constants/Resources';
7+
import userAPI from '../../../../api/user';
8+
import { pushErrors } from '../../../../actions/errorActions';
9+
import { setCrrentPage, setPage } from '../../../../actions/pageActions';
10+
import PageLayout from '../../../layouts/AdminPageLayout';
11+
import Pagination from '../../../utils/BsPagination';
12+
13+
class ListPage extends Component {
14+
constructor() {
15+
super();
16+
this.state = {
17+
users: [],
18+
};
19+
}
20+
21+
componentDidMount() {
22+
let { dispatch, location } = this.props;
23+
dispatch(setCrrentPage(Resources.USER, location.query.page || 1));
24+
}
25+
26+
componentDidUpdate(prevProps) {
27+
let { dispatch, apiEngine, page, router, location } = this.props;
28+
29+
if (prevProps.page.current !== page.current) {
30+
userAPI(apiEngine)
31+
.list({ page: page.current })
32+
.catch((err) => {
33+
dispatch(pushErrors(err));
34+
throw err;
35+
})
36+
.then((json) => {
37+
this.setState({ users: json.users });
38+
dispatch(setPage(Resources.USER, json.page));
39+
router.push({
40+
pathname: location.pathname,
41+
query: { page: json.page.current },
42+
});
43+
});
44+
}
45+
}
46+
47+
render() {
48+
let { users } = this.state;
49+
50+
return (
51+
<PageLayout>
52+
<PageHeader>User List</PageHeader>
53+
<Table striped bordered>
54+
<thead>
55+
<tr>
56+
<th>ID</th>
57+
<th>Name</th>
58+
<th>Email</th>
59+
<th>Role</th>
60+
<th>Created At</th>
61+
</tr>
62+
</thead>
63+
<tbody>
64+
{users.map((user) => (
65+
<tr key={user._id}>
66+
<td>{user._id}</td>
67+
<td>{user.name}</td>
68+
<td>{user.email.value}</td>
69+
<td>{user.role}</td>
70+
<td>{user.createdAt}</td>
71+
</tr>
72+
))}
73+
</tbody>
74+
</Table>
75+
<Pagination resourceName={Resources.USER} />
76+
</PageLayout>
77+
);
78+
}
79+
}
80+
81+
export default withRouter(connect(state => ({
82+
apiEngine: state.apiEngine,
83+
page: state.pages[Resources.USER] || {},
84+
}))(ListPage));

src/common/components/utils/Navigation.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { Component } from 'react';
22
import { Link } from 'react-router';
33
import Grid from 'react-bootstrap/lib/Grid';
4+
import Roles from '../../constants/Roles';
45
import { updateLocale } from '../../actions/intlActions';
56
import { pushErrors } from '../../actions/errorActions';
67
import Navbar from './BsNavbar';
@@ -24,6 +25,7 @@ class Navigation extends Component {
2425
let { cookies: { token, user } } = this.context.store.getState();
2526
let isAuth = !!token;
2627
user = (user && JSON.parse(user)) || {};
28+
let isAdmin = (user.role === Roles.ADMIN);
2729

2830
return (
2931
<Navbar staticTop>
@@ -76,6 +78,10 @@ class Navigation extends Component {
7678
<NavLink to="/user/register">
7779
<Text id="nav.user.register" />
7880
</NavLink>}
81+
{isAuth && isAdmin &&
82+
<NavLink to="/admin">
83+
Admin System
84+
</NavLink>}
7985
{isAuth &&
8086
<NavLink to="/user/me">
8187
<Text id="nav.user.profile" />

src/common/constants/Resources.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export default {
2+
USER: 'USER',
23
TODO: 'TODO',
34
};

src/common/routes/admin/index.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Roles from '../../constants/Roles';
2+
import compose from '../../utils/composeEnterHooks';
3+
4+
export default (store) => ({
5+
path: 'admin',
6+
getIndexRoute(location, cb) {
7+
require.ensure([], (require) => {
8+
cb(null, {
9+
component:
10+
require('../../components/pages/admin/user/ListPage').default,
11+
});
12+
});
13+
},
14+
getChildRoutes(location, cb) {
15+
require.ensure([], (require) => {
16+
cb(null, [
17+
require('./user').default(store),
18+
]);
19+
});
20+
},
21+
onEnter: compose.series(
22+
require('../../utils/authRequired').default(store),
23+
require('../../utils/roleRequired').default(store)(Roles.ADMIN),
24+
),
25+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export default (store) => ({
2+
path: 'user',
3+
getIndexRoute(location, cb) {
4+
require.ensure([], (require) => {
5+
cb(null, {
6+
component:
7+
require('../../../components/pages/admin/user/ListPage').default,
8+
});
9+
});
10+
},
11+
});

src/common/routes/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default (store) => ({
88
getChildRoutes(location, cb) {
99
require.ensure([], (require) => {
1010
cb(null, [
11+
require('./admin').default(store),
1112
require('./user').default(store),
1213
require('./todo').default(store),
1314
require('./notFound').default(store),

0 commit comments

Comments
 (0)