Browse Source

Load data with redux

feature/bike-tracking
Drew Larson 8 years ago
parent
commit
8f9d1c3663
  1. 7
      bikeshop_project/assets/js/bikes/actions.js
  2. 161
      bikeshop_project/assets/js/bikes/components/BikeForm/index.jsx
  3. 4
      bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx
  4. 73
      bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx
  5. 30
      bikeshop_project/assets/js/bikes/components/Size/index.jsx
  6. 1
      bikeshop_project/assets/js/bikes/components/Source/index.jsx
  7. 25
      bikeshop_project/assets/js/bikes/index.jsx
  8. 27
      bikeshop_project/assets/js/bikes/reducers.js
  9. 27
      bikeshop_project/assets/js/bikes/sagas.js
  10. 4
      bikeshop_project/assets/js/bikes/schema/index.js
  11. 28
      bikeshop_project/assets/js/bikes/services/index.js
  12. 6
      bikeshop_project/package.json
  13. 5
      bikeshop_project/webpack.dev.config.js

7
bikeshop_project/assets/js/bikes/actions.js

@ -0,0 +1,7 @@
import { createAction } from 'redux-actions';
export const fetchBikes = createAction('fetch bikes');
export const setBikes = createAction('set bikes');
export const setBikesIsFetching = createAction('set bikes.isFetching');
export const setBikesFetched = createAction('set bikes.fetched');
export const setBike = createAction('set bike');

161
bikeshop_project/assets/js/bikes/components/BikeForm/index.jsx

