From 1dbefb2d4b89814fdba44f2ebb3b4a421e82b762 Mon Sep 17 00:00:00 2001 From: Drew Larson Date: Sun, 9 Apr 2017 17:38:56 -0600 Subject: [PATCH] Edit bikes. --- bikeshop_project/assets/js/bikes/actions.js | 3 +- .../js/bikes/components/BikeForm/index.jsx | 40 +++++-------------- .../js/bikes/components/BikeModal/index.jsx | 3 ++ .../js/bikes/components/BikeTable/index.jsx | 13 +++++- bikeshop_project/assets/js/bikes/index.jsx | 4 +- bikeshop_project/assets/js/bikes/sagas.js | 36 ++++++++++++----- .../assets/js/bikes/services/index.js | 10 ++++- 7 files changed, 62 insertions(+), 47 deletions(-) diff --git a/bikeshop_project/assets/js/bikes/actions.js b/bikeshop_project/assets/js/bikes/actions.js index c294f2f..0304798 100644 --- a/bikeshop_project/assets/js/bikes/actions.js +++ b/bikeshop_project/assets/js/bikes/actions.js @@ -9,4 +9,5 @@ export const setBikeSaved = createAction('set bike.saved'); export const setBikeIsSaving = createAction('set bike.isSaving'); export const setBikeSaveFailed = createAction('set bike.isSaving'); export const editBike = createAction('edit bike'); -export const createBike = createAction('create bike'); \ No newline at end of file +export const createBike = createAction('create bike'); +export const saveBike = createAction('save bike'); \ No newline at end of file diff --git a/bikeshop_project/assets/js/bikes/components/BikeForm/index.jsx b/bikeshop_project/assets/js/bikes/components/BikeForm/index.jsx index 8579af7..3c86f23 100644 --- a/bikeshop_project/assets/js/bikes/components/BikeForm/index.jsx +++ b/bikeshop_project/assets/js/bikes/components/BikeForm/index.jsx @@ -12,6 +12,7 @@ import fetch from 'isomorphic-fetch'; import moment from 'moment-timezone'; import Source from '../Source'; import Size from '../Size'; +import { saveBike } from '../../actions'; const styles = { block: { @@ -84,7 +85,10 @@ const validate = (values) => { return errors; }; -const handleSubmit = data => false; +const handleSubmit = (data, dispatch) => { + console.log(data); + dispatch(saveBike(data)); +}; class BikeForm extends React.Component { constructor({ bike, create }) { @@ -100,18 +104,6 @@ class BikeForm extends React.Component { } } - handleChange(event, value) { - this.setState({ bike: { ...this.state.bike, [event.target.name]: value } }); - } - - handleSizeChange(event, index, value) { - this.setState({ bike: { ...this.state.bike, size: value } }); - } - - handleSourceChange(event, index, value) { - this.setState({ bike: { ...this.state.bike, source: value } }); - } - handleCpicCheck() { const id = this.state.bike.id; const serialNumber = this.state.bike.serial_number; @@ -160,24 +152,11 @@ class BikeForm extends React.Component { } render() { - // const timezone = moment.tz.guess(); - // const { - // claimed_at, - // claimed_by, - // cpic_searched_at, - // created_at, - // stolen, - // checked, - // } = this.props.bike || {}; - const create = this.props.create; - // const createdAtFormatted = (moment(created_at).isValid()) ? moment(created_at).tz(timezone).fromNow() : ''; - // const claimedAtFormatted = (moment(claimed_at).isValid()) ? moment(claimed_at).tz(timezone).fromNow() : ''; - // const cpicSearchedAtFormatted = (moment(cpic_searched_at).isValid()) ? moment(cpic_searched_at).tz(timezone) - // .fromNow() : ''; + const { create } = this.props; return (
-
+
- +
@@ -323,6 +302,7 @@ class BikeForm extends React.Component { BikeForm = reduxForm({ form: 'BikeForm', // a unique identifier for this form validate, + onSubmit: handleSubmit, })(BikeForm); const selector = formValueSelector('BikeForm') diff --git a/bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx b/bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx index de682f4..c8ecd16 100644 --- a/bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx +++ b/bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx @@ -6,6 +6,7 @@ import BikeForm from '../BikeForm'; /** * A modal dialog can only be closed by selecting one of the actions. */ + class BikeModal extends React.Component { constructor(props) { super(props); @@ -16,9 +17,11 @@ class BikeModal extends React.Component { } diff --git a/bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx b/bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx index 027f6b0..7e593d9 100644 --- a/bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx +++ b/bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx @@ -15,11 +15,11 @@ class BikeTableComponent extends React.Component { this.state = { bikeModal: { open: false, - bike: undefined, }, }; this.handleOpen = this.handleOpen.bind(this); + this.handleClose = this.handleClose.bind(this); this.renderBikes = this.renderBikes.bind(this); } @@ -38,6 +38,16 @@ class BikeTableComponent extends React.Component { this.props.editBike(bike); } + handleClose() { + this.setState({ + ...this.state, + bikeModal: { + ...this.state.bikeModal, + open: false, + }, + }); +} + renderBikes(bikes) { const bikeRows = bikes.map(bike => ( @@ -88,6 +98,7 @@ class BikeTableComponent extends React.Component {
); diff --git a/bikeshop_project/assets/js/bikes/index.jsx b/bikeshop_project/assets/js/bikes/index.jsx index fda265b..36969d5 100644 --- a/bikeshop_project/assets/js/bikes/index.jsx +++ b/bikeshop_project/assets/js/bikes/index.jsx @@ -9,7 +9,7 @@ import bikesReducer from './reducers'; import createSagaMiddleware from 'redux-saga' import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import BikeTable from './components/BikeTable'; -import watchFetchBikes from './sagas'; +import rootSaga from './sagas'; // Needed for onTouchTap @@ -30,7 +30,7 @@ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore(combinedReducers, composeEnhancers(applyMiddleware(sagaMiddleware))); -sagaMiddleware.run(watchFetchBikes); +sagaMiddleware.run(rootSaga); class App extends React.Component { diff --git a/bikeshop_project/assets/js/bikes/sagas.js b/bikeshop_project/assets/js/bikes/sagas.js index 83f208f..94ae5b5 100644 --- a/bikeshop_project/assets/js/bikes/sagas.js +++ b/bikeshop_project/assets/js/bikes/sagas.js @@ -1,7 +1,7 @@ import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'; import { fetchBikes as fetchBikesAction, setBikes, setBikesIsFetching, setBikesFetched, - setBikesFetchFailed, setBikeSaved, setBikeSaveFailed, setBikeIsSaving } from './actions'; -import { normalize } from 'normalizr'; + setBikesFetchFailed, setBikeSaved, setBikeSaveFailed, setBikeIsSaving, saveBike as saveBikeAction } from './actions'; +import { normalize, denormalize } from 'normalizr'; import * as schema from './schema'; import Api from './services'; @@ -25,13 +25,27 @@ function* watchFetchBikes() { yield takeEvery(fetchBikesAction.toString(), fetchBikes); } -// function *saveBike(action) { -// try { -// yield put({ type: setBikeIsSaving.toString(), payload: true }); -// const bike = yield call(Api.saveBike(action.payload)); -// yield put({ type: setBikes.toString(), payload: normalize([state])}) -// yield put({ type: setBikeSaved, payload: true}) -// } -// } +function* saveBike(action) { + try { + yield put({ type: setBikeIsSaving.toString(), payload: true }); + const bike = yield call(Api.saveBike(action.payload)); + yield put({ type: setBikes.toString(), payload: normalize([state])}) + yield put({ type: setBikeSaved, payload: true}) + } catch (e) { + yield put({ type: setBikeSaveFailed, payload: false }); + throw(e); + } finally { + yield put({ type: setBikeIsSaving.toSource(), payload: false }); + } +} + +function* watchSaveBike() { + yield takeEvery(saveBikeAction.toString(), saveBike) +} -export default watchFetchBikes; +export default function* rootSaga() { + yield [ + watchFetchBikes(), + watchSaveBike(), + ]; +}; diff --git a/bikeshop_project/assets/js/bikes/services/index.js b/bikeshop_project/assets/js/bikes/services/index.js index 2162c0a..de26b54 100644 --- a/bikeshop_project/assets/js/bikes/services/index.js +++ b/bikeshop_project/assets/js/bikes/services/index.js @@ -1,4 +1,8 @@ import fetch from 'isomorphic-fetch'; +import Cookies from 'js-cookie'; + +const csrfToken = Cookies.get('csrftoken') +const headers = new Headers({ 'X-CSRFToken': csrfToken, 'Content-Type': 'application/json' }); const checkStatus = (response) => { if (response.status >= 200 && response.status < 300) { @@ -24,10 +28,12 @@ const Api = { throw error; }); }, - saveBike(id) { - return fetch(`/api/v1/bike/${id}`, { + saveBike(data) { + return fetch(`/api/v1/bikes/${data.id}/`, { credentials: 'same-origin', method: 'PUT', + headers, + body: JSON.stringify(data), }) .then(checkStatus) .then(parseJson)