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, { | 
