diff options
| author | Luc Donnet | 2018-02-01 17:39:25 +0100 |
|---|---|---|
| committer | GitHub | 2018-02-01 17:39:25 +0100 |
| commit | f6b2a0b17591a786d41ba77ba1a2664223fc4b96 (patch) | |
| tree | 7db780a7ea455bb182e5fd9a1ef1830d43d2795f | |
| parent | c172bdb34862b6b48ea52e0de71a9444f14c2478 (diff) | |
| parent | b91895f897f6a9b401844e373d020c3f458fc130 (diff) | |
| download | chouette-core-f6b2a0b17591a786d41ba77ba1a2664223fc4b96.tar.bz2 | |
Merge pull request #273 from af83/5798-show-return-times-on-vjs-editor
5798 Show return journeys on the journeys' editor.
14 files changed, 132 insertions, 55 deletions
diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass index 998703ef0..ba5bbbde1 100644 --- a/app/assets/stylesheets/components/_forms.sass +++ b/app/assets/stylesheets/components/_forms.sass @@ -256,8 +256,15 @@ table, .table &.table-2entries .t2e-item > .th position: relative - - > .checkbox + > .st_action + list-style-type: none + button + border-radius: 50% + background: $blue + color: white + border: none + + > .checkbox, > .st_action position: absolute right: 0 top: 0 diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb index ed6ba6ed1..e031e4952 100644 --- a/app/controllers/vehicle_journeys_controller.rb +++ b/app/controllers/vehicle_journeys_controller.rb @@ -50,36 +50,8 @@ class VehicleJourneysController < ChouetteController format.html do load_missions load_custom_fields - @stop_points_list = [] - @stop_points_list = route.stop_points.includes(:stop_area).map do |sp| - { - :id => sp.stop_area.id, - :route_id => sp.try(:route_id), - :object_id => sp.try(:objectid), - :position => sp.try(:position), - :for_boarding => sp.try(:for_boarding), - :for_alighting => sp.try(:for_alighting), - :name => sp.stop_area.try(:name), - :time_zone_offset => sp.stop_area.try(:time_zone_offset), - :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset), - :zip_code => sp.stop_area.try(:zip_code), - :city_name => sp.stop_area.try(:city_name), - :comment => sp.stop_area.try(:comment), - :area_type => sp.stop_area.try(:area_type), - :area_type_i18n => I18n.t(sp.stop_area.try(:area_type), scope: 'area_types.label'), - :area_kind => sp.stop_area.try(:kind), - :stop_area_id => sp.stop_area_id, - :registration_number => sp.stop_area.try(:registration_number), - :nearest_topic_name => sp.stop_area.try(:nearest_topic_name), - :fare_code => sp.stop_area.try(:fare_code), - :longitude => sp.stop_area.try(:longitude), - :latitude => sp.stop_area.try(:latitude), - :long_lat_type => sp.stop_area.try(:long_lat_type), - :country_code => sp.stop_area.try(:country_code), - :country_name => sp.stop_area.try(:country_name), - :street_name => sp.stop_area.try(:street_name) - } - end + @stop_points_list = map_stop_points(route.stop_points) + @return_stop_points_list = map_stop_points(route.opposite_route&.stop_points) if has_feature?(:vehicle_journeys_return_route) @transport_mode = route.line['transport_mode'] @transport_submode = route.line['transport_submode'] @@ -185,6 +157,39 @@ class VehicleJourneysController < ChouetteController @custom_fields = current_workgroup.custom_fields_definitions end + def map_stop_points points + (points&.includes(:stop_area) || []).map do |sp| + { + :id => sp.stop_area.id, + :route_id => sp.try(:route_id), + :object_id => sp.try(:objectid), + :area_object_id => sp.stop_area.try(:objectid), + :position => sp.try(:position), + :for_boarding => sp.try(:for_boarding), + :for_alighting => sp.try(:for_alighting), + :name => sp.stop_area.try(:name), + :time_zone_offset => sp.stop_area.try(:time_zone_offset), + :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset), + :zip_code => sp.stop_area.try(:zip_code), + :city_name => sp.stop_area.try(:city_name), + :comment => sp.stop_area.try(:comment), + :area_type => sp.stop_area.try(:area_type), + :area_type_i18n => I18n.t(sp.stop_area.try(:area_type), scope: 'area_types.label'), + :area_kind => sp.stop_area.try(:kind), + :stop_area_id => sp.stop_area_id, + :registration_number => sp.stop_area.try(:registration_number), + :nearest_topic_name => sp.stop_area.try(:nearest_topic_name), + :fare_code => sp.stop_area.try(:fare_code), + :longitude => sp.stop_area.try(:longitude), + :latitude => sp.stop_area.try(:latitude), + :long_lat_type => sp.stop_area.try(:long_lat_type), + :country_code => sp.stop_area.try(:country_code), + :country_name => sp.stop_area.try(:country_name), + :street_name => sp.stop_area.try(:street_name) + } + end + end + def load_missions @all_missions = route.journey_patterns.count > 10 ? [] : route.journey_patterns.map do |item| { diff --git a/app/javascript/helpers/stop_area_header_manager.js b/app/javascript/helpers/stop_area_header_manager.js index 2c820caf9..5b18e2f63 100644 --- a/app/javascript/helpers/stop_area_header_manager.js +++ b/app/javascript/helpers/stop_area_header_manager.js @@ -42,6 +42,11 @@ export default class StopAreaHeaderManager { let index = this.ids_list.indexOf(object_id) let sp = this.stopPointsList[index] let previousBreakpoint = this.stopPointsList[index - 1] + if(sp == undefined){ + console.log("STOP_POINT NOT FOUND: " + object_id) + console.log("AVAILABLE IDS:" + this.ids_list) + return + } if(index == 0 || (sp[attribute_to_check] != previousBreakpoint[attribute_to_check])){ showHeadline = true headline = this.hasFeature('long_distance_routes') ? sp.country_name : sp.city_name diff --git a/app/javascript/packs/vehicle_journeys/index.js b/app/javascript/packs/vehicle_journeys/index.js index aa5738d59..e6867cb17 100644 --- a/app/javascript/packs/vehicle_journeys/index.js +++ b/app/javascript/packs/vehicle_journeys/index.js @@ -60,6 +60,7 @@ var initialState = { }, vehicleJourneys: [], stopPointsList: window.stopPoints, + returnStopPointsList: window.returnStopPoints, pagination: { page : 1, totalCount: 0, @@ -99,7 +100,7 @@ let store = createStore( render( <Provider store={store}> - <App /> + <App returnRouteUrl={window.returnRouteUrl} /> </Provider>, document.getElementById('vehicle_journeys_wip') ) diff --git a/app/javascript/vehicle_journeys/actions/index.js b/app/javascript/vehicle_journeys/actions/index.js index 8970c6025..74a333b53 100644 --- a/app/javascript/vehicle_journeys/actions/index.js +++ b/app/javascript/vehicle_journeys/actions/index.js @@ -13,8 +13,8 @@ const actions = { exitEditMode: () => ({ type: "EXIT_EDIT_MODE" }), - receiveVehicleJourneys : (json) => ({ - type: "RECEIVE_VEHICLE_JOURNEYS", + receiveVehicleJourneys : (json, returnJourneys) => ({ + type: (returnJourneys ? "RECEIVE_RETURN_VEHICLE_JOURNEYS" : "RECEIVE_VEHICLE_JOURNEYS"), json }), receiveErrors : (json) => ({ @@ -290,10 +290,17 @@ const actions = { type: 'RECEIVE_TOTAL_COUNT', total }), - fetchVehicleJourneys : (dispatch, currentPage, nextPage, queryString) => { + fetchVehicleJourneys : (dispatch, currentPage, nextPage, queryString, url) => { + let returnJourneys = false if(currentPage == undefined){ currentPage = 1 } + if(url == undefined){ + url = window.location.pathname + } + else{ + returnJourneys = true + } let vehicleJourneys = [] let page switch (nextPage) { @@ -315,7 +322,7 @@ const actions = { str = '.json?page=' + page.toString() sep = '&' } - let urlJSON = window.location.pathname + str + let urlJSON = url + str if (queryString){ urlJSON = urlJSON + sep + queryString } @@ -375,7 +382,7 @@ const actions = { ) } window.currentItemsLength = vehicleJourneys.length - dispatch(actions.receiveVehicleJourneys(vehicleJourneys)) + dispatch(actions.receiveVehicleJourneys(vehicleJourneys, returnJourneys)) dispatch(actions.receiveTotalCount(json.total)) } }) diff --git a/app/javascript/vehicle_journeys/components/App.js b/app/javascript/vehicle_journeys/components/App.js index 44559c7c6..5ac284438 100644 --- a/app/javascript/vehicle_journeys/components/App.js +++ b/app/javascript/vehicle_journeys/components/App.js @@ -22,6 +22,7 @@ export default function App() { <Filters /> <VehicleJourneysList /> + {window.returnRouteUrl && <VehicleJourneysList routeUrl={window.returnRouteUrl}/>} <div className='row'> <div className='col-lg-12 text-right'> diff --git a/app/javascript/vehicle_journeys/components/VehicleJourney.js b/app/javascript/vehicle_journeys/components/VehicleJourney.js index 2b5783dda..e7d4b5b30 100644 --- a/app/javascript/vehicle_journeys/components/VehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/VehicleJourney.js @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import actions from '../actions' +import EditVehicleJourney from '../containers/tools/EditVehicleJourney' export default class VehicleJourney extends Component { constructor(props) { @@ -80,7 +81,7 @@ export default class VehicleJourney extends Component { {purchase_windows.length > 3 && <span className='vj_tt'> + {purchase_windows.length - 3}</span>} </div> } - <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}> + {!this.props.disabled && <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}> <input id={this.props.index} name={this.props.index} @@ -91,7 +92,8 @@ export default class VehicleJourney extends Component { checked={this.props.value.selected} ></input> <label htmlFor={this.props.index}></label> - </div> + </div>} + {this.props.disabled && <EditVehicleJourney disabled={false} vehicleJourney={this.props.value} />} </div> {this.props.value.vehicle_journey_at_stops.map((vj, i) => <div key={i} className='td text-center'> diff --git a/app/javascript/vehicle_journeys/components/VehicleJourneys.js b/app/javascript/vehicle_journeys/components/VehicleJourneys.js index 256ca81f9..ae852b35a 100644 --- a/app/javascript/vehicle_journeys/components/VehicleJourneys.js +++ b/app/javascript/vehicle_journeys/components/VehicleJourneys.js @@ -8,14 +8,36 @@ export default class VehicleJourneys extends Component { constructor(props){ super(props) this.headerManager = new StopAreaHeaderManager( - _.map(this.props.stopPointsList, (sp)=>{return sp.object_id}), - this.props.stopPointsList, + _.map(this.stopPoints(), (sp)=>{return sp.object_id}), + this.stopPoints(), this.props.filters.features ) } + isReturn() { + return this.props.routeUrl != undefined + } + + vehicleJourneysList() { + if(this.isReturn()){ + return this.props.returnVehicleJourneys + } + else{ + return this.props.vehicleJourneys + } + } + + stopPoints() { + if(this.isReturn()){ + return this.props.returnStopPointsList + } + else{ + return this.props.stopPointsList + } + } + componentDidMount() { - this.props.onLoadFirstPage(this.props.filters) + this.props.onLoadFirstPage(this.props.filters, this.props.routeUrl) } hasFeature(key) { @@ -89,10 +111,10 @@ export default class VehicleJourneys extends Component { </div> )} - { this.props.vehicleJourneys.errors && this.props.vehicleJourneys.errors.length && _.some(this.props.vehicleJourneys, 'errors') && ( + { this.vehicleJourneysList().errors && this.vehicleJourneysList().errors.length && _.some(this.vehicleJourneysList(), 'errors') && ( <div className="alert alert-danger mt-sm"> <strong>Erreur : </strong> - {this.props.vehicleJourneys.map((vj, index) => + {this.vehicleJourneysList().map((vj, index) => vj.errors && vj.errors.map((err, i) => { return ( <ul key={i}> @@ -104,7 +126,7 @@ export default class VehicleJourneys extends Component { </div> )} - <div className={'table table-2entries mt-sm mb-sm' + ((this.props.vehicleJourneys.length > 0) ? '' : ' no_result')}> + <div className={'table table-2entries mt-sm mb-sm' + ((this.vehicleJourneysList().length > 0) ? '' : ' no_result')}> <div className='t2e-head w20'> <div className='th'> <div className='strong mb-xs'>ID course</div> @@ -114,7 +136,7 @@ export default class VehicleJourneys extends Component { <div>Calendriers</div> { this.hasFeature('purchase_windows') && <div>Calendriers Commerciaux</div> } </div> - {this.props.stopPointsList.map((sp, i) =>{ + {this.stopPoints().map((sp, i) =>{ return ( <div key={i} className='td'> {this.headerManager.stopPointHeader(sp.object_id)} @@ -125,17 +147,18 @@ export default class VehicleJourneys extends Component { <div className='t2e-item-list w80'> <div> - {this.props.vehicleJourneys.map((vj, index) => + {this.vehicleJourneysList().map((vj, index) => <VehicleJourney value={vj} key={index} index={index} - editMode={this.props.editMode} + editMode={this.isReturn() ? false : this.props.editMode} filters={this.props.filters} features={this.props.features} onUpdateTime={this.props.onUpdateTime} onSelectVehicleJourney={this.props.onSelectVehicleJourney} vehicleJourneys={this} + disabled={this.isReturn()} /> )} </div> diff --git a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js index 2893422f8..f814c0459 100644 --- a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js @@ -23,6 +23,10 @@ export default class EditVehicleJourney extends Component { } } + getSelected() { + return this.props.vehicleJourney ? [this.props.vehicleJourney] : actions.getSelected(this.props.vehicleJourneys) + } + render() { if(this.props.status.isFetching == true) { return false @@ -35,10 +39,10 @@ export default class EditVehicleJourney extends Component { <li className='st_action'> <button type='button' - disabled={(actions.getSelected(this.props.vehicleJourneys).length != 1 || this.props.disabled)} + disabled={(this.getSelected().length != 1 || this.props.disabled)} data-toggle='modal' data-target='#EditVehicleJourneyModal' - onClick={() => this.props.onOpenEditModal(actions.getSelected(this.props.vehicleJourneys)[0])} + onClick={() => this.props.onOpenEditModal(this.getSelected()[0])} > <span className='fa fa-info'></span> </button> diff --git a/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js b/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js index 38ab9f6d3..76d1c3a78 100644 --- a/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js +++ b/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js @@ -6,17 +6,19 @@ const mapStateToProps = (state) => { return { editMode: state.editMode, vehicleJourneys: state.vehicleJourneys, + returnVehicleJourneys: state.returnVehicleJourneys, status: state.status, filters: state.filters, - stopPointsList: state.stopPointsList + stopPointsList: state.stopPointsList, + returnStopPointsList: state.returnStopPointsList } } const mapDispatchToProps = (dispatch) => { return { - onLoadFirstPage: (filters) =>{ + onLoadFirstPage: (filters, routeUrl) =>{ dispatch(actions.fetchingApi()) - actions.fetchVehicleJourneys(dispatch, undefined, undefined, filters.queryString) + actions.fetchVehicleJourneys(dispatch, undefined, undefined, filters.queryString, routeUrl) }, onUpdateTime: (e, subIndex, index, timeUnit, isDeparture, isArrivalsToggled) => { dispatch(actions.updateTime(e.target.value, subIndex, index, timeUnit, isDeparture, isArrivalsToggled)) diff --git a/app/javascript/vehicle_journeys/reducers/index.js b/app/javascript/vehicle_journeys/reducers/index.js index 1963f7c6d..95ac9c7e1 100644 --- a/app/javascript/vehicle_journeys/reducers/index.js +++ b/app/javascript/vehicle_journeys/reducers/index.js @@ -1,5 +1,6 @@ import { combineReducers } from 'redux' import vehicleJourneys from './vehicleJourneys' +import returnVehicleJourneys from './returnVehicleJourneys' import pagination from './pagination' import modal from './modal' import status from './status' @@ -11,12 +12,14 @@ import custom_fields from './custom_fields' const vehicleJourneysApp = combineReducers({ vehicleJourneys, + returnVehicleJourneys, pagination, modal, status, filters, editMode, stopPointsList, + returnStopPointsList: stopPointsList, missions, custom_fields }) diff --git a/app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js b/app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js new file mode 100644 index 000000000..db3c71d17 --- /dev/null +++ b/app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js @@ -0,0 +1,11 @@ +import _ from 'lodash' +import actions from '../actions' + +export default function returnVehicleJourneys(state = [], action) { + switch (action.type) { + case 'RECEIVE_RETURN_VEHICLE_JOURNEYS': + return [...action.json] + default: + return state + } +} diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb index 55faaf997..aa9fdb810 100644 --- a/app/models/chouette/journey_pattern.rb +++ b/app/models/chouette/journey_pattern.rb @@ -160,7 +160,7 @@ module Chouette def full_schedule? full = true - stop_points.inject(nil) do |start, finish| + stop_points.order(:position).inject(nil) do |start, finish| next finish unless start.present? costs = costs_between(start, finish) full = false unless costs.present? diff --git a/app/views/vehicle_journeys/index.html.slim b/app/views/vehicle_journeys/index.html.slim index ce56f9332..caa8450a0 100644 --- a/app/views/vehicle_journeys/index.html.slim +++ b/app/views/vehicle_journeys/index.html.slim @@ -17,6 +17,7 @@ = javascript_tag do | window.route_id = #{params[:route_id]}; | window.stopPoints = #{(@stop_points_list.to_json).html_safe}; + | window.returnStopPoints = #{(@return_stop_points_list.to_json).html_safe}; | window.jpOrigin = #{(@jp_origin.present? ? @jp_origin.attributes.update({full_schedule: @jp_origin.full_schedule?}).to_json : "null").html_safe}; | window.jpOriginStopPoints = #{(@jp_origin_stop_points.to_json).html_safe}; | window.transportMode = #{(@transport_mode.to_json).html_safe}; @@ -30,4 +31,9 @@ | window.custom_fields = #{(@custom_fields.to_json).html_safe}; | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe}; +- if has_feature?(:vehicle_journeys_return_route) + = javascript_tag do + | window.returnRouteUrl = "#{(@route.opposite_route && url_for([@referential, @route.line, @route.opposite_route, :vehicle_journeys]) || "").html_safe}"; + + = javascript_pack_tag 'vehicle_journeys/index.js' |
