Skip to content

Commit 9405e17

Browse files
feat(dashboard): dashboard layout with sidebar menu
1 parent 841ee57 commit 9405e17

File tree

10 files changed

+402
-48
lines changed

10 files changed

+402
-48
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
},
5555
"dependencies": {
5656
"@material-ui/core": "^1.0.0",
57+
"@material-ui/icons": "^1.1.0",
5758
"axios": "^0.18.0",
5859
"jsona": "^1.1.10",
5960
"prop-types": "^15.6.1",
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @file DashboardLayout.js
3+
* Exports a React component that renders EditVR's dashboard layout.
4+
*/
5+
6+
import React from 'react';
7+
import PropTypes from 'prop-types';
8+
import { Link } from 'react-router-dom';
9+
import {
10+
withStyles,
11+
AppBar,
12+
Drawer,
13+
Toolbar,
14+
List,
15+
ListItem,
16+
ListItemIcon,
17+
ListItemText
18+
} from '@material-ui/core';
19+
import { ExitToApp, PanoramaWideAngle } from '@material-ui/icons';
20+
import LoadingBar from 'react-redux-loading-bar';
21+
22+
import { ThemeProvider } from '../../hoc';
23+
import DashboardLayoutStyles from './DashboardLayout.style';
24+
import EditVRLogo from '../../assets/editvr-logo.svg';
25+
26+
const DashboardLayout = ({ children, classes }) => (
27+
<div id="layout__wrapper" className={classes.wrapper}>
28+
<LoadingBar style={{ backgroundColor: '#FFFFFF' }} />
29+
<AppBar className={classes.appBar}>
30+
<Toolbar>
31+
<img src={EditVRLogo} alt="EditVR logo" className={classes.logo} />
32+
</Toolbar>
33+
</AppBar>
34+
<Drawer variant="permanent" classes={{ paper: classes.drawerPaper }}>
35+
<List>
36+
<ListItem button component={Link} to="/dashboard">
37+
<ListItemIcon>
38+
<PanoramaWideAngle />
39+
</ListItemIcon>
40+
<ListItemText>Experiences</ListItemText>
41+
</ListItem>
42+
<ListItem button component={Link} to="/logout">
43+
<ListItemIcon>
44+
<ExitToApp />
45+
</ListItemIcon>
46+
<ListItemText>Logout</ListItemText>
47+
</ListItem>
48+
</List>
49+
</Drawer>
50+
<main className={classes.content}>{children}</main>
51+
</div>
52+
);
53+
54+
DashboardLayout.propTypes = {
55+
children: PropTypes.node,
56+
classes: PropTypes.shape({
57+
wrapper: PropTypes.string.isRequired
58+
}).isRequired
59+
};
60+
61+
DashboardLayout.defaultProps = {
62+
children: null
63+
};
64+
65+
export default ThemeProvider(
66+
withStyles(DashboardLayoutStyles)(DashboardLayout)
67+
);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @file DashboardLayout.style.js
3+
* Exports styling that's shared across many layouts.
4+
*/
5+
6+
export default theme => ({
7+
wrapper: {
8+
backgroundColor: theme.palette.background.default,
9+
paddingTop: theme.spacing.unit * 8,
10+
flexGrow: 1,
11+
zIndex: 1,
12+
overflow: 'hidden',
13+
position: 'relative',
14+
display: 'flex',
15+
height: '100%'
16+
},
17+
appBar: {
18+
position: 'absolute',
19+
zIndex: theme.zIndex.drawer + 1
20+
},
21+
drawerPaper: {
22+
position: 'relative',
23+
width: 200,
24+
textAlign: 'left'
25+
},
26+
content: {
27+
flexGrow: 1,
28+
backgroundColor: theme.palette.background.default,
29+
padding: theme.spacing.unit * 3,
30+
minWidth: 0,
31+
maxWidth: 600
32+
},
33+
logo: {
34+
height: theme.spacing.unit * 3,
35+
marginRight: theme.spacing.unit * 5
36+
}
37+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @file DashboardLayout.test.js
3+
* Contains tests for DashboardLayout.js.
4+
*/
5+
6+
import React from 'react';
7+
import { MemoryRouter as Router } from 'react-router-dom';
8+
import renderer from 'react-test-renderer';
9+
import configureStore from 'redux-mock-store';
10+
import { Provider } from 'react-redux';
11+
12+
import DashboardLayout from './DashboardLayout';
13+
14+
describe('<DashboardLayout />', () => {
15+
it('Matches its snapshot', () => {
16+
const store = configureStore()({
17+
loadingBar: {
18+
default: 0
19+
}
20+
});
21+
22+
expect(
23+
renderer
24+
.create(
25+
<Provider store={store}>
26+
<Router>
27+
<DashboardLayout>
28+
<div>child</div>
29+
</DashboardLayout>
30+
</Router>
31+
</Provider>
32+
)
33+
.toJSON()
34+
).toMatchSnapshot();
35+
});
36+
});
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<DashboardLayout /> Matches its snapshot 1`] = `
4+
<div
5+
className="DashboardLayout-wrapper-1"
6+
id="layout__wrapper"
7+
>
8+
<div />
9+
<header
10+
className="MuiPaper-root-14 MuiPaper-elevation4-20 MuiAppBar-root-6 MuiAppBar-positionFixed-7 MuiAppBar-colorPrimary-12 mui-fixed DashboardLayout-appBar-2"
11+
>
12+
<div
13+
className="MuiToolbar-root-41 MuiToolbar-gutters-42"
14+
>
15+
<img
16+
alt="EditVR logo"
17+
className="DashboardLayout-logo-5"
18+
src="editvr-logo.svg"
19+
/>
20+
</div>
21+
</header>
22+
<div
23+
className="MuiDrawer-docked-43"
24+
>
25+
<div
26+
className="MuiPaper-root-14 MuiPaper-elevation0-16 MuiDrawer-paper-44 DashboardLayout-drawerPaper-3 MuiDrawer-paperAnchorLeft-45 MuiDrawer-paperAnchorDockedLeft-49"
27+
>
28+
<ul
29+
className="MuiList-root-54 MuiList-padding-55"
30+
>
31+
<a
32+
className="MuiButtonBase-root-68 MuiListItem-root-58 MuiListItem-default-61 MuiListItem-gutters-65 MuiListItem-button-66"
33+
href="/dashboard"
34+
onBlur={[Function]}
35+
onClick={[Function]}
36+
onFocus={[Function]}
37+
onKeyDown={[Function]}
38+
onKeyUp={[Function]}
39+
onMouseDown={[Function]}
40+
onMouseLeave={[Function]}
41+
onMouseUp={[Function]}
42+
onTouchEnd={[Function]}
43+
onTouchMove={[Function]}
44+
onTouchStart={[Function]}
45+
role="button"
46+
tabIndex="0"
47+
>
48+
<svg
49+
aria-hidden="true"
50+
className="MuiSvgIcon-root-72 MuiListItemIcon-root-71"
51+
color={undefined}
52+
focusable="false"
53+
viewBox="0 0 24 24"
54+
>
55+
<g>
56+
<path
57+
d="M12 6c2.45 0 4.71.2 7.29.64.47 1.78.71 3.58.71 5.36 0 1.78-.24 3.58-.71 5.36-2.58.44-4.84.64-7.29.64s-4.71-.2-7.29-.64C4.24 15.58 4 13.78 4 12c0-1.78.24-3.58.71-5.36C7.29 6.2 9.55 6 12 6m0-2c-2.73 0-5.22.24-7.95.72l-.93.16-.25.9C2.29 7.85 2 9.93 2 12s.29 4.15.87 6.22l.25.89.93.16c2.73.49 5.22.73 7.95.73s5.22-.24 7.95-.72l.93-.16.25-.89c.58-2.08.87-4.16.87-6.23s-.29-4.15-.87-6.22l-.25-.89-.93-.16C17.22 4.24 14.73 4 12 4z"
58+
/>
59+
</g>
60+
</svg>
61+
<div
62+
className="MuiListItemText-root-78"
63+
>
64+
<h3
65+
className="MuiTypography-root-84 MuiTypography-subheading-91 MuiListItemText-primary-81"
66+
>
67+
Experiences
68+
</h3>
69+
</div>
70+
<span
71+
className="MuiTouchRipple-root-108"
72+
/>
73+
</a>
74+
<a
75+
className="MuiButtonBase-root-68 MuiListItem-root-58 MuiListItem-default-61 MuiListItem-gutters-65 MuiListItem-button-66"
76+
href="/logout"
77+
onBlur={[Function]}
78+
onClick={[Function]}
79+
onFocus={[Function]}
80+
onKeyDown={[Function]}
81+
onKeyUp={[Function]}
82+
onMouseDown={[Function]}
83+
onMouseLeave={[Function]}
84+
onMouseUp={[Function]}
85+
onTouchEnd={[Function]}
86+
onTouchMove={[Function]}
87+
onTouchStart={[Function]}
88+
role="button"
89+
tabIndex="0"
90+
>
91+
<svg
92+
aria-hidden="true"
93+
className="MuiSvgIcon-root-72 MuiListItemIcon-root-71"
94+
color={undefined}
95+
focusable="false"
96+
viewBox="0 0 24 24"
97+
>
98+
<g>
99+
<path
100+
d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
101+
/>
102+
</g>
103+
</svg>
104+
<div
105+
className="MuiListItemText-root-78"
106+
>
107+
<h3
108+
className="MuiTypography-root-84 MuiTypography-subheading-91 MuiListItemText-primary-81"
109+
>
110+
Logout
111+
</h3>
112+
</div>
113+
<span
114+
className="MuiTouchRipple-root-108"
115+
/>
116+
</a>
117+
</ul>
118+
</div>
119+
</div>
120+
<main
121+
className="DashboardLayout-content-4"
122+
>
123+
<div>
124+
child
125+
</div>
126+
</main>
127+
</div>
128+
`;

src/layouts/ThinLayout/ThinLayout.style.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/**
2-
* @file Layout.style.js
2+
* @file ThinLayout.style.js
33
* Exports styling that's shared across many layouts.
44
*/
55

66
export default theme => ({
77
wrapper: {
8-
background: theme.palette.grays['500'],
8+
background: theme.palette.background.default,
99
width: '100%',
1010
height: '100%',
1111
position: 'absolute',

src/layouts/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
*/
55

66
import ThinLayout from './ThinLayout/ThinLayout';
7+
import DashboardLayout from './DashboardLayout/DashboardLayout';
78
import Header from './Header/Header';
89
import Footer from './Footer/Footer';
910

10-
export { ThinLayout, Header, Footer };
11+
export { ThinLayout, DashboardLayout, Header, Footer };

src/pages/Dashboard/Dashboard.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
withStyles
1616
} from '@material-ui/core';
1717

18-
import { ThinLayout } from '../../layouts';
18+
import { DashboardLayout } from '../../layouts';
1919
import { Message } from '../../components';
2020
import { EXPERIENCES_FETCH_FOR_USER } from '../../constants';
2121
import DashboardStyles from './Dashboard.style';
@@ -74,7 +74,7 @@ class Dashboard extends Component {
7474
} = this.props;
7575

7676
return (
77-
<ThinLayout>
77+
<DashboardLayout>
7878
<Typography variant="headline">Experiences</Typography>
7979
<Typography component="p">
8080
Please select an experience below. Click the Open button to open the
@@ -110,7 +110,7 @@ class Dashboard extends Component {
110110
</Card>
111111
)
112112
)}
113-
</ThinLayout>
113+
</DashboardLayout>
114114
);
115115
}
116116
}

0 commit comments

Comments
 (0)