diff options
| author | Zog | 2018-04-25 09:12:26 +0200 | 
|---|---|---|
| committer | Zog | 2018-04-25 09:12:26 +0200 | 
| commit | d0c9be18498c1179a9341f51c5705a736d21ea71 (patch) | |
| tree | bf540e06a33d5be29663a30dd75d62d0e1fedb7e /app/javascript | |
| parent | eb51cf0aa62a96c552c1a32778aa84e64df458a6 (diff) | |
| download | chouette-core-d0c9be18498c1179a9341f51c5705a736d21ea71.tar.bz2 | |
Refs #6472; Add Constraint Zone exclusions to journeys6472-itls-exclusions
along with the React interface
Diffstat (limited to 'app/javascript')
7 files changed, 340 insertions, 2 deletions
| diff --git a/app/javascript/vehicle_journeys/actions/index.js b/app/javascript/vehicle_journeys/actions/index.js index 70d6e953a..c67f9f0cf 100644 --- a/app/javascript/vehicle_journeys/actions/index.js +++ b/app/javascript/vehicle_journeys/actions/index.js @@ -97,10 +97,30 @@ const actions = {      vehicleJourneys,      timetables    }), +  editVehicleJourneyConstraintZones : (vehicleJourneys, zones) => ({ +    type: 'EDIT_VEHICLEJOURNEYS_CONSTRAINT_ZONES', +    vehicleJourneys, +    zones +  }),    openPurchaseWindowsEditModal : (vehicleJourneys) => ({      type : 'EDIT_PURCHASE_WINDOWS_VEHICLEJOURNEY_MODAL',      vehicleJourneys    }), +  openConstraintExclusionEditModal : (vehicleJourneys) => ({ +    type : 'EDIT_CONSTRAINT_EXCLUSIONS_VEHICLEJOURNEY_MODAL', +    vehicleJourneys +  }), +  selectConstraintZone: (selectedZone) =>({ +    type: 'SELECT_CONSTRAINT_ZONE_MODAL', +    selectedZone: { +      id: selectedZone.id, +      name: selectedZone.text +    } +  }), +  deleteConstraintZone : (constraintZone) => ({ +    type : 'DELETE_CONSTRAINT_ZONE_MODAL', +    constraintZone +  }),    selectPurchaseWindowsModal: (selectedItem) =>({      type: 'SELECT_PURCHASE_WINDOW_MODAL',      selectedItem diff --git a/app/javascript/vehicle_journeys/components/Tools.js b/app/javascript/vehicle_journeys/components/Tools.js index 22ea44283..efae6b2b5 100644 --- a/app/javascript/vehicle_journeys/components/Tools.js +++ b/app/javascript/vehicle_journeys/components/Tools.js @@ -9,6 +9,7 @@ import EditVehicleJourney from '../containers/tools/EditVehicleJourney'  import NotesEditVehicleJourney from '../containers/tools/NotesEditVehicleJourney'  import TimetablesEditVehicleJourney from '../containers/tools/TimetablesEditVehicleJourney'  import PurchaseWindowsEditVehicleJourney from '../containers/tools/PurchaseWindowsEditVehicleJourney' +import ConstraintExclusionEditVehicleJourney from '../containers/tools/ConstraintExclusionEditVehicleJourney'  export default class Tools extends Component { @@ -36,10 +37,12 @@ export default class Tools extends Component {            <DuplicateVehicleJourney disabled={!this.hasPolicy("create") || !this.hasPolicy("update") || !editMode}/>            <ShiftVehicleJourney disabled={!this.hasPolicy("update") || !editMode}/>            <EditVehicleJourney disabled={!this.hasPolicy("update")}/> +            <TimetablesEditVehicleJourney disabled={!this.hasPolicy("update")}/>            { this.hasFeature('purchase_windows') &&              <PurchaseWindowsEditVehicleJourney disabled={!this.hasPolicy("update")}/>            } +          <ConstraintExclusionEditVehicleJourney disabled={!this.hasPolicy("update")}/>            <NotesEditVehicleJourney disabled={!this.hasPolicy("update")}/>            <DeleteVehicleJourneys disabled={!this.hasPolicy("destroy") || !editMode}/>          </ul> diff --git a/app/javascript/vehicle_journeys/components/tools/ConstraintExclusionEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/ConstraintExclusionEditVehicleJourney.js new file mode 100644 index 000000000..bab77926f --- /dev/null +++ b/app/javascript/vehicle_journeys/components/tools/ConstraintExclusionEditVehicleJourney.js @@ -0,0 +1,182 @@ +import _ from 'lodash' +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import actions from '../../actions' +import ConstraintZoneSelect2 from './select2s/ConstraintZoneSelect2' + + +export default class ConstraintExclusionEditVehicleJourney extends Component { +  constructor(props) { +    super(props) +    this.handleSubmit = this.handleSubmit.bind(this) +    this.constraintZoneUrl = this.constraintZoneUrl.bind(this) +    this.excluded_constraint_zones = this.excluded_constraint_zones.bind(this) +    this.constraint_zones = null +  } + +  handleSubmit() { +    this.props.onConstraintZonesEditVehicleJourney(this.props.modal.modalProps.vehicleJourneys, this.props.modal.modalProps.selectedConstraintZones) +    this.props.onModalClose() +    $('#ConstraintExclusionEditVehicleJourney').modal('hide') +  } + +  constraintZoneUrl(contraint_zone) { +    return window.constraint_zones_routes + "/" + contraint_zone.id +  } + +  excluded_constraint_zones() { +    let out = [] +    this.props.modal.modalProps.selectedConstraintZones.map((id, _)=>{ +      this.constraint_zones.map((zone, _)=>{ +        if(zone.id == id){ +          out.push(zone) +        } +      }) +    }) +    return out +  } + +  fetch_constraint_zones() { +    let url = window.constraint_zones_routes + ".json" +    fetch(url, { +      credentials: 'same-origin', +    }).then(response => { +      return response.json() +    }).then((json) => { +      this.constraint_zones = [] +      json.map((item, i)=>{ +        this.constraint_zones.push( +          _.assign({}, item, {text: item.name}) +        ) +      }) +      this.forceUpdate() +    }) +  } + +  render() { +    if(this.constraint_zones === null) { +      this.fetch_constraint_zones() +      return false +    } +    if(this.props.status.fetchSuccess == true) { +      return ( +        <li className='st_action'> +          <button +            type='button' +            disabled={(actions.getSelected(this.props.vehicleJourneys).length < 1 || this.props.disabled)} +            data-toggle='modal' +            data-target='#ConstraintExclusionEditVehicleJourney' +            onClick={() => this.props.onOpenCalendarsEditModal(actions.getSelected(this.props.vehicleJourneys))} +            title={I18n.t('activerecord.attributes.vehicle_journey.constraint_exclusions')} +          > +            <span className='fa fa-ban fa-strong'></span> +          </button> + +          <div className={ 'modal fade ' + ((this.props.modal.type == 'duplicate') ? 'in' : '') } id='ConstraintExclusionEditVehicleJourney'> +            <div className='modal-container'> +              <div className='modal-dialog'> +                <div className='modal-content'> +                  <div className='modal-header'> +                    <h4 className='modal-title'>{I18n.t('activerecord.attributes.vehicle_journey.constraint_exclusions')}</h4> +                    <span type="button" className="close modal-close" data-dismiss="modal">×</span> +                  </div> + +                  {(this.props.modal.type == 'constraint_exclusions_edit') && ( +                    <form> +                      <div className='modal-body'> +                        <div className='row'> +                          <div className='col-lg-12'> +                            <div className='subform'> +                              <div className='nested-head'> +                                <div className='wrapper'> +                                  <div> +                                    <div className='form-group'> +                                      <label className='control-label'>{this.excluded_constraint_zones().length == 0 ? I18n.t('vehicle_journeys.vehicle_journeys_matrix.no_excluded_constraint_zones') : I18n.t('vehicle_journeys.form.excluded_constraint_zones')}</label> +                                    </div> +                                  </div> +                                  <div></div> +                                </div> +                              </div> +                              {this.excluded_constraint_zones().map((contraint_zone, i) => +                                <div className='nested-fields' key={i}> +                                  <div className='wrapper'> +                                    <div> <a href={this.constraintZoneUrl(contraint_zone)} target="_blank"> +                                      {contraint_zone.name} +                                    </a> </div> +                                    { +                                      this.props.editMode && +                                      <div> +                                        <a +                                          href='#' +                                          title='Supprimer' +                                          className='fa fa-trash remove_fields' +                                          style={{ height: 'auto', lineHeight: 'normal' }} +                                          onClick={(e) => { +                                            e.preventDefault() +                                            this.props.onDeleteConstraintZone(contraint_zone) +                                          }} +                                        ></a> +                                      </div> +                                    } +                                  </div> +                                </div> +                              )} +                              { +                                this.props.editMode && +                                <div className='nested-fields'> +                                  <div className='wrapper'> +                                    <div> +                                      <ConstraintZoneSelect2 +                                        data={this.constraint_zones} +                                        values={this.props.modal.modalProps.constraint_exclusions} +                                        placeholder={I18n.t('vehicle_journeys.vehicle_journeys_matrix.filters.constraint_zone')} +                                        onSelectConstraintZone={this.props.onSelectConstraintZone} +                                      /> +                                    </div> +                                  </div> +                                </div> +                              } +                            </div> +                          </div> +                        </div> +                      </div> +                      { +                        this.props.editMode && +                        <div className='modal-footer'> +                          <button +                            className='btn btn-link' +                            data-dismiss='modal' +                            type='button' +                            onClick={this.props.onModalClose} +                          > +                            {I18n.t('cancel')} +                          </button> +                          <button +                            className='btn btn-primary' +                            type='button' +                            onClick={this.handleSubmit} +                          > +                            {I18n.t('actions.submit')} +                          </button> +                        </div> +                      } +                    </form> +                  )} + +                </div> +              </div> +            </div> +          </div> +        </li> +      ) +    } else { +      return false +    } +  } +} + +ConstraintExclusionEditVehicleJourney.propTypes = { +  onOpenCalendarsEditModal: PropTypes.func.isRequired, +  onModalClose: PropTypes.func.isRequired, +  disabled: PropTypes.bool.isRequired +} diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/ConstraintZoneSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/ConstraintZoneSelect2.js new file mode 100644 index 000000000..1caaf2401 --- /dev/null +++ b/app/javascript/vehicle_journeys/components/tools/select2s/ConstraintZoneSelect2.js @@ -0,0 +1,37 @@ +import _ from 'lodash' +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import Select2 from 'react-select2-wrapper' +import actions from '../../../actions' + +export default class BSelect4 extends Component { +  constructor(props) { +    super(props) +  } + +  render() { +    return ( +      <Select2 +        data={this.props.data} +        value={this.props.value} +        onSelect={(e) => this.props.onSelectConstraintZone(e) } +        multiple={false} +        ref='constraint_zone_id' +        options={{ +          allowClear: false, +          theme: 'bootstrap', +          width: '100%', +          placeholder: this.props.placeholder, +          language: require('./language'), +          minimumInputLength: 1, +          escapeMarkup: function (markup) { return markup; }, +          templateResult: formatRepo +        }} +      /> +    ) +  } +} + +const formatRepo = (props) => { +  if(props.text) return props.text +} diff --git a/app/javascript/vehicle_journeys/containers/tools/ConstraintExclusionEditVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/ConstraintExclusionEditVehicleJourney.js new file mode 100644 index 000000000..76d85dfe6 --- /dev/null +++ b/app/javascript/vehicle_journeys/containers/tools/ConstraintExclusionEditVehicleJourney.js @@ -0,0 +1,37 @@ +import actions from '../../actions' +import { connect } from 'react-redux' +import ConstraintExclusionEditVehicleJourneyComponent from '../../components/tools/ConstraintExclusionEditVehicleJourney' + +const mapStateToProps = (state, ownProps) => { +  return { +    editMode: state.editMode, +    modal: state.modal, +    vehicleJourneys: state.vehicleJourneys, +    status: state.status, +    disabled: ownProps.disabled +  } +} + +const mapDispatchToProps = (dispatch) => { +  return { +    onModalClose: () =>{ +      dispatch(actions.closeModal()) +    }, +    onOpenCalendarsEditModal: (vehicleJourneys) =>{ +      dispatch(actions.openConstraintExclusionEditModal(vehicleJourneys)) +    }, +    onDeleteConstraintZone: (constraint_zone) => { +      dispatch(actions.deleteConstraintZone(constraint_zone)) +    }, +    onConstraintZonesEditVehicleJourney: (vehicleJourneys, constraint_zones) => { +      dispatch(actions.editVehicleJourneyConstraintZones(vehicleJourneys, constraint_zones)) +    }, +    onSelectConstraintZone: (e) => { +      dispatch(actions.selectConstraintZone(e.params.data)) +    }, +  } +} + +const ConstraintExclusionEditVehicleJourney = connect(mapStateToProps, mapDispatchToProps)(ConstraintExclusionEditVehicleJourneyComponent) + +export default ConstraintExclusionEditVehicleJourney diff --git a/app/javascript/vehicle_journeys/reducers/modal.js b/app/javascript/vehicle_journeys/reducers/modal.js index 84567ec0d..75ab2f4ca 100644 --- a/app/javascript/vehicle_journeys/reducers/modal.js +++ b/app/javascript/vehicle_journeys/reducers/modal.js @@ -82,6 +82,30 @@ export default function modal(state = {}, action) {          },          confirmModal: {}        } +    case 'EDIT_CONSTRAINT_EXCLUSIONS_VEHICLEJOURNEY_MODAL': +      var vehicleJourneys = JSON.parse(JSON.stringify(action.vehicleJourneys)) +      let uniqExclusions = [] +      vehicleJourneys.map((vj, i) => { +        vj.ignored_routing_contraint_zone_ids.map((exclusion, j) =>{ +          let found = false +          uniqExclusions.map((id, i)=>{ +            if(id == parseInt(exclusion)){ +              found = true +            } +          }) +          if(!found){ +            uniqExclusions.push(parseInt(exclusion)) +          } +        }) +      }) +      return { +        type: 'constraint_exclusions_edit', +        modalProps: { +          vehicleJourneys: vehicleJourneys, +          selectedConstraintZones: uniqExclusions +        }, +        confirmModal: {} +      }      case 'SELECT_CP_EDIT_MODAL':        vehicleJourney =  _.assign({}, state.modalProps.vehicleJourney, {company: action.selectedItem})        newModalProps = _.assign({}, state.modalProps, {vehicleJourney}) @@ -93,9 +117,28 @@ export default function modal(state = {}, action) {      case 'SELECT_TT_CALENDAR_MODAL':        newModalProps = _.assign({}, state.modalProps, {selectedTimetable : action.selectedItem})        return _.assign({}, state, {modalProps: newModalProps}) -    case 'SELECT_PURCHASE_WINDOW_MODAL': -      newModalProps = _.assign({}, state.modalProps, {selectedPurchaseWindow : action.selectedItem}) +    case 'SELECT_CONSTRAINT_ZONE_MODAL': +      let selectedConstraintZones = state.modalProps.selectedConstraintZones +      let already_present = false +      selectedConstraintZones.map((zone_id, i)=>{ +        if(zone_id == parseInt(action.selectedZone.id)){ +          already_present = true +        } +      }) +      if(already_present){ return state } +      selectedConstraintZones.push(parseInt(action.selectedZone.id)) +      newModalProps = _.assign({}, state.modalProps, {selectedConstraintZones})        return _.assign({}, state, {modalProps: newModalProps}) +    case 'DELETE_CONSTRAINT_ZONE_MODAL': +        newModalProps = JSON.parse(JSON.stringify(state.modalProps)) +        selectedConstraintZones = state.modalProps.selectedConstraintZones.slice(0) +        selectedConstraintZones.map((zone_id, i) =>{ +          if(zone_id == parseInt(action.constraintZone.id)){ +            selectedConstraintZones.splice(i, 1) +          } +        }) +        newModalProps.selectedConstraintZones = selectedConstraintZones +        return _.assign({}, state, {modalProps: newModalProps})      case 'ADD_SELECTED_TIMETABLE':        if(state.modalProps.selectedTimetable){          newModalProps = JSON.parse(JSON.stringify(state.modalProps)) diff --git a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js index b02c19a69..8432c5abe 100644 --- a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js +++ b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js @@ -116,6 +116,7 @@ const vehicleJourney= (state = {}, action, keep) => {          footnotes: [],          time_tables: [],          purchase_windows: [], +        ignored_routing_contraint_zone_ids: [],          vehicle_journey_at_stops: pristineVjasList,          selected: false,          deletable: false, @@ -232,6 +233,21 @@ export default function vehicleJourneys(state = [], action) {            return vj          }        }) +    case 'EDIT_VEHICLEJOURNEYS_CONSTRAINT_ZONES': +      let newExclusions = JSON.parse(JSON.stringify(action.zones)) +      return state.map((vj,i) =>{ +        if(vj.selected){ +          let updatedVJ = _.assign({}, vj) +          action.vehicleJourneys.map((vjm, j) =>{ +            if(vj.objectid == vjm.objectid){ +              updatedVJ.ignored_routing_contraint_zone_ids =  newExclusions +            } +          }) +          return updatedVJ +        }else{ +          return vj +        } +      })        case 'EDIT_VEHICLEJOURNEYS_PURCHASE_WINDOWS':          let newWindows = JSON.parse(JSON.stringify(action.purchase_windows))          return state.map((vj,i) =>{ | 
