diff options
| author | Alban Peignier | 2016-11-20 22:38:47 +0100 | 
|---|---|---|
| committer | Alban Peignier | 2016-11-20 22:38:47 +0100 | 
| commit | 85fd6480daebe50e423ba27bce772c7b7f86fbf6 (patch) | |
| tree | 04285d132e00fa82cb4786f946a605ac9f549795 | |
| parent | 7b05ae21fc9421b81fc071976f3bb98ed7c87f43 (diff) | |
| parent | 65c8a96a00f8d3afbd02cfb019b34f39ad44bc3e (diff) | |
| download | chouette-core-85fd6480daebe50e423ba27bce772c7b7f86fbf6.tar.bz2 | |
Merge branch 'master' into staging
213 files changed, 5127 insertions, 1797 deletions
| diff --git a/.gitignore b/.gitignore index 31b5d928c..4bd57ce25 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,8 @@ coverage  # IDE  .idea + +bin/ + +# Ignore node modules +/node_modules @@ -1,3 +1,4 @@ +# coding: utf-8  source 'http://rubygems.org'  # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' @@ -10,6 +11,9 @@ gem 'uglifier', '~> 2.7.2'  # Use CoffeeScript for .js.coffee assets and views  gem 'coffee-rails', '~> 4.0.0' +# ES6 powa +gem 'browserify-rails' +  # Use jquery as the JavaScript library  gem 'jquery-rails', '~> 3.1.4' # Update to v4 for Rails 4.2  # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks @@ -19,8 +23,15 @@ gem 'jbuilder', '~> 2.0'  # bundle exec rake doc:rails generates the API under doc/api.  gem 'sdoc', '~> 0.4.0', group: :doc +# Select2 for pretty select boxes w. autocomplete +gem 'select2-rails', '~> 4.0', '>= 4.0.3' +  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring  gem 'spring', group: :development +# ActiveRecord associations on top of PostgreSQL arrays +gem 'has_array_of', git: 'git@github.com:AF83/has_array_of.git' + +gem 'rails-observers'  # Use ActiveModel has_secure_password  # gem 'bcrypt', '~> 3.1.7' @@ -51,7 +62,7 @@ gem 'polylines'  # Codifligne API  gem 'codifligne', git: 'git@github.com:AF83/stif-codifline-api.git'  # Reflex API -gem 'reflex', git: 'git@github.com:AF83/stif-reflex-api.git', branch: 'sax_refactoring' +gem 'reflex', git: 'git@github.com:AF83/stif-reflex-api.git'  # Authentication  gem 'devise', '~> 3.4.0' @@ -110,7 +121,6 @@ gem 'rabl'  gem 'sidekiq'  gem 'sinatra' -gem 'delayed_job_active_record'  gem 'whenever', github: 'af83/whenever', require: false # '~> 0.9'  gem 'rake'  gem 'devise-async' @@ -123,6 +133,7 @@ gem 'letter_opener'  group :development do    gem 'capistrano', '2.13.5'    gem 'capistrano-ext' +  gem 'capistrano-npm', require: false    gem 'guard'    gem 'guard-rspec'    gem 'rails-erd' @@ -162,6 +173,8 @@ group :test, :development do    gem 'rb-fsevent', require: RUBY_PLATFORM.include?('darwin') && 'rb-fsevent'    gem 'transpec'    gem 'shoulda-matchers' +  gem "teaspoon-jasmine" +  gem "phantomjs"  end  group :production do diff --git a/Gemfile.lock b/Gemfile.lock index cda2bdf70..8ae079b8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,6 +6,15 @@ GIT        chronic (>= 0.6.3)  GIT +  remote: git@github.com:AF83/has_array_of.git +  revision: e00963f9599035ffa11bf412e6923d7ff74a32f8 +  specs: +    has_array_of (0.0.1) +      activerecord (>= 4.0) +      pg +      railties (>= 4.0) + +GIT    remote: git@github.com:AF83/stif-codifline-api.git    revision: 72d53d7666736523b5cbef41a2de7e466d58ea1a    specs: @@ -15,7 +24,6 @@ GIT  GIT    remote: git@github.com:AF83/stif-reflex-api.git    revision: 2c01010dce3a6cb39339995c373faf89ae00f3f3 -  branch: sax_refactoring    specs:      reflex (0.0.1)        nokogiri (~> 1.6) @@ -81,6 +89,8 @@ GEM      binding_of_caller (0.7.2)        debug_inspector (>= 0.0.1)      breadcrumbs_on_rails (2.3.0) +    browserify-rails (1.1.0) +      railties (>= 4.0.0, < 5.0)      builder (3.2.2)      calendar_helper (0.2.5)        open4 @@ -92,6 +102,8 @@ GEM        net-ssh-gateway (>= 1.1.0)      capistrano-ext (1.2.1)        capistrano (>= 1.0.0) +    capistrano-npm (0.0.2) +      capistrano (>= 2.5.5)      capybara (2.4.4)        mime-types (>= 1.16)        nokogiri (>= 1.3.3) @@ -140,11 +152,6 @@ GEM      debug_inspector (0.0.2)      deep_cloneable (2.0.2)        activerecord (>= 3.1.0, < 5.0.0) -    delayed_job (4.0.6) -      activesupport (>= 3.0, < 5.0) -    delayed_job_active_record (4.0.3) -      activerecord (>= 3.0, < 5.0) -      delayed_job (>= 3.0, < 4.1)      devise (3.4.1)        bcrypt (~> 3.0)        orm_adapter (~> 0.1) @@ -282,7 +289,7 @@ GEM      mime-types (2.4.3)      mimemagic (0.3.0)      mini_portile2 (2.1.0) -    minitest (5.8.3) +    minitest (5.9.1)      multi_json (1.11.2)      multi_test (0.1.2)      multipart-post (2.0.0) @@ -305,7 +312,8 @@ GEM      orm_adapter (0.5.0)      parser (2.2.0.3)        ast (>= 1.1, < 3.0) -    pg (0.18.1) +    pg (0.19.0) +    phantomjs (2.1.1.0)      poltergeist (1.6.0)        capybara (~> 2.1)        cliver (~> 0.3.1) @@ -331,7 +339,7 @@ GEM        railties (>= 3.1, < 5.0)      rabl (0.11.6)        activesupport (>= 2.3.14) -    rack (1.5.3) +    rack (1.5.5)      rack-protection (1.5.3)        rack      rack-test (0.6.3) @@ -385,13 +393,15 @@ GEM      rails-i18n (4.0.4)        i18n (~> 0.6)        railties (~> 4.0) +    rails-observers (0.1.2) +      activemodel (~> 4.0)      railties (4.1.10)        actionpack (= 4.1.10)        activesupport (= 4.1.10)        rake (>= 0.8.7)        thor (>= 0.18.1, < 2.0)      rainbow (2.0.0) -    rake (10.4.2) +    rake (11.3.0)      ransack (1.6.3)        actionpack (>= 3.0)        activerecord (>= 3.0) @@ -454,6 +464,8 @@ GEM      sdoc (0.4.1)        json (~> 1.7, >= 1.7.7)        rdoc (~> 4.0) +    select2-rails (4.0.3) +      thor (~> 0.14)      shellany (0.0.1)      shoulda-matchers (2.8.0)        activesupport (>= 3.0.0) @@ -502,6 +514,10 @@ GEM        activerecord (>= 3.0)        activesupport (>= 3.0)        polyamorous (~> 1.1.0) +    teaspoon (1.1.5) +      railties (>= 3.2.5, < 6) +    teaspoon-jasmine (2.3.4) +      teaspoon (>= 1.0.0)      temple (0.7.7)      term-ansicolor (1.3.2)        tins (~> 1.0) @@ -565,9 +581,11 @@ DEPENDENCIES    better_errors    binding_of_caller    breadcrumbs_on_rails +  browserify-rails    calendar_helper (= 0.2.5)    capistrano (= 2.13.5)    capistrano-ext +  capistrano-npm    capybara (~> 2.4.0)    cocoon    codifligne! @@ -576,7 +594,6 @@ DEPENDENCIES    daemons    database_cleaner    deep_cloneable (~> 2.0.0) -  delayed_job_active_record    devise (~> 3.4.0)    devise-async    devise-encryptable @@ -599,6 +616,7 @@ DEPENDENCIES    google-analytics-rails    guard    guard-rspec +  has_array_of!    i18n-tasks    inherited_resources    jbuilder (~> 2.0) @@ -611,6 +629,7 @@ DEPENDENCIES    mimemagic    newrelic_rpm    pg +  phantomjs    poltergeist    polylines    pry-rails @@ -632,6 +651,7 @@ DEPENDENCIES    rails-assets-typeahead.js-bootstrap3.less!    rails-erd    rails-i18n (~> 4.0.0) +  rails-observers    rake    ransack    rb-fsevent @@ -644,6 +664,7 @@ DEPENDENCIES    sass-rails (~> 4.0.3)    sawyer (~> 0.6.0)    sdoc (~> 0.4.0) +  select2-rails (~> 4.0, >= 4.0.3)    shoulda-matchers    sidekiq    simple_form (~> 3.1.0) @@ -654,6 +675,7 @@ DEPENDENCIES    spring    sqlite3    squeel +  teaspoon-jasmine    therubyracer (~> 0.12)    transpec    turbolinks @@ -664,4 +686,4 @@ DEPENDENCIES    will_paginate-bootstrap (~> 1.0.1)  BUNDLED WITH -   1.12.5 +   1.13.6 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7193d0d21..b0e100684 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,6 +12,8 @@  //= require raphael  //= require morrisjs  //= require bootstrap-sass-official +//= require select2-full +//= require select2_locale_fr  //= require typeahead.js  //= require jquery-tokeninput  //= require moment diff --git a/app/assets/javascripts/es6_browserified/actions/index.js b/app/assets/javascripts/es6_browserified/actions/index.js new file mode 100644 index 000000000..7d225f2f6 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/actions/index.js @@ -0,0 +1,42 @@ +const actions = { +  addStop : () => { +    return { +      type: 'ADD_STOP' +    } +  }, +  moveStopUp : (index) => { +    return { +      type: 'MOVE_STOP_UP', +      index +    } +  }, +  moveStopDown : (index) => { +    return { +      type: 'MOVE_STOP_DOWN', +      index +    } +  }, +  deleteStop : (index) => { +    return { +      type: 'DELETE_STOP', +      index +    } +  }, +  updateInputValue : (index, text) => { +    return { +      type : 'UPDATE_INPUT_VALUE', +      index, +      text +    } +  }, +  updateSelectValue: (e, index) => { +    return { +      type :'UPDATE_SELECT_VALUE', +      select_id: e.currentTarget.id, +      select_value: e.currentTarget.value, +      index +    } +  } +} + +module.exports = actions diff --git a/app/assets/javascripts/es6_browserified/components/App.js b/app/assets/javascripts/es6_browserified/components/App.js new file mode 100644 index 000000000..7488b0b39 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/App.js @@ -0,0 +1,12 @@ +var React = require('react') +var AddTodo = require('../containers/AddTodo') +var VisibleTodoList = require('../containers/VisibleTodoList') + +const App = () => ( +  <div> +    <AddTodo /> +    <VisibleTodoList /> +  </div> +) + +module.exports = App diff --git a/app/assets/javascripts/es6_browserified/components/BSelect2.js b/app/assets/javascripts/es6_browserified/components/BSelect2.js new file mode 100644 index 000000000..ec0d130d2 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/BSelect2.js @@ -0,0 +1,128 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +var Select2 = require('react-select2') + + +// get JSON full path +var origin = window.location.origin +var path = window.location.pathname.split('/', 3).join('/') + + +class BSelect3 extends React.Component{ +  constructor(props) { +    super(props) +    this.state = { +      edit: false +    } +  } +  onToggleEdit(e) { +    e.preventDefault() +    this.setState({edit: !this.state.edit}) +  } +  onChange(e) { +    this.props.onChange(this.props.index, { +      text: e.currentTarget.textContent, stoparea_id: e.currentTarget.value +    }) +    this.setState({edit: false}) +  } + +  render() { +    if(this.state.edit) +      return ( +        <div className='input-group select2-bootstrap-append'> +          <BSelect2 {...this.props} onSelect={ this.onChange.bind(this) }/> + +          <span className='input-group-btn'> +            <button type='button' className='btn btn-default' onClick={this.onToggleEdit.bind(this)}> +              <span className='fa fa-undo'></span> +            </button> +          </span> +        </div> +      ) +    else +      if(!this.props.value.stoparea_id) +        return ( +          <div> +            <BSelect2 {...this.props} onSelect={ this.onChange.bind(this) }/> +          </div> +        ) +      else +        return ( +          <div className='input-group'> +            <a +              className='form-control form-control-link' +              href={origin + path + '/stop_areas/' + this.props.value.stoparea_id} +              title={"Voir l'arrêt '" + this.props.value.text + "'"} +              style={{lineHeight: '22px', overflow: 'hidden'}} +            > +              {this.props.value.text} +            </a> +            <span className='input-group-btn'> +              <button type='button' className='btn btn-default' onClick={this.onToggleEdit.bind(this)}> +                <span className='fa fa-pencil'></span> +              </button> +            </span> +          </div> +        ) +  } +} + +class BSelect2 extends React.Component{ +  componentDidMount() { +    this.refs.newSelect.el.select2('open') +  } + +  render() { +    return ( +      <Select2 +        value={ this.props.value.stoparea_id } +        onSelect={ this.props.onSelect } +        ref='newSelect' +        options={{ +          placeholder: 'Sélectionnez un arrêt existant...', +          allowClear: true, +          language: 'fr', /* Doesn't seem to work... :( */ +          theme: 'bootstrap', +          width: '100%', +          ajax: { +            url: origin + path + '/autocomplete_stop_areas.json', +            dataType: 'json', +            delay: '500', +            data: function(params) { +              return { +                q: params.term +              }; +            }, +            processResults: function(data, params) { +              return { +                results: data.map( +                  item => Object.assign( +                    {}, +                    item, +                    { text: item.name + ", " + item.zip_code + " " + item.short_city_name } +                  ) +                ) +              }; +            }, +            cache: true +          }, +          minimumInputLength: 3, +          templateResult: formatRepo +        }} +      /> +    ) +  } +} + +const formatRepo = (props) => { +  if(props.text) return props.text +  // console.log(props) +  // return ( +  //   <div> +  //     {props.short_name} +  //     <small><em>{props.zip_code} {props.short_city_name}</em></small> +  //   </div> +  // ) +} + +module.exports = BSelect3 diff --git a/app/assets/javascripts/es6_browserified/components/Todo.js b/app/assets/javascripts/es6_browserified/components/Todo.js new file mode 100644 index 000000000..2a670370f --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/Todo.js @@ -0,0 +1,75 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +var BSelect2 = require('./BSelect2') + +const Todo = (props) => { +  return ( +    <div className='list-group-item'> +      <div className='row'> +        <div className='col-lg-5 col-md-5 col-sm-4 col-xs-5'> +          <div style={{display: 'inline-block', width: '20%', verticalAlign: 'middle', textAlign: 'right'}}> +            <span className='label label-default' style={{marginRight: 10}}>{props.value.stoparea_id}</span> +          </div> + +          <div style={{display: 'inline-block', width: '80%', verticalAlign: 'middle'}}> +            <BSelect2 id={'route_stop_points_' + props.id} value={props.value} onChange={props.onChange} index={props.index} /> +          </div> +        </div> + +        <div className='col-lg-2 col-md-2 col-sm-2 col-xs-2'> +          <div style={{display: 'inline-block', width: '100%', verticalAlign: 'middle'}}> +            <select className='form-control' value={props.value.for_boarding} id="for_boarding" onChange={props.onSelectChange}> +              <option value="forbidden">interdit</option> +              <option value="normal">normal</option> +            </select> +          </div> +        </div> +        <div className='col-lg-2 col-md-2 col-sm-2 col-xs-2'> +          <div style={{display: 'inline-block', width: '100%', verticalAlign: 'middle'}}> +            <select className='form-control' value={props.value.for_alighting} id="for_alighting" onChange={props.onSelectChange}> +              <option value="forbidden">interdit</option> +              <option value="normal">normal</option> +            </select> +          </div> +        </div> + +        <div className='col-lg-3 col-md-3 col-sm-4 col-xs-3' style={{textAlign: 'right'}}> +          <div className='btn-group btn-group-sm'> +            <div +              className={'btn btn-primary' + (props.first ? ' disabled' : '')} +              onClick={props.onMoveUpClick} +            > +              <span className='fa fa-arrow-up'></span> +            </div> +            <div +              className={'btn btn-primary' + (props.last ? ' disabled' : '')} +              onClick={props.onMoveDownClick} +            > +              <span className='fa fa-arrow-down'></span> +            </div> +            <div +              className='btn btn-danger' +              onClick={props.onDeleteClick} +            > +              <span className='fa fa-trash'></span> +            </div> +          </div> +        </div> +      </div> +    </div> +  ) +} + +Todo.propTypes = { +  onDeleteClick: PropTypes.func.isRequired, +  onMoveUpClick: PropTypes.func.isRequired, +  onMoveDownClick: PropTypes.func.isRequired, +  onChange: PropTypes.func.isRequired, +  onSelectChange: PropTypes.func.isRequired, +  first: PropTypes.bool, +  last: PropTypes.bool, +  index: PropTypes.number, +  value: PropTypes.object +} + +module.exports = Todo diff --git a/app/assets/javascripts/es6_browserified/components/TodoList.js b/app/assets/javascripts/es6_browserified/components/TodoList.js new file mode 100644 index 000000000..3ea2c90e1 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/TodoList.js @@ -0,0 +1,36 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +var Todo = require('./Todo') + +const TodoList = ({ todos, onDeleteClick, onMoveUpClick, onMoveDownClick, onChange, onSelectChange }) => { +  return ( +    <div className='list-group'> +      {todos.map((todo, index) => +        <Todo +          key={'item-' + index} +          onDeleteClick={() => onDeleteClick(index)} +          onMoveUpClick={() => { +            onMoveUpClick(index) +          }} +          onMoveDownClick={() => onMoveDownClick(index)} +          onChange={ onChange } +          onSelectChange={ (e) => onSelectChange(e, index) } +          first={ index === 0 } +          last={ index === (todos.length - 1) } +          index={ index } +          value={ todo } +        /> +      )} +    </div> +  ) +} + +TodoList.propTypes = { +  todos: PropTypes.array.isRequired, +  onDeleteClick: PropTypes.func.isRequired, +  onMoveUpClick: PropTypes.func.isRequired, +  onMoveDownClick: PropTypes.func.isRequired, +  onSelectChange: PropTypes.func.isRequired +} + +module.exports = TodoList diff --git a/app/assets/javascripts/es6_browserified/containers/AddTodo.js b/app/assets/javascripts/es6_browserified/containers/AddTodo.js new file mode 100644 index 000000000..d0128f16d --- /dev/null +++ b/app/assets/javascripts/es6_browserified/containers/AddTodo.js @@ -0,0 +1,22 @@ +var React = require('react') +var connect = require('react-redux').connect +var actions = require('../actions') + +let AddTodo = ({ dispatch }) => { +  return ( +    <div className="clearfix" style={{marginBottom: 10}}> +      <form onSubmit={e => { +        e.preventDefault() +        dispatch(actions.addStop()) +      }}> +        <label>Séquence d'arrêts</label> +        <button type="submit" className="btn btn-primary btn-xs pull-right"> +          <span className="fa fa-plus"></span> Ajouter un arrêt +        </button> +      </form> +    </div> +  ) +} +AddTodo = connect()(AddTodo) + +module.exports = AddTodo diff --git a/app/assets/javascripts/es6_browserified/containers/VisibleTodoList.js b/app/assets/javascripts/es6_browserified/containers/VisibleTodoList.js new file mode 100644 index 000000000..464d6e482 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/containers/VisibleTodoList.js @@ -0,0 +1,36 @@ +var actions = require('../actions') +var connect = require('react-redux').connect +var TodoList = require('../components/TodoList') + +const mapStateToProps = (state) => { +  return { +    todos: state.todos +  } +} + +const mapDispatchToProps = (dispatch) => { +  return { +    onDeleteClick: (index) =>{ +      dispatch(actions.deleteStop(index)) +    }, +    onMoveUpClick: (index) =>{ +      dispatch(actions.moveStopUp(index)) +    }, +    onMoveDownClick: (index) =>{ +      dispatch(actions.moveStopDown(index)) +    }, +    onChange: (index, text) =>{ +      dispatch(actions.updateInputValue(index, text)) +    }, +    onSelectChange: (e, index) =>{ +      dispatch(actions.updateSelectValue(e, index)) +    } +  } +} + +const VisibleTodoList = connect( +  mapStateToProps, +  mapDispatchToProps +)(TodoList) + +module.exports = VisibleTodoList diff --git a/app/assets/javascripts/es6_browserified/form_helper.js b/app/assets/javascripts/es6_browserified/form_helper.js new file mode 100644 index 000000000..d48718841 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/form_helper.js @@ -0,0 +1,10 @@ +const addInput = (name, value, index) => { +  let form = document.querySelector('form') +  let input = document.createElement('input') +  input.setAttribute('type', 'hidden') +  input.setAttribute('name', `route[stop_points_attributes][${index}][${name}]`) +  input.setAttribute('value', value) +  form.appendChild(input) +} + +module.exports = addInput diff --git a/app/assets/javascripts/es6_browserified/reducers/index.js b/app/assets/javascripts/es6_browserified/reducers/index.js new file mode 100644 index 000000000..381b32d8b --- /dev/null +++ b/app/assets/javascripts/es6_browserified/reducers/index.js @@ -0,0 +1,8 @@ +var combineReducers = require('redux').combineReducers +var todos = require('./todos') + +const todoApp = combineReducers({ +  todos +}) + +module.exports = todoApp diff --git a/app/assets/javascripts/es6_browserified/reducers/todos.js b/app/assets/javascripts/es6_browserified/reducers/todos.js new file mode 100644 index 000000000..916cd4704 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/reducers/todos.js @@ -0,0 +1,85 @@ +var addInput = require('../form_helper') + +const todo = (state = {}, action, length) => { +  switch (action.type) { +    case 'ADD_STOP': +      return { +        text: '', +        index: length, +        for_boarding: 'normal', +        for_alighting: 'normal' +      } +    default: +      return state +  } +} +const updateFormForDeletion = (stop) =>{ +  if (stop.stoppoint_id !== undefined){ +    let now = Date.now() +    addInput('id', stop.stoppoint_id, now) +    addInput('_destroy', 'true', now) +  } +} + +const todos = (state = [], action) => { +  switch (action.type) { +    case 'ADD_STOP': +      return [ +        ...state, +        todo(undefined, action, state.length) +      ] +    case 'MOVE_STOP_UP': +      return [ +        ...state.slice(0, action.index - 1), +        state[action.index], +        state[action.index - 1], +        ...state.slice(action.index + 1) +      ] +    case 'MOVE_STOP_DOWN': +      return [ +        ...state.slice(0, action.index), +        state[action.index + 1], +        state[action.index], +        ...state.slice(action.index + 2) +      ] +    case 'DELETE_STOP': +      updateFormForDeletion(state[action.index]) +      return [ +        ...state.slice(0, action.index), +        ...state.slice(action.index + 1).map((todo)=>{ +          todo.index-- +          return todo +        }) +      ] +    case 'UPDATE_INPUT_VALUE': +      return state.map( (t, i) => { +        if (i === action.index) { +          updateFormForDeletion(t) +          return Object.assign( +            {}, +            t, +            {text: action.text.text, stoparea_id: action.text.stoparea_id} +          ) +        } else { +          return t +        } +      }) +      // return state.map(t => +      //   todo(t, action) +      // ) +    case 'UPDATE_SELECT_VALUE': +      return state.map( (t,i) => { +        if (i === action.index) { +          let stopState = Object.assign({}, t) +          stopState[action.select_id] = action.select_value +          return stopState +        } else { +          return t +        } +      }) +    default: +      return state +  } +} + +module.exports = todos diff --git a/app/assets/javascripts/es6_browserified/stop_points.js b/app/assets/javascripts/es6_browserified/stop_points.js new file mode 100644 index 000000000..f594c0da4 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/stop_points.js @@ -0,0 +1,65 @@ +var React = require('react') +var render = require('react-dom').render +var Provider = require('react-redux').Provider +var createStore = require('redux').createStore +var todoApp = require('./reducers') +var App = require('./components/App') +var addInput = require('./form_helper') + +// logger, DO NOT REMOVE +// var applyMiddleware = require('redux').applyMiddleware +// var createLogger = require('redux-logger') +// var thunkMiddleware = require('redux-thunk').default +// var promise = require('redux-promise') + +const getInitialState = () => { +  let state = [] +  let datas = JSON.parse(decodeURIComponent(window.itinerary_stop)) +  for (let [index, value] of datas.entries()){ + +    let fancyText = value.name +    if(value.zip_code && value.city_name) +      fancyText += ", " + value.zip_code + " " + value.city_name + +    state.push({ +      stoppoint_id: value.stoppoint_id, +      stoparea_id: value.stoparea_id, +      index: index, +      city_name: value.city_name, +      zip_code: value.zip_code, +      text: fancyText, +      for_boarding: value.for_boarding || "normal", +      for_alighting: value.for_alighting || "normal" +    }) +  } +  return state +} + +var initialState = {todos: getInitialState()} +// const loggerMiddleware = createLogger() +let store = createStore( +  todoApp, +  initialState +  // applyMiddleware(thunkMiddleware, promise, loggerMiddleware) +) + +render( +  <Provider store={store}> +    <App /> +  </Provider>, +  document.getElementById('stop_points') +) + +document.querySelector('input[name=commit]').addEventListener('click', (event)=>{ +  let state = store.getState() +  for (let [i, todo] of state.todos.entries()){ +    if (todo.stoppoint_id == undefined){ +      todo.stoppoint_id = "" +    } +    addInput('id',todo.stoppoint_id, i) +    addInput('stop_area_id',todo.stoparea_id, i) +    addInput('position',i, i) +    addInput('for_boarding',todo.for_boarding, i) +    addInput('for_alighting',todo.for_alighting, i) +  } +}) diff --git a/app/assets/javascripts/select2.coffee b/app/assets/javascripts/select2.coffee new file mode 100644 index 000000000..edd4c476d --- /dev/null +++ b/app/assets/javascripts/select2.coffee @@ -0,0 +1,11 @@ +@select_2 = -> +  $("[data-select2ed='true']").each -> +    target = $(this) +    target.select2 +      theme: 'bootstrap' +      language: 'fr' +      placeholder: target.data('select2ed-placeholder') +      allowClear: true + + +$(document).on 'ready page:load', select_2 diff --git a/app/assets/stylesheets/application.sass.erb b/app/assets/stylesheets/application.sass.erb index 53b767384..d18ac0978 100644 --- a/app/assets/stylesheets/application.sass.erb +++ b/app/assets/stylesheets/application.sass.erb @@ -31,6 +31,10 @@ $body-bg: #eee  @import 'eonasdan-bootstrap-datetimepicker'  @import 'footable' +// Select2, themed w. Bootstrap +@import 'select2' +@import 'select2-bootstrap' +  @import 'vendor/openlayers_style'  @import 'vendor/openlayers_ie6-style'  @import 'vendor/openlayers_google' @@ -42,10 +46,16 @@ $body-bg: #eee  @import 'vendor/typeahead'  @import 'vendor/bootstrap_changes'  @import 'vendor/simple_form' +// Select2 +@import 'vendor/select2' +@import 'vendor/select2-bootstrap'  // Main css  @import 'main/*' +// Components +@import 'components/*' +  // Hack to make li simple  li    list-style: none diff --git a/app/assets/stylesheets/components/_form.sass b/app/assets/stylesheets/components/_form.sass new file mode 100644 index 000000000..d5f4a1eae --- /dev/null +++ b/app/assets/stylesheets/components/_form.sass @@ -0,0 +1,13 @@ +//-------// +// FORMS // +//-------// + +.form-control +  &.form-control-link +    &:hover, &:focus +      // Reset default link styles +      text-decoration: none +      color: inherit +      // Add custom +      color: #555 +      background-color: #f5f5f5 diff --git a/app/assets/stylesheets/components/_select2.sass b/app/assets/stylesheets/components/_select2.sass new file mode 100644 index 000000000..b7fd2c6df --- /dev/null +++ b/app/assets/stylesheets/components/_select2.sass @@ -0,0 +1,17 @@ +//-----------------------// +// Select2 Customisation // +//-----------------------// + +// With Font Awesome adjusts. + +.select2-selection__clear +  font-size: 0 +  font-family: FontAwesome +  text-rendering: auto +  -webkit-font-smoothing: antialiased + +  &::before +    content: '\f057' +    display: inline +    font-size: 14px +    font-weight: normal diff --git a/app/assets/stylesheets/vendor/bootstrap_changes.sass b/app/assets/stylesheets/vendor/bootstrap_changes.sass index 900949492..085f860a8 100644 --- a/app/assets/stylesheets/vendor/bootstrap_changes.sass +++ b/app/assets/stylesheets/vendor/bootstrap_changes.sass @@ -18,10 +18,10 @@    .validity_out      color: $brand-danger -   +    .validity_out_soon      color: $brand-warning -   +    .validity_regular      color: $brand-success @@ -42,6 +42,14 @@    > ul      margin: 0      padding: 0 -     +      > li -      list-style: none !important
\ No newline at end of file +      list-style: none !important + + +//-----------------------// +// Bootstrap-rails fixes // +//-----------------------// + +.input-group-btn > .btn +  height: 34px diff --git a/app/assets/stylesheets/vendor/select2-bootstrap.css b/app/assets/stylesheets/vendor/select2-bootstrap.css new file mode 100644 index 000000000..99437f434 --- /dev/null +++ b/app/assets/stylesheets/vendor/select2-bootstrap.css @@ -0,0 +1,720 @@ +/*! + * Select2 Bootstrap Theme v0.1.0-beta.9 (https://select2.github.io/select2-bootstrap-theme) + * Copyright 2015-2016 Florian Kissling and contributors (https://github.com/select2/select2-bootstrap-theme/graphs/contributors) + * Licensed under MIT (https://github.com/select2/select2-bootstrap-theme/blob/master/LICENSE) + */ + +.select2-container--bootstrap { +  display: block; +  /*------------------------------------*      #COMMON STYLES +  \*------------------------------------*/ +  /** +   * Search field in the Select2 dropdown. +   */ +  /** +   * No outline for all search fields - in the dropdown +   * and inline in multi Select2s. +   */ +  /** +   * Adjust Select2's choices hover and selected styles to match +   * Bootstrap 3's default dropdown styles. +   * +   * @see http://getbootstrap.com/components/#dropdowns +   */ +  /** +   * Clear the selection. +   */ +  /** +   * Address disabled Select2 styles. +   * +   * @see https://select2.github.io/examples.html#disabled +   * @see http://getbootstrap.com/css/#forms-control-disabled +   */ +  /*------------------------------------*      #DROPDOWN +  \*------------------------------------*/ +  /** +   * Dropdown border color and box-shadow. +   */ +  /** +   * Limit the dropdown height. +   */ +  /*------------------------------------*      #SINGLE SELECT2 +  \*------------------------------------*/ +  /*------------------------------------*    #MULTIPLE SELECT2 +  \*------------------------------------*/ +  /** +   * Address Bootstrap control sizing classes +   * +   * 1. Reset Bootstrap defaults. +   * 2. Adjust the dropdown arrow button icon position. +   * +   * @see http://getbootstrap.com/css/#forms-control-sizes +   */ +  /* 1 */ +  /*------------------------------------*    #RTL SUPPORT +  \*------------------------------------*/ +} + +.select2-container--bootstrap .select2-selection { +  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +  background-color: #fff; +  border: 1px solid #ccc; +  border-radius: 4px; +  color: #555555; +  font-size: 14px; +  outline: 0; +} + +.select2-container--bootstrap .select2-selection.form-control { +  border-radius: 4px; +} + +.select2-container--bootstrap .select2-search--dropdown .select2-search__field { +  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +  background-color: #fff; +  border: 1px solid #ccc; +  border-radius: 4px; +  color: #555555; +  font-size: 14px; +} + +.select2-container--bootstrap .select2-search__field { +  outline: 0; +  /* Firefox 18- */ +  /** +     * Firefox 19+ +     * +     * @see http://stackoverflow.com/questions/24236240/color-for-styled-placeholder-text-is-muted-in-firefox +     */ +} + +.select2-container--bootstrap .select2-search__field::-webkit-input-placeholder { +  color: #999; +} + +.select2-container--bootstrap .select2-search__field:-moz-placeholder { +  color: #999; +} + +.select2-container--bootstrap .select2-search__field::-moz-placeholder { +  color: #999; +  opacity: 1; +} + +.select2-container--bootstrap .select2-search__field:-ms-input-placeholder { +  color: #999; +} + +.select2-container--bootstrap .select2-results__option { +  padding: 6px 12px; +  /** +     * Disabled results. +     * +     * @see https://select2.github.io/examples.html#disabled-results +     */ +  /** +     * Hover state. +     */ +  /** +     * Selected state. +     */ +} + +.select2-container--bootstrap .select2-results__option[role=group] { +  padding: 0; +} + +.select2-container--bootstrap .select2-results__option[aria-disabled=true] { +  color: #777777; +  cursor: not-allowed; +} + +.select2-container--bootstrap .select2-results__option[aria-selected=true] { +  background-color: #f5f5f5; +  color: #262626; +} + +.select2-container--bootstrap .select2-results__option--highlighted[aria-selected] { +  background-color: #337ab7; +  color: #fff; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option { +  padding: 6px 12px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__group { +  padding-left: 0; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option { +  margin-left: -12px; +  padding-left: 24px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +  margin-left: -24px; +  padding-left: 36px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +  margin-left: -36px; +  padding-left: 48px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +  margin-left: -48px; +  padding-left: 60px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +  margin-left: -60px; +  padding-left: 72px; +} + +.select2-container--bootstrap .select2-results__group { +  color: #777777; +  display: block; +  padding: 6px 12px; +  font-size: 12px; +  line-height: 1.42857143; +  white-space: nowrap; +} + +.select2-container--bootstrap.select2-container--focus .select2-selection, .select2-container--bootstrap.select2-container--open .select2-selection { +  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +  -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +  -webkit-transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s; +  transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s; +  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s; +  border-color: #66afe9; +} + +.select2-container--bootstrap.select2-container--open { +  /** +     * Make the dropdown arrow point up while the dropdown is visible. +     */ +  /** +     * Handle border radii of the container when the dropdown is showing. +     */ +} + +.select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b { +  border-color: transparent transparent #999 transparent; +  border-width: 0 4px 4px 4px; +} + +.select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection { +  border-bottom-right-radius: 0; +  border-bottom-left-radius: 0; +  border-bottom-color: transparent; +} + +.select2-container--bootstrap.select2-container--open.select2-container--above .select2-selection { +  border-top-right-radius: 0; +  border-top-left-radius: 0; +  border-top-color: transparent; +} + +.select2-container--bootstrap .select2-selection__clear { +  color: #999; +  cursor: pointer; +  float: right; +  font-weight: bold; +  margin-right: 10px; +} + +.select2-container--bootstrap .select2-selection__clear:hover { +  color: #333; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection { +  border-color: #ccc; +  -webkit-box-shadow: none; +  box-shadow: none; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection, +.select2-container--bootstrap.select2-container--disabled .select2-search__field { +  cursor: not-allowed; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection, +.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice { +  background-color: #eeeeee; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection__clear, +.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove { +  display: none; +} + +.select2-container--bootstrap .select2-dropdown { +  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); +  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); +  border-color: #66afe9; +  overflow-x: hidden; +  margin-top: -1px; +} + +.select2-container--bootstrap .select2-dropdown--above { +  -webkit-box-shadow: 0px -6px 12px rgba(0, 0, 0, 0.175); +  box-shadow: 0px -6px 12px rgba(0, 0, 0, 0.175); +  margin-top: 1px; +} + +.select2-container--bootstrap .select2-results > .select2-results__options { +  max-height: 200px; +  overflow-y: auto; +} + +.select2-container--bootstrap .select2-selection--single { +  height: 34px; +  line-height: 1.42857143; +  padding: 6px 24px 6px 12px; +  /** +     * Adjust the single Select2's dropdown arrow button appearance. +     */ +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__arrow { +  position: absolute; +  bottom: 0; +  right: 12px; +  top: 0; +  width: 4px; +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__arrow b { +  border-color: #999 transparent transparent transparent; +  border-style: solid; +  border-width: 4px 4px 0 4px; +  height: 0; +  left: 0; +  margin-left: -4px; +  margin-top: -2px; +  position: absolute; +  top: 50%; +  width: 0; +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__rendered { +  color: #555555; +  padding: 0; +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__placeholder { +  color: #999; +} + +.select2-container--bootstrap .select2-selection--multiple { +  min-height: 34px; +  padding: 0; +  height: auto; +  /** +     * Make Multi Select2's choices match Bootstrap 3's default button styles. +     */ +  /** +     * Minus 2px borders. +     */ +  /** +     * Clear the selection. +     */ +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered { +  -webkit-box-sizing: border-box; +     -moz-box-sizing: border-box; +          box-sizing: border-box; +  display: block; +  line-height: 1.42857143; +  list-style: none; +  margin: 0; +  overflow: hidden; +  padding: 0; +  width: 100%; +  text-overflow: ellipsis; +  white-space: nowrap; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder { +  color: #999; +  float: left; +  margin-top: 5px; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice { +  color: #555555; +  background: #fff; +  border: 1px solid #ccc; +  border-radius: 4px; +  cursor: default; +  float: left; +  margin: 5px 0 0 6px; +  padding: 0 6px; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field { +  background: transparent; +  padding: 0 12px; +  height: 32px; +  line-height: 1.42857143; +  margin-top: 0; +  min-width: 5em; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove { +  color: #999; +  cursor: pointer; +  display: inline-block; +  font-weight: bold; +  margin-right: 3px; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove:hover { +  color: #333; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__clear { +  margin-top: 6px; +} + +.select2-container--bootstrap .select2-selection--single.input-sm, +.input-group-sm .select2-container--bootstrap .select2-selection--single, +.form-group-sm .select2-container--bootstrap .select2-selection--single { +  border-radius: 3px; +  font-size: 12px; +  height: 30px; +  line-height: 1.5; +  padding: 5px 22px 5px 10px; +  /* 2 */ +} + +.select2-container--bootstrap .select2-selection--single.input-sm .select2-selection__arrow b, +.input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, +.form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b { +  margin-left: -5px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple { +  min-height: 30px; +  border-radius: 3px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__choice, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice { +  font-size: 12px; +  line-height: 1.5; +  margin: 4px 0 0 5px; +  padding: 0 5px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field { +  padding: 0 10px; +  font-size: 12px; +  height: 28px; +  line-height: 1.5; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__clear, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear { +  margin-top: 5px; +} + +.select2-container--bootstrap .select2-selection--single.input-lg, +.input-group-lg .select2-container--bootstrap .select2-selection--single, +.form-group-lg .select2-container--bootstrap .select2-selection--single { +  border-radius: 6px; +  font-size: 18px; +  height: 46px; +  line-height: 1.3333333; +  padding: 10px 31px 10px 16px; +  /* 1 */ +} + +.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow, +.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow, +.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow { +  width: 5px; +} + +.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow b, +.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, +.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b { +  border-width: 5px 5px 0 5px; +  margin-left: -5px; +  margin-left: -10px; +  margin-top: -2.5px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple { +  min-height: 46px; +  border-radius: 6px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__choice, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice { +  font-size: 18px; +  line-height: 1.3333333; +  border-radius: 4px; +  margin: 9px 0 0 8px; +  padding: 0 10px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field { +  padding: 0 16px; +  font-size: 18px; +  height: 44px; +  line-height: 1.3333333; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__clear, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear { +  margin-top: 10px; +} + +.select2-container--bootstrap .select2-selection.input-lg.select2-container--open .select2-selection--single { +  /** +     * Make the dropdown arrow point up while the dropdown is visible. +     */ +} + +.select2-container--bootstrap .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b { +  border-color: transparent transparent #999 transparent; +  border-width: 0 5px 5px 5px; +} + +.input-group-lg .select2-container--bootstrap .select2-selection.select2-container--open .select2-selection--single { +  /** +     * Make the dropdown arrow point up while the dropdown is visible. +     */ +} + +.input-group-lg .select2-container--bootstrap .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b { +  border-color: transparent transparent #999 transparent; +  border-width: 0 5px 5px 5px; +} + +.select2-container--bootstrap[dir="rtl"] { +  /** +     * Single Select2 +     * +     * 1. Makes sure that .select2-selection__placeholder is positioned +     *    correctly. +     */ +  /** +     * Multiple Select2 +     */ +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single { +  padding-left: 24px; +  padding-right: 12px; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__rendered { +  padding-right: 0; +  padding-left: 0; +  text-align: right; +  /* 1 */ +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__clear { +  float: left; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__arrow { +  left: 12px; +  right: auto; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__arrow b { +  margin-left: 0; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice, +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder { +  float: right; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice { +  margin-left: 0; +  margin-right: 6px; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { +  margin-left: 2px; +  margin-right: auto; +} + +/*------------------------------------*  #ADDITIONAL GOODIES +\*------------------------------------*/ +/** + * Address Bootstrap's validation states + * + * If a Select2 widget parent has one of Bootstrap's validation state modifier + * classes, adjust Select2's border colors and focus states accordingly. + * You may apply said classes to the Select2 dropdown (body > .select2-container) + * via JavaScript match Bootstraps' to make its styles match. + * + * @see http://getbootstrap.com/css/#forms-control-validation + */ +.has-warning .select2-dropdown, +.has-warning .select2-selection { +  border-color: #8a6d3b; +} + +.has-warning .select2-container--focus .select2-selection, +.has-warning .select2-container--open .select2-selection { +  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +  border-color: #66512c; +} + +.has-warning.select2-drop-active { +  border-color: #66512c; +} + +.has-warning.select2-drop-active.select2-drop.select2-drop-above { +  border-top-color: #66512c; +} + +.has-error .select2-dropdown, +.has-error .select2-selection { +  border-color: #a94442; +} + +.has-error .select2-container--focus .select2-selection, +.has-error .select2-container--open .select2-selection { +  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +  border-color: #843534; +} + +.has-error.select2-drop-active { +  border-color: #843534; +} + +.has-error.select2-drop-active.select2-drop.select2-drop-above { +  border-top-color: #843534; +} + +.has-success .select2-dropdown, +.has-success .select2-selection { +  border-color: #3c763d; +} + +.has-success .select2-container--focus .select2-selection, +.has-success .select2-container--open .select2-selection { +  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +  border-color: #2b542c; +} + +.has-success.select2-drop-active { +  border-color: #2b542c; +} + +.has-success.select2-drop-active.select2-drop.select2-drop-above { +  border-top-color: #2b542c; +} + +/** + * Select2 widgets in Bootstrap Input Groups + * + * When Select2 widgets are combined with other elements using Bootstraps + * "Input Group" component, we don't want specific edges of the Select2 + * container to have a border-radius. + * + * Use .select2-bootstrap-prepend and .select2-bootstrap-append on + * a Bootstrap 3 .input-group to let the contained Select2 widget know which + * edges should not be rounded as they are directly followed by another element. + * + * @see http://getbootstrap.com/components/#input-groups + */ +/** + * Mimick Bootstraps .input-group .form-control styles. + * + * @see https://github.com/twbs/bootstrap/blob/master/less/input-groups.less + */ +.input-group .select2-container--bootstrap { +  display: table; +  table-layout: fixed; +  position: relative; +  z-index: 2; +  float: left; +  width: 100%; +  margin-bottom: 0; +  /** +   * Adjust z-index like Bootstrap does to show the focus-box-shadow +   * above appended buttons in .input-group and .form-group. +   */ +} + +.input-group .select2-container--bootstrap.select2-container--open, .input-group .select2-container--bootstrap.select2-container--focus { +  z-index: 3; +} + +.input-group.select2-bootstrap-prepend .select2-container--bootstrap .select2-selection { +  border-bottom-left-radius: 0; +  border-top-left-radius: 0; +} + +.input-group.select2-bootstrap-append .select2-container--bootstrap .select2-selection { +  border-bottom-right-radius: 0; +  border-top-right-radius: 0; +} + +/** + * Adjust alignment of Bootstrap buttons in Bootstrap Input Groups to address + * Multi Select2's height which - depending on how many elements have been selected - + * may grow taller than its initial size. + * + * @see http://getbootstrap.com/components/#input-groups + */ +.select2-bootstrap-append .select2-container--bootstrap, +.select2-bootstrap-append .input-group-btn, +.select2-bootstrap-append .input-group-btn .btn, +.select2-bootstrap-prepend .select2-container--bootstrap, +.select2-bootstrap-prepend .input-group-btn, +.select2-bootstrap-prepend .input-group-btn .btn { +  vertical-align: top; +} + +/** + * Temporary fix for https://github.com/select2/select2-bootstrap-theme/issues/9 + * + * Provides `!important` for certain properties of the class applied to the + * original `<select>` element to hide it. + * + * @see https://github.com/select2/select2/pull/3301 + * @see https://github.com/fk/select2/commit/31830c7b32cb3d8e1b12d5b434dee40a6e753ada + */ +.form-control.select2-hidden-accessible { +  position: absolute !important; +  width: 1px !important; +} + +/** + * Display override for inline forms + */ +.form-inline .select2-container--bootstrap { +  display: inline-block; +} diff --git a/app/assets/stylesheets/vendor/select2.css b/app/assets/stylesheets/vendor/select2.css new file mode 100644 index 000000000..6f3cb138d --- /dev/null +++ b/app/assets/stylesheets/vendor/select2.css @@ -0,0 +1,498 @@ +.select2-container { +  box-sizing: border-box; +  display: inline-block; +  margin: 0; +  position: relative; +  vertical-align: middle; } +  .select2-container .select2-selection--single { +    box-sizing: border-box; +    cursor: pointer; +    display: block; +    height: 28px; +    user-select: none; +    -webkit-user-select: none; } +    .select2-container .select2-selection--single .select2-selection__rendered { +      display: block; +      padding-left: 8px; +      padding-right: 20px; +      overflow: hidden; +      text-overflow: ellipsis; +      white-space: nowrap; } +    .select2-container .select2-selection--single .select2-selection__clear { +      position: relative; } +  .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { +    padding-right: 8px; +    padding-left: 20px; } +  .select2-container .select2-selection--multiple { +    box-sizing: border-box; +    cursor: pointer; +    display: block; +    min-height: 32px; +    user-select: none; +    -webkit-user-select: none; } +    .select2-container .select2-selection--multiple .select2-selection__rendered { +      display: inline-block; +      overflow: hidden; +      padding-left: 8px; +      text-overflow: ellipsis; +      white-space: nowrap; } +  .select2-container .select2-search--inline { +    float: left; } +    .select2-container .select2-search--inline .select2-search__field { +      box-sizing: border-box; +      border: none; +      font-size: 100%; +      margin-top: 5px; +      padding: 0; } +      .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { +        -webkit-appearance: none; } + +.select2-dropdown { +  background-color: white; +  border: 1px solid #aaa; +  border-radius: 4px; +  box-sizing: border-box; +  display: block; +  position: absolute; +  left: -100000px; +  width: 100%; +  z-index: 1051; } + +.select2-results { +  display: block; } + +.select2-results__options { +  list-style: none; +  margin: 0; +  padding: 0; } + +.select2-results__option { +  padding: 6px; +  user-select: none; +  -webkit-user-select: none; } +  .select2-results__option[aria-selected] { +    cursor: pointer; } + +.select2-container--open .select2-dropdown { +  left: 0; } + +.select2-container--open .select2-dropdown--above { +  border-bottom: none; +  border-bottom-left-radius: 0; +  border-bottom-right-radius: 0; } + +.select2-container--open .select2-dropdown--below { +  border-top: none; +  border-top-left-radius: 0; +  border-top-right-radius: 0; } + +.select2-search--dropdown { +  display: block; +  padding: 4px; } +  .select2-search--dropdown .select2-search__field { +    padding: 4px; +    width: 100%; +    box-sizing: border-box; } +    .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { +      -webkit-appearance: none; } +  .select2-search--dropdown.select2-search--hide { +    display: none; } + +.select2-close-mask { +  border: 0; +  margin: 0; +  padding: 0; +  display: block; +  position: fixed; +  left: 0; +  top: 0; +  min-height: 100%; +  min-width: 100%; +  height: auto; +  width: auto; +  opacity: 0; +  z-index: 99; +  background-color: #fff; +  filter: alpha(opacity=0); } + +.select2-hidden-accessible { +  border: 0 !important; +  clip: rect(0 0 0 0) !important; +  height: 1px !important; +  margin: -1px !important; +  overflow: hidden !important; +  padding: 0 !important; +  position: absolute !important; +  width: 1px !important; } + +.select2-container--default .select2-selection--single { +  background-color: #fff; +  border: 1px solid #aaa; +  border-radius: 4px; } +  .select2-container--default .select2-selection--single .select2-selection__rendered { +    color: #444; +    line-height: 28px; } +  .select2-container--default .select2-selection--single .select2-selection__clear { +    cursor: pointer; +    float: right; +    font-weight: bold; } +  .select2-container--default .select2-selection--single .select2-selection__placeholder { +    color: #999; } +  .select2-container--default .select2-selection--single .select2-selection__arrow { +    height: 26px; +    position: absolute; +    top: 1px; +    right: 1px; +    width: 20px; } +    .select2-container--default .select2-selection--single .select2-selection__arrow b { +      border-color: #888 transparent transparent transparent; +      border-style: solid; +      border-width: 5px 4px 0 4px; +      height: 0; +      left: 50%; +      margin-left: -4px; +      margin-top: -2px; +      position: absolute; +      top: 50%; +      width: 0; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { +  float: left; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { +  left: 1px; +  right: auto; } + +.select2-container--default.select2-container--disabled .select2-selection--single { +  background-color: #eee; +  cursor: default; } +  .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { +    display: none; } + +.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { +  border-color: transparent transparent #888 transparent; +  border-width: 0 4px 5px 4px; } + +.select2-container--default .select2-selection--multiple { +  background-color: white; +  border: 1px solid #aaa; +  border-radius: 4px; +  cursor: text; } +  .select2-container--default .select2-selection--multiple .select2-selection__rendered { +    box-sizing: border-box; +    list-style: none; +    margin: 0; +    padding: 0 5px; +    width: 100%; } +    .select2-container--default .select2-selection--multiple .select2-selection__rendered li { +      list-style: none; } +  .select2-container--default .select2-selection--multiple .select2-selection__placeholder { +    color: #999; +    margin-top: 5px; +    float: left; } +  .select2-container--default .select2-selection--multiple .select2-selection__clear { +    cursor: pointer; +    float: right; +    font-weight: bold; +    margin-top: 5px; +    margin-right: 10px; } +  .select2-container--default .select2-selection--multiple .select2-selection__choice { +    background-color: #e4e4e4; +    border: 1px solid #aaa; +    border-radius: 4px; +    cursor: default; +    float: left; +    margin-right: 5px; +    margin-top: 5px; +    padding: 0 5px; } +  .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { +    color: #999; +    cursor: pointer; +    display: inline-block; +    font-weight: bold; +    margin-right: 2px; } +    .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { +      color: #333; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { +  float: right; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { +  margin-left: 5px; +  margin-right: auto; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { +  margin-left: 2px; +  margin-right: auto; } + +.select2-container--default.select2-container--focus .select2-selection--multiple { +  border: solid black 1px; +  outline: 0; } + +.select2-container--default.select2-container--disabled .select2-selection--multiple { +  background-color: #eee; +  cursor: default; } + +.select2-container--default.select2-container--disabled .select2-selection__choice__remove { +  display: none; } + +.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { +  border-top-left-radius: 0; +  border-top-right-radius: 0; } + +.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { +  border-bottom-left-radius: 0; +  border-bottom-right-radius: 0; } + +.select2-container--default .select2-search--dropdown .select2-search__field { +  border: 1px solid #aaa; } + +.select2-container--default .select2-search--inline .select2-search__field { +  background: transparent; +  border: none; +  outline: 0; +  box-shadow: none; +  -webkit-appearance: textfield; } + +.select2-container--default .select2-results > .select2-results__options { +  max-height: 200px; +  overflow-y: auto; } + +.select2-container--default .select2-results__option[role=group] { +  padding: 0; } + +.select2-container--default .select2-results__option[aria-disabled=true] { +  color: #999; } + +.select2-container--default .select2-results__option[aria-selected=true] { +  background-color: #ddd; } + +.select2-container--default .select2-results__option .select2-results__option { +  padding-left: 1em; } +  .select2-container--default .select2-results__option .select2-results__option .select2-results__group { +    padding-left: 0; } +  .select2-container--default .select2-results__option .select2-results__option .select2-results__option { +    margin-left: -1em; +    padding-left: 2em; } +    .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +      margin-left: -2em; +      padding-left: 3em; } +      .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +        margin-left: -3em; +        padding-left: 4em; } +        .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +          margin-left: -4em; +          padding-left: 5em; } +          .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { +            margin-left: -5em; +            padding-left: 6em; } + +.select2-container--default .select2-results__option--highlighted[aria-selected] { +  background-color: #5897fb; +  color: white; } + +.select2-container--default .select2-results__group { +  cursor: default; +  display: block; +  padding: 6px; } + +.select2-container--classic .select2-selection--single { +  background-color: #f7f7f7; +  border: 1px solid #aaa; +  border-radius: 4px; +  outline: 0; +  background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); +  background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); +  background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); +  background-repeat: repeat-x; +  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } +  .select2-container--classic .select2-selection--single:focus { +    border: 1px solid #5897fb; } +  .select2-container--classic .select2-selection--single .select2-selection__rendered { +    color: #444; +    line-height: 28px; } +  .select2-container--classic .select2-selection--single .select2-selection__clear { +    cursor: pointer; +    float: right; +    font-weight: bold; +    margin-right: 10px; } +  .select2-container--classic .select2-selection--single .select2-selection__placeholder { +    color: #999; } +  .select2-container--classic .select2-selection--single .select2-selection__arrow { +    background-color: #ddd; +    border: none; +    border-left: 1px solid #aaa; +    border-top-right-radius: 4px; +    border-bottom-right-radius: 4px; +    height: 26px; +    position: absolute; +    top: 1px; +    right: 1px; +    width: 20px; +    background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); +    background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); +    background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); +    background-repeat: repeat-x; +    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } +    .select2-container--classic .select2-selection--single .select2-selection__arrow b { +      border-color: #888 transparent transparent transparent; +      border-style: solid; +      border-width: 5px 4px 0 4px; +      height: 0; +      left: 50%; +      margin-left: -4px; +      margin-top: -2px; +      position: absolute; +      top: 50%; +      width: 0; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { +  float: left; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { +  border: none; +  border-right: 1px solid #aaa; +  border-radius: 0; +  border-top-left-radius: 4px; +  border-bottom-left-radius: 4px; +  left: 1px; +  right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--single { +  border: 1px solid #5897fb; } +  .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { +    background: transparent; +    border: none; } +    .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { +      border-color: transparent transparent #888 transparent; +      border-width: 0 4px 5px 4px; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { +  border-top: none; +  border-top-left-radius: 0; +  border-top-right-radius: 0; +  background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); +  background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); +  background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); +  background-repeat: repeat-x; +  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { +  border-bottom: none; +  border-bottom-left-radius: 0; +  border-bottom-right-radius: 0; +  background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); +  background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); +  background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); +  background-repeat: repeat-x; +  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } + +.select2-container--classic .select2-selection--multiple { +  background-color: white; +  border: 1px solid #aaa; +  border-radius: 4px; +  cursor: text; +  outline: 0; } +  .select2-container--classic .select2-selection--multiple:focus { +    border: 1px solid #5897fb; } +  .select2-container--classic .select2-selection--multiple .select2-selection__rendered { +    list-style: none; +    margin: 0; +    padding: 0 5px; } +  .select2-container--classic .select2-selection--multiple .select2-selection__clear { +    display: none; } +  .select2-container--classic .select2-selection--multiple .select2-selection__choice { +    background-color: #e4e4e4; +    border: 1px solid #aaa; +    border-radius: 4px; +    cursor: default; +    float: left; +    margin-right: 5px; +    margin-top: 5px; +    padding: 0 5px; } +  .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { +    color: #888; +    cursor: pointer; +    display: inline-block; +    font-weight: bold; +    margin-right: 2px; } +    .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { +      color: #555; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { +  float: right; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { +  margin-left: 5px; +  margin-right: auto; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { +  margin-left: 2px; +  margin-right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--multiple { +  border: 1px solid #5897fb; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { +  border-top: none; +  border-top-left-radius: 0; +  border-top-right-radius: 0; } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { +  border-bottom: none; +  border-bottom-left-radius: 0; +  border-bottom-right-radius: 0; } + +.select2-container--classic .select2-search--dropdown .select2-search__field { +  border: 1px solid #aaa; +  outline: 0; } + +.select2-container--classic .select2-search--inline .select2-search__field { +  outline: 0; +  box-shadow: none; } + +.select2-container--classic .select2-dropdown { +  background-color: white; +  border: 1px solid transparent; } + +.select2-container--classic .select2-dropdown--above { +  border-bottom: none; } + +.select2-container--classic .select2-dropdown--below { +  border-top: none; } + +.select2-container--classic .select2-results > .select2-results__options { +  max-height: 200px; +  overflow-y: auto; } + +.select2-container--classic .select2-results__option[role=group] { +  padding: 0; } + +.select2-container--classic .select2-results__option[aria-disabled=true] { +  color: grey; } + +.select2-container--classic .select2-results__option--highlighted[aria-selected] { +  background-color: #3875d7; +  color: white; } + +.select2-container--classic .select2-results__group { +  cursor: default; +  display: block; +  padding: 6px; } + +.select2-container--classic.select2-container--open .select2-dropdown { +  border-color: #5897fb; } + +/* Do the shit, dude */ +.select2-container .select2-results__options .select2-results__option.select2-results__message { +  display: none; +} +.select2-container .select2-results__options .select2-results__option.loading-results { +  font-size: 0; +} +.select2-container .select2-results__options .select2-results__option.loading-results::before { +  content: "Recherche en cours..."; +  font-size: 14px; +  font-style: italic; +  display: inline; +} diff --git a/app/controllers/api/v1/routes_controller.rb b/app/controllers/api/v1/routes_controller.rb index e3694725f..fbc589355 100644 --- a/app/controllers/api/v1/routes_controller.rb +++ b/app/controllers/api/v1/routes_controller.rb @@ -3,11 +3,11 @@ class Api::V1::RoutesController < Api::V1::ChouetteController    defaults :resource_class => Chouette::Route, :finder => :find_by_objectid!    belongs_to :line, :parent_class => Chouette::Line, :optional => true, :finder => :find_by_objectid!, :param => :line_id -   +  protected    def collection      @routes ||= parent.routes -  end  +  end  end diff --git a/app/controllers/autocomplete_stop_areas_controller.rb b/app/controllers/autocomplete_stop_areas_controller.rb index cd3521f6a..1e43f3968 100644 --- a/app/controllers/autocomplete_stop_areas_controller.rb +++ b/app/controllers/autocomplete_stop_areas_controller.rb @@ -1,15 +1,15 @@  class AutocompleteStopAreasController < InheritedResources::Base    respond_to :json, :only => [:index, :children, :parent, :physicals] -   +    before_action :switch_referential -   +    def switch_referential      Apartment::Tenant.switch!(referential.slug)    end    def referential -    @referential ||= current_organisation.referentials.find params[:referential_id]   -  end  +    @referential ||= current_organisation.referentials.find params[:referential_id] +  end    protected @@ -26,7 +26,7 @@ class AutocompleteStopAreasController < InheritedResources::Base      else        result = referential.stop_areas      end -    @stop_areas = result.select{ |p| [p.name, p.registration_number, p.objectid].grep(/#{params[:q]}/i).any?  } +    @stop_areas = result.where("name LIKE '%#{params[:q]}%' OR registration_number LIKE '%#{params[:q]}%' OR objectid LIKE '%#{params[:q]}%' ").limit(50)      @stop_areas    end @@ -51,4 +51,3 @@ class AutocompleteStopAreasController < InheritedResources::Base    end  end - diff --git a/app/controllers/clean_ups_controller.rb b/app/controllers/clean_ups_controller.rb index 8718fc0dc..1e4835775 100644 --- a/app/controllers/clean_ups_controller.rb +++ b/app/controllers/clean_ups_controller.rb @@ -1,23 +1,19 @@  class CleanUpsController < ChouetteController    respond_to :html, :only => [:create] -    belongs_to :referential    def create -    clean_up = CleanUp.new(params[:clean_up]) - -    if clean_up.invalid? -      flash[:alert] = clean_up.errors.full_messages.join("<br/>") +    clean_up = CleanUp.new(clean_up_params) +    clean_up.referential = @referential +    if clean_up.valid? +      clean_up.save      else -      begin -        result = clean_up.clean -        flash[:notice] = result.notice.join("<br/>") -      rescue => e -        Rails.logger.error "CleanUp failed : #{e} #{e.backtrace}" -        flash[:alert] = t('clean_ups.failure', error_message: e.to_s) -      end +      flash[:alert] = clean_up.errors.full_messages.join("<br/>")      end      redirect_to referential_path(@referential)    end +  def clean_up_params +    params.require(:clean_up).permit(:keep_lines, :keep_stops, :keep_companies, :keep_networks, :keep_group_of_lines, :begin_date, :end_date) +  end  end diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb index a93084012..ef058e317 100644 --- a/app/controllers/lines_controller.rb +++ b/app/controllers/lines_controller.rb @@ -22,9 +22,7 @@ class LinesController < BreadcrumbController    end    def show -    @map = LineMap.new(resource).with_helpers(self) -    @routes = @line.routes -    @group_of_lines = @line.group_of_lines +    @group_of_lines = resource.group_of_lines      show! do        build_breadcrumb :show      end @@ -69,25 +67,16 @@ class LinesController < BreadcrumbController    end    def filtered_lines -    line_referential.lines.select{ |t| [t.name, t.published_name].find { |e| /#{params[:q]}/i =~ e }  } +    line_referential.lines.by_text(params[:q])    end    def collection -    if params[:q] && params[:q]["network_id_eq"] == "-1" -      params[:q]["network_id_eq"] = "" -      params[:q]["network_id_blank"] = "1" +    %w(network_id company_id group_of_lines_id comment_id transport_mode).each do |filter| +      if params[:q] && params[:q]["#{filter}_eq"] == '-1' +        params[:q]["#{filter}_eq"] = '' +        params[:q]["#{filter}_blank"] = '1' +      end      end - -    if params[:q] && params[:q]["company_id_eq"] == "-1" -      params[:q]["company_id_eq"] = "" -      params[:q]["company_id_blank"] = "1" -    end - -    if params[:q] && params[:q]["group_of_lines_id_eq"] == "-1" -      params[:q]["group_of_lines_id_eq"] = "" -      params[:q]["group_of_lines_id_blank"] = "1" -    end -      @q = line_referential.lines.search(params[:q])      @lines ||= @q.result(:distinct => true).order(:number).paginate(:page => params[:page]).includes([:network, :company])    end @@ -100,7 +89,7 @@ class LinesController < BreadcrumbController    end    def line_params -    params.require(:line).permit( :transport_mode, :network_id, :company_id, :objectid, :object_version, :creation_time, :creator_id, :name, :number, :published_name, :transport_mode_name, :registration_number, :comment, :mobility_restricted_suitability, :int_user_needs, :flexible_service, :group_of_lines, :group_of_line_ids, :group_of_line_tokens, :url, :color, :text_color, :stable_id, { footnotes_attributes: [ :code, :label, :_destroy, :id ] } ) +    params.require(:line).permit( :transport_mode, :network_id, :company_id, :objectid, :object_version, :creation_time, :creator_id, :name, :number, :published_name, :transport_mode, :registration_number, :comment, :mobility_restricted_suitability, :int_user_needs, :flexible_service, :group_of_lines, :group_of_line_ids, :group_of_line_tokens, :url, :color, :text_color, :stable_id, { footnotes_attributes: [ :code, :label, :_destroy, :id ] } )    end  end diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb index 104deba9f..a369488ba 100644 --- a/app/controllers/referential_companies_controller.rb +++ b/app/controllers/referential_companies_controller.rb @@ -27,7 +27,7 @@ class ReferentialCompaniesController < ChouetteController    end    def collection -    @q = referential.companies.search(params[:q]) +    @q = referential.workbench.companies.search(params[:q])      @companies ||= @q.result(:distinct => true).order(:name).paginate(:page => params[:page])    end diff --git a/app/controllers/referential_group_of_lines_controller.rb b/app/controllers/referential_group_of_lines_controller.rb index d40fd6090..4decef558 100644 --- a/app/controllers/referential_group_of_lines_controller.rb +++ b/app/controllers/referential_group_of_lines_controller.rb @@ -55,7 +55,7 @@ class ReferentialGroupOfLinesController < ChouetteController    end    def collection -    @q = referential.group_of_lines.search(params[:q]) +    @q = referential.workbench.group_of_lines.search(params[:q])      @group_of_lines ||= @q.result(:distinct => true).order(:name).paginate(:page => params[:page])    end diff --git a/app/controllers/referential_lines_controller.rb b/app/controllers/referential_lines_controller.rb index a566f440e..fb53e4959 100644 --- a/app/controllers/referential_lines_controller.rb +++ b/app/controllers/referential_lines_controller.rb @@ -22,7 +22,7 @@ class ReferentialLinesController < ChouetteController    def show      @map = LineMap.new(resource).with_helpers(self) -    @routes = @line.routes +    @routes = @line.routes.order(:name)      @group_of_lines = @line.group_of_lines      show! do        build_breadcrumb :show @@ -63,23 +63,15 @@ class ReferentialLinesController < ChouetteController    end    def filtered_lines -    referential.lines.select{ |t| [t.name, t.published_name].find { |e| /#{params[:q]}/i =~ e }  } +    referential.lines.by_text(params[:q])    end    def collection -    if params[:q] && params[:q]["network_id_eq"] == "-1" -      params[:q]["network_id_eq"] = "" -      params[:q]["network_id_blank"] = "1" -    end - -    if params[:q] && params[:q]["company_id_eq"] == "-1" -      params[:q]["company_id_eq"] = "" -      params[:q]["company_id_blank"] = "1" -    end - -    if params[:q] && params[:q]["group_of_lines_id_eq"] == "-1" -      params[:q]["group_of_lines_id_eq"] = "" -      params[:q]["group_of_lines_id_blank"] = "1" +    %w(network_id company_id group_of_lines_id comment_id transport_mode).each do |filter| +      if params[:q] && params[:q]["#{filter}_eq"] == '-1' +        params[:q]["#{filter}_eq"] = '' +        params[:q]["#{filter}_blank"] = '1' +      end      end      @q = referential.lines.search(params[:q]) @@ -89,7 +81,31 @@ class ReferentialLinesController < ChouetteController    private    def line_params -    params.require(:line).permit( :transport_mode, :network_id, :company_id, :objectid, :object_version, :creation_time, :creator_id, :name, :number, :published_name, :transport_mode_name, :registration_number, :comment, :mobility_restricted_suitability, :int_user_needs, :flexible_service, :group_of_lines, :group_of_line_ids, :group_of_line_tokens, :url, :color, :text_color, :stable_id, { footnotes_attributes: [ :code, :label, :_destroy, :id ] } ) +    params.require(:line).permit( +      :transport_mode, +      :transport_submode, +      :network_id, +      :company_id, +      :objectid, +      :object_version, +      :creation_time, +      :creator_id, +      :name, :number, +      :published_name, +      :transport_mode, +      :registration_number, +      :comment, +      :mobility_restricted_suitability, +      :int_user_needs, +      :flexible_service, +      :group_of_lines, +      :group_of_line_ids, +      :group_of_line_tokens, +      :url, +      :color, +      :text_color, +      :stable_id, +      { footnotes_attributes: [ :code, :label, :_destroy, :id ] } )    end  end diff --git a/app/controllers/referential_networks_controller.rb b/app/controllers/referential_networks_controller.rb index 2d3f4ad6b..00c680c65 100644 --- a/app/controllers/referential_networks_controller.rb +++ b/app/controllers/referential_networks_controller.rb @@ -35,7 +35,7 @@ class ReferentialNetworksController < ChouetteController    end    def collection -    @q = referential.networks.search(params[:q]) +    @q = referential.workbench.networks.search(params[:q])      @networks ||= @q.result(:distinct => true).order(:name).paginate(:page => params[:page])    end diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index 28a95c784..b7e6d8031 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -7,8 +7,15 @@ class ReferentialsController < BreadcrumbController    respond_to :js, :only => :show    def new +    @referential = Referential.new_from(Referential.find(params[:from])) if params[:from] +      new! do        @referential.data_format = current_organisation.data_format +      @referential.workbench_id ||= params[:workbench_id] + +      if @referential.in_workbench? +        @referential.init_metadatas first_period_begin: Date.today, first_period_end: Date.today.advance(months: 1) +      end      end    end @@ -23,17 +30,36 @@ class ReferentialsController < BreadcrumbController                  :referential_id => resource.id}         }         format.html { build_breadcrumb :show} -       end    end +  def edit +    edit! do +      if @referential.in_workbench? +        @referential.init_metadatas first_period_begin: Date.today, first_period_end: Date.today.advance(months: 1) +      end +    end +  end + +  def destroy +    workbench = referential.workbench_id + +    referential.destroy! +    redirect_to workbench_path(workbench), notice: t('notice.referential.deleted') +  end +    def archive      referential.archive! -    redirect_to referential_path, notice: t('notice.referential.archived') +    redirect_to workbench_path(referential.workbench_id), notice: t('notice.referential.archived')    end    def unarchive -    referential.unarchive! -    redirect_to referential_path, notice: t('notice.referential.unarchived') +    if referential.unarchive! +      flash[:notice] = t('notice.referential.unarchived') +    else +      flash[:alert] = t('notice.referential.unarchived_failed') +    end + +    redirect_to workbench_path(referential.workbench_id)    end    protected @@ -56,7 +82,7 @@ class ReferentialsController < BreadcrumbController    end    def create_resource(referential) -    referential.organisation = current_organisation +    referential.organisation = current_organisation unless referential.created_from      super    end @@ -73,8 +99,11 @@ class ReferentialsController < BreadcrumbController        :organisation_id,        :projection_type,        :data_format, -      :archived_at +      :archived_at, +      :created_from_id, +      :workbench_id, +      metadatas_attributes: [:id, :first_period_begin, :first_period_end, :lines => []]      )    end -end
\ No newline at end of file +end diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb index 59c129867..a7e8e32a6 100644 --- a/app/controllers/routes_controller.rb +++ b/app/controllers/routes_controller.rb @@ -77,7 +77,7 @@ class RoutesController < ChouetteController    private    def route_params -    params.require(:route).permit( :direction_code, :wayback_code, :line_id, :objectid, :object_version, :creation_time, :creator_id, :name, :comment, :opposite_route_id, :published_name, :number, :direction, :wayback, { stop_points_attributes: [ :id, :_destroy, :position, :stop_area_id, :for_boarding, :for_alighting ] } ) +    params.require(:route).permit( :line_id, :objectid, :object_version, :creation_time, :creator_id, :name, :comment, :opposite_route_id, :published_name, :number, :direction, :wayback, { stop_points_attributes: [ :id, :_destroy, :position, :stop_area_id, :for_boarding, :for_alighting ] } )    end  end diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index 8f6a1565a..1f55b1de8 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -26,6 +26,7 @@ class StopAreasController < BreadcrumbController    end    def add_children +    authorize stop_area      @stop_area = stop_area      @children = stop_area.children      build_breadcrumb :edit diff --git a/app/controllers/vehicle_journey_frequencies_controller.rb b/app/controllers/vehicle_journey_frequencies_controller.rb index 683bd6d5a..9626bd36d 100644 --- a/app/controllers/vehicle_journey_frequencies_controller.rb +++ b/app/controllers/vehicle_journey_frequencies_controller.rb @@ -12,7 +12,7 @@ class VehicleJourneyFrequenciesController < VehicleJourneysController    def vehicle_journey_frequency_params      params.require(:vehicle_journey_frequency).permit( { footnote_ids: [] } , :journey_pattern_id, :number, :published_journey_name, -                                             :published_journey_identifier, :comment, :transport_mode_name, +                                             :published_journey_identifier, :comment, :transport_mode,                                               :mobility_restricted_suitability, :flexible_service, :status_value,                                               :facility, :vehicle_type_identifier, :objectid, :time_table_tokens,                                               { date: [ :hour, :minute ] }, :button, :referential_id, :line_id, diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb index 036816b21..d1c54827b 100644 --- a/app/controllers/vehicle_journeys_controller.rb +++ b/app/controllers/vehicle_journeys_controller.rb @@ -81,7 +81,7 @@ class VehicleJourneysController < ChouetteController    def vehicle_journey_params      params.require(:vehicle_journey).permit( { footnote_ids: [] } , :journey_pattern_id, :number, :published_journey_name, -                                             :published_journey_identifier, :comment, :transport_mode_name, +                                             :published_journey_identifier, :comment, :transport_mode,                                               :mobility_restricted_suitability, :flexible_service, :status_value,                                               :facility, :vehicle_type_identifier, :objectid, :time_table_tokens,                                               { date: [ :hour, :minute ] }, :button, :referential_id, :line_id, diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb index 1d67db3ab..b2bf5eab8 100644 --- a/app/controllers/workbenches_controller.rb +++ b/app/controllers/workbenches_controller.rb @@ -4,6 +4,8 @@ class WorkbenchesController < BreadcrumbController    respond_to :html, :only => [:show]    def show +    @wbench_refs = Workbench.find(params[:id]).referentials.paginate(page: params[:page], per_page: 20) +      show! do        build_breadcrumb :show      end diff --git a/app/exporters/chouette/hub/exporter.rb b/app/exporters/chouette/hub/exporter.rb index 3a9313762..d098ad15e 100644 --- a/app/exporters/chouette/hub/exporter.rb +++ b/app/exporters/chouette/hub/exporter.rb @@ -16,7 +16,7 @@ class Chouette::Hub::Exporter    end    def select_time_tables(start_date, end_date) -    all_time_tables = Chouette::TimeTable.all  +    all_time_tables = Chouette::TimeTable.all      time_tables = []      s_date = Date.strptime(start_date, "%Y-%m-%d")      e_date = Date.strptime(end_date, "%Y-%m-%d") @@ -82,21 +82,21 @@ class Chouette::Hub::Exporter          Dir.mktmpdir(nil, "/tmp") { |temp_dir|            @time_tables = select_time_tables(options[:start_date], options[:end_date])            @lines = select_lines(options[:o], options[:id]) -           +            @routes = []            if @lines              @lines.each { |line| @routes << Chouette::Route.where("line_id = ?", line.id).order(:wayback) }            end -           +            @journey_patterns = []            if @routes              @routes.each { |subroutes| @journey_patterns << Chouette::JourneyPattern.where(:route_id => subroutes.map(&:id)).order(:objectid) }            end            @journey_patterns = @journey_patterns.flatten -           +            @routes = @routes.flatten            @vehicle_journeys = Chouette::VehicleJourney.where(:route_id => @routes.map(&:id)).order(:objectid) if routes_exportable? -           +            rts = []            jps = []            vjs = [] @@ -113,18 +113,18 @@ class Chouette::Hub::Exporter            @vehicle_journeys = vjs.uniq            rts = rts.flatten.uniq            jps = jps.flatten.uniq -           +            @routes.delete_if {|r| !(rts.include?(r.id)) }            @journey_patterns.delete_if {|jp| !(jps.include?(jp.id)) } -           +            vehicle_journey_at_stops = Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => @vehicle_journeys.map(&:id) ) #.order(:id) if vehicle_journeys_exportable? -           +            if time_tables_exportable?              Chouette::Hub::TimeTableExporter.save(@time_tables, temp_dir, hub_export)            else              log_overflow_warning(Chouette::TimeTable)            end -         +            if journey_patterns_exportable?              Chouette::Hub::RouteExporter.save(@routes, temp_dir, hub_export)              Chouette::Hub::ItlExporter.save(@routes, temp_dir, hub_export) @@ -133,7 +133,7 @@ class Chouette::Hub::Exporter            else              log_overflow_warning(Chouette::JourneyPattern) if routes_exportable?            end -           +            if vehicle_journeys_exportable?              Chouette::Hub::VehicleJourneyExporter.save(@vehicle_journeys, temp_dir, hub_export)              Chouette::Hub::VehicleJourneyOperationExporter.save(@vehicle_journeys, temp_dir, hub_export) @@ -141,40 +141,40 @@ class Chouette::Hub::Exporter            else              log_overflow_warning(Chouette::VehicleJourney)            end -         +            stop_points = Chouette::StopPoint.where( :id => vehicle_journey_at_stops.map(&:stop_point_id)) #.order(:id)            physical_stop_areas =  Chouette::StopArea.where( :id => stop_points.map(&:stop_area_id)) #.order(:parent_id)            commercial_stop_areas = Chouette::StopArea.where( :id => physical_stop_areas.map(&:parent_id)).order(:objectid) -           +            physical_stop_areas = []            commercial_stop_areas.each { |commercial_stop_area| physical_stop_areas << Chouette::StopArea.where( :parent_id => [commercial_stop_area.id] ).order(:objectid) }            physical_stop_areas = physical_stop_areas.flatten -           +            city_codes = Hash.new            commercial_stop_areas.each { |commercial_stop_area| city_codes[commercial_stop_area.zip_code] =  commercial_stop_area.city_name if commercial_stop_area.zip_code }            physical_stop_areas.each { |physical_stop_area| city_codes[physical_stop_area.zip_code] =  physical_stop_area.city_name if physical_stop_area.zip_code } -           +            Chouette::Hub::CityCodeExporter.save(city_codes, temp_dir, hub_export)            Chouette::Hub::CommercialStopAreaExporter.save(commercial_stop_areas, temp_dir, hub_export)            Chouette::Hub::PhysicalStopAreaExporter.save(physical_stop_areas, temp_dir, hub_export) -           +            connection_links = Chouette::ConnectionLink.where( "departure_id IN (?) AND arrival_id IN (?)", (physical_stop_areas.map(&:id) + commercial_stop_areas.map(&:id)), (physical_stop_areas.map(&:id) + commercial_stop_areas.map(&:id)) ).order(:id) -           +            Chouette::Hub::ConnectionLinkExporter.save(connection_links, temp_dir, hub_export) -           +            if lines_exportable?              Chouette::Hub::LineExporter.save(@lines, temp_dir, hub_export)              transport_modes = Hash.new              @lines.each do |l| -              if l.transport_mode_name -                case l.transport_mode_name -                when "Coach" +              if l.transport_mode +                case l.transport_mode +                when 'coach'                    if transport_modes["CAR"]                      transport_modes["CAR"] += "|"+l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')                    else                      transport_modes["CAR"] = l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')                    end -                when "Bus" +                when 'bus'                    if transport_modes["BUS"]                      transport_modes["BUS"] += "|"+l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')                    else @@ -195,12 +195,12 @@ class Chouette::Hub::Exporter            else              log_overflow_warning(Chouette::Line)            end -           +            if lines_exportable?              stop_areas = Chouette::StopArea.joins( :stop_points => [:route => :line]).where(:lines => {:id => lines.map(&:id)}).uniq.order(:name)              commercial_stop_areas = Chouette::StopArea.where( :id => stop_areas.map(&:parent_id).compact.uniq).order(:name)            end -           +            ::Zip::File.open(zip_file_path, ::Zip::File::CREATE) do |zipfile|              Dir[File.join(temp_dir, '*.TXT')].each do |f|                #Rails.logger.error("Adding File #{File.basename(f)}") diff --git a/app/helpers/breadcrumb_helper.rb b/app/helpers/breadcrumb_helper.rb index 683036032..9d503fe2e 100644 --- a/app/helpers/breadcrumb_helper.rb +++ b/app/helpers/breadcrumb_helper.rb @@ -237,6 +237,10 @@ module BreadcrumbHelper    def referential_breadcrumb (action = :edit)      organisation_breadcrumb      if @referential +      if workbench = @referential.workbench +        add_breadcrumb breadcrumb_label(workbench), workbench_path(workbench), :title => breadcrumb_tooltip(workbench) +      end +        add_breadcrumb breadcrumb_label(@referential), referential_path(@referential),:title => breadcrumb_tooltip(@referential) if action == :edit || action == :show || action == :update      end    end diff --git a/app/helpers/path_builder_helper.rb b/app/helpers/path_builder_helper.rb new file mode 100644 index 000000000..482cb91f0 --- /dev/null +++ b/app/helpers/path_builder_helper.rb @@ -0,0 +1,11 @@ +module PathBuilderHelper + +  # Companies +  def company_path(company) +    line_referential_company_path(company.line_referential_id, company) +  end +  def edit_company_path(company) +    edit_line_referential_company_path(company.line_referential_id, company) +  end + +end diff --git a/app/helpers/refobjects_helper.rb b/app/helpers/refobjects_helper.rb index f7ebb65ea..aac40b944 100644 --- a/app/helpers/refobjects_helper.rb +++ b/app/helpers/refobjects_helper.rb @@ -5,26 +5,31 @@ module RefobjectsHelper      head = content_tag :thead do        content_tag :tr do -        columns.each do |col| -          concat content_tag :th, col.to_s.titleize -        end -        concat content_tag :th, "Actions" if actions.any? +        attributes_head = columns.collect do |col| +          content_tag :th, col.to_s.titleize +        end.join.html_safe +        links_head = content_tag :th, "Actions" if actions.any? +        attributes_head + links_head        end      end      body = content_tag :tbody do        collection.collect { |item|          content_tag :tr do -          columns.collect { |col| -            concat content_tag(:td, item.try(col)) -          }.to_s.html_safe +          attributes = columns.collect { |col| +            content_tag(:td, item.try(col)) +          }.join.html_safe +            # Build links -          concat content_tag :td, autolinks_builder(item, actions, :xs) if actions.any? +          links = content_tag :td, autolinks_builder(item, actions, :xs), class: 'text-center' if actions.any? + +          attributes + links          end -      }.join().html_safe +      }.join.html_safe      end -    content_tag :table, head.concat(body), class: cls +    # content_tag :table, head + body, class: cls +    content_tag :table, "pouet"    end    def autolinks_builder(item, actions, cls) @@ -32,17 +37,17 @@ module RefobjectsHelper      actions.each do |action|        if action == "show" -        showlink = link_to({controller: params[:controller], action: action, id: item}, class: 'btn btn-default') do +        showlink = link_to(company_path(item), class: 'btn btn-default') do            content_tag :span, "", class: 'fa fa-eye'          end          link << showlink        elsif action == "edit" -        editlink = link_to({controller: params[:controller], action: action, id: item.id}, class: 'btn btn-default') do +        editlink = link_to(edit_company_path(item), class: 'btn btn-default') do            content_tag :span, "", class: 'fa fa-pencil'          end          link << editlink        elsif action == "delete" -        deletelink = link_to({controller: params[:controller], action: "show", id: item.id}, method: :delete, data: { confirm: 'Are you sure?'}, class: 'btn btn-default') do +        deletelink = link_to(company_path(item), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default') do            content_tag :span, "", class: 'fa fa-trash-o'          end          link << deletelink diff --git a/app/helpers/routes_helper.rb b/app/helpers/routes_helper.rb index b3d79262e..99278625d 100644 --- a/app/helpers/routes_helper.rb +++ b/app/helpers/routes_helper.rb @@ -6,11 +6,19 @@ module RoutesHelper    end    def fonticon_wayback(wayback) -    if wayback == "A" +    if wayback == 'straight_forward'        return '<i class="fa fa-arrow-right"></i>'.html_safe      else -      return '<i class="fa fa-arrow-left"></i>'.html_safe   +      return '<i class="fa fa-arrow-left"></i>'.html_safe      end    end -   + +  def route_json_for_edit(route) +    route.stop_points.includes(:stop_area).map do |stop_point| +      stop_area_attributes = stop_point.stop_area.attributes.slice("name","city_name", "zip_code") +      stop_point_attributes = stop_point.attributes.slice("for_boarding","for_alighting") +      stop_area_attributes.merge(stop_point_attributes).merge(stoppoint_id: stop_point.id, stoparea_id: stop_point.stop_area.id) +    end.to_json +  end +  end diff --git a/app/helpers/sync_message_helper.rb b/app/helpers/sync_message_helper.rb new file mode 100644 index 000000000..d4f11c0f5 --- /dev/null +++ b/app/helpers/sync_message_helper.rb @@ -0,0 +1,5 @@ +module SyncMessageHelper +  def criticity_class criticity +    return criticity == 'error' ? 'danger' : criticity +  end +end diff --git a/app/inputs/search_stop_area_input.rb b/app/inputs/search_stop_area_input.rb index e5cfafc34..c7e21e921 100644 --- a/app/inputs/search_stop_area_input.rb +++ b/app/inputs/search_stop_area_input.rb @@ -1,5 +1,5 @@  class SearchStopAreaInput < Formtastic::Inputs::SearchInput -   +    def search      if options[:json]        tokenLimit = options[:tokenLimit].present? ? options[:tokenLimit] : "null" @@ -16,19 +16,19 @@ class SearchStopAreaInput < Formtastic::Inputs::SearchInput             var item_localization = function( item){                var localization = item.zip_code + ' ' + item.short_city_name; -              return localization;          +              return localization;             }; -           var item_format = function( item ){                        -              var name = item_name( item );   +           var item_format = function( item ){ +              var name = item_name( item );                var localization = item_localization( item ); -               +                html_result = '<li>';                html_result += '<span><image src=\"' + item.stop_area_path + '\" height=\"25px\" width=\"25px\"></span>'                if(name != '')                { -                html_result += '<span style=\"height:25px; line-height:25px; margin-left: 5px; \">' + name + '</span>' ;     -              }               +                html_result += '<span style=\"height:25px; line-height:25px; margin-left: 5px; \">' + name + '</span>' ; +              }                if(localization != '')                {                  html_result += '<small style=\"height:25px; line-height:25px; margin-left: 10px; color: #555; \">' + localization + '</small>'; @@ -48,7 +48,7 @@ class SearchStopAreaInput < Formtastic::Inputs::SearchInput               noResultsText: '#{options[:no_result_text]}',               searchingText: '#{options[:searching_text]}',               resultsFormatter: item_format, -             tokenFormatter: item_format,              +             tokenFormatter: item_format,             });          });").html_safe)      end @@ -62,7 +62,7 @@ class SearchStopAreaInput < Formtastic::Inputs::SearchInput      end    end -  def input_html_options     +  def input_html_options      css_class =  super[:class]      super.merge({                    :required          => nil, diff --git a/app/models/chouette/for_alighting_enumerations.rb b/app/models/chouette/for_alighting_enumerations.rb index 4f34927d3..ab07a670d 100644 --- a/app/models/chouette/for_alighting_enumerations.rb +++ b/app/models/chouette/for_alighting_enumerations.rb @@ -2,7 +2,7 @@ module Chouette    module ForAlightingEnumerations      extend Enumerize      extend ActiveModel::Naming -     +      enumerize :for_alighting, in: %w[normal forbidden request_stop is_flexible]    end  end diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb index c3a867caa..80b901bd4 100644 --- a/app/models/chouette/line.rb +++ b/app/models/chouette/line.rb @@ -1,8 +1,13 @@  class Chouette::Line < Chouette::ActiveRecord    include DefaultNetexAttributesSupport    include LineRestrictions -    include LineReferentialSupport +  include StifTransportModeEnumerations + +  extend Enumerize +  extend ActiveModel::Naming + +  enumerize :transport_submode, in: %i(unknown undefined internationalFlight domesticFlight intercontinentalFlight domesticScheduledFlight shuttleFlight intercontinentalCharterFlight internationalCharterFlight roundTripCharterFlight sightseeingFlight helicopterService domesticCharterFlight SchengenAreaFlight airshipService shortHaulInternationalFlight canalBarge localBus regionalBus expressBus nightBus postBus specialNeedsBus mobilityBus mobilityBusForRegisteredDisabled sightseeingBus shuttleBus highFrequencyBus dedicatedLaneBus schoolBus schoolAndPublicServiceBus railReplacementBus demandAndResponseBus airportLinkBus internationalCoach nationalCoach shuttleCoach regionalCoach specialCoach schoolCoach sightseeingCoach touristCoach commuterCoach metro tube urbanRailway local highSpeedRail suburbanRailway regionalRail interregionalRail longDistance intermational sleeperRailService nightRail carTransportRailService touristRailway railShuttle replacementRailService specialTrain crossCountryRail rackAndPinionRailway cityTram localTram regionalTram sightseeingTram shuttleTram trainTram internationalCarFerry nationalCarFerry regionalCarFerry localCarFerry internationalPassengerFerry nationalPassengerFerry regionalPassengerFerry localPassengerFerry postBoat trainFerry roadFerryLink airportBoatLink highSpeedVehicleService highSpeedPassengerService sightseeingService schoolBoat cableFerry riverBus scheduledFerry shuttleFerryService telecabin cableCar lift chairLift dragLift telecabinLink funicular streetCableCar allFunicularServices undefinedFunicular)    # FIXME http://jira.codehaus.org/browse/JRUBY-6358    self.primary_key = "id" @@ -19,7 +24,6 @@ class Chouette::Line < Chouette::ActiveRecord    accepts_nested_attributes_for :footnotes, :reject_if => :all_blank, :allow_destroy => true    attr_reader :group_of_line_tokens -  attr_accessor :transport_mode    # validates_presence_of :network    # validates_presence_of :company @@ -32,6 +36,9 @@ class Chouette::Line < Chouette::ActiveRecord    validates_presence_of :name +  scope :by_text, ->(text) { where('lower(name) LIKE :t or lower(published_name) LIKE :t or lower(objectid) LIKE :t or lower(comment) LIKE :t or lower(number) LIKE :t', +    t: "%#{text.downcase}%") } +    def self.nullable_attributes      [:published_name, :number, :comment, :url, :color, :text_color, :stable_id]    end @@ -40,22 +47,6 @@ class Chouette::Line < Chouette::ActiveRecord      Chouette::Geometry::LinePresenter.new self    end -  def transport_mode -    # return nil if transport_mode_name is nil -    transport_mode_name && Chouette::TransportMode.new( transport_mode_name.underscore) -  end - -  def transport_mode=(transport_mode) -    self.transport_mode_name = (transport_mode ? transport_mode.camelcase : nil) -  end - -  @@transport_modes = nil -  def self.transport_modes -    @@transport_modes ||= Chouette::TransportMode.all.select do |transport_mode| -      transport_mode.to_i > 0 -    end -  end -    def commercial_stop_areas      Chouette::StopArea.joins(:children => [:stop_points => [:route => :line] ]).where(:lines => {:id => self.id}).uniq    end diff --git a/app/models/chouette/route.rb b/app/models/chouette/route.rb index 8949a6bc2..020220a19 100644 --- a/app/models/chouette/route.rb +++ b/app/models/chouette/route.rb @@ -1,14 +1,17 @@  class Chouette::Route < Chouette::TridentActiveRecord    include RouteRestrictions +  extend Enumerize +  extend ActiveModel::Naming + +  enumerize :direction, in: %i(straight_forward backward clockwise counter_clockwise north north_west west south_west south south_east east north_east) +  enumerize :wayback, in: %i(straight_forward backward) +    # FIXME http://jira.codehaus.org/browse/JRUBY-6358    self.primary_key = "id" -  attr_accessor :wayback_code -  attr_accessor :direction_code -    def self.nullable_attributes -    [:published_name, :comment, :number, :name] +    [:published_name, :comment, :number, :name, :direction, :wayback]    end    belongs_to :line @@ -61,10 +64,10 @@ class Chouette::Route < Chouette::TridentActiveRecord    # validates_presence_of :name    validates_presence_of :line -  # validates_presence_of :direction_code -  # validates_presence_of :wayback_code +  # validates_presence_of :direction +  # validates_presence_of :wayback -  before_destroy :dereference_opposite_route +  validates :wayback, inclusion: { in: self.wayback.values }    after_commit :journey_patterns_control_route_sections @@ -72,9 +75,25 @@ class Chouette::Route < Chouette::TridentActiveRecord      Chouette::Geometry::RoutePresenter.new self    end -  def dereference_opposite_route -    self.line.routes.each do |r| -      r.update_attributes( :opposite_route => nil) if r.opposite_route == self +  @@opposite_waybacks = { straight_forward: :backward, backward: :straight_forward} +  def opposite_wayback +    @@opposite_waybacks[wayback.to_sym] +  end + +  def opposite_route_candidates +    if opposite_wayback +      line.routes.where(opposite_route: [nil, self], wayback: opposite_wayback) +    else +      self.class.none +    end +  end + +  validate :check_opposite_route +  def check_opposite_route +    return unless opposite_route && opposite_wayback + +    unless opposite_route_candidates.include?(opposite_route) +      errors.add(:opposite_route_id, :invalid)      end    end @@ -96,52 +115,6 @@ class Chouette::Route < Chouette::TridentActiveRecord          .order( "vehicle_journey_at_stops.departure_time")    end -  def self.direction_binding -    { "A" => "straight_forward", -      "R" => "backward", -      "ClockWise" => "clock_wise", -      "CounterClockWise" => "counter_clock_wise", -      "North" => "north", -      "NorthWest" => "north_west", -      "West" => "west", -      "SouthWest" => "south_west", -      "South" => "south", -      "SouthEast" => "south_east", -      "East" => "east", -      "NorthEast" => "north_east"} -  end -  def direction_code -    return nil if self.class.direction_binding[direction].nil? -    Chouette::Direction.new( self.class.direction_binding[direction]) -  end -  def direction_code=(direction_code) -    self.direction = nil -    self.class.direction_binding.each do |k,v| -      self.direction = k if v==direction_code -    end -  end -  @@directions = nil -  def self.directions -    @@directions ||= Chouette::Direction.all -  end -  def self.wayback_binding -    { "A" => "straight_forward", "R" => "backward"} -  end -  def wayback_code -    return nil if self.class.wayback_binding[wayback].nil? -    Chouette::Wayback.new( self.class.wayback_binding[wayback]) -  end -  def wayback_code=(wayback_code) -    self.wayback = nil -    self.class.wayback_binding.each do |k,v| -      self.wayback = k if v==wayback_code -    end -  end -  @@waybacks = nil -  def self.waybacks -    @@waybacks ||= Chouette::Wayback.all -  end -    def stop_point_permutation?( stop_point_ids)      stop_points.map(&:id).map(&:to_s).sort == stop_point_ids.map(&:to_s).sort    end diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index 9af80fbb7..abe6186a7 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -4,8 +4,8 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord    self.primary_key = "id"    acts_as_taggable -   -  attr_accessor :monday,:tuesday,:wednesday,:thursday,:friday,:saturday,:sunday   + +  attr_accessor :monday,:tuesday,:wednesday,:thursday,:friday,:saturday,:sunday    attr_accessor :tag_search    def self.ransackable_attributes auth_object = nil @@ -70,6 +70,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord      return false unless self.end_date      self.end_date <= expected_date    end +    def validity_out_between?(starting_date, ending_date)      return false unless self.start_date      starting_date < self.end_date  && @@ -414,7 +415,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord    # remove dates form tt which aren't in another_tt    def intersect!(another_tt)      transaction do -       +        # transform tt as effective dates and get common ones        days = another_tt.intersects(self.effective_days) & self.intersects(another_tt.effective_days)        self.dates.clear diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb index 17d4d952f..b4bd38850 100644 --- a/app/models/chouette/vehicle_journey.rb +++ b/app/models/chouette/vehicle_journey.rb @@ -1,6 +1,7 @@  module Chouette    class VehicleJourney < TridentActiveRecord      include VehicleJourneyRestrictions +    include StifTransportModeEnumerations      # FIXME http://jira.codehaus.org/browse/JRUBY-6358      self.primary_key = "id" @@ -8,7 +9,6 @@ module Chouette      default_scope { where(journey_category: journey_categories[:timed]) } -    attr_accessor :transport_mode_name      attr_reader :time_table_tokens      def self.nullable_attributes @@ -43,27 +43,10 @@ module Chouette      accepts_nested_attributes_for :vehicle_journey_at_stops, :allow_destroy => true -      def presenter        @presenter ||= ::VehicleJourneyPresenter.new( self)      end -    def transport_mode_name -      # return nil if transport_mode is nil -      transport_mode && Chouette::TransportMode.new( transport_mode.underscore) -    end - -    def transport_mode_name=(transport_mode_name) -      self.transport_mode = (transport_mode_name ? transport_mode_name.camelcase : nil) -    end - -    @@transport_mode_names = nil -    def self.transport_mode_names -      @@transport_mode_names ||= Chouette::TransportMode.all.select do |transport_mode_name| -        transport_mode_name.to_i > 0 -      end -    end -      def increasing_times        previous = nil        vehicle_journey_at_stops.select{|vjas| vjas.departure_time && vjas.arrival_time}.each do |vjas| diff --git a/app/models/chouette_transport_mode_enumerations.rb b/app/models/chouette_transport_mode_enumerations.rb new file mode 100644 index 000000000..30e9100fc --- /dev/null +++ b/app/models/chouette_transport_mode_enumerations.rb @@ -0,0 +1,6 @@ +module ChouetteTransportModeEnumerations +  extend Enumerize + +  enumerize :transport_mode, in: %w(interchange unknown coach air waterborne bus ferry walk +    metro shuttle rapid_transit taxi local_train train long_distance_train tramway trolleybus private_vehicle bicycle other) +end diff --git a/app/models/clean_up.rb b/app/models/clean_up.rb index 1a03b0fb1..a44bb46a4 100644 --- a/app/models/clean_up.rb +++ b/app/models/clean_up.rb @@ -1,151 +1,67 @@ -class CleanUp -  include ActiveModel::Validations -  include ActiveModel::Conversion -  extend ActiveModel::Naming +class CleanUp < ActiveRecord::Base +  include AASM +  belongs_to :referential +  has_one :clean_up_result -  attr_accessor :expected_date, :keep_lines, :keep_stops , :keep_companies -  attr_accessor :keep_networks, :keep_group_of_lines +  validates :begin_date, presence: true +  after_commit :perform_cleanup, :on => :create -  validates_presence_of :expected_date - -  def initialize(attributes = {}) -    attributes.each do |name, value| -      send("#{name}=", value) -    end +  def perform_cleanup +    CleanUpWorker.perform_async(self.id)    end -  def persisted? -    false +  def clean +    result = {} +    result['time_table_count']      = self.clean_time_tables +    result['vehicle_journey_count'] = self.clean_vehicle_journeys +    result['journey_pattern_count'] = self.clean_journey_patterns +    result    end -  def vehicle_journeys -    Chouette::VehicleJourney.where "id not in (select distinct vehicle_journey_id from time_tables_vehicle_journeys)" +  def clean_time_tables +    Chouette::TimeTable.validity_out_between?(begin_date, end_date).delete_all    end -  def journey_patterns -    Chouette::JourneyPattern.where "id not in (select distinct journey_pattern_id from vehicle_journeys)" +  def clean_vehicle_journeys +    ids = Chouette::VehicleJourney.includes(:time_tables).where(:time_tables => {id: nil}).pluck(:id) +    Chouette::VehicleJourney.where(id: ids).delete_all    end -  def routes -    Chouette::Route.where "id not in (select distinct route_id from journey_patterns)" +  def clean_journey_patterns +    ids = Chouette::JourneyPattern.includes(:vehicle_journeys).where(:vehicle_journeys => {id: nil}).pluck(:id) +    Chouette::JourneyPattern.where(id: ids).delete_all    end -  def lines -    Chouette::Line.where "id not in (select distinct line_id from routes)" -  end +  aasm column: :status do +    state :new, :initial => true +    state :pending +    state :successful +    state :failed -  def physical_stop_areas -    Chouette::StopArea.physical -  end +    event :run, after: :log_pending do +      transitions :from => [:new, :failed], :to => :pending +    end -  def commercial_stop_areas -    Chouette::StopArea.commercial -  end +    event :successful, after: :log_successful do +      transitions :from => [:pending, :failed], :to => :successful +    end -  def stop_place_stop_areas -    Chouette::StopArea.stop_place +    event :failed, after: :log_failed do +      transitions :from => :pending, :to => :failed +    end    end -  def itl_stop_areas -    Chouette::StopArea.itl +  def log_pending +    update_attribute(:started_at, Time.now)    end -  def clean -    # as foreign keys are presents , delete method can be used for faster performance -    result = CleanUpResult.new -    # find and remove time_tables -    tms = Chouette::TimeTable.validity_out_from_on?(Date.parse(expected_date)) -    result.time_table_count = tms.size -    tms.each do |tm| -      tm.delete -    end -    # remove vehiclejourneys without timetables -    vehicle_journeys.find_each do |vj| -      if vj.time_tables.size == 0 -        result.vehicle_journey_count += 1 -        vj.delete -      end -    end -    # remove journeypatterns without vehicle journeys -    journey_patterns.find_each do |jp| -      if jp.vehicle_journeys.size == 0 -        result.journey_pattern_count += 1 -        jp.delete -      end -    end -    # remove routes without journeypatterns -    routes.find_each do |r| -      if r.journey_patterns.size == 0 -        result.route_count += 1 -        r.delete -      end -    end -    # if asked remove lines without routes -    if keep_lines == "0" -      lines.find_each do |l| -        if l.routes.size == 0 -          result.line_count += 1 -          l.delete -        end -      end -    end -    # if asked remove stops without children (recurse) -    if keep_stops == "0" -      physical_stop_areas.find_each do |bp| -        if bp.stop_points.size == 0 -          result.stop_count += 1 -          bp.delete -        end -      end -      commercial_stop_areas.find_each do |csp| -        if csp.children.size == 0 -          result.stop_count += 1 -          csp.delete -        end -      end -      stop_place_stop_areas.find_each do |sp| -        if sp.children.size == 0 -          result.stop_count += 1 -          sp.delete -        end -      end -      itl_stop_areas.find_each do |itl| -        if itl.routing_stops.size == 0 -          result.stop_count += 1 -          itl.delete -        end -      end -    end -    # if asked remove companies without lines or vehicle journeys -    if keep_companies == "0" -      Chouette::Company.find_each do |c| -        if c.lines.size == 0 -          result.company_count += 1 -          c.delete -        end -      end -    end - -    # if asked remove networks without lines -    if keep_networks == "0" -      Chouette::Network.find_each do |n| -        if n.lines.size == 0 -          result.network_count += 1 -          n.delete -        end -      end -    end - -    # if asked remove group_of_lines without lines -    if keep_group_of_lines == "0" -      Chouette::GroupOfLine.find_each do |n| -        if n.lines.size == 0 -          result.group_of_line_count += 1 -          n.delete -        end -      end -    end -    result +  def log_successful message_attributs +    update_attribute(:ended_at, Time.now) +    CleanUpResult.create(clean_up: self, message_key: :successfull, message_attributs: message_attributs)    end +  def log_failed message_attributs +    update_attribute(:ended_at, Time.now) +    CleanUpResult.create(clean_up: self, message_key: :failed, message_attributs: message_attributs) +  end  end diff --git a/app/models/clean_up_result.rb b/app/models/clean_up_result.rb index 92f326c0f..24d262deb 100644 --- a/app/models/clean_up_result.rb +++ b/app/models/clean_up_result.rb @@ -1,55 +1,3 @@ -class CleanUpResult -  include ActiveModel::Conversion   -  extend ActiveModel::Naming -   -  attr_accessor :time_table_count,:vehicle_journey_count,:journey_pattern_count,:route_count,:line_count -  attr_accessor :stop_count,:company_count,:network_count,:group_of_line_count -   -  def initialize() -    self.time_table_count = 0 -    self.vehicle_journey_count = 0 -    self.journey_pattern_count = 0 -    self.route_count = 0 -    self.line_count = 0 -    self.stop_count = 0 -    self.company_count = 0 -    self.network_count = 0 -    self.group_of_line_count = 0 -  end   -     -  def persisted?   -    false   -  end  - -  def notice -    a = Array.new -    a << I18n.t('clean_ups.success_tm', :count => time_table_count.to_s) -    if (vehicle_journey_count > 0)  -      a << I18n.t('clean_ups.success_vj', :count => vehicle_journey_count.to_s) -    end    -    if (journey_pattern_count > 0)  -      a << I18n.t('clean_ups.success_jp', :count => journey_pattern_count.to_s) -    end    -    if (route_count > 0)  -      a << I18n.t('clean_ups.success_r', :count => route_count.to_s) -    end    -    if (line_count > 0)  -      a << I18n.t('clean_ups.success_l', :count => line_count.to_s) -    end    -    if (company_count > 0)  -      a << I18n.t('clean_ups.success_c', :count => company_count.to_s) -    end    -    if (network_count > 0)  -      a << I18n.t('clean_ups.success_n', :count => network_count.to_s) -    end    -    if (group_of_line_count > 0)  -      a << I18n.t('clean_ups.success_g', :count => group_of_line_count.to_s) -    end    -    if (stop_count > 0)  -      a << I18n.t('clean_ups.success_sa', :count => stop_count.to_s) -    end  -    a   - -  end -   +class CleanUpResult < ActiveRecord::Base +  belongs_to :clean_up  end diff --git a/app/models/concerns/route_restrictions.rb b/app/models/concerns/route_restrictions.rb index 5a098d86f..4a21cbccf 100644 --- a/app/models/concerns/route_restrictions.rb +++ b/app/models/concerns/route_restrictions.rb @@ -8,7 +8,7 @@ module RouteRestrictions      # HUB-37      def wayback_code_limitation        return unless hub_restricted? -      errors.add( :wayback_code, I18n.t('hub.routes.wayback_code_exclusive')) if line.routes.reject {|r| r.id==id}.map(&:wayback_code).include?( wayback_code) +      errors.add( :wayback, I18n.t('hub.routes.wayback_code_exclusive')) if line.routes.reject {|r| r.id==id}.map(&:wayback).include?( wayback)      end      # HUB-37 diff --git a/app/models/line_referential.rb b/app/models/line_referential.rb index e4801a61e..8bbc32993 100644 --- a/app/models/line_referential.rb +++ b/app/models/line_referential.rb @@ -1,13 +1,12 @@  class LineReferential < ActiveRecord::Base    has_many :line_referential_memberships    has_many :organisations, through: :line_referential_memberships -    has_many :lines, class_name: 'Chouette::Line'    has_many :group_of_lines, class_name: 'Chouette::GroupOfLine'    has_many :companies, class_name: 'Chouette::Company'    has_many :networks, class_name: 'Chouette::Network' - -  has_many :line_referential_syncs, -> { order created_at: :desc} +  has_many :line_referential_syncs, -> { order created_at: :desc } +  has_many :workbenches    def add_member(organisation, options = {})      attributes = options.merge organisation: organisation @@ -26,4 +25,8 @@ class LineReferential < ActiveRecord::Base    def last_sync      line_referential_syncs.last    end + +  def transport_modes +    Chouette::TransportMode.all.select { |tm| tm.to_i > 0 } +  end  end diff --git a/app/models/line_referential_sync_message.rb b/app/models/line_referential_sync_message.rb index c62b77689..3b6cf3367 100644 --- a/app/models/line_referential_sync_message.rb +++ b/app/models/line_referential_sync_message.rb @@ -1,6 +1,6 @@  class LineReferentialSyncMessage < ActiveRecord::Base    belongs_to :line_referential_sync -  enum criticity: [:info, :warn, :error] +  enum criticity: [:info, :warning, :error]    validates :criticity, presence: true  end diff --git a/app/models/organisation.rb b/app/models/organisation.rb index 3b8ad7e57..af1042081 100644 --- a/app/models/organisation.rb +++ b/app/models/organisation.rb @@ -14,7 +14,8 @@ class Organisation < ActiveRecord::Base    has_many :workbenches -  validates :name, :presence => true, :uniqueness => true +  validates_presence_of :name +  validates_uniqueness_of :code    after_create :add_rule_parameter_set @@ -39,16 +40,26 @@ class Organisation < ActiveRecord::Base      end    end +  def self.sync_update code, name, scope +    org = Organisation.find_or_initialize_by(code: code) +    if scope +      org.sso_attributes ||= {} +      if org.sso_attributes['functional_scope'] != scope +        org.sso_attributes['functional_scope'] = scope +        # FIXME see #1941 +        org.sso_attributes_will_change! +      end +    end +    org.name      = name +    org.synced_at = Time.now +    org.save +    org +  end +    def self.portail_sync      self.portail_api_request.each do |el| -      Organisation.find_or_create_by(code: el['code']).tap do |org| -        org.name = el['name'] -        if org.changed? -          org.synced_at = Time.now -          org.save -          puts "✓ Organisation #{org.name} has been updated" unless Rails.env.test? -        end -      end +      org = self.sync_update el['code'], el['name'], el['functional_scope'] +      puts "✓ Organisation #{org.name} has been updated" unless Rails.env.test?      end    end  end diff --git a/app/models/referential.rb b/app/models/referential.rb index dedf2aabd..84bc1110d 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -8,6 +8,7 @@ class Referential < ActiveRecord::Base    validates_presence_of :time_zone    validates_presence_of :upper_corner    validates_presence_of :lower_corner +    validates_uniqueness_of :slug    validates_uniqueness_of :name    validates_format_of :slug, :with => %r{\A[a-z][0-9a-z_]+\Z} @@ -26,18 +27,30 @@ class Referential < ActiveRecord::Base    validates_presence_of :organisation    belongs_to :line_referential -  # validates_presence_of :line_referential -  has_many :lines, through: :line_referential +  validates_presence_of :line_referential + +  belongs_to :created_from, class_name: 'Referential' +  has_many :associated_lines, through: :line_referential, source: :lines    has_many :companies, through: :line_referential    has_many :group_of_lines, through: :line_referential    has_many :networks, through: :line_referential +  has_many :metadatas, class_name: "ReferentialMetadata", inverse_of: :referential, dependent: :destroy +  accepts_nested_attributes_for :metadatas +    belongs_to :stop_area_referential -  # validates_presence_of :stop_area_referential +  validates_presence_of :stop_area_referential    has_many :stop_areas, through: :stop_area_referential -    belongs_to :workbench +  def lines +    if metadatas.blank? +      workbench ? workbench.lines : associated_lines +    else +      metadatas_lines +    end +  end +    def slug_excluded_values      if ! slug.nil?        if slug.start_with? "pg_" @@ -108,6 +121,22 @@ class Referential < ActiveRecord::Base      self    end +  def self.new_from from +    Referential.new({ +      name: I18n.t("activerecord.copy", :name => from.name), +      slug: "#{from.slug}_clone", +      prefix: from.prefix, +      time_zone: from.time_zone, +      bounds: from.bounds, +      organisation: from.organisation, +      line_referential: from.line_referential, +      stop_area_referential: from.stop_area_referential, +      workbench: from.workbench, +      created_from: from, +      metadatas: from.metadatas.map { |m| ReferentialMetadata.new_from(m) } +    }) +  end +    def self.available_srids      [        [ "RGF 93 Lambert 93 (2154)", 2154 ], @@ -144,17 +173,98 @@ class Referential < ActiveRecord::Base      projection_type || ""    end +  before_validation :assign_line_and_stop_area_referential, :on => :create, if: :workbench, unless: :created_from +  before_validation :clone_associations, :on => :create, if: :created_from    before_create :create_schema + +  after_create :clone_schema, if: :created_from + +  before_destroy :destroy_schema +  before_destroy :destroy_jobs + +  def in_workbench? +    workbench_id.present? +  end + +  def init_metadatas(attributes = {}) +    metadatas.build attributes if metadatas.blank? +  end + +  def clone_associations +    self.organisation          = created_from.organisation +    self.line_referential      = created_from.line_referential +    self.stop_area_referential = created_from.stop_area_referential +    self.workbench             = created_from.workbench +  end + +  def clone_metadatas +    created_from.metadatas.each do |meta| +      self.metadatas << ReferentialMetadata.new_from(meta) +    end +  end + +  def metadatas_period +    # FIXME +    if metadatas.present? +      metadatas.first.periodes.first +    end +  end +  alias_method :validity_period, :metadatas_period + +  def metadatas_lines +    # FIXME +    metadatas.present? ? metadatas.first.lines : [] +  end + +  def overlapped_referential_ids +    return [] unless metadatas.present? + +    line_ids = metadatas.first.line_ids +    period = metadatas.first.periodes.first + +    return [] unless line_ids.present? && period + +    not_myself = "and referential_id != #{id}" if persisted? + +    query = "SELECT distinct(referential_id) FROM +    (SELECT unnest(public.referential_metadata.line_ids) as line, unnest(public.referential_metadata.periodes) as period, public.referential_metadata.referential_id +     FROM public.referential_metadata +     INNER JOIN public.referentials ON public.referential_metadata.referential_id = public.referentials.id +     WHERE public.referentials.workbench_id = 1 and public.referentials.archived_at is null) as metadatas +    WHERE line in (#{line_ids.join(',')}) and period && '#{ActiveRecord::ConnectionAdapters::PostgreSQLColumn.range_to_string(period)}' #{not_myself};" + +    self.class.connection.select_values(query).map(&:to_i) +  end + +  def metadatas_overlap? +    overlapped_referential_ids.present? +  end + +  validate :detect_overlapped_referentials + +  def detect_overlapped_referentials +    self.class.where(id: overlapped_referential_ids).each do |referential| +      errors.add :metadatas, I18n.t("referentials.errors.overlapped_referential", :referential => referential.name) +    end +  end + +  def clone_schema +    ReferentialCloning.create(source_referential: self.created_from, target_referential: self) +  end +    def create_schema      Apartment::Tenant.create slug    end -  before_destroy :destroy_schema +  def assign_line_and_stop_area_referential +    self.line_referential = workbench.line_referential +    self.stop_area_referential = workbench.stop_area_referential +  end +    def destroy_schema      Apartment::Tenant.drop slug    end -  before_destroy :destroy_jobs    def destroy_jobs      #Ievkit.delete_jobs(slug)      true @@ -199,7 +309,7 @@ class Referential < ActiveRecord::Base      GeoRuby::SimpleFeatures::Geometry.from_ewkt(bounds.present? ? bounds : default_bounds ).envelope    end -  # Archive +  # Archive    def archived?      archived_at != nil    end @@ -209,8 +319,13 @@ class Referential < ActiveRecord::Base      touch :archived_at    end    def unarchive! +    return false unless can_unarchive?      # self.archived = false      update_column :archived_at, nil    end +  def can_unarchive? +    not metadatas_overlap? +  end +  end diff --git a/app/models/referential_cloning.rb b/app/models/referential_cloning.rb new file mode 100644 index 000000000..9bf824ac5 --- /dev/null +++ b/app/models/referential_cloning.rb @@ -0,0 +1,38 @@ +class ReferentialCloning < ActiveRecord::Base +  include AASM +  belongs_to :source_referential, class_name: 'Referential' +  belongs_to :target_referential, class_name: 'Referential' +  after_commit :perform_clone, :on => :create + +  private +  def perform_clone +    ReferentialCloningWorker.perform_async(self.id) +  end + +  aasm column: :status do +    state :new, :initial => true +    state :pending +    state :successful +    state :failed + +    event :run, after: :update_started_at do +      transitions :from => [:new, :failed], :to => :pending +    end + +    event :successful, after: :update_ended_at do +      transitions :from => [:pending, :failed], :to => :successful +    end + +    event :failed, after: :update_ended_at do +      transitions :from => :pending, :to => :failed +    end +  end + +  def update_started_at +    update_attribute(:started_at, Time.now) +  end + +  def update_ended_at +    update_attribute(:ended_at, Time.now) +  end +end diff --git a/app/models/referential_metadata.rb b/app/models/referential_metadata.rb new file mode 100644 index 000000000..4228d2f7c --- /dev/null +++ b/app/models/referential_metadata.rb @@ -0,0 +1,70 @@ +class ReferentialMetadata < ActiveRecord::Base +  belongs_to :referential +  belongs_to :referential_source, class_name: 'Referential' +  has_array_of :lines, class_name: 'Chouette::Line' + +  validates :referential, presence: true +  validates :lines, presence: true +  validates :periodes, presence: true + +  scope :include_lines, -> (line_ids) { where('line_ids && ARRAY[?]', line_ids) } +  scope :include_dateranges, -> (dateranges) { where('periodes && ARRAY[?]', dateranges) } + +  def first_period +    periodes.first if periodes +  end + +  def first_period_begin +    @first_period_begin or first_period.try(:begin) +  end +  def first_period_begin=(date) +    periodes_will_change! unless @first_period_begin == date +    @first_period_begin = date +  end +  def first_period_end +    if @first_period_end +      @first_period_end +    else +      if first_period +        date = first_period.end +        date -= 1 if first_period.exclude_end? +        date +      end +    end +  end +  def first_period_end=(date) +    periodes_will_change! unless @first_period_end == date +    @first_period_end = date +  end + +  validate :check_first_period_end + +  def check_first_period_end +    if @first_period_begin and @first_period_end and @first_period_begin > @first_period_end +      errors.add(:first_period_end, :invalid) +    end +  end + +  before_validation :set_first_period + +  def set_first_period +    if @first_period_begin and @first_period_end and @first_period_begin <= @first_period_end +      self.periodes ||= [] +      self.periodes[0] = Range.new @first_period_begin, @first_period_end +    end +  end + +  def column_for_attribute(name) +    if %i{first_period_begin first_period_end}.include?(name.to_sym) +      ActiveRecord::ConnectionAdapters::Column.new(name, nil, "date") +    else +      super name +    end +  end + +  def self.new_from from +    from.dup.tap do |metadata| +      metadata.referential_id = nil +    end +  end +end diff --git a/app/models/route_observer.rb b/app/models/route_observer.rb new file mode 100644 index 000000000..71578c6da --- /dev/null +++ b/app/models/route_observer.rb @@ -0,0 +1,21 @@ +class RouteObserver < ActiveRecord::Observer +  observe Chouette::Route + +  def after_save(route) +    Rails.logger.debug "after_save #{route.inspect}" +    if route.opposite_route_id +      Rails.logger.debug "dereference_opposite_route all routes except #{route.opposite_route_id}" +      route.line.routes.where("id <> ?", route.opposite_route_id).where(opposite_route_id: route).update_all(opposite_route_id: nil) +      Rails.logger.debug "reference_opposite_route #{route.opposite_route_id}" +      route.opposite_route.update_column :opposite_route_id, route +    else +      Rails.logger.debug "dereference_opposite_route all routes associated to #{route.id}" +      route.line.routes.where(opposite_route_id: route).update_all(opposite_route_id: nil) +    end +  end + +  def after_destroy(route) +    Rails.logger.debug "after_destroy(#{route.inspect})" +    line.routes.where(opposite_route: route).update_all(opposite_route: nil) +  end +end diff --git a/app/models/route_section_search.rb b/app/models/route_section_search.rb index a03eb894d..bf53cdf05 100644 --- a/app/models/route_section_search.rb +++ b/app/models/route_section_search.rb @@ -13,8 +13,7 @@ class RouteSectionSearch      attributes.each { |k,v| send "#{k}=", v } if attributes    end -  def collection() -    Rails.logger.debug "Search RouteSections with #{inspect}" +  def collection      collection = scope      [:departure, :arrival].each do |endpoint| diff --git a/app/models/stif_transport_mode_enumerations.rb b/app/models/stif_transport_mode_enumerations.rb new file mode 100644 index 000000000..a9a3fc3e0 --- /dev/null +++ b/app/models/stif_transport_mode_enumerations.rb @@ -0,0 +1,5 @@ +module StifTransportModeEnumerations +  extend Enumerize + +  enumerize :transport_mode, in: %w(air bus coach ferry metro rail trolleyBus tram water cableway funicular other) +end diff --git a/app/models/stop_area_referential.rb b/app/models/stop_area_referential.rb index 5b84e6178..dd206f9e9 100644 --- a/app/models/stop_area_referential.rb +++ b/app/models/stop_area_referential.rb @@ -4,6 +4,7 @@ class StopAreaReferential < ActiveRecord::Base    has_many :stop_areas, class_name: 'Chouette::StopArea'    has_many :stop_area_referential_syncs, -> {order created_at: :desc} +  has_many :workbenches    def add_member(organisation, options = {})      attributes = options.merge organisation: organisation diff --git a/app/models/stop_area_referential_sync_message.rb b/app/models/stop_area_referential_sync_message.rb index e965297da..cd2e62405 100644 --- a/app/models/stop_area_referential_sync_message.rb +++ b/app/models/stop_area_referential_sync_message.rb @@ -1,6 +1,6 @@  class StopAreaReferentialSyncMessage < ActiveRecord::Base    belongs_to :stop_area_referential_sync -  enum criticity: [:info, :warn, :error] +  enum criticity: [:info, :warning, :error]    validates :criticity, presence: true  end diff --git a/app/models/user.rb b/app/models/user.rb index 31fda6aed..5cfdf0605 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,15 +29,10 @@ class User < ActiveRecord::Base    after_destroy :check_destroy_organisation    def cas_extra_attributes=(extra_attributes) -    extra         = extra_attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} -    self.name     = extra[:full_name] -    self.email    = extra[:email] -    self.username = extra[:username] - -    self.organisation = Organisation.find_or_create_by(code: extra[:organisation_code]).tap do |org| -      org.name      = extra[:organisation_name] -      org.synced_at = Time.now -    end +    extra             = extra_attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} +    self.name         = extra[:full_name] +    self.email        = extra[:email] +    self.organisation = Organisation.sync_update extra[:organisation_code], extra[:organisation_name], extra[:functional_scope]    end    def self.portail_api_request @@ -59,23 +54,14 @@ class User < ActiveRecord::Base    def self.portail_sync      self.portail_api_request.each do |el| -      User.find_or_create_by(username: el['username']).tap do |user| -        user.name         = "#{el['firstname']} #{el['lastname']}" -        user.email        = el['email'] -        user.locked_at    = el['locked_at'] - -        # Set organisation -        user.organisation = Organisation.find_or_create_by(code: el['organization_code']).tap do |org| -          org.name      = el['organization_name'] -          org.synced_at = Time.now -        end - -        if user.changed? -          user.synced_at = Time.now -          user.save -          puts "✓ user #{user.username} has been updated" unless Rails.env.test? -        end -      end +      user              = User.find_or_initialize_by(username: el['username']) +      user.name         = "#{el['firstname']} #{el['lastname']}" +      user.email        = el['email'] +      user.locked_at    = el['locked_at'] +      user.organisation = Organisation.sync_update el['organization_code'], el['organization_name'], el['functional_scope'] +      user.synced_at    = Time.now +      user.save +      puts "✓ user #{user.username} has been updated" unless Rails.env.test?      end    end diff --git a/app/models/workbench.rb b/app/models/workbench.rb index e4efb6bd9..419790edb 100644 --- a/app/models/workbench.rb +++ b/app/models/workbench.rb @@ -1,9 +1,17 @@  class Workbench < ActiveRecord::Base    belongs_to :organisation +  belongs_to :line_referential +  belongs_to :stop_area_referential + +  has_many :lines, -> (workbench) { Stif::MyWorkbenchScopes.new(workbench).line_scope(self) }, through: :line_referential +  has_many :networks, through: :line_referential +  has_many :companies, through: :line_referential +  has_many :group_of_lines, through: :line_referential +  has_many :stop_areas, through: :stop_area_referential    validates :name, presence: true    validates :organisation, presence: true    has_many :referentials - +  has_many :referential_metadatas, through: :referentials, source: :metadatas  end diff --git a/app/policies/line_policy.rb b/app/policies/line_policy.rb index 61cf6c1b8..92310f042 100644 --- a/app/policies/line_policy.rb +++ b/app/policies/line_policy.rb @@ -8,8 +8,8 @@ class LinePolicy < ApplicationPolicy    def create?      false    end -  def update?  ; create? end +  def update?  ; true end    def new?     ; create? end -  def edit?    ; create? end +  def edit?    ; true end    def destroy? ; create? end  end diff --git a/app/views/api/kml/routes/show.kml.slim b/app/views/api/kml/routes/show.kml.slim index 3b08d81ce..51d2817c8 100644 --- a/app/views/api/kml/routes/show.kml.slim +++ b/app/views/api/kml/routes/show.kml.slim @@ -6,11 +6,11 @@ kml xmlns="http://www.opengis.net/kml/2.2"      placemark id="#{@route.objectid}"        name = h(@route.name)        extendeddata -        - [:direction_code, :wayback_code, :objectid, :object_version, :creation_time, :creator_id, :name, :comment, :published_name, :number, :direction, :wayback].each do |prop| +        - [:direction, :wayback, :objectid, :object_version, :creation_time, :creator_id, :name, :comment, :published_name, :number, :direction_text, :wayback_text].each do |prop|            data name="#{prop.to_s}"              value = h(@route.send( prop))          data name="line_objectid"            value = h(@route.line.objectid) -      = @route.geometry_presenter.geometry.kml_representation.html_safe
\ No newline at end of file +      = @route.geometry_presenter.geometry.kml_representation.html_safe diff --git a/app/views/api/v1/lines/show.rabl b/app/views/api/v1/lines/show.rabl index dcd497aa5..16a265dfe 100644 --- a/app/views/api/v1/lines/show.rabl +++ b/app/views/api/v1/lines/show.rabl @@ -1,6 +1,6 @@  object @line  extends "api/v1/trident_objects/show" -[ :name, :number, :published_name, :transport_mode_name, :registration_number, :comment, :mobility_restricted_suitability].each do |attr| +[ :name, :number, :published_name, :transport_mode, :registration_number, :comment, :mobility_restricted_suitability].each do |attr|    attributes attr, :unless => lambda { |m| m.send( attr).nil?}  end @@ -9,6 +9,6 @@ node :network_short_description do |line|  end unless root_object.network.nil?  node :company_short_description do |line| -  partial("api/v1/companies/short_description", :object => line.company)  +  partial("api/v1/companies/short_description", :object => line.company)  end  unless root_object.company.nil? diff --git a/app/views/companies/_companies.html.slim b/app/views/companies/_companies.html.slim index 028a21af4..4f89e8ede 100644 --- a/app/views/companies/_companies.html.slim +++ b/app/views/companies/_companies.html.slim @@ -5,7 +5,7 @@  .companies.paginated_content style="margin-top:20px;"    = table_builder @decoratedcompanies,                    [:name, :edited_at, :published_at, :validity_period, :linecount, :transporter, :status], -                  ["show"], +                  ["show", "delete"],                    'table table-bordered'  .pagination diff --git a/app/views/footnotes/_footnote_fields.html.slim b/app/views/footnotes/_footnote_fields.html.slim index ab006cfa9..c1944ed2d 100644 --- a/app/views/footnotes/_footnote_fields.html.slim +++ b/app/views/footnotes/_footnote_fields.html.slim @@ -1,4 +1,4 @@  = f.inputs :class => 'nested-fields footnote' do    = f.input :code, :wrapper_html => { class: 'col-md-3' }    = f.input :label, :wrapper_html => { class: 'col-md-7' } -  = link_to_remove_association t('actions.destroy'), f, class: 'col-md-2 remove'
\ No newline at end of file +  = link_to_remove_association t('actions.destroy'), f, class: 'col-md-2 remove' diff --git a/app/views/line_referentials/show.html.slim b/app/views/line_referentials/show.html.slim index 406da8fee..3e9cab269 100644 --- a/app/views/line_referentials/show.html.slim +++ b/app/views/line_referentials/show.html.slim @@ -25,17 +25,19 @@    h3 Historique des synchronisations    ul.list-group width="75%" -  - @line_referential.line_referential_syncs.each do |sync| -    - unless sync.line_referential_sync_messages.empty? -      - sync.line_referential_sync_messages.last.tap do |log| -        - if log.criticity = log.criticity -          li.alert class="alert-#{log.criticity}" -            strong = l(log.created_at, format: :short) + " : " -            / [:processing_time] unit conversion -            - data = log.message_attributs.symbolize_keys! -            - data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) - -            = t("line_referential_sync.message.#{log.message_key}", log.message_attributs.symbolize_keys!) +  - @line_referential.line_referential_syncs.each_with_index do |sync, i| +    / Display only 10 msgs +    - if i < 10 +      - unless sync.line_referential_sync_messages.empty? +        - sync.line_referential_sync_messages.last.tap do |log| +          - if log.criticity = log.criticity +            li.alert class="alert-#{criticity_class(log.criticity)}" +              strong = l(log.created_at, format: :short) + " : " +              / [:processing_time] unit conversion +              - data = log.message_attributs.symbolize_keys! +              - data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) + +              = t("line_referential_sync.message.#{log.message_key}", log.message_attributs.symbolize_keys!)  - content_for :sidebar do    ul.actions diff --git a/app/views/lines/_form.html.slim b/app/views/lines/_form.html.slim index 113a5c46c..cbb50ae28 100644 --- a/app/views/lines/_form.html.slim +++ b/app/views/lines/_form.html.slim @@ -6,7 +6,7 @@      = form.input :published_name      = form.input :registration_number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@line_referential)}.line.registration_number")}      = form.input :number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@line_referential)}.line.number") } -    = form.input :transport_mode, as: :select, :collection => Chouette::Line.transport_modes, :include_blank => false, :member_label => Proc.new { |mode| t("transport_modes.label.#{mode}") } +    = form.input :transport_mode, include_blank: false      = form.input :color, as: :string      = form.input :text_color      = form.input :stable_id @@ -19,11 +19,11 @@      .footnotes_block        h3 = t("footnotes.index.title") -       +        #footnotes          = form.semantic_fields_for :footnotes do |f|            = render "footnotes/footnote_fields",  :f => f -         +        .add_footnote          = link_to_add_association t("footnotes.actions.add_footnote"), form, :footnotes , :partial => "footnotes/footnote_fields", :"data-association-insertion-method" => "append", :"data-association-insertion-node" => "div#footnotes", class: 'add' @@ -32,7 +32,7 @@      = form.action :cancel, as: :link  javascript: -	$(function() { +  $(function() {      $("#line_group_of_line_tokens").tokenInput("#{name_filter_referential_group_of_lines_path(@line_referential, format: :json)}", {        crossDomain: false,        prePopulate: $('#group_of_line_tokens').data('pre'), @@ -42,4 +42,4 @@ javascript:        noResultsText: "#{I18n.t('no_result_text')}",        searchingText: "#{I18n.t('searching_term')}"      }); -	});
\ No newline at end of file +  }); diff --git a/app/views/lines/_lines.html.slim b/app/views/lines/_lines.html.slim index 7de88c2c3..638fdfb6d 100644 --- a/app/views/lines/_lines.html.slim +++ b/app/views/lines/_lines.html.slim @@ -6,4 +6,4 @@    = paginated_content(@lines)  .pagination -  = will_paginate @lines, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer
\ No newline at end of file +  = will_paginate @lines, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim index bf83486eb..d2ab3f087 100644 --- a/app/views/lines/index.html.slim +++ b/app/views/lines/index.html.slim @@ -1,28 +1,6 @@  = title_tag t('lines.index.title') -= search_form_for @q, url: line_referential_lines_path(@line_referential), remote: true, html: {method: :get, class: "form", id: "search", role: "form"} do |f| -  .well.well-sm -    .input-group -      = f.text_field :name_or_number_or_objectid_cont, placeholder: t('.name_or_number_or_objectid'), class: 'form-control' -       -      .input-group-btn -        button.btn.btn-primary type="submit" -          span.fa.fa-search - -= search_form_for @q, url: line_referential_lines_path(@line_referential), remote: true, html: {method: :get, class: "form", id: "search", role: "form"} do |f| -  .well.well-sm -    .row -      .col-md-10.col-sm-9 -        .row -          .col-md-4.col-sm-4 -            = f.select(:network_id_eq, @line_referential.networks.collect {|n| [ n.name, n.id ] }.unshift([t('.no_networks'), -1]), {include_blank: t('.all_networks')}, {class: 'form-control'}) -          .col-md-4.col-sm-4 -            = f.select(:company_id_eq, @line_referential.companies.collect {|c| [ c.name, c.id ] }.unshift([t('.no_companies'), -1]), {include_blank: t('.all_companies')}, {class: 'form-control'}) -          .col-md-4.col-sm-4 -            = f.select(:group_of_lines_id_eq, @line_referential.group_of_lines.collect {|c| [ c.name, c.id ] }.unshift([t('.no_group_of_lines'), -1]), {include_blank: t('.all_group_of_lines')}, {class: 'form-control'}) -         -      .col-md-2.col-sm-3 -        button.btn.btn-primary.btn-block type="submit" Filtrer += render partial: 'shared/lines_search_form', locals: { referential_type: 'line_referential' }  #lines    = render 'lines' @@ -33,22 +11,23 @@        li          = link_to t('lines.actions.new'), new_line_referential_line_path(@line_referential), class: 'add' -  #multiple_selection_menu -    h4 = t('.multi_selection') +  - if policy(Chouette::Line).destroy? +    #multiple_selection_menu +      h4 = t('.multi_selection') -    .disabled -      a.enable href="#" -        = t('.multi_selection_enable') +      .disabled +        a.enable href="#" +          = t('.multi_selection_enable') -    .enabled style="display: none;" -      a.disable href="#" -        = t('.multi_selection_disable') +      .enabled style="display: none;" +        a.disable href="#" +          = t('.multi_selection_disable') -      ul.actions -        = link_to t('.delete_selected'), line_referential_lines_path(@line_referential), "data-multiple-method" => "delete", class: 'remove', "confirmation-text" => t("lines.actions.destroy_selection_confirm") +        ul.actions +          = link_to t('.delete_selected'), line_referential_lines_path(@line_referential), "data-multiple-method" => "delete", class: 'remove', "confirmation-text" => t("lines.actions.destroy_selection_confirm") -      a.select_all href="#" -        = t('.select_all') -      = " | " -      a.deselect_all href="#" -        = t('.deselect_all') +        a.select_all href="#" +          = t('.select_all') +        = " | " +        a.deselect_all href="#" +          = t('.deselect_all') diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim index cca0e395c..636313d54 100644 --- a/app/views/lines/show.html.slim +++ b/app/views/lines/show.html.slim @@ -4,8 +4,6 @@  = title_tag t('lines.show.title', line: @line.name)  .line_show -  = @map.to_html -    .summary      - text_color = @line.text_color.blank? ? "black" : "##{@line.text_color}"      - bg_color = @line.color.blank? ? "white" : "##{@line.color}" @@ -23,18 +21,17 @@      p        label = "#{@line.human_attribute_name(:network)} : " -    - if @line.network.nil? -      = t('lines.index.unset') -    - else -      = link_to @line.network.name, [@line_referential, @line.network] +      - if @line.network.nil? +        = t('lines.index.unset') +      - else +        = link_to @line.network.name, [@line_referential, @line.network]      p        label = "#{@line.human_attribute_name(:company)} : " - -    - if @line.company.nil? -      = t('lines.index.unset') -    - else -      = link_to @line.company.name, [@line_referential, @line.company] +      - if @line.company.nil? +        = t('lines.index.unset') +      - else +        = link_to @line.company.name, [@line_referential, @line.company]      p        label = "#{@line.human_attribute_name('number')} : " @@ -50,57 +47,67 @@      p        label = "#{@line.human_attribute_name('transport_mode')} : " -      = t("transport_modes.label.#{@line.transport_mode}") - -    p -      label = "#{@line.human_attribute_name('stable_id')} : " -      = @line.stable_id - -    p -      label = "#{@line.human_attribute_name('url')} : " -      = @line.url - -    p -      label = "#{@line.human_attribute_name('mobility_restricted_suitability')} : " - -      - if @line.mobility_restricted_suitability.nil? -        = @line.human_attribute_name("unspecified_mrs") -      - elsif @line.mobility_restricted_suitability? -        = @line.human_attribute_name("accessible") +      - if @line.transport_mode +        = " " + t("enumerize.line.transport_mode.#{@line.transport_mode}")        - else -        = @line.human_attribute_name("not_accessible") - -      br -      = "#{@line.human_attribute_name('number_of_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', true).count}" -      br -      = "#{@line.human_attribute_name('number_of_non_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', false).count}" -      br -      = @line.human_attribute_name("number_of_null_mrs_vj") -      = " : " -      = @line.vehicle_journeys.count - (@line.vehicle_journeys.where("mobility_restricted_suitability = ?", true).count + @line.vehicle_journeys.where("mobility_restricted_suitability = ?", false).count) +        = " -"      p -      label = "#{@line.human_attribute_name('flexible_service')} : " - -      - if @line.flexible_service.nil? -        = @line.human_attribute_name("unspecified_fs") -      - elsif @line.flexible_service? -        = @line.human_attribute_name("on_demaond_fs") +      label = "#{@line.human_attribute_name('transport_submode')} : " +      - if @line.transport_submode +        = " " + t("enumerize.line.transport_submode.#{@line.transport_submode}")        - else -        = @line.human_attribute_name("regular_fs") +        = " -" -      br -      = "#{@line.human_attribute_name('number_of_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', true).count}" -      br -      = "#{@line.human_attribute_name('number_of_non_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', false).count}" -      br -      = @line.human_attribute_name("number_of_null_fs_vj") +    / p +    /   label = "#{@line.human_attribute_name('stable_id')} : " +    /   = @line.stable_id -      - if @line.flexible_service.nil? -        = "(#{@line.human_attribute_name('default_fs_msg')})" +    p +      label = "#{@line.human_attribute_name('url')} : " +      = @line.url -      = " : " -      = @line.vehicle_journeys.count - (@line.vehicle_journeys.where("flexible_service = ?", true).count + @line.vehicle_journeys.where("flexible_service = ?", false).count) +    / p +    /   label = "#{@line.human_attribute_name('mobility_restricted_suitability')} : " +    / +    /   - if @line.mobility_restricted_suitability.nil? +    /     = @line.human_attribute_name("unspecified_mrs") +    /   - elsif @line.mobility_restricted_suitability? +    /     = @line.human_attribute_name("accessible") +    /   - else +    /     = @line.human_attribute_name("not_accessible") +    / +    /   br +    /   = "#{@line.human_attribute_name('number_of_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', true).count}" +    /   br +    /   = "#{@line.human_attribute_name('number_of_non_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', false).count}" +    /   br +    /   = @line.human_attribute_name("number_of_null_mrs_vj") +    /   = " : " +    /   = @line.vehicle_journeys.count - (@line.vehicle_journeys.where("mobility_restricted_suitability = ?", true).count + @line.vehicle_journeys.where("mobility_restricted_suitability = ?", false).count) +    / +    / p +    /   label = "#{@line.human_attribute_name('flexible_service')} : " +    / +    /   - if @line.flexible_service.nil? +    /     = @line.human_attribute_name("unspecified_fs") +    /   - elsif @line.flexible_service? +    /     = @line.human_attribute_name("on_demaond_fs") +    /   - else +    /     = @line.human_attribute_name("regular_fs") +    / +    /   br +    /   = "#{@line.human_attribute_name('number_of_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', true).count}" +    /   br +    /   = "#{@line.human_attribute_name('number_of_non_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', false).count}" +    /   br +    /   = @line.human_attribute_name("number_of_null_fs_vj") +    / +    /   - if @line.flexible_service.nil? +    /     = "(#{@line.human_attribute_name('default_fs_msg')})" +    / +    /   = " : " +    /   = @line.vehicle_journeys.count - (@line.vehicle_journeys.where("flexible_service = ?", true).count + @line.vehicle_journeys.where("flexible_service = ?", false).count)      p        label = "#{@line.human_attribute_name('footnotes')} : " @@ -108,26 +115,13 @@          - @line.footnotes.each do |footnote|            li = "#{footnote.code} : #{footnote.label}" -    p -      label = "#{@line.human_attribute_name('comment')} : " -      = @line.comment - -  .row -    #mobility_restricted_suitability.col-md-6 -    #flexible_service.col-md-6 - -p.after_map - -h3.routes = t('.itineraries') - -.routes.paginated_content -  / FIXME #825 -  / = paginated_content @routes, "routes/route" +    / p +    /   label = "#{@line.human_attribute_name('comment')} : " +    /   = @line.comment -- if @line.group_of_lines.any? -  h3.line_group_of_lines = t('.group_of_lines') -  .group_of_lines.paginated_content -    = paginated_content @group_of_lines, "group_of_lines/group_of_line", delete: false +  / .row +  /   #mobility_restricted_suitability.col-md-6 +  /   #flexible_service.col-md-6  - content_for :sidebar do    ul.actions diff --git a/app/views/offer_workbenches/_referential.html.slim b/app/views/offer_workbenches/_referential.html.slim deleted file mode 100644 index cc1964f30..000000000 --- a/app/views/offer_workbenches/_referential.html.slim +++ /dev/null @@ -1,34 +0,0 @@ -#index_item.panel.panel-default.referential -  .panel-heading -    .panel-title.clearfix -      span.pull-right -        .btn-group -          = link_to edit_referential_path(referential), class: 'btn btn-default btn-sm' do -            span.fa.fa-pencil - -          = link_to referential_path(referential), method: :delete, :data => {:confirm => t('referentials.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do -            span.fa.fa-trash-o - -      h5 -        = link_to [@referential, referential], class: 'preview', title: "#{Referential.model_name.human.capitalize} #{referential.name}" do -          span.name -            = truncate(referential.name, :length => 30) - -  div.panel-body id="referential_#{referential.id}" -    p -      = "#{referential.human_attribute_name('lines')} : " -      span.lines_count - -    p -      = "#{referential.human_attribute_name('networks')} : " -      span.networks_count - -    p -      = "#{referential.human_attribute_name('vehicle_journeys')} : " -      span.vehicle_journeys_count - -    p -      = "#{referential.human_attribute_name('time_tables')} : " -      span.time_tables_count -     -= javascript_include_tag referential_path(referential, format: :js)
\ No newline at end of file diff --git a/app/views/offer_workbenches/show.html.slim b/app/views/offer_workbenches/show.html.slim deleted file mode 100644 index 49396a0e2..000000000 --- a/app/views/offer_workbenches/show.html.slim +++ /dev/null @@ -1,5 +0,0 @@ -= title_tag "#{@workbench.name} - Tableau de bord" - -.referentials.paginated_content -  h4 Liste des jeux de données -  = paginated_content @workbench.referentials diff --git a/app/views/referential_companies/_company.html.slim b/app/views/referential_companies/_company.html.slim index 06e13764e..e6090540d 100644 --- a/app/views/referential_companies/_company.html.slim +++ b/app/views/referential_companies/_company.html.slim @@ -2,10 +2,12 @@    .panel-heading      .panel-title.clearfix        span.pull-right -        = link_to edit_referential_company_path(@referential, company), class: 'btn btn-default btn-sm' do -          span.fa.fa-pencil -        = link_to referential_company_path(@referential, company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do -          span.fa.fa-trash-o +        - if policy(company).update? +          = link_to edit_referential_company_path(@referential, company), class: 'btn btn-default btn-sm' do +            span.fa.fa-pencil +        - if policy(company).destroy? +          = link_to referential_company_path(@referential, company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do +            span.fa.fa-trash-o        h5          = link_to [@referential, company], class: 'preview', title: "#{Chouette::Company.model_name.human.capitalize} #{company.name}" do            span.name @@ -13,4 +15,4 @@    .panel-body      p        = company.human_attribute_name('code') -      = company.code
\ No newline at end of file +      = company.code diff --git a/app/views/referential_companies/index.html.slim b/app/views/referential_companies/index.html.slim index b32f206ca..6af6d7fc8 100644 --- a/app/views/referential_companies/index.html.slim +++ b/app/views/referential_companies/index.html.slim @@ -19,6 +19,7 @@  - content_for :sidebar do    ul.actions -    li -      = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' -  br
\ No newline at end of file +    - if policy(Chouette::Company).create? +      li +        = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' +    br diff --git a/app/views/referential_companies/show.html.slim b/app/views/referential_companies/show.html.slim index a445dad61..a1a767bbd 100644 --- a/app/views/referential_companies/show.html.slim +++ b/app/views/referential_companies/show.html.slim @@ -44,12 +44,15 @@  - content_for :sidebar do    ul.actions -    li -      = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' -    li -      = link_to t('companies.actions.edit'), edit_referential_company_path(@referential, @company), class: 'edit' -    li -      = link_to  t('companies.actions.destroy'), referential_company_path(@referential, @company), :method => :delete,  :data => {:confirm =>  t('companies.actions.destroy_confirm')}, class: 'remove' -    br - -  = creation_tag(@company)
\ No newline at end of file +    - if policy(Chouette::Company).create? +      li +        = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' +    - if policy(@company).update? +      li +        = link_to t('companies.actions.edit'), edit_referential_company_path(@referential, @company), class: 'edit' +    - if policy(@company).destroy? +      li +        = link_to  t('companies.actions.destroy'), referential_company_path(@referential, @company), :method => :delete,  :data => {:confirm =>  t('companies.actions.destroy_confirm')}, class: 'remove' +      br + +  = creation_tag(@company) diff --git a/app/views/referential_lines/_form.html.slim b/app/views/referential_lines/_form.html.slim index f4e49b3a3..a4c98d43d 100644 --- a/app/views/referential_lines/_form.html.slim +++ b/app/views/referential_lines/_form.html.slim @@ -1,25 +1,25 @@  = semantic_form_for [@referential, @line] do |form|    = form.inputs do -    = form.input :network, as: :select, :collection => Chouette::Network.all, :include_blank => false -    = form.input :company, as: :select, :collection => Chouette::Company.all, :include_blank => false -    = form.input :name, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.name") } -    = form.input :published_name -    = form.input :registration_number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.registration_number") } -    = form.input :number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.number") } -    = form.input :transport_mode, as: :select, :collection => Chouette::Line.transport_modes, :include_blank => false, :member_label => Proc.new { |mode| t("transport_modes.label.#{mode}") } -    = form.input :color, as: :string -    = form.input :text_color -    = form.input :stable_id -    = form.input :url -    = form.input :mobility_restricted_suitability, as: :select, :collection => [[@line.human_attribute_name("accessible"), true], [@line.human_attribute_name("not_accessible"), false]], :include_blank => true -    = form.input :flexible_service, as: :select, :collection => [[@line.human_attribute_name("on_demaond_fs"), true], [@line.human_attribute_name("regular_fs"), false]], :include_blank => true -    = form.input :comment -    = form.input :objectid, :required => !@line.new_record?, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.objectid") } -    = form.input :group_of_line_tokens, :label => t('.group_of_lines'), as: :text,  :input_html => { :"data-pre" => ( @line.group_of_lines.map { |group_of_line| { :id => group_of_line.id, :name => group_of_line.name } } ).to_json } +    / = form.input :network, as: :select, :collection => Chouette::Network.all, :include_blank => false +    / = form.input :company, as: :select, :collection => Chouette::Company.all, :include_blank => false +    / = form.input :name, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.name") } +    / = form.input :published_name +    / = form.input :registration_number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.registration_number") } +    / = form.input :number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.number") } +    / = form.input :transport_mode, include_blank: false +    / = form.input :color, as: :string +    / = form.input :text_color +    / = form.input :stable_id +    / = form.input :url +    / = form.input :mobility_restricted_suitability, as: :select, :collection => [[@line.human_attribute_name("accessible"), true], [@line.human_attribute_name("not_accessible"), false]], :include_blank => true +    / = form.input :flexible_service, as: :select, :collection => [[@line.human_attribute_name("on_demaond_fs"), true], [@line.human_attribute_name("regular_fs"), false]], :include_blank => true +    / = form.input :comment +    / = form.input :objectid, :required => !@line.new_record?, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.line.objectid") } +    / = form.input :group_of_line_tokens, :label => t('.group_of_lines'), as: :text,  :input_html => { :"data-pre" => ( @line.group_of_lines.map { |group_of_line| { :id => group_of_line.id, :name => group_of_line.name } } ).to_json }      .footnotes_block        h3 = t("footnotes.index.title") -       +        #footnotes          = form.semantic_fields_for :footnotes do |f|            = render "footnotes/footnote_fields",  f: f @@ -42,4 +42,4 @@ javascript:        noResultsText: "#{I18n.t('no_result_text')}",        searchingText: "#{I18n.t('searching_term')}"      }); -	});
\ No newline at end of file +	}); diff --git a/app/views/referential_lines/_line.html.slim b/app/views/referential_lines/_line.html.slim index 0dffb50aa..1c8b8eaa8 100644 --- a/app/views/referential_lines/_line.html.slim +++ b/app/views/referential_lines/_line.html.slim @@ -3,7 +3,7 @@      ul.ce-LineBlock-header-list        li          = check_box_tag "ids[]", line.id, false, class: "multiple_selection", style: "display: none;" -         +          - if line.number && line.number.length <= 3            span.label.label-default.line_number style="#{number_style(line)}"              = line.number @@ -13,11 +13,11 @@            h5.ce-LineBlock-header-title = truncate(line.name, length: 24)        li -        - if edit +        - if edit && policy(Chouette::Line).update?            = link_to edit_referential_line_path(@referential, line), class: 'btn btn-default btn-sm' do              span.fa.fa-pencil -        - if delete +        - if delete && policy(Chouette::Line).destroy?            = link_to referential_line_path(@referential, line), method: :delete, data: { confirm: t('lines.actions.destroy_confirm') }, class: 'btn btn-danger btn-sm' do              span.fa.fa-trash-o @@ -46,4 +46,4 @@          = line.human_attribute_name('group_of_line')          = link_to_if( line.group_of_lines.first, line.group_of_lines.first.name, referential_group_of_line_path(@referential, line.group_of_lines.first), :title => "#{line.human_attribute_name('group_of_line')} #{line.group_of_lines.first.name}")        - else -        = t('lines.form.several_group_of_lines', :count => line.group_of_lines.count)
\ No newline at end of file +        = t('lines.form.several_group_of_lines', :count => line.group_of_lines.count) diff --git a/app/views/referential_lines/_reflines_routes.html.slim b/app/views/referential_lines/_reflines_routes.html.slim new file mode 100644 index 000000000..77b350fa6 --- /dev/null +++ b/app/views/referential_lines/_reflines_routes.html.slim @@ -0,0 +1,34 @@ +- if @routes.any? +  h3 = "Itinéraires" + +  table.table.table-bordered.table-hover +    thead +      tr +        th.text-center = @routes.human_attribute_name(:name) +        th.text-center = @routes.human_attribute_name(:published_name) +        th.text-center = @routes.human_attribute_name(:wayback) +        th.text-center = @routes.human_attribute_name(:opposite_route) +        th.text-center = "Actions" +     +    tbody +      - @routes.each do |route| +        tr +          td = truncate(route.name, length: 20) +          td = route.published_name +          td = route.wayback_text +          td +            - if route.opposite_route +              = route.opposite_route.name +            - else +              = "Aucune séquence d'arrêts associée en sens opposé" +             +          td.text-center +            .btn.btn-group.btn-group-sm +              = link_to [@referential, @line, route], class: 'btn btn-default preview', title: "#{Chouette::Route.model_name.human.capitalize} #{route.name}" do +                span.fa.fa-eye +               +              = link_to edit_referential_line_route_path(@referential, @line, route), class: 'btn btn-default' do +                span.fa.fa-pencil + +              = link_to referential_line_route_path(@referential, @line, route), method: :delete, :data => {:confirm =>  t('routes.actions.destroy_confirm')}, class: 'btn btn-danger' do +                span.fa.fa-trash-o diff --git a/app/views/referential_lines/index.html.slim b/app/views/referential_lines/index.html.slim index 4922cde85..d6fb00e6b 100644 --- a/app/views/referential_lines/index.html.slim +++ b/app/views/referential_lines/index.html.slim @@ -1,48 +1,33 @@  = title_tag t('lines.index.title') -= search_form_for @q, :url => referential_lines_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| -  .panel.panel-default -    .panel-heading -      .input-group.col-md-9 -        = f.text_field :name_or_number_cont, :placeholder => "#{t('.name_or_number')}", :class => 'form-control' -        .input-group-btn -        button.btn.btn-default type="submit" -          i.fa.fa-search - -      a data-toggle="collapse" data-parent="#search" href="#advanced_search" -        i.fa.fa-plus -        = "#{t('.advanced_search')}" - -    #advanced_search.panel-collapse.collapse -      .panel-body -        = f.select(:network_id_eq, @referential.networks.collect {|n| [ n.name, n.id ] }.unshift([t('.no_networks'), -1]), {include_blank: t('.all_networks')}, { :class => 'form-control' }) -        = f.select(:company_id_eq, @referential.companies.collect {|c| [ c.name, c.id ] }.unshift([t('.no_companies'), -1]), { include_blank: t('.all_companies')}, { :class => 'form-control' }) -        = f.select(:group_of_lines_id_eq, @referential.group_of_lines.collect {|c| [ c.name, c.id ] }.unshift([t('.no_group_of_lines'), -1]), {include_blank: t('.all_group_of_lines')}, { :class => 'form-control' }) += render partial: 'shared/lines_search_form', locals: { referential_type: 'referential' }  #lines    = render 'lines'  - content_for :sidebar do    ul.actions -    li -      = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' +    - if policy(Chouette::Line).create? +      li +        = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' -  #multiple_selection_menu -    h4> = t(".multi_selection") +  - if policy(Chouette::Line).destroy? +    #multiple_selection_menu +      h4> = t(".multi_selection") -    .disabled -      a.enable href="#" -        = t(".multi_selection_enable") +      .disabled +        a.enable href="#" +          = t(".multi_selection_enable") -    .enabled style="display: none;" -      a.disable href="#" -        = t(".multi_selection_disable") +      .enabled style="display: none;" +        a.disable href="#" +          = t(".multi_selection_disable") -      ul.actions -        = link_to t(".delete_selected"), referential_lines_path(@referential), "data-multiple-method" => "delete", :class => "remove", "confirmation-text" => t("lines.actions.destroy_selection_confirm") +        ul.actions +          = link_to t(".delete_selected"), referential_lines_path(@referential), "data-multiple-method" => "delete", :class => "remove", "confirmation-text" => t("lines.actions.destroy_selection_confirm")        a.select_all href="#"          = t(".select_all")        = " | "        a.deselect_all href="#" -        = t(".deselect_all")
\ No newline at end of file +        = t(".deselect_all") diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim index ae8314a14..e32978b20 100644 --- a/app/views/referential_lines/show.html.slim +++ b/app/views/referential_lines/show.html.slim @@ -1,7 +1,10 @@  - text_color = @line.text_color.blank? ? "black" : "##{@line.text_color}"  - bg_color = @line.color.blank? ? "white" : "##{@line.color}" -= title_tag t('lines.show.title', line: @line.name) +h2 +  = t('lines.show.title', line: @line.name) +  - if @line.deactivated? +    small = " (désactivé)"  .line_show    = @map.to_html @@ -14,122 +17,130 @@        p          label = "#{t('lines.index.color')} : "          label.color style="#{number_style(@line)}" -          = line_sticker(@line) +          = " #{line_sticker(@line)}"      p        label = "#{@line.human_attribute_name(:network)} : "        - if @line.network.nil? -        = t('lines.index.unset') +        = " #{t('lines.index.unset')}"        - else -        = link_to @line.network.name, [@referential, @line.network] +        = link_to " #{@line.network.name}", [@referential, @line.network]      p        label = "#{@line.human_attribute_name(:company)} : "        - if @line.company.nil? -        = t('lines.index.unset') +        = " #{t('lines.index.unset')}"        - else -        = link_to @line.company.name, [@referential, @line.company] +        = link_to " #{@line.company.name}", [@referential, @line.company]      p        label = "#{@line.human_attribute_name('number')} : " -      = @line.number +      = " #{@line.number}"      p        label = "#{@line.human_attribute_name('published_name')} : " -      = @line.published_name +      = " #{@line.published_name}"      p        label = "#{@line.human_attribute_name('registration_number')} : " -      = @line.registration_number +      = " #{@line.registration_number}"      p        label = "#{@line.human_attribute_name('transport_mode')} : " -      = t("transport_modes.label.#{@line.transport_mode}") - -    p -      label = "#{@line.human_attribute_name('stable_id')} : " -      = @line.stable_id - -    p -      label = "#{@line.human_attribute_name('url')} : " -      = @line.url - -    p -      label = "#{@line.human_attribute_name('mobility_restricted_suitability')} : " - -      - if @line.mobility_restricted_suitability.nil? -        = @line.human_attribute_name("unspecified_mrs") -      - elsif @line.mobility_restricted_suitability? -        = @line.human_attribute_name("accessible") +      - if @line.transport_mode +        = " " + t("enumerize.line.transport_mode.#{@line.transport_mode}")        - else -        = @line.human_attribute_name("not_accessible") - -      br -      = "#{@line.human_attribute_name('number_of_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', true).count}" -      br -      = "#{@line.human_attribute_name('number_of_non_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', false).count}" -      br -      = "#{@line.human_attribute_name('number_of_null_mrs_vj')} : " -      = @line.vehicle_journeys.count - (@line.vehicle_journeys.where("mobility_restricted_suitability = ?", true).count + @line.vehicle_journeys.where("mobility_restricted_suitability = ?", false).count) +        = " -"      p -      label = "#{@line.human_attribute_name('flexible_service')} : " - -      - if @line.flexible_service.nil? -        = @line.human_attribute_name("unspecified_fs") -      - elsif @line.flexible_service? -        = @line.human_attribute_name("on_demaond_fs") +      label = "#{@line.human_attribute_name('transport_submode')} : " +      - if @line.transport_submode +        = " " + t("enumerize.line.transport_submode.#{@line.transport_submode}")        - else -        = @line.human_attribute_name("regular_fs") +        = " -" -      br -      = "#{@line.human_attribute_name('number_of_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', true).count}" -      br -      = "#{@line.human_attribute_name('number_of_non_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', false).count}" -      br -      = @line.human_attribute_name("number_of_null_fs_vj") - -      - if @line.flexible_service.nil? -        = "(#{@line.human_attribute_name('default_fs_msg')})" - -      = ": #{@line.vehicle_journeys.count - (@line.vehicle_journeys.where('flexible_service = ?', true).count + @line.vehicle_journeys.where('flexible_service = ?', false).count)}" +    / p +    /   label = "#{@line.human_attribute_name('stable_id')} : " +    /   = " #{@line.stable_id}"      p +      label = "#{@line.human_attribute_name('url')} : " +      = " #{@line.url}" + +    / p +    /   label = "#{@line.human_attribute_name('mobility_restricted_suitability')} : " +    / +    /   - if @line.mobility_restricted_suitability.nil? +    /     = @line.human_attribute_name("unspecified_mrs") +    /   - elsif @line.mobility_restricted_suitability? +    /     = @line.human_attribute_name("accessible") +    /   - else +    /     = @line.human_attribute_name("not_accessible") +    / +    /   br +    /   = "#{@line.human_attribute_name('number_of_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', true).count}" +    /   br +    /   = "#{@line.human_attribute_name('number_of_non_mrs_vj')} : #{@line.vehicle_journeys.where('mobility_restricted_suitability = ?', false).count}" +    /   br +    /   = "#{@line.human_attribute_name('number_of_null_mrs_vj')} : " +    /   = @line.vehicle_journeys.count - (@line.vehicle_journeys.where("mobility_restricted_suitability = ?", true).count + @line.vehicle_journeys.where("mobility_restricted_suitability = ?", false).count) +    / +    / p +    /   label = "#{@line.human_attribute_name('flexible_service')} : " +    / +    /   - if @line.flexible_service.nil? +    /     = @line.human_attribute_name("unspecified_fs") +    /   - elsif @line.flexible_service? +    /     = @line.human_attribute_name("on_demaond_fs") +    /   - else +    /     = @line.human_attribute_name("regular_fs") +    / +    /   br +    /   = "#{@line.human_attribute_name('number_of_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', true).count}" +    /   br +    /   = "#{@line.human_attribute_name('number_of_non_fs_vj')} : #{@line.vehicle_journeys.where('flexible_service = ?', false).count}" +    /   br +    /   = @line.human_attribute_name("number_of_null_fs_vj") +    / +    /   - if @line.flexible_service.nil? +    /     = "(#{@line.human_attribute_name('default_fs_msg')})" +    / +    /   = ": #{@line.vehicle_journeys.count - (@line.vehicle_journeys.where('flexible_service = ?', true).count + @line.vehicle_journeys.where('flexible_service = ?', false).count)}" +    / +    p        label = "#{@line.human_attribute_name('footnotes')} : "        ul          - @line.footnotes.each do |footnote|            li = "#{footnote.code} : #{footnote.label}" -    p -      label = "#{@line.human_attribute_name('comment')} : " -      = @line.comment +    / p +    /   label = "#{@line.human_attribute_name('comment')} : " +    /   = @line.comment    .row      #mobility_restricted_suitability.col-md-6      #flexible_service.col-md-6  p.after_map -h3.routes = t('.itineraries') -.routes.paginated_content -  = paginated_content @routes, "routes/route" - -- if @line.group_of_lines.any? -  h3.line_group_of_lines = t('.group_of_lines') -  .group_of_lines.paginated_content -    = paginated_content @group_of_lines, "group_of_lines/group_of_line", :delete => false +.routes +  = render 'reflines_routes'  - content_for :sidebar do    ul.actions -    li -      = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' -    li -      = link_to t('lines.actions.edit'), edit_referential_line_path(@referential, @line), class: 'edit' -    li -      = link_to t('lines.actions.destroy'), referential_line_path(@referential, @line), method: :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, class: 'remove' +    - if policy(Chouette::Line).create? +      li +        = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' +    - if policy(@line).update? +      li +        = link_to t('lines.actions.edit'), edit_referential_line_path(@referential, @line), class: 'edit' +    - if policy(@line).destroy? +      li +        = link_to t('lines.actions.destroy'), referential_line_path(@referential, @line), method: :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, class: 'remove'      - if !@line.hub_restricted? || (@line.hub_restricted? && @line.routes.size < 2) -      li +        / FIXME #825 +        li          = link_to t('routes.actions.new'), new_referential_line_route_path(@referential, @line), class: 'add' -  = creation_tag(@line)
\ No newline at end of file +  = creation_tag(@line) diff --git a/app/views/referential_networks/_network.html.slim b/app/views/referential_networks/_network.html.slim index dc1aa6b5c..f7c7b66eb 100644 --- a/app/views/referential_networks/_network.html.slim +++ b/app/views/referential_networks/_network.html.slim @@ -2,13 +2,14 @@    .panel-heading      .panel-title.clearfix        span.pull-right -        = link_to edit_referential_network_path(@referential, network), class: 'btn btn-default btn-sm' do -          span.fa.fa-pencil - -        = link_to referential_network_path(@referential, network), method: :delete, :data => { :confirm => t('networks.actions.destroy_confirm') }, class: 'btn btn-danger btn-sm' do -          span.fa.fa-trash-o +        - if policy(network).update? +          = link_to edit_referential_network_path(@referential, network), class: 'btn btn-default btn-sm' do +            span.fa.fa-pencil +        - if policy(network).destroy? +          = link_to referential_network_path(@referential, network), method: :delete, :data => { :confirm => t('networks.actions.destroy_confirm') }, class: 'btn btn-danger btn-sm' do +            span.fa.fa-trash-o        h5          = link_to [@referential, network], class: 'preview', title: "#{Chouette::Network.model_name.human.capitalize} #{network.name}" do            span.name -            = truncate(network.name, :length => 20)
\ No newline at end of file +            = truncate(network.name, :length => 20) diff --git a/app/views/referential_networks/index.html.slim b/app/views/referential_networks/index.html.slim index f3ead931e..e3e9f2a07 100644 --- a/app/views/referential_networks/index.html.slim +++ b/app/views/referential_networks/index.html.slim @@ -19,5 +19,6 @@  - content_for :sidebar do    ul.actions      li +    - if policy(Chouette::Network).create?        = link_to t('networks.actions.new'), new_referential_network_path(@referential), class: 'add' -    br
\ No newline at end of file +    br diff --git a/app/views/referential_networks/show.html.slim b/app/views/referential_networks/show.html.slim index 936f6a4a8..d579d311b 100644 --- a/app/views/referential_networks/show.html.slim +++ b/app/views/referential_networks/show.html.slim @@ -36,12 +36,15 @@  - content_for :sidebar do    ul.actions -    li -      = link_to t('networks.actions.new'), new_referential_network_path(@referential), class: 'add' -    li -      = link_to t('networks.actions.edit'), edit_referential_network_path(@referential, @network), class: 'edit' -    li -      = link_to t('networks.actions.destroy'), referential_network_path(@referential, @network), method: :delete, data: { :confirm => t('networks.actions.destroy_confirm')}, class: 'remove' -    br -   -  = creation_tag(@network)
\ No newline at end of file +    - if policy(Chouette::Network).create? +      li +        = link_to t('networks.actions.new'), new_referential_network_path(@referential), class: 'add' +    - if policy(@network).update? +      li +        = link_to t('networks.actions.edit'), edit_referential_network_path(@referential, @network), class: 'edit' +    - if policy(@network).destroy? +      li +        = link_to t('networks.actions.destroy'), referential_network_path(@referential, @network), method: :delete, data: { :confirm => t('networks.actions.destroy_confirm')}, class: 'remove' +      br + +  = creation_tag(@network) diff --git a/app/views/referential_stop_areas/_genealogical.html.slim b/app/views/referential_stop_areas/_genealogical.html.slim index a44884c92..162c24d9b 100644 --- a/app/views/referential_stop_areas/_genealogical.html.slim +++ b/app/views/referential_stop_areas/_genealogical.html.slim @@ -5,7 +5,7 @@ h3 = genealogical_title      = link_to([@referential, @stop_area.parent], :title => t("area_types.label.#{@stop_area.parent.stop_area_type}") + "#{@stop_area.parent.name}") do        = image_tag "map/" + @stop_area.parent.stop_area_type + ".png"        = @stop_area.parent.name -     +    .link      = image_tag "icons/link.png" @@ -18,7 +18,7 @@ h3 = genealogical_title    .link = image_tag "icons/link.png"  - else -  .no_parent =   +  .no_parent  .target    = image_tag "map/" + @stop_area.stop_area_type + ".png" @@ -51,4 +51,4 @@ h3 = genealogical_title            span = route.line.number          = link_to([@referential, route.line , route]) do -          span = route.name
\ No newline at end of file +          span = route.name diff --git a/app/views/referential_stop_areas/_stop_area.html.slim b/app/views/referential_stop_areas/_stop_area.html.slim index f94bd319e..bb9ed7ce3 100644 --- a/app/views/referential_stop_areas/_stop_area.html.slim +++ b/app/views/referential_stop_areas/_stop_area.html.slim @@ -2,11 +2,13 @@    .panel-heading      .panel-title.clearfix        span.pull-right -        = link_to edit_referential_stop_area_path(@referential, stop_area), class: 'btn btn-default btn-sm' do -          span.fa.fa-pencil +        - if policy(stop_area).update? +          = link_to edit_referential_stop_area_path(@referential, stop_area), class: 'btn btn-default btn-sm' do +            span.fa.fa-pencil -        = link_to referential_stop_area_path(@referential, stop_area), method: :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do -          span.fa.fa-trash-o +        - if policy(stop_area).destroy? +          = link_to referential_stop_area_path(@referential, stop_area), method: :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do +            span.fa.fa-trash-o        h5          = link_to([@referential, stop_area], class: "preview", :title => t("area_types.label.#{stop_area.stop_area_type}") + " #{stop_area.name}") do @@ -34,11 +36,11 @@          - else            - stop_area.routing_lines.each do |line|              span.label.label-default.line = line.number -       +        - else          = "#{t('.lines')} : "          - if stop_area.lines.blank?            = t(".no_object")          - else            - stop_area.lines.each do |line| -            span.label.label-default.line = line.number || truncate( line.name, length: 4 )
\ No newline at end of file +            span.label.label-default.line = line.number || truncate( line.name, length: 4 ) diff --git a/app/views/referential_stop_areas/index.html.slim b/app/views/referential_stop_areas/index.html.slim index 85bd15d20..42ac267aa 100644 --- a/app/views/referential_stop_areas/index.html.slim +++ b/app/views/referential_stop_areas/index.html.slim @@ -6,7 +6,7 @@  = search_form_for @q, :url => referential_stop_areas_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f|    .panel.panel-default      .panel-heading -      .input-group.col-md-9 +      .input-group.col-md-9.col-sm-9          = f.text_field :name_cont, :placeholder => "#{t('.name')}", class: 'form-control'          .input-group-btn            button.btn.btn-default type="submit" @@ -18,15 +18,19 @@      #advanced_search.panel-collapse.collapse        .panel-body -        = f.text_field :zip_code_cont, :placeholder => "#{t('.zip_code')}", class: 'form-control typeahead' -        = f.select(:area_type_cont, options_from_collection_for_select(Chouette::StopArea.stop_area_types, 'name', Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } ), { :include_blank => "#{t('.area_type')}" }, { :class => 'form-control' }) +        .row +          .col-sm-3 +            = f.text_field :zip_code_cont, placeholder: "#{t('.zip_code')}", class: 'form-control typeahead', style: 'width: 100%' +          .col-sm-3 +            = f.select(:area_type_cont, options_from_collection_for_select(Chouette::StopArea.stop_area_types, 'name', Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } ), { include_blank: '' }, { class: 'form-control', style: 'width: 100%', 'data-select2ed': 'true', 'data-select2ed-placeholder': t(".area_type") })  #stop_areas    = render 'stop_areas'  - content_for :sidebar do    ul.actions +    - if policy(Chouette::StopArea).create? +      li +        = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add'      li -      = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' -    li -      / = link_to t('stop_areas.actions.default_geometry'), default_geometry_referential_stop_areas_path(@referential), :method => :put, :class => "calculator"
\ No newline at end of file +      / = link_to t('stop_areas.actions.default_geometry'), default_geometry_referential_stop_areas_path(@referential), :method => :put, :class => "calculator" diff --git a/app/views/referential_stop_areas/show.html.slim b/app/views/referential_stop_areas/show.html.slim index 76414edf0..c1475723d 100644 --- a/app/views/referential_stop_areas/show.html.slim +++ b/app/views/referential_stop_areas/show.html.slim @@ -6,47 +6,52 @@    .summary      p        label = "#{@stop_area.human_attribute_name('comment')} : " -      = @stop_area.comment +      = " #{@stop_area.comment}"      p        label = "#{@stop_area.human_attribute_name('nearest_topic_name')} : " -      = @stop_area.nearest_topic_name +      = " #{@stop_area.nearest_topic_name}"      p        label = "#{@stop_area.human_attribute_name('street_name')} : " -      = @stop_area.street_name +      = " #{@stop_area.street_name}"      p        label = "#{@stop_area.human_attribute_name('country_code')} : " -      = @stop_area.country_code +      = " #{@stop_area.country_code}"      p        label = "#{@stop_area.human_attribute_name('zip_code')} : " -      = @stop_area.zip_code +      = " #{@stop_area.zip_code}"      p        label = "#{@stop_area.human_attribute_name('city_name')} : " -      = @stop_area.city_name +      = " #{@stop_area.city_name}"      p        label = "#{@stop_area.human_attribute_name('fare_code')} : " -      = @stop_area.fare_code +      = " #{@stop_area.fare_code}"      p        label = "#{@stop_area.human_attribute_name('time_zone')} : " -      = @stop_area.time_zone +      = " #{@stop_area.time_zone}"      p        label = "#{@stop_area.human_attribute_name('url')} : " -      = @stop_area.url +      = " #{@stop_area.url}"      p        label = "#{@stop_area.human_attribute_name('registration_number')} : " -      = @stop_area.registration_number +      = " #{@stop_area.registration_number}" +     +    - if @stop_area.deleted_at +      p +        label = "#{@stop_area.human_attribute_name('deleted_at')} : " +        = " #{l @stop_area.deleted_at, format: :long}"      p        label = "#{@stop_area.human_attribute_name('stop_area_type')} : " -      = t("area_types.label.#{@stop_area.stop_area_type}") +      = " " + t("area_types.label.#{@stop_area.stop_area_type}")        i.fa.fa-info-circle data-toggle="tooltip" data-placement="right" title="#{t('.not_editable')}" @@ -55,24 +60,24 @@          label = "#{@stop_area.human_attribute_name('mobility_restricted_suitability')} : "          - if !@stop_area.mobility_restricted_suitability.nil? -          = t((@stop_area.mobility_restricted_suitability == true).to_s) +          = " #{t((@stop_area.mobility_restricted_suitability == true).to_s)}"          - else -          = t('unknown') +          = " #{t('unknown')}"  	    p          label = "#{@stop_area.human_attribute_name('stairs_availability')} : "          - if !@stop_area.stairs_availability.nil? -          = t((@stop_area.stairs_availability == true).to_s) +          = " #{t((@stop_area.stairs_availability == true).to_s)}"          - else -          = t('unknown') +          = " #{t('unknown')}"        p          label = "#{@stop_area.human_attribute_name('lift_availability')} : "          - if !@stop_area.lift_availability.nil? -          = t((@stop_area.lift_availability == true).to_s) +          = " #{t((@stop_area.lift_availability == true).to_s)}"          - else -          = t('unknown') +          = " #{t('unknown')}"        p          label = t('stop_areas.show.geographic_data') @@ -109,7 +114,7 @@  p.after_map  .genealogical.clearfix -  = render "stop_areas/genealogical" +  = render "referential_stop_areas/genealogical"  - if manage_access_points    div @@ -122,22 +127,25 @@ p.after_map      tr        td          ul.actions -          li -            = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' -      	  li -            = link_to t('stop_areas.actions.edit'), edit_referential_stop_area_path(@referential, @stop_area), class: 'edit' -      	  li -            = link_to t('stop_areas.actions.destroy'), referential_stop_area_path(@referential, @stop_area), method: :delete, data: { :confirm => t('stop_areas.actions.destroy_confirm') }, class: 'remove' +          - if policy(Chouette::StopArea).new? +            li +              = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' +          - if policy(@stop_area).update? +        	  li +              = link_to t('stop_areas.actions.edit'), edit_referential_stop_area_path(@referential, @stop_area), class: 'edit' +          - if policy(@stop_area).destroy? +        	  li +              = link_to t('stop_areas.actions.destroy'), referential_stop_area_path(@referential, @stop_area), method: :delete, data: { :confirm => t('stop_areas.actions.destroy_confirm') }, class: 'remove'      - if manage_itl -      tr -        td -          h4 = t('.itl_managment') -          ul.actions -            li -              = link_to t('stop_areas.actions.add_routing_lines'), add_routing_lines_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_lines' -            li -              = link_to t('stop_areas.actions.add_routing_stops'), add_routing_stops_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_stops' +      / tr +      /   td +      /     h4 = t('.itl_managment') +      /     ul.actions +      /       li +      /         = link_to t('stop_areas.actions.add_routing_lines'), add_routing_lines_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_lines' +      /       li +      /         = link_to t('stop_areas.actions.add_routing_stops'), add_routing_stops_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_stops'      - else        tr @@ -145,17 +153,17 @@ p.after_map            h4 = t('.stop_managment')            ul.actions              li -              = link_to t('stop_areas.actions.select_parent'), select_parent_referential_stop_area_path(@referential, @stop_area), class: 'parent' +              / = link_to t('stop_areas.actions.select_parent'), select_parent_referential_stop_area_path(@referential, @stop_area), class: 'parent'              - if @stop_area.parent == nil                li -                = link_to t('stop_areas.actions.clone_as_parent'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'parent'), class: 'clone' +                / = link_to t('stop_areas.actions.clone_as_parent'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'parent'), class: 'clone'              - if manage_children                li -                = link_to t('stop_areas.actions.add_children'), add_children_referential_stop_area_path(@referential, @stop_area), class: 'children' +                / = link_to t('stop_areas.actions.add_children'), add_children_referential_stop_area_path(@referential, @stop_area), class: 'children'                li -                = link_to t('stop_areas.actions.clone_as_child'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'child'), class: 'clone' +                / = link_to t('stop_areas.actions.clone_as_child'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'child'), class: 'clone'        - if manage_access_points          tr @@ -163,9 +171,9 @@ p.after_map              h4 = t(".access_managment")              ul.actions                li -                = link_to t('access_points.actions.new'), new_referential_stop_area_access_point_path(@referential,@stop_area), class: 'add' +                / = link_to t('access_points.actions.new'), new_referential_stop_area_access_point_path(@referential,@stop_area), class: 'add'                li -                = link_to t('stop_areas.actions.manage_access_links'), access_links_referential_stop_area_path(@referential,@stop_area), class: 'access_link' +                / = link_to t('stop_areas.actions.manage_access_links'), access_links_referential_stop_area_path(@referential,@stop_area), class: 'access_link'    br diff --git a/app/views/referentials/_clean.html.slim b/app/views/referentials/_clean.html.slim index 8e09c14cb..4064d77ae 100644 --- a/app/views/referentials/_clean.html.slim +++ b/app/views/referentials/_clean.html.slim @@ -1,12 +1,7 @@  #clean_up    = semantic_form_for [@referential, CleanUp.new] do |form|      = form.inputs do -      = form.input :expected_date, as: :date_picker, :wrapper_html => { class: 'date', title: t('titles.clean_up.expected_date') } -      = form.input :keep_lines, as: :boolean -      = form.input :keep_stops, as: :boolean -      = form.input :keep_companies, as: :boolean -      = form.input :keep_networks, as: :boolean -      = form.input :keep_group_of_lines, as: :boolean - +      = form.input :begin_date, as: :date_picker, label: t('titles.clean_up.begin_date'),:wrapper_html => { class: 'date', title: t('titles.clean_up.begin_date') } +      = form.input :end_date, as: :date_picker, label: t('titles.clean_up.end_date'), :wrapper_html => { class: 'date', title: t('titles.clean_up.end_date') }      = form.actions do -      = form.action :submit, as: :button, label: t('clean_ups.actions.clean_up') , :button_html => { data: { confirm: t('clean_ups.actions.confirm') } }
\ No newline at end of file +      = form.action :submit, as: :button, label: t('clean_ups.actions.clean_up') , :button_html => { data: { confirm: t('clean_ups.actions.confirm') } } diff --git a/app/views/referentials/_counts.html.slim b/app/views/referentials/_counts.html.slim deleted file mode 100644 index fc3ad251e..000000000 --- a/app/views/referentials/_counts.html.slim +++ /dev/null @@ -1,70 +0,0 @@ -.panel.panel-default -  / Default panel contents -  .panel-heading = t(".objects") - -  ul.list-group  width="75%" -    li.list-group-item -      span.badge = @referential.networks.size -      = Referential.human_attribute_name('networks') - -    li.list-group-item -      span.badge = @referential.companies.size -      = Referential.human_attribute_name('companies') - -    li.list-group-item -      span.badge = @referential.group_of_lines.size -      = Referential.human_attribute_name('group_of_lines') - -    li.list-group-item -      span.badge = @referential.lines.size -      = Referential.human_attribute_name('lines') - -    li.list-group-item -      span.badge = @referential.vehicle_journeys.size -      = Referential.human_attribute_name('vehicle_journeys') - -    li.list-group-item -      span.badge = @referential.time_tables.size -      = Referential.human_attribute_name('time_tables') - -    li.list-group-item -      span.badge = @referential.connection_links.size -      = Referential.human_attribute_name('connection_links') - -    li.list-group-item -      span.badge = @referential.route_sections.size -      = Referential.human_attribute_name('route_sections') - -    li.list-group-item -      span.badge = @referential.stop_areas.size -      = Referential.human_attribute_name('stop_areas') - -    li.list-group-item -      span.badge = @referential.stop_areas.where("area_type = ?","BoardingPosition").size -      = image_tag "map/boarding_position.png" -      = Referential.human_attribute_name("boarding_positions") - -    li.list-group-item -      span.badge = @referential.stop_areas.where("area_type = ?","Quay").size -      = image_tag "map/quay.png" -      = Referential.human_attribute_name("quays") - -    li.list-group-item -      span.badge = @referential.stop_areas.where("area_type = ?","CommercialStopPoint").size -      = image_tag "map/commercial_stop_point.png" -      = Referential.human_attribute_name("commercial_stops") - -    li.list-group-item -      span.badge = @referential.stop_areas.where("area_type = ?","StopPlace").size -      = image_tag "map/stop_place.png" -      = Referential.human_attribute_name("stop_places") - -    li.list-group-item -      span.badge = @referential.stop_areas.where("area_type = ?","ITL").size -      = image_tag "map/itl.png" -      = Referential.human_attribute_name("itls") - -    li.list-group-item -      span.badge = @referential.access_points.size -      = image_tag "map/access_in_out.png" -      = Referential.human_attribute_name("access_points")
\ No newline at end of file diff --git a/app/views/referentials/_form.html.slim b/app/views/referentials/_form.html.slim index 985fee4b4..777c942f4 100644 --- a/app/views/referentials/_form.html.slim +++ b/app/views/referentials/_form.html.slim @@ -1,21 +1,70 @@ -= semantic_form_for @referential, class: 'form-horizontal' do |form| -  = form.inputs do -    = form.input :name -     += simple_form_for @referential, class: 'form' do |form| +  .row +    .col-lg-8.col-md-8.col-sm-7.col-xs-8 +      = form.input :name +            - if @referential.new_record? -      = form.input :slug, :input_html => { title: t("formtastic.titles.referential.slug") } +      - if @referential.created_from +        .col-lg-2.col-md-2.col-sm-3.col-xs-2 +          = form.input :created_from, input_html: { value: @referential.created_from.name} +           +        .col-lg-2.col-md-2.col-sm-2.col-xs-2 +          = form.input :slug, :input_html => { title: t("formtastic.titles.referential.slug") } +      - else +        .col-lg-4.col-md-4.col-sm-5.col-xs-4 +          = form.input :slug, :input_html => { title: t("formtastic.titles.referential.slug") } +            - else -      li.input -        label.label = @referential.human_attribute_name('slug') -        = @referential.slug +      - if @referential.created_from +        .col-lg-2.col-md-2.col-sm-2.col-xs-2 +          label.control-label = @referential.human_attribute_name('slug') +          br +          = @referential.slug +           +        .col-lg-2.col-md-2.col-sm-2.col-xs-2 +          label.control-label = @referential.human_attribute_name('created_from') +          = @referential.created_from.name +      - else +        .col-lg-4.col-md-4.col-sm-4.col-xs-4 +          label.control-label = @referential.human_attribute_name('slug') +          br +          = @referential.slug -    = form.input :prefix, input_html: { title: t("formtastic.titles.referential.prefix") } -    = form.input :projection_type, as: :select, :collection => Referential.available_srids -    = form.input :time_zone -    = form.input :upper_corner, input_html: { title: t("formtastic.titles.referential.upper_corner") } -    = form.input :lower_corner, input_html: { title: t("formtastic.titles.referential.lower_corner") } -    = form.input :data_format, label: true, include_blank: false +  .row +    .col-lg-5.col-md-5.col-sm-5.col-xs-5 +      = form.input :prefix, input_html: { title: t("formtastic.titles.referential.prefix") } +    .col-lg-7.col-md-7.col-sm-7.col-xs-7 +      = form.input :projection_type, as: :select, collection: Referential.available_srids +   +  .row +    .col-lg-6.col-md-6.col-sm-6.col-xs-6 +      = form.input :time_zone +   +  .row +    .col-lg-6.col-md-6.col-sm-6.col-xs-6 +      = form.input :upper_corner, input_html: {title: t("formtastic.titles.referential.upper_corner")} +    .col-lg-6.col-md-6.col-sm-6.col-xs-6 +      = form.input :lower_corner, input_html: {title: t("formtastic.titles.referential.lower_corner")} -  = form.actions do -    = form.action :submit, as: :button -    = form.action :cancel, as: :link
\ No newline at end of file +  - if @referential.errors.has_key? :metadatas +    ul.errors +      - @referential.errors[:metadatas].each do |message| +        li = message + +  = form.simple_fields_for :metadatas do |subform| +    .row +      .col-lg-6.col-md-6.col-sm-6.col-xs-6 +        = subform.input :first_period_begin, as: :date, html5: true, input_html: { style: 'width: 100%' } +      .col-lg-6.col-md-6.col-sm-6.col-xs-6 +        = subform.input :first_period_end, as: :date, html5: true, input_html: { style: 'width: 100%' } +    .row +      .col-lg-8.col-md-12.col-sm-12.col-xs-12 +        = subform.input :lines, as: :select, collection: @referential.workbench.lines, selected: subform.object.line_ids, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Sélection de lignes', 'multiple': 'multiple', style: 'width: 100%' } + +  = form.input :workbench_id, as: :hidden + +  / Actions +  .row +    .col-lg-12.text-center +      = link_to 'Annuler', @referential,  class: 'btn btn-link' +      = form.button :submit, class: 'btn btn-danger' diff --git a/app/views/referentials/_validity_out.html.slim b/app/views/referentials/_validity_out.html.slim deleted file mode 100644 index a7920ce01..000000000 --- a/app/views/referentials/_validity_out.html.slim +++ /dev/null @@ -1,27 +0,0 @@ -.panel.panel-default -  / Default panel contents -  .panel-heading -    = "#{t('.validity_out_time_tables')} : " -    = (tm_cnt = @referential.time_tables.validity_out_from_on?(Date.today).size) -   -  ul.list-group -    - if tm_cnt > 0 -      - @referential.time_tables.validity_out_from_on?(Date.today, 5).each do |tm| -        li.list-group-item = link_to tm.comment, referential_time_table_path(@referential, tm) - -      - if tm_cnt > 5 -        li.list-group-item ... - -.panel.panel-default -  / Default panel contents -  .panel-heading -    = "#{t('.validity_out_soon_time_tables', count: '7')} : " -    = (tm_cnt = @referential.time_tables.validity_out_between?(Date.today,Date.today+7).size) - -  ul.list-group -    - if tm_cnt > 0 -      - @referential.time_tables.validity_out_between?(Date.today,Date.today+7,5).each do |tm| -        li.list-group-item = link_to tm.comment, referential_time_table_path(@referential, tm) - -      - if tm_cnt > 5 -        li.list-group-item ...
\ No newline at end of file diff --git a/app/views/referentials/edit.html.slim b/app/views/referentials/edit.html.slim index cc5637bb6..12b5e23c9 100644 --- a/app/views/referentials/edit.html.slim +++ b/app/views/referentials/edit.html.slim @@ -1,3 +1,5 @@  = title_tag t('.title') -== render 'form'
\ No newline at end of file +.row +  .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2 +    == render 'form' diff --git a/app/views/referentials/index.html.slim b/app/views/referentials/index.html.slim index e37f157de..b8c16b5ae 100644 --- a/app/views/referentials/index.html.slim +++ b/app/views/referentials/index.html.slim @@ -11,15 +11,8 @@  - content_for :sidebar do    ul.actions +    li = link_to 'Données Reflex', stop_area_referential_path(1) +    li = link_to 'Données CodifLigne', line_referential_path(1)      / FIXME #823      - if false        li = link_to t('referentials.actions.new'), new_referential_path, class: 'add' - -  ul -    / FIXME #820 -    / Don't blame me. See #820 -    li = link_to 'Données Reflex', stop_area_referential_path(1) - -    / FIXME #824 -    / Don't blame me. See #824 -    li = link_to 'Données CodifLigne', line_referential_path(1) diff --git a/app/views/referentials/new.html.slim b/app/views/referentials/new.html.slim index cc5637bb6..12b5e23c9 100644 --- a/app/views/referentials/new.html.slim +++ b/app/views/referentials/new.html.slim @@ -1,3 +1,5 @@  = title_tag t('.title') -== render 'form'
\ No newline at end of file +.row +  .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2 +    == render 'form' diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim index d5fed0344..94c463d74 100644 --- a/app/views/referentials/show.html.slim +++ b/app/views/referentials/show.html.slim @@ -3,71 +3,55 @@ h2    em.small = " (archivé)" if @referential.archived?  .summary +  - if @referential.created_from +    p +      label = "#{Referential.human_attribute_name('created_from')} : " +      = " #{@referential.created_from.name}" +    p      label = "#{Referential.human_attribute_name('slug')} : " -    = @referential.slug +    = " #{@referential.slug}"    p      label = "#{Referential.human_attribute_name('prefix')} : " -    = @referential.prefix +    = " #{@referential.prefix}"    p      label = "#{Referential.human_attribute_name('projection_type')} : "      - if !@referential.projection_type_label.empty? -      = "#{@referential.projection_type_label} (epsg:#{@referential.projection_type})" +      = " #{@referential.projection_type_label} (epsg:#{@referential.projection_type})"    p      label = "#{Referential.human_attribute_name('time_zone').capitalize} : " -    = @referential.time_zone - -  p -    label = "#{Referential.human_attribute_name('data_format_restrictions')} : " -    = @referential.data_format +    = " #{@referential.time_zone}"    p      label = "#{Referential.human_attribute_name('validity_period')} : "      - if Chouette::TimeTable.start_validity_period.nil? -      = Referential.human_attribute_name("no_validity_period") +      = " #{Referential.human_attribute_name('no_validity_period')}"      - else -      = Referential.human_attribute_name("start_validity_period") +      = " #{Referential.human_attribute_name('start_validity_period')}"        = l Chouette::TimeTable.start_validity_period        = Referential.human_attribute_name("end_validity_period")        = l Chouette::TimeTable.end_validity_period -  table width="100%" -    tr -      td valign="top" width="50%" -        == render 'counts' - -      td valign="top" -        == render 'validity_out' - -  - if @referential.api_keys.present? -    h3.api_keys = t('.api_keys') -     -    .api_keys.paginated_content -      = paginated_content(@referential.api_keys, "api_keys/api_key") +  / - if @referential.api_keys.present? +  /   h3.api_keys = t('.api_keys') +  / +  /   .api_keys.paginated_content +  /     = paginated_content(@referential.api_keys, "api_keys/api_key")  - content_for :sidebar do    ul.actions -    li = link_to t('referentials.actions.edit'), edit_referential_path(@referential), class: 'edit' - -    li -      - if @referential.archived? -        = link_to unarchive_referential_path(@referential), method: :put do -          span.fa-stack -            span.fa.fa-archive.fa-stack-1x -            span.fa.fa-ban.fa-stack-2x -          = " Désarchiver cet espace de données" -      - else -        = link_to archive_referential_path(@referential), method: :put do -          span.fa.fa-archive -          = " Archiver cet espace de données" +    - unless @referential.archived? # FIXME +      li = link_to t('referentials.actions.edit'), edit_referential_path(@referential), class: 'edit'      li = link_to t('referentials.actions.destroy'), referential_path(@referential), method: :delete, data: {:confirm => t('referentials.actions.destroy_confirm')}, class: "remove" -    li = link_to t('api_keys.actions.new'), new_referential_api_key_path(@referential), class: 'add' +    / li = link_to t('api_keys.actions.new'), new_referential_api_key_path(@referential), class: 'add' +    li = link_to t('referentials.actions.clone'), new_referential_path(from: @referential.id), class: 'add'      br -  h4 = t('.clean_up') +  - unless @referential.archived? # FIXME +    h4 = t('.clean_up') -  == render 'clean'
\ No newline at end of file +    == render 'clean' diff --git a/app/views/referentials/show.js.slim b/app/views/referentials/show.js.slim index f1d01ce6c..5e47bf935 100644 --- a/app/views/referentials/show.js.slim +++ b/app/views/referentials/show.js.slim @@ -3,7 +3,6 @@  |   update_infos = function(json) {  |     var info, update_info;  |     info = $('#referential_' + json.referential_id); -|     console.log(info)  |     update_info = function(key, value) {  |       if (key.match(/_count$/)) {  |         return $(info.find('.' + key)[0]).text(value); @@ -16,5 +15,5 @@  |   };  |   _results = [];  |   _results.push(update_referential_details()); -|   return _results;  -| });
\ No newline at end of file +|   return _results; +| }); diff --git a/app/views/routes/_form.html.slim b/app/views/routes/_form.html.slim index 329862955..4b0cbd015 100644 --- a/app/views/routes/_form.html.slim +++ b/app/views/routes/_form.html.slim @@ -1,91 +1,32 @@ -= semantic_form_for [@referential, @line, @route] do |form| -  = form.inputs do -    = form.input :name -    = form.input :published_name -    = form.input :number -    = form.input :comment -    = form.input :opposite_route, as: :select, :collection => @line.routes.select { |r| r.id != @route.id } -    = form.input :direction_code, as: :select, :collection => Chouette::Route.directions, :include_blank => false, :member_label => Proc.new { |mode| t("directions.label.#{mode}") } -    = form.input :wayback_code, as: :select, :collection => Chouette::Route.waybacks, :include_blank => false, :member_label => Proc.new { |mode| t("waybacks.label.#{mode}") } -    = form.input :objectid, :required => !@route.new_record?, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.route.objectid")} - -  #stop_points -    = form.semantic_fields_for :stop_points, :include_id => false do |p| -      == render "stop_point_fields",  f: p - -    .links -      = link_to_add_association t("routes.actions.add_stop_point"), form, :stop_points, class: 'add_stop_point add' -      br -      = link_to t('routes.actions.new_stop_point'), new_referential_stop_area_path(@referential), { class: 'add', target: '_blank' } - -  = form.actions do -    = form.action :submit, as: :button -    = form.action :cancel, as: :link - -javascript: -  $(document).ready(function() { -    var stop_point_ids = []; - -    var order_position = function() { -      $('#stop_points input[type="hidden"][id$="position"]').each(function(index) { -        $(this).val(index); -      }); -    }; - -    var write_stop_point_ids = function(){ -      $('#stop_points input[type="hidden"][class~="stop_point_id"]').each(function(index,element) { -        // soit le parent a la classe added_stop_point -          if ( $(element).hasClass("added_stop_point") ){ -            $(this).attr("value", ""); -          } else { -            $(this).attr("value", stop_point_ids.shift()); -          } -      }); -    } - -    var empty_stop_point_ids = function() { -      stop_point_ids = $.map($('#stop_points input[type="hidden"][class="stop_point_id"]'), function(element, index) { -        return $(element).val(); -      }); -      // console.log(  "before-remove"); -      // console.log(  stop_point_ids); -    }; - -    $('#stop_points').sortable({ -      axis: 'y', -      dropOnEmpty: false, -      handle: '.handle', -      cursor: 'crosshair', -      items: '.stop_point', -      opacity: 0.4, -      scroll: true, -      start: function( event, ui ) { -        empty_stop_point_ids(); -      }, -      update: function( event, ui ) { -        write_stop_point_ids(); -        order_position(); -      } -    }); - -    $('#stop_points').bind("cocoon:after-insert", function(event, insertedItem) { -      var new_stop_count = $('div.nested-fields.stop_point').size(); -      var cocoonId = insertedItem.find("input.new_stop_point").attr("id").match( /route_stop_points_attributes_(\d+)_stop_area_id/)[1]; -      insertedItem.find('input').each( function(index,e){ -        var old = $(e).attr("name"); -        if (old!=undefined) { -          $(e).attr("name", old.replace( cocoonId, new_stop_count - 1)); -        } -      }); - -      //console.log( "cocoonId="+cocoonId+", new_stop_count="+new_stop_count); -      order_position(); -    }); - -    $('#stop_points').on("cocoon:before-remove", empty_stop_point_ids); - -    $('#stop_points').on("cocoon:after-remove", function() { -      write_stop_point_ids(); -      order_position(); -    }); -  });
\ No newline at end of file += simple_form_for [@referential, @line, @route] do |f| +  .row +    .col-lg-6.col-md-6.col-sm-12.col-xs-12 +      = f.input :name +    .col-lg-6.col-md-6.col-sm-12.col-xs-12 +      = f.input :published_name + +  .row +    .col-lg-4.col-md-6.col-sm-8.col-xs-8 +      = f.input :opposite_route_id, collection: @line.routes.where("id <> ?", @route) + +    / .col-lg-4.col-md-4.col-sm-4.col-xs-4 +    /   = f.input :direction, include_blank: false + +    .col-lg-4.col-md-4.col-sm-4.col-xs-4 +      = f.input :wayback, include_blank: false + +  .row style="margin-top:20px" +    .col-lg-12.col-md-12.col-sm-12.col-xs-12 +      #stop_points + +  .row style="margin-top:20px" +    .col-lg-12.col-md-12.col-sm-12.col-xs-12.text-right +      = link_to 'Annuler', :back, class: 'btn btn-link' +      = f.button :submit, class: 'btn btn-danger' + +// Get JSON data for route stop points += javascript_tag do +  | window.itinerary_stop = "#{URI.escape(route_json_for_edit(@route))}" + +/ StopPoints Reactux component += javascript_include_tag 'es6_browserified/stop_points.js' diff --git a/app/views/routes/_route.html.slim b/app/views/routes/_route.html.slim index fd740fa9b..251c92000 100644 --- a/app/views/routes/_route.html.slim +++ b/app/views/routes/_route.html.slim @@ -1,19 +1,19 @@  #index_item.panel.panel-default.route    .panel-heading      .panel-title.clearfix -      span.pull-right -        = link_to edit_referential_line_route_path(@referential, @line, route), class: 'btn btn-default btn-sm' do +      .btn-group.btn-group-sm.pull-right +        = link_to edit_referential_line_route_path(@referential, @line, route), class: 'btn btn-default' do            span.fa.fa-pencil -        = link_to referential_line_route_path(@referential, @line, route), method: :delete, :data => {:confirm =>  t('routes.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do +        = link_to referential_line_route_path(@referential, @line, route), method: :delete, :data => {:confirm =>  t('routes.actions.destroy_confirm')}, class: 'btn btn-danger' do            span.fa.fa-trash-o        h5          = link_to [@referential, @line, route], class: 'preview', title: "#{Chouette::Route.model_name.human.capitalize} #{route.name}" do            span.name -            - if route.wayback_code +            - if route.wayback                = fonticon_wayback(route.wayback) -             +              = truncate(route.name, length: 20)    .panel-body @@ -38,6 +38,6 @@      p        - if !route.direction.blank? -        = "#{route.human_attribute_name('direction_code')} : #{t('directions.label.'+route.direction_code)}" +        => "#{route.human_attribute_name('direction')} : #{route.direction_text}"        - else -        br
\ No newline at end of file +        br diff --git a/app/views/routes/_stop_point_fields.html.slim b/app/views/routes/_stop_point_fields.html.slim index 814e882c2..3b51e5e0d 100644 --- a/app/views/routes/_stop_point_fields.html.slim +++ b/app/views/routes/_stop_point_fields.html.slim @@ -1,16 +1,23 @@ -.nested-fields.stop_point.row -  = f.inputs do -    .col-md-1.resize -      = link_to_remove_association "<i class='fa fa-trash-o'></i>".html_safe, f -      span.handle alt="#{t('stop_points.index.move')}" title="#{t('stop_points.index.move')}" > -        i.fa.fa-arrows - -    .col-md-11 -      - if f.object.stop_area.nil? || f.object.new_record? -        = f.input :id, as: :hidden, :input_html => { :class => "stop_point_id added_stop_point", :value => "" } -        = f.input :position, as: :hidden, :input_html => { :class => "position" } +.list-group-item +  div style="display:inline-block;vertical-align:middle;width:75%;" +    - if f.object.stop_area.nil? || f.object.new_record? +        / = f.input :stop_area_id, label: false          = f.input :stop_area_id, :label => false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "new_stop_point stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render } -      - else -        = f.input :id, as: :hidden, :input_html => { class: 'stop_point_id' } -        = f.input :position, as: :hidden, :input_html => { class: 'position' } -        = f.input :stop_area_id, label: false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render }
\ No newline at end of file +       +    - else +      = "#{@route.stop_areas.find(f.object.stop_area_id).name} " +      em.small +        = "#{@route.stop_areas.find(f.object.stop_area_id).zip_code} #{@route.stop_areas.find(f.object.stop_area_id).city_name}" +     +  div.text-right style="display:inline-block;vertical-align:middle;width:25%;" +    .btn-group.btn-group-sm style="padding:0;" +      .btn.btn-default +        span.fa.fa-times +      .btn.btn-primary +        span.fa.fa-arrow-up +      .btn.btn-primary +        span.fa.fa-arrow-down +      .btn.btn-danger +        span.fa.fa-trash +      / = link_to_remove_association f, class: 'btn btn-danger', data: {confirm: 'Are you sure?'} do +      /   span.fa.fa-trash diff --git a/app/views/routes/_test.html.slim b/app/views/routes/_test.html.slim new file mode 100644 index 000000000..deb525d32 --- /dev/null +++ b/app/views/routes/_test.html.slim @@ -0,0 +1,36 @@ +.list-group-item +  = f.inputs do +    - if f.object.stop_area.nil? || f.object.new_record? +      div style="display:inline-block;vertical-align:middle;width:75%;" +        span +          span.text-danger = "[#{@route.stop_areas.find(f.object.stop_area_id).position.inspect}] " +          = @route.stop_areas.find(f.object.stop_area_id).name +                 +        / = f.input :stop_area_id, :label => false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "new_stop_point stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render } +         +        = f.input :stop_area_id, :label => false, as: :search_stop_area +         +        = f.input :id, as: :hidden, :input_html => { :class => "stop_point_id added_stop_point", :value => "" } +        = f.input :position, as: :hidden, :input_html => { :class => "position" } +   +    - else +      div style="display:inline-block;vertical-align:middle;width:75%;" +        span +          span.text-danger = "[#{@route.stop_areas.find(f.object.stop_area_id).position.inspect}] " +          = @route.stop_areas.find(f.object.stop_area_id).name +                   +        / = f.input :stop_area_id, label: false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render } +         +        = f.input :id, as: :hidden, :input_html => { class: 'stop_point_id' } +        = f.input :position, as: :hidden, :input_html => { class: 'position' } +     +    div.text-right style="display:inline-block;;vertical-align:middle;width:25%;" +      .btn-group.btn-group-sm style="padding:0;" +        .btn.btn-default +          span.fa.fa-times +        .btn.btn-primary +          span.fa.fa-arrow-up +        .btn.btn-primary +          span.fa.fa-arrow-down +        = link_to_remove_association f, class: 'btn btn-danger' do +          span.fa.fa-trash diff --git a/app/views/routes/edit.html.slim b/app/views/routes/edit.html.slim index 7e2c1f982..a0431dc32 100644 --- a/app/views/routes/edit.html.slim +++ b/app/views/routes/edit.html.slim @@ -1,3 +1,5 @@  = title_tag t('routes.edit.title', route: @route.name ) -== render 'form'
\ No newline at end of file +.row +  .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2 +    == render 'form' diff --git a/app/views/routes/new.html.slim b/app/views/routes/new.html.slim index e91ebf362..51410a2e5 100644 --- a/app/views/routes/new.html.slim +++ b/app/views/routes/new.html.slim @@ -1,3 +1,5 @@  = title_tag t('routes.new.title') -== render 'form'
\ No newline at end of file +.row +  .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2 +    == render 'form' diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim index a4e1aa90f..cfd71e16a 100644 --- a/app/views/routes/show.html.slim +++ b/app/views/routes/show.html.slim @@ -6,66 +6,72 @@    .summary      p        label = "#{@route.human_attribute_name(:name)} : " -      = @route.name +      = " #{@route.name}"      p        label = "#{@route.human_attribute_name(:published_name)} : " -      = @route.published_name +      = " #{@route.published_name}" + +    / p +    /   label = "#{@route.human_attribute_name(:number)} : " +    /   = " #{@route.number}" +    /  +    / p +    /   label = "#{@route.human_attribute_name(:comment)} : " +    /   = " #{@route.comment}" +    /  +    / p +    /   label = "#{@route.human_attribute_name(:direction)} : " +    /   - if @route.direction +    /     = " #{@route.direction_text}" +    /   - else +    /     = " #{t('.undefined')}"      p -      label = "#{@route.human_attribute_name(:number)} : " -      = @route.number - -    p -      label = "#{@route.human_attribute_name(:comment)} : " -      = @route.comment - -    p -      label = "#{@route.human_attribute_name(:direction_code)} : " -      - if @route.direction_code -        = t("directions.label.#{@route.direction_code}").capitalize -      - else -        = t(".undefined") - -    p -      label = "#{@route.human_attribute_name(:wayback_code)} : " -      - if @route.wayback_code -        = t("waybacks.label.#{@route.wayback_code}").capitalize +      label = "#{@route.human_attribute_name(:wayback)} : " +      - if @route.wayback +        = " #{@route.wayback_text}"        - else -        = t(".undefined") +        = " #{t('.undefined')}"      p        label = "#{@route.human_attribute_name(:opposite_route)} : "        - if @route.opposite_route          = link_to @route.opposite_route.name, [@referential, @line, @route.opposite_route]        - else -        = t(".no_opposite_route") +        = " #{t('.no_opposite_route')}"  p.after_map -#accordion.panel-group -  .panel.panel-default -    .panel-heading -      h4.panel-title -        a data-toggle="collapse" data-parent="#accordion" href="#stop_points" -          = t('.stop_points') - -    #stop_points.panel-collapse.collapse -      .panel-body -        .stop_points.paginated_content -          = paginated_content(@route.stop_points, "stop_points/stop_point") - -#accordion.panel-group -  .panel.panel-default -    .panel-heading -      h4.panel-title -        a data-toggle="collapse" data-parent="#accordion" href="#journey_patterns" -          = t('.journey_patterns') - -    #journey_patterns.panel-collapse.collapse -      .panel-body -        .journey_patterns.paginated_content -          = paginated_content( @route.journey_patterns, "journey_patterns/journey_pattern") +#stop_points.panel.panel-default +  .panel-heading +    h4.panel-title +      strong = t('.stop_points') +   +  .list-group +    - @route.stop_points.each do |point| +      - if point.stop_area.zip_code && point.stop_area.city_name +        - linktxt = "#{point.stop_area.name}, #{point.stop_area.zip_code} #{point.stop_area.city_name}" +      - else +        - linktxt = "#{point.stop_area.name}" +       +      = link_to [@referential, point.stop_area], { style: 'display: table;width: 100%;', class: 'list-group-item', title: "Voir l'arrêt '#{linktxt}'" } do +        div style='display: table-cell;vertical-align: middle;' +          div style='display: inline-block;width: 10%;vertical-align: middle;text-align: right;' +            span.label.label-default style='margin-right: 10px;' +              = "#{point.stop_area.id}" +          div style='display: inline-block;width: 90%;vertical-align: middle;' +            = linktxt +             + +/ .panel.panel-default +/   .panel-heading +/     h4.panel-title +/       strong = t('.journey_patterns') +/  +/   .panel-body +/     .journey_patterns.paginated_content +/       = paginated_content( @route.journey_patterns, "journey_patterns/journey_pattern")  - content_for :sidebar do    ul.actions @@ -76,15 +82,15 @@ p.after_map    ul.actions      - if @route.stop_points.size >= 2        li = link_to t('journey_patterns.actions.new'), new_referential_line_route_journey_pattern_path(@referential, @line, @route), class: 'add' -     -    - if @route.stop_points.present? -      li = link_to t('routes.actions.edit_boarding_alighting'), edit_boarding_alighting_referential_line_route_path(@referential, @line, @route), class: 'edit' -     + +    / - if @route.stop_points.present? +    /   li = link_to t('routes.actions.edit_boarding_alighting'), edit_boarding_alighting_referential_line_route_path(@referential, @line, @route), class: 'edit' +      - if @route.journey_patterns.size > 0        li = link_to t('vehicle_journeys.actions.index'), [@referential, @line, @route, :vehicle_journeys], class: 'clock' -  ul.actions -    li = link_to t('vehicle_journey_imports.new.title'), new_referential_line_route_vehicle_journey_import_path( @referential, @line, @route ), class: 'import' -    li = link_to t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, format: :zip), class: 'export' +  / ul.actions +  /   li = link_to t('vehicle_journey_imports.new.title'), new_referential_line_route_vehicle_journey_import_path( @referential, @line, @route ), class: 'import' +  /   li = link_to t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, format: :zip), class: 'export' -  = creation_tag(@route)
\ No newline at end of file +  = creation_tag(@route) diff --git a/app/views/rule_parameter_sets/_form.html.slim b/app/views/rule_parameter_sets/_form.html.slim index 74ad9ae3b..b93caae58 100644 --- a/app/views/rule_parameter_sets/_form.html.slim +++ b/app/views/rule_parameter_sets/_form.html.slim @@ -25,7 +25,7 @@        thead        	tr            th = t("transport_modes.name") -           +            - RuleParameterSet.mode_attribute_prefixes.each do |prefix|              - if prefix == "allowed_transport"                - hidden = (@rule_parameter_set.check_allowed_transport_modes == "1") ? "" : 'display:none;' @@ -35,7 +35,8 @@                th = RuleParameterSet.human_attribute_name(prefix)        tbody -        - Chouette::Line.transport_modes.map(&:to_s).each do |mode| +        / To be removed, see #1936 +        - Chouette::Line.transport_mode.values.each do |mode|            tr              == render partial: "mode_fields", :locals => { f: form, mode: mode } @@ -69,4 +70,4 @@ javascript:      $( "#rule_parameter_set_check_allowed_transport_modes").change( function() {        $(".allowed").toggle();      }); -  });
\ No newline at end of file +  }); diff --git a/app/views/rule_parameter_sets/show.html.slim b/app/views/rule_parameter_sets/show.html.slim index 2d54f4572..6adfeab89 100644 --- a/app/views/rule_parameter_sets/show.html.slim +++ b/app/views/rule_parameter_sets/show.html.slim @@ -5,10 +5,10 @@      p        label = "#{RuleParameterSet.human_attribute_name('stop_areas_area')} : "        = @rule_parameter_set.stop_areas_area -     +      .attributes_group        span.title = t(".min_distance") -       +        .columns          .two_columns            label = "#{t('.inter_stop_area_distance_min')} : " @@ -20,7 +20,7 @@      .attributes_group        span.title = t(".max_distance") -       +        .columns          .two_columns            label = "#{t('.parent_stop_area_distance_max')} : " @@ -28,7 +28,7 @@          .two_columns            label = "#{t('.inter_connection_link_distance_max')} : " -          span.value = @rule_parameter_set.inter_connecion_link_distance_max +          span.value = @rule_parameter_set.inter_connection_link_distance_max        .columns          .two_columns @@ -91,23 +91,23 @@        table.table.table-striped.table-condensed          tr            th = t("transport_modes.name") -           +            - RuleParameterSet.mode_attribute_prefixes.each do |prefix|              - unless prefix == "allowed_transport"                th = RuleParameterSet.human_attribute_name(prefix) - -        - Chouette::Line.transport_modes.map(&:to_s).each do |mode| +        / To be removed, see #1936 +        - Chouette::Line.transport_mode.values.each do |mode|            - if @rule_parameter_set.allowed(mode)              tr                td = t("transport_modes.label.#{mode}") -               +                - RuleParameterSet.mode_attribute_prefixes.each do |prefix|                  - unless prefix == "allowed_transport"                    td = @rule_parameter_set.send  "#{prefix}_mode_#{mode}"      .rule_parameter_by_object        label = t("rule_parameter_sets.labels.columns_restrictions") -       +        table.table.table-bordered.table-condensed          - RuleParameterSet.validable_object_names.each do |object_name|            - if @rule_parameter_set.selected(object_name) @@ -119,7 +119,7 @@                  th = RuleParameterSet.human_attribute_name("string_type")                  th = RuleParameterSet.human_attribute_name("min_size")                  th = RuleParameterSet.human_attribute_name("max_size") -           +              tbody                - RuleParameterSet.validable_columns[object_name].each do |col|                  - if @rule_parameter_set.selected_column(object_name,col) @@ -140,4 +140,4 @@        li = link_to t('rule_parameter_sets.actions.edit'), edit_organisation_rule_parameter_set_path( @rule_parameter_set), class: 'edit'        - if current_organisation.rule_parameter_sets.size > 1 -        li = link_to  t('rule_parameter_sets.actions.destroy'), organisation_rule_parameter_set_path( @rule_parameter_set), method: :delete, data: { confirm: t('rule_parameter_sets.actions.destroy_confirm') }, class: 'remove'
\ No newline at end of file +        li = link_to  t('rule_parameter_sets.actions.destroy'), organisation_rule_parameter_set_path( @rule_parameter_set), method: :delete, data: { confirm: t('rule_parameter_sets.actions.destroy_confirm') }, class: 'remove' diff --git a/app/views/shared/_header.html.slim b/app/views/shared/_header.html.slim index 27b0139c2..73e705e35 100644 --- a/app/views/shared/_header.html.slim +++ b/app/views/shared/_header.html.slim @@ -7,7 +7,7 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation"          span.icon-bar          span.icon-bar          span.icon-bar -        span.icon-bar.version = APP_VERSION +        / span.icon-bar.version = APP_VERSION        = link_to referentials_path, class: 'navbar-brand' do          / = image_tag("logo_chouette.png") @@ -85,12 +85,12 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation"                  = link_to referential_route_sections_path(@referential) do                    span.badge.pull-right = @referential.route_sections.size                    = Referential.human_attribute_name("route_sections") -                 +                li                  = link_to referential_timebands_path(@referential) do                    span.badge.pull-right = @referential.timebands.size                    = Referential.human_attribute_name("timebands") -           +            li              = link_to Referential.human_attribute_name("imports"), referential_imports_path(@referential)            li @@ -128,4 +128,4 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation"                li = link_to t('layouts.user.sign_out'), destroy_user_session_path, method: :delete                li.divider                li -                = tab_link_to Organisation.model_name.human, organisation_path
\ No newline at end of file +                = tab_link_to Organisation.model_name.human, organisation_path diff --git a/app/views/shared/_lines_search_form.html.slim b/app/views/shared/_lines_search_form.html.slim new file mode 100644 index 000000000..8cab8caf4 --- /dev/null +++ b/app/views/shared/_lines_search_form.html.slim @@ -0,0 +1,24 @@ +- referential = instance_variable_get("@#{referential_type}") += search_form_for @q, url: eval("#{referential_type}_lines_path(referential)"), remote: true, html: { method: :get, class: 'form-inline', id: 'search', role: 'form' } do |f| +  .panel.panel-default +    .panel-heading +      .input-group.col-md-9.col-sm-9 +        = f.search_field :name_or_number_or_objectid_or_comment_cont, placeholder: t('lines.index.name_or_number_or_objectid_or_comment'), class: 'form-control' +        .input-group-btn +          button.btn.btn-primary type='submit' +            i.fa.fa-search + +      a data-toggle='collapse' data-parent='#search' href='#advanced_search' +        i.fa.fa-plus +        = " #{t('lines.index.advanced_search')}" + +    #advanced_search.panel-collapse.collapse +      .panel-body +        .row +          - %w(networks companies group_of_lines transport_modes).each do |filter| +            - options_container = (referential_type == 'referential' && filter == 'transport_modes') ? referential.line_referential : referential +            - if options_container && options_container.send(filter).any? +              - options = options_container.send(filter).collect { |f| [f.name, filter == 'transport_modes' ? f.name : f.id] }.unshift([t("lines.index.no_#{filter}"), -1]) +              - matcher = filter == 'transport_modes' ? :transport_mode_eq : :"#{filter == 'group_of_lines' ? filter : filter.singularize}_id_eq" +              .col-xs-3 +                = f.select(matcher, options, { include_blank: '' }, { class: 'form-control', style: 'width: 100%', 'data-select2ed': 'true', 'data-select2ed-placeholder': t("lines.index.all_#{filter}") }) diff --git a/app/views/stop_area_referentials/show.html.slim b/app/views/stop_area_referentials/show.html.slim index 9cceed5e5..9080d1bec 100644 --- a/app/views/stop_area_referentials/show.html.slim +++ b/app/views/stop_area_referentials/show.html.slim @@ -13,17 +13,19 @@    h3 Historique des synchronisations    ul.list-group width="75%" -  - @stop_area_referential.stop_area_referential_syncs.each do |sync| -    - unless sync.stop_area_referential_sync_messages.empty? -      - sync.stop_area_referential_sync_messages.last.tap do |log| -        - if log.criticity = log.criticity -          li.alert class="alert-#{log.criticity}" -            strong = l(log.created_at, format: :short) + " : " -            / [:processing_time] unit conversion -            - data = log.message_attributs.symbolize_keys! -            - data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) +  - @stop_area_referential.stop_area_referential_syncs.each_with_index do |sync, i| +    / Display only 10 msgs +    - if i < 10 +      - unless sync.stop_area_referential_sync_messages.empty? +        - sync.stop_area_referential_sync_messages.last.tap do |log| +          - if log.criticity = log.criticity +            li.alert class="alert-#{criticity_class(log.criticity)}" +              strong = l(log.created_at, format: :short) + " : " +              / [:processing_time] unit conversion +              - data = log.message_attributs.symbolize_keys! +              - data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) -            = t("stop_area_referential_sync.message.#{log.message_key}", log.message_attributs.symbolize_keys!) +              = t("stop_area_referential_sync.message.#{log.message_key}", log.message_attributs.symbolize_keys!)  - content_for :sidebar do    ul.actions diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim index 7f7e1fa74..7701fb268 100644 --- a/app/views/stop_areas/index.html.slim +++ b/app/views/stop_areas/index.html.slim @@ -23,7 +23,7 @@              = f.select(:area_type_cont, options_from_collection_for_select(Chouette::StopArea.stop_area_types, 'name', Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } ), { include_blank: t('.area_type') }, { class: 'form-control' })        .col-md-2.col-sm-3 -        button.btn.btn-primary.btn-block type="submit" Filtrer         +        button.btn.btn-primary.btn-block type="submit" Filtrer  #stop_areas    = render 'stop_areas' diff --git a/app/views/vehicle_journeys/_form.html.slim b/app/views/vehicle_journeys/_form.html.slim index bc26e1ac5..c738b8b00 100644 --- a/app/views/vehicle_journeys/_form.html.slim +++ b/app/views/vehicle_journeys/_form.html.slim @@ -7,7 +7,7 @@      = form.input :published_journey_name      = form.input :published_journey_identifier      = form.input :comment -    = form.input :transport_mode_name, as: :select, :collection => Chouette::Line.transport_modes, :include_blank => true, :member_label => Proc.new { |mode| t("transport_modes.label.#{mode}") } +    = form.input :transport_mode, include_blank: false      = form.input :mobility_restricted_suitability, as: :select, :collection => [[vehicle_journey.human_attribute_name("accessible"), true], [vehicle_journey.human_attribute_name("not_accessible"), false]], :include_blank => true      = form.input :flexible_service, as: :select, :collection => [[vehicle_journey.human_attribute_name("on_demand_fs"), true], [vehicle_journey.human_attribute_name("regular_fs"), false]], :include_blank => true      = form.input :status_value @@ -23,4 +23,4 @@      = form.action :submit, as: :button, label: t(".submit_#{vehicle_journey.journey_category}#{'_edit' unless form.object.new_record?}"), button_html: { class: 'btn btn-primary' }      = form.action :cancel, as: :link -== render 'form_footer', vehicle_journey: vehicle_journey
\ No newline at end of file +== render 'form_footer', vehicle_journey: vehicle_journey diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim new file mode 100644 index 000000000..2f9937452 --- /dev/null +++ b/app/views/workbenches/show.html.slim @@ -0,0 +1,74 @@ += title_tag "#{@workbench.name} - Tableau de bord" + +.referentials.paginated_content +  h4 Liste des jeux de données + +  table.table.table-bordered.table-hover +    thead +      tr +        th = Referential.human_attribute_name(:name) +        th = Referential.human_attribute_name(:updated_at) +        th = "Publié le" +        th = Referential.human_attribute_name(:validity_period) +        th = Referential.human_attribute_name(:lines) +        th = Referential.human_attribute_name(:organisation) +        th = "Etat" +        th = "Actions" + +    tbody +      - @wbench_refs.each do |referential| +        tr +          td = referential.name +          td = l referential.updated_at, format: :long +          td +          td +            - if referential.validity_period.nil? +              = Referential.human_attribute_name('no_validity_period') +            - else +              => Referential.human_attribute_name('start_validity_period') +              => l referential.validity_period.begin, format: :long +              => Referential.human_attribute_name('end_validity_period') +              => l referential.validity_period.end, format: :long + +          td = referential.lines.count +          td = referential.organisation.name + +          / Status (archived?) +          td.text-center +            - if referential.archived? +              span.fa.fa-archive title="Archivé" +            - else +              = "-" + +          / Actions +          td.text-center +            .btn-group.btn-group-xs +              .btn-primary.btn.dropdown-toggle data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" +                span.fa.fa-bars +                span.caret + +              ul.dropdown-menu +                li = link_to "Voir", referential_path(referential) + +                - unless referential.archived? # FIXME +                  li = link_to "Editer", edit_referential_path(referential) + +                li = link_to "Cloner", new_referential_path(from: referential) + +                li +                  - if referential.archived? +                    - if referential.can_unarchive? +                      = link_to "Désarchiver", unarchive_referential_path(referential), method: :put +                    - else +                      = link_to "Désarchiver", "#" +                  - else +                    = link_to "Archiver", archive_referential_path(referential), method: :put + +                li = link_to "Supprimer", referential_path(referential), method: :delete, :data => {:confirm => t('referentials.actions.destroy_confirm')} + +  .text-center +    = will_paginate @wbench_refs, container: false, renderer: RemoteBootstrapPaginationLinkRenderer + +- content_for :sidebar do +  ul.actions +    li = link_to t('referentials.actions.new'), new_referential_path(workbench_id: @workbench), class: 'add' diff --git a/app/workers/clean_up_worker.rb b/app/workers/clean_up_worker.rb new file mode 100644 index 000000000..2d76b3a68 --- /dev/null +++ b/app/workers/clean_up_worker.rb @@ -0,0 +1,17 @@ +class CleanUpWorker +  include Sidekiq::Worker +  sidekiq_options :retry => false + +  def perform(id) +    cleaner = CleanUp.find id +    cleaner.run if cleaner.may_run? +    begin +      cleaner.referential.switch +      result = cleaner.clean +      cleaner.successful(result) +    rescue Exception => e +      Rails.logger.error "CleanUpWorker : #{e}" +      cleaner.failed({error: e.message}) +    end +  end +end diff --git a/app/workers/referential_cloning_worker.rb b/app/workers/referential_cloning_worker.rb new file mode 100644 index 000000000..dda569d7c --- /dev/null +++ b/app/workers/referential_cloning_worker.rb @@ -0,0 +1,24 @@ +class ReferentialCloningWorker +  include Sidekiq::Worker + +  def perform(id) +    # Replace default apartment created schema with clone schema from source referential +    ref_cloning = ReferentialCloning.find id +    sql_func    = "CREATE OR REPLACE FUNCTION clone_schema( source_schema text, dest_schema text, include_recs boolean) RETURNS void AS $BODY$ DECLARE src_oid oid; tbl_oid oid; func_oid oid; object text; buffer text; srctbl text; default_ text; column_ text; qry text; dest_qry text; v_def text; seqval bigint; sq_last_value bigint; sq_max_value bigint; sq_start_value bigint; sq_increment_by bigint; sq_min_value bigint; sq_cache_value bigint; sq_log_cnt bigint; sq_is_called boolean; sq_is_cycled boolean; sq_cycled char(10); BEGIN SELECT oid INTO src_oid FROM pg_namespace WHERE nspname = quote_ident(source_schema); IF NOT FOUND THEN RAISE NOTICE 'source schema % does not exist!', source_schema; RETURN ; END IF; PERFORM nspname FROM pg_namespace WHERE nspname = quote_ident(dest_schema); IF FOUND THEN RAISE NOTICE 'dest schema % already exists!', dest_schema; RETURN ; END IF; EXECUTE 'CREATE SCHEMA ' || quote_ident(dest_schema) ; FOR object IN SELECT sequence_name::text FROM information_schema.sequences WHERE sequence_schema = quote_ident(source_schema) LOOP EXECUTE 'CREATE SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object); srctbl := quote_ident(source_schema) || '.' || quote_ident(object); EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';' INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ; IF sq_is_cycled THEN sq_cycled := 'CYCLE'; ELSE sq_cycled := 'NO CYCLE'; END IF; EXECUTE 'ALTER SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object) || ' INCREMENT BY ' || sq_increment_by || ' MINVALUE ' || sq_min_value || ' MAXVALUE ' || sq_max_value || ' START WITH ' || sq_start_value || ' RESTART ' || sq_min_value || ' CACHE ' || sq_cache_value || sq_cycled || ' ;' ; buffer := quote_ident(dest_schema) || '.' || quote_ident(object); IF include_recs THEN EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ; ELSE EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ; END IF; END LOOP; FOR object IN SELECT TABLE_NAME::text FROM information_schema.tables WHERE table_schema = quote_ident(source_schema) AND table_type = 'BASE TABLE' LOOP buffer := dest_schema || '.' || quote_ident(object); EXECUTE 'CREATE TABLE ' || buffer || '(LIKE ' || quote_ident(source_schema) || '.' || quote_ident(object) || ' INCLUDING ALL)'; IF include_recs THEN EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';'; END IF; FOR column_, default_ IN SELECT column_name::text, REPLACE(column_default::text, source_schema, dest_schema) FROM information_schema.COLUMNS WHERE table_schema = dest_schema AND TABLE_NAME = object AND column_default LIKE 'nextval(%' || quote_ident(source_schema) || '%::regclass)' LOOP EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_; END LOOP; END LOOP; FOR qry IN SELECT 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname) || ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';' FROM pg_constraint ct JOIN pg_class rn ON rn.oid = ct.conrelid WHERE connamespace = src_oid AND rn.relkind = 'r' AND ct.contype = 'f' LOOP EXECUTE qry; END LOOP; FOR object IN SELECT table_name::text, view_definition FROM information_schema.views WHERE table_schema = quote_ident(source_schema) LOOP buffer := dest_schema || '.' || quote_ident(object); SELECT view_definition INTO v_def FROM information_schema.views WHERE table_schema = quote_ident(source_schema) AND table_name = quote_ident(object); EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ; END LOOP; FOR func_oid IN SELECT oid FROM pg_proc WHERE pronamespace = src_oid LOOP SELECT pg_get_functiondef(func_oid) INTO qry; SELECT replace(qry, source_schema, dest_schema) INTO dest_qry; EXECUTE dest_qry; END LOOP; RETURN; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;" +    sql_clone   = "SELECT clone_schema('#{ref_cloning.source_referential.slug}', '#{ref_cloning.target_referential.slug}_tmp', TRUE);" +    sql_drop    = "DROP SCHEMA #{ref_cloning.target_referential.slug} CASCADE;" +    sql_rename  = "ALTER SCHEMA #{ref_cloning.target_referential.slug}_tmp RENAME TO #{ref_cloning.target_referential.slug};" +    ref_cloning.run! + +    begin +      ActiveRecord::Base.connection.execute sql_func +      ActiveRecord::Base.connection.execute sql_clone +      ActiveRecord::Base.connection.execute sql_drop +      ActiveRecord::Base.connection.execute sql_rename +      ref_cloning.successful! +    rescue Exception => e +      Rails.logger.error "ReferentialCloningWorker : #{e}" +      ref_cloning.failed! +    end +  end +end diff --git a/config/application.rb b/config/application.rb index 52da477a5..70b927855 100644 --- a/config/application.rb +++ b/config/application.rb @@ -26,5 +26,20 @@ module ChouetteIhm      # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.      # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]      config.i18n.default_locale = :fr + +    # Configure Browserify to use babelify to compile ES6 +    config.browserify_rails.commandline_options = "-t [ babelify --presets [ react es2015 ] ]" + +    config.active_record.observers = :route_observer + +    unless Rails.env.production? +        # Work around sprockets+teaspoon mismatch: +        Rails.application.config.assets.precompile += %w(spec_helper.js) +        # Make sure Browserify is triggered when +        # asked to serve javascript spec files +        config.browserify_rails.paths << lambda { |p| +            p.start_with?(Rails.root.join("spec/javascripts").to_s) +        } +    end    end  end diff --git a/config/deploy.rb b/config/deploy.rb index cd6391ec3..bfbcabb4e 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -23,6 +23,11 @@ ssh_options[:forward_agent] = true  require "bundler/capistrano"  require 'whenever/capistrano' +require 'capistrano/npm' +set :npm_options, '--production --silent --no-progress' + +after 'deploy:finalize_update', 'npm:install' +  # Whenever  set :whenever_variables, ->{ "'environment=#{fetch :whenever_environment}&bundle_command=bin/bundle exec&additionnal_path=/var/lib/gems/2.2.0/bin'" } # invoke bin/bundle to use 'correct' ruby environment @@ -73,10 +78,3 @@ namespace :deploy do      run "cd #{current_path} && #{bundle_cmd} exec /var/lib/gems/2.2.0/bin/rake db:seed RAILS_ENV=#{rails_env}"    end  end - -namespace :delayed_job do -  task :restart do -    run "sudo /etc/init.d/stif-boiv restart" -  end -  # after "deploy:restart", "delayed_job:restart" -end diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index db352fa6f..b439821d2 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -19,9 +19,9 @@ Apartment.configure do |config|    #    config.excluded_models = [      "Referential", +    "ReferentialMetadata",      "Organisation",      "User", -    "Delayed::Backend::ActiveRecord::Job",      "Api::V1::ApiKey",      "RuleParameterSet",      "StopAreaReferential", @@ -34,7 +34,11 @@ Apartment.configure do |config|      "Chouette::Line",      "Chouette::GroupOfLine",      "Chouette::Company", -    "Chouette::Network" +    "Chouette::Network", +    "ReferentialCloning", +    "Workbench", +    "CleanUp", +    "CleanUpResult"    ]    # use postgres schemas? diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d2f4ec33a..928236c4a 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -5,4 +5,4 @@ Rails.application.config.assets.version = '1.0'  # Precompile additional assets.  # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) +Rails.application.config.assets.precompile += %w( es6_browserified/*.js ) diff --git a/config/initializers/delayed_job_config.rb b/config/initializers/delayed_job_config.rb deleted file mode 100644 index 147b2550e..000000000 --- a/config/initializers/delayed_job_config.rb +++ /dev/null @@ -1,6 +0,0 @@ -# config/initializers/delayed_job_config.rb -#Delayed::Job.destroy_failed_jobs = false -silence_warnings do -  Delayed::Job.const_set("MAX_ATTEMPTS", 1) -  Delayed::Job.const_set("MAX_RUN_TIME", 12.hours) -end
\ No newline at end of file diff --git a/config/initializers/devise_async.rb b/config/initializers/devise_async.rb index 3ee0a7858..10f4d98b6 100644 --- a/config/initializers/devise_async.rb +++ b/config/initializers/devise_async.rb @@ -1,2 +1,2 @@ -Devise::Async.backend = :delayed_job +Devise::Async.backend = :sidekiq  Devise::Async.enabled = false # Set to true to use Delayed Job for asynchronous mail diff --git a/config/initializers/postgresql_adapter_patch.rb b/config/initializers/postgresql_adapter_patch.rb index ae228f62f..2e4d73f85 100644 --- a/config/initializers/postgresql_adapter_patch.rb +++ b/config/initializers/postgresql_adapter_patch.rb @@ -10,3 +10,45 @@  #   end  # end  # ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "bigserial primary key" + +# Add missing double-quote to write array of daterange in SQL query +# See #1782 + +class ActiveRecord::ConnectionAdapters::PostgreSQLColumn + +  def self.array_to_string(value, column, adapter) +    casted_values = value.map do |val| +      if String === val +        if val == "NULL" +          "\"#{val}\"" +        else +          quote_and_escape(adapter.type_cast(val, column, true)) +        end +      elsif Range === val +        casted_value = adapter.type_cast(val, column, true) +        "\"#{casted_value}\"" +      else +        adapter.type_cast(val, column, true) +      end +    end +    "{#{casted_values.join(',')}}" +  end + +end + +module ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID +  class DateRange < Range +    # Unnormalize daterange +    # [2016-11-19,2016-12-26) -> 2016-11-19..2016-12-25 +    def type_cast(value) +      result = super value + +      if result.respond_to?(:exclude_end?) && result.exclude_end? +        ::Range.new(result.begin, result.end - 1, false) +      else +        result +      end +    end +  end +  register_type 'daterange', DateRange.new(:date) +end diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb index d5492e529..472863fa8 100644 --- a/config/initializers/simple_form.rb +++ b/config/initializers/simple_form.rb @@ -5,8 +5,9 @@ SimpleForm.setup do |config|    # wrapper, change the order or even add your own to the    # stack. The options given below are used to wrap the    # whole input. -  config.wrappers :default, class: :input, -    hint_class: :field_with_hint, error_class: :field_with_errors do |b| +  config.wrappers :default, class: 'form-group', +    error_class: 'has-error' do |b| +    # hint_class: :field_with_hint, error_class: :field_with_errors do |b|      ## Extensions enabled by default      # Any of these extensions can be disabled for a      # given input by passing: `f.input EXTENSION_NAME => false`. @@ -41,8 +42,8 @@ SimpleForm.setup do |config|      ## Inputs      b.use :label_input -    b.use :hint,  wrap_with: { tag: :span, class: :hint }      b.use :error, wrap_with: { tag: :span, class: :error } +    b.use :hint,  wrap_with: { tag: :span, class: :hint }      ## full_messages_for      # If you want to display the full error message for the attribute, you can @@ -72,7 +73,7 @@ SimpleForm.setup do |config|    config.error_notification_tag = :div    # CSS class to add for error notification helper. -  config.error_notification_class = 'error_notification' +  config.error_notification_class = 'alert alert-error'    # ID to add for error notification helper.    # config.error_notification_id = nil @@ -90,25 +91,24 @@ SimpleForm.setup do |config|    # config.collection_wrapper_class = nil    # You can wrap each item in a collection of radio/check boxes with a tag, -  # defaulting to :span. Please note that when using :boolean_style = :nested, -  # SimpleForm will force this option to be a label. +  # defaulting to :span.    # config.item_wrapper_tag = :span    # You can define a class to use in all item wrappers. Defaulting to none.    # config.item_wrapper_class = nil    # How the label text should be generated altogether with the required text. -  # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } +  config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }    # You can define the class to use on all labels. Default is nil.    # config.label_class = nil    # You can define the default class to be used on forms. Can be overriden    # with `html: { :class }`. Defaulting to none. -  # config.default_form_class = nil +  config.default_form_class = 'form'    # You can define which elements should obtain additional classes -  # config.generate_additional_classes_for = [:wrapper, :label, :input] +  config.generate_additional_classes_for = [:label, :input]    # Whether attributes are required by default (or not). Default is true.    # config.required_by_default = true diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb index 4f4dc23b3..be0f4bf55 100644 --- a/config/initializers/simple_form_bootstrap.rb +++ b/config/initializers/simple_form_bootstrap.rb @@ -14,8 +14,8 @@ SimpleForm.setup do |config|      b.use :label, class: 'control-label'      b.use :input, class: 'form-control' -    b.use :error, wrap_with: { tag: 'span', class: 'help-block' } -    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +    b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }    end    config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -26,8 +26,8 @@ SimpleForm.setup do |config|      b.use :label, class: 'control-label'      b.use :input -    b.use :error, wrap_with: { tag: 'span', class: 'help-block' } -    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +    b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }    end    config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -38,8 +38,8 @@ SimpleForm.setup do |config|        ba.use :label_input      end -    b.use :error, wrap_with: { tag: 'span', class: 'help-block' } -    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +    b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }    end    config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -47,8 +47,8 @@ SimpleForm.setup do |config|      b.optional :readonly      b.use :label, class: 'control-label'      b.use :input -    b.use :error, wrap_with: { tag: 'span', class: 'help-block' } -    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +    b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }    end    config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -62,8 +62,8 @@ SimpleForm.setup do |config|      b.wrapper tag: 'div', class: 'col-sm-9' do |ba|        ba.use :input, class: 'form-control' -      ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } -      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +      ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }      end    end @@ -76,8 +76,8 @@ SimpleForm.setup do |config|      b.wrapper tag: 'div', class: 'col-sm-9' do |ba|        ba.use :input -      ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } -      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +      ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }      end    end @@ -90,8 +90,8 @@ SimpleForm.setup do |config|          ba.use :label_input        end -      wr.use :error, wrap_with: { tag: 'span', class: 'help-block' } -      wr.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +      wr.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +      wr.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }      end    end @@ -103,8 +103,8 @@ SimpleForm.setup do |config|      b.wrapper tag: 'div', class: 'col-sm-9' do |ba|        ba.use :input -      ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } -      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +      ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }      end    end @@ -118,45 +118,32 @@ SimpleForm.setup do |config|      b.use :label, class: 'sr-only'      b.use :input, class: 'form-control' -    b.use :error, wrap_with: { tag: 'span', class: 'help-block' } -    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +    b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }    end -  config.wrappers :form_without_label, :tag => 'div', :class => 'form-group', :error_class => 'error' do |b| - +  config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|      b.use :html5 -    b.use :placeholder -    b.optional :maxlength -    b.optional :pattern -    b.optional :min_max      b.optional :readonly - -    b.wrapper tag: 'div', class: 'col-sm-12' do |ba| +    b.use :label, class: 'control-label' +    b.wrapper tag: 'div', class: 'form-inline' do |ba|        ba.use :input, class: 'form-control' -      ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } -      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' } +      ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } +      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block small' }      end -  end                                                                                       -                                                                                         -  config.wrappers :nested, :tag => 'span', :error_class => 'has-error' do |b| -     b.use :html5 -     b.use :placeholder -     b.optional :readonly -     b.use :input -     b.use :error, wrap_with: { tag: 'span', class: 'help-block' } -     b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }    end -    # Wrappers for forms and inputs using the Bootstrap toolkit.    # Check the Bootstrap docs (http://getbootstrap.com)    # to learn about the different styles for forms and inputs,    # buttons and other elements. -  config.default_wrapper = :horizontal_form +  config.default_wrapper = :vertical_form    config.wrapper_mappings = {      check_boxes: :vertical_radio_and_checkboxes,      radio_buttons: :vertical_radio_and_checkboxes,      file: :vertical_file_input,      boolean: :vertical_boolean, +    datetime: :multi_select, +    date: :multi_select, +    time: :multi_select    }  end - diff --git a/config/locales/clean_ups.en.yml b/config/locales/clean_ups.en.yml index 27b3dc5c1..148362c35 100644 --- a/config/locales/clean_ups.en.yml +++ b/config/locales/clean_ups.en.yml @@ -3,12 +3,6 @@ en:      success_tm: "%{count} time tables deleted"      success_vj: "%{count} vehicle journeys deleted"      success_jp: "%{count} journey patterns deleted" -    success_r: "%{count} routes deleted" -    success_l: "%{count} lines deleted" -    success_sa: "%{count} stop areas deleted" -    success_c: "%{count} companies deleted" -    success_n: "%{count} networks deleted" -    success_g: "%{count} groups of lines deleted"      failure: "Fail when clean_up : %{error_message}"      actions:        clean_up: "clean up" @@ -16,12 +10,15 @@ en:    activemodel:      attributes:        clean_up: -        expected_date: "Final date : " -        keep_lines: "keep lines" -        keep_stops: "keep stop areas" -        keep_companies: "keep companies" -        keep_networks: "keep networks" -        keep_group_of_lines: "keep groups of lines" +        begin_date: "Begin date : " +        end_date: "End date : "    titles:      clean_up: -      expected_date: "value included in clean up" +      begin_date: "Begin date of clean up" +      end_date: "End date of clean up" + +  formtastic: +    titles: +      clean_up: +        begin_date: "Begin date of clean up" +        end_date: "End date of clean up" diff --git a/config/locales/clean_ups.fr.yml b/config/locales/clean_ups.fr.yml index 13d34ac4c..cb0ce3f1a 100644 --- a/config/locales/clean_ups.fr.yml +++ b/config/locales/clean_ups.fr.yml @@ -3,12 +3,6 @@ fr:      success_tm: "%{count} calendrier(s) supprimé(s)"      success_vj: "%{count} course(s) supprimée(s)"      success_jp: "%{count} mission(s) supprimée(s)" -    success_r: "%{count} séquence(s) d'arrêt supprimée(s)" -    success_l: "%{count} ligne(s) supprimée(s)" -    success_sa: "%{count} arrêt(s) supprimé(s)" -    success_c: "%{count} transporteur(s) supprimé(s)" -    success_n: "%{count} réseau(x) supprimé(s)" -    success_g: "%{count} groupe(s) de lignes supprimé(s)"      failure: "Echec de la purge : %{error_message}"      actions:        clean_up: "Purger" @@ -16,12 +10,15 @@ fr:    activemodel:      attributes:        clean_up: -        expected_date: "Date limite : " -        keep_lines: "conserver les lignes" -        keep_stops: "conserver les arrêts" -        keep_companies: "conserver les transporteurs" -        keep_networks: "conserver les réseaux" -        keep_group_of_lines: "conserver les groupes de lignes" +        begin_date: "Début date limite : " +        end_date: "Fin date limite : "    titles:      clean_up: -      expected_date: "valeur incluse dans la purge" +      begin_date: "Début date de la purge" +      end_date: "Fin date de la purge" + +  formtastic: +    titles: +      clean_up: +        begin_date: "Début date de la purge" +        end_date: "Fin date de la purge" diff --git a/config/locales/enumerize.en.yml b/config/locales/enumerize.en.yml index 99e2edb75..e09a08696 100644 --- a/config/locales/enumerize.en.yml +++ b/config/locales/enumerize.en.yml @@ -33,3 +33,190 @@ en:        netex: "Experimental"        hub: "Specific Transdev Format"        kml: "line, route, ... drawings on Keyhole Markup Language format" +    route: +      direction: +        straight_forward: 'Straight Forward' +        backward: 'Backward' +        clockwise: 'ClockWise' +        counter_clockwise: 'Counter Clockwise' +        north: 'North' +        north_west: 'North West' +        west: 'West' +        south_west: 'South West' +        south: 'South' +        south_east: 'South East' +        east: 'East' +        north_east: 'North East' +      wayback: +        straight_forward: 'Straight Forward' +        backward: 'Backward' +    vehicle_journey: +      transport_mode: +        interchange: Interchange +        unknown: "unknown" +        air: "Air" +        train: "Train" +        long_distance_train: "Long distance train" +        local_train: "Local train" +        rapid_transit: "Rapid transit" +        metro: "Metro" +        tramway: "Tramway" +        coach: "Coach" +        bus: "Bus" +        ferry: "Ferry" +        waterborne: "Waterborne" +        private_vehicle: "Private vehicle" +        walk: "Walk" +        trolleybus: "Trolleybus" +        bicycle: "Bicycle" +        shuttle: "Shuttle" +        taxi: "Taxi" +        val: "VAL" +        other: "Other" +        air: Air +        bus: Bus +        coach: Coach +        ferry: Ferry +        metro: Metro +        rail: Rail +        trolleybus: Trolleybus +        tram: Tramway +        water: Water +        cableway: Cableway +        funicular: Funicular +        other: Other + +    line: +      transport_mode: +        interchange: Interchange +        unknown: "unknown" +        air: "Air" +        train: "Train" +        long_distance_train: "Long distance train" +        local_train: "Local train" +        rapid_transit: "Rapid transit" +        metro: "Metro" +        tramway: "Tramway" +        coach: "Coach" +        bus: "Bus" +        ferry: "Ferry" +        waterborne: "Waterborne" +        private_vehicle: "Private vehicle" +        walk: "Walk" +        trolleybus: "Trolleybus" +        bicycle: "Bicycle" +        shuttle: "Shuttle" +        taxi: "Taxi" +        val: "VAL" +        other: "Other" +        air: Air +        bus: Bus +        coach: Coach +        ferry: Ferry +        metro: Metro +        rail: Rail +        trolleybus: Trolleybus +        tram: Tramway +        water: Water +        cableway: Cableway +        funicular: Funicular +        other: Other +      transport_submode: +        unknown: 'Unknown' +        undefined: 'Undefined' +        internationalFlight: 'International flight' +        domesticFlight: 'Domestic flight' +        intercontinentalFlight: 'Intercontinental flight' +        domesticScheduledFlight: 'Domestic scheduled flight' +        shuttleFlight: 'Shuttle flight' +        intercontinentalCharterFlight: "Intercontinental charter flight" +        internationalCharterFlight: "International charter flight" +        roundTripCharterFlight: "Roundtrip charter flight" +        sightseeingFlight: 'Sightseeing flight' +        helicopterService: "Helicopter service" +        domesticCharterFlight: "Domestic charter flight" +        SchengenAreaFlight: 'Schengen area flight' +        airshipService: 'Airship service' +        shortHaulInternationalFlight: 'Short haul international flight' +        canalBarge: 'Canal barge' +        localBus: 'Local bus' +        regionalBus: 'Regional bus' +        expressBus: 'Express bus' +        nightBus: 'Night bus' +        postBus: 'Post but' +        specialNeedsBus: 'Special needs bus' +        mobilityBus: 'Mobility bus' +        mobilityBusForRegisteredDisabled: 'Mobility bus for registered disabled' +        sightseeingBus: 'sightseeingBus' +        shuttleBus: 'Shuttle bus' +        highFrequencyBus: 'High frequency bus' +        dedicatedLaneBus: 'Dedicated lane bus' +        schoolBus: 'School bus' +        schoolAndPublicServiceBus: 'School and public service bus' +        railReplacementBus: 'Rail replacement bus' +        demandAndResponseBus: 'Demand and response bus' +        airportLinkBus: 'Airport link bus' +        internationalCoach: 'International coach' +        nationalCoach: 'National coach' +        shuttleCoach: 'Shuttle coach' +        regionalCoach: 'Regional coach' +        specialCoach: 'Special coach' +        schoolCoach: 'School coach' +        sightseeingCoach: 'Sightseeing coach' +        touristCoach: 'Tourist coach' +        commuterCoach: 'Commuter coach' +        metro: 'Metro' +        tube: 'Tube' +        urbanRailway: 'Urban railway' +        local: 'Local' +        highSpeedRail: 'High speed rail' +        suburbanRailway: 'Suburban railway' +        regionalRail: 'Regional rail' +        interregionalRail: 'Interregional rail' +        longDistance: 'Long distance' +        international: 'International' +        sleeperRailService: 'Sleeper rail service' +        nightRail: 'Night rail' +        carTransportRailService: 'Car transport rail service' +        touristRailway: 'Tourist railway' +        railShuttle: 'Rail shuttle' +        replacementRailService: 'Replacement rail service' +        specialTrain: 'Special train' +        crossCountryRail: 'Cross country rail' +        rackAndPinionRailway: 'Rack and pinion railway' +        cityTram: 'City tram' +        localTram: 'Local tram' +        regionalTram: 'Regional tram' +        sightseeingTram: 'Sightseeing tram' +        shuttleTram: 'Shuttle tram' +        trainTram: 'Train tram' +        internationalCarFerry: 'International car ferry' +        nationalCarFerry: 'National car ferry' +        regionalCarFerry: 'Regional car ferry' +        localCarFerry: 'Local car ferry' +        internationalPassengerFerry: 'International passenger ferry' +        nationalPassengerFerry: 'National passenger ferry' +        regionalPassengerFerry: 'Regional passenger ferry' +        localPassengerFerry: 'Local passenger ferry' +        postBoat: 'Post boat' +        trainFerry: 'Train ferry' +        roadFerryLink: 'Road ferry link' +        airportBoatLink: "Airport boat link" +        highSpeedVehicleService: 'High speed vehicle service' +        highSpeedPassengerService: 'High speed passenger service' +        sightseeingService: 'Sightseeing service' +        schoolBoat: 'School boat' +        cableFerry: 'Cable ferry' +        riverBus: 'River bus' +        scheduledFerry: 'Scheduled ferry' +        shuttleFerryService: 'Shuttle ferry service' +        telecabin: 'Telecabin' +        cableCar: 'Cable car' +        lift: 'Lift' +        chairLift: 'Chair lift' +        dragLift: 'Drag lift' +        telecabinLink: 'Telecabin link' +        funicular: 'Funicular' +        streetCableCar: 'Street cable car' +        allFunicularServices: 'All funicular services' +        undefinedFunicular: 'Undefined funicular' diff --git a/config/locales/enumerize.fr.yml b/config/locales/enumerize.fr.yml index 4bfd71d28..62f5d53f6 100644 --- a/config/locales/enumerize.fr.yml +++ b/config/locales/enumerize.fr.yml @@ -1,6 +1,6 @@  fr: -  simple_form:   -    include_blanks:      +  simple_form: +    include_blanks:        defaults:          for_boarding: "Non défini"          for_alighting: "Non défini" @@ -9,7 +9,7 @@ fr:        normal: "Montée autorisée"        forbidden: "Montée interdite"        request_stop: "Montée sur demande au conducteur" -      is_flexible: "Montée sur réservation"                 +      is_flexible: "Montée sur réservation"      for_alighting:        normal: "Descente autorisée"        forbidden: "Descente interdite" @@ -32,4 +32,190 @@ fr:        gtfs: "General Transit Feed Specification défini par Google"        netex: "Expérimental"        hub: "Format spécifique Transdev" -      kml: "Tracés de lignes, séquences d'arrêts, ...  en 'Keyhole Markup Language'"   +      kml: "Tracés de lignes, séquences d'arrêts, ...  en 'Keyhole Markup Language'" +    route: +      direction: +        straight_forward: 'Aller' +        backward: 'Retour' +        clockwise: 'Sens horaire' +        counter_clockwise: 'Sens anti horaire' +        north: 'Nord' +        north_west: 'Nord Ouest' +        west: 'Ouest' +        south_west: 'Sud Ouest' +        south: 'Sud' +        south_east: 'Sud Est' +        east: 'Est' +        north_east: 'Nord Est' +      wayback: +        straight_forward: 'Aller' +        backward: 'Retour' +    vehicle_journey: +      transport_mode: +        interchange: Interconnection +        unknown: Inconnu +        air: Air +        train: Train +        long_distance_train: Train Grande Ligne +        local_train: TER +        rapid_transit: RER +        metro: Métro +        tramway: Tramway +        coach: Autocar +        bus: Bus +        ferry: Ferry +        waterborne: Bac +        private_vehicle: Voiture particulière +        walk: Marche à pied +        trolleybus: Trolleybus +        bicycle: Vélo +        shuttle: Navette +        taxi: Taxi +        val: VAL +        other: Autre +        bus: Bus +        coach: Autocar +        ferry: Ferry +        metro: Métro +        rail: Train +        trolleybus: Trolleybus +        tram: Tramway +        water: Eau +        cableway: Téléphérique +        funicular: Funiculaire +        other: Autre + +    line: +      transport_mode: +        interchange: Interconnection +        unknown: Inconnu +        air: Air +        train: Train +        long_distance_train: Train Grande Ligne +        local_train: TER +        rapid_transit: RER +        metro: Métro +        tramway: Tramway +        coach: Autocar +        bus: Bus +        ferry: Ferry +        waterborne: Bac +        private_vehicle: Voiture particulière +        walk: Marche à pied +        trolleybus: Trolleybus +        bicycle: Vélo +        shuttle: Navette +        taxi: Taxi +        val: VAL +        other: Autre +        bus: Bus +        coach: Autocar +        ferry: Ferry +        metro: Métro +        rail: Train +        trolleybus: Trolleybus +        tram: Tramway +        water: Eau +        cableway: Téléphérique +        funicular: Funiculaire +        other: Autre + +      transport_submode: +        unknown: 'Inconnu' +        undefined: 'Non défini' +        internationalFlight: 'Vol international' +        domesticFlight: 'Vol intérieur' +        intercontinentalFlight: 'Vol intercontinental' +        domesticScheduledFlight: 'Vol intérieur régulier' +        shuttleFlight: 'Vol de navette' +        intercontinentalCharterFlight: "Vol 'charter' intercontinental" +        internationalCharterFlight: "Vol 'charter' international" +        roundTripCharterFlight: "Vol 'charter' aller/retour" +        sightseeingFlight: 'Vol tourisme' +        helicopterService: "Service d'hélicoptère" +        domesticCharterFlight: "Vol 'charter' intérieur" +        SchengenAreaFlight: 'Vol de zone Shengen' +        airshipService: 'Service de dirigeable' +        shortHaulInternationalFlight: 'Vol international à courte distance' +        canalBarge: 'Péniche' +        localBus: 'Bus local' +        regionalBus: 'Bus régional' +        expressBus: 'Bus express' +        nightBus: 'Bus de nuit' +        postBus: 'Bus postal' +        specialNeedsBus: 'Bus de besoins spécial' +        mobilityBus: 'Bus de mobilité' +        mobilityBusForRegisteredDisabled: 'Bus de mobilité pour personnes handicapées' +        sightseeingBus: 'Bus touristique' +        shuttleBus: 'Bus navette' +        highFrequencyBus: 'Bus à haute fréquence' +        dedicatedLaneBus: 'Bus à voie réservée' +        schoolBus: 'Bus scolaire' +        schoolAndPublicServiceBus: 'Bus scolaire/service public' +        railReplacementBus: 'Bus de remplacement de train' +        demandAndResponseBus: 'Bus demande/réponse' +        airportLinkBus: 'Bus de liaison aéroport' +        internationalCoach: 'Autocar international' +        nationalCoach: 'Autocar national' +        shuttleCoach: 'Autocar navette' +        regionalCoach: 'Autocar régional' +        specialCoach: 'Autocar spécial' +        schoolCoach: 'Autocar scolaire' +        sightseeingCoach: 'Autocar touristique' +        touristCoach: 'Autocar touristique (2)' +        commuterCoach: 'Autocar de banlieue' +        metro: 'Métro' +        tube: 'Métro (2)' +        urbanRailway: 'Train urbain' +        local: 'Local' +        highSpeedRail: 'Train à grande vitesse' +        suburbanRailway: 'Train de banlieue' +        regionalRail: 'Train régional' +        interregionalRail: 'Train interrégional' +        longDistance: 'Longue distance' +        international: 'International' +        sleeperRailService: 'Train à couchettes' +        nightRail: 'Train de nuit' +        carTransportRailService: 'Service ferroviaire de transport de voitures' +        touristRailway: 'Train touristique' +        railShuttle: 'Navette ferroviaire' +        replacementRailService: 'Service de train de remplacement' +        specialTrain: 'Train spécial' +        crossCountryRail: 'Train de campagne' +        rackAndPinionRailway: 'Train à crémaillère' +        cityTram: 'Tramway de ville' +        localTram: 'Tramway local' +        regionalTram: 'Tramway régional' +        sightseeingTram: 'Tramway touristique' +        shuttleTram: 'Tramway navette' +        trainTram: 'Train/tramway' +        internationalCarFerry: 'Ferry international' +        nationalCarFerry: 'Ferry national' +        regionalCarFerry: 'Ferry régional' +        localCarFerry: 'Ferry local' +        internationalPassengerFerry: 'Traversier international à passagers' +        nationalPassengerFerry: 'Traversier national à passagers' +        regionalPassengerFerry: 'Traversier régional à passagers' +        localPassengerFerry: 'Traversier local à passagers' +        postBoat: 'Bateau de poste' +        trainFerry: 'Navire transbordeur' +        roadFerryLink: 'Liaison par navire transbordeur' +        airportBoatLink: "Liaison maritime d'aéroport" +        highSpeedVehicleService: 'Service de véhicule à grande vitesse' +        highSpeedPassengerService: 'Service passager à grande vitesse' +        sightseeingService: 'Service touristique' +        schoolBoat: 'Bateau scolaire' +        cableFerry: 'Traversier à câble' +        riverBus: 'Bateau-bus' +        scheduledFerry: 'Traversier régulier' +        shuttleFerryService: 'Service de traversier-navette' +        telecabin: 'Télécabine' +        cableCar: 'Téléphérique' +        lift: 'Ascenseur' +        chairLift: 'Télésiège' +        dragLift: 'Téléski' +        telecabinLink: 'Liaison télécabine' +        funicular: 'Funiculaire' +        streetCableCar: 'Tramway (2)' +        allFunicularServices: 'Tous services de funiculaire' +        undefinedFunicular: 'Funiculaire non défini' diff --git a/config/locales/line_referential_syncs.en.yml b/config/locales/line_referential_syncs.en.yml index 82ef48170..e78288299 100644 --- a/config/locales/line_referential_syncs.en.yml +++ b/config/locales/line_referential_syncs.en.yml @@ -10,8 +10,8 @@ en:      message:        new: "New synchronisation added"        pending: "Synchronisation en cours" -      successful: "Synchronisation réussie après %{processing_time} secondes avec %{imported} éléments importés. %{deleted} éléments ont été supprimés." -      failed: "Synchronisation interrompue après %{processing_time} secondes avec l'erreur : %{error}." +      successful: "Synchronization successful after %{processing_time} with %{imported} objects created, %{updated} objects updated. %{deleted} objects were deleted.." +      failed: "Synchronization failed after %{processing_time} with error: %{error}."    notice:      line_referential_sync: diff --git a/config/locales/line_referential_syncs.fr.yml b/config/locales/line_referential_syncs.fr.yml index 48b5df190..4a24fd937 100644 --- a/config/locales/line_referential_syncs.fr.yml +++ b/config/locales/line_referential_syncs.fr.yml @@ -10,7 +10,7 @@ fr:      message:        new: "Synchronisation en attente"        pending: "Synchronisation en cours" -      successful: "Synchronisation réussie après %{processing_time}, avec %{imported} éléments importés. %{deleted} éléments ont été supprimés." +      successful: "Synchronisation réussie après %{processing_time}, avec %{imported} éléments importés, %{updated} éléments mise à jour. %{deleted} éléments ont été supprimés."        failed: "Synchronisation interrompue après %{processing_time}, avec l'erreur : %{error}."    notice:      line_referential_sync: diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml index 4bc485180..51ea2a176 100644 --- a/config/locales/lines.en.yml +++ b/config/locales/lines.en.yml @@ -23,13 +23,15 @@ en:        deactivated: "Disabled line"        title: "Lines"        name_or_number: "Search by name or number..." -      name_or_number_or_objectid: "Search by name, number or objectid..." +      name_or_number_or_objectid_or_comment: "Search by name, number, objectid or comment..."        no_networks: "No networks"        no_companies: "No companies"        no_group_of_lines: "No group of lines" +      no_transport_modes: No transport mode        all_networks: "All networks"        all_companies: "All companies"        all_group_of_lines: "All group of lines" +      all_transport_modes: All transport modes        multi_selection: "Multiple selection"        multi_selection_enable: "Enable multiple selection"        multi_selection_disable: "Disable multiple selection" @@ -59,6 +61,7 @@ en:          published_name: "Published name"          number: "Number"          transport_mode: "Transport mode" +        transport_submode: "Transport Submode"          url: "Web page"          color: "Line color"          text_color: "Text color" diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml index 9e749f038..0ac9e676e 100644 --- a/config/locales/lines.fr.yml +++ b/config/locales/lines.fr.yml @@ -23,13 +23,15 @@ fr:        deactivated: "Ligne désactivée"        title: "Lignes"        name_or_number: "Recherche par nom ou indice..." -      name_or_number_or_objectid: "Recherche par nom, indice ou objectid..." +      name_or_number_or_objectid_or_comment: "Recherche par nom, indice, objectid ou commentaire..."        no_networks: "Aucun réseaux"        no_companies: "Aucun transporteurs"        no_group_of_lines: "Aucun groupes de ligne" +      no_transport_modes: Aucun mode de transport        all_networks: "Tous les réseaux"        all_companies: "Tous les transporteurs"        all_group_of_lines: "Tous les groupes de ligne" +      all_transport_modes: Tous les modes de transport        multi_selection: "Sélection multiple"        multi_selection_enable: "Activer la sélection multiple"        multi_selection_disable: "Désactiver la sélection multiple" @@ -59,6 +61,7 @@ fr:          published_name: "Nom public"          number: "Indice"          transport_mode: "Mode de transport" +        transport_submode: "Sous mode de transport"          url: "Page web associée"          color: "Couleur du tracé"          text_color: "Couleur du texte" diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml index 3691a8227..3af12e7f4 100644 --- a/config/locales/referentials.en.yml +++ b/config/locales/referentials.en.yml @@ -24,6 +24,7 @@ en:        destroy_confirm: "Do you confirm to destroy this data space ?"        destroy: "Destroy this data space"        edit: "Edit this data space" +      clone: "Clone this data space"      errors:        pg_excluded: "can't begins with pg_"        public_excluded: "public is a reserved value" @@ -78,7 +79,16 @@ en:          upper_corner: "latitude,longitude in WGS84 referential, dot for decimal separator"          lower_corner: "latitude,longitude in WGS84 referential, dot for decimal separator" +  simple_form: +    labels: +      referential: +        metadatas: +          first_period_begin: 'First period begin' +          first_period_end: 'First period end' +          lines: Lines +    notice:      referential:        archived: "The data space has been successfully archived" -      unarchived: "The data space has been successfully unarchived"
\ No newline at end of file +      unarchived: "The data space has been successfully unarchived" +      deleted: "The data space has been successfully destroyed" diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml index cada9c3a0..8c512a676 100644 --- a/config/locales/referentials.fr.yml +++ b/config/locales/referentials.fr.yml @@ -24,10 +24,12 @@ fr:        destroy_confirm: "Etes vous sûr de vouloir supprimer cet espace de données ?"        destroy: "Supprimer cet espace de données"        edit: "Modifier cet espace de données" +      clone: "Cloner cet espace de données"      errors:        pg_excluded: "ne peut pas commencer par pg_ (valeurs réservées)"        public_excluded: "public est une valeur réservée"        user_excluded: "%{user} est une valeur réservée" +      overlapped_referential: "%{referential} couvre le même périmètre d'offre"    activerecord:      models:        referential: @@ -78,7 +80,17 @@ fr:          upper_corner: "latitude,longitude dans le référentiel WGS84, le séparateur de décimales est 'point'"          lower_corner: "latitude,longitude dans le référentiel WGS84, le séparateur de décimales est 'point'" +  simple_form: +    labels: +      referential: +        metadatas: +          first_period_begin: 'Première période de départ' +          first_period_end: 'Première période de fin' +          lines: Lignes +    notice:      referential:        archived: "L'espace de données a été correctement archivé"        unarchived: "L'espace de données a été correctement désarchivé" +      unarchived_failed: "L'espace de données ne peut être désarchivé" +      deleted: "L'espace de données a été correctement supprimé" diff --git a/config/locales/routes.en.yml b/config/locales/routes.en.yml index a3a26cb8c..073294884 100644 --- a/config/locales/routes.en.yml +++ b/config/locales/routes.en.yml @@ -18,8 +18,8 @@ en:        title: "Update route %{route}"      show:        title: "Route %{route}" -      stop_points: "Stop point on route list"  -      journey_patterns: "Route journey patterns list"  +      stop_points: "Stop point on route list" +      journey_patterns: "Route journey patterns list"        no_opposite_route: "No reversed route associated"        undefined: "Undefined"      index: @@ -33,37 +33,37 @@ en:        for_alighting: "Alighting"      route:        no_journey_pattern: "No Journey pattern" -      wayback:  +      wayback:          positive: "forward"          negative: "backward"        opposite: "Opposite route"        no_opposite: "No opposite route" -  activerecord:         -    models:         -      route:  +  activerecord: +    models: +      route:          zero:  "route"          one:   "route"          other: "routes"      attributes:        route: -        wayback:  +        wayback:            positive: "forward"            negative: "backward"          line: "Line"          vehicle_journeys: "Vehicle journeys"          journey_patterns: "Journey patterns"          name: "Name" -        published_name: "Published name"         +        published_name: "Published name"          comment: "Comments"          number: "Number" -        direction_code: "Direction" -        wayback_code: "Wayback" +        direction: "Direction" +        wayback: "Wayback"          opposite_route: "Reversed route"          objectid: "Neptune identifier"          object_version: "Version"          creation_time: "Created on"          creator_id: "Created by" -        no_journey_pattern: "No journey pattern"         +        no_journey_pattern: "No journey pattern"    formtastic:      titles:        route: @@ -80,3 +80,9 @@ en:        hub:          route:            objectid: "[prefix]:Route:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character. Maximum length of the unique key = 8." + +  # simpleform +  helpers: +    submit: +      route: +        create: 'Create route' diff --git a/config/locales/routes.fr.yml b/config/locales/routes.fr.yml index ea190e6e2..183531236 100644 --- a/config/locales/routes.fr.yml +++ b/config/locales/routes.fr.yml @@ -1,29 +1,29 @@  fr:    routes:      actions: -      new: "Ajouter une séquence d'arrêts" -      edit: "Modifier cette séquence d'arrêts" +      new: "Ajouter un itinéraire" +      edit: "Modifier cet itinéraire"        edit_boarding_alighting: "Contraintes de montée - descente" -      destroy: "Supprimer cette séquence d'arrêts" -      destroy_confirm: "Etes vous sûr de supprimer cette séquence d'arrêts ?" -      export_kml: "Export KML de la séquence d'arrêts" -      export_kml_all: "Export KML des séquences d'arrêts" -      export_hub: "Export HUB de la séquence d'arrêts" -      export_hub_all: "Export HUB des séquences d'arrêts" +      destroy: "Supprimer cet itinéraire" +      destroy_confirm: "Etes vous sûr de supprimer cet itinéraire ?" +      export_kml: "Export KML de l'itinéraire" +      export_kml_all: "Export KML des itinéraires" +      export_hub: "Export HUB de l'itinéraire" +      export_hub_all: "Export HUB des itinéraires"        add_stop_point: "Ajouter un arrêt"        new_stop_point: "Créer un arrêt pour l'ajouter"      new: -      title: "Ajouter une séquence d'arrêts" +      title: "Ajouter un itinéraire"      edit: -      title: "Modifier la séquence d'arrêts %{route}" +      title: "Modifier l'itinéraire %{route}"      show: -      title: "Séquence d'arrêts %{route} de la ligne %{line}" -      stop_points: "Liste des arrêts de la séquence d'arrêts" +      title: "Itinéraire %{route} de la ligne %{line}" +      stop_points: "Liste des arrêts de l'itinéraire'"        journey_patterns: "Liste des missions" -      no_opposite_route: "Aucune séquence d'arrêts associée en sens opposé" +      no_opposite_route: "Aucun itinéraire associé en sens opposé"        undefined: "Non défini"      index: -      title: "Séquences d'arrêts" +      title: "Itinéraires"        selection: "Sélection"        selection_all: "Tous"      edit_boarding_alighting: @@ -36,14 +36,14 @@ fr:        wayback:          positive: "Aller"          negative: "Retour" -      opposite: "Séquence opposée" -      no_opposite: "Pas de séquence opposée" +      opposite: "Itinéraire opposé" +      no_opposite: "Pas d'itinéraire opposé"    activerecord:      models:        route: -        zero:  "séquence d'arrêts" -        one:   "séquence d'arrêts" -        other: "séquences d'arrêts" +        zero:  "itinéraire" +        one:   "itinéraire" +        other: "itinéraires"      attributes:        route:          wayback: @@ -56,9 +56,10 @@ fr:          published_name: "Nom public"          number: "Indice"          comment: "Commentaire" -        direction_code: "Direction" -        wayback_code: "Sens" -        opposite_route: "Séquence d'arrêts associée en sens opposé" +        direction: "Direction" +        wayback: "Sens" +        opposite_route: "Itinéraire associé en sens opposé" +        opposite_route_id: "Itinéraire associé en sens opposé"          objectid: "Identifiant Neptune"          object_version: "Version"          creation_time: "Créé le" @@ -80,3 +81,9 @@ fr:        hub:          route:            objectid: "[prefixe]:Route:[clé_unique]  caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'. Longueur maximale de la clé unique = 8." + +  # simpleform +  helpers: +    submit: +      route: +        create: 'Créer un itinéraire' diff --git a/config/locales/stop_area_referential_syncs.en.yml b/config/locales/stop_area_referential_syncs.en.yml index 9dc3173bc..8b3a5e8c3 100644 --- a/config/locales/stop_area_referential_syncs.en.yml +++ b/config/locales/stop_area_referential_syncs.en.yml @@ -7,13 +7,11 @@ en:              base:                multiple_process: 'There is already an synchronisation in progress'    stop_area_referential_sync: -    synchronization: -      message: -        new: "New synchronisation added" -        pending: "Synchronization pending" -        successful: "Synchronization successful after %{processing_time} with %{imported} objects. %{deleted} objects were deleted.." -        failed: "Synchronization failed after %{processing_time} with error: %{error}." +    message: +      new: "New synchronisation added" +      pending: "Synchronization pending" +      successful: "Synchronization successful after %{processing_time} with %{imported} objects created, %{updated} objects updated. %{deleted} objects were deleted.." +      failed: "Synchronization failed after %{processing_time} with error: %{error}."    notice:      stop_area_referential_sync:        created: 'Your synchronisation request has been created' - diff --git a/config/locales/stop_area_referential_syncs.fr.yml b/config/locales/stop_area_referential_syncs.fr.yml index d0b79a8db..bf8d32ac5 100644 --- a/config/locales/stop_area_referential_syncs.fr.yml +++ b/config/locales/stop_area_referential_syncs.fr.yml @@ -10,7 +10,7 @@ fr:      message:        new: "Synchronisation en attente"        pending: "Synchronisation en cours" -      successful: "Synchronisation réussie après %{processing_time}, avec %{imported} éléments importés. %{deleted} éléments ont été supprimés." +      successful: "Synchronisation réussie après %{processing_time}, avec %{imported} éléments importés, %{updated} éléments mise à jour. %{deleted} éléments ont été supprimés."        failed: "Synchronisation interrompue après %{processing_time}, avec l'erreur : %{error}."    notice:      stop_area_referential_sync: diff --git a/config/locales/vehicle_journeys.en.yml b/config/locales/vehicle_journeys.en.yml index 0687c32aa..abaa85d29 100644 --- a/config/locales/vehicle_journeys.en.yml +++ b/config/locales/vehicle_journeys.en.yml @@ -1,7 +1,7 @@  en:    vehicle_journeys:      vehicle_journeys_matrix: -      line_routes: "Line's routes"       +      line_routes: "Line's routes"      vehicle_journey:        title_stopless: "Vehicle journey %{name}"        title: "Vehicle journey leaving from %{stop} at %{time}" @@ -84,7 +84,7 @@ en:          number: "Number"          comment: "Comments"          status_value: "Status Value" -        transport_mode_name: "Transport Mode" +        transport_mode: "Transport Mode"          mobility_restricted_suitability: "PRM accessibility"          flexible_service: "On demond transportation"          unspecified_mrs: "Not specified" diff --git a/config/locales/vehicle_journeys.fr.yml b/config/locales/vehicle_journeys.fr.yml index 30a4bf081..5cd1b3087 100644 --- a/config/locales/vehicle_journeys.fr.yml +++ b/config/locales/vehicle_journeys.fr.yml @@ -84,7 +84,7 @@ fr:          number: "Numéro"          comment: "Commentaires"          status_value: "Etat de trafic" -        transport_mode_name: "Mode de transport" +        transport_mode: "Mode de transport"          mobility_restricted_suitability: "Accessibilité PMR"          flexible_service: "Transport à la demande"          unspecified_mrs: "Non spécifié" diff --git a/config/routes.rb b/config/routes.rb index 4b4411ea5..74e4b47b5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,6 +23,8 @@ ChouetteIhm::Application.routes.draw do      end    end +  mount Sidekiq::Web => '/sidekiq' +    namespace :api do      namespace :v1 do        resources :time_tables, :only => [:index, :show] diff --git a/db/migrate/20120516172252_create_delayed_jobs.rb b/db/migrate/20120516172252_create_delayed_jobs.rb deleted file mode 100644 index e7841608c..000000000 --- a/db/migrate/20120516172252_create_delayed_jobs.rb +++ /dev/null @@ -1,22 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration -  def self.up -    create_table :delayed_jobs, :force => true do |table| -      table.integer  :priority, :default => 0      # Allows some jobs to jump to the front of the queue -      table.integer  :attempts, :default => 0      # Provides for retries, but still fail eventually. -      table.text     :handler                      # YAML-encoded string of the object that will do work -      table.text     :last_error                   # reason for last failure (See Note below) -      table.datetime :run_at                       # When to run. Could be Time.zone.now for immediately, or sometime in the future. -      table.datetime :locked_at                    # Set when a client is working on this object -      table.datetime :failed_at                    # Set when all retries have failed (actually, by default, the record is deleted instead) -      table.string   :locked_by                    # Who is working on this object (if locked) -      table.string   :queue                        # The name of the queue this job is in -      table.timestamps -    end - -    add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority' -  end - -  def self.down -    drop_table :delayed_jobs -  end -end diff --git a/db/migrate/20161017091304_add_sso_attributes_to_organisations.rb b/db/migrate/20161017091304_add_sso_attributes_to_organisations.rb new file mode 100644 index 000000000..608e78ef6 --- /dev/null +++ b/db/migrate/20161017091304_add_sso_attributes_to_organisations.rb @@ -0,0 +1,5 @@ +class AddSsoAttributesToOrganisations < ActiveRecord::Migration +  def change +    add_column :organisations, :sso_attributes, :hstore +  end +end diff --git a/db/migrate/20161018121633_add_line_referential_to_workbenches.rb b/db/migrate/20161018121633_add_line_referential_to_workbenches.rb new file mode 100644 index 000000000..2cffc4c1a --- /dev/null +++ b/db/migrate/20161018121633_add_line_referential_to_workbenches.rb @@ -0,0 +1,5 @@ +class AddLineReferentialToWorkbenches < ActiveRecord::Migration +  def change +    add_reference :workbenches, :line_referential, index: true +  end +end diff --git a/db/migrate/20161018121647_add_stop_area_referential_to_workbenches.rb b/db/migrate/20161018121647_add_stop_area_referential_to_workbenches.rb new file mode 100644 index 000000000..5c368dd57 --- /dev/null +++ b/db/migrate/20161018121647_add_stop_area_referential_to_workbenches.rb @@ -0,0 +1,5 @@ +class AddStopAreaReferentialToWorkbenches < ActiveRecord::Migration +  def change +    add_reference :workbenches, :stop_area_referential, index: true +  end +end diff --git a/db/migrate/20161019090255_create_referential_metadata.rb b/db/migrate/20161019090255_create_referential_metadata.rb new file mode 100644 index 000000000..d862e2df0 --- /dev/null +++ b/db/migrate/20161019090255_create_referential_metadata.rb @@ -0,0 +1,13 @@ +class CreateReferentialMetadata < ActiveRecord::Migration +  def change +    create_table :referential_metadata do |t| +      t.references :referential, index: true +      t.daterange :periode +      t.integer :line_ids, array: true +      t.index :line_ids, using: :gin +      t.references :referential_source, index: true + +      t.timestamps +    end +  end +end diff --git a/db/migrate/20161020093344_change_periode_from_referential_metadata.rb b/db/migrate/20161020093344_change_periode_from_referential_metadata.rb new file mode 100644 index 000000000..b39d17190 --- /dev/null +++ b/db/migrate/20161020093344_change_periode_from_referential_metadata.rb @@ -0,0 +1,12 @@ +class ChangePeriodeFromReferentialMetadata < ActiveRecord::Migration +  def up +    if column_exists? :referential_metadata, :periode +      remove_column :referential_metadata, :periode, :daterange +    end +    add_column :referential_metadata, :periodes, :daterange, array: true +  end + +  def down +    remove_column :referential_metadata, :periodes, :daterange +  end +end diff --git a/db/migrate/20161024123819_add_created_from_to_referentials.rb b/db/migrate/20161024123819_add_created_from_to_referentials.rb new file mode 100644 index 000000000..a125a0c21 --- /dev/null +++ b/db/migrate/20161024123819_add_created_from_to_referentials.rb @@ -0,0 +1,5 @@ +class AddCreatedFromToReferentials < ActiveRecord::Migration +  def change +    add_reference :referentials, :created_from, index: true +  end +end diff --git a/db/migrate/20161024135931_create_referential_clonings.rb b/db/migrate/20161024135931_create_referential_clonings.rb new file mode 100644 index 000000000..d82f30bb1 --- /dev/null +++ b/db/migrate/20161024135931_create_referential_clonings.rb @@ -0,0 +1,13 @@ +class CreateReferentialClonings < ActiveRecord::Migration +  def change +    create_table :referential_clonings do |t| +      t.string :status +      t.datetime :started_at +      t.datetime :ended_at +      t.references :source_referential, index: true +      t.references :target_referential, index: true + +      t.timestamps +    end +  end +end diff --git a/db/migrate/20161109160857_add_organisation_code_index.rb b/db/migrate/20161109160857_add_organisation_code_index.rb new file mode 100644 index 000000000..89d9e67c2 --- /dev/null +++ b/db/migrate/20161109160857_add_organisation_code_index.rb @@ -0,0 +1,5 @@ +class AddOrganisationCodeIndex < ActiveRecord::Migration +  def change +    add_index :organisations, :code, unique: true +  end +end diff --git a/db/migrate/20161114134518_create_clean_ups.rb b/db/migrate/20161114134518_create_clean_ups.rb new file mode 100644 index 000000000..3fa60d484 --- /dev/null +++ b/db/migrate/20161114134518_create_clean_ups.rb @@ -0,0 +1,18 @@ +class CreateCleanUps < ActiveRecord::Migration +  def change +    create_table :clean_ups do |t| +      t.string :status +      t.datetime :started_at +      t.datetime :ended_at +      t.references :referential, index: true +      t.boolean :keep_lines +      t.boolean :keep_stops +      t.boolean :keep_companies +      t.boolean :keep_networks +      t.boolean :keep_group_of_lines +      t.datetime :expected_date + +      t.timestamps +    end +  end +end diff --git a/db/migrate/20161115141458_remove_keep_lines_from_clean_ups.rb b/db/migrate/20161115141458_remove_keep_lines_from_clean_ups.rb new file mode 100644 index 000000000..08337a72a --- /dev/null +++ b/db/migrate/20161115141458_remove_keep_lines_from_clean_ups.rb @@ -0,0 +1,5 @@ +class RemoveKeepLinesFromCleanUps < ActiveRecord::Migration +  def change +    remove_column :clean_ups, :keep_lines, :boolean +  end +end diff --git a/db/migrate/20161115141525_remove_keep_stops_from_clean_ups.rb b/db/migrate/20161115141525_remove_keep_stops_from_clean_ups.rb new file mode 100644 index 000000000..8a322d43f --- /dev/null +++ b/db/migrate/20161115141525_remove_keep_stops_from_clean_ups.rb @@ -0,0 +1,5 @@ +class RemoveKeepStopsFromCleanUps < ActiveRecord::Migration +  def change +    remove_column :clean_ups, :keep_stops, :boolean +  end +end diff --git a/db/migrate/20161115141541_remove_keep_companies_from_clean_ups.rb b/db/migrate/20161115141541_remove_keep_companies_from_clean_ups.rb new file mode 100644 index 000000000..3a9865071 --- /dev/null +++ b/db/migrate/20161115141541_remove_keep_companies_from_clean_ups.rb @@ -0,0 +1,5 @@ +class RemoveKeepCompaniesFromCleanUps < ActiveRecord::Migration +  def change +    remove_column :clean_ups, :keep_companies, :boolean +  end +end diff --git a/db/migrate/20161115141559_remove_keep_networks_from_clean_ups.rb b/db/migrate/20161115141559_remove_keep_networks_from_clean_ups.rb new file mode 100644 index 000000000..9f88d0edd --- /dev/null +++ b/db/migrate/20161115141559_remove_keep_networks_from_clean_ups.rb @@ -0,0 +1,5 @@ +class RemoveKeepNetworksFromCleanUps < ActiveRecord::Migration +  def change +    remove_column :clean_ups, :keep_networks, :boolean +  end +end diff --git a/db/migrate/20161115141625_remove_keep_group_of_lines_from_clean_ups.rb b/db/migrate/20161115141625_remove_keep_group_of_lines_from_clean_ups.rb new file mode 100644 index 000000000..b188ff194 --- /dev/null +++ b/db/migrate/20161115141625_remove_keep_group_of_lines_from_clean_ups.rb @@ -0,0 +1,5 @@ +class RemoveKeepGroupOfLinesFromCleanUps < ActiveRecord::Migration +  def change +    remove_column :clean_ups, :keep_group_of_lines, :boolean +  end +end diff --git a/db/migrate/20161115142708_create_clean_up_results.rb b/db/migrate/20161115142708_create_clean_up_results.rb new file mode 100644 index 000000000..689fb1268 --- /dev/null +++ b/db/migrate/20161115142708_create_clean_up_results.rb @@ -0,0 +1,10 @@ +class CreateCleanUpResults < ActiveRecord::Migration +  def change +    create_table :clean_up_results do |t| +      t.string :message_key +      t.hstore :message_attributs +      t.references :clean_up, index: true +      t.timestamps +    end +  end +end diff --git a/db/migrate/20161116130746_rename_columnexpected_date_from_cleanups.rb b/db/migrate/20161116130746_rename_columnexpected_date_from_cleanups.rb new file mode 100644 index 000000000..a5fa2577d --- /dev/null +++ b/db/migrate/20161116130746_rename_columnexpected_date_from_cleanups.rb @@ -0,0 +1,9 @@ +class RenameColumnexpectedDateFromCleanups < ActiveRecord::Migration +  def up +    rename_column :clean_ups, :expected_date, :begin_date +  end + +  def down +    rename_column :clean_ups, :begin_date, :expected_date +  end +end diff --git a/db/migrate/20161116130958_add_end_date_to_clean_ups.rb b/db/migrate/20161116130958_add_end_date_to_clean_ups.rb new file mode 100644 index 000000000..b1c1f7226 --- /dev/null +++ b/db/migrate/20161116130958_add_end_date_to_clean_ups.rb @@ -0,0 +1,5 @@ +class AddEndDateToCleanUps < ActiveRecord::Migration +  def change +    add_column :clean_ups, :end_date, :datetime +  end +end diff --git a/db/migrate/20161117104301_add_transport_submode_to_lines.rb b/db/migrate/20161117104301_add_transport_submode_to_lines.rb new file mode 100644 index 000000000..e652dc190 --- /dev/null +++ b/db/migrate/20161117104301_add_transport_submode_to_lines.rb @@ -0,0 +1,5 @@ +class AddTransportSubmodeToLines < ActiveRecord::Migration +  def change +    add_column :lines, :transport_submode, :string +  end +end diff --git a/db/migrate/20161118101544_rename_transport_mode_name.rb b/db/migrate/20161118101544_rename_transport_mode_name.rb new file mode 100644 index 000000000..60fa62754 --- /dev/null +++ b/db/migrate/20161118101544_rename_transport_mode_name.rb @@ -0,0 +1,5 @@ +class RenameTransportModeName < ActiveRecord::Migration +  def change +    rename_column :lines, :transport_mode_name, :transport_mode +  end +end diff --git a/db/schema.rb b/db/schema.rb index e8a0c8c7a..e97ba8e52 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@  #  # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161010135256) do +ActiveRecord::Schema.define(version: 20161118101544) do    # These are extensions that must be enabled in order to support this database    enable_extension "plpgsql" @@ -77,6 +77,29 @@ ActiveRecord::Schema.define(version: 20161010135256) do      t.datetime "updated_at"    end +  create_table "clean_up_results", force: true do |t| +    t.string   "message_key" +    t.hstore   "message_attributs" +    t.integer  "clean_up_id" +    t.datetime "created_at" +    t.datetime "updated_at" +  end + +  add_index "clean_up_results", ["clean_up_id"], :name => "index_clean_up_results_on_clean_up_id" + +  create_table "clean_ups", force: true do |t| +    t.string   "status" +    t.datetime "started_at" +    t.datetime "ended_at" +    t.integer  "referential_id" +    t.datetime "begin_date" +    t.datetime "created_at" +    t.datetime "updated_at" +    t.datetime "end_date" +  end + +  add_index "clean_ups", ["referential_id"], :name => "index_clean_ups_on_referential_id" +    create_table "companies", force: true do |t|      t.string   "objectid",                  null: false      t.integer  "object_version" @@ -124,22 +147,6 @@ ActiveRecord::Schema.define(version: 20161010135256) do    add_index "connection_links", ["objectid"], :name => "connection_links_objectid_key", :unique => true -  create_table "delayed_jobs", force: true do |t| -    t.integer  "priority",   default: 0 -    t.integer  "attempts",   default: 0 -    t.text     "handler" -    t.text     "last_error" -    t.datetime "run_at" -    t.datetime "locked_at" -    t.datetime "failed_at" -    t.string   "locked_by" -    t.string   "queue" -    t.datetime "created_at" -    t.datetime "updated_at" -  end - -  add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" -    create_table "exports", force: true do |t|      t.integer  "referential_id",  limit: 8      t.string   "status" @@ -312,7 +319,7 @@ ActiveRecord::Schema.define(version: 20161010135256) do      t.string   "name"      t.string   "number"      t.string   "published_name" -    t.string   "transport_mode_name" +    t.string   "transport_mode"      t.string   "registration_number"      t.string   "comment"      t.boolean  "mobility_restricted_suitability" @@ -325,6 +332,7 @@ ActiveRecord::Schema.define(version: 20161010135256) do      t.integer  "line_referential_id"      t.boolean  "deactivated",                               default: false      t.text     "import_xml" +    t.string   "transport_submode"    end    add_index "lines", ["line_referential_id"], :name => "index_lines_on_line_referential_id" @@ -356,11 +364,14 @@ ActiveRecord::Schema.define(version: 20161010135256) do      t.string   "name"      t.datetime "created_at"      t.datetime "updated_at" -    t.string   "data_format", default: "neptune" +    t.string   "data_format",    default: "neptune"      t.string   "code"      t.datetime "synced_at" +    t.hstore   "sso_attributes"    end +  add_index "organisations", ["code"], :name => "index_organisations_on_code", :unique => true +    create_table "pt_links", force: true do |t|      t.integer  "start_of_link_id", limit: 8      t.integer  "end_of_link_id",   limit: 8 @@ -376,6 +387,32 @@ ActiveRecord::Schema.define(version: 20161010135256) do    add_index "pt_links", ["objectid"], :name => "pt_links_objectid_key", :unique => true +  create_table "referential_clonings", force: true do |t| +    t.string   "status" +    t.datetime "started_at" +    t.datetime "ended_at" +    t.integer  "source_referential_id" +    t.integer  "target_referential_id" +    t.datetime "created_at" +    t.datetime "updated_at" +  end + +  add_index "referential_clonings", ["source_referential_id"], :name => "index_referential_clonings_on_source_referential_id" +  add_index "referential_clonings", ["target_referential_id"], :name => "index_referential_clonings_on_target_referential_id" + +  create_table "referential_metadata", force: true do |t| +    t.integer   "referential_id" +    t.integer   "line_ids",              array: true +    t.integer   "referential_source_id" +    t.datetime  "created_at" +    t.datetime  "updated_at" +    t.daterange "periodes",              array: true +  end + +  add_index "referential_metadata", ["line_ids"], :name => "index_referential_metadata_on_line_ids" +  add_index "referential_metadata", ["referential_id"], :name => "index_referential_metadata_on_referential_id" +  add_index "referential_metadata", ["referential_source_id"], :name => "index_referential_metadata_on_referential_source_id" +    create_table "referentials", force: true do |t|      t.string   "name"      t.string   "slug" @@ -394,8 +431,11 @@ ActiveRecord::Schema.define(version: 20161010135256) do      t.integer  "stop_area_referential_id"      t.integer  "workbench_id"      t.datetime "archived_at" +    t.integer  "created_from_id"    end +  add_index "referentials", ["created_from_id"], :name => "index_referentials_on_created_from_id" +    create_table "route_sections", force: true do |t|      t.integer  "departure_id",       limit: 8      t.integer  "arrival_id",         limit: 8 @@ -682,13 +722,15 @@ ActiveRecord::Schema.define(version: 20161010135256) do      t.integer  "organisation_id"      t.datetime "created_at"      t.datetime "updated_at" +    t.integer  "line_referential_id" +    t.integer  "stop_area_referential_id"    end +  add_index "workbenches", ["line_referential_id"], :name => "index_workbenches_on_line_referential_id"    add_index "workbenches", ["organisation_id"], :name => "index_workbenches_on_organisation_id" +  add_index "workbenches", ["stop_area_referential_id"], :name => "index_workbenches_on_stop_area_referential_id"    Foreigner.load -  add_foreign_key "access_links", "access_points", name: "aclk_acpt_fkey", dependent: :delete -    add_foreign_key "group_of_lines_lines", "group_of_lines", name: "groupofline_group_fkey", dependent: :delete    add_foreign_key "journey_frequencies", "timebands", name: "journey_frequencies_timeband_id_fk", dependent: :nullify diff --git a/db/seeds.rb b/db/seeds.rb index dae717966..0d7748f9c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -17,7 +17,6 @@ stif.users.find_or_create_by!(username: "admin") do |user|    user.name = "STIF Administrateur"  end -Workbench.find_or_create_by(name: "Gestion de l'offre", organisation: stif)  operator = Organisation.find_or_create_by!(code: 'transporteur-a') do |organisation|    organisation.name = "Transporteur A" @@ -43,6 +42,12 @@ line_referential = LineReferential.find_or_create_by(name: "CodifLigne") do |ref    referential.add_member operator  end +Workbench.find_or_create_by(name: "Gestion de l'offre", organisation: stif) do |workbench| +  workbench.line_referential      = line_referential +  workbench.stop_area_referential = stop_area_referential +end + +  LineReferentialSync.find_or_create_by(line_referential: line_referential)  StopAreaReferentialSync.find_or_create_by(stop_area_referential: stop_area_referential) @@ -52,16 +57,16 @@ StopAreaReferentialSync.find_or_create_by(stop_area_referential: stop_area_refer    end  end - -workbench = Workbench.find_or_create_by(name: "Gestion de l'offre", organisation: operator) +workbench = Workbench.find_or_create_by(name: "Gestion de l'offre", organisation: operator) do |workbench| +  workbench.line_referential      = line_referential +  workbench.stop_area_referential = stop_area_referential +end  [["parissudest201604", "Paris Sud-Est Avril 2016"],   ["parissudest201605", "Paris Sud-Est Mai 2016"]].each do |slug, name|    operator.referentials.find_or_create_by!(slug: slug) do |referential| -    referential.name = name -    referential.prefix = slug +    referential.name      = name +    referential.prefix    = slug      referential.workbench = workbench -    referential.line_referential = line_referential -    referential.stop_area_referential = stop_area_referential    end  end diff --git a/lib/stif/codif_line_synchronization.rb b/lib/stif/codif_line_synchronization.rb index d580ae3b8..318d5427c 100644 --- a/lib/stif/codif_line_synchronization.rb +++ b/lib/stif/codif_line_synchronization.rb @@ -1,7 +1,28 @@  module Stif    module CodifLineSynchronization      class << self +      attr_accessor :imported_count, :updated_count, :deleted_count + +      def reset_counts +        self.imported_count = 0 +        self.updated_count  = 0 +        self.deleted_count  = 0 +      end + +      def processed_counts +        { +          imported: self.imported_count, +          updated: self.updated_count, +          deleted: self.deleted_count +        } +      end + +      def increment_counts prop_name, value +        self.send("#{prop_name}=", self.send(prop_name) + value) +      end +        def synchronize +        self.reset_counts          start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)          # Fetch Codifline data          client = Codifligne::API.new @@ -47,10 +68,8 @@ module Stif          # Delete deprecated Operators          deleted_op = delete_deprecated(operators, Chouette::Company)          log_deleted "Operators", deleted_op unless deleted_op == 0 -        { -          imported: operators.count + lines.count + networks.count, -          deleted: deleted_op + deleted_li + deleted_ne -        } + +        self.processed_counts        end        def create_or_update_company(api_operator) @@ -70,7 +89,8 @@ module Stif            deactivated: (api_line.status == "inactive" ? true : false),            import_xml: api_line.xml          } - +        params[:transport_mode] = api_line.transport_mode.to_s +        params[:transport_submode] = api_line.transport_submode.to_s          unless api_line.operator_ref.nil?            params[:company] = Chouette::Company.find_by(objectid: api_line.operator_ref)          end @@ -117,13 +137,14 @@ module Stif        def delete_deprecated(objects, klass)          ids = objects.map{ |o| o.stif_id }.to_a          deprecated = klass.where.not(objectid: ids) -        deprecated.destroy_all.length +        increment_counts :deleted_count, deprecated.destroy_all.length        end        def delete_deprecated_lines(lines)          ids = lines.map{ |l| l.stif_id }.to_a          deprecated = Chouette::Line.where.not(objectid: ids).where(deactivated: false)          deprecated.update_all deactivated: true +        increment_counts :deleted_count, deprecated.update_all(deactivated: true)        end        def save_or_update(params, klass) @@ -131,10 +152,16 @@ module Stif          object = klass.where(objectid: params[:objectid]).first          if object            object.assign_attributes(params) -          object.save if object.changed? +          if object.changed? +            object.save +            increment_counts :updated_count, 1 +          end          else            object = klass.new(params) -          object.save if object.valid? +          if object.valid? +            object.save +            increment_counts :imported_count, 1 +          end          end          object        end diff --git a/lib/stif/my_workbench_scopes.rb b/lib/stif/my_workbench_scopes.rb new file mode 100644 index 000000000..89c4e659c --- /dev/null +++ b/lib/stif/my_workbench_scopes.rb @@ -0,0 +1,23 @@ +module Stif +  class MyWorkbenchScopes +    attr_accessor :workbench + +    def initialize(workbench) +      @workbench = workbench +    end + +    def line_scope(initial_scope) +      ids = self.parse_functional_scope +      ids ? initial_scope.where(objectid: ids) : initial_scope +    end + +    def parse_functional_scope +      return false unless @workbench.organisation.sso_attributes +      begin +        JSON.parse @workbench.organisation.sso_attributes['functional_scope'] +      rescue Exception => e +        Rails.logger.error "MyWorkbenchScopes : #{e}" +      end +    end +  end +end diff --git a/lib/stif/reflex_synchronization.rb b/lib/stif/reflex_synchronization.rb index 822a295c0..bc3b9dd2d 100644 --- a/lib/stif/reflex_synchronization.rb +++ b/lib/stif/reflex_synchronization.rb @@ -1,6 +1,31 @@  module Stif    module ReflexSynchronization      class << self +      attr_accessor :imported_count, :updated_count, :deleted_count, :processed + +      def reset_counts +        self.imported_count = 0 +        self.updated_count  = 0 +        self.deleted_count  = 0 +        self.processed      = [] +      end + +      def processed_counts +        { +          imported: self.imported_count, +          updated: self.updated_count, +          deleted: self.deleted_count +        } +      end + +      def log_processing_time message, time +        Rails.logger.info "Reflex:sync - #{message} done in #{time} seconds" +      end + +      def increment_counts prop_name, value +        self.send("#{prop_name}=", self.send(prop_name) + value) +      end +        def defaut_referential          StopAreaReferential.find_by(name: "Reflex")        end @@ -10,41 +35,32 @@ module Stif        end        def synchronize -        tstart           = Time.now -        client           = Reflex::API.new -        processed        = [] -        initial_count    = Chouette::StopArea.where(deleted_at: nil).count - +        self.reset_counts          ['getOR', 'getOP'].each do |method|            start   = Time.now -          results = client.process method -          Rails.logger.info "Reflex:sync - Process #{method} done in #{Time.now - start} seconds" -          results.each do |type, entries| -            Rails.logger.info "Reflex:sync - #{entries.count} #{type} retrieved" -          end - -          # Create or update stop_area for every quay, stop_place +          results = Reflex::API.new().process(method) +          log_processing_time("Process #{method}", Time.now - start)            stop_areas = results[:Quay] | results[:StopPlace] -          start = Time.now -          stop_areas.each do |entry| -            next unless is_valid_type_of_place_ref?(method, entry) -            processed << entry['id'] -            self.create_or_update_stop_area entry +          time = Benchmark.measure do +            stop_areas.each do |entry| +              next unless is_valid_type_of_place_ref?(method, entry) +              self.processed << entry['id'] +              self.create_or_update_stop_area entry +            end            end -          Rails.logger.info "Reflex:sync - Create or update StopArea done in #{Time.now - start} seconds" +          log_processing_time("Create or update StopArea", time.real) -          # Walk through every entry and set parent stop_area -          start = Time.now -          stop_areas.each do |entry| -            self.stop_area_set_parent entry +          time = Benchmark.measure do +            stop_areas.map{|entry| self.stop_area_set_parent(entry)}            end -          Rails.logger.info "Reflex:sync - StopArea set parent done in #{Time.now - start} seconds" +          log_processing_time("StopArea set parent", time.real)          end -        { -          imported: Chouette::StopArea.where(deleted_at: nil).count - initial_count, -          deleted: self.set_deleted_stop_area(processed.uniq).size -        } + +        # Set deleted_at for item not returned by api since last sync +        time = Benchmark.measure { self.set_deleted_stop_area } +        log_processing_time("StopArea #{self.deleted_count} deleted", time.real) +        self.processed_counts        end        def is_valid_type_of_place_ref? method, entry @@ -53,14 +69,12 @@ module Stif          return true if method == 'getOP' && ['ZDE'].include?(entry["TypeOfPlaceRef"])        end -      def set_deleted_stop_area processed -        start   = Time.now -        deleted = Chouette::StopArea.where(deleted_at: nil).pluck(:objectid).uniq - processed +      def set_deleted_stop_area +        deleted = Chouette::StopArea.where(deleted_at: nil).pluck(:objectid).uniq - self.processed.uniq          deleted.each_slice(50) do |object_ids|            Chouette::StopArea.where(objectid: object_ids).update_all(deleted_at: Time.now)          end -        Rails.logger.info "Reflex:sync - StopArea #{deleted.size} stop_area deleted since last sync in #{Time.now - start} seconds" -        deleted +        increment_counts :deleted_count, deleted.size        end        def stop_area_set_parent entry @@ -122,7 +136,9 @@ module Stif          if stop.changed?            stop.creation_time = entry[:created] -          stop.import_xml = entry[:xml] +          stop.import_xml    = entry[:xml] +          prop = stop.new_record? ? :imported_count : :updated_count +          increment_counts prop, 1            stop.save!          end          # Create AccessPoint from StopPlaceEntrance diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index 7fca878b6..2b584c08b 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -3,6 +3,7 @@ namespace :ci do    task :setup do      cp "config/database/jenkins.yml", "config/database.yml"      sh "RAILS_ENV=test rake db:migrate" +    sh "npm install"    end    def git_branch diff --git a/package.json b/package.json new file mode 100644 index 000000000..43f8c4c6a --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ +  "name": "something", +  "dependencies": { +    "babel-polyfill": "6.16.0", +    "babel-preset-es2015": "6.18.0", +    "babel-preset-react": "6.16.0", +    "babelify": "7.3.0", +    "browserify": "13.1.1", +    "browserify-incremental": "3.1.1", +    "react": "15.3.2", +    "react-dom": "15.3.2", +    "react-redux": "4.4.5", +    "react-select2": "4.0.2", +    "redux": "3.6.0" +  }, +  "license": "MIT", +  "engines": { +    "node": ">= 0.10" +  } +} diff --git a/script/delayed_job b/script/delayed_job deleted file mode 100755 index edf195985..000000000 --- a/script/delayed_job +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env ruby - -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) -require 'delayed/command' -Delayed::Command.new(ARGV).daemonize diff --git a/spec/factories/chouette_2_factories.rb b/spec/factories/chouette_2_factories.rb index b88b0d773..e8eba13e6 100644 --- a/spec/factories/chouette_2_factories.rb +++ b/spec/factories/chouette_2_factories.rb @@ -10,7 +10,9 @@ FactoryGirl.define do      sequence(:slug) { |n| "test_#{n}" }      sequence(:prefix) { |n| "test_#{n}" }      association :organisation - +    association :workbench +    association :line_referential +    association :stop_area_referential      time_zone "Europe/Paris"    end diff --git a/spec/factories/chouette_lines.rb b/spec/factories/chouette_lines.rb index da79f8c98..e5be80b10 100644 --- a/spec/factories/chouette_lines.rb +++ b/spec/factories/chouette_lines.rb @@ -3,7 +3,7 @@ FactoryGirl.define do    factory :line, :class => Chouette::Line do      sequence(:name) { |n| "Line #{n}" }      sequence(:objectid) { |n| "chouette:test:Line:#{n}" } -    sequence(:transport_mode_name) { |n| "Bus" } +    sequence(:transport_mode) { |n| "bus" }      association :network, :factory => :network      association :company, :factory => :company diff --git a/spec/factories/chouette_routes.rb b/spec/factories/chouette_routes.rb index 047c35912..e872d24f5 100644 --- a/spec/factories/chouette_routes.rb +++ b/spec/factories/chouette_routes.rb @@ -4,23 +4,23 @@ FactoryGirl.define do      sequence(:name) { |n| "Route #{n}" }      sequence(:published_name) { |n| "Long route #{n}" }      sequence(:number) { |n| "#{n}" } -    sequence(:wayback_code) { |n| Chouette::Wayback.new( n % 2) } -    sequence(:direction_code) { |n| Chouette::Direction.new( n % 12) } +    sequence(:wayback) { |n| Chouette::Route.wayback.values[n % 2] } +    sequence(:direction) { |n| Chouette::Route.direction.values[n % 12] }      sequence(:objectid) { |n| "test:Route:#{n}" } -     +      association :line, :factory => :line -     +      factory :route do        transient do          stop_points_count 5        end -       +        after(:create) do |route, evaluator|          create_list(:stop_point, evaluator.stop_points_count, route: route)        end -       +      end    end -   +  end diff --git a/spec/factories/clean_up_results.rb b/spec/factories/clean_up_results.rb new file mode 100644 index 000000000..6d3818eff --- /dev/null +++ b/spec/factories/clean_up_results.rb @@ -0,0 +1,9 @@ +FactoryGirl.define do +  factory :clean_up_result do +    criticity 1 +message_key "MyString" +message_attributs "" +cleanup nil +  end + +end diff --git a/spec/factories/clean_ups.rb b/spec/factories/clean_ups.rb new file mode 100644 index 000000000..41165ac16 --- /dev/null +++ b/spec/factories/clean_ups.rb @@ -0,0 +1,15 @@ +FactoryGirl.define do +  factory :clean_up do +    status "MyString" +started_at "2016-11-14 14:45:18" +ended_at "2016-11-14 14:45:18" +referential nil +keep_lines false +keep_stops false +keep_companies false +keep_networks false +keep_group_of_lines false +expected_date "2016-11-14 14:45:18" +  end + +end diff --git a/spec/factories/referential_clonings.rb b/spec/factories/referential_clonings.rb new file mode 100644 index 000000000..e968d44f1 --- /dev/null +++ b/spec/factories/referential_clonings.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do +  factory :referential_cloning do +    association :source_referential, :factory => :referential +    association :target_referential, :factory => :referential +  end +end diff --git a/spec/factories/referential_metadata.rb b/spec/factories/referential_metadata.rb new file mode 100644 index 000000000..88f400ed7 --- /dev/null +++ b/spec/factories/referential_metadata.rb @@ -0,0 +1,12 @@ +FactoryGirl.define do +  factory :referential_metadata, :class => 'ReferentialMetadata' do +    referential +    periodes { [ generate(:period) ] } +    lines { create_list(:line, 3) } +  end + +  sequence :period do |n| +    date = Date.today + 2*n +    date..(date+1) +  end +end diff --git a/spec/factories/workbenches.rb b/spec/factories/workbenches.rb index 16c673655..f51e7d94c 100644 --- a/spec/factories/workbenches.rb +++ b/spec/factories/workbenches.rb @@ -3,5 +3,7 @@ FactoryGirl.define do      sequence(:name) { |n| "Workbench #{n}" }      association :organisation, :factory => :organisation +    association :line_referential +    association :stop_area_referential    end  end diff --git a/spec/features/access_points_spec.rb b/spec/features/access_points_spec.rb index a78545ee4..327c5879a 100644 --- a/spec/features/access_points_spec.rb +++ b/spec/features/access_points_spec.rb @@ -40,24 +40,25 @@ describe "Access points", :type => :feature do    end -  describe "new" do -    it "creates an access point" do -      visit referential_stop_area_path(referential, stop_area) -      click_link I18n.t("access_points.actions.new") -      fill_in "access_point[name]", :with => "My Access Point Name" -      click_button(I18n.t('formtastic.create',model: I18n.t('activerecord.models.access_point.one'))) -      expect(page).to have_content("My Access Point Name") -    end -  end +  # Fixme #1780 +  # describe "new" do +  #   it "creates an access point" do +  #     visit referential_stop_area_path(referential, stop_area) +  #     click_link I18n.t("access_points.actions.new") +  #     fill_in "access_point[name]", :with => "My Access Point Name" +  #     click_button(I18n.t('formtastic.create',model: I18n.t('activerecord.models.access_point.one'))) +  #     expect(page).to have_content("My Access Point Name") +  #   end +  # end -  describe "edit" do -    it "edits an acess point" do -      visit referential_stop_area_access_point_path(referential, stop_area, subject) -      click_link I18n.t("access_points.actions.edit") -      fill_in "access_point[name]", :with => "My New Access Point Name" -      click_button(I18n.t('formtastic.update',model: I18n.t('activerecord.models.access_point.one'))) -      expect(page).to have_content("My New Access Point Name") -    end -  end +  # describe "edit" do +  #   it "edits an acess point" do +  #     visit referential_stop_area_access_point_path(referential, stop_area, subject) +  #     click_link I18n.t("access_points.actions.edit") +  #     fill_in "access_point[name]", :with => "My New Access Point Name" +  #     click_button(I18n.t('formtastic.update',model: I18n.t('activerecord.models.access_point.one'))) +  #     expect(page).to have_content("My New Access Point Name") +  #   end +  # end  end diff --git a/spec/features/companies_spec.rb b/spec/features/companies_spec.rb index adb5fa9f9..08221f637 100644 --- a/spec/features/companies_spec.rb +++ b/spec/features/companies_spec.rb @@ -11,8 +11,8 @@ describe "Companies", :type => :feature do    describe "list" do      it "display companies" do        visit line_referential_companies_path(line_referential) -      expect(page).to have_content(companies.first.name) -      expect(page).to have_content(companies.last.name) +      expect(page).to have_content(companies.first.short_name) +      expect(page).to have_content(companies.last.short_name)      end    end diff --git a/spec/features/journey_pattern_spec.rb b/spec/features/journey_pattern_spec.rb index 470d74a99..1dbd2752d 100644 --- a/spec/features/journey_pattern_spec.rb +++ b/spec/features/journey_pattern_spec.rb @@ -8,45 +8,44 @@ describe "JourneyPatterns", :type => :feature do    let!(:route) { create(:route, :line => line) }    let!(:journey_pattern) { create(:journey_pattern, :route => route) } -  describe "from routes page to a journey_pattern page" do -    it "display route's journey_patterns" do -      visit referential_line_route_path(referential,line,route)       -      click_link I18n.t('routes.show.journey_patterns') -      expect(page).to have_content(journey_pattern.name) -    end -  end -   -  describe "from route's page to journey_pattern's page" do -    it "display journey_pattern properties" do -      visit referential_line_route_path(referential,line,route) -      click_link I18n.t('routes.show.journey_patterns') -      click_link journey_pattern.name -      expect(page).to have_content(journey_pattern.published_name) -      expect(page).to have_content(journey_pattern.comment) -      expect(page).to have_content(journey_pattern.registration_number) -    end -  end -   -  describe "from route's page, create a new journey_pattern" do       -    it "return to route's page that display new journey_pattern" do -      visit referential_line_route_path(referential,line,route) -      click_link I18n.t("journey_patterns.actions.new") -      fill_in "journey_pattern[name]", :with => "A to B" -      fill_in "journey_pattern[comment]", :with => "AB" -      click_button(I18n.t('formtastic.create',model: I18n.t('activerecord.models.journey_pattern.one'))) -      expect(page).to have_content("A to B") -    end -  end -   -  describe "from route's page, select a journey_pattern and delete it" do       -    it "return to route's page without journey_pattern name" do -      visit referential_line_route_path(referential,line,route) -      click_link I18n.t('routes.show.journey_patterns') -      click_link journey_pattern.name -      click_link I18n.t('journey_patterns.actions.destroy') -      click_link I18n.t('routes.show.journey_patterns') -      expect(page).not_to have_content(journey_pattern.name) -    end -  end -end +  # describe "from routes page to a journey_pattern page" do +  #   it "display route's journey_patterns" do +  #     visit referential_line_route_path(referential,line,route) +  #     click_link I18n.t('routes.show.journey_patterns') +  #     expect(page).to have_content(journey_pattern.name) +  #   end +  # end +  # describe "from route's page to journey_pattern's page" do +  #   it "display journey_pattern properties" do +  #     visit referential_line_route_path(referential,line,route) +  #     click_link I18n.t('routes.show.journey_patterns') +  #     click_link journey_pattern.name +  #     expect(page).to have_content(journey_pattern.published_name) +  #     expect(page).to have_content(journey_pattern.comment) +  #     expect(page).to have_content(journey_pattern.registration_number) +  #   end +  # end +  # +  # describe "from route's page, create a new journey_pattern" do +  #   it "return to route's page that display new journey_pattern" do +  #     visit referential_line_route_path(referential,line,route) +  #     click_link I18n.t("journey_patterns.actions.new") +  #     fill_in "journey_pattern[name]", :with => "A to B" +  #     fill_in "journey_pattern[comment]", :with => "AB" +  #     click_button(I18n.t('formtastic.create',model: I18n.t('activerecord.models.journey_pattern.one'))) +  #     expect(page).to have_content("A to B") +  #   end +  # end +  # +  # describe "from route's page, select a journey_pattern and delete it" do +  #   it "return to route's page without journey_pattern name" do +  #     visit referential_line_route_path(referential,line,route) +  #     click_link I18n.t('routes.show.journey_patterns') +  #     click_link journey_pattern.name +  #     click_link I18n.t('journey_patterns.actions.destroy') +  #     click_link I18n.t('routes.show.journey_patterns') +  #     expect(page).not_to have_content(journey_pattern.name) +  #   end +  # end +end diff --git a/spec/features/lines_spec.rb b/spec/features/lines_spec.rb index 875a01cf9..f6f351049 100644 --- a/spec/features/lines_spec.rb +++ b/spec/features/lines_spec.rb @@ -26,13 +26,6 @@ describe "Lines", :type => :feature do        click_link "#{lines.first.name}"        expect(page).to have_content(lines.first.name)      end - -    it "display map" do -      visit line_referential_lines_path(line_referential) -      click_link "#{lines.first.name}" -      expect(page).to have_selector("#map.line") -    end -    end    # Fixme #1780 diff --git a/spec/features/referentials_spec.rb b/spec/features/referentials_spec.rb index d04c53e18..122f2b660 100644 --- a/spec/features/referentials_spec.rb +++ b/spec/features/referentials_spec.rb @@ -41,7 +41,7 @@ describe "Referentials", :type => :feature do        fill_in "Code", :with => "test"        fill_in "Point haut/droite de l'emprise par défaut", :with => "0.0, 0.0"        fill_in "Point bas/gauche de l'emprise par défaut", :with => "1.0, 1.0" -      click_button "Créer Espace de Données" +      click_button "Créer un(e) Espace de Données"        expect(Referential.where(:name => "Test")).not_to be_nil        # CREATE SCHEMA diff --git a/spec/features/routes_spec.rb b/spec/features/routes_spec.rb index c50ff50bc..e5f21ee73 100644 --- a/spec/features/routes_spec.rb +++ b/spec/features/routes_spec.rb @@ -31,51 +31,17 @@ describe "Routes", :type => :feature do    describe "from line's page, create a new route" do      it "return to line's page that display new route" do        visit referential_line_path(referential,line) -      click_link "Ajouter une séquence d'arrêts" +      click_link "Ajouter un itinéraire"        fill_in "route_name", :with => "A to B" -      fill_in "Indice", :with => "AB" -      select 'aller', :from => "route_direction_code" -      select 'aller', :from => "route_wayback_code" -      click_button("Créer séquence d'arrêts") +      # select 'Aller', :from => "route_direction" +      select 'Aller', :from => "route_wayback" +      click_button("Créer un itinéraire")        expect(page).to have_content("A to B")      end    end -  describe "from line's page, select a route and edit it" do -    it "return to line's page with changed name" do -      visit referential_line_path(referential,line) -      click_link "#{route.name}" -      click_link "Modifier cette séquence d'arrêts" -      fill_in "route_name", :with => "#{route.name}-changed" -      click_button("Modifier séquence d'arrêts") -      expect(page).to have_content("#{route.name}-changed") -    end -  end - -  describe "from line's page, select a route and delete it" do -    it "return to line's page without route name" do -      visit referential_line_path(referential,line) -      click_link "#{route.name}" -      click_link "Supprimer cette séquence d'arrêts" -      expect(page).not_to have_content(route.name) -    end -  end - -  describe "from route's page, select edit boarding/alighting and update it" do -    it "Edits boarding/alighting properties on route stops" do -      visit referential_line_route_path(referential, line, route) -      click_link I18n.t('routes.actions.edit_boarding_alighting') -      expect(page).to have_content(I18n.t('routes.edit_boarding_alighting.title')) -      stop_points.each do |sp| -        expect(page).to have_content(sp.stop_area.name) -        expect(page).to have_content(sp.for_boarding) -        expect(page).to have_content(sp.for_alighting) -      end -    end -  end -    describe "Modifies boarding/alighting properties on route stops" do -    it "Puts (http) an update request" do +    xit "Puts (http) an update request" do        #visit edit_boarding_alighting_referential_line_route_path(referential, line, route)        visit referential_line_route_path(referential, line, route)        click_link I18n.t('routes.actions.edit_boarding_alighting') diff --git a/spec/features/stop_points_spec.rb b/spec/features/stop_points_spec.rb index 34548f3dc..18cd97709 100644 --- a/spec/features/stop_points_spec.rb +++ b/spec/features/stop_points_spec.rb @@ -11,13 +11,13 @@ describe "StopPoints", :type => :feature do    describe "from route's page to a stop points page" do      it "display route's stop points" do        visit referential_line_route_path(referential,line,route) -      click_link "Liste des arrêts de la séquence d'arrêts" +      #click_link "Liste des arrêts de la séquence d'arrêts"        route.stop_areas.each do |sa|          expect(page).to have_content(sa.name)        end      end    end -   +    describe "from route's page, go to new stop point page" do      it "display route's stop points" do        visit referential_line_route_path(referential,line,route) diff --git a/spec/features/vehicle_journey_imports_spec.rb b/spec/features/vehicle_journey_imports_spec.rb index f18d9baf0..262d585f2 100644 --- a/spec/features/vehicle_journey_imports_spec.rb +++ b/spec/features/vehicle_journey_imports_spec.rb @@ -4,7 +4,7 @@ require 'csv'  describe "VehicleJourneyImports", :type => :feature do    login_user -   +    let!(:route) { create :route }    let(:valid_file_path) { @@ -24,16 +24,16 @@ describe "VehicleJourneyImports", :type => :feature do          if counter == 0            row2 = []            row.each do |cell| -            cell = "" if cell == "import:VehicleJourney:1"  -            cell = "" if cell == "import:VehicleJourney:2"  -            cell = "" if cell == "import:VehicleJourney:3"  +            cell = "" if cell == "import:VehicleJourney:1" +            cell = "" if cell == "import:VehicleJourney:2" +            cell = "" if cell == "import:VehicleJourney:3"              row2 << cell            end            csv << row2          elsif  counter < 8            csv << row          else -          csv << ( row[0] = route.stop_points[counter - 8].id; row)           +          csv << ( row[0] = route.stop_points[counter - 8].id; row)          end          counter += 1        end @@ -42,14 +42,14 @@ describe "VehicleJourneyImports", :type => :feature do      File.open("/tmp/#{filename}")    end -   -  describe "new" do       + +  describe "new" do      it "should create vehicle journey file and return to route show page" do        visit new_referential_line_route_vehicle_journey_import_path(referential, route.line, route)        attach_file('Fichier', valid_file_path)        click_button "Lancer l'import"        expect(page).to have_content(I18n.t("vehicle_journey_imports.new.success")) -      expect(page).to have_content("Séquence d'arrêts #{route.name}") +      expect(page).to have_content("Itinéraire #{route.name}")      end      it "should return error messages when file is invalid" do @@ -58,12 +58,12 @@ describe "VehicleJourneyImports", :type => :feature do        click_button "Lancer l'import"        expect(page).to have_content(I18n.t("vehicle_journey_imports.errors.import_aborted"))      end -     +      it "should return error message when file missing on upload" do        visit new_referential_line_route_vehicle_journey_import_path(referential, route.line, route)        click_button "Lancer l'import" -      expect(page).to have_content(I18n.t("vehicle_journey_imports.errors.import_aborted"))      -    end     +      expect(page).to have_content(I18n.t("vehicle_journey_imports.errors.import_aborted")) +    end    end -   +  end diff --git a/spec/fixtures/organizations.json b/spec/fixtures/organizations.json index b70f99520..6b507b445 100644 --- a/spec/fixtures/organizations.json +++ b/spec/fixtures/organizations.json @@ -84,6 +84,7 @@    "code": "RATP",    "created_at": "2016-05-17T16:04:26.646Z",    "updated_at": "2016-05-31T10:06:39.349Z", +  "functional_scope": "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]",    "organization_users": {      "users_count": 8    }, diff --git a/spec/javascripts/actions_spec.js b/spec/javascripts/actions_spec.js new file mode 100644 index 000000000..55de1c31f --- /dev/null +++ b/spec/javascripts/actions_spec.js @@ -0,0 +1,71 @@ +var actions = require('es6_browserified/actions') + +describe('actions', () => { +  it('should create an action to add a stop', () => { +    const expectedAction = { +      type: 'ADD_STOP', +    } +    expect(actions.addStop()).toEqual(expectedAction) +  }) +}) +describe('actions', () => { +  it('should create an action to move up a stop', () => { +    const index = 1 +    const expectedAction = { +      type: 'MOVE_STOP_UP', +      index +    } +    expect(actions.moveStopUp(index)).toEqual(expectedAction) +  }) +}) +describe('actions', () => { +  it('should create an action to move down a stop', () => { +    const index = 1 +    const expectedAction = { +      type: 'MOVE_STOP_DOWN', +      index +    } +    expect(actions.moveStopDown(index)).toEqual(expectedAction) +  }) +}) +describe('actions', () => { +  it('should create an action to delete a stop', () => { +    const index = 1 +    const expectedAction = { +      type: 'DELETE_STOP', +      index +    } +    expect(actions.deleteStop(index)).toEqual(expectedAction) +  }) +}) +describe('actions', () => { +  it('should create an action to update the value of a stop', () => { +    const text = 'updated text' +    const index = 1 +    const expectedAction = { +      type: 'UPDATE_INPUT_VALUE', +      index, +      text +    } +    expect(actions.updateInputValue(index, text)).toEqual(expectedAction) +  }) +}) + +describe('actions', () => { +  it('should create an action to update the up select of a stop', () => { +    const event = { +      currentTarget: { +        value: 'forbidden', +        id: 'up' +      } +    } +    const index = 1 +    const expectedAction = { +      type :'UPDATE_SELECT_VALUE', +      select_id: 'up', +      select_value: 'forbidden', +      index +    } +    expect(actions.updateSelectValue(event, index)).toEqual(expectedAction) +  }) +}) diff --git a/spec/javascripts/reducers_spec.js b/spec/javascripts/reducers_spec.js new file mode 100644 index 000000000..a4880e73e --- /dev/null +++ b/spec/javascripts/reducers_spec.js @@ -0,0 +1,178 @@ +var reducer = require('es6_browserified/reducers/todos') +let state = [] +describe('stops reducer', () => { +  beforeEach(()=>{ +    state = [ +      { +        text: 'first', +        index: 0, +        for_boarding: 'normal', +        for_alighting: 'normal' +      }, +      { +        text: 'second', +        index: 1, +        for_boarding: 'normal', +        for_alighting: 'normal' +      } +    ] +  }) + +  it('should return the initial state', () => { +    expect( +      reducer(undefined, {}) +    ).toEqual([]) +  }) + +  it('should handle ADD_STOP', () => { +    expect( +      reducer(state, { +        type: 'ADD_STOP' +      }) +    ).toEqual( +      [ +        { +          text: 'first', +          index: 0, +          for_boarding: 'normal', +          for_alighting: 'normal' +        }, +        { +          text: 'second', +          index: 1, +          for_boarding: 'normal', +          for_alighting: 'normal' +        }, +        { +          text: '', +          index: 2, +          for_boarding: 'normal', +          for_alighting: 'normal' +        } +      ] +    ) +  }) + +  it('should handle MOVE_UP_STOP', () => { +    expect( +      reducer(state, { +        type: 'MOVE_STOP_UP', +        index: 1 +      }) +    ).toEqual( +      [ +        { +          text: 'second', +          index: 1, +          for_boarding: 'normal', +          for_alighting: 'normal' +        }, +        { +          text: 'first', +          index: 0, +          for_boarding: 'normal', +          for_alighting: 'normal' +        } +      ] +    ) +  }) + +  it('should handle MOVE_DOWN_STOP', () => { +    expect( +      reducer(state, { +        type: 'MOVE_STOP_DOWN', +        index: 0 +      }) +    ).toEqual( +      [ +        { +          text: 'second', +          index: 1, +          for_boarding: 'normal', +          for_alighting: 'normal' +        }, +        { +          text: 'first', +          index: 0, +          for_boarding: 'normal', +          for_alighting: 'normal' +        } +      ] +    ) +  }) + +  it('should handle DELETE_STOP', () => { +    expect( +      reducer(state, { +        type: 'DELETE_STOP', +        index: 1 +      }) +    ).toEqual( +      [ +        { +          text: 'first', +          index: 0, +          for_boarding: 'normal', +          for_alighting: 'normal' +        } +      ] +    ) +  }) + +  //TODO unskip when es6 is properly functionnal +  xit('should handle UPDATE_INPUT_VALUE', () => { +    expect( +      reducer(state, { +        type: 'UPDATE_INPUT_VALUE', +        index: 0, +        text: { +          text: "new value", +          stoparea_id: 1 +        } +      }) +    ).toEqual( +      [ +        { +          text: 'new value', +          index: 0, +          stoparea_id: 1, +          for_boarding: 'normal', +          for_alighting: 'normal' +        }, +        { +          text: 'second', +          index: 1, +          for_boarding: 'normal', +          for_alighting: 'normal' +        } +      ] +    ) +  }) + +  xit('should handle UPDATE_SELECT_VALUE', () => { +    expect( +      reducer(state, { +          type :'UPDATE_SELECT_VALUE', +          select_id: 'for_boarding', +          select_value: 'prohibited', +          index: 0 +      }) +    ).toEqual( +      [ +        { +          text: 'new value', +          index: 0, +          stoparea_id: 1, +          for_boarding: 'prohibited', +          for_alighting: 'normal' +        }, +        { +          text: 'second', +          index: 1, +          for_boarding: 'normal', +          for_alighting: 'normal' +        } +      ] +    ) +  }) +}) diff --git a/spec/javascripts/spec_helper.js b/spec/javascripts/spec_helper.js new file mode 100644 index 000000000..71d30ff8d --- /dev/null +++ b/spec/javascripts/spec_helper.js @@ -0,0 +1,32 @@ +// Teaspoon includes some support files, but you can use anything from your own support path too. +// require support/jasmine-jquery-1.7.0 +// require support/jasmine-jquery-2.0.0 +// require support/jasmine-jquery-2.1.0 +// require support/sinon +// require support/your-support-file +// +// PhantomJS (Teaspoons default driver) doesn't have support for Function.prototype.bind, which has caused confusion. +// Use this polyfill to avoid the confusion. +//= require support/phantomjs-shims +// +// You can require your own javascript files here. By default this will include everything in application, however you +// may get better load performance if you require the specific files that are being used in the spec that tests them. +//= require application +// +// Deferring execution +// If you're using CommonJS, RequireJS or some other asynchronous library you can defer execution. Call +// Teaspoon.execute() after everything has been loaded. Simple example of a timeout: +// +// Teaspoon.defer = true +// setTimeout(Teaspoon.execute, 1000) +// +// Matching files +// By default Teaspoon will look for files that match _spec.{js,js.coffee,.coffee}. Add a filename_spec.js file in your +// spec path and it'll be included in the default suite automatically. If you want to customize suites, check out the +// configuration in teaspoon_env.rb +// +// Manifest +// If you'd rather require your spec files manually (to control order for instance) you can disable the suite matcher in +// the configuration and use this file as a manifest. +// +// For more information: http://github.com/modeset/teaspoon diff --git a/spec/models/chouette/line_spec.rb b/spec/models/chouette/line_spec.rb index fee4bee5a..1c233de6f 100644 --- a/spec/models/chouette/line_spec.rb +++ b/spec/models/chouette/line_spec.rb @@ -47,51 +47,6 @@ describe Chouette::Line, :type => :model do      end    end -  describe "#transport_mode" do - -    def self.legacy_transport_mode_names -      %w{Air Train LongDistanceTrain LocalTrain RapidTransit Metro Tramway Coach Bus Ferry Waterborne PrivateVehicle Walk Trolleybus Bicycle Shuttle Taxi VAL Other} -    end - -    legacy_transport_mode_names.each do |transport_mode_name| -      context "when transport_mode_name is #{transport_mode_name}" do -        transport_mode = Chouette::TransportMode.new(transport_mode_name.underscore) -        it "should be #{transport_mode}" do -          subject.transport_mode_name = transport_mode_name -          expect(subject.transport_mode).to eq(transport_mode) -        end -      end -    end -    context "when transport_mode_name is nil" do -      it "should be nil" do -        subject.transport_mode_name = nil -        expect(subject.transport_mode).to be_nil -      end -    end - -  end - -  describe "#transport_mode=" do - -    it "should change transport_mode_name with TransportMode#name" do -      subject.transport_mode = "Test" -      expect(subject.transport_mode_name).to eq("Test") -    end - -  end - -  describe ".transport_modes" do - -    it "should not include unknown transport_mode" do -      expect(Chouette::Line.transport_modes).not_to include(Chouette::TransportMode.new("unknown")) -    end - -    it "should not include interchange transport_mode" do -      expect(Chouette::Line.transport_modes).not_to include(Chouette::TransportMode.new("interchange")) -    end - -  end -    context "#group_of_line_tokens=" do      let!(:group_of_line1){create(:group_of_line)}      let!(:group_of_line2){create(:group_of_line)} diff --git a/spec/models/chouette/route_spec.rb b/spec/models/chouette/route_spec.rb index 1acc5a0f7..0392485d8 100644 --- a/spec/models/chouette/route_spec.rb +++ b/spec/models/chouette/route_spec.rb @@ -3,17 +3,21 @@ require 'spec_helper'  describe Chouette::Route, :type => :model do    subject { create(:route) } -  it { is_expected.to validate_uniqueness_of :objectid } -    describe '#objectid' do      subject { super().objectid }      it { is_expected.to be_kind_of(Chouette::ObjectId) }    end +  it { is_expected.to enumerize(:direction).in(:straight_forward, :backward, :clockwise, :counter_clockwise, :north, :north_west, :west, :south_west, :south, :south_east, :east, :north_east) } +  it { is_expected.to enumerize(:wayback).in(:straight_forward, :backward) } +    #it { is_expected.to validate_presence_of :name }    it { is_expected.to validate_presence_of :line } +  it { is_expected.to validate_uniqueness_of :objectid }    #it { is_expected.to validate_presence_of :wayback_code }    #it { is_expected.to validate_presence_of :direction_code } +  it { is_expected.to validate_inclusion_of(:direction).in_array(%i(straight_forward backward clockwise counter_clockwise north north_west west south_west south south_east east north_east)) } +  it { is_expected.to validate_inclusion_of(:wayback).in_array(%i(straight_forward backward)) }    context "reordering methods" do      let( :bad_stop_point_ids){subject.stop_points.map { |sp| sp.id + 1}} @@ -165,74 +169,4 @@ describe Chouette::Route, :type => :model do        end      end    end - -  describe "#direction_code" do -    def self.legacy_directions -      %w{A R ClockWise CounterClockWise North NorthWest West SouthWest -        South SouthEast East NorthEast} -    end -    legacy_directions.each do |direction| -      context "when direction is #{direction}" do -        direction_code = Chouette::Direction.new( Chouette::Route.direction_binding[ direction]) -        it "should be #{direction_code}" do -          subject.direction = direction -          expect(subject.direction_code).to eq(direction_code) -        end -      end -    end -    context "when direction is nil" do -      it "should be nil" do -        subject.direction = nil -        expect(subject.direction_code).to be_nil -      end -    end -  end -  describe "#direction_code=" do -    context "when unknown direction is provided" do -      it "should change direction to nil" do -        subject.direction_code = "dummy" -        expect(subject.direction).to be_nil -      end -    end -    context "when an existing direction (west) is provided" do -      it "should change direction Direction.west" do -        subject.direction_code = "west" -        expect(subject.direction).to eq("West") -      end -    end -  end -  describe "#wayback_code" do -    def self.legacy_waybacks -      %w{A R} -    end -    legacy_waybacks.each do |wayback| -      context "when wayback is #{wayback}" do -        wayback_code = Chouette::Wayback.new( Chouette::Route.wayback_binding[ wayback]) -        it "should be #{wayback_code}" do -          subject.wayback = wayback -          expect(subject.wayback_code).to eq(wayback_code) -        end -      end -    end -    context "when wayback is nil" do -      it "should be nil" do -        subject.wayback = nil -        expect(subject.wayback_code).to be_nil -      end -    end -  end -  describe "#wayback_code=" do -    context "when unknown wayback is provided" do -      it "should change wayback to nil" do -        subject.wayback_code = "dummy" -        expect(subject.wayback).to be_nil -      end -    end -    context "when an existing wayback (straight_forward) is provided" do -      it "should change wayback Wayback.straight_forward" do -        subject.wayback_code = "straight_forward" -        expect(subject.wayback).to eq("A") -      end -    end -  end  end diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb index 87c0f9d92..91f519a59 100644 --- a/spec/models/chouette/vehicle_journey_spec.rb +++ b/spec/models/chouette/vehicle_journey_spec.rb @@ -155,51 +155,6 @@ describe Chouette::VehicleJourney, :type => :model do    end -    describe "#transport_mode_name" do - -    def self.legacy_transport_modes -      %w{Air Train LongDistanceTrain LocalTrain RapidTransit Metro Tramway Coach Bus Ferry Waterborne PrivateVehicle Walk Trolleybus Bicycle Shuttle Taxi VAL Other} -    end - -    legacy_transport_modes.each do |transport_mode| -      context "when transport_mode is #{transport_mode}" do -        transport_mode_name = Chouette::TransportMode.new(transport_mode.underscore) -        it "should be #{transport_mode_name}" do -          subject.transport_mode = transport_mode -          expect(subject.transport_mode_name).to eq(transport_mode_name) -        end -      end -    end -    context "when transport_mode is nil" do -      it "should be nil" do -        subject.transport_mode = nil -        expect(subject.transport_mode_name).to be_nil -      end -    end - -  end - -  describe "#transport_mode_name=" do - -    it "should change transport_mode with TransportMode#name" do -      subject.transport_mode_name = "Test" -      expect(subject.transport_mode).to eq("Test") -    end - -  end - -  describe ".transport_mode_names" do - -    it "should not include unknown transport_mode_name" do -      expect(Chouette::VehicleJourney.transport_mode_names).not_to include(Chouette::TransportMode.new("unknown")) -    end - -    it "should not include interchange transport_mode" do -      expect(Chouette::VehicleJourney.transport_mode_names).not_to include(Chouette::TransportMode.new("interchange")) -    end - -  end -    describe "#footnote_ids=" do      context "when line have footnotes, " do        let!( :route) { create( :route ) } diff --git a/spec/models/clean_up_result_spec.rb b/spec/models/clean_up_result_spec.rb new file mode 100644 index 000000000..c8a54d7bc --- /dev/null +++ b/spec/models/clean_up_result_spec.rb @@ -0,0 +1,4 @@ +require 'rails_helper' + +RSpec.describe CleanUpResult, :type => :model do +end diff --git a/spec/models/clean_up_spec.rb b/spec/models/clean_up_spec.rb new file mode 100644 index 000000000..c495abdfe --- /dev/null +++ b/spec/models/clean_up_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe CleanUp, :type => :model do +  let(:cleaner) { CleanUp.new } + +  it { should validate_presence_of(:begin_date) } +  it { should belong_to(:referential) } + +  it 'should delete vehiclejourneys without timetables' do +    create_list(:vehicle_journey, 2) +    create_list(:vehicle_journey, 2, time_tables:[create(:time_table)]) +    expect(cleaner.clean_vehicle_journeys).to eq 2 +  end + +  it 'should delete journeypatterns without vehicle journeys' do +    create_list(:journey_pattern, 2) +    create_list(:vehicle_journey, 2, journey_pattern: create(:journey_pattern)) +    expect(cleaner.clean_journey_patterns).to eq 2 +  end +end diff --git a/spec/models/line_referential_spec.rb b/spec/models/line_referential_spec.rb index 8b06f07ad..8472faaa0 100644 --- a/spec/models/line_referential_spec.rb +++ b/spec/models/line_referential_spec.rb @@ -7,5 +7,12 @@ RSpec.describe LineReferential, :type => :model do    it { should validate_presence_of(:name) }    it { is_expected.to have_many(:line_referential_syncs) } +  it { is_expected.to have_many(:workbenches) }    it { should validate_presence_of(:sync_interval) } + +  describe "#transport_modes" do +    it 'returns a list of all transport modes' do +      expect(FactoryGirl.create(:line_referential).transport_modes).to eq( Chouette::TransportMode.all.select { |tm| tm.to_i > 0 } ) +    end +  end  end diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb index 9d9749b18..9b4235755 100644 --- a/spec/models/organisation_spec.rb +++ b/spec/models/organisation_spec.rb @@ -1,9 +1,8 @@  require 'spec_helper'  describe Organisation, :type => :model do -    it { should validate_presence_of(:name) } -  it { should validate_uniqueness_of(:name) } +  it { should validate_uniqueness_of(:code) }    it 'should have a valid factory' do      expect(FactoryGirl.build(:organisation)).to be_valid @@ -33,14 +32,20 @@ describe Organisation, :type => :model do        expect(Organisation.all.map(&:name)).to include 'ALBATRANS', 'OPTILE', 'SNCF', 'STIF'      end +    it 'should retrieve functional scope' do +      Organisation.portail_sync +      org = Organisation.find_by(code: 'RATP') +      expect(org.sso_attributes['functional_scope']).to eq "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]" +    end +      it 'should update existing organisations' do -      create :organisation, name: 'dummy_name', code:'RATP', updated_at: 10.days.ago +      create :organisation, name: 'dummy_name', code:'RATP', updated_at: 10.days.ago, sso_attributes: {functional_scope: "[\"STIF:CODIFLIGNE:Line:C00840\"]"}        Organisation.portail_sync -      Organisation.find_by(code: 'RATP').tap do |org| -        expect(org.name).to eq('RATP') -        expect(org.updated_at.utc).to be_within(1.second).of Time.now -        expect(org.synced_at.utc).to be_within(1.second).of Time.now -      end +      org = Organisation.find_by(code: 'RATP') +      expect(org.name).to eq('RATP') +      expect(org.updated_at.utc).to be_within(1.second).of Time.now +      expect(org.synced_at.utc).to be_within(1.second).of Time.now +      expect(org.sso_attributes['functional_scope']).to eq "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]"      end      it 'should not create organisation if code is already present' do diff --git a/spec/models/referential_cloning_spec.rb b/spec/models/referential_cloning_spec.rb new file mode 100644 index 000000000..30391b53e --- /dev/null +++ b/spec/models/referential_cloning_spec.rb @@ -0,0 +1,10 @@ +require 'rails_helper' + +RSpec.describe ReferentialCloning, :type => :model do +  it 'should have a valid factory' do +    expect(FactoryGirl.build(:referential_cloning)).to be_valid +  end + +  it { should belong_to :source_referential } +  it { should belong_to :target_referential } +end diff --git a/spec/models/referential_metadata_spec.rb b/spec/models/referential_metadata_spec.rb new file mode 100644 index 000000000..e31caf8a1 --- /dev/null +++ b/spec/models/referential_metadata_spec.rb @@ -0,0 +1,94 @@ +require 'rails_helper' + +RSpec.describe ReferentialMetadata, :type => :model do + +  it { should belong_to(:referential) } +  it { should belong_to(:referential_source) } + +  it { is_expected.to validate_presence_of(:referential) } +  it { is_expected.to validate_presence_of(:lines) } +  it { is_expected.to validate_presence_of(:periodes) } + +  describe ".new_from" do + +    let(:referential_metadata) { create :referential_metadata, referential_source: create(:referential) } +    let(:new_referential_metadata) { ReferentialMetadata.new_from(referential_metadata) } + +    it "should not have an associated referential" do +      expect(new_referential_metadata).to be_a_new(ReferentialMetadata) +    end + +    it "should have the same lines" do +      expect(new_referential_metadata.lines).to eq(referential_metadata.lines) +    end + +    it "should have the same periods" do +      expect(new_referential_metadata.periodes).to eq(referential_metadata.periodes) +    end + +    it "should not have an associated referential" do +      expect(new_referential_metadata.referential).to be(nil) +    end + +    it "should have the same referential_source" do +      expect(new_referential_metadata.referential_source).to eq(referential_metadata.referential_source) +    end + +  end + +  describe "#first_period" do + +    let(:referential_metadata) { create :referential_metadata } + +    describe "begin" do +      it "should return first period begin" do +        expect(referential_metadata.first_period_begin).to eq(referential_metadata.first_period.begin) +      end +    end + +    describe "begin=" do +      let(:date) { Date.today } +      it "should change the first period begin" do +        referential_metadata.first_period_begin = date +        expect(referential_metadata.first_period_begin).to eq(date) +      end +    end + +    describe "end" do +      it "should return first period end" do +        expect(referential_metadata.first_period_end).to eq(referential_metadata.first_period.end) +      end +    end + +    describe "end=" do +      let(:date) { Date.today } +      it "should change the first period end" do +        referential_metadata.first_period_end = date +        expect(referential_metadata.first_period_end).to eq(date) +      end +    end + +    describe "after_validation" do +      it "should define first_period with first_period_begin and first_period_end" do +        referential_metadata.first_period_begin = Date.today +        referential_metadata.first_period_end = Date.tomorrow + +        referential_metadata.valid? + +        expect(referential_metadata.first_period).to eq(Range.new(referential_metadata.first_period_begin, referential_metadata.first_period_end)) +      end +    end + +  end + +  describe "#includes_lines" do + +    let(:referential_metadata) { create :referential_metadata } + +    it "should find ReferentialMetadata associated with given Line" do +      expect(ReferentialMetadata.include_lines(referential_metadata.lines)).to eq([referential_metadata]) +    end + +  end + +end diff --git a/spec/models/referential_spec.rb b/spec/models/referential_spec.rb index cde219ee1..4c9338aa6 100644 --- a/spec/models/referential_spec.rb +++ b/spec/models/referential_spec.rb @@ -1,9 +1,98 @@  require 'spec_helper'  describe Referential, :type => :model do +  let(:ref) { create :referential, metadatas: [create(:referential_metadata)] } -  it "create a rule_parameter_set" do -    referential = create(:referential) +  # it "create a rule_parameter_set" do +    # referential = create(:referential)      #expect(referential.rule_parameter_sets.size).to eq(1) +  # end + +  it { should have_many(:metadatas) } +  it { should belong_to(:workbench) } + +  context "Cloning referential" do +    let(:cloned) { Referential.new_from(ref).tap(&:save!) } + +    it 'should create a ReferentialCloning' do +      expect { cloned }.to change{ReferentialCloning.count}.by(1) +    end + +    def metadatas_attributes(referential) +      referential.metadatas.map { |m| [ m.periodes, m.line_ids ] } +    end + +    it 'should clone referential_metadatas' do +      expect(metadatas_attributes(cloned)).to eq(metadatas_attributes(ref)) +    end    end + +  describe "metadatas" do +    context "nested attributes support" do +      let(:attributes) do +        { +          "organisation_id" => first_organisation.id, +          "name"=>"Test", +          "slug"=>"test", +          "prefix"=>"test", +          "time_zone"=>"American Samoa", +          "upper_corner"=>"51.1,8.23", +          "lower_corner"=>"42.25,-5.2", +          "data_format"=>"neptune", +          "metadatas_attributes"=> { +            "0"=> { +              "first_period_begin(3i)"=>"19", +              "first_period_begin(2i)"=>"11", +              "first_period_begin(1i)"=>"2016", +              "first_period_end(3i)"=>"19", +              "first_period_end(2i)"=>"12", +              "first_period_end(1i)"=>"2016", +              "lines"=> [""] + lines.map { |l| l.id.to_s } +            } +          }, +          "workbench_id"=>"1", +        } +      end + +      let(:lines) { create_list(:line, 3)} + +      let(:new_referential) { Referential.new(attributes) } +      let(:first_metadata) { new_referential.metadatas.first } + +      it "should create a metadata" do +        expect(new_referential.metadatas.size).to eq(1) +      end + +      it "should define first_period_begin" do +        expect(first_metadata.first_period_begin).to eq(Date.new(2016,11,19)) +      end + +      it "should define first_period_end" do +        expect(first_metadata.first_period_end).to eq(Date.new(2016,12,19)) +      end + +      it "should define period" do +        new_referential.save! +        expect(first_metadata.first_period).to eq(Range.new(Date.new(2016,11,19), Date.new(2016,12,19))) +      end + +      it "should define period" do +        new_referential.save! +        expect(first_metadata.lines).to eq(lines) +      end +    end +  end + +  context "lines" do + +    describe "search" do + +      it "should support Ransack search method" do +        expect(ref.lines.search.result.to_a).to eq(ref.lines.to_a) +      end + +    end + +  end +  end diff --git a/spec/models/stop_area_referential_spec.rb b/spec/models/stop_area_referential_spec.rb index 87b99b18b..271badff8 100644 --- a/spec/models/stop_area_referential_spec.rb +++ b/spec/models/stop_area_referential_spec.rb @@ -6,4 +6,5 @@ RSpec.describe StopAreaReferential, :type => :model do    end    it { is_expected.to have_many(:stop_area_referential_syncs) } +  it { is_expected.to have_many(:workbenches) }  end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 16fbed27a..7d0a548c1 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -12,7 +12,8 @@ describe User, :type => :model do            :username          => 'john.doe',            :email             => 'john.doe@af83.com',            :organisation_code => '0083', -          :organisation_name => 'af83' +          :organisation_name => 'af83', +          :functional_scope  => "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]"          }          ticket.user    = "john.doe"          ticket.success = true @@ -32,6 +33,19 @@ describe User, :type => :model do          expect(Organisation.find_by(code: ticket.extra_attributes[:organisation_code])).to be_truthy        end +      it 'should store organisation functional_scope' do +        User.authenticate_with_cas_ticket(ticket) +        org = Organisation.find_by(code: ticket.extra_attributes[:organisation_code]) +        expect(org.sso_attributes['functional_scope']).to eq "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]" +      end + +      it 'should update organisation functional_scope' do +        create :organisation, code: ticket.extra_attributes[:organisation_code], sso_attributes: {functional_scope: "[\"STIF:CODIFLIGNE:Line:C00840\"]"} +        User.authenticate_with_cas_ticket(ticket) +        org = Organisation.find_by(code: ticket.extra_attributes[:organisation_code]) +        expect(org.sso_attributes['functional_scope']).to eq "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]" +      end +        it 'should not create a new organisation if organisation is already present' do          ticket.extra_attributes[:organisation_code] = create(:organisation).code          expect{User.authenticate_with_cas_ticket(ticket)}.not_to change{ Organisation.count } diff --git a/spec/models/workbench_spec.rb b/spec/models/workbench_spec.rb index bafe95e75..84149ddb0 100644 --- a/spec/models/workbench_spec.rb +++ b/spec/models/workbench_spec.rb @@ -1,7 +1,6 @@  require 'rails_helper'  RSpec.describe Workbench, :type => :model do -    it 'should have a valid factory' do      expect(FactoryGirl.build(:workbench)).to be_valid    end @@ -9,4 +8,29 @@ RSpec.describe Workbench, :type => :model do    it { should validate_presence_of(:name) }    it { should validate_presence_of(:organisation) } +  it { should belong_to(:organisation) } +  it { should belong_to(:line_referential) } +  it { should belong_to(:stop_area_referential) } + +  it { should have_many(:lines).through(:line_referential) } +  it { should have_many(:networks).through(:line_referential) } +  it { should have_many(:companies).through(:line_referential) } +  it { should have_many(:group_of_lines).through(:line_referential) } + +  it { should have_many(:stop_areas).through(:stop_area_referential) } + +  context '.lines' do +    let!(:ids) { ['STIF:CODIFLIGNE:Line:C00840', 'STIF:CODIFLIGNE:Line:C00086'] } +    let!(:organisation) { create :organisation, sso_attributes: { functional_scope: ids.to_json } } +    let(:workbench) { create :workbench, organisation: organisation } + +    it 'should filter lines based on my organisation functional_scope' do +      ids.insert('STIF:CODIFLIGNE:Line:0000').each do |id| +        create :line, objectid: id, line_referential: workbench.line_referential +      end +      lines = workbench.lines +      expect(lines.count).to eq 2 +      expect(lines.map(&:objectid)).to include(*ids) +    end +  end  end diff --git a/spec/support/devise.rb b/spec/support/devise.rb index d33812e6f..2258fefbb 100644 --- a/spec/support/devise.rb +++ b/spec/support/devise.rb @@ -2,7 +2,7 @@ module DeviseRequestHelper    include Warden::Test::Helpers    def login_user -    organisation = Organisation.where(:name => "first").first_or_create(attributes_for(:organisation)) +    organisation = Organisation.where(:code => "first").first_or_create(attributes_for(:organisation))      @user ||= create(:user, :organisation => organisation)      login_as @user, :scope => :user      # post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password @@ -33,7 +33,7 @@ module DeviseControllerHelper    def login_user      before(:each) do        @request.env["devise.mapping"] = Devise.mappings[:user] -      organisation = Organisation.where(:name => "first").first_or_create(attributes_for(:organisation)) +      organisation = Organisation.where(:code => "first").first_or_create(attributes_for(:organisation))        user = create(:user, :organisation => organisation)        sign_in user      end diff --git a/spec/support/referential.rb b/spec/support/referential.rb index ddad29963..57b510f69 100644 --- a/spec/support/referential.rb +++ b/spec/support/referential.rb @@ -1,7 +1,11 @@  module ReferentialHelper    def first_referential -    Referential.where(:slug => "first").take! +    Referential.find_by!(:slug => "first") +  end + +  def first_organisation +    Organisation.find_by!(code: "first")    end    def self.included(base) @@ -38,13 +42,17 @@ RSpec.configure do |config|      # Truncating doesn't drop schemas, ensure we're clean here, first *may not* exist      Apartment::Tenant.drop('first') rescue nil      # Create the default tenant for our tests -    organisation = Organisation.create!(:name => "first") +    organisation = Organisation.create!(code: "first", name: "first")      line_referential = LineReferential.find_or_create_by(name: "first") do |referential|        referential.add_member organisation, owner: true      end +    stop_area_referential = StopAreaReferential.find_or_create_by(name: "first") do |referential| +      referential.add_member organisation, owner: true +    end -    Referential.create! prefix: "first", name: "first", slug: "first", organisation: organisation, line_referential: line_referential +    workbench = Workbench.create!(:name => "first", organisation: organisation, line_referential: line_referential, stop_area_referential: stop_area_referential) +    referential = Referential.create! prefix: "first", name: "first", slug: "first", organisation: organisation, workbench: workbench    end    config.before(:each) do diff --git a/spec/teaspoon_env.rb b/spec/teaspoon_env.rb new file mode 100644 index 000000000..d9dd2cc47 --- /dev/null +++ b/spec/teaspoon_env.rb @@ -0,0 +1,186 @@ +Teaspoon.configure do |config| +  # Determines where the Teaspoon routes will be mounted. Changing this to "/jasmine" would allow you to browse to +  # `http://localhost:3000/jasmine` to run your tests. +  config.mount_at = "/teaspoon" + +  # Specifies the root where Teaspoon will look for files. If you're testing an engine using a dummy application it can +  # be useful to set this to your engines root (e.g. `Teaspoon::Engine.root`). +  # Note: Defaults to `Rails.root` if nil. +  config.root = nil + +  # Paths that will be appended to the Rails assets paths +  # Note: Relative to `config.root`. +  config.asset_paths = ["spec/javascripts", "spec/javascripts/stylesheets"] + +  # Fixtures are rendered through a controller, which allows using HAML, RABL/JBuilder, etc. Files in these paths will +  # be rendered as fixtures. +  config.fixture_paths = ["spec/javascripts/fixtures"] + +  # SUITES +  # +  # You can modify the default suite configuration and create new suites here. Suites are isolated from one another. +  # +  # When defining a suite you can provide a name and a block. If the name is left blank, :default is assumed. You can +  # omit various directives and the ones defined in the default suite will be used. +  # +  # To run a specific suite +  # - in the browser: http://localhost/teaspoon/[suite_name] +  # - with the rake task: rake teaspoon suite=[suite_name] +  # - with the cli: teaspoon --suite=[suite_name] +  config.suite do |suite| +    # Specify the framework you would like to use. This allows you to select versions, and will do some basic setup for +    # you -- which you can override with the directives below. This should be specified first, as it can override other +    # directives. +    # Note: If no version is specified, the latest is assumed. +    # +    # Versions: 1.3.1, 2.0.3, 2.1.3, 2.2.0, 2.2.1, 2.3.4 +    suite.use_framework :jasmine, "2.3.4" + +    # Specify a file matcher as a regular expression and all matching files will be loaded when the suite is run. These +    # files need to be within an asset path. You can add asset paths using the `config.asset_paths`. +    suite.matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee}" + +    # Load additional JS files, but requiring them in your spec helper is the preferred way to do this. +    #suite.javascripts = [] + +    # You can include your own stylesheets if you want to change how Teaspoon looks. +    # Note: Spec related CSS can and should be loaded using fixtures. +    #suite.stylesheets = ["teaspoon"] + +    # This suites spec helper, which can require additional support files. This file is loaded before any of your test +    # files are loaded. +    suite.helper = "spec_helper" + +    # Partial to be rendered in the head tag of the runner. You can use the provided ones or define your own by creating +    # a `_boot.html.erb` in your fixtures path, and adjust the config to `"/boot"` for instance. +    # +    # Available: boot, boot_require_js +    suite.boot_partial = "boot" + +    # Partial to be rendered in the body tag of the runner. You can define your own to create a custom body structure. +    suite.body_partial = "body" + +    # Hooks allow you to use `Teaspoon.hook("fixtures")` before, after, or during your spec run. This will make a +    # synchronous Ajax request to the server that will call all of the blocks you've defined for that hook name. +    #suite.hook :fixtures, &proc{} + +    # Determine whether specs loaded into the test harness should be embedded as individual script tags or concatenated +    # into a single file. Similar to Rails' asset `debug: true` and `config.assets.debug = true` options. By default,  +    # Teaspoon expands all assets to provide more valuable stack traces that reference individual source files. +    #suite.expand_assets = true + +    # Non-.js file extensions Teaspoon should consider JavaScript files +    #suite.js_extensions = [/(\.js)?.coffee/, /(\.js)?.es6/, ".es6.js"] +  end + +  # Example suite. Since we're just filtering to files already within the root test/javascripts, these files will also +  # be run in the default suite -- but can be focused into a more specific suite. +  #config.suite :targeted do |suite| +  #  suite.matcher = "spec/javascripts/targeted/*_spec.{js,js.coffee,coffee}" +  #end + +  # CONSOLE RUNNER SPECIFIC +  # +  # These configuration directives are applicable only when running via the rake task or command line interface. These +  # directives can be overridden using the command line interface arguments or with ENV variables when using the rake +  # task. +  # +  # Command Line Interface: +  # teaspoon --driver=phantomjs --server-port=31337 --fail-fast=true --format=junit --suite=my_suite /spec/file_spec.js +  # +  # Rake: +  # teaspoon DRIVER=phantomjs SERVER_PORT=31337 FAIL_FAST=true FORMATTERS=junit suite=my_suite + +  # Specify which headless driver to use. Supports PhantomJS, Selenium Webdriver and BrowserStack Webdriver. +  # +  # Available: :phantomjs, :selenium, :browserstack, :capybara_webkit +  # PhantomJS: https://github.com/modeset/teaspoon/wiki/Using-PhantomJS +  # Selenium Webdriver: https://github.com/modeset/teaspoon/wiki/Using-Selenium-WebDriver +  # BrowserStack Webdriver: https://github.com/modeset/teaspoon/wiki/Using-BrowserStack-WebDriver +  # Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit +  #config.driver = :phantomjs + +  # Specify additional options for the driver. +  # +  # PhantomJS: https://github.com/modeset/teaspoon/wiki/Using-PhantomJS +  # Selenium Webdriver: https://github.com/modeset/teaspoon/wiki/Using-Selenium-WebDriver +  # BrowserStack Webdriver: https://github.com/modeset/teaspoon/wiki/Using-BrowserStack-WebDriver +  # Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit +  #config.driver_options = nil + +  # Specify the timeout for the driver. Specs are expected to complete within this time frame or the run will be +  # considered a failure. This is to avoid issues that can arise where tests stall. +  #config.driver_timeout = 180 + +  # Specify a server to use with Rack (e.g. thin, mongrel). If nil is provided Rack::Server is used. +  #config.server = nil + +  # Specify a host to run on a specific host, otherwise Teaspoon will use 127.0.0.1. +  #config.server_host = nil + +  # Specify a port to run on a specific port, otherwise Teaspoon will use a random available port. +  #config.server_port = nil + +  # Timeout for starting the server in seconds. If your server is slow to start you may have to bump this, or you may +  # want to lower this if you know it shouldn't take long to start. +  #config.server_timeout = 20 + +  # Force Teaspoon to fail immediately after a failing suite. Can be useful to make Teaspoon fail early if you have +  # several suites, but in environments like CI this may not be desirable. +  #config.fail_fast = true + +  # Specify the formatters to use when outputting the results. +  # Note: Output files can be specified by using `"junit>/path/to/output.xml"`. +  # +  # Available: :dot, :clean, :documentation, :json, :junit, :pride, :rspec_html, :snowday, :swayze_or_oprah, :tap, :tap_y, :teamcity +  #config.formatters = [:dot] + +  # Specify if you want color output from the formatters. +  #config.color = true + +  # Teaspoon pipes all console[log/debug/error] to $stdout. This is useful to catch places where you've forgotten to +  # remove them, but in verbose applications this may not be desirable. +  #config.suppress_log = false + +  # COVERAGE REPORTS / THRESHOLD ASSERTIONS +  # +  # Coverage reports requires Istanbul (https://github.com/gotwarlost/istanbul) to add instrumentation to your code and +  # display coverage statistics. +  # +  # Coverage configurations are similar to suites. You can define several, and use different ones under different +  # conditions. +  # +  # To run with a specific coverage configuration +  # - with the rake task: rake teaspoon USE_COVERAGE=[coverage_name] +  # - with the cli: teaspoon --coverage=[coverage_name] + +  # Specify that you always want a coverage configuration to be used. Otherwise, specify that you want coverage +  # on the CLI. +  # Set this to "true" or the name of your coverage config. +  #config.use_coverage = nil + +  # You can have multiple coverage configs by passing a name to config.coverage. +  # e.g. config.coverage :ci do |coverage| +  # The default coverage config name is :default. +  config.coverage do |coverage| +    # Which coverage reports Istanbul should generate. Correlates directly to what Istanbul supports. +    # +    # Available: text-summary, text, html, lcov, lcovonly, cobertura, teamcity +    #coverage.reports = ["text-summary", "html"] + +    # The path that the coverage should be written to - when there's an artifact to write to disk. +    # Note: Relative to `config.root`. +    #coverage.output_path = "coverage" + +    # Assets to be ignored when generating coverage reports. Accepts an array of filenames or regular expressions. The +    # default excludes assets from vendor, gems and support libraries. +    #coverage.ignore = [%r{/lib/ruby/gems/}, %r{/vendor/assets/}, %r{/support/}, %r{/(.+)_helper.}] + +    # Various thresholds requirements can be defined, and those thresholds will be checked at the end of a run. If any +    # aren't met the run will fail with a message. Thresholds can be defined as a percentage (0-100), or nil. +    #coverage.statements = nil +    #coverage.functions = nil +    #coverage.branches = nil +    #coverage.lines = nil +  end +end diff --git a/spec/views/companies/index.html.erb_spec.rb b/spec/views/companies/index.html.erb_spec.rb index 6f244064d..43981ac87 100644 --- a/spec/views/companies/index.html.erb_spec.rb +++ b/spec/views/companies/index.html.erb_spec.rb @@ -1,6 +1,6 @@  require 'spec_helper' -describe "/companies/index", :type => :view do +RSpec.describe "/companies/index", :type => :view do    let!(:line_referential) { assign :line_referential, create(:line_referential) }    let!(:companies) { assign :companies, CompanyDecorator.decorate_collection(Array.new(2) { create(:company, line_referential: line_referential) }.paginate) } @@ -9,14 +9,16 @@ describe "/companies/index", :type => :view do    # Fixme #1795    # it "should render a show link for each group" do    #   render +  #   puts rendered +  #    #   companies.each do |company|    #     expect(rendered).to have_selector("a[href='#{view.line_referential_company_path(line_referential, company)}']")    #   end    # end -  # it "should render a link to create a new group" do -  #   render -  #   expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_line_referential_company_path(line_referential)}']") -  # end +  it "should render a link to create a new group" do +    render +    expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_line_referential_company_path(line_referential)}']") +  end  end diff --git a/spec/views/rule_parameter_sets/new.html.erb_spec.rb b/spec/views/rule_parameter_sets/new.html.erb_spec.rb index 62d9f2fe0..6f44311d5 100644 --- a/spec/views/rule_parameter_sets/new.html.erb_spec.rb +++ b/spec/views/rule_parameter_sets/new.html.erb_spec.rb @@ -1,20 +1,20 @@  require 'spec_helper'  describe "/rule_parameter_sets/new", :type => :view do -   +    assign_organisation    let!(:organisation) { create(:organisation) }    let!(:rule_parameter_set) { assign :rule_parameter_set, build( :rule_parameter_set, :organisation => organisation) } -   +    describe "form" do -     -    it "should render input for name" do + +    xit "should render input for name" do        render        expect(rendered).to have_selector("form") do          with_selector "input[type=text][name=?]", rule_parameter_set.name        end      end -    it "should render input div for added_mode_parameter_set" do +    xit "should render input div for added_mode_parameter_set" do        render        expect(rendered).to have_selector("form") do          with_selector "#added_mode_parameter_set" @@ -22,6 +22,6 @@ describe "/rule_parameter_sets/new", :type => :view do      end    end -   +  end diff --git a/spec/views/vehicle_journeys/_form.html.erb_spec.rb b/spec/views/vehicle_journeys/_form.html.erb_spec.rb index 05fa068d9..bf25c8092 100644 --- a/spec/views/vehicle_journeys/_form.html.erb_spec.rb +++ b/spec/views/vehicle_journeys/_form.html.erb_spec.rb @@ -1,7 +1,7 @@  require 'spec_helper'  describe "/vehicle_journeys/_form", :type => :view do -   +    assign_referential    let!(:line) { assign :line, create(:line) }    let!(:route) { assign :route, create(:route, :line => line) } @@ -13,8 +13,8 @@ describe "/vehicle_journeys/_form", :type => :view do                                                                                                                line,                                                                                                                route,                                                                                                                vehicle_journey) } -    expect(rendered).to have_selector( "select#vehicle_journey_transport_mode_name") do |node| -      Chouette::Line.transport_modes.each do |mode| +    expect(rendered).to have_selector( "select#vehicle_journey_transport_mode") do |node| +      line.transport_modes.each do |mode|          expect(node).to have_selector("option", :text => mode.text_code)        end      end @@ -26,7 +26,7 @@ describe "/vehicle_journeys/_form", :type => :view do                                                                                                                line,                                                                                                                route,                                                                                                                vehicle_journey) } -    expect(rendered).to have_selector("form") do  +    expect(rendered).to have_selector("form") do        with_selector "input[type=text][comment=]", vehicle_journey.comment      end    end @@ -37,7 +37,7 @@ describe "/vehicle_journeys/_form", :type => :view do                                                                                                                  line,                                                                                                                  route,                                                                                                                  vehicle_journey) } -      expect(rendered).to have_selector("form") do |form_node|  +      expect(rendered).to have_selector("form") do |form_node|          vehicle_journey.stop_points.each do |sp|            form_node.with_selector "label", :text => sp.stop_area.name          end @@ -51,14 +51,14 @@ describe "/vehicle_journeys/_form", :type => :view do                                                                                                                  vehicle_journey) }        expect(view).to render_template(:partial => "_vehicle_journey_at_stop_fields", :count => vehicle_journey.vehicle_journey_at_stops.count)      end -     +      it "should render vehicle_journey_at_stop's departure time" do        render partial: 'vehicle_journeys/form',               locals: { vehicle_journey: vehicle_journey, form_url: referential_line_route_vehicle_journeys_path(referential,                                                                                                                  line,                                                                                                                  route,                                                                                                                  vehicle_journey) } -      expect(rendered).to have_selector("form") do |form_node|  +      expect(rendered).to have_selector("form") do |form_node|          vehicle_journey.stop_points.each_with_index do |sp, index|            form_node.with_selector "select", :name => "vehicle_journey[vehicle_journey_at_stops_attributes][#{index}][departure_time(4i)]"            form_node.with_selector "select", :name => "vehicle_journey[vehicle_journey_at_stops_attributes][#{index}][departure_time(5i)]" @@ -73,7 +73,7 @@ describe "/vehicle_journeys/_form", :type => :view do                                                                                                                  line,                                                                                                                  route,                                                                                                                  vehicle_journey) } -      expect(rendered).to have_selector("form") do  +      expect(rendered).to have_selector("form") do          with_selector "input[type=text][objectid=][disabled=true]", vehicle_journey.objectid        end      end @@ -86,7 +86,7 @@ describe "/vehicle_journeys/_form", :type => :view do                                                                                                                  line,                                                                                                                  route,                                                                                                                  vehicle_journey) } -      expect(rendered).to have_selector("form") do  +      expect(rendered).to have_selector("form") do          with_selector "input[type=text][objectid=][disabled=false]", vehicle_journey.objectid        end      end diff --git a/spec/workers/clean_up_worker_spec.rb b/spec/workers/clean_up_worker_spec.rb new file mode 100644 index 000000000..e85768fa3 --- /dev/null +++ b/spec/workers/clean_up_worker_spec.rb @@ -0,0 +1,4 @@ +require 'rails_helper' +RSpec.describe CleanUpWorker, type: :worker do +    pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/workers/referential_cloning_worker_spec.rb b/spec/workers/referential_cloning_worker_spec.rb new file mode 100644 index 000000000..dd7b33f23 --- /dev/null +++ b/spec/workers/referential_cloning_worker_spec.rb @@ -0,0 +1,4 @@ +require 'rails_helper' +RSpec.describe ReferentialCloningWorker, type: :worker do +    pending "add some examples to (or delete) #{__FILE__}" +end | 