@ -1,8 +1,12 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import Checkbox from 'material-ui/Checkbox'; import Checkbox from 'material-ui/Checkbox';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import MenuItem from 'material-ui/MenuItem';
import RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import SelectField from 'material-ui/SelectField';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
import fetch from 'isomorphic-fetch'; import fetch from 'isomorphic-fetch';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
@ -21,12 +25,68 @@ const styles = {
}, },
}; };
class BikeForm extends React.Component { const sources = ['COS_BIKE_DIVERSION_PILOT', 'UOFS', 'DROP_OFF'];
static propTypes = {
bike: PropTypes.object, const friendly = (s) => {
editing: PropTypes.bool, switch (s) {
handleClose: PropTypes.func, case 'COS_BIKE_DIVERSION_PILOT':
return 'City of Saskatoon Bike Diversion Pilot';
case 'UOFS':
return 'University of Saskatchewan';
case 'DROP_OFF':
return 'Drop Off';
default:
return undefined;
}
};
const sourceMenuItems = sources.map(s =>
<MenuItem key={s} value={s} primaryText={friendly(s)} />,
);
const renderTextField = ({ input, meta: { touched, error }, ...custom }) => (
<TextField
errorText={touched && error}
{...input}
{...custom}
/>
);
const renderCheckbox = ({ input, meta, label, ...custom }) => (
<Checkbox
label={label}
checked={!!input.value}
onCheck={input.onChange}
{...custom}
/>
);
const renderSelectField = ({ input, label, meta: { touched, error }, children, ...custom }) => (
<SelectField
errorText={touched && error}
{...input}
onChange={(event, index, value) => input.onChange(value)}
children={children}
{...custom}
/>
);
const validate = (values) => {
console.log(values);
const errors = {};
const requiredFields = ['make', 'colour', 'size', 'serial_number', 'donation_source'];
requiredFields.forEach((field) => {
if (!values[field]) {
errors[field] = 'Required';
} }
});
return errors;
};
const handleSubmit = data => false;
class BikeForm extends React.Component {
constructor({ bike, editing = false }) { constructor({ bike, editing = false }) {
super(); super();
if (editing) { if (editing) {
@ -40,19 +100,19 @@ class BikeForm extends React.Component {
} }
} }
handleChange = (event, value) => { handleChange(event, value) {
this.setState({ bike: { ...this.state.bike, [event.target.name]: value } }); this.setState({ bike: { ...this.state.bike, [event.target.name]: value } });
} }
handleSizeChange = (event, index, value) => { handleSizeChange(event, index, value) {
this.setState({ bike: { ...this.state.bike, size: value } }); this.setState({ bike: { ...this.state.bike, size: value } });
} }
handleSourceChange = (event, index, value) => { handleSourceChange(event, index, value) {
this.setState({ bike: { ...this.state.bike, source: value } }); this.setState({ bike: { ...this.state.bike, source: value } });
} }
handleCpicCheck = () => { handleCpicCheck() {
const id = this.state.bike.id; const id = this.state.bike.id;
const serialNumber = this.state.bike.serial_number; const serialNumber = this.state.bike.serial_number;
const data = JSON.stringify({ serial_number: serialNumber }); const data = JSON.stringify({ serial_number: serialNumber });
@ -107,6 +167,7 @@ class BikeForm extends React.Component {
cpic_searched_at, cpic_searched_at,
created_at, created_at,
stolen, stolen,
checked,
} = this.props.bike; } = this.props.bike;
const editing = this.props.editing; const editing = this.props.editing;
const createdAtFormatted = (moment(created_at).isValid()) ? moment(created_at).tz(timezone).fromNow() : ''; const createdAtFormatted = (moment(created_at).isValid()) ? moment(created_at).tz(timezone).fromNow() : '';
@ -116,61 +177,54 @@ class BikeForm extends React.Component {
return ( return (
<div> <div>
<form onSubmit={handleSubmit}>
<div className="mdl-grid"> <div className="mdl-grid">
<div className="mdl-cell mdl-cell--3-col"> <div className="mdl-cell mdl-cell--3-col">
<TextField <Field
name="make" name="make"
component={renderTextField}
floatingLabelText="Make" floatingLabelText="Make"
hintText="Norco" hintText="Norco"
value={this.state.bike.make || undefined}
onChange={this.handleChange}
fullWidth fullWidth
required
/> />
</div> </div>
<div className="mdl-cell mdl-cell--3-col"> <div className="mdl-cell mdl-cell--3-col">
<TextField <Field
name="price" name="price"
component={renderTextField}
floatingLabelText="Price" floatingLabelText="Price"
hintText="35.60" hintText="35.60"
value={this.state.bike.price || undefined}
onChange={this.handleChange}
fullWidth fullWidth
/> />
</div> </div>
<div className="mdl-cell mdl-cell--3-col"> <div className="mdl-cell mdl-cell--3-col">
<TextField <Field
name="colour" name="colour"
component={renderTextField}
floatingLabelText="Colour" floatingLabelText="Colour"
hintText="orange" hintText="orange"
value={this.state.bike.colour || undefined}
onChange={this.handleChange}
fullWidth fullWidth
required
/> />
</div> </div>
<div className="mdl-cell mdl-cell--3-col"> <div className="mdl-cell mdl-cell--3-col">
<Size <Size />
onChange={this.handleSizeChange}
size={this.state.bike.size}
/>
</div> </div>
</div> </div>
<div className="mdl-grid"> <div className="mdl-grid">
<div className="mdl-cell mdl-cell--6-col"> <div className="mdl-cell mdl-cell--6-col">
<TextField <Field
name="serial_number" name="serial_number"
component={renderTextField}
floatingLabelText="Serial number" floatingLabelText="Serial number"
hintText="ab90cd23" hintText="ab90cd23"
value={this.state.bike.serial_number || undefined}
onChange={this.handleChange}
fullWidth fullWidth
required
/> />
</div> </div>
{editing && {editing &&
<div className="mdl-cell mdl-cell--6-col"> <div className="mdl-cell mdl-cell--6-col">
<TextField <Field
name="created_at"
component={renderTextField}
floatingLabelText="Created at" floatingLabelText="Created at"
value={createdAtFormatted} value={createdAtFormatted}
fullWidth fullWidth
@ -183,7 +237,9 @@ class BikeForm extends React.Component {
{editing && {editing &&
<div className="mdl-grid"> <div className="mdl-grid">
<div className="mdl-cell mdl-cell--6-col"> <div className="mdl-cell mdl-cell--6-col">
<TextField <Field
name="claimed_at"
component={renderTextField}
floatingLabelText="Claimed on" floatingLabelText="Claimed on"
value={claimedAtFormatted} value={claimedAtFormatted}
fullWidth fullWidth
@ -191,9 +247,10 @@ class BikeForm extends React.Component {
/> />
</div> </div>
<div className="mdl-cell mdl-cell--6-col"> <div className="mdl-cell mdl-cell--6-col">
<TextField <Field
name="claimed_by"
component={renderTextField}
floatingLabelText="Claimed by" floatingLabelText="Claimed by"
value={claimed_by || undefined}
fullWidth fullWidth
disabled disabled
readOnly readOnly
@ -208,13 +265,15 @@ class BikeForm extends React.Component {
<TextField floatingLabelText="CPIC searched" value={cpicSearchedAtFormatted} disabled /> <TextField floatingLabelText="CPIC searched" value={cpicSearchedAtFormatted} disabled />
</div> </div>
<div className="mdl-cell mdl-cell--4-col"> <div className="mdl-cell mdl-cell--4-col">
<Checkbox <Field
name="stolen" name="stolen"
component={renderCheckbox}
label="Stolen" label="Stolen"
labelPosition="left" labelPosition="left"
style={styles.checkbox} style={styles.checkbox}
checked={stolen} checked={stolen}
disabled disabled
readOnly
/> />
</div> </div>
<div className="mdl-cell mdl-cell--2-col"> <div className="mdl-cell mdl-cell--2-col">
@ -224,21 +283,25 @@ class BikeForm extends React.Component {
} }
<div className="mdl-grid" style={styles.bottom}> <div className="mdl-grid" style={styles.bottom}>
<div className="mdl-cell mdl-cell--8-col"> <div className="mdl-cell mdl-cell--8-col">
<Source <Field
source={this.state.bike.source} name="donation_source"
onChange={this.handleSourceChange} component={renderSelectField}
/> floatingLabelText="Donation source"
fullWidth
>
{sourceMenuItems}
</Field>
</div> </div>
{editing && {editing &&
<div className="mdl-cell mdl-cell--4-col"> <div className="mdl-cell mdl-cell--4-col">
<div style={styles.block}> <div style={styles.block}>
<Checkbox <Field
checked={this.state.bike.stripped} checked={checked}
name="stripped" name="stripped"
label="Stripped" label="Stripped"
labelPosition="left" labelPosition="left"
style={styles.checkbox} style={styles.checkbox}
onCheck={this.handleChange} component={renderCheckbox}
/> />
</div> </div>
</div> </div>
@ -246,17 +309,31 @@ class BikeForm extends React.Component {
</div> </div>
<div className="mdl-grid"> <div className="mdl-grid">
<div style={{ textAlign: 'right' }} className="mdl-cell mdl-cell--12-col"> <div style={{ textAlign: 'right' }} className="mdl-cell mdl-cell--12-col">
<RaisedButton label="Cancel" onTouchTap={this.props.handleClose} secondary /> <RaisedButton style={{ marginRight: '8px' }} label="Cancel" onTouchTap={this.props.handleClose} secondary />
<RaisedButton label="Save" onTouchTap={this.handleSave} default /> <RaisedButton type="submit" label="Save" default disabled={this.props.pristine || this.props.submitting || this.props.invalid} />
</div> </div>
</div> </div>
</form>
</div> </div>
); );
} }
} }
BikeForm = reduxForm({
form: 'BikeForm', // a unique identifier for this form
validate,
})(BikeForm);
BikeForm = connect(
state => ({
initialValues: state.bike, // pull initial values from account reducer
}),
)(BikeForm);
BikeForm.propTypes = { BikeForm.propTypes = {
editing: PropTypes.bool, editing: PropTypes.bool,
handleClose: PropTypes.func, handleClose: PropTypes.func,
} }
export default BikeForm; export default BikeForm;

4
bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx

@ -58,8 +58,10 @@ class BikeModal extends React.Component {
} }
} }
export default BikeModal.propTypes = { BikeModal.propTypes = {
open: PropTypes.bool, open: PropTypes.bool,
bike: PropTypes.object, bike: PropTypes.object,
editing: PropTypes.bool, editing: PropTypes.bool,
}; };
export default BikeModal;

73
bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx

@ -1,27 +1,30 @@
import { connect } from 'react-redux'
import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table'; import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
import Cookies from 'js-cookie';
import fetch from 'isomorphic-fetch';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import FloatingActionButton from 'material-ui/FloatingActionButton'; import FloatingActionButton from 'material-ui/FloatingActionButton';
import ContentAdd from 'material-ui/svg-icons/content/add'; import ContentAdd from 'material-ui/svg-icons/content/add';
import React from 'react'; import React from 'react';
import { friendlySize } from '../Size'; import { friendlySize } from '../Size';
import BikeModal from '../BikeModal'; import BikeModal from '../BikeModal';
import { fetchBikes, setBike } from '../../actions';
function checkStatus(response) { const renderBikes = (bikes) => {
if (response.status >= 200 && response.status < 300) { console.log(bikes);
return response; const bikeRows = bikes.map(bike => (
} <TableRow selectable={false} key={bike.id}>
const error = new Error(response.statusText); <TableRowColumn>{friendlySize(bike.size)}</TableRowColumn>
error.response = response; <TableRowColumn>{bike.colour}</TableRowColumn>
throw error; <TableRowColumn>{bike.make}</TableRowColumn>
} <TableRowColumn>{bike.serial_number}</TableRowColumn>
<TableRowColumn>{bike.state}</TableRowColumn>
function parseJSON(response) { <TableRowColumn>{bike.claimed_by}</TableRowColumn>
return response.json(); <TableRowColumn><FlatButton label="Edit" primary /></TableRowColumn>
</TableRow>
));
return bikeRows;
} }
export default class BikeTable extends React.Component { class BikeTableComponent extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -38,10 +41,9 @@ export default class BikeTable extends React.Component {
} }
componentDidMount() { componentDidMount() {
this.getBikes(); this.props.fetchBikes();
} }
getBikes = () => {
handleEditBike(bike) { handleEditBike(bike) {
this.setState({ this.setState({
...this.state, ...this.state,
@ -65,18 +67,8 @@ export default class BikeTable extends React.Component {
} }
render() { render() {
const bikeRows = this.state.bikes.map(bike => ( if (this.props.bikes.fetched) {
<TableRow selectable={false} key={bike.id}> const bikeRows = renderBikes(Object.values(this.props.bikes.entities['bikes'] || []));
<TableRowColumn>{friendlySize(bike.size)}</TableRowColumn>
<TableRowColumn>{bike.colour}</TableRowColumn>
<TableRowColumn>{bike.make}</TableRowColumn>
<TableRowColumn>{bike.serial_number}</TableRowColumn>
<TableRowColumn>{bike.state}</TableRowColumn>
<TableRowColumn>{bike.claimed_by}</TableRowColumn>
<TableRowColumn><FlatButton label="Edit" primary onTouchTap={this.handleEditBike.bind(null, bike)} /></TableRowColumn>
</TableRow>
));
return ( return (
<div className="mdl-grid"> <div className="mdl-grid">
<div className="mdl-cell mdl-cell--12-col"> <div className="mdl-cell mdl-cell--12-col">
@ -105,14 +97,27 @@ export default class BikeTable extends React.Component {
} }
</TableBody> </TableBody>
</Table> </Table>
<BikeModal
bike={this.state.bikeModal.bike}
open={this.state.bikeModal.open}
editing={this.state.bikeModal.editing}
getBikes={this.getBikes}
/>
</div> </div>
</div> </div>
); );
} }
return null;
}
} }
const mapStateToProps = state => ({
bikes: state.bikes.bikes,
});
const mapDispatchToProps = dispatch => ({
fetchBikes: () => {
dispatch(fetchBikes());
},
setBike: (id) => {
dispatch(setBike(id));
},
});
const BikeTable = connect(mapStateToProps, mapDispatchToProps)(BikeTableComponent);
export default BikeTable;

30
bikeshop_project/assets/js/bikes/components/Size/index.jsx

@ -1,6 +1,7 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import SelectField from 'material-ui/SelectField'; import { Field } from 'redux-form';
import MenuItem from 'material-ui/MenuItem'; import MenuItem from 'material-ui/MenuItem';
import SelectField from 'material-ui/SelectField';
const sizes = ['C', 'S', 'M', 'L', 'XL']; const sizes = ['C', 'S', 'M', 'L', 'XL'];
@ -23,26 +24,33 @@ export const friendlySize = (size) => {
const styles = { const styles = {
float: 'left', float: 'left',
} };
const renderSelectField = ({ input, label, meta: { touched, error }, children, ...custom }) => (
<SelectField
errorText={touched && error}
{...input}
onChange={(event, index, value) => input.onChange(value)}
children={children}
{...custom}
/>
);
const Size = ({ size, onChange }) => { const Size = () => {
const items = sizes.map(s => const items = sizes.map(s =>
<MenuItem key={s} name="size" value={s} primaryText={friendlySize(s)} />, <MenuItem key={s} name="size" value={s} primaryText={friendlySize(s)} />,
); );
return ( return (
<div style={styles}> <Field
<SelectField
floatingLabelText="Size"
name="size" name="size"
value={size} component={renderSelectField}
onChange={onChange} floatingLabelText="Size"
autoWidth fullWidth
> >
<MenuItem value={null} primaryText="" /> <MenuItem value={null} primaryText="" />
{items} {items}
</SelectField> </Field>
</div>
); );
}; };

1
bikeshop_project/assets/js/bikes/components/Source/index.jsx

@ -25,6 +25,7 @@ const Source = ({ source, onChange }) => {
return ( return (
<div> <div>
<SelectField <SelectField
name="donation_source"
floatingLabelText="Donation source" floatingLabelText="Donation source"
value={source} value={source}
onChange={onChange} onChange={onChange}

25
bikeshop_project/assets/js/bikes/index.jsx

@ -1,14 +1,37 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import injectTapEventPlugin from 'react-tap-event-plugin'; import injectTapEventPlugin from 'react-tap-event-plugin';
import getMuiTheme from 'material-ui/styles/getMuiTheme'; import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import { reducer as formReducer } from 'redux-form';
import bikesReducer from './reducers';
import createSagaMiddleware from 'redux-saga'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import BikeTable from './components/BikeTable'; import BikeTable from './components/BikeTable';
import watchFetchBikes from './sagas';
// Needed for onTouchTap // Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941 // http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin(); injectTapEventPlugin();
const reducers = {
// ... your other reducers here ...
form: formReducer, // <---- Mounted at 'form'
bikes: bikesReducer,
};
const sagaMiddleware = createSagaMiddleware();
const combinedReducers = combineReducers(reducers);
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(combinedReducers, composeEnhancers(applyMiddleware(sagaMiddleware)));
sagaMiddleware.run(watchFetchBikes);
class App extends React.Component { class App extends React.Component {
render() { render() {
@ -20,4 +43,4 @@ class App extends React.Component {
} }
} }
ReactDOM.render(<App />, document.getElementById('root')); ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));

27
bikeshop_project/assets/js/bikes/reducers.js

@ -0,0 +1,27 @@
import { setBike, setBikes, setBikesIsFetching, setBikesFetched } from './actions';
import { handleActions } from 'redux-actions';
export default handleActions({
[setBikes]: (state, action) => ({
...state,
bikes: action.payload,
}),
[setBikesIsFetching]: (state, action) => ({
...state,
bikes: {
...state.bikes,
isFetching: action.payload,
},
}),
[setBikesFetched]: (state, action) => ({
...state,
bikes: {
...state.bikes,
fetched: action.payload
}
}),
[setBike]: (state, action) => ({
...state,
...action.payload,
}),
}, { bikes: [], bike: undefined });

27
bikeshop_project/assets/js/bikes/sagas.js

@ -0,0 +1,27 @@
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects';
import { fetchBikes as fetchBikesAction, setBikes, setBikesIsFetching, setBikesFetched } from './actions';
import { normalize } from 'normalizr';
import * as schema from './schema';
import Api from './services';
// worker Saga: will be fired on USER_FETCH_REQUESTED actions
function* fetchBikes(action) {
try {
yield put({ type: setBikesIsFetching.toString(), payload: true });
const bikes = yield call(Api.fetchBikes);
yield put({ type: setBikes.toString(), payload: normalize(bikes, schema.bikes) });
yield put({ type: setBikesFetched, payload: true });
} catch (e) {
yield put({ type: 'BIKES_FETCH_FAILED', message: e.message });
throw e;
} finally {
yield put({ type: setBikesIsFetching.toString(), payload: false });
}
}
function* watchFetchBikes() {
yield takeEvery(fetchBikesAction.toString(), fetchBikes);
}
export default watchFetchBikes;

4
bikeshop_project/assets/js/bikes/schema/index.js

@ -0,0 +1,4 @@
import { normalize, schema } from 'normalizr';
const bike = new schema.Entity('bikes');
export const bikes = new schema.Array(bike);

28
bikeshop_project/assets/js/bikes/services/index.js

@ -0,0 +1,28 @@
import fetch from 'isomorphic-fetch';
const checkStatus = (response) => {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
};
const parseJson = response => response.json();
const Api = {
fetchBikes() {
return fetch('/api/v1/bikes/', {
credentials: 'same-origin',
})
.then(checkStatus)
.then(parseJson)
.then(data => data)
.catch((error) => {
console.log('request failed', error);
});
},
};
export default Api;

6
bikeshop_project/package.json

@ -18,10 +18,16 @@
"material-ui": "^0.18.1", "material-ui": "^0.18.1",
"moment": "^2.13.0", "moment": "^2.13.0",
"node-sass": "^3.4.2", "node-sass": "^3.4.2",
"normalizr": "^3.2.2",
"react": "^15.4.1", "react": "^15.4.1",
"react-addons-css-transition-group": "^15.4.2", "react-addons-css-transition-group": "^15.4.2",
"react-dom": "^15.4.1", "react-dom": "^15.4.1",
"react-redux": "^5.0.2",
"react-tap-event-plugin": "^2.0.1", "react-tap-event-plugin": "^2.0.1",
"redux": "^3.6.0",
"redux-actions": "^1.2.2",
"redux-form": "^6.5.0",
"redux-saga": "^0.14.3",
"webpack": "1.13.1", "webpack": "1.13.1",
"webpack-bundle-tracker": "0.0.93" "webpack-bundle-tracker": "0.0.93"
}, },

5
bikeshop_project/webpack.dev.config.js

@ -7,8 +7,7 @@ const config = require('./webpack.base.config.js');
// Use webpack dev server // Use webpack dev server
config.entry = { config.entry = {
webpack: [ webpack: [
'webpack-dev-server/client?http://localhost:3000', 'webpack-dev-server/client?http://workstand.docker:3000',
'webpack/hot/only-dev-server',
], ],
signin: './assets/js/index', signin: './assets/js/index',
members: './assets/js/members/index', members: './assets/js/members/index',
@ -16,7 +15,7 @@ config.entry = {
}; };
// override django's STATIC_URL for webpack bundles // override django's STATIC_URL for webpack bundles
config.output.publicPath = 'http://localhost:3000/assets/bundles/'; config.output.publicPath = 'http://workstand.docker:3000/assets/bundles/';
config.devtool = 'eval-source-map'; config.devtool = 'eval-source-map';

Loading…
Cancel
Save