diff options
Diffstat (limited to 'app/javascript')
50 files changed, 575 insertions, 135 deletions
| diff --git a/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js b/app/javascript/helpers/CustomFieldsInputs.js index 827c36b76..9547021eb 100644 --- a/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js +++ b/app/javascript/helpers/CustomFieldsInputs.js @@ -16,7 +16,7 @@ export default class CustomFieldsInputs extends Component {          })}          ref={'custom_fields.' + cf.code}          className='form-control' -        defaultValue={cf.value} +        defaultValue={cf.value || cf.options.default}          disabled={this.props.disabled}          options={{            theme: 'bootstrap', @@ -34,8 +34,21 @@ export default class CustomFieldsInputs extends Component {          ref={'custom_fields.' + cf.code}          className='form-control'          disabled={this.props.disabled} -        defaultValue={cf.value} -        onChange={(e) => this.props.onUpdate(cf.code, e.target.value) } +        value={cf.value || cf.options.default} +        onChange={(e) => {this.props.onUpdate(cf.code, e.target.value); this.forceUpdate()} } +        /> +    ) +  } + +  integerInput(cf){ +    return( +      <input +        type='number' +        ref={'custom_fields.' + cf.code} +        className='form-control' +        disabled={this.props.disabled} +        value={cf.value || cf.options.default} +        onChange={(e) => {this.props.onUpdate(cf.code, e.target.value); this.forceUpdate()} }          />      )    } diff --git a/app/javascript/helpers/polyfills.js b/app/javascript/helpers/polyfills.js new file mode 100644 index 000000000..93e3e9846 --- /dev/null +++ b/app/javascript/helpers/polyfills.js @@ -0,0 +1,4 @@ +import 'promise-polyfill/src/polyfill' +import 'es6-symbol/implement' +import 'polyfill-array-includes' +import 'whatwg-fetch' diff --git a/app/javascript/journey_patterns/actions/index.js b/app/javascript/journey_patterns/actions/index.js index ea54f4e05..a813f4b9e 100644 --- a/app/javascript/journey_patterns/actions/index.js +++ b/app/javascript/journey_patterns/actions/index.js @@ -1,10 +1,3 @@ -import Promise from 'promise-polyfill' - -// To add to window -if (!window.Promise) { -  window.Promise = Promise; -} -  const actions = {    enterEditMode: () => ({      type: "ENTER_EDIT_MODE" @@ -195,15 +188,19 @@ const actions = {            dispatch(actions.unavailableServer())          } else {            if(json.length != 0){ -            let val -            for (val of json){ -              for (let stop_point of val.route_short_description.stop_points){ +            let j = 0 +            while(j < json.length){ +              let val = json[j] +              let i = 0 +              while(i < val.route_short_description.stop_points.length){ +                let stop_point = val.route_short_description.stop_points[i]                  stop_point.checked = false                  val.stop_area_short_descriptions.map((element) => {                    if(element.stop_area_short_description.id === stop_point.id){                      stop_point.checked = true                    }                  }) +                i ++                }                journeyPatterns.push(                  _.assign({}, val, { @@ -212,6 +209,7 @@ const actions = {                    deletable: false                  })                ) +              j ++              }            }            window.currentItemsLength = journeyPatterns.length diff --git a/app/javascript/journey_patterns/components/CreateModal.js b/app/javascript/journey_patterns/components/CreateModal.js index 946c13d9c..51f6f6c1b 100644 --- a/app/javascript/journey_patterns/components/CreateModal.js +++ b/app/javascript/journey_patterns/components/CreateModal.js @@ -1,15 +1,17 @@  import React, { Component } from 'react'  import PropTypes from 'prop-types'  import actions from '../actions' +import CustomFieldsInputs from '../../helpers/CustomFieldsInputs'  export default class CreateModal extends Component {    constructor(props) {      super(props) +    this.custom_fields = _.assign({}, this.props.custom_fields)    }    handleSubmit() {      if(actions.validateFields(this.refs) == true) { -      this.props.onAddJourneyPattern(this.refs) +      this.props.onAddJourneyPattern(_.assign({}, this.refs, {custom_fields: this.custom_fields}))        this.props.onModalClose()        $('#NewJourneyPatternModal').modal('hide')      } @@ -78,8 +80,14 @@ export default class CreateModal extends Component {                                      />                                  </div>                                </div> +                              <CustomFieldsInputs +                                values={this.props.custom_fields} +                                onUpdate={(code, value) => this.custom_fields[code]["value"] = value} +                                disabled={false} +                              />                              </div>                            </div> +                            <div className='modal-footer'>                              <button                                className='btn btn-link' diff --git a/app/javascript/journey_patterns/components/EditModal.js b/app/javascript/journey_patterns/components/EditModal.js index 1960849fb..a23a57f96 100644 --- a/app/javascript/journey_patterns/components/EditModal.js +++ b/app/javascript/journey_patterns/components/EditModal.js @@ -1,19 +1,27 @@  import React, { Component } from 'react'  import PropTypes from 'prop-types'  import actions from '../actions' +import CustomFieldsInputs from '../../helpers/CustomFieldsInputs'  export default class EditModal extends Component {    constructor(props) {      super(props) +    this.updateValue = this.updateValue.bind(this)    }    handleSubmit() {      if(actions.validateFields(this.refs) == true) { -      this.props.saveModal(this.props.modal.modalProps.index, this.refs) +      this.props.saveModal(this.props.modal.modalProps.index, _.assign({}, this.refs, {custom_fields: this.custom_fields}))        $('#JourneyPatternModal').modal('hide')      }    } +  updateValue(attribute, e) { +    actions.resetValidation(e.currentTarget) +    this.props.modal.modalProps.journeyPattern[attribute] = e.target.value +    this.forceUpdate() +  } +    renderModalTitle() {      if (this.props.editMode) {        return ( @@ -28,6 +36,9 @@ export default class EditModal extends Component {    }    render() { +    if(this.props.modal.modalProps.journeyPattern){ +      this.custom_fields = _.assign({}, this.props.modal.modalProps.journeyPattern.custom_fields) +    }      return (        <div className={ 'modal fade ' + ((this.props.modal.type == 'edit') ? 'in' : '') } id='JourneyPatternModal'>          <div className='modal-container'> @@ -48,8 +59,8 @@ export default class EditModal extends Component {                          className='form-control'                          disabled={!this.props.editMode}                          id={this.props.modal.modalProps.index} -                        defaultValue={this.props.modal.modalProps.journeyPattern.name} -                        onKeyDown={(e) => actions.resetValidation(e.currentTarget)} +                        value={this.props.modal.modalProps.journeyPattern.name} +                        onChange={(e) => this.updateValue('name', e)}                          required                          />                      </div> @@ -64,8 +75,8 @@ export default class EditModal extends Component {                              className='form-control'                              disabled={!this.props.editMode}                              id={this.props.modal.modalProps.index} -                            defaultValue={this.props.modal.modalProps.journeyPattern.published_name} -                            onKeyDown={(e) => actions.resetValidation(e.currentTarget)} +                            value={this.props.modal.modalProps.journeyPattern.published_name} +                            onChange={(e) => this.updateValue('published_name', e)}                              required                              />                          </div> @@ -79,12 +90,19 @@ export default class EditModal extends Component {                              className='form-control'                              disabled={!this.props.editMode}                              id={this.props.modal.modalProps.index} -                            defaultValue={this.props.modal.modalProps.journeyPattern.registration_number} -                            onKeyDown={(e) => actions.resetValidation(e.currentTarget)} +                            value={this.props.modal.modalProps.journeyPattern.registration_number} +                            onChange={(e) => this.updateValue('registration_number', e)}                              />                          </div>                        </div>                      </div> +                    <div className='row'> +                      <CustomFieldsInputs +                        values={this.props.modal.modalProps.journeyPattern.custom_fields} +                        onUpdate={(code, value) => this.custom_fields[code]["value"] = value} +                        disabled={!this.props.editMode} +                      /> +                    </div>                      <div>                        <label className='control-label'>{I18n.attribute_name('journey_pattern', 'checksum')}</label>                          <input @@ -92,7 +110,7 @@ export default class EditModal extends Component {                          ref='checksum'                          className='form-control'                          disabled='disabled' -                        defaultValue={this.props.modal.modalProps.journeyPattern.checksum} +                        value={this.props.modal.modalProps.journeyPattern.checksum}                          />                      </div>                    </div> diff --git a/app/javascript/journey_patterns/containers/AddJourneyPattern.js b/app/javascript/journey_patterns/containers/AddJourneyPattern.js index b093fd111..9e85afd5e 100644 --- a/app/javascript/journey_patterns/containers/AddJourneyPattern.js +++ b/app/javascript/journey_patterns/containers/AddJourneyPattern.js @@ -7,7 +7,8 @@ const mapStateToProps = (state) => {      modal: state.modal,      journeyPatterns: state.journeyPatterns,      editMode: state.editMode, -    status: state.status +    status: state.status, +    custom_fields: state.custom_fields    }  } diff --git a/app/javascript/journey_patterns/containers/Modal.js b/app/javascript/journey_patterns/containers/Modal.js index 33ee8583c..fc04843e4 100644 --- a/app/javascript/journey_patterns/containers/Modal.js +++ b/app/javascript/journey_patterns/containers/Modal.js @@ -7,7 +7,8 @@ const mapStateToProps = (state) => {    return {      editMode: state.editMode,      modal: state.modal, -    journeyPattern: state.journeyPattern +    journeyPattern: state.journeyPattern, +    custom_fields: state.custom_fields,    }  } diff --git a/app/javascript/journey_patterns/reducers/index.js b/app/javascript/journey_patterns/reducers/index.js index 2ffaf86d4..d3a1d29a2 100644 --- a/app/javascript/journey_patterns/reducers/index.js +++ b/app/javascript/journey_patterns/reducers/index.js @@ -12,7 +12,8 @@ const journeyPatternsApp = combineReducers({    journeyPatterns,    pagination,    stopPointsList, -  modal +  modal, +  custom_fields: (state = [], action) => state  })  export default journeyPatternsApp diff --git a/app/javascript/journey_patterns/reducers/journeyPatterns.js b/app/javascript/journey_patterns/reducers/journeyPatterns.js index b046f2b38..1a6a27da6 100644 --- a/app/javascript/journey_patterns/reducers/journeyPatterns.js +++ b/app/javascript/journey_patterns/reducers/journeyPatterns.js @@ -103,7 +103,8 @@ export default function journeyPatterns (state = [], action)  {            return _.assign({}, j, {              name: action.data.name.value,              published_name: action.data.published_name.value, -            registration_number: action.data.registration_number.value +            registration_number: action.data.registration_number.value, +            custom_fields: action.data.custom_fields,            })          } else {            return j diff --git a/app/javascript/packs/calendars/edit.js b/app/javascript/packs/calendars/edit.js index bd09657ec..0c46313b9 100644 --- a/app/javascript/packs/calendars/edit.js +++ b/app/javascript/packs/calendars/edit.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import React from 'react'  import { render } from 'react-dom'  import { Provider } from 'react-redux' diff --git a/app/javascript/packs/exports/new.js b/app/javascript/packs/exports/new.js index ffe702cdb..b113cc709 100644 --- a/app/javascript/packs/exports/new.js +++ b/app/javascript/packs/exports/new.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import MasterSlave from "../../helpers/master_slave"  new MasterSlave("form") diff --git a/app/javascript/packs/journey_patterns/index.js b/app/javascript/packs/journey_patterns/index.js index 367a8830f..bd7df2634 100644 --- a/app/javascript/packs/journey_patterns/index.js +++ b/app/javascript/packs/journey_patterns/index.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import React from 'react'  import { render } from 'react-dom'  import { Provider } from 'react-redux' @@ -32,7 +34,8 @@ var initialState = {      type: '',      modalProps: {},      confirmModal: {} -  } +  }, +  custom_fields: window.custom_fields  }  // const loggerMiddleware = createLogger() diff --git a/app/javascript/packs/referential_lines/show.js b/app/javascript/packs/referential_lines/show.js index 99c5072ef..523f2040f 100644 --- a/app/javascript/packs/referential_lines/show.js +++ b/app/javascript/packs/referential_lines/show.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import clone from '../../helpers/clone'  import RoutesMap from '../../helpers/routes_map' diff --git a/app/javascript/packs/referential_overview/overview.js b/app/javascript/packs/referential_overview/overview.js index 59c326e9a..03da12ef3 100644 --- a/app/javascript/packs/referential_overview/overview.js +++ b/app/javascript/packs/referential_overview/overview.js @@ -1 +1,3 @@ +import '../../helpers/polyfills' +  import ReferentialOverview from '../../referential_overview' diff --git a/app/javascript/packs/routes/edit.js b/app/javascript/packs/routes/edit.js index fc7aa203d..0512b7aff 100644 --- a/app/javascript/packs/routes/edit.js +++ b/app/javascript/packs/routes/edit.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import React from 'react'  import PropTypes from 'prop-types' @@ -56,12 +58,25 @@ const getInitialState = () => {  }  var initialState = { stopPoints: getInitialState() } -const loggerMiddleware = createLogger() -let store = createStore( -  reducers, -  initialState, -  applyMiddleware(thunkMiddleware, promise, loggerMiddleware) -) +let store = null + +if(Object.assign){ +  const loggerMiddleware = createLogger() +  store = createStore( +   reducers, +   initialState, +   applyMiddleware(thunkMiddleware, promise, loggerMiddleware) + ) +} +else{ +  // IE +  store = createStore( +   reducers, +   initialState, +   applyMiddleware(thunkMiddleware, promise) + ) +} +  render(    <Provider store={store}> diff --git a/app/javascript/packs/routes/show.js b/app/javascript/packs/routes/show.js index c20de0800..e8e068ddd 100644 --- a/app/javascript/packs/routes/show.js +++ b/app/javascript/packs/routes/show.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import clone from '../../helpers/clone'  import RoutesMap from '../../helpers/routes_map' diff --git a/app/javascript/packs/stop_areas/new.js b/app/javascript/packs/stop_areas/new.js index ffe702cdb..b113cc709 100644 --- a/app/javascript/packs/stop_areas/new.js +++ b/app/javascript/packs/stop_areas/new.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import MasterSlave from "../../helpers/master_slave"  new MasterSlave("form") diff --git a/app/javascript/packs/time_tables/edit.js b/app/javascript/packs/time_tables/edit.js index cf058d501..873bdea50 100644 --- a/app/javascript/packs/time_tables/edit.js +++ b/app/javascript/packs/time_tables/edit.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import React from 'react'  import { render } from 'react-dom'  import { Provider } from 'react-redux' diff --git a/app/javascript/packs/vehicle_journeys/index.js b/app/javascript/packs/vehicle_journeys/index.js index 9cad3870e..0b4351d26 100644 --- a/app/javascript/packs/vehicle_journeys/index.js +++ b/app/javascript/packs/vehicle_journeys/index.js @@ -1,3 +1,5 @@ +import '../../helpers/polyfills' +  import React from 'react'  import { render } from 'react-dom'  import { Provider } from 'react-redux' diff --git a/app/javascript/routes/actions/index.js b/app/javascript/routes/actions/index.js index 5fbf5bce9..13b2d60b2 100644 --- a/app/javascript/routes/actions/index.js +++ b/app/javascript/routes/actions/index.js @@ -56,12 +56,7 @@ const actions = {    unselectMarker: (index) => ({      type: 'UNSELECT_MARKER',      index -  }), -  defaultAttribute: (attribute, stopAreaKind) => { -    if (attribute !== '') return attribute -    if (stopAreaKind === undefined) return '' -    return stopAreaKind === "commercial" ? "normal" : "forbidden"  -  }  +  })  }  module.exports = actions diff --git a/app/javascript/routes/components/App.js b/app/javascript/routes/components/App.js index 26e69bf53..6f8cdf749 100644 --- a/app/javascript/routes/components/App.js +++ b/app/javascript/routes/components/App.js @@ -3,14 +3,9 @@ import PropTypes from 'prop-types'  import AddStopPoint from '../containers/AddStopPoint'  import VisibleStopPoints from'../containers/VisibleStopPoints'  import clone  from '../../helpers/clone' -const I18n = clone(window , "I18n", true)  export default class App extends Component { -  getChildContext() { -    return { I18n } -  } -    render() {      return (        <div> @@ -20,7 +15,3 @@ export default class App extends Component {      )    }  } - -App.childContextTypes = { -  I18n: PropTypes.object -} diff --git a/app/javascript/routes/components/BSelect2.js b/app/javascript/routes/components/BSelect2.js index 89e1b6cfa..90f288944 100644 --- a/app/javascript/routes/components/BSelect2.js +++ b/app/javascript/routes/components/BSelect2.js @@ -10,8 +10,8 @@ var path = window.location.pathname.split('/', 3).join('/')  export default class BSelect3 extends Component { -  constructor(props, context) { -    super(props, context) +  constructor(props) { +    super(props)    }    onChange(e) {      this.props.onChange(this.props.index, { @@ -86,7 +86,7 @@ class BSelect2 extends Component{          onSelect={ this.props.onSelect }          ref='newSelect'          options={{ -          placeholder: this.context.I18n.t("routes.edit.select2.placeholder"), +          placeholder: I18n.t("routes.edit.select2.placeholder"),            allowClear: true,            language: 'fr', /* Doesn't seem to work... :( */            theme: 'bootstrap', @@ -129,8 +129,4 @@ class BSelect2 extends Component{        />      )    } -} - -BSelect2.contextTypes = { -  I18n: PropTypes.object -} +}
\ No newline at end of file diff --git a/app/javascript/routes/components/OlMap.js b/app/javascript/routes/components/OlMap.js index 4beb02872..16fec0e87 100644 --- a/app/javascript/routes/components/OlMap.js +++ b/app/javascript/routes/components/OlMap.js @@ -3,8 +3,8 @@ import React, { Component } from 'react'  import PropTypes from 'prop-types'  export default class OlMap extends Component{ -  constructor(props, context){ -    super(props, context) +  constructor(props){ +    super(props)    }    fetchApiURL(id){ @@ -115,40 +115,40 @@ export default class OlMap extends Component{                <strong>{this.props.value.olMap.json.name}</strong>              </p>              <p> -              <strong>{this.context.I18n.t('routes.edit.map.stop_point_type')} : </strong> +              <strong>{I18n.t('routes.edit.map.stop_point_type')} : </strong>                {this.props.value.olMap.json.area_type}              </p>              <p> -              <strong>{this.context.I18n.t('routes.edit.map.short_name')} : </strong> +              <strong>{I18n.t('routes.edit.map.short_name')} : </strong>                {this.props.value.olMap.json.short_name}              </p>              <p> -              <strong>{this.context.I18n.t('id_reflex')} : </strong> +              <strong>{I18n.t('id_reflex')} : </strong>                {this.props.value.olMap.json.user_objectid}              </p> -            <p><strong>{this.context.I18n.t('routes.edit.map.coordinates')} : </strong></p> +            <p><strong>{I18n.t('routes.edit.map.coordinates')} : </strong></p>              <p style={{paddingLeft: 10, marginTop: 0}}> -              <em>{this.context.I18n.t('routes.edit.map.proj')}.: </em>WSG84<br/> -              <em>{this.context.I18n.t('routes.edit.map.lat')}.: </em>{this.props.value.olMap.json.latitude} <br/> -              <em>{this.context.I18n.t('routes.edit.map.lon')}.: </em>{this.props.value.olMap.json.longitude} +              <em>{I18n.t('routes.edit.map.proj')}.: </em>WSG84<br/> +              <em>{I18n.t('routes.edit.map.lat')}.: </em>{this.props.value.olMap.json.latitude} <br/> +              <em>{I18n.t('routes.edit.map.lon')}.: </em>{this.props.value.olMap.json.longitude}              </p>              <p> -              <strong>{this.context.I18n.t('routes.edit.map.postal_code')} : </strong> +              <strong>{I18n.t('routes.edit.map.postal_code')} : </strong>                {this.props.value.olMap.json.zip_code}              </p>              <p> -              <strong>{this.context.I18n.t('routes.edit.map.city')} : </strong> +              <strong>{I18n.t('routes.edit.map.city')} : </strong>                {this.props.value.olMap.json.city_name}              </p>              <p> -              <strong>{this.context.I18n.t('routes.edit.map.comment')} : </strong> +              <strong>{I18n.t('routes.edit.map.comment')} : </strong>                {this.props.value.olMap.json.comment}              </p>              {(this.props.value.stoparea_id != this.props.value.olMap.json.stoparea_id) &&(                <div className='btn btn-outline-primary btn-sm'                  onClick= {() => {this.props.onUpdateViaOlMap(this.props.index, this.props.value.olMap.json)}} -              >{this.context.I18n.t('actions.select')}</div> +              >{I18n.t('actions.select')}</div>              )}            </div>              <div className='map_content'> @@ -164,7 +164,3 @@ export default class OlMap extends Component{  OlMap.propTypes = {  } - -OlMap.contextTypes = { -  I18n: PropTypes.object -} diff --git a/app/javascript/routes/components/StopPoint.js b/app/javascript/routes/components/StopPoint.js index 768d069c0..916052b42 100644 --- a/app/javascript/routes/components/StopPoint.js +++ b/app/javascript/routes/components/StopPoint.js @@ -6,7 +6,7 @@ import OlMap from './OlMap'  import { defaultAttribute } from '../actions' -export default function StopPoint(props, {I18n}) { +export default function StopPoint(props) {    return (      <div className='nested-fields'>        <div className='wrapper'> @@ -19,14 +19,14 @@ export default function StopPoint(props, {I18n}) {          </div>          <div> -          <select className='form-control' value={defaultAttribute(props.value.for_boarding, props.value.stoparea_kind)} id="for_boarding" onChange={props.onSelectChange}> +          <select className='form-control' value={props.value.for_boarding} id="for_boarding" onChange={props.onSelectChange}>              <option value="normal">{I18n.t('routes.edit.stop_point.boarding.normal')}</option>              <option value="forbidden">{I18n.t('routes.edit.stop_point.boarding.forbidden')}</option>            </select>          </div>          <div> -          <select className='form-control' value={defaultAttribute(props.value.for_alighting, props.value.stoparea_kind)} id="for_alighting" onChange={props.onSelectChange}> +          <select className='form-control' value={props.value.for_alighting} id="for_alighting" onChange={props.onSelectChange}>              <option value="normal">{I18n.t('routes.edit.stop_point.alighting.normal')}</option>              <option value="forbidden">{I18n.t('routes.edit.stop_point.alighting.forbidden')}</option>            </select> @@ -92,7 +92,3 @@ StopPoint.propTypes = {    index: PropTypes.number,    value: PropTypes.object  } - -StopPoint.contextTypes = { -  I18n: PropTypes.object -} diff --git a/app/javascript/routes/components/StopPointList.js b/app/javascript/routes/components/StopPointList.js index b227abdea..9bc5e02d1 100644 --- a/app/javascript/routes/components/StopPointList.js +++ b/app/javascript/routes/components/StopPointList.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'  import StopPoint from './StopPoint' -export default function StopPointList({ stopPoints, onDeleteClick, onMoveUpClick, onMoveDownClick, onChange, onSelectChange, onToggleMap, onToggleEdit, onSelectMarker, onUnselectMarker, onUpdateViaOlMap }, {I18n}) { +export default function StopPointList({ stopPoints, onDeleteClick, onMoveUpClick, onMoveDownClick, onChange, onSelectChange, onToggleMap, onToggleEdit, onSelectMarker, onUnselectMarker, onUpdateViaOlMap }) {    return (      <div className='subform'>        <div className='nested-head'> diff --git a/app/javascript/routes/containers/AddStopPoint.js b/app/javascript/routes/containers/AddStopPoint.js index fd9227ff3..4b169807d 100644 --- a/app/javascript/routes/containers/AddStopPoint.js +++ b/app/javascript/routes/containers/AddStopPoint.js @@ -11,7 +11,7 @@ let AddStopPoint = ({ dispatch }) => {          dispatch(actions.addStop())        }}>          <button type="submit" className="btn btn-outline-primary"> -          Ajouter un arrêt +          {I18n.t('stop_areas.actions.new')}          </button>        </form>      </div> diff --git a/app/javascript/routes/index.js b/app/javascript/routes/index.js index 3c7322953..fc99a3086 100644 --- a/app/javascript/routes/index.js +++ b/app/javascript/routes/index.js @@ -22,6 +22,7 @@ const getInitialState = () => {      let fancyText = v.name.replace("'", "\'")      if(v.zip_code && v.city_name)        fancyText += ", " + v.zip_code + " " + v.city_name.replace("'", "\'") +      forAlightingAndBoarding = v.stoparea_kind === 'commercial' ? 'normal' : 'forbidden'      state.push({        stoppoint_id: v.stoppoint_id, @@ -37,8 +38,8 @@ const getInitialState = () => {        name: v.name ? v.name.replace("'", "\'") : '',        registration_number: v.registration_number,        text: fancyText, -      for_boarding: v.for_boarding || '', -      for_alighting: v.for_alighting || '', +      for_boarding: v.for_boarding || forAlightingAndBoarding, +      for_alighting: v.for_alighting || forAlightingAndBoarding,        longitude: v.longitude || 0,        latitude: v.latitude || 0,        comment: v.comment ? v.comment.replace("'", "\'") : '', diff --git a/app/javascript/routes/reducers/stopPoints.js b/app/javascript/routes/reducers/stopPoints.js index ba183d002..54142338d 100644 --- a/app/javascript/routes/reducers/stopPoints.js +++ b/app/javascript/routes/reducers/stopPoints.js @@ -8,8 +8,8 @@ const stopPoint = (state = {}, action, length) => {          text: '',          index: length,          edit: true, -        for_boarding: '', -        for_alighting: '', +        for_boarding: 'normal', +        for_alighting: 'normal',          olMap: {            isOpened: false,            json: {} @@ -61,6 +61,7 @@ const stopPoints = (state = [], action) => {      case 'UPDATE_INPUT_VALUE':        return state.map( (t, i) => {          if (i === action.index) { +          let forAlightingAndBoarding = action.text.stoparea_kind === 'commercial' ? 'normal' : 'forbidden'            return _.assign(              {},              t, @@ -77,7 +78,9 @@ const stopPoints = (state = [], action) => {                area_type: action.text.area_type,                city_name: action.text.city_name,                comment: action.text.comment, -              registration_number: action.text.registration_number +              registration_number: action.text.registration_number, +              for_alighting: forAlightingAndBoarding, +              for_boarding: forAlightingAndBoarding              }            )          } else { diff --git a/app/javascript/time_tables/actions/index.js b/app/javascript/time_tables/actions/index.js index b56279889..283897b63 100644 --- a/app/javascript/time_tables/actions/index.js +++ b/app/javascript/time_tables/actions/index.js @@ -190,10 +190,13 @@ const actions = {    isInPeriod: (periods, date) => {      date = new Date(date) -    for (let period of periods) { +    let i = 0; +    while(i < periods.length){ +      let period = periods[i]        let begin = new Date(period.period_start)        let end = new Date(period.period_end)        if (date >= begin && date <= end) return true +      i++      }      return false @@ -234,12 +237,14 @@ const actions = {      let error = ''      start = new Date(start)      end = new Date(end) - -    for (let day of in_days) { +    let i = 0; +    while(i < in_days){ +      let day = in_days[i]        if (start <= new Date(day.date) && end >= new Date(day.date)) {          error = I18n.t('time_tables.edit.error_submit.dates_overlaps')          break        } +      i ++      }      return error    }, diff --git a/app/javascript/time_tables/components/Metas.js b/app/javascript/time_tables/components/Metas.js index d9746a379..186af540a 100644 --- a/app/javascript/time_tables/components/Metas.js +++ b/app/javascript/time_tables/components/Metas.js @@ -76,7 +76,6 @@ export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdat              <label htmlFor="" className="control-label col-sm-4">{I18n.attribute_name('time_table', 'tag_list')}</label>              <div className="col-sm-8">                <TagsSelect2 -                initialTags={metas.initial_tags}                  tags={metas.tags}                  onSelect2Tags={(e) => onSelect2Tags(e)}                  onUnselect2Tags={(e) => onUnselect2Tags(e)} diff --git a/app/javascript/time_tables/components/TagsSelect2.js b/app/javascript/time_tables/components/TagsSelect2.js index dd8d6e9c0..fe610ed58 100644 --- a/app/javascript/time_tables/components/TagsSelect2.js +++ b/app/javascript/time_tables/components/TagsSelect2.js @@ -27,7 +27,7 @@ export default class TagsSelect2 extends Component {      return (        <Select2          value={(this.props.tags.length) ? map(this.props.tags, 'id') : undefined} -        data={(this.props.initialTags.length) ? this.mapKeys(this.props.initialTags) : undefined} +        data={(this.props.tags.length) ? this.mapKeys(this.props.tags) : undefined}          onSelect={(e) => this.props.onSelect2Tags(e)}          onUnselect={(e) => setTimeout( () => this.props.onUnselect2Tags(e, 150))}          multiple={true} @@ -74,4 +74,4 @@ export default class TagsSelect2 extends Component {  const formatRepo = (props) => {    if(props.name) return props.name -}
\ No newline at end of file +} diff --git a/app/javascript/time_tables/containers/Metas.js b/app/javascript/time_tables/containers/Metas.js index ebccf556e..7bc3ef4e1 100644 --- a/app/javascript/time_tables/containers/Metas.js +++ b/app/javascript/time_tables/containers/Metas.js @@ -24,6 +24,7 @@ const mapDispatchToProps = (dispatch) => {      },      onSelect2Tags: (e) => {        e.preventDefault() +      $(e.target).find('[data-select2-tag]').remove()        dispatch(actions.select2Tags(e.params.data))      },      onUnselect2Tags: (e) => { diff --git a/app/javascript/time_tables/reducers/metas.js b/app/javascript/time_tables/reducers/metas.js index 51e1ec149..012f29511 100644 --- a/app/javascript/time_tables/reducers/metas.js +++ b/app/javascript/time_tables/reducers/metas.js @@ -31,11 +31,13 @@ export default function metas(state = {}, action) {        return assign({}, state, {color: action.color})      case 'UPDATE_SELECT_TAG':        let tags = [...state.tags] -      tags.push(action.selectedItem) +      if(tags.length == 0 || tags[tags.length-1].name != action.selectedItem.name){ +        tags.push(action.selectedItem) +      }        return assign({}, state, {tags: tags})      case 'UPDATE_UNSELECT_TAG':        return assign({}, state, {tags: filter(state.tags, (t) => (t.id != action.selectedItem.id))})      default:        return state    } -}
\ No newline at end of file +} diff --git a/app/javascript/vehicle_journeys/actions/index.js b/app/javascript/vehicle_journeys/actions/index.js index 537dcfc06..c67f9f0cf 100644 --- a/app/javascript/vehicle_journeys/actions/index.js +++ b/app/javascript/vehicle_journeys/actions/index.js @@ -1,9 +1,3 @@ -import Promise from 'promise-polyfill' - -// To add to window -if (!window.Promise) { -  window.Promise = Promise; -}  import { batchActions } from '../batch'  const actions = { @@ -54,16 +48,10 @@ const actions = {    }),    selectJPCreateModal : (selectedJP) => ({      type : 'SELECT_JP_CREATE_MODAL', -    selectedItem: { -      id: selectedJP.id, +    selectedItem: _.assign({}, selectedJP, {        objectid: selectedJP.object_id, -      short_id: selectedJP.short_id, -      name: selectedJP.name, -      published_name: selectedJP.published_name, -      stop_areas: selectedJP.stop_area_short_descriptions, -      costs: selectedJP.costs, -      full_schedule: selectedJP.full_schedule -    } +      stop_areas: selectedJP.stop_area_short_descriptions +    })    }),    openEditModal : (vehicleJourney) => ({      type : 'EDIT_VEHICLEJOURNEY_MODAL', @@ -109,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 @@ -339,16 +347,23 @@ const actions = {          if(hasError == true) {            dispatch(actions.unavailableServer())          } else { -          let val -          for (val of json.vehicle_journeys){ +          let i = 0 +          while(i < json.vehicle_journeys.length){ +            let val = json.vehicle_journeys[i] +            i++              var timeTables = []              var purchaseWindows = [] -            let tt -            for (tt of val.time_tables){ +            let k = 0 +            while(k < val.time_tables.length){ +              let tt = val.time_tables[k] +              k++                timeTables.push(tt)              }              if(val.purchase_windows){ -              for (tt of val.purchase_windows){ +              k = 0 +              while(k < val.purchase_windows.length){ +                let tt = val.purchase_windows[k] +                k++                  purchaseWindows.push(tt)                }              } diff --git a/app/javascript/vehicle_journeys/components/Filters.js b/app/javascript/vehicle_journeys/components/Filters.js index 93fe015a8..1e43a490e 100644 --- a/app/javascript/vehicle_journeys/components/Filters.js +++ b/app/javascript/vehicle_journeys/components/Filters.js @@ -33,6 +33,7 @@ export default function Filters({filters, pagination, missions, onFilter, onRese              {/* Calendriers */}              <div className='form-group w33'>                <TimetableSelect2 +                placeholder={I18n.t('vehicle_journeys.vehicle_journeys_matrix.filters.timetable')}                  onSelect2Timetable={onSelect2Timetable}                  hasRoute={true}                  chunkURL={("/autocomplete_time_tables.json?route_id=" + String(window.route_id))} diff --git a/app/javascript/vehicle_journeys/components/Tools.js b/app/javascript/vehicle_journeys/components/Tools.js index 22ea44283..41a521d12 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 { @@ -35,11 +36,13 @@ export default class Tools extends Component {            <AddVehicleJourney disabled={!this.hasPolicy("create") || !editMode} />            <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")}/> +          <EditVehicleJourney disabled={false}/> + +          <TimetablesEditVehicleJourney disabled={false}/>            { this.hasFeature('purchase_windows') && -            <PurchaseWindowsEditVehicleJourney disabled={!this.hasPolicy("update")}/> +            <PurchaseWindowsEditVehicleJourney disabled={false}/>            } +          <ConstraintExclusionEditVehicleJourney disabled={false}/>            <NotesEditVehicleJourney disabled={!this.hasPolicy("update")}/>            <DeleteVehicleJourneys disabled={!this.hasPolicy("destroy") || !editMode}/>          </ul> diff --git a/app/javascript/vehicle_journeys/components/VehicleJourney.js b/app/javascript/vehicle_journeys/components/VehicleJourney.js index 73d99d120..f7ae9341f 100644 --- a/app/javascript/vehicle_journeys/components/VehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/VehicleJourney.js @@ -10,6 +10,10 @@ export default class VehicleJourney extends Component {      this.previousCity = undefined    } +  journey_length() { +    return this.props.value.journey_pattern.journey_length + "km" +  } +    cityNameChecker(sp) {      return this.props.vehicleJourneys.showHeader(sp.stop_point_objectid)    } @@ -107,7 +111,21 @@ export default class VehicleJourney extends Component {            }            >            <div className='strong mb-xs'>{this.props.value.short_id || '-'}</div> -          <div>{this.props.value.published_journey_name && this.props.value.published_journey_name != I18n.t('undefined') ? this.props.value.published_journey_name : '-'}</div> +          <div> +            <a href="#" +              onClick={(e) => { +                if(this.props.disabled){ return } +                e.stopPropagation(true) +                e.preventDefault() +                this.props.onOpenInfoModal(this.props.value) +                $('#EditVehicleJourneyModal').modal('show') +                false +                } +              } +            > +              {this.props.value.published_journey_name && this.props.value.published_journey_name != I18n.t('undefined') ? this.props.value.published_journey_name : '-'} +            </a> +          </div>            <div>{this.props.value.journey_pattern.short_id || '-'}</div>            <div>{this.props.value.company ? this.props.value.company.name : '-'}</div>            { @@ -115,6 +133,11 @@ export default class VehicleJourney extends Component {                <div key={i}>{this.extraHeaderValue(header)}</div>              )            } +          { this.hasFeature('journey_length_in_vehicle_journeys') && +            <div> +              {this.journey_length()} +            </div> +          }            { this.hasFeature('purchase_windows') &&              <div>              {purchase_windows.slice(0,3).map((tt, i)=> diff --git a/app/javascript/vehicle_journeys/components/VehicleJourneys.js b/app/javascript/vehicle_journeys/components/VehicleJourneys.js index c6f59ce9d..0bb00e1ea 100644 --- a/app/javascript/vehicle_journeys/components/VehicleJourneys.js +++ b/app/javascript/vehicle_journeys/components/VehicleJourneys.js @@ -87,16 +87,18 @@ export default class VehicleJourneys extends Component {    }    toggleTimetables(e) { -    $('.table-2entries .detailed-timetables').toggleClass('hidden') -    $('.table-2entries .detailed-timetables-bt').toggleClass('active') +    let root = $(this.refs['vehicleJourneys']) +    root.find('.table-2entries .detailed-timetables').toggleClass('hidden') +    root.find('.table-2entries .detailed-timetables-bt').toggleClass('active')      this.componentDidUpdate()      e.preventDefault()      false    }    togglePurchaseWindows(e) { -    $('.table-2entries .detailed-purchase-windows').toggleClass('hidden') -    $('.table-2entries .detailed-purchase-windows-bt').toggleClass('active') +    let root = $(this.refs['vehicleJourneys']) +    root.find('.table-2entries .detailed-purchase-windows').toggleClass('hidden') +    root.find('.table-2entries .detailed-purchase-windows-bt').toggleClass('active')      this.componentDidUpdate()      e.preventDefault()      false @@ -186,7 +188,7 @@ export default class VehicleJourneys extends Component {        )      } else {        return ( -        <div className='row'> +        <div className='row' ref='vehicleJourneys'>            <div className='col-lg-12'>              {(this.props.status.fetchSuccess == false) && (                <div className='alert alert-danger mt-sm'> @@ -222,6 +224,11 @@ export default class VehicleJourneys extends Component {                        <div key={i}>{this.extraHeaderLabel(header)}</div>                      )                    } +                  { this.hasFeature('journey_length_in_vehicle_journeys') && +                    <div> +                    {I18n.attribute_name("vehicle_journey", "journey_length")} +                    </div> +                  }                    { this.hasFeature('purchase_windows') &&                      <div>                        { detailed_purchase_windows && @@ -288,6 +295,7 @@ export default class VehicleJourneys extends Component {                        features={this.props.features}                        onUpdateTime={this.props.onUpdateTime}                        onSelectVehicleJourney={this.props.onSelectVehicleJourney} +                      onOpenInfoModal={this.props.onOpenInfoModal}                        vehicleJourneys={this}                        disabled={this.isReturn()}                        allTimeTables={this.allTimeTables()} 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/CreateModal.js b/app/javascript/vehicle_journeys/components/tools/CreateModal.js index f49b51f08..2806708f4 100644 --- a/app/javascript/vehicle_journeys/components/tools/CreateModal.js +++ b/app/javascript/vehicle_journeys/components/tools/CreateModal.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'  import actions from '../../actions'  import MissionSelect2 from './select2s/MissionSelect2'  import CompanySelect2 from './select2s/CompanySelect2' -import CustomFieldsInputs from './CustomFieldsInputs' +import CustomFieldsInputs from '../../../helpers/CustomFieldsInputs'  export default class CreateModal extends Component {    constructor(props) { @@ -14,7 +14,8 @@ export default class CreateModal extends Component {    handleSubmit() {      if(!this.props.modal.modalProps.selectedJPModal){        let field = $('#NewVehicleJourneyModal').find(".vjCreateSelectJP") -      field.parent().parent().addClass('has-error').children('.help-block').remove() +      field.parent().parent().addClass('has-error') +      field.parent().children('.help-block').remove()        field.parent().append("<span class='small help-block'>" + I18n.t("simple_form.required.text") + "</span>")        return      } diff --git a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js index e4e266c79..60d982845 100644 --- a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'  import PropTypes from 'prop-types'  import actions from '../../actions'  import CompanySelect2 from './select2s/CompanySelect2' -import CustomFieldsInputs from './CustomFieldsInputs' +import CustomFieldsInputs from '../../../helpers/CustomFieldsInputs'  export default class EditVehicleJourney extends Component {    constructor(props) { diff --git a/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js index 5d300f70c..ef58916f4 100644 --- a/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js @@ -31,13 +31,13 @@ export default class NotesEditVehicleJourney extends Component {          type='button'          className='btn btn-outline-danger btn-xs'          onClick={() => this.props.onToggleFootnoteModal(lf, false)} -      ><span className="fa fa-trash"></span> Retirer</button> +      ><span className="fa fa-trash"></span>{I18n.t('actions.remove')}</button>      } else {        return <button          type='button'          className='btn btn-outline-primary btn-xs'          onClick={() => this.props.onToggleFootnoteModal(lf, true)} -      ><span className="fa fa-plus"></span> Ajouter</button> +      ><span className="fa fa-plus"></span>{I18n.t('actions.add')}</button>      }    } diff --git a/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js index 30c511302..5fc925f4c 100644 --- a/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js @@ -44,7 +44,7 @@ export default class PurchaseWindowsEditVehicleJourney extends Component {                <div className='modal-dialog'>                  <div className='modal-content'>                    <div className='modal-header'> -                    <h4 className='modal-title'>{I18n.t('vehicle_journeys.form.purchase_windows')}s</h4> +                    <h4 className='modal-title'>{I18n.t('vehicle_journeys.form.purchase_windows')}</h4>                      <span type="button" className="close modal-close" data-dismiss="modal">×</span>                    </div> @@ -95,6 +95,7 @@ export default class PurchaseWindowsEditVehicleJourney extends Component {                                    <div className='wrapper'>                                      <div>                                        <TimetableSelect2 +                                        placeholder={I18n.t('vehicle_journeys.vehicle_journeys_matrix.filters.purchase_window')}                                          onSelect2Timetable={this.props.onSelect2Timetable}                                          chunkURL={'/autocomplete_purchase_windows.json'}                                          searchKey={"name_or_objectid_cont_any"} diff --git a/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js index 9ee2e1849..594140c76 100644 --- a/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js @@ -97,6 +97,7 @@ export default class TimetablesEditVehicleJourney extends Component {                                    <div className='wrapper'>                                      <div>                                        <TimetableSelect2 +                                        placeholder={I18n.t('vehicle_journeys.vehicle_journeys_matrix.filters.timetable')}                                          onSelect2Timetable={this.props.onSelect2Timetable}                                          chunkURL={'/autocomplete_time_tables.json'}                                          searchKey={"unaccented_comment_or_objectid_cont_any"} 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/components/tools/select2s/TimetableSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js index d5aad20d0..919853a71 100644 --- a/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js +++ b/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js @@ -26,7 +26,7 @@ export default class BSelect4 extends Component {            allowClear: false,            theme: 'bootstrap',            width: '100%', -          placeholder: I18n.t('vehicle_journeys.vehicle_journeys_matrix.filters.timetable'), +          placeholder: this.props.placeholder,            language: require('./language'),            ajax: {              url: origin + path + this.props.chunkURL, diff --git a/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js b/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js index f21e2c87e..45b061b66 100644 --- a/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js +++ b/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js @@ -27,7 +27,10 @@ const mapDispatchToProps = (dispatch) => {      },      onSelectVehicleJourney: (index) => {        dispatch(actions.selectVehicleJourney(index)) -    } +    }, +    onOpenInfoModal: (vj) =>{ +      dispatch(actions.openInfoModal(vj)) +    },    }  } 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 bcfc6ea0b..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)) @@ -164,7 +207,9 @@ export default function modal(state = {}, action) {          confirmModal: {}        }      case 'SELECT_JP_CREATE_MODAL': -      newModalProps = _.assign({}, state.modalProps, {selectedJPModal : action.selectedItem}) +      let selected = action.selectedItem +      delete selected["element"] +      newModalProps = _.assign({}, state.modalProps, {selectedJPModal : selected})        return _.assign({}, state, {modalProps: newModalProps})      case 'SHIFT_VEHICLEJOURNEY_MODAL':        return { diff --git a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js index b02c19a69..121be6a00 100644 --- a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js +++ b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js @@ -40,6 +40,7 @@ const vehicleJourney= (state = {}, action, keep) => {            }            let offsetHours = sp.time_zone_offset / 3600            let offsetminutes = sp.time_zone_offset/60 - 60*offsetHours +            newVjas = {              delta: 0,              arrival_time:{ @@ -53,6 +54,7 @@ const vehicleJourney= (state = {}, action, keep) => {            if(sp.waiting_time && inJourney){              current_time = actions.addMinutesToTime(current_time, parseInt(sp.waiting_time)) +            newVjas.delta = parseInt(sp.waiting_time)            }            newVjas.departure_time = { @@ -96,6 +98,7 @@ const vehicleJourney= (state = {}, action, keep) => {          let lastStop = action.selectedJourneyPattern.stop_areas && action.selectedJourneyPattern.stop_areas[action.selectedJourneyPattern.stop_areas.length - 1]          if(lastStop && lastStop.stop_area_short_description.id == sp.id){            newVjas.departure_time = newVjas.arrival_time +          newVjas.delta = 0          }          if(newVjas.dummy){ @@ -116,6 +119,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 +236,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) =>{ | 
