reativo 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -0
- data/app/controllers/reativo/crud_controller.rb +17 -2
- data/lib/generators/reativo/install_generator.rb +55 -0
- data/lib/generators/reativo/js_generator.rb +78 -0
- data/lib/generators/reativo/op_generator.rb +96 -0
- data/lib/generators/reativo/templates/component/Edit.js +43 -0
- data/lib/generators/reativo/templates/component/Form.js +52 -0
- data/lib/generators/reativo/templates/component/Index.js +51 -0
- data/lib/generators/reativo/templates/component/New.js +37 -0
- data/lib/generators/reativo/templates/component/Show.js +32 -0
- data/lib/generators/reativo/templates/operation/create.erb +3 -4
- data/lib/generators/reativo/templates/operation/destroy.erb +2 -2
- data/lib/generators/reativo/templates/operation/index.erb +2 -1
- data/lib/generators/reativo/templates/operation/update.erb +3 -4
- data/lib/generators/reativo/templates/representer/create.erb +1 -1
- data/lib/generators/reativo/templates/representer/index.erb +1 -1
- data/lib/generators/reativo/templates/representer/module.erb +1 -1
- data/lib/generators/reativo/templates/representer/update.erb +1 -1
- data/lib/generators/reativo/templates/support/store.js +24 -0
- data/lib/generators/reativo/templates/support/theme.js +25 -0
- data/lib/generators/reativo/templates/theme/Baseline.js +10 -0
- data/lib/generators/reativo/templates/theme/Drawer.js +50 -0
- data/lib/generators/reativo/templates/theme/MainBar.js +223 -0
- data/lib/generators/reativo/templates/theme/Menu.js +79 -0
- data/lib/generators/reativo/templates/theme/Snackbar.js +9 -0
- data/lib/generators/reativo/templates/theme/layout.erb +59 -0
- data/lib/generators/reativo/templates/theme/layout.rb +6 -0
- data/lib/reativo/version.rb +1 -1
- metadata +33 -4
- data/lib/generators/reativo/USAGE +0 -23
- data/lib/generators/reativo/reativo_generator.rb +0 -63
@@ -0,0 +1,51 @@
|
|
1
|
+
import { hot } from 'react-hot-loader/root'
|
2
|
+
import React from 'react'
|
3
|
+
|
4
|
+
import Button from '@material-ui/core/Button'
|
5
|
+
import MaterialTable from 'material-table'
|
6
|
+
import { wrapper } from "reativo"
|
7
|
+
|
8
|
+
function Index({model, rows}) {
|
9
|
+
return (
|
10
|
+
<>
|
11
|
+
<MaterialTable
|
12
|
+
columns={[
|
13
|
+
{ title: 'ID', field: 'id' },
|
14
|
+
<%- options[:properties].each do |prop| -%>
|
15
|
+
{ title: '<%= prop.humanize %>', field: '<%= prop %>' },
|
16
|
+
<%- end -%>
|
17
|
+
]}
|
18
|
+
data={model}
|
19
|
+
title="<%= model_name_plural %>"
|
20
|
+
actions={[
|
21
|
+
rowData => ({
|
22
|
+
icon: 'create',
|
23
|
+
iconProps: {'data-testid': `edit-${rowData.id}`},
|
24
|
+
tooltip: 'Edit <%= model_name_singular %>',
|
25
|
+
onClick: (event, rowData) => {
|
26
|
+
Turbolinks.visit(`/<%= collection_path %>/${rowData.id}/edit`)
|
27
|
+
},
|
28
|
+
})
|
29
|
+
]}
|
30
|
+
options={{
|
31
|
+
columnsButton: true,
|
32
|
+
exportButton: true,
|
33
|
+
actionsColumnIndex: -1,
|
34
|
+
}}
|
35
|
+
detailPanel={rowData => {
|
36
|
+
return (
|
37
|
+
<pre>
|
38
|
+
{rowData.key}
|
39
|
+
</pre>
|
40
|
+
)
|
41
|
+
}}
|
42
|
+
onRowClick={(event, rowData, togglePanel) => togglePanel()}
|
43
|
+
/>
|
44
|
+
<Button variant="contained" color="secondary" href="/<%= collection_path %>/new">
|
45
|
+
New <%= model_name_singular %>
|
46
|
+
</Button>
|
47
|
+
</>
|
48
|
+
)
|
49
|
+
}
|
50
|
+
|
51
|
+
export default hot(wrapper(Index))
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { hot } from 'react-hot-loader/root'
|
2
|
+
import React from 'react'
|
3
|
+
|
4
|
+
import {
|
5
|
+
Typography,
|
6
|
+
Button,
|
7
|
+
} from '@material-ui/core';
|
8
|
+
import Form from './Form'
|
9
|
+
|
10
|
+
import { Form as FinalForm } from 'react-final-form'
|
11
|
+
import { RailsForm } from 'reativo'
|
12
|
+
import { validate } from './Form'
|
13
|
+
import { wrapper } from "reativo"
|
14
|
+
|
15
|
+
function New() {
|
16
|
+
return (
|
17
|
+
<div style={{ padding: 16, margin: 'auto', maxWidth: 600 }}>
|
18
|
+
<Typography variant="h4" align="center" component="h1" gutterBottom>
|
19
|
+
New <%= model_name_singular %>
|
20
|
+
</Typography>
|
21
|
+
<RailsForm
|
22
|
+
component={FinalForm}
|
23
|
+
action='create'
|
24
|
+
url='/<%= collection_path %>'
|
25
|
+
validate={validate}
|
26
|
+
render={(props) => (
|
27
|
+
<Form {...props} />
|
28
|
+
)}
|
29
|
+
/>
|
30
|
+
<Button variant="contained" color="secondary" href="/<%= collection_path %>">
|
31
|
+
<%= model_name_plural %>
|
32
|
+
</Button>
|
33
|
+
</div>
|
34
|
+
);
|
35
|
+
}
|
36
|
+
|
37
|
+
export default hot(wrapper(New))
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { hot } from 'react-hot-loader/root'
|
2
|
+
import React from 'react'
|
3
|
+
|
4
|
+
import {
|
5
|
+
Typography,
|
6
|
+
Button,
|
7
|
+
} from '@material-ui/core'
|
8
|
+
|
9
|
+
import { wrapper } from "reativo"
|
10
|
+
|
11
|
+
function Show({model}) {
|
12
|
+
const { id } = model
|
13
|
+
|
14
|
+
return (
|
15
|
+
<div style={{ padding: 16, margin: 'auto', maxWidth: 600 }}>
|
16
|
+
<Typography variant="h4" align="center" component="h1" gutterBottom>
|
17
|
+
<%= model_name_singular %>
|
18
|
+
</Typography>
|
19
|
+
<%- options[:properties].each do |prop| -%>
|
20
|
+
<p><%= prop.humanize %>: {model.<%= prop %>}</p>
|
21
|
+
<%- end -%>
|
22
|
+
<Button variant="contained" color="primary" href={`/<%= collection_path %>/${id}/edit`}>
|
23
|
+
Edit
|
24
|
+
</Button>
|
25
|
+
<Button variant="contained" color="secondary" href="/<%= collection_path %>">
|
26
|
+
Back to <%= model_name_plural %>
|
27
|
+
</Button>
|
28
|
+
</div>
|
29
|
+
);
|
30
|
+
}
|
31
|
+
|
32
|
+
export default hot(wrapper(Show))
|
@@ -1,16 +1,15 @@
|
|
1
1
|
module <%= class_name %>::Operation
|
2
2
|
class Create < Trailblazer::Operation
|
3
3
|
class Present < Trailblazer::Operation
|
4
|
+
step ->(options, params) { options["representer.render.class"] = <%= class_name %>::Representer::Create }
|
5
|
+
step ->(options, params) { options["representer.errors.class"] = Reativo::Representer::Errors }
|
4
6
|
step Model(<%= model_name %>, :new)
|
5
7
|
step Contract::Build( constant: <%= class_name %>::Contract::Create )
|
6
8
|
end
|
7
9
|
|
8
|
-
step ->(options, params) { options["representer.render.class"] = <%= class_name %>::Representer::Create }
|
9
|
-
step ->(options, params) { options["representer.errors.class"] = Reativo::Representer::Errors }
|
10
10
|
step Nested( Present )
|
11
|
-
|
12
11
|
step Contract::Build(constant: <%= class_name %>::Contract::Create)
|
13
|
-
step Contract::Validate(key: '<%= model_name.underscore %>')
|
12
|
+
step Contract::Validate(key: '<%= model_name.demodulize.underscore %>')
|
14
13
|
step Contract::Persist()
|
15
14
|
end
|
16
15
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module <%= class_name %>::Operation
|
2
|
-
class
|
2
|
+
class Destroy < Trailblazer::Operation
|
3
3
|
step ->(options, params) { options["representer.render.class"] = <%= class_name %>::Representer::Create }
|
4
4
|
step ->(options, params) { options["representer.errors.class"] = Reativo::Representer::Errors }
|
5
5
|
step Model( <%= model_name %>, :find )
|
6
6
|
step :destroy!
|
7
7
|
|
8
8
|
def destroy!(ctx, params:, current_user:, **)
|
9
|
-
|
9
|
+
ctx[:model].destroy
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -15,7 +15,8 @@ module <%= class_name %>::Operation
|
|
15
15
|
step :cache_key!
|
16
16
|
|
17
17
|
def scope!(ctx, params:, current_user:, **)
|
18
|
-
|
18
|
+
# Change the scope, so avoid data leaking
|
19
|
+
ctx[:scope] = <%= model_name.singularize %>.where('created_at > ?', DateTime.current)
|
19
20
|
end
|
20
21
|
|
21
22
|
def model!(ctx, params:, current_user:, **)
|
@@ -1,16 +1,15 @@
|
|
1
1
|
module <%= class_name %>::Operation
|
2
2
|
class Update < Trailblazer::Operation
|
3
3
|
class Present < Trailblazer::Operation
|
4
|
+
step ->(options, params) { options["representer.render.class"] = <%= class_name %>::Representer::Update }
|
5
|
+
step ->(options, params) { options["representer.errors.class"] = Reativo::Representer::Errors }
|
4
6
|
step Model(<%= model_name %>, :find)
|
5
7
|
step Contract::Build( constant: <%= class_name %>::Contract::Update )
|
6
8
|
end
|
7
9
|
|
8
|
-
step ->(options, params) { options["representer.render.class"] = <%= class_name %>::Representer::Update }
|
9
|
-
step ->(options, params) { options["representer.errors.class"] = Reativo::Representer::Errors }
|
10
10
|
step Nested( Present )
|
11
|
-
|
12
11
|
step Contract::Build(constant: <%= class_name %>::Contract::Update)
|
13
|
-
step Contract::Validate(key: '<%= model_name.underscore %>')
|
12
|
+
step Contract::Validate(key: '<%= model_name.demodulize.underscore %>')
|
14
13
|
step Contract::Persist()
|
15
14
|
end
|
16
15
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { createStore } from 'redux'
|
2
|
+
import { combineReducers } from 'redux'
|
3
|
+
|
4
|
+
const DRAWER_OPEN = 'DRAWER_OPEN'
|
5
|
+
const DRAWER_CLOSE = 'DRAWER_CLOSE'
|
6
|
+
|
7
|
+
function drawer(state = { open: true }, action) {
|
8
|
+
switch (action.type) {
|
9
|
+
case DRAWER_OPEN:
|
10
|
+
return {...action.props, open: true}
|
11
|
+
case DRAWER_CLOSE:
|
12
|
+
return {...action.props, open: false}
|
13
|
+
default:
|
14
|
+
return state
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
const rootReducer = combineReducers({
|
19
|
+
drawer,
|
20
|
+
})
|
21
|
+
|
22
|
+
const store = createStore(rootReducer)
|
23
|
+
|
24
|
+
export default store
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { createMuiTheme } from '@material-ui/core/styles';
|
2
|
+
|
3
|
+
export const theme = createMuiTheme({
|
4
|
+
palette: {
|
5
|
+
},
|
6
|
+
typography: {
|
7
|
+
useNextVariants: true,
|
8
|
+
},
|
9
|
+
overrides: {
|
10
|
+
MuiAppBar: {
|
11
|
+
root: {
|
12
|
+
boxShadow: 'unset',
|
13
|
+
backgroundColor: "#aaa"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
MuiSvgIcon: { // Name of the component ⚛️ / style sheet
|
17
|
+
root: { // Name of the rule
|
18
|
+
color: '#000', // Some CSS
|
19
|
+
opacity: 0.54,
|
20
|
+
},
|
21
|
+
},
|
22
|
+
},
|
23
|
+
});
|
24
|
+
|
25
|
+
export default theme
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React from "react"
|
2
|
+
import PropTypes from "prop-types"
|
3
|
+
import Button from '@material-ui/core/Button'
|
4
|
+
import { hot } from 'react-hot-loader/root'
|
5
|
+
import { withStyles } from '@material-ui/core/styles';
|
6
|
+
import { wrapper } from "reativo"
|
7
|
+
import Menu from "./Menu"
|
8
|
+
|
9
|
+
const styles = theme => ({
|
10
|
+
root: {
|
11
|
+
paddingBottom: 10
|
12
|
+
},
|
13
|
+
})
|
14
|
+
|
15
|
+
class Drawer extends React.Component {
|
16
|
+
render () {
|
17
|
+
const { classes } = this.props;
|
18
|
+
return (
|
19
|
+
<div className={classes.root}>
|
20
|
+
<Menu />
|
21
|
+
</div>
|
22
|
+
);
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
Drawer.propTypes = {
|
27
|
+
classes: PropTypes.object.isRequired,
|
28
|
+
};
|
29
|
+
|
30
|
+
|
31
|
+
function mapStateToProps (state) {
|
32
|
+
return {
|
33
|
+
drawer: state.drawer
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
function mapDispatchToProps (dispatch) {
|
38
|
+
return {
|
39
|
+
toggle: () => {
|
40
|
+
dispatch({type: "DRAWER_TOGGLE"})
|
41
|
+
},
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
export default hot(
|
46
|
+
withStyles(styles)(
|
47
|
+
wrapper(Drawer, mapStateToProps, mapDispatchToProps)
|
48
|
+
)
|
49
|
+
)
|
50
|
+
|
@@ -0,0 +1,223 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import AppBar from '@material-ui/core/AppBar';
|
4
|
+
import Toolbar from '@material-ui/core/Toolbar';
|
5
|
+
import IconButton from '@material-ui/core/IconButton';
|
6
|
+
import Typography from '@material-ui/core/Typography';
|
7
|
+
import InputBase from '@material-ui/core/InputBase';
|
8
|
+
import MenuItem from '@material-ui/core/MenuItem';
|
9
|
+
import Menu from '@material-ui/core/Menu';
|
10
|
+
import { fade } from '@material-ui/core/styles/colorManipulator';
|
11
|
+
import { withStyles } from '@material-ui/core/styles';
|
12
|
+
import MenuIcon from '@material-ui/icons/Menu';
|
13
|
+
import SearchIcon from '@material-ui/icons/Search';
|
14
|
+
import AccountCircle from '@material-ui/icons/AccountCircle';
|
15
|
+
import MailIcon from '@material-ui/icons/Mail';
|
16
|
+
import NotificationsIcon from '@material-ui/icons/Notifications';
|
17
|
+
import MoreIcon from '@material-ui/icons/MoreVert';
|
18
|
+
import { wrapper } from "reativo"
|
19
|
+
import { hot } from 'react-hot-loader/root'
|
20
|
+
|
21
|
+
const styles = theme => ({
|
22
|
+
root: {
|
23
|
+
width: '100%',
|
24
|
+
},
|
25
|
+
grow: {
|
26
|
+
flexGrow: 1,
|
27
|
+
},
|
28
|
+
menuButton: {
|
29
|
+
marginLeft: -12,
|
30
|
+
marginRight: 20,
|
31
|
+
},
|
32
|
+
title: {
|
33
|
+
display: 'none',
|
34
|
+
[theme.breakpoints.up('sm')]: {
|
35
|
+
display: 'block',
|
36
|
+
},
|
37
|
+
},
|
38
|
+
search: {
|
39
|
+
position: 'relative',
|
40
|
+
borderRadius: theme.shape.borderRadius,
|
41
|
+
backgroundColor: fade(theme.palette.common.white, 0.15),
|
42
|
+
'&:hover': {
|
43
|
+
backgroundColor: fade(theme.palette.common.white, 0.25),
|
44
|
+
},
|
45
|
+
marginRight: theme.spacing.unit * 2,
|
46
|
+
marginLeft: 0,
|
47
|
+
width: '100%',
|
48
|
+
[theme.breakpoints.up('sm')]: {
|
49
|
+
marginLeft: theme.spacing.unit * 3,
|
50
|
+
width: 'auto',
|
51
|
+
},
|
52
|
+
},
|
53
|
+
searchIcon: {
|
54
|
+
width: theme.spacing.unit * 9,
|
55
|
+
height: '100%',
|
56
|
+
position: 'absolute',
|
57
|
+
pointerEvents: 'none',
|
58
|
+
display: 'flex',
|
59
|
+
alignItems: 'center',
|
60
|
+
justifyContent: 'center',
|
61
|
+
},
|
62
|
+
inputRoot: {
|
63
|
+
color: 'inherit',
|
64
|
+
width: '100%',
|
65
|
+
},
|
66
|
+
inputInput: {
|
67
|
+
paddingTop: theme.spacing.unit,
|
68
|
+
paddingRight: theme.spacing.unit,
|
69
|
+
paddingBottom: theme.spacing.unit,
|
70
|
+
paddingLeft: theme.spacing.unit * 10,
|
71
|
+
transition: theme.transitions.create('width'),
|
72
|
+
width: '100%',
|
73
|
+
[theme.breakpoints.up('md')]: {
|
74
|
+
width: 200,
|
75
|
+
},
|
76
|
+
},
|
77
|
+
sectionDesktop: {
|
78
|
+
display: 'none',
|
79
|
+
[theme.breakpoints.up('md')]: {
|
80
|
+
display: 'flex',
|
81
|
+
},
|
82
|
+
},
|
83
|
+
sectionMobile: {
|
84
|
+
display: 'flex',
|
85
|
+
[theme.breakpoints.up('md')]: {
|
86
|
+
display: 'none',
|
87
|
+
},
|
88
|
+
},
|
89
|
+
});
|
90
|
+
|
91
|
+
class PrimarySearchAppBar extends React.Component {
|
92
|
+
state = {
|
93
|
+
anchorEl: null,
|
94
|
+
mobileMoreAnchorEl: null,
|
95
|
+
};
|
96
|
+
|
97
|
+
handleProfileMenuOpen = event => {
|
98
|
+
this.setState({ anchorEl: event.currentTarget });
|
99
|
+
};
|
100
|
+
|
101
|
+
handleMenuClose = () => {
|
102
|
+
this.setState({ anchorEl: null });
|
103
|
+
this.handleMobileMenuClose();
|
104
|
+
};
|
105
|
+
|
106
|
+
handleMobileMenuOpen = event => {
|
107
|
+
this.setState({ mobileMoreAnchorEl: event.currentTarget });
|
108
|
+
};
|
109
|
+
|
110
|
+
handleMobileMenuClose = () => {
|
111
|
+
this.setState({ mobileMoreAnchorEl: null });
|
112
|
+
};
|
113
|
+
|
114
|
+
render() {
|
115
|
+
const { anchorEl, mobileMoreAnchorEl } = this.state;
|
116
|
+
const { classes } = this.props;
|
117
|
+
const isMenuOpen = Boolean(anchorEl);
|
118
|
+
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
|
119
|
+
|
120
|
+
const renderMenu = (
|
121
|
+
<Menu
|
122
|
+
anchorEl={anchorEl}
|
123
|
+
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
124
|
+
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
125
|
+
open={isMenuOpen}
|
126
|
+
onClose={this.handleMenuClose}
|
127
|
+
>
|
128
|
+
<MenuItem onClick={this.handleMenuClose}>Profile</MenuItem>
|
129
|
+
<MenuItem onClick={this.handleMenuClose}>My account</MenuItem>
|
130
|
+
</Menu>
|
131
|
+
);
|
132
|
+
|
133
|
+
const renderMobileMenu = (
|
134
|
+
<Menu
|
135
|
+
anchorEl={mobileMoreAnchorEl}
|
136
|
+
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
137
|
+
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
138
|
+
open={isMobileMenuOpen}
|
139
|
+
onClose={this.handleMenuClose}
|
140
|
+
>
|
141
|
+
<MenuItem onClick={this.handleMobileMenuClose}>
|
142
|
+
<IconButton color="inherit">
|
143
|
+
<MailIcon />
|
144
|
+
</IconButton>
|
145
|
+
<p>Messages</p>
|
146
|
+
</MenuItem>
|
147
|
+
<MenuItem onClick={this.handleMobileMenuClose}>
|
148
|
+
<IconButton color="inherit">
|
149
|
+
<NotificationsIcon />
|
150
|
+
</IconButton>
|
151
|
+
<p>Notifications</p>
|
152
|
+
</MenuItem>
|
153
|
+
<MenuItem onClick={this.handleProfileMenuOpen}>
|
154
|
+
<IconButton color="inherit">
|
155
|
+
<AccountCircle />
|
156
|
+
</IconButton>
|
157
|
+
<p>Profile</p>
|
158
|
+
</MenuItem>
|
159
|
+
</Menu>
|
160
|
+
);
|
161
|
+
|
162
|
+
return (
|
163
|
+
<div className={classes.root}>
|
164
|
+
<AppBar position="fixed">
|
165
|
+
<Toolbar>
|
166
|
+
<IconButton className={classes.menuButton} color="inherit" aria-label="Open drawer">
|
167
|
+
<MenuIcon />
|
168
|
+
</IconButton>
|
169
|
+
<Typography className={classes.title} variant="h6" color="inherit" noWrap>
|
170
|
+
Reativo
|
171
|
+
</Typography>
|
172
|
+
<div className={classes.search}>
|
173
|
+
<div className={classes.searchIcon}>
|
174
|
+
<SearchIcon />
|
175
|
+
</div>
|
176
|
+
<InputBase
|
177
|
+
placeholder="Search…"
|
178
|
+
classes={{
|
179
|
+
root: classes.inputRoot,
|
180
|
+
input: classes.inputInput,
|
181
|
+
}}
|
182
|
+
/>
|
183
|
+
</div>
|
184
|
+
<div className={classes.grow} />
|
185
|
+
<div className={classes.sectionDesktop}>
|
186
|
+
<IconButton color="inherit">
|
187
|
+
<MailIcon />
|
188
|
+
</IconButton>
|
189
|
+
<IconButton color="inherit">
|
190
|
+
<NotificationsIcon />
|
191
|
+
</IconButton>
|
192
|
+
<IconButton
|
193
|
+
aria-owns={isMenuOpen ? 'material-appbar' : undefined}
|
194
|
+
aria-haspopup="true"
|
195
|
+
onClick={this.handleProfileMenuOpen}
|
196
|
+
color="inherit"
|
197
|
+
>
|
198
|
+
<AccountCircle />
|
199
|
+
</IconButton>
|
200
|
+
</div>
|
201
|
+
<div className={classes.sectionMobile}>
|
202
|
+
<IconButton aria-haspopup="true" onClick={this.handleMobileMenuOpen} color="inherit">
|
203
|
+
<MoreIcon />
|
204
|
+
</IconButton>
|
205
|
+
</div>
|
206
|
+
</Toolbar>
|
207
|
+
</AppBar>
|
208
|
+
{renderMenu}
|
209
|
+
{renderMobileMenu}
|
210
|
+
</div>
|
211
|
+
);
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
PrimarySearchAppBar.propTypes = {
|
216
|
+
classes: PropTypes.object.isRequired,
|
217
|
+
};
|
218
|
+
|
219
|
+
export default hot(
|
220
|
+
withStyles(styles)(
|
221
|
+
wrapper(PrimarySearchAppBar)
|
222
|
+
)
|
223
|
+
);
|