diff options
9 files changed, 139 insertions, 8 deletions
diff --git a/app/javascript/journey_patterns/actions/index.js b/app/javascript/journey_patterns/actions/index.js index a70a2e6f2..b90908264 100644 --- a/app/javascript/journey_patterns/actions/index.js +++ b/app/javascript/journey_patterns/actions/index.js @@ -20,6 +20,12 @@ const actions = { type: "RECEIVE_ERRORS", json }), + receiveRouteCosts: (costs, key, index) => ({ + type: "RECEIVE_ROUTE_COSTS", + costs, + key, + index + }), unavailableServer : () => ({ type: 'UNAVAILABLE_SERVER' }), @@ -213,6 +219,30 @@ const actions = { } }) }, + fetchRouteCosts: (dispatch, key, index) => { + if (actions.routeCostsCache) { + // Dispatch asynchronously to prevent warning when + // this executes during `render()` + requestAnimationFrame(() => { + dispatch(actions.receiveRouteCosts( + actions.routeCostsCache, + key, + index + )) + }) + } else { + fetch(window.routeCostsUrl, { + credentials: 'same-origin', + }).then(response => { + return response.json() + }).then(json => { + let costs = json.costs ? json.costs : {} + actions.routeCostsCache = costs + + dispatch(actions.receiveRouteCosts(costs, key, index)) + }) + } + }, getChecked : (jp) => { return jp.filter((obj) => { return obj.checked diff --git a/app/javascript/journey_patterns/components/JourneyPattern.js b/app/javascript/journey_patterns/components/JourneyPattern.js index d20294594..15d8b6db4 100644 --- a/app/javascript/journey_patterns/components/JourneyPattern.js +++ b/app/javascript/journey_patterns/components/JourneyPattern.js @@ -98,12 +98,24 @@ export default class JourneyPattern extends Component{ getTimeAndDistanceBetweenStops(from, to){ let costsKey = from + "-" + to - let costs = this.props.value.costs[costsKey] || {distance: 0, time: 0} + let costs = this.getCosts(costsKey) let time = costs['time'] || 0 let distance = costs['distance'] || 0 return [costsKey, costs, time, distance] } + getCosts(costsKey) { + let cost = this.props.value.costs[costsKey] + + if (cost) { + return cost + } + + this.props.fetchRouteCosts(costsKey) + + return { distance: 0, time: 0 } + } + formatDistance(distance){ return parseFloat(Math.round(distance * 100) / 100).toFixed(2) + " km" } @@ -119,9 +131,12 @@ export default class JourneyPattern extends Component{ } } + componentWillUpdate() { + [this.totalTime, this.totalDistance] = this.totals(false) + } + render() { this.previousSpId = undefined - let [totalTime, totalDistance] = this.totals(false) let [commercialTotalTime, commercialTotalDistance] = this.totals(true) return ( <div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.object_id ? '' : ' to_record') + (this.props.value.errors ? ' has-error': '') + (this.hasFeature('costs_in_journey_patterns') ? ' with-costs' : '')}> @@ -131,8 +146,8 @@ export default class JourneyPattern extends Component{ <div>{actions.getChecked(this.props.value.stop_points).length} arrĂȘt(s)</div> {this.hasFeature('costs_in_journey_patterns') && <div className="small row totals"> - <span className="col-md-6"><i className="fa fa-arrows-h"></i>{totalDistance}</span> - <span className="col-md-6"><i className="fa fa-clock-o"></i>{totalTime}</span> + <span className="col-md-6"><i className="fa fa-arrows-h"></i>{this.totalDistance}</span> + <span className="col-md-6"><i className="fa fa-clock-o"></i>{this.totalTime}</span> </div> } {this.hasFeature('costs_in_journey_patterns') && @@ -228,5 +243,6 @@ JourneyPattern.propTypes = { onCheckboxChange: PropTypes.func.isRequired, onOpenEditModal: PropTypes.func.isRequired, onDeleteJourneyPattern: PropTypes.func.isRequired, - journeyPatterns: PropTypes.object.isRequired + journeyPatterns: PropTypes.object.isRequired, + fetchRouteCosts: PropTypes.func.isRequired } diff --git a/app/javascript/journey_patterns/components/JourneyPatterns.js b/app/javascript/journey_patterns/components/JourneyPatterns.js index e8b6bf143..930acb390 100644 --- a/app/javascript/journey_patterns/components/JourneyPatterns.js +++ b/app/javascript/journey_patterns/components/JourneyPatterns.js @@ -138,6 +138,7 @@ export default class JourneyPatterns extends Component { status= {this.props.status} editMode= {this.props.editMode} journeyPatterns= {this} + fetchRouteCosts={(costsKey) => this.props.fetchRouteCosts(costsKey, index)} /> )} </div> @@ -156,5 +157,6 @@ JourneyPatterns.propTypes = { status: PropTypes.object.isRequired, onCheckboxChange: PropTypes.func.isRequired, onLoadFirstPage: PropTypes.func.isRequired, - onOpenEditModal: PropTypes.func.isRequired + onOpenEditModal: PropTypes.func.isRequired, + fetchRouteCosts: PropTypes.func.isRequired } diff --git a/app/javascript/journey_patterns/containers/JourneyPatternList.js b/app/javascript/journey_patterns/containers/JourneyPatternList.js index d338345f2..539b6b54c 100644 --- a/app/javascript/journey_patterns/containers/JourneyPatternList.js +++ b/app/javascript/journey_patterns/containers/JourneyPatternList.js @@ -29,6 +29,9 @@ const mapDispatchToProps = (dispatch) => { onUpdateJourneyPatternCosts: (index, costs) =>{ dispatch(actions.updateJourneyPatternCosts(index, costs)) }, + fetchRouteCosts: (key, index) => { + actions.fetchRouteCosts(dispatch, key, index) + }, } } diff --git a/app/javascript/journey_patterns/reducers/journeyPatterns.js b/app/javascript/journey_patterns/reducers/journeyPatterns.js index 1ce069522..6c38e9288 100644 --- a/app/javascript/journey_patterns/reducers/journeyPatterns.js +++ b/app/javascript/journey_patterns/reducers/journeyPatterns.js @@ -40,6 +40,17 @@ export default function journeyPatterns (state = [], action) { return [...action.json] case 'RECEIVE_ERRORS': return [...action.json] + case 'RECEIVE_ROUTE_COSTS': + return state.map((j, i) =>{ + if(i == action.index) { + const new_costs = Object.assign({}, j.costs) + new_costs[action.key] = action.costs[action.key] || + {distance: 0, time: 0} + return _.assign({}, j, {costs: new_costs}) + } else { + return j + } + }) case 'GO_TO_PREVIOUS_PAGE': $('#ConfirmModal').modal('hide') if(action.pagination.page > 1){ diff --git a/app/views/journey_patterns_collections/show.html.slim b/app/views/journey_patterns_collections/show.html.slim index 8a7b0c47c..b389a1da7 100644 --- a/app/views/journey_patterns_collections/show.html.slim +++ b/app/views/journey_patterns_collections/show.html.slim @@ -19,5 +19,6 @@ | window.journeyPatternsPerPage = #{@ppage}; | window.perms = #{raw @perms}; | window.features = #{raw @features}; + | window.routeCostsUrl = "#{costs_referential_line_route_url(@referential, @route.line, @route, format: :json).html_safe}"; = javascript_pack_tag 'journey_patterns/index.js' diff --git a/spec/javascript/journey_patterns/components/JourneyPattern_spec.js b/spec/javascript/journey_patterns/components/JourneyPattern_spec.js index 0da75ad47..82c996424 100644 --- a/spec/javascript/journey_patterns/components/JourneyPattern_spec.js +++ b/spec/javascript/journey_patterns/components/JourneyPattern_spec.js @@ -26,7 +26,8 @@ describe('the edit button', () => { stop_points: [] }, index: 0, - editMode: editMode + editMode: editMode, + fetchRouteCosts: () => {} } let list = renderer.create( <JourneyPattern @@ -38,6 +39,7 @@ describe('the edit button', () => { onDeleteJourneyPattern={props.onDeleteJourneyPattern} onOpenEditModal={props.onOpenEditModal} editMode={props.editMode} + fetchRouteCosts={props.fetchRouteCosts} /> ) diff --git a/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js b/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js index 0c852deff..b6f83963b 100644 --- a/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js +++ b/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js @@ -15,7 +15,8 @@ describe('stopPointHeader', () => { onLoadFirstPage: ()=>{}, onOpenEditModal: ()=>{}, stopPointsList: [stop_point, same_city_stop_point, other_country_stop_point], - journeyPatterns: [] + journeyPatterns: [], + fetchRouteCosts: () => {} } let list = renderer.create( <JourneyPatterns @@ -25,6 +26,7 @@ describe('stopPointHeader', () => { onCheckboxChange={props.onCheckboxChange} onLoadFirstPage={props.onLoadFirstPage} onOpenEditModal={props.onOpenEditModal} + fetchRouteCosts={props.fetchRouteCosts} /> ).toJSON() diff --git a/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js b/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js index bfa87d24a..ce3bdc055 100644 --- a/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js +++ b/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js @@ -132,6 +132,70 @@ describe('journeyPatterns reducer', () => { ).toEqual([state[0], new_state]) }) + it('should handle RECEIVE_ROUTE_COSTS', () => { + const costs = { + "1-2": { + distance: 1, + time: 9, + }, + "2-3": { + distance: 23, + time: 10 + } + } + const new_costs = { + "1-2": { + distance: 0, + time: 10, + }, + "2-3": { + distance: 23, + time: 10 + } + } + const new_state = Object.assign({}, state[1], {costs: new_costs}) + expect( + jpReducer(state, { + type: 'RECEIVE_ROUTE_COSTS', + costs, + key: '2-3', + index: 1 + }) + ).toEqual([state[0], new_state]) + }) + + it('should handle RECEIVE_ROUTE_COSTS when cost key is missing', () => { + const costs = { + "1-2": { + distance: 1, + time: 9, + }, + "2-3": { + distance: 23, + time: 10 + } + } + const new_costs = { + "1-2": { + distance: 0, + time: 10, + }, + "3-4": { + distance: 0, + time: 0 + } + } + const new_state = Object.assign({}, state[1], {costs: new_costs}) + expect( + jpReducer(state, { + type: 'RECEIVE_ROUTE_COSTS', + costs, + key: '3-4', + index: 1 + }) + ).toEqual([state[0], new_state]) + }) + it('should handle DELETE_JOURNEYPATTERN', () => { expect( jpReducer(state, { |
