diff options
| author | Thomas Haddad | 2017-02-16 17:14:45 +0100 |
|---|---|---|
| committer | Thomas Haddad | 2017-02-16 17:15:49 +0100 |
| commit | bb693070b8f06bc9cb4845d27d58dfed9ce3411e (patch) | |
| tree | 0c0e2f155e98daa609ca04ab09fd4fd63bae7e21 | |
| parent | 051b25a06ae9cb5fd19791688eac6ba40ab56396 (diff) | |
| download | chouette-core-bb693070b8f06bc9cb4845d27d58dfed9ce3411e.tar.bz2 | |
Refs #2522: Add vehicleJourney via modal, and put it first (not select2 yet for mission_id)
Signed-off-by: Thomas Shawarma Haddad <thomas.haddad@af83.com>
11 files changed, 300 insertions, 0 deletions
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js index 817dbb81c..56ed1ef07 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js @@ -33,10 +33,44 @@ const actions = { return callback } }, + openCreateModal : () => ({ + type : 'CREATE_VEHICLEJOURNEY_MODAL' + }), + addVehicleJourney : (data) => ({ + type: 'ADD_VEHICLEJOURNEY', + data, + }), openConfirmModal : (callback) => ({ type : 'OPEN_CONFIRM_MODAL', callback }), + closeModal : () => ({ + type : 'CLOSE_MODAL' + }), + resetValidation: (target) => { + $(target).parent().removeClass('has-error').children('.help-block').remove() + }, + validateFields : (fields) => { + const test = [] + + Object.keys(fields).map(function(key) { + test.push(fields[key].validity.valid) + }) + if(test.indexOf(false) >= 0) { + // Form is invalid + test.map(function(item, i) { + if(item == false) { + const k = Object.keys(fields)[i] + $(fields[k]).parent().addClass('has-error').children('.help-block').remove() + $(fields[k]).parent().append("<span class='small help-block'>" + fields[k].validationMessage + "</span>") + } + }) + return false + } else { + // Form is valid + return true + } + }, toggleArrivals : () => ({ type: 'TOGGLE_ARRIVALS', }), diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/App.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/App.js index 7368d4de3..99c88930a 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/App.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/App.js @@ -4,12 +4,14 @@ var Navigate = require('../containers/Navigate') var FiltersList = require('../containers/FiltersList') var SaveVehicleJourneys = require('../containers/SaveVehicleJourneys') var ConfirmModal = require('../containers/ConfirmModal') +var AddVehicleJourney = require('../containers/AddVehicleJourney') const App = () => ( <div> <div className='clearfix' style={{ marginBottom: 10 }}> <FiltersList /> <Navigate /> + <AddVehicleJourney /> </div> <VehicleJourneysList /> <SaveVehicleJourneys /> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/CreateModal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/CreateModal.js new file mode 100644 index 000000000..34b1a3afc --- /dev/null +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/CreateModal.js @@ -0,0 +1,109 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes +var actions = require('../actions') + +class CreateModal extends Component { + constructor(props) { + super(props) + } + + handleSubmit() { + if(actions.validateFields(this.refs) == true) { + this.props.onAddVehicleJourney(this.refs) + $('#NewVehicleJourneyModal').modal('hide') + } + } + + render() { + if(this.props.status.isFetching == true) { + return false + } + if(this.props.status.fetchSuccess == true) { + return ( + <div className='pull-right'> + <button + type='button' + className='btn btn-primary btn-sm' + data-toggle='modal' + data-target='#NewVehicleJourneyModal' + onClick={this.props.onOpenCreateModal} + > + <span className='fa fa-plus'></span> Ajouter une mission + </button> + + <div className={ 'modal fade ' + ((this.props.modal.type == 'create') ? 'in' : '') } id='NewVehicleJourneyModal'> + <div className='modal-dialog'> + <div className='modal-content'> + <div className='modal-header clearfix'> + <h4>Ajouter une mission</h4> + </div> + + {(this.props.modal.type == 'create') && ( + <form> + <div className='modal-body'> + <div className='form-group'> + <label className='control-label is-required'>Nom de la course</label> + <input + type='text' + ref='comment' + className='form-control' + onKeyDown={(e) => actions.resetValidation(e.currentTarget)} + required + /> + </div> + <div className='row'> + <div className='col-lg-6 col-md-6 col-sm-6 col-xs-6'> + <div className='form-group'> + <label className='control-label is-required'>ID de la mission</label> + <input + type='text' + ref='journey_pattern_id' + className='form-control' + onKeyDown={(e) => actions.resetValidation(e.currentTarget)} + required + /> + </div> + </div> + </div> + </div> + <div className='modal-footer'> + <button + className='btn btn-default' + data-dismiss='modal' + type='button' + onClick={this.props.onModalClose} + > + Annuler + </button> + <button + className='btn btn-danger' + type='button' + onClick={this.handleSubmit.bind(this)} + > + Valider + </button> + </div> + </form> + )} + </div> + </div> + </div> + </div> + ) + } else { + return false + } + } +} + +CreateModal.propTypes = { + index: PropTypes.number, + modal: PropTypes.object.isRequired, + status: PropTypes.object.isRequired, + onOpenCreateModal: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired, + onAddVehicleJourney: PropTypes.func.isRequired +} + +module.exports = CreateModal diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/AddVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/AddVehicleJourney.js new file mode 100644 index 000000000..a0ff923bf --- /dev/null +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/AddVehicleJourney.js @@ -0,0 +1,29 @@ +var actions = require('../actions') +var connect = require('react-redux').connect +var CreateModal = require('../components/CreateModal') + +const mapStateToProps = (state) => { + return { + modal: state.modal, + vehicleJourneys: state.vehicleJourneys, + status: state.status + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onModalClose: () =>{ + dispatch(actions.closeModal()) + }, + onAddVehicleJourney: (data) =>{ + dispatch(actions.addVehicleJourney(data)) + }, + onOpenCreateModal: () =>{ + dispatch(actions.openCreateModal()) + } + } +} + +const AddVehicleJourney = connect(mapStateToProps, mapDispatchToProps)(CreateModal) + +module.exports = AddVehicleJourney diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Modal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Modal.js new file mode 100644 index 000000000..13190b041 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Modal.js @@ -0,0 +1,23 @@ +var connect = require('react-redux').connect +var EditModal = require('../components/EditModal') +var CreateModal = require('../components/CreateModal') +var actions = require('../actions') + +const mapStateToProps = (state) => { + return { + modal: state.modal, + journeyPattern: state.journeyPattern + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onModalClose: () =>{ + dispatch(actions.closeModal()) + } + } +} + +const ModalContainer = connect(mapStateToProps, mapDispatchToProps)(CreateModal) + +module.exports = ModalContainer diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js index bc9d448fe..127b69686 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js @@ -8,6 +8,12 @@ const modal = (state = {}, action) => { callback: action.callback, } }) + case 'CREATE_VEHICLEJOURNEY_MODAL': + return { + type: 'create', + modalProps: {}, + confirmModal: {} + } case 'CLOSE_MODAL': return { type: '', diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/pagination.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/pagination.js index 4ac2a4586..c9bcec6de 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/pagination.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/pagination.js @@ -12,6 +12,7 @@ const pagination = (state = {}, action) => { return Object.assign({}, state, {page : action.pagination.page + 1, stateChanged: false}) } return state + case 'ADD_VEHICLEJOURNEY': case 'UPDATE_TIME': toggleOnConfirmModal('modal') return Object.assign({}, state, {stateChanged: true}) diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js index b48ac33b3..ccf1efea1 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js @@ -2,6 +2,16 @@ var actions = require("../actions") const vehicleJourney= (state = {}, action) => { switch (action.type) { + case 'ADD_VEHICLEJOURNEY': + return { + journey_pattern_id: parseInt(action.data.journey_pattern_id.value), + comment: action.data.comment.value, + objectid: '', + footnotes: [], + time_tables: [], + vehicle_journey_at_stops: [], + deletable: false + } case 'UPDATE_TIME': let vj, vjas, vjasArray, newSchedule vjasArray = state.vehicle_journey_at_stops.map((vjas, i) =>{ @@ -45,6 +55,11 @@ const vehicleJourneys = (state = [], action) => { actions.fetchVehicleJourneys(action.dispatch, action.pagination.page, action.nextPage) } return state + case 'ADD_VEHICLEJOURNEY': + return [ + vehicleJourney(state, action), + ...state + ] case 'UPDATE_TIME': return state.map((vj, i) =>{ if (i == action.index){ diff --git a/spec/javascripts/vehicle_journeys/actions_spec.js b/spec/javascripts/vehicle_journeys/actions_spec.js index 5eb3abe45..9f3f5e168 100644 --- a/spec/javascripts/vehicle_journeys/actions_spec.js +++ b/spec/javascripts/vehicle_journeys/actions_spec.js @@ -29,6 +29,58 @@ describe('when receiveJourneyPatterns is triggered', () => { expect(actions.receiveVehicleJourneys()).toEqual(expectedAction) }) }) +describe('when clicking on add button', () => { + it('should create an action to open a create modal', () => { + const expectedAction = { + type: 'CREATE_VEHICLEJOURNEY_MODAL', + } + expect(actions.openCreateModal()).toEqual(expectedAction) + }) +}) +describe('when clicking on validate button inside create modal', () => { + it('should create an action to create a new journey pattern', () => { + const data = {} + const expectedAction = { + type: 'ADD_VEHICLEJOURNEY', + data + } + expect(actions.addVehicleJourney(data)).toEqual(expectedAction) + }) +}) +describe('when previous navigation button is clicked', () => { + it('should create an action to go to previous page', () => { + const nextPage = false + const pagination = { + totalCount: 25, + perPage: 12, + page:1 + } + const expectedAction = { + type: 'GO_TO_PREVIOUS_PAGE', + dispatch, + pagination, + nextPage + } + expect(actions.goToPreviousPage(dispatch, pagination)).toEqual(expectedAction) + }) +}) +describe('when next navigation button is clicked', () => { + it('should create an action to go to next page', () => { + const nextPage = true + const pagination = { + totalCount: 25, + perPage: 12, + page:1 + } + const expectedAction = { + type: 'GO_TO_NEXT_PAGE', + dispatch, + pagination, + nextPage + } + expect(actions.goToNextPage(dispatch, pagination)).toEqual(expectedAction) + }) +}) describe('when toggling arrivals', () => { it('should create an action to toggleArrivals', () => { const expectedAction = { diff --git a/spec/javascripts/vehicle_journeys/reducers/modal_spec.js b/spec/javascripts/vehicle_journeys/reducers/modal_spec.js index 8da8e6c65..8e854be40 100644 --- a/spec/javascripts/vehicle_journeys/reducers/modal_spec.js +++ b/spec/javascripts/vehicle_journeys/reducers/modal_spec.js @@ -34,6 +34,14 @@ describe('modal reducer', () => { ).toEqual(newState) }) + it('should handle CREATE_VEHICLEJOURNEY_MODAL', () => { + expect( + modalReducer(state, { + type: 'CREATE_VEHICLEJOURNEY_MODAL' + }) + ).toEqual(Object.assign({}, state, { type: 'create' })) + }) + it('should handle CLOSE_MODAL', () => { expect( modalReducer(state, { diff --git a/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js b/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js index 5540caf02..bb40add3a 100644 --- a/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js +++ b/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js @@ -55,6 +55,27 @@ describe('vehicleJourneys reducer', () => { }) + it('should handle ADD_VEHICLEJOURNEY', () => { + let fakeData = { + journey_pattern_id: {value : '1'}, + comment: {value: 'test'} + } + expect( + vjReducer(state, { + type: 'ADD_VEHICLEJOURNEY', + data: fakeData + }) + ).toEqual([{ + journey_pattern_id: 1, + comment: 'test', + objectid: '', + footnotes: [], + time_tables: [], + vehicle_journey_at_stops: [], + deletable: false + }, ...state]) + }) + it('should handle RECEIVE_VEHICLE_JOURNEYS', () => { expect( vjReducer(state, { |
