diff options
96 files changed, 735 insertions, 527 deletions
| diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..150fbd629 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +.git +Dockerfile +.DS_Store +.gitignore +README.md + +public/javascripts/i18n.js +public/javascripts/translations.js + +/config/development_toolbar.rb +/coverage/* +/log/* +/node_modules/* +/public/assets/* +/public/packs-test/* +/public/packs/* +/public/uploads/* +/spec/fixtures/target_* +/tmp/* +/vendor/bundle/* diff --git a/DEVNOTES.md b/DEVNOTES.md deleted file mode 100644 index bcdd37f5e..000000000 --- a/DEVNOTES.md +++ /dev/null @@ -1,61 +0,0 @@ - -# Authorization Logic in Policies - -## Base Rules - -### ApplicationPolicy - -Policies inheriting from the `ApplicationPolicy` authorize _Undestructive_ _Permissions_ whiche are `index?` and -`show?`. And forbid _Destructive_ _Permissions_ which are `create?`, `destroy?` & `update`. - -These _CRUD_ permissions are tied to to _Action_ permissions, `delete?`→ `destroy?`, `edit?` → `update? and `new?`→ `create?`. - -These three _Action_ permissions are not supposed to be overriden in `ApplicationPolicy` subclasses. - - -### Common Policy Types - -There are two common policy types. - -#### Read Only Type Policy - -This corresponds to inheriting from  `ApplicationPolicy` without overriding one of the five aforementioned _CRUD_ permissions. - -The following Policies are of this type. - -  - `Company` -  - `GroupOfLine` -  - `Line` + custom -  - `Network` -  - `StopArea` - -#### Standard Type Policy - -The standard type policy inherits from `ApplicationPolicy` does not override any _Undesructive_ _Pemission_ but overrides the _Destructive_ ones. - -They are overriden as follows - -```ruby -      def <destructive>? -        !referential_read_only? && organisation_match? && user.has_permission('<resource in plural form>.<action>') -      end -``` - -**An exception** is `Referntial` which **cannot** check for `organisation_match?` for creation as there is no referential. - -The following Policies are of this type. - -  - `AccessLink` -  - `AccessPoint` -  - `Calendar` -  - `ConnectionLink` -  - `JourneyPattern` -  - `Referential` + custom -  - `Route` (used by `StopPoint` too) -  - `RoutingConstraintZone` -  - `TimeTable` + custom - - - - - diff --git a/Dockerfile.build b/Dockerfile.build new file mode 100644 index 000000000..d15b3424c --- /dev/null +++ b/Dockerfile.build @@ -0,0 +1,37 @@ +FROM debian:stable-slim + +ENV RAILS_ENV test +ENV KEEP_DATABASE_CONFIG true +ENV IGNORE_YARN_INSTALL true + +# Prepare nodejs 6.x and yarn package installation +RUN apt-get update && apt-get install -y --no-install-recommends curl gnupg ca-certificates apt-transport-https && \ +    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ +    echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list && \ +    curl -sS https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ +    echo "deb https://deb.nodesource.com/node_6.x stretch main" > /etc/apt/sources.list.d/nodesource.list + +# Install ruby, native dependencies, bundler and yarn +RUN apt-get update && mkdir -p /usr/share/man/man1 /usr/share/man/man7 && \ +    apt-get install -y --no-install-recommends ruby2.3 && \ +    apt-get install -y --no-install-recommends libpq5 libxml2 zlib1g imagemagick libproj12 postgresql-client-common postgresql-client-9.6 yarn nodejs && \ +    gem2.3 install --no-ri --no-rdoc bundler + +# Install bundler packages +COPY Gemfile Gemfile.lock /app/ +RUN apt-get -y install --no-install-recommends build-essential ruby2.3-dev libpq-dev libxml2-dev zlib1g-dev libproj-dev libmagic1 libmagic-dev git-core&& \ +    cd /app && bundle install --deployment + +# Install yarn packages +COPY package.json yarn.lock /app/ +RUN cd /app && yarn --frozen-lockfile install + +# Install application file +COPY . /app/ + +# Override database.yml and secrets.yml files +COPY config/database.yml.docker app/config/database.yml +COPY config/secrets.yml.docker app/config/secrets.yml + +WORKDIR /app +CMD ["sh", "-c", "bundle exec rake ci:docker"] diff --git a/INSTALL.md b/INSTALL.md index 392ef5d9f..e33ea9a92 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -5,7 +5,7 @@  Example with [rvm](https://rvm.io/) (other solutions : rbenv, packages..):  ```sh -rvm install 2.3.1 +rvm install 2.3.5  ```  Nokogiri on macOS @@ -104,41 +104,7 @@ bundle exec rake db:create db:migrate  Run :  ```sh -bundle exec rake db:seed:stif -``` - -Two users are created : stif-boiv@af83.com/secret and stif-boiv+transporteur@af83.com/secret - -#### Synchronize with STIF CODIFLIGNE (Line) and REFLEX (StopArea) - -```sh -bundle exec rake codifligne:sync -bundle exec rake reflex:sync -``` - -**N.B.** These are asynchronous tasks, you can observe the launched jobs in your [Sidekiq Console](http://localhost:3000/sidekiq) - -#### Create Referential - -To create `Referential` objects with some data (`Route`, `JourneyPattern`, `VehicleJourney`, etc), you need to wait codifligne and reflex jobs finished. And then you can launch : - -```sh -bundle exec rake referential:create -``` - -### Run tests - -* Rspec (Rails test) - -```sh -bundle exec rake spec -``` - -* Jest (JavaScript tests) - -```sh -grunt jest #to run the whole specs. -grunt #to watch for changes and automatically run corresponding tests. +bundle exec rake db:seed  ```  ### Run @@ -153,5 +119,3 @@ bundle exec sidekiq  bin/webpack-dev-server // Launch webpack server to compile assets on the fly  bundle exec rails server // Launch rails server  ``` - -You need to have an account on [STIF Portail](http://stif-portail-dev.af83.priv/) to connect to the Rails application. @@ -1,5 +1,5 @@  # Chouette -[](https://codeclimate.com/github/af83/chouette-core/maintainability) <a href="https://codeclimate.com/github/af83/chouette-core/test_coverage"><img src="https://api.codeclimate.com/v1/badges/f9680a36dcfd25d4f2cf/test_coverage" /></a> +[](https://codeclimate.com/github/af83/chouette-core/maintainability)  Chouette is a Ruby/Rails & Java project to manage transport offer data. It is designed as an [SaaS](http://en.wikipedia.org/wiki/Software_as_a_service) platform and can : @@ -23,6 +23,11 @@ Requirements  * [Import, Export and Validation Operations](https://github.com/af83/chouette-core-iev) are in the Java part of the project +Install +---------------- + +Install steps are available [here](https://github.com/af83/chouette-core/blob/master/INSTALL.md) +  More Information  ---------------- diff --git a/app/assets/javascripts/modal_confirmation.js b/app/assets/javascripts/modal_confirmation.js new file mode 100644 index 000000000..e82a8a81b --- /dev/null +++ b/app/assets/javascripts/modal_confirmation.js @@ -0,0 +1,31 @@ +$(document).ready(() => { +  $.rails.allowAction = (link) => { +    let message = link.data('confirm') +    if (!message) return true +    showConfirmModal(link) +    return false +  } + +  let showConfirmModal = (link) => { +    let message = link.data('confirm') +    let html = `<div class="modal fade" id="confirmationDialog" tabindex="1" role="dialog"> +        <div class="modal-container"> +          <div class="modal-dialog"> +            <div class="modal-content"> +              <div class="modal-header"> +                <h4 class="modal-title"> ${I18n.t('warning')} </h4> +              </div> +              <div class="modal-body"> +                <p>${message}</p> +              </div> +              <div class="modal-footer"> +                <a data-dismiss="modal" class="btn">${I18n.t('cancel')}</a> +                <a data-dismiss="modal" class="btn btn-primary" data-method=${link.data('method')} href=${link.attr('href')}>${I18n.t('ok')}</a> +              </div> +            </div> +          </div> +        </div> +      </div> ` +    $(html).modal() +  } +})
\ No newline at end of file diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb index 2c32ed3a5..c359dfd6d 100644 --- a/app/controllers/companies_controller.rb +++ b/app/controllers/companies_controller.rb @@ -44,9 +44,9 @@ class CompaniesController < ChouetteController      ids = @q.result(:distinct => true).pluck(:id)      scope = scope.where(id: ids)      if sort_column && sort_direction -      @companies ||= scope.order(sort_column + ' ' + sort_direction).paginate(:page => params[:page]) +      @companies ||= scope.order("lower(#{sort_column})" + ' ' + sort_direction).paginate(:page => params[:page])      else -      @companies ||= scope.order(:name).paginate(:page => params[:page]) +      @companies ||= scope.order('lower(name)').paginate(:page => params[:page])      end    end diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index 734152c64..38363e8ef 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -120,7 +120,6 @@ class StopAreasController < ChouetteController    def collection      scope = parent.present? ? parent.stop_areas : referential.stop_areas -    scope = ransack_status(scope)      @q = scope.search(params[:q])      if sort_column && sort_direction @@ -206,24 +205,4 @@ class StopAreasController < ChouetteController      ] + permitted_custom_fields_params(Chouette::StopArea.custom_fields(stop_area_referential.workgroup))      params.require(:stop_area).permit(fields)    end - -   # Fake ransack filter -  def ransack_status scope -    return scope unless params[:q].try(:[], :status) -    return scope if params[:q][:status].values.uniq.length == 1 - -    @status = { -      in_creation: params[:q][:status]['in_creation'] == 'true', -      confirmed: params[:q][:status]['confirmed'] == 'true', -      deactivated: params[:q][:status]['deactivated'] == 'true', -    } - -    scope = Chouette::StopArea.where( -      "confirmed_at #{(@status[:confirmed] || @status[:deactivated]) ? "IS NOT NULL" : "IS NULL"} -      AND deleted_at #{@status[:deactivated] ? "IS NOT NULL" : "IS NULL"}" -      ) - -    params[:q].delete :status -    scope -  end  end diff --git a/app/decorators/compliance_control_decorator.rb b/app/decorators/compliance_control_decorator.rb index fd2dbd9ce..7cdb4a890 100644 --- a/app/decorators/compliance_control_decorator.rb +++ b/app/decorators/compliance_control_decorator.rb @@ -5,7 +5,7 @@ class ComplianceControlDecorator < AF83::Decorator    with_instance_decorator do |instance_decorator|      instance_decorator.show_action_link do |l| -      l.content h.t('compliance_control_sets.actions.show') +      l.content t('compliance_control_sets.actions.show')        l.href do          h.compliance_control_set_compliance_control_path(            object.compliance_control_set.id, @@ -17,7 +17,7 @@ class ComplianceControlDecorator < AF83::Decorator      instance_decorator.edit_action_link      instance_decorator.destroy_action_link do |l| -      l.data confirm: h.t('compliance_controls.actions.destroy_confirm') +      l.data confirm: t('compliance_controls.actions.destroy_confirm')      end    end diff --git a/app/decorators/compliance_control_set_decorator.rb b/app/decorators/compliance_control_set_decorator.rb index b16a06886..ad38c492c 100644 --- a/app/decorators/compliance_control_set_decorator.rb +++ b/app/decorators/compliance_control_set_decorator.rb @@ -20,7 +20,7 @@ class ComplianceControlSetDecorator < AF83::Decorator      instance_decorator.destroy_action_link do |l|        l.content h.destroy_link_content        l.href { h.compliance_control_set_path(object.id) } -      l.data confirm: h.t('compliance_control_sets.actions.destroy_confirm') +      l.data confirm: t('compliance_control_sets.actions.destroy_confirm')      end    end  end diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb index 077978c36..0fdb7cc0b 100644 --- a/app/decorators/line_decorator.rb +++ b/app/decorators/line_decorator.rb @@ -44,7 +44,7 @@ class LineDecorator < AF83::Decorator        l.content  { h.deactivate_link_content('lines.actions.deactivate') }        l.href     { h.deactivate_line_referential_line_path(context[:line_referential], object) }        l.method   :put -      l.data     confirm: h.t('lines.actions.deactivate_confirm') +      l.data     {{ confirm: h.t('lines.actions.deactivate_confirm') }}        l.add_class "delete-action"      end @@ -52,13 +52,13 @@ class LineDecorator < AF83::Decorator        l.content  { h.activate_link_content('lines.actions.activate') }        l.href     { h.activate_line_referential_line_path(context[:line_referential], object) }        l.method   :put -      l.data     confirm: h.t('lines.actions.activate_confirm') +      l.data     {{ confirm: h.t('lines.actions.activate_confirm') }}        l.add_class "delete-action"      end      instance_decorator.destroy_action_link do |l|        l.content  { h.destroy_link_content('lines.actions.destroy') } -      l.data     confirm: h.t('lines.actions.destroy_confirm') +      l.data     {{ confirm: h.t('lines.actions.destroy_confirm') }}        l.add_class "delete-action"      end    end diff --git a/app/decorators/network_decorator.rb b/app/decorators/network_decorator.rb index ea0f73dc2..55cd37082 100644 --- a/app/decorators/network_decorator.rb +++ b/app/decorators/network_decorator.rb @@ -25,8 +25,8 @@ class NetworkDecorator < AF83::Decorator      end      instance_decorator.destroy_action_link do |l| -      l.content h.destroy_link_content('networks.actions.destroy') -      l.data confirm: h.t('networks.actions.destroy_confirm') +      l.content { h.destroy_link_content('networks.actions.destroy') } +      l.data {{ confirm: h.t('networks.actions.destroy_confirm') }}      end    end  end diff --git a/app/decorators/purchase_window_decorator.rb b/app/decorators/purchase_window_decorator.rb index 9b58577b2..8e6ca9d36 100644 --- a/app/decorators/purchase_window_decorator.rb +++ b/app/decorators/purchase_window_decorator.rb @@ -15,7 +15,7 @@ class PurchaseWindowDecorator < AF83::Decorator      instance_decorator.edit_action_link      instance_decorator.destroy_action_link do |l| -      l.data confirm: h.t('purchase_windows.actions.destroy_confirm') +      l.data confirm: t('purchase_windows.actions.destroy_confirm')      end    end diff --git a/app/decorators/referential_line_decorator.rb b/app/decorators/referential_line_decorator.rb index 3ac846d76..4416e133e 100644 --- a/app/decorators/referential_line_decorator.rb +++ b/app/decorators/referential_line_decorator.rb @@ -13,12 +13,12 @@ class ReferentialLineDecorator < AF83::Decorator      instance_decorator.show_action_link      instance_decorator.action_link secondary: true do |l| -      l.content Chouette::Line.human_attribute_name(:footnotes) +      l.content Chouette::Line.tmf(:footnotes)        l.href { h.referential_line_footnotes_path(context[:referential], object) }      end      instance_decorator.action_link secondary: true do |l| -      l.content h.t('routing_constraint_zones.index.title') +      l.content t('routing_constraint_zones.index.title')        l.href do          h.referential_line_routing_constraint_zones_path(            scope, @@ -36,7 +36,7 @@ class ReferentialLineDecorator < AF83::Decorator        },        secondary: true      ) do |l| -      l.content h.t('routes.actions.new') +      l.content t('routes.actions.new')        l.href { h.new_referential_line_route_path(scope, object) }      end    end diff --git a/app/decorators/referential_network_decorator.rb b/app/decorators/referential_network_decorator.rb index c508452c0..f8c656e7c 100644 --- a/app/decorators/referential_network_decorator.rb +++ b/app/decorators/referential_network_decorator.rb @@ -20,8 +20,8 @@ class ReferentialNetworkDecorator < AF83::Decorator      end      instance_decorator.destroy_action_link do |l| -      l.content h.destroy_link_content('networks.actions.destroy') -      l.data confirm: h.t('networks.actions.destroy_confirm') +      l.content { h.destroy_link_content('networks.actions.destroy') } +      l.data confirm: t('networks.actions.destroy_confirm')      end    end  end diff --git a/app/decorators/route_decorator.rb b/app/decorators/route_decorator.rb index 646bc1620..801e139b0 100644 --- a/app/decorators/route_decorator.rb +++ b/app/decorators/route_decorator.rb @@ -18,7 +18,7 @@ class RouteDecorator < AF83::Decorator        if: ->() { object.stop_points.any? },        secondary: :show      ) do |l| -      l.content h.t('journey_patterns.actions.index') +      l.content t('journey_patterns.actions.index')        l.href do          [            context[:referential], @@ -33,7 +33,7 @@ class RouteDecorator < AF83::Decorator        if: ->() { object.journey_patterns.present? },        secondary: :show      ) do |l| -      l.content h.t('vehicle_journeys.actions.index') +      l.content t('vehicle_journeys.actions.index')        l.href do          [            context[:referential], @@ -45,7 +45,7 @@ class RouteDecorator < AF83::Decorator      end      instance_decorator.action_link secondary: :show do |l| -      l.content h.t('vehicle_journey_exports.new.title') +      l.content t('vehicle_journey_exports.new.title')        l.href do          h.referential_line_route_vehicle_journey_exports_path(            context[:referential], @@ -60,7 +60,7 @@ class RouteDecorator < AF83::Decorator        secondary: :show,        policy: :duplicate      ) do |l| -      l.content h.t('routes.duplicate.title') +      l.content t('routes.duplicate.title')        l.method :post        l.href do          h.duplicate_referential_line_route_path( @@ -76,7 +76,7 @@ class RouteDecorator < AF83::Decorator        policy: :create_opposite,        if: ->{h.has_feature?(:create_opposite_routes)}      ) do |l| -      l.content h.t('routes.create_opposite.title') +      l.content t('routes.create_opposite.title')        l.method :post        l.disabled { object.opposite_route.present? }        l.href do @@ -90,7 +90,7 @@ class RouteDecorator < AF83::Decorator      end      instance_decorator.destroy_action_link do |l| -      l.data confirm: h.t('routes.actions.destroy_confirm') +      l.data confirm: t('routes.actions.destroy_confirm')      end    end  end diff --git a/app/decorators/routing_constraint_zone_decorator.rb b/app/decorators/routing_constraint_zone_decorator.rb index de73068be..3ff286cc1 100644 --- a/app/decorators/routing_constraint_zone_decorator.rb +++ b/app/decorators/routing_constraint_zone_decorator.rb @@ -21,7 +21,7 @@ class RoutingConstraintZoneDecorator < AF83::Decorator      instance_decorator.edit_action_link      instance_decorator.destroy_action_link do |l| -      l.data confirm: h.t('routing_constraint_zones.actions.destroy_confirm') +      l.data confirm: t('routing_constraint_zones.actions.destroy_confirm')      end    end  end diff --git a/app/decorators/stop_area_decorator.rb b/app/decorators/stop_area_decorator.rb index 525681971..c7f10b13b 100644 --- a/app/decorators/stop_area_decorator.rb +++ b/app/decorators/stop_area_decorator.rb @@ -11,11 +11,11 @@ class StopAreaDecorator < AF83::Decorator      instance_decorator.show_action_link      instance_decorator.edit_action_link do |l| -      l.content h.t('stop_areas.actions.edit') +      l.content t('stop_areas.actions.edit')      end      instance_decorator.action_link policy: :deactivate, secondary: true do |l| -      l.content h.deactivate_link_content('stop_areas.actions.deactivate') +      l.content { h.deactivate_link_content('stop_areas.actions.deactivate') }        l.href do          h.deactivate_stop_area_referential_stop_area_path(            object.stop_area_referential, @@ -23,12 +23,12 @@ class StopAreaDecorator < AF83::Decorator          )        end        l.method :put -      l.data confirm: h.t('stop_areas.actions.deactivate_confirm') +      l.data confirm: t('stop_areas.actions.deactivate_confirm')        l.add_class 'delete-action'      end      instance_decorator.action_link policy: :activate, secondary: true do |l| -      l.content h.activate_link_content('stop_areas.actions.activate') +      l.content { h.activate_link_content('stop_areas.actions.activate') }        l.href do          h.activate_stop_area_referential_stop_area_path(            object.stop_area_referential, @@ -36,13 +36,13 @@ class StopAreaDecorator < AF83::Decorator          )        end        l.method :put -      l.data confirm: h.t('stop_areas.actions.activate_confirm') +      l.data confirm: t('stop_areas.actions.activate_confirm')        l.add_class 'delete-action'      end      instance_decorator.destroy_action_link do |l| -      l.content h.destroy_link_content('stop_areas.actions.destroy') -      l.data confirm: h.t('stop_areas.actions.destroy_confirm') +      l.content { h.destroy_link_content('stop_areas.actions.destroy') } +      l.data confirm: t('stop_areas.actions.destroy_confirm')      end    end diff --git a/app/decorators/stop_area_referential_decorator.rb b/app/decorators/stop_area_referential_decorator.rb index d30501ec9..36e45abca 100644 --- a/app/decorators/stop_area_referential_decorator.rb +++ b/app/decorators/stop_area_referential_decorator.rb @@ -5,9 +5,9 @@ class StopAreaReferentialDecorator < AF83::Decorator      instance_decorator.action_link policy: :synchronize, primary: :show do |l|        l.content t('actions.sync') -      l.href { h. sync_stop_area_referential_path(object.id) } +      l.href { h.sync_stop_area_referential_path(object.id) }        l.method :post      end -     +    end  end diff --git a/app/decorators/stop_point_decorator.rb b/app/decorators/stop_point_decorator.rb index 4ff5bce9c..575938fa2 100644 --- a/app/decorators/stop_point_decorator.rb +++ b/app/decorators/stop_point_decorator.rb @@ -4,8 +4,8 @@ class StopPointDecorator < AF83::Decorator    with_instance_decorator do |instance_decorator|      instance_decorator.show_action_link do |l|        l.href do -        h.referential_stop_area_path( -          object.referential, +        h.stop_area_referential_stop_area_path( +          object.stop_area.stop_area_referential,            object.stop_area          )        end diff --git a/app/helpers/menus_helper.rb b/app/helpers/menus_helper.rb new file mode 100644 index 000000000..81d55a944 --- /dev/null +++ b/app/helpers/menus_helper.rb @@ -0,0 +1,20 @@ +module MenusHelper +  def main_nav_menu_item label, &block +    @current_menu_item_count ||= 0 +    @current_menu_item_count += 1 +    content_tag :div, class: "menu-item panel" do +      out = "" +      out += content_tag(:div, class: "panel-heading") do +        content_tag :h4, class: "panel-title" do +          link_to label, "#menu-item-#{@current_menu_item_count}", data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' +        end +      end +      out += content_tag(:div, class: "panel-collapse collapse", id: "menu-item-#{@current_menu_item_count}") do +        content_tag :div, class: "list-group" do +          capture(&block) +        end +      end +      out.html_safe +    end +  end +end diff --git a/app/helpers/stop_areas_helper.rb b/app/helpers/stop_areas_helper.rb index 314154fb7..d3e7dd2a4 100644 --- a/app/helpers/stop_areas_helper.rb +++ b/app/helpers/stop_areas_helper.rb @@ -75,16 +75,17 @@ module StopAreasHelper      t "formtastic.hints.stop_area.registration_number"    end -  def stop_area_status(stop_area) -    if stop_area.activated? -      content_tag(:span, nil, class: 'fa fa-check-circle fa-lg text-success') + -      t('activerecord.attributes.stop_area.confirmed') -    elsif stop_area.deactivated? -      content_tag(:span, nil, class: 'fa fa-exclamation-circle fa-lg text-danger') + -      t('activerecord.attributes.stop_area.deactivated') -    else -      content_tag(:span, nil, class: 'fa fa-pencil fa-lg text-info') + -      t('activerecord.attributes.stop_area.in_creation') +  def stop_area_status(status) +    case status +      when :confirmed +        content_tag(:span, nil, class: 'fa fa-check-circle fa-lg text-success') + +        t('activerecord.attributes.stop_area.confirmed') +      when :deactivated +        content_tag(:span, nil, class: 'fa fa-exclamation-circle fa-lg text-danger') + +        t('activerecord.attributes.stop_area.deactivated') +      else +        content_tag(:span, nil, class: 'fa fa-pencil fa-lg text-info') + +        t('activerecord.attributes.stop_area.in_creation')      end    end diff --git a/app/javascript/helpers/polyfills.js b/app/javascript/helpers/polyfills.js index 93e3e9846..691fe04af 100644 --- a/app/javascript/helpers/polyfills.js +++ b/app/javascript/helpers/polyfills.js @@ -1,4 +1,5 @@  import 'promise-polyfill/src/polyfill'  import 'es6-symbol/implement'  import 'polyfill-array-includes' +import 'babel-polyfill'  import 'whatwg-fetch' diff --git a/app/javascript/vehicle_journeys/actions/index.js b/app/javascript/vehicle_journeys/actions/index.js index 98594083d..8ac8b5ec5 100644 --- a/app/javascript/vehicle_journeys/actions/index.js +++ b/app/javascript/vehicle_journeys/actions/index.js @@ -379,11 +379,11 @@ const actions = {                  vehicle_journey_at_stops: vjasWithDelta,                  deletable: false,                  selected: false, -                published_journey_name: val.published_journey_name || 'non renseigné', -                published_journey_identifier: val.published_journey_identifier || 'non renseigné', -                company: val.company || {name: 'non renseigné'}, -                transport_mode: val.route.line.transport_mode || 'undefined', -                transport_submode: val.route.line.transport_submode || 'undefined' +                published_journey_name: val.published_journey_name || '', +                published_journey_identifier: val.published_journey_identifier || '', +                company: val.company || {name: ''}, +                transport_mode: val.route.line.transport_mode || '', +                transport_submode: val.route.line.transport_submode || ''                })              )            } diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js index cec39ab4e..a0438d7c5 100644 --- a/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js +++ b/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js @@ -58,7 +58,8 @@ export default class BSelect4 extends Component {        this.props.onSelect2JourneyPattern(e)      }      else{ -      let data = JSON.parse(e.currentTarget.selectedOptions[0].dataset.item) +      let option = e.currentTarget.options[e.currentTarget.selectedIndex] +      let data = JSON.parse(option.dataset.item)        this.props.onSelect2JourneyPattern({params:          { diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb index b933e1944..25a0010d8 100644 --- a/app/models/chouette/stop_area.rb +++ b/app/models/chouette/stop_area.rb @@ -383,6 +383,28 @@ module Chouette        end      end +    def self.ransackable_scopes(auth_object = nil) +      [:by_status] +    end + + +    def self.by_status(*statuses) +      return Chouette::StopArea.all if statuses.reject(&:blank?).length == 3 || statuses.reject(&:blank?).empty? + +      status = { +        in_creation: statuses.include?('in_creation'), +        confirmed: statuses.include?('confirmed'), +        deactivated: statuses.include?('deactivated'), +      } + +      query = [] +      query << "deleted_at IS NOT NULL" if statuses.include?('deactivated') +      query << "(confirmed_at IS NULL AND deleted_at IS NULL)" if statuses.include?('in_creation') +      query << "(confirmed_at IS NOT NULL AND deleted_at IS NULL)" if statuses.include?('confirmed') + +      Chouette::StopArea.where(query.join(' OR ')) +    end +      def activated?        !!(deleted_at.nil? && confirmed_at)      end @@ -410,7 +432,7 @@ module Chouette      end      def status -      return :deleted if deleted_at +      return :deactivated if deleted_at        return :confirmed if confirmed_at        :in_creation @@ -418,7 +440,7 @@ module Chouette      def status=(status)        case status&.to_sym -      when :deleted +      when :deactivated          deactivate        when :confirmed          activate @@ -428,7 +450,7 @@ module Chouette      end      def self.statuses -      %i{in_creation confirmed deleted} +      %i{in_creation confirmed deactivated}      end      def time_zone_offset @@ -441,7 +463,7 @@ module Chouette        return unless ActiveSupport::TimeZone[time_zone].present?        ActiveSupport::TimeZone[time_zone].tzinfo.name      end -     +      def country        return unless country_code        country = ISO3166::Country[country_code] diff --git a/app/models/clean_up.rb b/app/models/clean_up.rb index 0f73e07b2..9cf2389c9 100644 --- a/app/models/clean_up.rb +++ b/app/models/clean_up.rb @@ -16,6 +16,8 @@ class CleanUp < ApplicationModel      where(referential_id: referential.id)    end +  attr_accessor :methods +    def end_date_must_be_greater_that_begin_date      if self.end_date && self.date_type == 'between' && self.begin_date >= self.end_date        errors.add(:base, I18n.t('activerecord.errors.models.clean_up.invalid_period')) @@ -43,17 +45,22 @@ class CleanUp < ApplicationModel            end          end -        destroy_vehicle_journeys_outside_referential +        destroy_routes_outside_referential          # Disabled for the moment. See #5372          # destroy_time_tables_outside_referential -        destroy_vehicle_journeys -        destroy_journey_patterns -        destroy_routes +        # Run caller-specified cleanup methods +        run_methods        end      end    end +  def run_methods +    return if methods.nil? + +    methods.each { |method| send(method) } +  end +    def destroy_time_tables_between      time_tables = Chouette::TimeTable.where('end_date < ? AND start_date > ?', self.end_date, self.begin_date)      self.destroy_time_tables(time_tables) @@ -100,9 +107,9 @@ class CleanUp < ApplicationModel      destroy_time_tables(time_tables)    end -  def destroy_vehicle_journeys_outside_referential +  def destroy_routes_outside_referential      line_ids = referential.metadatas.pluck(:line_ids).flatten.uniq -    Chouette::VehicleJourney.joins(:route).where(["routes.line_id not in (?)", line_ids]).destroy_all +    Chouette::Route.where(['line_id not in (?)', line_ids]).destroy_all    end    def destroy_vehicle_journeys @@ -117,6 +124,12 @@ class CleanUp < ApplicationModel      Chouette::Route.where("id not in (select distinct route_id from journey_patterns)").destroy_all    end +  def destroy_empty +    destroy_vehicle_journeys +    destroy_journey_patterns +    destroy_routes +  end +    def overlapping_periods      self.end_date = self.begin_date if self.date_type != 'between'      Chouette::TimeTablePeriod.where('(period_start, period_end) OVERLAPS (?, ?)', self.begin_date, self.end_date) diff --git a/app/models/concerns/checksum_support.rb b/app/models/concerns/checksum_support.rb index fe52604bb..86bbd1d00 100644 --- a/app/models/concerns/checksum_support.rb +++ b/app/models/concerns/checksum_support.rb @@ -10,19 +10,24 @@ module ChecksumSupport    end    module ClassMethods +      def has_checksum_children klass, opts={}        parent_class = self        belongs_to = opts[:relation] || self.model_name.singular        has_many = opts[:relation] || self.model_name.plural        Rails.logger.debug "Define callback in #{klass} to update checksums #{self.model_name} (via #{has_many}/#{belongs_to})" -      klass.after_save do + +      child_update_parent = Proc.new do          parents = []          parents << self.send(belongs_to) if klass.reflections[belongs_to].present?          parents += self.send(has_many) if klass.reflections[has_many].present?          Rails.logger.debug "Request from #{klass.name} checksum updates for #{parents.count} #{parent_class} parent(s)"          parents.compact.each &:update_checksum_without_callbacks!        end + +      klass.after_save &child_update_parent +      klass.after_destroy &child_update_parent      end    end diff --git a/app/models/import/netex.rb b/app/models/import/netex.rb index b4422328c..753f9128d 100644 --- a/app/models/import/netex.rb +++ b/app/models/import/netex.rb @@ -100,7 +100,6 @@ class Import::Netex < Import::Base          metadata.periodes = frame.periods          line_objectids = frame.line_refs.map { |ref| "STIF:CODIFLIGNE:Line:#{ref}" } -        create_message criticity: :info, message_key: "referential_creation_lines_found", message_attributes: {line_objectids: line_objectids.to_sentence}          metadata.line_ids = workbench.lines.where(objectid: line_objectids).pluck(:id)        end      end diff --git a/app/models/merge.rb b/app/models/merge.rb index 2824e1f83..aca2f4d4d 100644 --- a/app/models/merge.rb +++ b/app/models/merge.rb @@ -145,12 +145,19 @@ class Merge < ApplicationModel        end      end +    referential_route_opposite_route_ids = referential.switch do +      Hash[referential.routes.where('opposite_route_id is not null').pluck(:id, :opposite_route_id)] +    end +      referential_routing_constraint_zones_new_ids = {}      new.switch do +      route_ids_mapping = {} +        referential_routes.each do |route|          existing_route = new.routes.find_by line_id: route.line_id, checksum: route.checksum          if existing_route +          route_ids_mapping[route.id] = existing_route.id            existing_route.merge_metadata_from route          else            objectid = Chouette::Route.where(objectid: route.objectid).exists? ? nil : route.objectid @@ -159,7 +166,7 @@ class Merge < ApplicationModel              objectid: objectid,              # line_id is the same              # all other primary must be changed -            opposite_route_id: nil #FIXME +            opposite_route_id: nil # merged after            )            new_route = new.routes.build attributes @@ -179,6 +186,8 @@ class Merge < ApplicationModel            # We need to create StopPoints to known new primary keys            new_route.save! +          route_ids_mapping[route.id] = new_route.id +            old_stop_point_ids = route_stop_points.sort_by(&:position).map(&:id)            new_stop_point_ids = new_route.stop_points.sort_by(&:position).map(&:id) @@ -225,6 +234,20 @@ class Merge < ApplicationModel            end          end        end + +      referential_route_opposite_route_ids.each do |route_id, opposite_route_id| +        new_route_id = route_ids_mapping[route_id] +        new_opposite_route_id = route_ids_mapping[opposite_route_id] + +        new_route = nil +        if new_route_id && new_opposite_route_id +          if new_route = new.routes.find_by(id: new_route_id) +            new_route.update_column :opposite_route_id, new_opposite_route_id +          end +        end + +        Rails.logger.warn "Can't merge opposite route for Route #{route_id}" unless new_route +      end      end      # JourneyPatterns diff --git a/app/models/simple_importer.rb b/app/models/simple_importer.rb index 4cfe90cff..d47ff6a92 100644 --- a/app/models/simple_importer.rb +++ b/app/models/simple_importer.rb @@ -42,8 +42,10 @@ class SimpleImporter < SimpleInterface    end    def dump_csv_from_context -    dir = context[:logs_output_dir] || "log/importers" -    filepath = File.join dir, "#{self.configuration_name}_#{Time.now.strftime "%y%m%d%H%M"}.csv" +    dir = @output_dir +    FileUtils.mkdir_p dir + +    filepath = File.join dir, "#{self.configuration_name}_#{Time.now.strftime "%y%m%d%H%M"}_dump.csv"      # for some reason, context[:csv].to_csv does not work      CSV.open(filepath, 'w') do |csv|        header = true @@ -131,14 +133,16 @@ class SimpleImporter < SimpleInterface            @current_attribute = col[:attribute]            val = col[:value]            if val.nil? || val.is_a?(Proc) -            if row.has_key? col.name -              if val.is_a?(Proc) +            if val.is_a?(Proc) +              if row.has_key? col.name                  val = instance_exec(row[col.name], &val)                else -                val = row[col.name] +                val = instance_exec(&val)                end +            elsif row.has_key? col.name +              val = row[col.name]              else -              push_in_journal({event: :column_not_found, message: "Column not found: #{col.name}", kind: :warning}) +              push_in_journal({event: :column_not_found, message: "Column not found: #{col.name || col.attribute}", kind: :warning})                self.status ||= :success_with_warnings              end            end diff --git a/app/models/simple_interface.rb b/app/models/simple_interface.rb index 7b04a07df..d5feafb07 100644 --- a/app/models/simple_interface.rb +++ b/app/models/simple_interface.rb @@ -97,13 +97,14 @@ class SimpleInterface < ApplicationModel    def write_output_to_csv      cols = %i(line kind event message error) -    if self.journal.size > 0 && self.journal.first[:row].present? +    journal = self.journal && self.journal.map(&:symbolize_keys) +    if journal && journal.size > 0 && journal.first[:row].present?        log "Writing output log"        FileUtils.mkdir_p @output_dir -      keys = self.journal.first[:row].map(&:first) +      keys = journal.first[:row].map(&:first)        CSV.open(output_filepath, "w") do |csv|          csv << cols + keys -        self.journal.each do |j| +        journal.each do |j|            csv << cols.map{|c| j[c]} + j[:row].map(&:last)          end        end diff --git a/app/models/simple_interfaces_group.rb b/app/models/simple_interfaces_group.rb index 808be6570..1e13bd0b5 100644 --- a/app/models/simple_interfaces_group.rb +++ b/app/models/simple_interfaces_group.rb @@ -30,7 +30,9 @@ class SimpleInterfacesGroup      name = "### #{self.name} ###"      centered_name = " " * ([width - name.size, 0].max / 2) + name -    banner = [centered_name, ""] +    banner = [centered_name] +    banner << "Output to: #{shared_options[:output_dir]}" if shared_options && shared_options[:output_dir] +    banner << ""      banner << @interfaces.each_with_index.map do |interface, i|        if interface[:interface].status.present?          SimpleInterface.colorize interface[:name], SimpleInterface.status_color(interface[:interface].status) diff --git a/app/views/companies/show.html.slim b/app/views/companies/show.html.slim index 8960b92dd..6335d88da 100644 --- a/app/views/companies/show.html.slim +++ b/app/views/companies/show.html.slim @@ -6,7 +6,7 @@    .container-fluid      .row        .col-lg-6.col-md-6.col-sm-12.col-xs-12 -        - attributes = { t('id_codif') => @company.try(:objectid).try(:local_id), +        - attributes = { t('id_codif') => @company.get_objectid.try(:short_id),            Chouette::Company.human_attribute_name(:phone) => @company.phone,            Chouette::Company.human_attribute_name(:email) => @company.email,            Chouette::Company.human_attribute_name(:url) => @company.url } diff --git a/app/views/compliance_control_sets/show.html.slim b/app/views/compliance_control_sets/show.html.slim index 729c1ce43..48c03d7c8 100644 --- a/app/views/compliance_control_sets/show.html.slim +++ b/app/views/compliance_control_sets/show.html.slim @@ -15,8 +15,9 @@          = render '/compliance_controls/filters'    / compliance controls without block -  = render_compliance_control_block -  = render_compliance_controls(@direct_compliance_controls) +  - unless params[:q].present? && @direct_compliance_controls.nil? +    = render_compliance_control_block +    = render_compliance_controls(@direct_compliance_controls)    / compliance controls with block    - if params[:q] && params[:q][:compliance_control_block_id_eq_any].try(:present?) diff --git a/app/views/dashboards/_dashboard.html.slim b/app/views/dashboards/_dashboard.html.slim index ce869ee4a..18105041a 100644 --- a/app/views/dashboards/_dashboard.html.slim +++ b/app/views/dashboards/_dashboard.html.slim @@ -6,6 +6,24 @@            h3.panel-title.with_actions              div                = link_to t('dashboards.workbench.title', organisation: workbench.organisation.name), workbench_path(workbench) +              span.badge.ml-xs = workbench.output.referentials.count if workbench.output.referentials.present? + +            div +              = link_to '', workbench_path(workbench), class: ' fa fa-chevron-right pull-right', title: t('workbenches.index.offers.see') + +        - if workbench.output.referentials.present? +          .list-group +            - workbench.output.referentials.limit(5).each do |referential| +              = link_to referential.name, referential_path(referential), class: 'list-group-item' +        - else +          .panel-body +            em.small.text-muted = t('workbenches.index.offers.no_content') + +      .panel.panel-default +        .panel-heading +          h3.panel-title.with_actions +            div +              = link_to t('dashboards.workbench.title', organisation: workbench.organisation.name), workbench_path(workbench)                span.badge.ml-xs = workbench.all_referentials.uniq.count if workbench.all_referentials.present?              div diff --git a/app/views/devise/invitations/edit.html.slim b/app/views/devise/invitations/edit.html.slim index 7a22146c0..20c2f15c8 100644 --- a/app/views/devise/invitations/edit.html.slim +++ b/app/views/devise/invitations/edit.html.slim @@ -1,6 +1,5 @@  / PageHeader - -- content_for :page_header_title, t('.title') +- content_for :page_header_title, t('devise.registrations.edit.title')  / PageContent  .page_content @@ -16,4 +15,4 @@                  = form.input :password, as: :password                  = form.input :password_confirmation, as: :password -            = form.button :submit, value: t('devise.invitations.edit.submit_button'), class: 'btn-info btn-default formSubmitr', form: 'invitation_form' +            = form.button :submit, value: t('actions.submit'), class: 'btn-info btn-default formSubmitr', form: 'invitation_form' diff --git a/app/views/devise/invitations/new.html.slim b/app/views/devise/invitations/new.html.slim index 87bfbf750..90f086c2b 100644 --- a/app/views/devise/invitations/new.html.slim +++ b/app/views/devise/invitations/new.html.slim @@ -1,10 +1,15 @@ -h2 = t('devise.invitations.new.header') +- content_for :page_header_title, t('devise.registrations.new.title') -= simple_form_for resource, as: resource_name, :url => invitation_path(resource_name), :html => {:method => :post, class: "form-horizontal"} do |form| -  = form.input :organisation_id, :as => :hidden, input_html: { :value => current_organisation.id } +/ PageContent +.page_content +  .container-fluid +    .row +      .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1 +        = simple_form_for resource, as: resource_name, :url => invitation_path(resource_name), :html => {:method => :post, class: "form-horizontal", id: "new_user_form"} do |form| +          = form.input :organisation_id, :as => :hidden, input_html: { :value => current_organisation.id } -  - resource.class.invite_key_fields.each do |field| -    = form.input field +          - resource.class.invite_key_fields.each do |field| +            = form.input field -  .form-actions -    = form.button :submit, value: t('devise.invitations.new.submit_button'), class: 'btn-info'
\ No newline at end of file +          .form-actions +            = form.button :submit, value: t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'new_user_form'
\ No newline at end of file diff --git a/app/views/imports/import/_gtf.html.slim b/app/views/imports/import/_gtf.html.slim index 8b92f2e92..e50b45888 100644 --- a/app/views/imports/import/_gtf.html.slim +++ b/app/views/imports/import/_gtf.html.slim @@ -1,7 +1,8 @@ +- breadcrumb :gtfs_import, @workbench, @import +  .row    .col-lg-6.col-md-6.col-sm-12.col-xs-12 -    - metadata = { t('.parent') => link_to(@import.parent.name, [@import.parent.workbench, @import.parent]) } -    - metadata = metadata.update({t('.status') => import_status(@import.status, verbose: true) }) +    - metadata = {t('.status') => import_status(@import.status, verbose: true) }      - metadata = metadata.update({t('.referential') => @import.referential ? link_to(@import.referential.name, [@import.referential]) : "-" })      = definition_list t('metadatas'), metadata @@ -14,7 +15,7 @@      = table_builder_2 @import.resources,        [ \          TableBuilderHelper::Column.new( \ -          name: t('.referential_name'), \ +          name: t('imports.show.referential_name'), \            attribute: 'name', \            sortable: false, \            link_to: lambda do |item| \ diff --git a/app/views/imports/import/_netex.html.slim b/app/views/imports/import/_netex.html.slim index 2f341016a..ab0ed20d7 100644 --- a/app/views/imports/import/_netex.html.slim +++ b/app/views/imports/import/_netex.html.slim @@ -1,8 +1,9 @@ +- breadcrumb :netex_import, @workbench, @import +  .row    .col-lg-6.col-md-6.col-sm-12.col-xs-12 -    - metadata = { t('.parent') => link_to(@import.parent.name, [@import.parent.workbench, @import.parent]) } -    - metadata = metadata.update({t('.status') => import_status(@import.status, verbose: true) }) -    - metadata = metadata.update({t('.referential') => @import.referential ? link_to(@import.referential.name, [@import.referential]) : "-" }) +    - metadata = {Import::Base.tmf(:status) => import_status(@import.status, verbose: true) } +    - metadata = metadata.update({Import::Base.tmf(:referential) => @import.referential ? link_to(@import.referential.name, [@import.referential]) : "-" })      = definition_list t('metadatas'), metadata  .col-lg-12 @@ -11,9 +12,9 @@  - if @import.resources.present?    .col-lg-12 -    h2 = t('.table_title') +    h2 = t('imports.show.netex.table_title')    .col-lg-12 -    = t('.table_explanation') +    = t('imports.show.netex.table_explanation')    .col-lg-12      = table_builder_2 @import.resources.where(resource_type: :file),        [ \ @@ -28,12 +29,12 @@            sortable: false, \          ), \          TableBuilderHelper::Column.new( \ -          name: 'Résultat des tests' , \ +          name: t('imports.show.table.test_results') , \            attribute: Proc.new { |n| I18n.t('import_resources.index.metrics', n.metrics.deep_symbolize_keys) }, \            sortable: false, \          ), \          TableBuilderHelper::Column.new( \ -          name: 'Téléchargement' , \ +          name: t('imports.show.table.download') , \            attribute: Proc.new { |n| '<i class="fa fa-download" aria-hidden="true"></i>'.html_safe }, \            sortable: false, \            link_to: lambda do |import_resource| \ diff --git a/app/views/imports/import/_workbench.html.slim b/app/views/imports/import/_workbench.html.slim index e41ceb0f0..cbdf604c2 100644 --- a/app/views/imports/import/_workbench.html.slim +++ b/app/views/imports/import/_workbench.html.slim @@ -1,7 +1,9 @@ +- breadcrumb :import, @workbench, @import +  .row    .col-lg-6.col-md-6.col-sm-12.col-xs-12 -    - metadata = { t('.data_recovery') => '-', t('.filename') => @import.try(:file_identifier)} -    - metadata = metadata.update({t('.status') => import_status(@import.status, verbose: true) }) +    - metadata = { t('.data_recovery') => '-', t('imports.show.filename') => @import.try(:file_identifier)} +    - metadata = metadata.update({Import::Base.tmf(:status) => import_status(@import.status, verbose: true) })      = definition_list t('metadatas'), metadata  .col-lg-12 @@ -25,7 +27,7 @@ ruby:      = table_builder_2 @import.resources,        [ \          TableBuilderHelper::Column.new( \ -          name: t('.referential_name'), \ +          name: t('imports.show.referential_name'), \            attribute: 'name', \            sortable: false, \            link_to: lambda do |item| \ diff --git a/app/views/imports/show.html.slim b/app/views/imports/show.html.slim index 10552129d..fb83e9a06 100644 --- a/app/views/imports/show.html.slim +++ b/app/views/imports/show.html.slim @@ -1,5 +1,3 @@ -- breadcrumb :import, @workbench, @import -  - page_header_content_for @import  .page_content diff --git a/app/views/layouts/navigation/_main_nav_left_content.html.slim b/app/views/layouts/navigation/_main_nav_left_content.html.slim index 889f8f944..547c6fae7 100644 --- a/app/views/layouts/navigation/_main_nav_left_content.html.slim +++ b/app/views/layouts/navigation/_main_nav_left_content.html.slim @@ -2,69 +2,54 @@  - current_organisation.workbenches.each do |workbench|    #menu-items.panel-group      .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miOne', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.current_offer.other') - -      #miOne.panel-collapse.collapse -        .list-group -          = link_to root_path, class: "list-group-item" do -            span = t('layouts.navbar.dashboard') -          = link_to workbench_output_path(workbench), class: 'list-group-item' do -            span = t('layouts.navbar.workbench_outputs.organisation') -          = link_to '#', class: 'list-group-item disabled' do -            span = t('layouts.navbar.workbench_outputs.workgroup') -          - if policy(workbench.workgroup).edit? -            = link_to [:edit, workbench.workgroup], class: 'list-group-item' do -              span = t('layouts.navbar.workbench_outputs.edit_workgroup') +      = main_nav_menu_item 'layouts.navbar.current_offer.other'.t do +        = link_to root_path, class: "list-group-item" do +          span = 'layouts.navbar.dashboard'.t +        = link_to workbench_output_path(workbench), class: 'list-group-item' do +          span = 'layouts.navbar.workbench_outputs.organisation'.t +        = link_to '#', class: 'list-group-item disabled' do +          span = 'layouts.navbar.workbench_outputs.workgroup'.t +        - if policy(workbench.workgroup).edit? +          = link_to [:edit, workbench.workgroup], class: 'list-group-item' do +            span = 'layouts.navbar.workbench_outputs.edit_workgroup'.t      .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miTwo', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            - t('activerecord.models.workbench.one').capitalize - -      #miTwo.panel-collapse.collapse -        .list-group -          = link_to workbench_path(workbench), class: "list-group-item" do -            span = t('activerecord.models.referential.other').capitalize -          = link_to workbench_imports_path(workbench), class: "list-group-item" do -            span = t('activerecord.models.import.other').capitalize -          = link_to workbench_exports_path(workbench), class: "list-group-item" do -            span = t('activerecord.models.export.other').capitalize -          = link_to workgroup_calendars_path(workbench.workgroup), class: 'list-group-item' do -            span = t('activerecord.models.calendar.other').capitalize -          = link_to workbench_compliance_check_sets_path(workbench), class: 'list-group-item' do -            span = t('activerecord.models.compliance_check_set.other').capitalize -          = link_to compliance_control_sets_path, class: 'list-group-item' do -            span = t('activerecord.models.compliance_control_set.other').capitalize -          - if policy(workbench).edit? -            = link_to [:edit, workbench], class: 'list-group-item' do -              span = t('workbenches.edit.link') +      = main_nav_menu_item 'activerecord.models.workbench.one'.t.capitalize do +        = link_to workbench_path(workbench), class: "list-group-item" do +          span = 'activerecord.models.referential.other'.t.capitalize +        = link_to workbench_imports_path(workbench), class: "list-group-item" do +          span = 'activerecord.models.import.other'.t.capitalize +        = link_to workbench_exports_path(workbench), class: "list-group-item" do +          span = 'activerecord.models.export.other'.t.capitalize +        = link_to workgroup_calendars_path(workbench.workgroup), class: 'list-group-item' do +          span = 'activerecord.models.calendar.other'.t.capitalize +        = link_to workbench_compliance_check_sets_path(workbench), class: 'list-group-item' do +          span = 'activerecord.models.compliance_check_set.other'.t.capitalize +        = link_to compliance_control_sets_path, class: 'list-group-item' do +          span = 'activerecord.models.compliance_control_set.other'.t.capitalize +        - if policy(workbench).edit? +          = link_to [:edit, workbench], class: 'list-group-item' do +            span = 'workbenches.edit.link'.t      .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miFour', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.line_referential') - -      #miFour.panel-collapse.collapse -        .list-group -          = link_to line_referential_lines_path(workbench.line_referential), class: "list-group-item" do -            span = Chouette::Line.t.capitalize -          = link_to line_referential_networks_path(workbench.line_referential), class: "list-group-item" do -            span = Chouette::Network.t.capitalize -          = link_to line_referential_companies_path(workbench.line_referential), class: "list-group-item" do -            span = Chouette::Company.t.capitalize +      = main_nav_menu_item 'layouts.navbar.line_referential'.t do +        = link_to line_referential_lines_path(workbench.line_referential), class: "list-group-item" do +          span = Chouette::Line.t.capitalize +        = link_to line_referential_networks_path(workbench.line_referential), class: "list-group-item" do +          span = Chouette::Network.t.capitalize +        = link_to line_referential_companies_path(workbench.line_referential), class: "list-group-item" do +          span = Chouette::Company.t.capitalize      .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miFive', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.stop_area_referential') +      = main_nav_menu_item 'layouts.navbar.stop_area_referential'.t do +        = link_to stop_area_referential_stop_areas_path(workbench.stop_area_referential), class: "list-group-item" do +          span = Chouette::StopArea.t.capitalize -      #miFive.panel-collapse.collapse -        .list-group -          = link_to stop_area_referential_stop_areas_path(workbench.stop_area_referential), class: "list-group-item" do -            span = Chouette::StopArea.t.capitalize +    .menu-item.panel +      = main_nav_menu_item 'layouts.navbar.configuration'.t do +        - if policy(workbench).edit? +          = link_to [:edit, workbench], class: 'list-group-item' do +            span = 'layouts.navbar.workbench_configuration'.t +        - if policy(workbench.workgroup).edit? +          = link_to [:edit, workbench.workgroup], class: 'list-group-item' do +            span = 'layouts.navbar.workgroup_configuration'.t diff --git a/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim b/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim index a7bb3f511..950c23580 100644 --- a/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim +++ b/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim @@ -1,101 +1,68 @@  - current_organisation.workbenches.each do |workbench|    #menu-items.panel-group -    .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miOne', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.current_offer.other') +    = main_nav_menu_item 'layouts.navbar.current_offer.other'.t do +      = link_to root_path, class: "list-group-item" do +        span = t('layouts.navbar.dashboard') +      = link_to workbench_output_path(workbench), class: 'list-group-item' do +        span = t('layouts.navbar.workbench_outputs.organisation') +      = link_to '#', class: 'list-group-item disabled' do +        span = t('layouts.navbar.workbench_outputs.workgroup') -      #miOne.panel-collapse.collapse -        .list-group -          = link_to root_path, class: "list-group-item" do -            span = t('layouts.navbar.dashboard') -          = link_to workbench_output_path(workbench), class: 'list-group-item' do -            span = t('layouts.navbar.workbench_outputs.organisation') -          = link_to '#', class: 'list-group-item disabled' do -            span = t('layouts.navbar.workbench_outputs.workgroup') -          - if policy(workbench.workgroup).edit? -            = link_to [:edit, workbench.workgroup], class: 'list-group-item' do -              span = t('layouts.navbar.workbench_outputs.edit_workgroup') +    = main_nav_menu_item 'activerecord.models.workbench.one'.t.capitalize do +      = link_to workbench_path(workbench), class: "list-group-item" do +        span = t('activerecord.models.referential.other').capitalize +      = link_to workbench_imports_path(workbench), class: "list-group-item" do +        span = t('activerecord.models.import.other').capitalize +      = link_to workbench_exports_path(workbench), class: "list-group-item" do +        span = t('activerecord.models.export.other').capitalize +      = link_to workgroup_calendars_path(workbench.workgroup), class: 'list-group-item' do +        span = t('activerecord.models.calendar.other').capitalize +      = link_to workbench_compliance_check_sets_path(workbench), class: 'list-group-item' do +        span = t('activerecord.models.compliance_check_set.other').capitalize +      = link_to compliance_control_sets_path, class: 'list-group-item' do +        span = t('activerecord.models.compliance_control_set.other').capitalize -    .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miTwo', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            - t('activerecord.models.workbench.one').capitalize +    = main_nav_menu_item 'layouts.navbar.line_referential'.t do +      = link_to line_referential_path(workbench.line_referential), class: "list-group-item" do +        span = t('layouts.navbar.sync_ilico') +      = link_to line_referential_lines_path(workbench.line_referential), class: "list-group-item" do +        span = Chouette::Line.t.capitalize +      = link_to line_referential_networks_path(workbench.line_referential), class: "list-group-item" do +        span = Chouette::Network.t.capitalize +      = link_to line_referential_companies_path(workbench.line_referential), class: "list-group-item" do +        span = Chouette::Company.t.capitalize -      #miTwo.panel-collapse.collapse -        .list-group -          = link_to workbench_path(workbench), class: "list-group-item" do -            span = t('activerecord.models.referential.other').capitalize -          = link_to workbench_imports_path(workbench), class: "list-group-item" do -            span = t('activerecord.models.import.other').capitalize -          = link_to workbench_exports_path(workbench), class: "list-group-item" do -            span = t('activerecord.models.export.other').capitalize -          = link_to workgroup_calendars_path(workbench.workgroup), class: 'list-group-item' do -            span = t('activerecord.models.calendar.other').capitalize -          = link_to workbench_compliance_check_sets_path(workbench), class: 'list-group-item' do -            span = t('activerecord.models.compliance_check_set.other').capitalize -          = link_to compliance_control_sets_path, class: 'list-group-item' do -            span = t('activerecord.models.compliance_control_set.other').capitalize -          - if policy(workbench).edit? -            = link_to [:edit, workbench], class: 'list-group-item' do -              span = t('workbenches.edit.link') +    = main_nav_menu_item 'layouts.navbar.stop_area_referential'.t do +      = link_to stop_area_referential_path(workbench.stop_area_referential), class: "list-group-item" do +        span = t('layouts.navbar.sync_icar') +      = link_to stop_area_referential_stop_areas_path(workbench.stop_area_referential), class: "list-group-item" do +        span = Chouette::StopArea.t.capitalize -    .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miFour', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.line_referential') +    = main_nav_menu_item 'layouts.navbar.configuration'.t do +      - if policy(workbench).edit? +        = link_to [:edit, workbench], class: 'list-group-item' do +          span = t('layouts.navbar.workbench_configuration') +      - if policy(workbench.workgroup).edit? +        = link_to [:edit, workbench.workgroup], class: 'list-group-item' do +          span = t('layouts.navbar.workgroup_configuration') -      #miFour.panel-collapse.collapse -        .list-group -          = link_to line_referential_path(workbench.line_referential), class: "list-group-item" do -            span = t('layouts.navbar.sync_ilico') -          = link_to line_referential_lines_path(workbench.line_referential), class: "list-group-item" do -            span = Chouette::Line.t.capitalize -          = link_to line_referential_networks_path(workbench.line_referential), class: "list-group-item" do -            span = Chouette::Network.t.capitalize -          = link_to line_referential_companies_path(workbench.line_referential), class: "list-group-item" do -            span = Chouette::Company.t.capitalize - -    .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miFive', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.stop_area_referential') - -      #miFive.panel-collapse.collapse -        .list-group -          = link_to stop_area_referential_path(workbench.stop_area_referential), class: "list-group-item" do -            span = t('layouts.navbar.sync_icar') -          = link_to stop_area_referential_stop_areas_path(workbench.stop_area_referential), class: "list-group-item" do -            span = Chouette::StopArea.t.capitalize - -    .menu-item.panel -      .panel-heading -        h4.panel-title -          = link_to '#miSix', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do -            = t('layouts.navbar.tools') - -      #miSix.panel-collapse.collapse -        .list-group -          = link_to Rails.application.config.try(:portal_url), target: '_blank', class: 'list-group-item' do -            span -              span.fa.fa-2x.fa-circle -              = t('layouts.navbar.portal') - -          = link_to Rails.application.config.try(:codifligne_url), target: '_blank', class: 'list-group-item' do -            span -              span.fa.fa-2x.fa-circle -              = t('layouts.navbar.ilico') - -          = link_to Rails.application.config.try(:reflex_url), target: '_blank', class: 'list-group-item' do -            span -              span.fa.fa-2x.fa-circle -              = t('layouts.navbar.icar') - -          = link_to '#', target: '_blank', class: 'list-group-item' do -            span -              span.fa.fa-2x.fa-circle -              = t('layouts.navbar.support') +    = main_nav_menu_item 'layouts.navbar.tools'.t do +      = link_to Rails.application.config.try(:portal_url), target: '_blank', class: 'list-group-item' do +        span +          span.fa.fa-2x.fa-circle +          = t('layouts.navbar.portal') +       +      = link_to Rails.application.config.try(:codifligne_url), target: '_blank', class: 'list-group-item' do +        span +          span.fa.fa-2x.fa-circle +          = t('layouts.navbar.ilico') +       +      = link_to Rails.application.config.try(:reflex_url), target: '_blank', class: 'list-group-item' do +        span +          span.fa.fa-2x.fa-circle +          = t('layouts.navbar.icar') +       +      = link_to '#', target: '_blank', class: 'list-group-item' do +        span +          span.fa.fa-2x.fa-circle +        = t('layouts.navbar.support') diff --git a/app/views/lines/_form.html.slim b/app/views/lines/_form.html.slim index 909d6512e..4623abf8a 100644 --- a/app/views/lines/_form.html.slim +++ b/app/views/lines/_form.html.slim @@ -4,7 +4,7 @@        = f.input :name        = f.input :network_id, as: :select, :collection => @line_referential.networks, include_blank: false        = f.input :company_id, as: :select, :collection => @line_referential.companies, include_blank: true -      = f.input :secondary_company_ids, :collection => @line_referential.companies, include_blank: false, input_html: { multiple: true, 'data-select2ed': true }, label: t('activerecord.attributes.line.secondary_company') +      = f.input :secondary_company_ids, :collection => @line_referential.companies, include_blank: false, input_html: { multiple: true, 'data-select2ed': true }, label: Chouette::Line.tmf(:secondary_companies)        = f.input :published_name        = f.input :registration_number        = f.input :number diff --git a/app/views/referential_stop_areas/show.html.slim b/app/views/referential_stop_areas/show.html.slim index beee0383f..06096bbaa 100644 --- a/app/views/referential_stop_areas/show.html.slim +++ b/app/views/referential_stop_areas/show.html.slim @@ -7,7 +7,7 @@        .col-lg-6.col-md-6.col-sm-12.col-xs-12          = definition_list t('metadatas'),            { t('id_reflex') => @stop_area.try(:user_objectid), -            Chouette::StopArea.tmf(:status) => stop_area_status(@stop_area), +            Chouette::StopArea.tmf(:status) => stop_area_status(@stop_area.status),              Chouette::StopArea.tmf(:comment) => @stop_area.try(:comment),              Chouette::StopArea.tmf(:stop_area_type) => t("area_types.label.#{@stop_area.stop_area_type}"),              Chouette::StopArea.tmf(:registration_number) => @stop_area.registration_number, diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim index aea824a89..615913faa 100644 --- a/app/views/routes/show.html.slim +++ b/app/views/routes/show.html.slim @@ -30,13 +30,13 @@                  key: :name, \                  attribute: Proc.new { |s| content_tag :span, s.stop_area&.name, class: s.stop_area&.area_type }, \                  link_to: lambda do |stop_point| \ -                  referential_stop_area_path(@referential, stop_point.stop_area) \ +                  stop_area_referential_stop_area_path(stop_point.stop_area.referential, stop_point.stop_area) \                  end \                ), \                TableBuilderHelper::Column.new( \                  key: :status, \                  name: Chouette::StopArea.tmf('status'), \ -                attribute: Proc.new { |s| stop_area_status(s.try(:stop_area)) } \ +                attribute: Proc.new { |s| stop_area_status(s.try(:stop_area).try(:status) ) } \                ), \                TableBuilderHelper::Column.new( \                  key: :zip_code, \ diff --git a/app/views/routing_constraint_zones/index.html.slim b/app/views/routing_constraint_zones/index.html.slim index 7e9fb12a3..a804de449 100644 --- a/app/views/routing_constraint_zones/index.html.slim +++ b/app/views/routing_constraint_zones/index.html.slim @@ -14,7 +14,7 @@              [ \                TableBuilderHelper::Column.new( \                  name: t('objectid'), \ -                attribute: Proc.new { |n| n.get_objectid.local_id }, \ +                attribute: Proc.new { |n| n.get_objectid.short_id }, \                  sortable: false \                ), \                TableBuilderHelper::Column.new( \ @@ -39,6 +39,8 @@              ],              links: [:show],              cls: 'table has-filter has-search' +           +          = new_pagination @routing_constraint_zones, 'pull-right'      - unless @routing_constraint_zones.any?        .row.mt-xs diff --git a/app/views/routing_constraint_zones/show.html.slim b/app/views/routing_constraint_zones/show.html.slim index 8c8e9b17a..55c952ae6 100644 --- a/app/views/routing_constraint_zones/show.html.slim +++ b/app/views/routing_constraint_zones/show.html.slim @@ -16,15 +16,15 @@          = table_builder_2 @routing_constraint_zone.route.stop_points,            [ \              TableBuilderHelper::Column.new( \ -              name: "Arrêts de l'itinéraire", \ +              name: t('.route_stop_points'), \                attribute: 'name', \                link_to: lambda do |stop_point| \                  referential_stop_area_path(@referential, stop_point.stop_area) \                end \              ),              TableBuilderHelper::Column.new( \ -              name: "Arrêts inclus dans l'ITL", \ -              attribute: Proc.new{ |rsp| (@routing_constraint_zone.stop_point_ids.include? rsp.id) ? 'Oui' : 'Non' } \ +              name: t('.stop_points'), \ +              attribute: Proc.new{ |rsp| (@routing_constraint_zone.stop_point_ids.include? rsp.id) ? t('yes') : t('no') } \              ) \            ],            sortable: false, diff --git a/app/views/stop_areas/_filters.html.slim b/app/views/stop_areas/_filters.html.slim index cca48bb17..88ed6a772 100644 --- a/app/views/stop_areas/_filters.html.slim +++ b/app/views/stop_areas/_filters.html.slim @@ -9,38 +9,16 @@            span.fa.fa-search    .ffg-row -    = f.input :zip_code_cont, placeholder: t('.zip_code'), label: Chouette::StopArea.human_attribute_name(:zip_code), required: false, wrapper_html: {class: filter_item_class(params[:q], :zip_code_cont)} -    = f.input :city_name_cont, placeholder: t('.city_name'), label: Chouette::StopArea.human_attribute_name(:city_name), required: false, wrapper_html: {class: filter_item_class(params[:q], :city_name_cont)} +    = f.input :zip_code_cont, placeholder: t('.zip_code'), label: Chouette::StopArea.tmf('zip_code'), required: false, wrapper_html: {class: filter_item_class(params[:q], :zip_code_cont)} +    = f.input :city_name_cont, placeholder: t('.city_name'), label: Chouette::StopArea.tmf('city_name'), required: false, wrapper_html: {class: filter_item_class(params[:q], :city_name_cont)}      .form-group.togglable class=filter_item_class(params[:q], :area_type_eq_any) -      = f.label Chouette::StopArea.human_attribute_name(:area_type), required: false, class: 'control-label' +      = f.label Chouette::StopArea.tmf('area_type'), required: false, class: 'control-label'        = f.input :area_type_eq_any, checked: params[:q] && params[:q][:area_type_eq_any], collection: Chouette::AreaType.options, as: :check_boxes, label: false, label_method: lambda{|w| ("<span>" + w[0] + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' } -       -    .form-group.togglable class=filter_item_class(params[:q], :status) + +    .form-group.togglable class=filter_item_class(params[:q], :by_status)        = f.label Chouette::StopArea.tmf('status'), required: false, class: 'control-label' -      .form-group.checkbox_list -        = f.simple_fields_for :status do |p| -          = p.input :in_creation, -            label: ("<span>#{t('activerecord.attributes.stop_area.in_creation')}<span class='fa fa-pencil text-info'></span></span>").html_safe, -            as: :boolean, -            wrapper_html: { class: 'checkbox-wrapper' }, -            checked_value: true, -            unchecked_value: false, -            input_html: { checked: @status.try(:[], :in_creation) } -          = p.input :confirmed, -            label: ("<span>#{t('activerecord.attributes.stop_area.confirmed')}<span class='fa fa-check-circle text-success'></span></span>").html_safe, -            as: :boolean, -            wrapper_html: { class: 'checkbox-wrapper' }, -            checked_value: true, -            unchecked_value: false, -            input_html: { checked: @status.try(:[], :confirmed) } -          = p.input :deactivated, -            label: ("<span>#{t('activerecord.attributes.stop_area.deleted')}<span class='fa fa-exclamation-circle text-danger'></span></span>").html_safe, -            as: :boolean, -            wrapper_html: { class: 'checkbox-wrapper' }, -            checked_value: true, -            unchecked_value: false, -            input_html: { checked: @status.try(:[], :deactivated) } +      = f.input :by_status, checked: params[:q] && params[:q][:by_status], collection: [:in_creation, :confirmed, :deactivated], as: :check_boxes, label: false, label_method: lambda{|w| ("<span>" + stop_area_status(w) + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }    .actions      = link_to t('actions.erase'), @workbench, class: 'btn btn-link' diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim index 62b873c36..e5ca82ee2 100644 --- a/app/views/stop_areas/index.html.slim +++ b/app/views/stop_areas/index.html.slim @@ -33,7 +33,7 @@                ), \                TableBuilderHelper::Column.new( \                  key: :status, \ -                attribute: Proc.new { |s| stop_area_status(s) } \ +                attribute: Proc.new { |s| stop_area_status(s.status) } \                ), \                TableBuilderHelper::Column.new( \                  key: :zip_code, \ diff --git a/app/views/stop_areas/show.html.slim b/app/views/stop_areas/show.html.slim index c10d22bfb..c1965c161 100644 --- a/app/views/stop_areas/show.html.slim +++ b/app/views/stop_areas/show.html.slim @@ -21,7 +21,7 @@              Chouette::StopArea.tmf('city_name') => @stop_area.city_name,              Chouette::StopArea.tmf('country_code') => @stop_area.country_code.presence || '-',              Chouette::StopArea.tmf('time_zone') => @stop_area.time_zone.presence || '-', -            Chouette::StopArea.tmf('status') => stop_area_status(@stop_area), +            Chouette::StopArea.tmf('status') => stop_area_status(@stop_area.status),              Chouette::StopArea.tmf('comment') => @stop_area.try(:comment),              })          - @stop_area.custom_fields.each do |code, field| diff --git a/app/views/workbenches/_form.html.slim b/app/views/workbenches/_form.html.slim index 819346c35..c7b6fd4f3 100644 --- a/app/views/workbenches/_form.html.slim +++ b/app/views/workbenches/_form.html.slim @@ -1,4 +1,6 @@ -= simple_form_for @workbench, html: { class: 'form-horizontal', id: 'workbench_form' }, wrapper: :horizontal_form do |f| += title_tag t('activerecord.models.compliance_control_set.other') + += simple_form_for @workbench, html: { class: 'form-horizontal', id: 'workbench_form' }, wrapper: :horizontal_form, title: "prout" do |f|    .row      .col-lg-12        = f.fields_for :compliance_control_set_ids do |ff| diff --git a/app/views/workbenches/edit.html.slim b/app/views/workbenches/edit.html.slim index 893024490..0774610e1 100644 --- a/app/views/workbenches/edit.html.slim +++ b/app/views/workbenches/edit.html.slim @@ -1,4 +1,4 @@ -- breadcrumb @workbench +- breadcrumb :workbench_configure, @workbench  - page_header_content_for @workbench  .page_content diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index 213c9e5f2..979e7ff04 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -6,8 +6,8 @@        - if policy(Workbench).update?          = link_to t('workbenches.actions.configure'), edit_workbench_path(@workbench), class: 'btn btn-primary'        - if policy(Referential).create? -        = link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary' -        = link_to t('actions.export'), workbench_exports_path(@workbench), class: 'btn btn-primary' +        = link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary' unless @workbench.workgroup.import_types.empty? +        = link_to t('actions.export'), workbench_exports_path(@workbench), class: 'btn btn-primary' unless @workbench.workgroup.export_types.empty?          = link_to t('actions.add'), new_workbench_referential_path(@workbench), class: 'btn btn-primary'        = link_to t('workbenches.actions.show_output'), workbench_output_path(@workbench), class: 'btn btn-primary' diff --git a/app/views/workgroups/_form.html.slim b/app/views/workgroups/_form.html.slim index 7245cfc40..52d1faca8 100644 --- a/app/views/workgroups/_form.html.slim +++ b/app/views/workgroups/_form.html.slim @@ -1,3 +1,5 @@ += title_tag t('activerecord.models.compliance_control_set.other') +  = simple_form_for @workgroup, html: { class: 'form-horizontal', id: 'workgroup_form' }, wrapper: :horizontal_form do |f|    table.table      thead diff --git a/app/workers/route_way_cost_worker.rb b/app/workers/route_way_cost_worker.rb index b62416c3d..5d8ed52f9 100644 --- a/app/workers/route_way_cost_worker.rb +++ b/app/workers/route_way_cost_worker.rb @@ -3,7 +3,11 @@ class RouteWayCostWorker    def perform(referential_id, route_id)      Referential.find(referential_id).switch -    route = Chouette::Route.find(route_id) +    route = Chouette::Route.where(id: route_id).last +    unless route.present? +      Rails.logger.warn "RouteWayCost called on missing route ##{route_id}".red +      return +    end      # Prevent recursive worker spawning since this call updates the      # `costs` field of the route. diff --git a/config/breadcrumbs.rb b/config/breadcrumbs.rb index babaa2c8c..28a117d52 100644 --- a/config/breadcrumbs.rb +++ b/config/breadcrumbs.rb @@ -6,6 +6,11 @@ crumb :workbench do |workbench|    link workbench.name, workbench_path(workbench)  end +crumb :workbench_configure do |workbench| +  link I18n.t('workbenches.edit.title'), edit_workbench_path(workbench) +  parent :workbench, workbench +end +  crumb :workbench_output do |workbench|    link I18n.t('workbench_outputs.show.title'), workbench_output_path(workbench)    parent :workbench, mutual_workbench(workbench) @@ -121,6 +126,16 @@ crumb :import do |workbench, import|    parent :imports, workbench  end +crumb :netex_import do |workbench, netex_import| +  link breadcrumb_name(netex_import), workbench_import_path(workbench, netex_import) +  parent :import, workbench, netex_import.parent +end + +crumb :gtfs_import do |workbench, gtfs_import| +  link breadcrumb_name(gtfs_import), workbench_import_path(workbench, gtfs_import) +  parent :import, workbench, gtfs_import.parent +end +  crumb :export do |workbench, export|    link breadcrumb_name(export), workbench_export_path(workbench, export)    parent :exports, workbench @@ -160,7 +175,6 @@ end  crumb :stop_areas do |stop_area_referential|    link I18n.t('stop_areas.index.title'), stop_area_referential_stop_areas_path(stop_area_referential) -  parent :stop_area_referential, stop_area_referential  end  crumb :stop_area do |stop_area_referential, stop_area| @@ -273,7 +287,7 @@ crumb :vehicle_journeys do |referential, route|  end  crumb :workgroup do |w| -  link I18n.t('layouts.navbar.workbench_outputs.edit_workgroup') +  link I18n.t('workgroups.edit.title')  end  # crumb :compliance_controls do|compliance_control_sets| diff --git a/config/database.yml.docker b/config/database.yml.docker index f49b22b87..29d198604 100644 --- a/config/database.yml.docker +++ b/config/database.yml.docker @@ -6,6 +6,6 @@    port: <%= ENV.fetch 'RAILS_DB_PORT', '5432' %>    schema_search_path: 'public,shared_extensions'    postgis_schema: 'shared_extensions' -  database: <%= ENV.fetch 'RAILS_DB_NAME', 'chouette' %> +  database: <%= ENV.fetch 'RAILS_DB_NAME', 'chouette' %><%= ENV['TEST_ENV_NUMBER'] %>    username: <%= ENV.fetch 'RAILS_DB_USER', 'chouette' %>    password: <%= ENV.fetch 'RAILS_DB_PASSWORD' %> diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml index faf0dcec2..2c48f11a9 100644 --- a/config/locales/actions.en.yml +++ b/config/locales/actions.en.yml @@ -35,3 +35,4 @@ en:    no_result_text: "No Results"    searching_term: "Searching..."    are_you_sure: Are you sure? +  ok: Ok diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml index 9e1a132a7..f02ab2198 100644 --- a/config/locales/actions.fr.yml +++ b/config/locales/actions.fr.yml @@ -35,3 +35,4 @@ fr:    no_result_text: "Aucun résultat"    searching_term: "Recherche en cours..."    are_you_sure: Etes vous sûr ? +  ok: Ok diff --git a/config/locales/companies.en.yml b/config/locales/companies.en.yml index f2b19bc19..8a746f6b7 100644 --- a/config/locales/companies.en.yml +++ b/config/locales/companies.en.yml @@ -6,7 +6,7 @@ en:        new: "Add a new company"        edit: "Edit this company"        destroy: "Remove this company" -      destroy_confirm: "Are you sure you want destroy this company?" +      destroy_confirm: "Are you sure you want to destroy this company?"      new:        title: "Add a new company"      edit: diff --git a/config/locales/import_messages.en.yml b/config/locales/import_messages.en.yml index 27035ba84..211ac426c 100644 --- a/config/locales/import_messages.en.yml +++ b/config/locales/import_messages.en.yml @@ -5,7 +5,7 @@ en:      missing_calendar_in_zip_file: "The folder %{source_filename} lacks a calendar file"      wrong_calendar_in_zip_file: "The calendar file %{source_filename} cannot be parsed, or contains inconsistant data"      referential_creation: "The referential %{referential_name} has not been created because another referential with the same lines and periods already exists" -    referential_creation_missing_lines: "The referential %{referential_name} has not been created because no matching line has been found" +    referential_creation_missing_lines: "The referential %{referential_name} has not been created because a line has not be found in the organization"      1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"      1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"      2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN" diff --git a/config/locales/import_messages.fr.yml b/config/locales/import_messages.fr.yml index a8dd31f8a..c15171ac4 100644 --- a/config/locales/import_messages.fr.yml +++ b/config/locales/import_messages.fr.yml @@ -6,8 +6,7 @@ fr:      wrong_calendar_in_zip_file: "Le calendrier contenu dans %{source_filename} contient des données incorrectes ou incohérentes"      referential_creation: "Le référentiel %{referential_name} n'a pas pu être créé."      referential_creation_overlapping_existing_referential: "Le référentiel %{referential_name} n'a pas pu être créé car un référentiel existe déjà sur les mêmes périodes et lignes: <a href='%{overlapped_url}'>%{overlapped_name}</a>" -    referential_creation_missing_lines: "Le référentiel %{referential_name} n'a pas pu être créé car aucune ligne ne correspond" -    referential_creation_lines_found: "Lignes lues dans le dossier: %{line_objectids}" +    referential_creation_missing_lines: "Le référentiel %{referential_name} n'a pas pu être créé car au moins une ligne n'appartient pas à l'organisation"      gtfs:        agencies:          imported: "%{count} agence(s) importée(s)" diff --git a/config/locales/import_resources.en.yml b/config/locales/import_resources.en.yml index 4b1f9c394..ebb481dcc 100644 --- a/config/locales/import_resources.en.yml +++ b/config/locales/import_resources.en.yml @@ -3,9 +3,7 @@ en:      resources: &resources        index:          title: "NeTEx conformity" -        table_state: "%{lines_imported} line(s) imported on %{lines_in_zipfile} presents in zipfile" -        table_title: "Satus of anlyzed files" -        table_explanation: "When calendriers.xml and/or commun.xml are not imported, then all lines file are not processed." +        table_state: "%{lines_imported} line(s) imported on %{lines_in_zipfile} presents in zip file"          metrics: "%{error_count} errors, %{warning_count} warnings"    import_resources:      <<: *resources diff --git a/config/locales/import_resources.fr.yml b/config/locales/import_resources.fr.yml index 8ddb3fb6b..ca9b6c8e5 100644 --- a/config/locales/import_resources.fr.yml +++ b/config/locales/import_resources.fr.yml @@ -3,8 +3,6 @@ fr:      resources: &resources        table: &table          table_state: "%{lines_imported} ligne(s) importée(s) sur %{lines_in_zipfile} présente(s) dans l'archive" -        table_title: "Etat des fichiers analysés" -        table_explanation: "Dans le cas ou le(s) fichiers calendriers.xml et/ou commun.xml sont dans un état non importé, alors tous les fichiers lignes sont automatiquement dans un état non traité."        index:          <<: *table          title: "Rapport de conformité NeTEx" diff --git a/config/locales/imports.en.yml b/config/locales/imports.en.yml index 344ee05a8..ed34043c5 100644 --- a/config/locales/imports.en.yml +++ b/config/locales/imports.en.yml @@ -33,6 +33,13 @@ en:        organisation_control: Organization control        results: "%{count} validated referential(s) out of %{total} in the file"        summary: Summay of import compliance check sets <span title="Lorem ipsum..." class="fa fa-lg fa-info-circle text-info"></span> +      parent: Parent +      netex: +        table_title: "Satus of anlyzed files" +        table_explanation: "When calendriers.xml and/or commun.xml are not imported, then all lines file are not processed." +      table: +        test_results: Test results +        download: Download      compliance_check_task: "Validate Report"      severities:        info: "Information" @@ -95,6 +102,7 @@ en:          max_distance_for_connection_link: "Max distance for connection link"          ignore_last_word: "ignore last word"          ignore_end_chars: "ignore last chars" +        referential: Referential        import:          <<: *attrs          base: diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml index 870896111..5affd2c0c 100644 --- a/config/locales/imports.fr.yml +++ b/config/locales/imports.fr.yml @@ -33,6 +33,13 @@ fr:        organisation_control: Contrôle organisation        results: "%{count} jeu(x) de données validé(s) sur %{total}"        summary: Bilan des jeux de contrôles d'import <span title="Lorem ipsum..." class="fa fa-lg fa-info-circle text-info"></span> +      parent: Parent +      netex: +        table_title: "Etat des fichiers analysés" +        table_explanation: "Dans le cas ou le(s) fichiers calendriers.xml et/ou commun.xml sont dans un état non importé, alors tous les fichiers lignes sont automatiquement dans un état non traité." +      table: +        test_results: Résultats des tests +        download: Téléchargement      compliance_check_task: "Validation"      severities:        info: "Information" @@ -99,7 +106,7 @@ fr:          max_distance_for_connection_link: "Distance max pour créer les correspondances"          ignore_last_word: "ignorer le dernier mot"          ignore_end_chars: "ignorer les n derniers caractères" - +        referential: Jeu de données        import:          <<: *attrs          base: diff --git a/config/locales/layouts.en.yml b/config/locales/layouts.en.yml index 70e95646e..3f67c5c20 100644 --- a/config/locales/layouts.en.yml +++ b/config/locales/layouts.en.yml @@ -23,7 +23,10 @@ en:        workbench_output:          organisation: Organisation offers          workgroup: Workgroup offers -        edit_workgroup: Application settings +        edit_workgroup: App configuration +      configuration: Settings +      workgroup_configuration:  Application +      workbench_configuration: Workbench        tools: Tools        sync: Synchronization        sync_icar: iCAR synchronization @@ -68,6 +71,7 @@ en:    yesterday: "Yestersday"    edit_periods: "Edit periods"    delete_periods: "Delete periods" +  warning: Warning    attributes:      author: "Edited by"      created_at: "Created at" diff --git a/config/locales/layouts.fr.yml b/config/locales/layouts.fr.yml index 810ede34c..48c1211d4 100644 --- a/config/locales/layouts.fr.yml +++ b/config/locales/layouts.fr.yml @@ -23,7 +23,10 @@ fr:        workbench_outputs:          organisation: Offre de mon organisation          workgroup: Offre du groupe de travail -        edit_workgroup: Paramétrages de l'application +        edit_workgroup: Configuration de l'application +      configuration: Paramétrages +      workgroup_configuration:  Application +      workbench_configuration: Espace de travail        tools: Outils        sync: Synchronisation        sync_icar: Synchronisation iCAR @@ -68,6 +71,7 @@ fr:    yesterday: "Hier"    edit_periods: "Editer Périodes"    delete_periods: "Supprimer Périodes" +  warning: Avertissement    attributes:      author: "Edité par"      created_at: "Créé le" diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml index 6501faa57..0f3eaadd9 100644 --- a/config/locales/lines.en.yml +++ b/config/locales/lines.en.yml @@ -8,7 +8,7 @@ en:        activate: "Activate this line"        deactivate: "Deactivate this line"        activate_confirm: "Are you sure you want to activate this line ?" -      deactivate_confirm: "Are you sure you want tode activate this line ?" +      deactivate_confirm: "Are you sure you want to deactivate this line ?"        destroy_confirm: "Are you sure you want to destroy this line ?"        destroy_selection_confirm: "Are you sure you want to destroy those lines ?"        import: "Import lines" @@ -117,7 +117,7 @@ en:          updated_at: Updated at          creator_id: "Created by"          footnotes: "Footnotes" -        stable_id: External permanent idenifier" +        stable_id: External permanent identifier          status: Status          activated: Activated          deactivated: Deactivated diff --git a/config/locales/networks.en.yml b/config/locales/networks.en.yml index 2046a30ae..d4164f9a6 100644 --- a/config/locales/networks.en.yml +++ b/config/locales/networks.en.yml @@ -5,7 +5,7 @@ en:        new: "Add a new network"        edit: "Edit this network"        destroy: "Remove this network" -      destroy_confirm: "Are you sure you want destroy this network?" +      destroy_confirm: "Are you sure you want to destroy this network ?"      new:        title: "Add a new network"      edit: diff --git a/config/locales/routing_constraint_zones.en.yml b/config/locales/routing_constraint_zones.en.yml index 2143ce1e1..a4bb9b36c 100644 --- a/config/locales/routing_constraint_zones.en.yml +++ b/config/locales/routing_constraint_zones.en.yml @@ -39,6 +39,8 @@ en:        title: "Update routing constraint zone %{name}"      show:        title: "Routing constraint zone %{name}" +      route_stop_points: Route stop points +      stop_points: Stop points included in the RCZ      index:        title: "Routing constraint zones"        search_no_results: "No ITL matches your query" diff --git a/config/locales/routing_constraint_zones.fr.yml b/config/locales/routing_constraint_zones.fr.yml index b5e0fa7fb..8de1bc225 100644 --- a/config/locales/routing_constraint_zones.fr.yml +++ b/config/locales/routing_constraint_zones.fr.yml @@ -39,6 +39,8 @@ fr:        title: "Editer l'ITL : %{name}"      show:        title: "Zone de contrainte %{name}" +      route_stop_points: Arrêts de l'itinéraire +      stop_points: Arrêts inclus dans l'ITL      index:        title: "Interdictions de trafic local"        search_no_results: "Aucune ITL ne correspond à votre recherche" diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml index 7f460381c..3a26f93b2 100644 --- a/config/locales/stop_areas.en.yml +++ b/config/locales/stop_areas.en.yml @@ -28,7 +28,7 @@ en:        activate: "Activate this stop"        deactivate: "Deactivate this stop"        activate_confirm: "Are you sure you want to activate this stop ?" -      deactivate_confirm: "Are you sure you want tode activate this stop ?" +      deactivate_confirm: "Are you sure you want to deactivate this stop ?"        deleted_at: "Activated"        destroy_confirm: "Are you sure you want destroy this stop and all of his children ?"        select_parent: "Create or modify the relation child -> parent" diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml index ce890942d..234f36e81 100644 --- a/config/locales/time_tables.en.yml +++ b/config/locales/time_tables.en.yml @@ -90,7 +90,7 @@ en:        to: " to: "        start_date: "mm/jj/aaaa"        end_date: "mm/jj/aaaa" -      title: "timetables" +      title: "Timetables"        selection: "Selection"        selection_all: "All"        advanced_search: "Advanced Search" diff --git a/config/schedule.rb b/config/schedule.rb index 0d2a24f31..9642fa3a4 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -28,25 +28,19 @@ set :NEW_RELIC_LOG, 'stdout'  set :job_template, "/bin/bash -c ':job'"  every :hour do -  rake "organisations:sync" -  rake "users:sync" +  runner "Cron.every_hour"  end  every :day, :at => '3:00am' do -  rake "reflex:sync" -end -every :day, :at => '4:00 am' do -  rake "codifligne:sync" +  runner "Cron.every_day_at_3AM"  end -every 5.minutes do -  rake "import:netex_abort_old" -  rake "import:notify_parent" +every :day, :at => '4:00 am' do + runner "Cron.every_day_at_4AM"  end  every 5.minutes do -  rake "compliance_check_sets:abort_old" -  rake "compliance_check_sets:notify_parent" +  runner "Cron.every_5_minutes"  end  every 1.minute do diff --git a/db/migrate/20180517190722_alter_import_resource_referential_id.rb b/db/migrate/20180517190722_alter_import_resource_referential_id.rb new file mode 100644 index 000000000..2570ff640 --- /dev/null +++ b/db/migrate/20180517190722_alter_import_resource_referential_id.rb @@ -0,0 +1,5 @@ +class AlterImportResourceReferentialId < ActiveRecord::Migration +  def change +    change_column :import_resources, :referential_id, :bigint +  end +end diff --git a/db/schema.rb b/db/schema.rb index ec8dae690..c5fe6e0d1 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: 20180509071833) do +ActiveRecord::Schema.define(version: 20180517190722) do    # These are extensions that must be enabled in order to support this database    enable_extension "plpgsql" @@ -92,9 +92,9 @@ ActiveRecord::Schema.define(version: 20180509071833) do      t.integer   "organisation_id", limit: 8      t.datetime  "created_at"      t.datetime  "updated_at" -    t.integer   "workgroup_id",    limit: 8      t.integer   "int_day_types"      t.date      "excluded_dates",                            array: true +    t.integer   "workgroup_id",    limit: 8      t.jsonb     "metadata",                  default: {}    end @@ -450,7 +450,7 @@ ActiveRecord::Schema.define(version: 20180509071833) do      t.string   "reference"      t.string   "name"      t.hstore   "metrics" -    t.integer  "referential_id",  limit: 8 +    t.integer  "referential_id", limit: 8    end    add_index "import_resources", ["import_id"], name: "index_import_resources_on_import_id", using: :btree @@ -472,9 +472,9 @@ ActiveRecord::Schema.define(version: 20180509071833) do      t.string   "type"      t.integer  "parent_id",             limit: 8      t.string   "parent_type" -    t.datetime "notified_parent_at"      t.integer  "current_step",                    default: 0      t.integer  "total_steps",                     default: 0 +    t.datetime "notified_parent_at"      t.string   "creator"    end diff --git a/lib/cron.rb b/lib/cron.rb new file mode 100644 index 000000000..fe010ffd9 --- /dev/null +++ b/lib/cron.rb @@ -0,0 +1,78 @@ +module Cron +  class << self + +    def every_day_at_3AM +      sync_reflex +    end + +    def every_day_at_4AM +      sync_codifligne +    end + +    def every_hour +      sync_organizations +      sync_users +    end + +    def every_5_minutes +      check_import_operations +      check_ccset_operations +    end + +    private + +    def sync_organizations +      begin +        Organisation.portail_sync +      rescue => e +        Rails.logger.error(e.inspect) +      end +    end + +    def sync_users +      begin +        User.portail_sync +      rescue => e +        Rails.logger.error(e.inspect) +      end +    end + +    def sync_reflex +      begin +        sync = StopAreaReferential.find_by(name: 'Reflex').stop_area_referential_syncs.build +        raise "reflex:sync aborted - There is already an synchronisation in progress" unless sync.valid? +        sync.save +      rescue => e +        Rails.logger.warn(e.message) +      end +    end + +    def sync_codifligne +      begin +        sync = LineReferential.find_by(name: 'CodifLigne').line_referential_syncs.build +        raise "Codifligne:sync aborted - There is already an synchronisation in progress" unless sync.valid? +        sync.save  +      rescue => e +        Rails.logger.warn(e.message) +      end +    end + +    def check_ccset_operations +      begin +        ParentNotifier.new(ComplianceCheckSet).notify_when_finished +        ComplianceCheckSet.abort_old +      rescue => e +        Rails.logger.error(e.inspect) +      end +    end + +    def check_import_operations +      begin +        ParentNotifier.new(Import::Base).notify_when_finished +        Import::Netex.abort_old +      rescue => e +        Rails.logger.error(e.inspect) +      end +    end +  end +end
\ No newline at end of file diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index 0723e4ccb..7ef867b71 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -14,10 +14,19 @@ namespace :ci do    desc "Prepare CI build"    task :setup do -    cp "config/database.yml", "config/database.yml.orig" -    cp "config/database/ci.yml", "config/database.yml" -    puts "Use #{database_name} database" +    unless ENV["IGNORE_YARN_INSTALL"] +      # FIXME remove this specific behavior +      # Managed by Dockerfile.build +      sh "yarn --frozen-lockfile install" +    end + +    unless ENV["KEEP_DATABASE_CONFIG"] +      # FIXME remove this specific behavior +      cp "config/database.yml", "config/database.yml.orig" +      cp "config/database/ci.yml", "config/database.yml" +    end +    puts "Use #{database_name} database"      if parallel_tests?        sh "RAILS_ENV=test rake parallel:drop parallel:create parallel:migrate"      else @@ -25,6 +34,15 @@ namespace :ci do      end    end +  task :fix_webpacker do +    # Redefine webpacker:yarn_install to avoid --production +    # in CI process +    Rake::Task["webpacker:yarn_install"].clear +    Rake::Task.define_task "webpacker:yarn_install" do +      puts "Don't run yarn" +    end +  end +    def git_branch      if ENV['GIT_BRANCH'] =~ %r{/(.*)$}        $1 @@ -52,7 +70,7 @@ namespace :ci do    end    task :assets do -    sh "RAILS_ENV=test bundle exec rake assets:precompile i18n:js:export" +    sh "RAILS_ENV=test bundle exec rake ci:fix_webpacker assets:precompile i18n:js:export"    end    task :jest do diff --git a/lib/tasks/codifligne.rake b/lib/tasks/codifligne.rake deleted file mode 100644 index dd5e99370..000000000 --- a/lib/tasks/codifligne.rake +++ /dev/null @@ -1,8 +0,0 @@ -namespace :codifligne do -  desc "Sync lines, companies, networks, and group of lines from codifligne" -  task sync: :environment  do -    sync = LineReferential.find_by(name: 'CodifLigne').line_referential_syncs.build -    raise "Codifligne:sync aborted - There is already an synchronisation in progress" unless sync.valid? -    sync.save if sync.valid? -  end -end diff --git a/lib/tasks/compliance_check_sets.rb b/lib/tasks/compliance_check_sets.rb deleted file mode 100644 index c53c7f9ed..000000000 --- a/lib/tasks/compliance_check_sets.rb +++ /dev/null @@ -1,11 +0,0 @@ -namespace :compliance_check_sets do -  desc "Notify parent check sets when children finish" -  task notify_parent: :environment do -    ParentNotifier.new(ComplianceCheckSet).notify_when_finished -  end - -  desc "Mark old unfinished check sets as 'aborted'" -  task abort_old: :environment do -    ComplianceCheckSet.abort_old -  end -end diff --git a/lib/tasks/exports.rake b/lib/tasks/exports.rake index 845d581d3..33fbf81ed 100644 --- a/lib/tasks/exports.rake +++ b/lib/tasks/exports.rake @@ -52,9 +52,9 @@ namespace :export do        puts "No maching journeys were found".red      else        exports_group = SimpleInterfacesGroup.new "Export Complet \"#{referential.name}\" du #{Time.now.to_date} au #{args[:timelapse].to_i.days.from_now.to_date}" -      exports_group.shared_options = {verbose: true} +      exports_group.shared_options = {verbose: true, output_dir: args[:output_dir]} -      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_companies", filepath: "#{args[:output_dir]}/#{args[:configuration_name]}_companies.json" +      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_companies", filepath: "#{args[:output_dir]}/service_type.json"        ids = journeys.pluck :company_id        ids += journeys.joins(route: :line).pluck :"lines.company_id" @@ -64,28 +64,28 @@ namespace :export do        exports_group.add_interface exporter, "Services Types", :export -      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_schedules", filepath: "#{args[:output_dir]}/#{args[:configuration_name]}_schedules.json" +      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_schedules", filepath: "#{args[:output_dir]}/schedule.json"        exporter.configure do |config| -        config.collection = journeys +        config.collection = journeys.where("custom_field_values->>'capacity' IS NOT NULL")        end        exports_group.add_interface exporter, "Schedules", :export -      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_routes", filepath: "#{args[:output_dir]}/#{args[:configuration_name]}_routes.json" +      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_routes", filepath: "#{args[:output_dir]}/route.json"        exporter.configure do |config|          config.collection = Chouette::JourneyPattern.where(id: journeys.pluck(:journey_pattern_id).uniq)        end        exports_group.add_interface exporter, "Routes", :export -      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_stops", filepath: "#{args[:output_dir]}/#{args[:configuration_name]}_stops.json" +      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_stops", filepath: "#{args[:output_dir]}/station.json"        exporter.configure do |config|          config.collection = Chouette::StopArea.where(id: journeys.joins(:stop_points).pluck(:"stop_points.stop_area_id").uniq).order('parent_id ASC NULLS FIRST')        end        exports_group.add_interface exporter, "Stops", :export -      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_journeys", filepath: "#{args[:output_dir]}/#{args[:configuration_name]}_journeys.json" +      exporter = SimpleJsonExporter.create configuration_name: "#{args[:configuration_name]}_journeys", filepath: "#{args[:output_dir]}/service.json"        exporter.configure do |config|          config.collection = journeys        end diff --git a/lib/tasks/imports.rake b/lib/tasks/imports.rake index d393ab156..258c37bbd 100644 --- a/lib/tasks/imports.rake +++ b/lib/tasks/imports.rake @@ -2,16 +2,6 @@ require 'csv'  require 'tasks/helpers/simple_interfaces'  namespace :import do -  desc "Notify parent imports when children finish" -    task notify_parent: :environment do -    ParentNotifier.new(Import::Base).notify_when_finished -  end - -  desc "Mark old unfinished Netex imports as 'aborted'" -  task netex_abort_old: :environment do -    Import::Netex.abort_old -  end -    desc "import the given file with the corresponding importer"    task :import, [:configuration_name, :filepath, :referential_id, :logs_output_dir] => :environment do |t, args|      args.with_defaults(logs_output_dir: "./log/importers/") diff --git a/lib/tasks/organisations.rake b/lib/tasks/organisations.rake deleted file mode 100644 index 1b21d7119..000000000 --- a/lib/tasks/organisations.rake +++ /dev/null @@ -1,6 +0,0 @@ -namespace :organisations do -  desc "Sync organisations from stif portail" -  task sync: :environment  do -    Organisation.portail_sync -  end -end diff --git a/lib/tasks/reflex.rake b/lib/tasks/reflex.rake deleted file mode 100644 index 67496cee0..000000000 --- a/lib/tasks/reflex.rake +++ /dev/null @@ -1,8 +0,0 @@ -namespace :reflex do -  desc "Sync data from Reflex api" -  task sync: :environment  do -    sync = StopAreaReferential.find_by(name: 'Reflex').stop_area_referential_syncs.build -    raise "reflex:sync aborted - There is already an synchronisation in progress" unless sync.valid? -    sync.save if sync.valid? -  end -end diff --git a/lib/tasks/users.rake b/lib/tasks/users.rake deleted file mode 100644 index c045639c1..000000000 --- a/lib/tasks/users.rake +++ /dev/null @@ -1,6 +0,0 @@ -namespace :users do -  desc "Sync users from stif portail" -  task sync: :environment  do -    User.portail_sync -  end -end diff --git a/package.json b/package.json index 2967ad3d3..df48d5209 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@    "dependencies": {      "@rails/webpacker": "3.2.0",      "babel-jest": "22.0.4", -    "babel-polyfill": "6.26.0", +    "babel-polyfill": "^6.26.0",      "babel-preset-es2015": "6.24.1",      "babel-preset-react": "6.24.1",      "babelify": "8.0.0", diff --git a/spec/features/stop_areas_spec.rb b/spec/features/stop_areas_spec.rb index 52040f070..3a47f826f 100644 --- a/spec/features/stop_areas_spec.rb +++ b/spec/features/stop_areas_spec.rb @@ -43,30 +43,30 @@ describe "StopAreas", :type => :feature do          describe 'updated stop areas in before block' do            it 'supports displaying only stop areas in creation' do -            find("#q_status_in_creation").set(true) +            find("#q_by_status_in_creation").set(true)              click_button 'search-btn'              expect(page).not_to have_content(stop_areas.first.name)              expect(page).not_to have_content(stop_areas.last.name)            end            it 'supports displaying only confirmed stop areas' do -            find("#q_status_confirmed").set(true) +            find("#q_by_status_confirmed").set(true)              click_button 'search-btn'              expect(page).to have_content(stop_areas.first.name)              expect(page).not_to have_content(stop_areas.last.name)            end            it 'supports displaying only deactivated stop areas' do -            find("#q_status_deactivated").set(true) +            find("#q_by_status_deactivated").set(true)              click_button 'search-btn'              expect(page).not_to have_content(stop_areas.first.name)              expect(page).to have_content(stop_areas.last.name)            end            it 'should display all stop areas if all filters are checked' do -            find("#q_status_in_creation").set(true) -            find("#q_status_confirmed").set(true) -            find("#q_status_deactivated").set(true) +            find("#q_by_status_in_creation").set(true) +            find("#q_by_status_confirmed").set(true) +            find("#q_by_status_deactivated").set(true)              click_button 'search-btn'              expect(page).to have_content(stop_areas.first.name)              expect(page).to have_content(stop_areas.last.name) diff --git a/spec/features/users/user_edit_spec.rb b/spec/features/users/user_edit_spec.rb index 14995d8e5..020a4bc57 100644 --- a/spec/features/users/user_edit_spec.rb +++ b/spec/features/users/user_edit_spec.rb @@ -40,8 +40,8 @@ feature 'User edit', :devise do      other = FactoryGirl.create(:user, email: 'other@example.com')      login_as(me, :scope => :user)      visit edit_user_registration_path(other) -    expect(page).to have_content 'Votre Profil' -    expect(page).to have_field('Email', with: me.email) +    expect(page).to have_content I18n.t('devise.registrations.edit.title') +    expect(page).to have_field(I18n.t('simple_form.labels.user.email'), with: me.email)    end  end diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb index 0fc75bec9..05560f9e3 100644 --- a/spec/models/chouette/vehicle_journey_spec.rb +++ b/spec/models/chouette/vehicle_journey_spec.rb @@ -36,6 +36,16 @@ describe Chouette::VehicleJourney, :type => :model do        expect{create(:vehicle_journey_at_stop, vehicle_journey: vehicle_journey)}.to change{vehicle_journey.checksum}      end +    it "changes when a vjas is deleted" do +      vehicle_journey = create(:vehicle_journey) +      3.times do +        create(:vehicle_journey_at_stop, vehicle_journey: vehicle_journey).run_callbacks(:commit) +      end +      vjas = vehicle_journey.vehicle_journey_at_stops.last +      expect(vehicle_journey).to receive(:update_checksum_without_callbacks!).at_least(:once).and_call_original +      expect{vjas.destroy; vjas.run_callbacks(:commit)}.to change{vehicle_journey.reload.checksum} +    end +      context "when custom_field_values change" do        let(:vehicle_journey){ create(:vehicle_journey, custom_field_values: {custom_field.code.to_s => former_value}) }        let(:custom_field){ create :custom_field, field_type: :string, code: :energy, name: :energy, resource_type: "VehicleJourney" } diff --git a/spec/models/clean_up_spec.rb b/spec/models/clean_up_spec.rb index afd2d8721..f39ca2f2b 100644 --- a/spec/models/clean_up_spec.rb +++ b/spec/models/clean_up_spec.rb @@ -264,4 +264,68 @@ RSpec.describe CleanUp, :type => :model do        }      end    end + +  describe "#destroy_routes_outside_referential" do +    let(:line_referential) { create(:line_referential) } +    let(:line) { create(:line, line_referential: line_referential) } +    let(:metadata) { create(:referential_metadata, lines: [line]) } +    let(:referential) { create(:workbench_referential, metadatas: [metadata]) } +    let(:cleaner) { create(:clean_up, referential: referential) } + +    it "destroys routes not in the the referential" do +      route = create(:route) + +      cleaner.destroy_routes_outside_referential + +      expect(Chouette::Route.exists?(route.id)).to be false + +      line.routes.each do |route| +        expect(route).not_to be_destroyed +      end +    end + +    it "cascades destruction of vehicle journeys and journey patterns" do +      vehicle_journey = create(:vehicle_journey) + +      cleaner.destroy_routes_outside_referential + +      expect(Chouette::Route.exists?(vehicle_journey.route.id)).to be false +      expect( +        Chouette::JourneyPattern.exists?(vehicle_journey.journey_pattern.id) +      ).to be false +      expect(Chouette::VehicleJourney.exists?(vehicle_journey.id)).to be false +    end +  end + +  describe "#destroy_empty" do +    it "calls the appropriate destroy methods" do +      cleaner = create(:clean_up) + +      expect(cleaner).to receive(:destroy_vehicle_journeys) +      expect(cleaner).to receive(:destroy_journey_patterns) +      expect(cleaner).to receive(:destroy_routes) + +      cleaner.destroy_empty +    end +  end + +  describe "#run_methods" do +    let(:cleaner) { create(:clean_up) } + +    it "calls methods in the :methods attribute" do +      cleaner = create( +        :clean_up, +        methods: [:destroy_routes_outside_referential] +      ) + +      expect(cleaner).to receive(:destroy_routes_outside_referential) +      cleaner.run_methods +    end + +    it "doesn't do anything if :methods is nil" do +      cleaner = create(:clean_up) + +      expect { cleaner.run_methods }.not_to raise_error +    end +  end  end diff --git a/spec/models/merge_spec.rb b/spec/models/merge_spec.rb index 59e2cc500..8c3f48272 100644 --- a/spec/models/merge_spec.rb +++ b/spec/models/merge_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Merge do      line_referential = FactoryGirl.create :line_referential      company = FactoryGirl.create :company, line_referential: line_referential -    10.times { FactoryGirl.create :line, line_referential: line_referential, company: company, network: nil } +    4.times { FactoryGirl.create :line, line_referential: line_referential, company: company, network: nil }      workbench = FactoryGirl.create :workbench, line_referential: line_referential, stop_area_referential: stop_area_referential @@ -19,7 +19,7 @@ RSpec.describe Merge do                                        organisation: workbench.organisation,                                        metadatas: [referential_metadata] -    factor = 1 +    factor = 2      stop_points_positions = {}      routing_constraint_zones = {} @@ -32,7 +32,7 @@ RSpec.describe Merge do          end        end -      referential.routes.each do |route| +      referential.routes.each_with_index do |route, index|          route.stop_points.each do |sp|            sp.set_list_position 0          end @@ -47,9 +47,18 @@ RSpec.describe Merge do            routing_constraint_zones[route.id][constraint_zone.checksum] = constraint_zone          end -        route.reload.update_checksum! +        if index.even? +          route.wayback = :outbound +        else +          route.update_column :wayback, :inbound +          route.opposite_route = route.opposite_route_candidates.sample +        end + +        route.save! +        route.reload.update_checksum!          expect(route.reload.checksum).to_not eq checksum +          factor.times do            FactoryGirl.create :journey_pattern, route: route, stop_points: route.stop_points.sample(3)          end @@ -83,12 +92,14 @@ RSpec.describe Merge do      output.routes.each do |route|        stop_points = nil        old_route = nil +      old_opposite_route = nil        referential.switch do          old_route = Chouette::Route.find_by(checksum: route.checksum)          stop_points = {}          old_route.routing_constraint_zones.each do |constraint_zone|            stop_points[constraint_zone.checksum] = constraint_zone.stop_points.map(&:registration_number)          end +        old_opposite_route = old_route.opposite_route        end        routing_constraint_zones[old_route.id].each do |checksum, constraint_zone|          new_constraint_zone = route.routing_constraint_zones.where(checksum: checksum).last @@ -99,6 +110,8 @@ RSpec.describe Merge do        route.vehicle_journeys.each do |vehicle_journey|          expect(vehicle_journey.ignored_routing_contraint_zones.size).to eq vehicle_journey.ignored_routing_contraint_zone_ids.size        end + +      expect(route.opposite_route&.checksum).to eq(old_opposite_route&.checksum)      end      # Let's check stop_point positions are respected diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb index 58524038b..dbf00ab0b 100644 --- a/spec/models/route_spec.rb +++ b/spec/models/route_spec.rb @@ -2,6 +2,11 @@ require 'spec_helper'  RSpec.describe Chouette::Route, :type => :model do    subject(:route){ create :route } +  context "the checksum" do +    it "should change when a stop is removed" do +      expect{route.stop_points.last.destroy}.to change {route.reload.checksum} +    end +  end    context "metadatas" do      it "should be empty at first" do        expect(Chouette::Route.has_metadata?).to be_truthy @@ -791,7 +791,7 @@ babel-plugin-transform-strict-mode@^6.24.1:      babel-runtime "^6.22.0"      babel-types "^6.24.1" -babel-polyfill@6.26.0, babel-polyfill@^6.26.0: +babel-polyfill@^6.26.0:    version "6.26.0"    resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"    dependencies: | 
