diff options
| author | Guillaume | 2017-10-31 11:54:08 +0100 |
|---|---|---|
| committer | Guillaume | 2017-10-31 11:54:08 +0100 |
| commit | f201d7cdd68ca554e7a99eb791baf48a540b8978 (patch) | |
| tree | 428c823e77c330cdc5ea85e03ff34805bdae854e | |
| parent | 90173e6bdd12d1aabe68a0d28f4f228782d3adf0 (diff) | |
| parent | 718d9ab7f8d5b1cd125ee341bd098c41615a0cbd (diff) | |
| download | chouette-core-f201d7cdd68ca554e7a99eb791baf48a540b8978.tar.bz2 | |
Merge branch 'master' into 4755-page_for_validate_referential
189 files changed, 1042 insertions, 952 deletions
@@ -93,7 +93,7 @@ gem 'RedCloth', '~> 4.3.0' gem 'simple_form', '~> 3.1.0' gem 'font-awesome-sass', '~> 4.7' gem 'will_paginate-bootstrap' -gem 'breadcrumbs_on_rails' +gem 'gretel' # Format Output gem 'json' diff --git a/Gemfile.lock b/Gemfile.lock index da7c4f3c1..48a8b638a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -105,7 +105,6 @@ GEM rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - breadcrumbs_on_rails (3.0.1) builder (3.2.3) bundler-audit (0.5.0) bundler (~> 1.2) @@ -245,6 +244,8 @@ GEM globalid (0.3.7) activesupport (>= 4.1.0) google-analytics-rails (1.1.0) + gretel (3.0.9) + rails (>= 3.1.0) has_scope (0.7.0) actionpack (>= 4.1, < 5.1) activesupport (>= 4.1, < 5.1) @@ -256,7 +257,8 @@ GEM htmlbeautifier (1.3.1) httparty (0.14.0) multi_xml (>= 0.5.2) - i18n (0.8.6) + i18n (0.9.0) + concurrent-ruby (~> 1.0) i18n-tasks (0.9.15) activesupport (>= 4.0.2) ast (>= 2.1.0) @@ -380,7 +382,7 @@ GEM activesupport (>= 4.2.0.beta, < 5.0) nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) - rails-erd (1.5.0) + rails-erd (1.5.2) activerecord (>= 3.2) activesupport (>= 3.2) choice (~> 0.2.0) @@ -567,7 +569,6 @@ DEPENDENCIES awesome_print better_errors binding_of_caller - breadcrumbs_on_rails bundler-audit calendar_helper (= 0.2.5) capistrano (= 2.13.5) @@ -603,6 +604,7 @@ DEPENDENCIES georuby (= 2.3.0) georuby-ext (= 0.0.5) google-analytics-rails + gretel has_array_of! hstore_accessor (~> 1.1) htmlbeautifier diff --git a/INSTALL.md b/INSTALL.md index bd4a3f330..6e497b580 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -19,6 +19,14 @@ Go into your local repro and install the gems bundle +## Node and Yarn + +Yarn needs a node version ≥ 6, if you use Node Version Manager [NVM](https://github.com/creationix/nvm) you can rely on the content of `.nvmrc`. + +Otherwise please make sure to use a compatible version, still best to use the same as indicated by `.nvrmc`. + +Then install yarn (`brew install yarn` does nicely on macOS). + ### Installation Caveats #### Node Related Issue, libv8 diff --git a/app/assets/stylesheets/components/_breadcrumb.sass b/app/assets/stylesheets/components/_breadcrumb.sass new file mode 100644 index 000000000..62f167eb4 --- /dev/null +++ b/app/assets/stylesheets/components/_breadcrumb.sass @@ -0,0 +1,3 @@ +.breadcrumbs + a + color: white
\ No newline at end of file diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass index 7a5323011..2b715d669 100644 --- a/app/assets/stylesheets/components/_forms.sass +++ b/app/assets/stylesheets/components/_forms.sass @@ -53,6 +53,8 @@ input border-right: none &:last-child border-left: none + &[readonly] + background-color: white + span display: table-cell @@ -61,7 +63,7 @@ input border-bottom: 1px solid #ccc box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) - &.disabled > .form-control + span + &[disabled], &.disabled > .form-control + span background-color: #eee // Validations diff --git a/app/assets/stylesheets/components/_modals.sass b/app/assets/stylesheets/components/_modals.sass index 2db4fe955..e52a2e125 100644 --- a/app/assets/stylesheets/components/_modals.sass +++ b/app/assets/stylesheets/components/_modals.sass @@ -38,6 +38,11 @@ $modalW: 600px .modal-title font-size: $h2-size + display: inline-block + + .modal-close + text-align: right + display: inline-block .modal-body padding: 15px 30px diff --git a/app/controllers/access_links_controller.rb b/app/controllers/access_links_controller.rb index 6f1ad8bfd..936b8ea5e 100644 --- a/app/controllers/access_links_controller.rb +++ b/app/controllers/access_links_controller.rb @@ -21,9 +21,7 @@ class AccessLinksController < ChouetteController @access_point = Chouette::AccessPoint.find(params[:access_point_id]) #@access_link = Chouette::AccessLink.find(params[:id]) @stop_area = @access_link.stop_area - show! do |format| - format.html {build_breadcrumb :show} - end + show! end def new @@ -41,9 +39,7 @@ class AccessLinksController < ChouetteController data[:name] = name end @access_link = Chouette::AccessLink.new(data.permit!) - new! do - build_breadcrumb :new - end + new! end def create @@ -59,9 +55,7 @@ class AccessLinksController < ChouetteController @access_link = Chouette::AccessLink.find(params[:id]) @stop_area = @access_link.stop_area @orientation = @access_link.link_orientation_type - edit! do - build_breadcrumb :edit - end + edit! end def update @@ -69,9 +63,7 @@ class AccessLinksController < ChouetteController @access_link = Chouette::AccessLink.find(params[:id]) @stop_area = @access_link.stop_area @orientation = @access_link.link_orientation_type - update! do |success, failure| - build_breadcrumb :edit - end + update! end protected diff --git a/app/controllers/access_points_controller.rb b/app/controllers/access_points_controller.rb index d43880c0b..477875cc9 100644 --- a/app/controllers/access_points_controller.rb +++ b/app/controllers/access_points_controller.rb @@ -6,7 +6,6 @@ class AccessPointsController < ChouetteController end respond_to :html, :kml, :xml, :json - include PolicyChecker def index @@ -32,7 +31,6 @@ class AccessPointsController < ChouetteController } end - format.html {build_breadcrumb :show} end end @@ -40,9 +38,7 @@ class AccessPointsController < ChouetteController def edit access_point.position ||= access_point.default_position map.editable = true - edit! do - build_breadcrumb :edit - end + edit! end diff --git a/app/controllers/api/v1/imports_controller.rb b/app/controllers/api/v1/imports_controller.rb index 6050418d8..3d7f4ca79 100644 --- a/app/controllers/api/v1/imports_controller.rb +++ b/app/controllers/api/v1/imports_controller.rb @@ -5,7 +5,11 @@ class Api::V1::ImportsController < Api::V1::IbooController def create args = workbench_import_params.merge(creator: 'Webservice') @import = parent.workbench_imports.create(args) - create! + if @import.valid? + create! + else + render json: { status: "error", messages: @import.errors.full_messages } + end end private diff --git a/app/controllers/api_keys_controller.rb b/app/controllers/api_keys_controller.rb index 7ae8d4732..eebad5e7b 100644 --- a/app/controllers/api_keys_controller.rb +++ b/app/controllers/api_keys_controller.rb @@ -1,4 +1,4 @@ -class ApiKeysController < BreadcrumbController +class ApiKeysController < InheritedResources::Base defaults resource_class: Api::V1::ApiKey include PolicyChecker diff --git a/app/controllers/breadcrumb_controller.rb b/app/controllers/breadcrumb_controller.rb deleted file mode 100644 index cb639fdb8..000000000 --- a/app/controllers/breadcrumb_controller.rb +++ /dev/null @@ -1,41 +0,0 @@ -class BreadcrumbController < InheritedResources::Base - include Pundit - include BreadcrumbHelper - - def show - show! do - build_breadcrumb :show - end - end - - def index - index! do - build_breadcrumb :index - end - end - - def edit - edit! do - build_breadcrumb :edit - end - end - - def update - update! do |success, failure| - build_breadcrumb :edit - end - end - - def new - new! do - build_breadcrumb :new - end - end - - def create - create! do |success, failure| - build_breadcrumb :new - end - end - -end diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index 1c342c718..e9ee7579a 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -1,4 +1,4 @@ -class CalendarsController < BreadcrumbController +class CalendarsController < InheritedResources::Base include PolicyChecker defaults resource_class: Calendar before_action :ransack_contains_date, only: [:index] @@ -8,16 +8,12 @@ class CalendarsController < BreadcrumbController def index index! do @calendars = ModelDecorator.decorate(@calendars, with: CalendarDecorator) - - build_breadcrumb :index end end def show show! do @calendar = @calendar.decorate - - build_breadcrumb :show end end diff --git a/app/controllers/chouette_controller.rb b/app/controllers/chouette_controller.rb index dc9ab4fa5..1313aa7cc 100644 --- a/app/controllers/chouette_controller.rb +++ b/app/controllers/chouette_controller.rb @@ -1,6 +1,5 @@ -class ChouetteController < BreadcrumbController +class ChouetteController < InheritedResources::Base include ApplicationHelper - include BreadcrumbHelper include ReferentialSupport end diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb index cf27c39cf..bc5bedd7f 100644 --- a/app/controllers/companies_controller.rb +++ b/app/controllers/companies_controller.rb @@ -1,4 +1,4 @@ -class CompaniesController < BreadcrumbController +class CompaniesController < InheritedResources::Base include ApplicationHelper include PolicyChecker defaults :resource_class => Chouette::Company @@ -22,8 +22,6 @@ class CompaniesController < BreadcrumbController format.json { @companies = decorate_companies(@companies) } - - build_breadcrumb :index end end diff --git a/app/controllers/compliance_check_sets_controller.rb b/app/controllers/compliance_check_sets_controller.rb index fce8dcc56..95dcfbf05 100644 --- a/app/controllers/compliance_check_sets_controller.rb +++ b/app/controllers/compliance_check_sets_controller.rb @@ -1,4 +1,4 @@ -class ComplianceCheckSetsController < BreadcrumbController +class ComplianceCheckSetsController < InheritedResources::Base defaults resource_class: ComplianceCheckSet include RansackDateFilter before_action only: [:index] { set_date_time_params("created_at", DateTime) } @@ -18,4 +18,4 @@ class ComplianceCheckSetsController < BreadcrumbController } end end -end
\ No newline at end of file +end diff --git a/app/controllers/compliance_control_blocks_controller.rb b/app/controllers/compliance_control_blocks_controller.rb index 2dd69a865..996f8a464 100644 --- a/app/controllers/compliance_control_blocks_controller.rb +++ b/app/controllers/compliance_control_blocks_controller.rb @@ -1,4 +1,4 @@ -class ComplianceControlBlocksController < BreadcrumbController +class ComplianceControlBlocksController < InheritedResources::Base defaults resource_class: ComplianceControlBlock belongs_to :compliance_control_set actions :all, :except => [:show, :index] @@ -9,4 +9,4 @@ class ComplianceControlBlocksController < BreadcrumbController params.require(:compliance_control_block).permit(:transport_mode, :transport_submode) end -end
\ No newline at end of file +end diff --git a/app/controllers/compliance_control_sets_controller.rb b/app/controllers/compliance_control_sets_controller.rb index fd66a54e7..f6002956b 100644 --- a/app/controllers/compliance_control_sets_controller.rb +++ b/app/controllers/compliance_control_sets_controller.rb @@ -1,4 +1,4 @@ -class ComplianceControlSetsController < BreadcrumbController +class ComplianceControlSetsController < InheritedResources::Base defaults resource_class: ComplianceControlSet include RansackDateFilter before_action only: [:index] { set_date_time_params("updated_at", DateTime) } diff --git a/app/controllers/compliance_controls_controller.rb b/app/controllers/compliance_controls_controller.rb index e51d1eb74..bd4a33ff4 100644 --- a/app/controllers/compliance_controls_controller.rb +++ b/app/controllers/compliance_controls_controller.rb @@ -1,6 +1,7 @@ -class ComplianceControlsController < BreadcrumbController +class ComplianceControlsController < InheritedResources::Base defaults resource_class: ComplianceControl belongs_to :compliance_control_set + actions :all, :except => [:show, :index] def select_type @sti_subclasses = ComplianceControl.subclasses @@ -15,7 +16,6 @@ class ComplianceControlsController < BreadcrumbController end def create - puts build_resource.inspect create! do |success, failure| success.html { redirect_to compliance_control_set_path(parent) } failure.html { render( :action => 'new' ) } diff --git a/app/controllers/concerns/policy_checker.rb b/app/controllers/concerns/policy_checker.rb index 65a4428e2..d84263f2c 100644 --- a/app/controllers/concerns/policy_checker.rb +++ b/app/controllers/concerns/policy_checker.rb @@ -1,4 +1,5 @@ module PolicyChecker + include Pundit extend ActiveSupport::Concern included do diff --git a/app/controllers/connection_links_controller.rb b/app/controllers/connection_links_controller.rb index 403f0ed9e..b56450291 100644 --- a/app/controllers/connection_links_controller.rb +++ b/app/controllers/connection_links_controller.rb @@ -18,23 +18,19 @@ class ConnectionLinksController < ChouetteController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - build_breadcrumb :index } end end def show @map = ConnectionLinkMap.new(resource).with_helpers(self) - show! do - build_breadcrumb :show - end + show! end def select_areas @connection_link = connection_link @departure = connection_link.departure @arrival = connection_link.arrival - build_breadcrumb :show end protected diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb index 2585dafca..1c7876c58 100644 --- a/app/controllers/dashboards_controller.rb +++ b/app/controllers/dashboards_controller.rb @@ -3,7 +3,7 @@ # this controller will use a custom partial like # custom/dashboards/_dashboard.html.slim for Custom::Dashboard # -class DashboardsController < BreadcrumbController +class DashboardsController < InheritedResources::Base respond_to :html, only: [:show] def show diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb index 2cfa0b6fa..ad88c6dae 100644 --- a/app/controllers/exports_controller.rb +++ b/app/controllers/exports_controller.rb @@ -3,16 +3,14 @@ require 'open-uri' class ExportsController < ChouetteController defaults :resource_class => Export - + respond_to :html, :only => [:show, :index, :destroy, :exported_file] respond_to :js, :only => [:index] belongs_to :referential def index begin - index! do - build_breadcrumb :index - end + index! rescue Ievkit::Error, Faraday::Error => error logger.error("Iev failure : #{error.message}") flash[:error] = t(error.locale_for_error) @@ -22,9 +20,7 @@ class ExportsController < ChouetteController def show begin - show! do - build_breadcrumb :show - end + show! rescue Ievkit::Error, Faraday::Error => error logger.error("Iev failure : #{error.message}") flash[:error] = t(error.locale_for_error) @@ -32,7 +28,7 @@ class ExportsController < ChouetteController end end - def destroy + def destroy begin destroy! rescue Ievkit::Error, Faraday::Error => error @@ -57,11 +53,11 @@ class ExportsController < ChouetteController end protected - + def export_service ExportService.new(@referential) end - + def resource @export ||= export_service.find( params[:id] ) @line_items = @export.report.line_items diff --git a/app/controllers/group_of_lines_controller.rb b/app/controllers/group_of_lines_controller.rb index 5cadd40d3..1a59d39f7 100644 --- a/app/controllers/group_of_lines_controller.rb +++ b/app/controllers/group_of_lines_controller.rb @@ -1,4 +1,4 @@ -class GroupOfLinesController < BreadcrumbController +class GroupOfLinesController < InheritedResources::Base include ApplicationHelper include PolicyChecker defaults :resource_class => Chouette::GroupOfLine @@ -13,9 +13,7 @@ class GroupOfLinesController < BreadcrumbController def show @map = GroupOfLineMap.new(resource).with_helpers(self) @lines = resource.lines.order(:name) - show! do - build_breadcrumb :show - end + show! end def index @@ -24,7 +22,6 @@ class GroupOfLinesController < BreadcrumbController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - build_breadcrumb :index } end end diff --git a/app/controllers/import_messages_controller.rb b/app/controllers/import_messages_controller.rb index 4ad398cbb..c3c6b46b5 100644 --- a/app/controllers/import_messages_controller.rb +++ b/app/controllers/import_messages_controller.rb @@ -1,4 +1,4 @@ -class ImportMessagesController < BreadcrumbController +class ImportMessagesController < InheritedResources::Base defaults resource_class: ImportMessage, collection_name: 'import_messages', instance_name: 'import_message' respond_to :csv belongs_to :import, :parent_class => Import do diff --git a/app/controllers/import_resources_controller.rb b/app/controllers/import_resources_controller.rb index ac3dd042e..3e52233f2 100644 --- a/app/controllers/import_resources_controller.rb +++ b/app/controllers/import_resources_controller.rb @@ -1,4 +1,4 @@ -class ImportResourcesController < BreadcrumbController +class ImportResourcesController < InheritedResources::Base defaults resource_class: ImportResource, collection_name: 'import_resources', instance_name: 'import_resource' respond_to :html belongs_to :import @@ -8,8 +8,6 @@ class ImportResourcesController < BreadcrumbController format.html { @import_resources = decorate_import_resources(@import_resources) } - - build_breadcrumb :index end end diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb index 3c52dc935..6c9d81d82 100644 --- a/app/controllers/imports_controller.rb +++ b/app/controllers/imports_controller.rb @@ -1,4 +1,4 @@ -class ImportsController < BreadcrumbController +class ImportsController < InheritedResources::Base include PolicyChecker include RansackDateFilter before_action only: [:index] { set_date_time_params("started_at", DateTime) } @@ -13,8 +13,6 @@ class ImportsController < BreadcrumbController @import = @import.decorate(context: { workbench: @workbench }) - - build_breadcrumb :show end end @@ -24,17 +22,8 @@ class ImportsController < BreadcrumbController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - @imports = decorate_imports(@imports) } - - build_breadcrumb :index - end - end - - def new - new! do - build_breadcrumb :new end end diff --git a/app/controllers/journey_patterns_collections_controller.rb b/app/controllers/journey_patterns_collections_controller.rb index e8924b7ad..546158fa8 100644 --- a/app/controllers/journey_patterns_collections_controller.rb +++ b/app/controllers/journey_patterns_collections_controller.rb @@ -45,7 +45,6 @@ class JourneyPatternsCollectionsController < ChouetteController } end @stop_points_list = @stop_points_list.sort_by {|a| a[:position] } - build_breadcrumb :index end def user_permissions diff --git a/app/controllers/journey_patterns_controller.rb b/app/controllers/journey_patterns_controller.rb index f4ae55b4e..a72e7da7f 100644 --- a/app/controllers/journey_patterns_controller.rb +++ b/app/controllers/journey_patterns_controller.rb @@ -30,9 +30,7 @@ class JourneyPatternsController < ChouetteController def show @map = JourneyPatternMap.new(journey_pattern).with_helpers(self) @stop_points = journey_pattern.stop_points.paginate(:page => params[:page]) - show! do - build_breadcrumb :show - end + show! end def new_vehicle_journey diff --git a/app/controllers/line_footnotes_controller.rb b/app/controllers/line_footnotes_controller.rb index 581c921e8..2d4d10064 100644 --- a/app/controllers/line_footnotes_controller.rb +++ b/app/controllers/line_footnotes_controller.rb @@ -5,12 +5,6 @@ class LineFootnotesController < ChouetteController before_action :authorize_resource, only: [:destroy_footnote, :edit_footnote, :show_footnote, :update_footnote] before_action :authorize_resource_class, only: [:create_footnote, :index_footnote, :new_footnote] - def edit - edit! do - build_breadcrumb :edit - end - end - def update update! do |success, failure| success.html { redirect_to referential_line_footnotes_path(@referential, @line) , notice: t('notice.footnotes.updated') } diff --git a/app/controllers/line_referentials_controller.rb b/app/controllers/line_referentials_controller.rb index fc4ab3cf5..f70ddef41 100644 --- a/app/controllers/line_referentials_controller.rb +++ b/app/controllers/line_referentials_controller.rb @@ -1,4 +1,4 @@ -class LineReferentialsController < BreadcrumbController +class LineReferentialsController < InheritedResources::Base defaults :resource_class => LineReferential diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb index 4b6448ce8..cf2908500 100644 --- a/app/controllers/lines_controller.rb +++ b/app/controllers/lines_controller.rb @@ -1,4 +1,4 @@ -class LinesController < BreadcrumbController +class LinesController < InheritedResources::Base include ApplicationHelper include PolicyChecker defaults :resource_class => Chouette::Line @@ -26,7 +26,6 @@ class LinesController < BreadcrumbController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - build_breadcrumb :index } end end @@ -38,8 +37,6 @@ class LinesController < BreadcrumbController line_referential: @line_referential, current_organisation: current_organisation }) - - build_breadcrumb :show end end diff --git a/app/controllers/networks_controller.rb b/app/controllers/networks_controller.rb index 5dae1ba3f..98c840777 100644 --- a/app/controllers/networks_controller.rb +++ b/app/controllers/networks_controller.rb @@ -1,4 +1,4 @@ -class NetworksController < BreadcrumbController +class NetworksController < InheritedResources::Base include ApplicationHelper include PolicyChecker defaults :resource_class => Chouette::Network @@ -17,8 +17,6 @@ class NetworksController < BreadcrumbController @network = @network.decorate(context: { line_referential: line_referential }) - - build_breadcrumb :show end end @@ -43,8 +41,6 @@ class NetworksController < BreadcrumbController format.js { @networks = decorate_networks(@networks) } - - build_breadcrumb :index end end diff --git a/app/controllers/organisations_controller.rb b/app/controllers/organisations_controller.rb index 51a325586..d80541800 100644 --- a/app/controllers/organisations_controller.rb +++ b/app/controllers/organisations_controller.rb @@ -1,4 +1,4 @@ -class OrganisationsController < BreadcrumbController +class OrganisationsController < InheritedResources::Base defaults :resource_class => Organisation respond_to :html, :only => [:edit, :show, :update] @@ -18,6 +18,6 @@ class OrganisationsController < BreadcrumbController def organisation_params params.require(:organisation).permit(:name) end - + end diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb index 482f74ea0..fdbd83dc9 100644 --- a/app/controllers/referential_companies_controller.rb +++ b/app/controllers/referential_companies_controller.rb @@ -20,8 +20,6 @@ class ReferentialCompaniesController < ChouetteController format.js { @companies = decorate_companies(@companies) } - - build_breadcrumb :index end end diff --git a/app/controllers/referential_group_of_lines_controller.rb b/app/controllers/referential_group_of_lines_controller.rb index 73520d00a..d88daab84 100644 --- a/app/controllers/referential_group_of_lines_controller.rb +++ b/app/controllers/referential_group_of_lines_controller.rb @@ -12,9 +12,7 @@ class ReferentialGroupOfLinesController < ChouetteController def show @map = GroupOfLineMap.new(resource).with_helpers(self) @lines = resource.lines.order(:name) - show! do - build_breadcrumb :show - end + show! end def index @@ -23,7 +21,6 @@ class ReferentialGroupOfLinesController < ChouetteController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - build_breadcrumb :index } end end diff --git a/app/controllers/referential_lines_controller.rb b/app/controllers/referential_lines_controller.rb index ec0bbbb18..b9f8c0050 100644 --- a/app/controllers/referential_lines_controller.rb +++ b/app/controllers/referential_lines_controller.rb @@ -44,8 +44,6 @@ class ReferentialLinesController < ChouetteController current_organisation: current_organisation } ) - - build_breadcrumb :show end end diff --git a/app/controllers/referential_networks_controller.rb b/app/controllers/referential_networks_controller.rb index ee2db8008..2131b8e57 100644 --- a/app/controllers/referential_networks_controller.rb +++ b/app/controllers/referential_networks_controller.rb @@ -18,8 +18,6 @@ class ReferentialNetworksController < ChouetteController referential: referential } ) - - build_breadcrumb :show end end @@ -36,8 +34,6 @@ class ReferentialNetworksController < ChouetteController format.js { @networks = decorate_networks(@networks) } - - build_breadcrumb :index end end diff --git a/app/controllers/referential_stop_areas_controller.rb b/app/controllers/referential_stop_areas_controller.rb index 7519418e7..78dcd6dd9 100644 --- a/app/controllers/referential_stop_areas_controller.rb +++ b/app/controllers/referential_stop_areas_controller.rb @@ -14,31 +14,26 @@ class ReferentialStopAreasController < ChouetteController def select_parent @stop_area = stop_area @parent = stop_area.parent - build_breadcrumb :edit end def add_children @stop_area = stop_area @children = stop_area.children - build_breadcrumb :edit end def add_routing_lines @stop_area = stop_area @lines = stop_area.routing_lines - build_breadcrumb :edit end def add_routing_stops @stop_area = stop_area - build_breadcrumb :edit end def access_links @stop_area = stop_area @generic_access_links = stop_area.generic_access_link_matrix @detail_access_links = stop_area.detail_access_link_matrix - build_breadcrumb :edit end def index @@ -49,7 +44,6 @@ class ReferentialStopAreasController < ChouetteController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - build_breadcrumb :index } end end @@ -57,9 +51,7 @@ class ReferentialStopAreasController < ChouetteController def new @map = StopAreaMap.new( Chouette::StopArea.new).with_helpers(self) @map.editable = true - new! do - build_breadcrumb :show - end + new! end def create @@ -81,8 +73,6 @@ class ReferentialStopAreasController < ChouetteController end @stop_area = @stop_area.decorate - - build_breadcrumb :show end end @@ -90,7 +80,6 @@ class ReferentialStopAreasController < ChouetteController edit! do stop_area.position ||= stop_area.default_position map.editable = true - build_breadcrumb :edit end end diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index c8984076a..6b479e938 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -1,4 +1,4 @@ -class ReferentialsController < BreadcrumbController +class ReferentialsController < InheritedResources::Base defaults :resource_class => Referential include PolicyChecker @@ -18,8 +18,6 @@ class ReferentialsController < BreadcrumbController if !!@referential.created_from_id format.html { redirect_to workbench_path(@referential.workbench) } - else - build_breadcrumb :new end end end @@ -45,7 +43,6 @@ class ReferentialsController < BreadcrumbController :time_tables_count => resource.time_tables.count, :referential_id => resource.id} } - format.html { build_breadcrumb :show} end end diff --git a/app/controllers/route_sections_controller.rb b/app/controllers/route_sections_controller.rb index c1aaf732e..03d6cf176 100644 --- a/app/controllers/route_sections_controller.rb +++ b/app/controllers/route_sections_controller.rb @@ -8,14 +8,9 @@ class RouteSectionsController < ChouetteController belongs_to :referential before_action :save_return_to_path, only: [:edit, :create_to_edit] - before_action ->(controller) { build_breadcrumb controller.action_name } helper_method :search - def index - index! - end - def new @stop_areas = referential.stop_areas.with_geometry.order :name new! diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb index 78daffb30..93f30f4d5 100644 --- a/app/controllers/routes_controller.rb +++ b/app/controllers/routes_controller.rb @@ -19,7 +19,6 @@ class RoutesController < ChouetteController def edit_boarding_alighting @route = route - build_breadcrumb :edit end def save_boarding_alighting @@ -51,8 +50,6 @@ class RoutesController < ChouetteController @route_sp, with: StopPointDecorator ) - - build_breadcrumb :show end end diff --git a/app/controllers/routing_constraint_zones_controller.rb b/app/controllers/routing_constraint_zones_controller.rb index 78cd0e209..6c3da5980 100644 --- a/app/controllers/routing_constraint_zones_controller.rb +++ b/app/controllers/routing_constraint_zones_controller.rb @@ -20,8 +20,6 @@ class RoutingConstraintZonesController < ChouetteController line: parent } ) - - build_breadcrumb :index end end @@ -31,8 +29,6 @@ class RoutingConstraintZonesController < ChouetteController referential: referential, line: parent }) - - build_breadcrumb :show end end diff --git a/app/controllers/rule_parameter_sets_controller.rb b/app/controllers/rule_parameter_sets_controller.rb index 6a23407d0..de4863a08 100644 --- a/app/controllers/rule_parameter_sets_controller.rb +++ b/app/controllers/rule_parameter_sets_controller.rb @@ -1,15 +1,13 @@ -class RuleParameterSetsController < BreadcrumbController +class RuleParameterSetsController < InheritedResources::Base defaults :resource_class => RuleParameterSet respond_to :html respond_to :js, :only => [ :mode ] def new @rule_parameter_set = RuleParameterSet.default( current_organisation) - new! do - build_breadcrumb :new - end + new! end - + def destroy if current_organisation.rule_parameter_sets.count == 1 flash[:alert] = t('rule_parameter_sets.destroy.last_rps_protected') diff --git a/app/controllers/stop_area_referentials_controller.rb b/app/controllers/stop_area_referentials_controller.rb index 5c87be43d..e2815e5fb 100644 --- a/app/controllers/stop_area_referentials_controller.rb +++ b/app/controllers/stop_area_referentials_controller.rb @@ -1,4 +1,4 @@ -class StopAreaReferentialsController < BreadcrumbController +class StopAreaReferentialsController < InheritedResources::Base defaults :resource_class => StopAreaReferential def sync diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index cdb7c59ab..0c9f3067a 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -class StopAreasController < BreadcrumbController +class StopAreasController < InheritedResources::Base include ApplicationHelper defaults :resource_class => Chouette::StopArea @@ -22,32 +22,27 @@ class StopAreasController < BreadcrumbController def select_parent @stop_area = stop_area @parent = stop_area.parent - build_breadcrumb :edit end def add_children authorize stop_area @stop_area = stop_area @children = stop_area.children - build_breadcrumb :edit end def add_routing_lines @stop_area = stop_area @lines = stop_area.routing_lines - build_breadcrumb :edit end def add_routing_stops @stop_area = stop_area - build_breadcrumb :edit end def access_links @stop_area = stop_area @generic_access_links = stop_area.generic_access_link_matrix @detail_access_links = stop_area.detail_access_link_matrix - build_breadcrumb :edit end def index @@ -64,8 +59,6 @@ class StopAreasController < BreadcrumbController @stop_areas, with: StopAreaDecorator ) - - build_breadcrumb :index } end end @@ -74,9 +67,7 @@ class StopAreasController < BreadcrumbController authorize resource_class @map = StopAreaMap.new( Chouette::StopArea.new).with_helpers(self) @map.editable = true - new! do - build_breadcrumb :show - end + new! end def create @@ -99,8 +90,6 @@ class StopAreasController < BreadcrumbController end @stop_area = @stop_area.decorate - - build_breadcrumb :show end end @@ -109,7 +98,6 @@ class StopAreasController < BreadcrumbController edit! do stop_area.position ||= stop_area.default_position map.editable = true - build_breadcrumb :edit end end diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb index af74f635f..0c1769ad7 100644 --- a/app/controllers/time_tables_controller.rb +++ b/app/controllers/time_tables_controller.rb @@ -19,7 +19,6 @@ class TimeTablesController < ChouetteController @time_table = @time_table.decorate(context: { referential: @referential }) - build_breadcrumb :show end end @@ -30,9 +29,7 @@ class TimeTablesController < ChouetteController def new @autocomplete_items = ActsAsTaggableOn::Tag.all - new! do - build_breadcrumb :new - end + new! end def create @@ -66,7 +63,6 @@ class TimeTablesController < ChouetteController def edit edit! do - build_breadcrumb :edit @autocomplete_items = ActsAsTaggableOn::Tag.all end end @@ -89,8 +85,6 @@ class TimeTablesController < ChouetteController end @time_tables = decorate_time_tables(@time_tables) - - build_breadcrumb :index } format.js { @@ -101,8 +95,6 @@ class TimeTablesController < ChouetteController def duplicate @time_table = Chouette::TimeTable.find params[:id] - # prepare breadcrumb before prepare data for new timetable - build_breadcrumb :edit @time_table = @time_table.duplicate render :new end diff --git a/app/controllers/timebands_controller.rb b/app/controllers/timebands_controller.rb index 446255cac..765557193 100644 --- a/app/controllers/timebands_controller.rb +++ b/app/controllers/timebands_controller.rb @@ -6,14 +6,7 @@ class TimebandsController < ChouetteController belongs_to :referential - def new - new! do - build_breadcrumb :new - end - end - private - def timeband_params params.require(:timeband).permit( :name, :start_time, :end_time ) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 23ce3ef0a..2452a2796 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,4 @@ -class UsersController < BreadcrumbController +class UsersController < InheritedResources::Base defaults :resource_class => User diff --git a/app/controllers/vehicle_journey_imports_controller.rb b/app/controllers/vehicle_journey_imports_controller.rb index 2e2a3a718..58f8816aa 100644 --- a/app/controllers/vehicle_journey_imports_controller.rb +++ b/app/controllers/vehicle_journey_imports_controller.rb @@ -12,9 +12,7 @@ class VehicleJourneyImportsController < ChouetteController def new @vehicle_journey_import = VehicleJourneyImport.new(:route => route) - new! do - build_breadcrumb :new - end + new! end def create diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb index 70cca15ed..050f2f219 100644 --- a/app/controllers/vehicle_journeys_controller.rb +++ b/app/controllers/vehicle_journeys_controller.rb @@ -76,7 +76,6 @@ class VehicleJourneysController < ChouetteController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end - build_breadcrumb :index end end diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb index e271007d6..9b4f0d6c4 100644 --- a/app/controllers/workbenches_controller.rb +++ b/app/controllers/workbenches_controller.rb @@ -1,4 +1,4 @@ -class WorkbenchesController < BreadcrumbController +class WorkbenchesController < InheritedResources::Base before_action :query_params, only: [:show] include RansackDateFilter before_action only: [:show] { set_date_time_params("validity_period", Date) } @@ -25,9 +25,7 @@ class WorkbenchesController < BreadcrumbController current_workbench_id: params[:id] } ) - show! do - build_breadcrumb :show - end + show! end def delete_referentials diff --git a/app/helpers/breadcrumb_helper.rb b/app/helpers/breadcrumb_helper.rb deleted file mode 100644 index da1f270ab..000000000 --- a/app/helpers/breadcrumb_helper.rb +++ /dev/null @@ -1,310 +0,0 @@ -# coding: utf-8 -module BreadcrumbHelper - - def build_breadcrumb(action) - action = action.to_sym - case resource_class.to_s - when "Chouette::Network" - network_breadcrumb action - when "Chouette::Company" - company_breadcrumb action - when "Chouette::GroupOfLine" - group_of_line_breadcrumb action - when "Chouette::Line" - line_breadcrumb action - when "Chouette::Route" - route_breadcrumb action - when "Chouette::JourneyPattern" - journey_pattern_breadcrumb action - when "Chouette::VehicleJourney" - vehicle_journey_breadcrumb action - when "Chouette::VehicleJourneyFrequency" - vehicle_journey_frequency_breadcrumb action - when "VehicleJourneyImport" - vehicle_journey_import_breadcrumb action - when "Chouette::StopArea" - stop_area_breadcrumb action - when "Chouette::AccessPoint" - access_point_breadcrumb action - when "Chouette::AccessLink" - access_link_breadcrumb action - when "Chouette::ConnectionLink" - connection_link_breadcrumb action - when "Chouette::TimeTable" - time_table_breadcrumb action - when "Chouette::RouteSection" - route_section_breadcrumb action - when "Chouette::Timeband" - timeband_breadcrumb action - when 'Chouette::RoutingConstraintZone' - routing_constraint_zone_breadcrumb action - when 'Calendar' - calendar_breadcrumb action - when "StopAreaCopy" - stop_area_copy_breadcrumb action - when "Import" - import_breadcrumb action - when "Export" - export_breadcrumb action - when "ComplianceCheck" - compliance_check_breadcrumb action - when "ComplianceCheckTask" - compliance_check_task_breadcrumb action - when "ComplianceControlSets" - compliance_control_sets_breadcrumb action - when "RuleParameterSet" - rule_parameter_breadcrumb action - when "User" - user_breadcrumb action - when "Referential" - referential_breadcrumb action - when "LineReferential" - line_referential_breadcrumb action - when "Organisation" - organisation_breadcrumb action - when "Api::V1::ApiKey" - referential_breadcrumb - when "Workbench" - workbench_breadcrumb action - else - Rails.logger.info "---------" - Rails.logger.info ">>>>>>> "+resource_class.to_s+" unmapped" - Rails.logger.info "---------" - organisation_breadcrumb :index - end - end - - def calendar_breadcrumb(action) - add_breadcrumb I18n.t('breadcrumbs.root'), root_path - add_breadcrumb I18n.t('calendars.index.title'), calendars_path - add_breadcrumb @calendar.name if %i(show edit).include? action - end - - def workbench_breadcrumb(action) - add_breadcrumb I18n.t("breadcrumbs.root"), root_path - add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench) - end - - def network_breadcrumb(action) - if @line_referential - line_referential_breadcrumb - add_breadcrumb Chouette::Network.model_name.human(:count => 2).capitalize, line_referential_networks_path(@line_referential) unless action == :index - add_breadcrumb breadcrumb_label(@network), line_referential_network_path(@line_referential, @network),:title => breadcrumb_tooltip(@network) if action == :edit - else - referential_breadcrumb - add_breadcrumb Chouette::Network.model_name.human(:count => 2).capitalize, referential_networks_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@network), referential_network_path(@referential, @network),:title => breadcrumb_tooltip(@network) if action == :edit - end - end - - def group_of_line_breadcrumb(action) - if @line_referential - line_referential_breadcrumb - add_breadcrumb Chouette::GroupOfLine.model_name.human(:count => 2).capitalize, line_referential_group_of_lines_path(@line_referential) unless action == :index - add_breadcrumb breadcrumb_label(@group_of_line), line_referential_group_of_line_path(@line_referential, @group_of_line),:title => breadcrumb_tooltip(@group_of_line) if action == :edit - else - referential_breadcrumb - add_breadcrumb Chouette::GroupOfLine.model_name.human(:count => 2).capitalize, referential_group_of_lines_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@group_of_line), referential_group_of_line_path(@referential, @group_of_line),:title => breadcrumb_tooltip(@group_of_line) if action == :edit - end - end - - def stop_area_breadcrumb(action) - referential_breadcrumb - add_breadcrumb Chouette::StopArea.model_name.human(:count => 2).capitalize, stop_area_referential_stop_areas_path(@stop_area.stop_area_referential) unless action == :index - add_breadcrumb breadcrumb_label(@stop_area), stop_area_referential_stop_area_path(@stop_area.stop_area_referential, @stop_area),:title => breadcrumb_tooltip(@stop_area) if action == :edit - end - - def stop_area_copy_breadcrumb(action) - stop_area_breadcrumb :edit - end - - def access_point_breadcrumb(action) - stop_area_breadcrumb :edit - add_breadcrumb breadcrumb_label(@access_point), referential_stop_area_access_point_path(@referential, @access_point.stop_area,@access_point),:title => breadcrumb_tooltip(@access_point) if action == :edit - end - - def access_link_breadcrumb(action) - access_point_breadcrumb :edit - add_breadcrumb Chouette::AccessLink.model_name.human(:count => 2).capitalize.capitalize, access_links_referential_stop_area_path(@referential, @stop_area) - add_breadcrumb breadcrumb_label(@access_link), referential_access_point_access_link_path(@referential, @access_point,@access_link),:title => breadcrumb_tooltip(@access_link) if action == :edit - end - - def connection_link_breadcrumb(action) - referential_breadcrumb - add_breadcrumb Chouette::ConnectionLink.model_name.human.pluralize.capitalize, referential_connection_links_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@connection_link), referential_connection_link_path(@referential, @connection_link),:title => breadcrumb_tooltip(@connection_link) if action == :edit - end - - def time_table_breadcrumb(action) - referential_breadcrumb - add_breadcrumb Chouette::TimeTable.model_name.human(:count => 2).capitalize, referential_time_tables_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@time_table), referential_time_table_path(@referential, @time_table),:title => breadcrumb_tooltip(@time_table) if action == :edit - end - - def route_section_breadcrumb(action) - referential_breadcrumb - add_breadcrumb Chouette::RouteSection.model_name.human.pluralize, referential_route_sections_path(@referential) - add_breadcrumb breadcrumb_label(resource), referential_route_section_path(@referential, resource),:title => breadcrumb_tooltip(resource) if action.in?([:show, :edit]) - end - - def timeband_breadcrumb(action) - referential_breadcrumb - add_breadcrumb Chouette::Timeband.model_name.human(:count => 2).capitalize, referential_timebands_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@timeband), referential_timeband_path(@referential, @timeband),:title => breadcrumb_tooltip(@timeband) if action == :edit - end - - def line_breadcrumb(action) - if @line_referential - line_referential_breadcrumb - add_breadcrumb Chouette::Line.model_name.human(:count => 2).capitalize, line_referential_lines_path(@line_referential) unless action == :index - add_breadcrumb breadcrumb_label(@line), line_referential_line_path(@line_referential, @line),:title => breadcrumb_tooltip(@line) if action == :edit - else - referential_breadcrumb - add_breadcrumb breadcrumb_label(@line), referential_line_path(@referential, @line),:title => breadcrumb_tooltip(@line) if action == :edit - end - end - - def route_breadcrumb(action) - line_breadcrumb :edit - add_breadcrumb breadcrumb_label(@route), referential_line_route_path(@referential, @line,@route),:title => breadcrumb_tooltip(@route) if action == :edit - end - - def routing_constraint_zone_breadcrumb(action) - line_breadcrumb :edit - add_breadcrumb Chouette::RoutingConstraintZone.model_name.human.pluralize(:fr), referential_line_routing_constraint_zones_path(@referential, @line) unless action == :index - add_breadcrumb breadcrumb_label(@routing_constraint_zone), referential_line_routing_constraint_zone_path(@referential, @line, @routing_constraint_zone), title: breadcrumb_tooltip(@routing_constraint_zone) if %i(show edit).include? action - end - - def journey_pattern_breadcrumb(action) - route_breadcrumb :edit - add_breadcrumb breadcrumb_label(@journey_pattern), referential_line_route_journey_pattern_path(@referential, @line,@route,@journey_pattern),:title => breadcrumb_tooltip(@journey_pattern) if action == :edit - end - - def vehicle_journey_breadcrumb(action) - route_breadcrumb :edit - add_breadcrumb I18n.t("breadcrumbs.vehicle_journeys"), referential_line_route_vehicle_journeys_path(@referential, @line,@route) unless action == :index - add_breadcrumb breadcrumb_label(@vehicle_journey), referential_line_route_vehicle_journey_path(@referential, @line,@route,@vehicle_journey),:title => breadcrumb_tooltip(@vehicle_journey) if action == :edit - end - - def vehicle_journey_frequency_breadcrumb(action) - route_breadcrumb :edit - add_breadcrumb I18n.t("breadcrumbs.vehicle_journey_frequencies"), referential_line_route_vehicle_journey_frequencies_path(@referential, @line, @route) unless action == :index - add_breadcrumb breadcrumb_label(@vehicle_journey_frequency), referential_line_route_vehicle_journey_frequency_path(@referential, @line,@route, @vehicle_journey_frequency),:title => breadcrumb_tooltip(@vehicle_journey_frequency) if action == :edit - end - - def vehicle_journey_import_breadcrumb (action) - route_breadcrumb :edit - end - - def line_referential_breadcrumb(action = :edit) - organisation_breadcrumb - if @line_referential - add_breadcrumb breadcrumb_label(@line_referential), line_referential_path(@line_referential), :title => breadcrumb_tooltip(@line_referential) if action == :edit || action == :show || action == :update - end - end - - def company_breadcrumb (action) - if @line_referential - line_referential_breadcrumb - add_breadcrumb Chouette::Company.model_name.human(:count => 2).capitalize, line_referential_companies_path(@line_referential) unless action == :index - add_breadcrumb breadcrumb_label(@company), line_referential_company_path(@line_referential, @company),:title => breadcrumb_tooltip(@company) if action == :edit - else - referential_breadcrumb - add_breadcrumb Chouette::Company.model_name.human(:count => 2).capitalize, referential_companies_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@company), referential_company_path(@referential, @company),:title => breadcrumb_tooltip(@company) if action == :edit - end - end - - def import_breadcrumb (action) - add_breadcrumb I18n.t("breadcrumbs.root"), root_path - add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench) - add_breadcrumb I18n.t("breadcrumbs.imports"), workbench_imports_path(@workbench) - - end - - def export_breadcrumb (action) - referential_breadcrumb - add_breadcrumb Referential.human_attribute_name("exports"), referential_exports_path(@referential) unless action == :index - end - - def compliance_check_breadcrumb (action) - referential_breadcrumb - add_breadcrumb Referential.human_attribute_name("compliance_checks"), referential_compliance_checks_path(@referential) unless action == :index - add_breadcrumb @compliance_check.name, referential_compliance_check_path(@referential, @compliance_check.id) if @compliance_check - add_breadcrumb t("compliance_checks.rule_parameter_set"), rule_parameter_set_referential_compliance_check_path(@referential, @rule_parameter_set.compliance_check.id) if action == :rule_parameter_set - end - - def compliance_check_task_breadcrumb (action) - referential_breadcrumb - add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) unless action == :index - add_breadcrumb breadcrumb_label(@compliance_check_task), referential_compliance_check_task_path(@referential, @compliance_check_task),:title => breadcrumb_tooltip(@compliance_check_task) if action == :edit - end - - def compliance_control_sets_breadcrumb (action) - add_breadcrumb I18n.t("breadcrumbs.root"), root_path - #add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench) - end - - def rule_parameter_breadcrumb (action) - organisation_breadcrumb - add_breadcrumb Referential.human_attribute_name("rule_parameter_sets"), organisation_path unless action == :index - add_breadcrumb breadcrumb_label(@rule_parameter_set), organisation_rule_parameter_set_path(@rule_parameter_set),:title => breadcrumb_tooltip(@rule_parameter_set) if action == :edit - end - - def referential_breadcrumb (action = :edit) - organisation_breadcrumb - if @referential - if workbench = @referential.workbench - add_breadcrumb breadcrumb_label(workbench), workbench_path(workbench), :title => breadcrumb_tooltip(workbench) - end - - add_breadcrumb breadcrumb_label(@referential), referential_path(@referential),:title => breadcrumb_tooltip(@referential) if action == :edit || action == :show || action == :update - end - end - - def organisation_breadcrumb (action = :index) - add_breadcrumb I18n.t("breadcrumbs.root"), root_path - add_breadcrumb breadcrumb_label(@organisation), organisation_path,:title => breadcrumb_tooltip(@organisation) unless action == :index - end - - def user_breadcrumb (action) - organisation_breadcrumb - add_breadcrumb I18n.t("breadcrumbs.users"), organisation_path unless action == :index - add_breadcrumb breadcrumb_label(@user), organisation_user_path(@user),:title => breadcrumb_tooltip(@user) if action == :edit - end - - def breadcrumb_label(obj) - label = breadcrumb_name(obj) - if label.blank? - label = obj.class.model_name.human+" "+obj.id.to_s - end - - if label.length > 20 - label[0..16]+"..." - else - label - end - end - - def breadcrumb_tooltip(obj) - label = breadcrumb_name(obj) - if label.blank? - label = obj.class.model_name.human+" ("+obj.id.to_s+")" - else - label = obj.class.model_name.human+" : "+label - end - label - end - - def breadcrumb_name(obj) - label = "" - if obj.respond_to?('name') - label = obj.name - elsif obj.respond_to?('comment') - label = obj.comment - end - label - end - -end diff --git a/app/javascript/journey_patterns/actions/index.js b/app/javascript/journey_patterns/actions/index.js index 0c1cb5f5c..8bea5a990 100644 --- a/app/javascript/journey_patterns/actions/index.js +++ b/app/javascript/journey_patterns/actions/index.js @@ -90,7 +90,10 @@ const actions = { resetValidation: (target) => { $(target).parent().removeClass('has-error').children('.help-block').remove() }, - humanOID : (oid) => oid.split(':')[2].split("-").pop(), + humanOID : (oid) => { + let shortOId = oid.split(':')[2].split("-").pop() + return shortOId.length > 10 ? `${shortOId.slice(0, 10)}...` : shortOId + }, validateFields : (fields) => { const test = [] diff --git a/app/javascript/journey_patterns/components/EditModal.js b/app/javascript/journey_patterns/components/EditModal.js index 699f89b85..e7ce24aa1 100644 --- a/app/javascript/journey_patterns/components/EditModal.js +++ b/app/javascript/journey_patterns/components/EditModal.js @@ -13,6 +13,19 @@ export default class EditModal extends Component { } } + renderModalTitle() { + if (this.props.editMode) { + return ( + <h4 className='modal-title'> + Editer la mission + {this.props.modal.type == 'edit' && <em> "{this.props.modal.modalProps.journeyPattern.name}"</em>} + </h4> + ) + } else { + return <h4 className='modal-title'> Informations </h4> + } + } + render() { return ( <div className={ 'modal fade ' + ((this.props.modal.type == 'edit') ? 'in' : '') } id='JourneyPatternModal'> @@ -20,12 +33,8 @@ export default class EditModal extends Component { <div className='modal-dialog'> <div className='modal-content'> <div className='modal-header'> - <h4 className='modal-title'> - Editer la mission - {(this.props.modal.type == 'edit') && ( - <em> "{this.props.modal.modalProps.journeyPattern.name}"</em> - )} - </h4> + {this.renderModalTitle()} + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'edit') && ( @@ -37,6 +46,7 @@ export default class EditModal extends Component { type='text' ref='name' className='form-control' + disabled={!this.props.editMode} id={this.props.modal.modalProps.index} defaultValue={this.props.modal.modalProps.journeyPattern.name} onKeyDown={(e) => actions.resetValidation(e.currentTarget)} @@ -52,6 +62,7 @@ export default class EditModal extends Component { type='text' ref='published_name' className='form-control' + disabled={!this.props.editMode} id={this.props.modal.modalProps.index} defaultValue={this.props.modal.modalProps.journeyPattern.published_name} onKeyDown={(e) => actions.resetValidation(e.currentTarget)} @@ -66,6 +77,7 @@ export default class EditModal extends Component { type='text' ref='registration_number' className='form-control' + disabled={!this.props.editMode} id={this.props.modal.modalProps.index} defaultValue={this.props.modal.modalProps.journeyPattern.registration_number} onKeyDown={(e) => actions.resetValidation(e.currentTarget)} @@ -74,24 +86,26 @@ export default class EditModal extends Component { </div> </div> </div> - - <div className='modal-footer'> - <button - className='btn btn-link' - data-dismiss='modal' - type='button' - onClick={this.props.onModalClose} + { + this.props.editMode && + <div className='modal-footer'> + <button + className='btn btn-link' + data-dismiss='modal' + type='button' + onClick={this.props.onModalClose} > - Annuler - </button> - <button - className='btn btn-primary' - type='button' - onClick={this.handleSubmit.bind(this)} + Annuler + </button> + <button + className='btn btn-primary' + type='button' + onClick={this.handleSubmit.bind(this)} > - Valider - </button> - </div> + Valider + </button> + </div> + } </form> )} </div> diff --git a/app/javascript/journey_patterns/components/JourneyPattern.js b/app/javascript/journey_patterns/components/JourneyPattern.js index dde73a957..34d102c5d 100644 --- a/app/javascript/journey_patterns/components/JourneyPattern.js +++ b/app/javascript/journey_patterns/components/JourneyPattern.js @@ -56,7 +56,7 @@ export default class JourneyPattern extends Component{ } isDisabled(action) { - return !this.props.status.policy[`journey_patterns.${action}`] && !this.props.editMode + return !this.props.status.policy[`journey_patterns.${action}`] } render() { @@ -88,16 +88,17 @@ export default class JourneyPattern extends Component{ data-toggle='modal' data-target='#JourneyPatternModal' > - Editer + {this.props.editMode ? 'Editer' : 'Consulter'} </button> </li> <li className={this.props.value.object_id ? '' : 'disabled'}> {this.vehicleJourneyURL(this.props.value.object_id)} </li> - <li className={'delete-action' + (this.isDisabled('destroy') ? ' disabled' : '')}> + <li className={'delete-action' + (this.isDisabled('destroy') || !this.props.editMode ? ' disabled' : '')}> <button type='button' - disabled={this.isDisabled('destroy') ? 'disabled' : ''} + className="disabled" + disabled={this.isDisabled('destroy') || !this.props.editMode} onClick={(e) => { e.preventDefault() this.props.onDeleteJourneyPattern(this.props.index)} diff --git a/app/javascript/journey_patterns/containers/Modal.js b/app/javascript/journey_patterns/containers/Modal.js index ace71a857..33ee8583c 100644 --- a/app/javascript/journey_patterns/containers/Modal.js +++ b/app/javascript/journey_patterns/containers/Modal.js @@ -5,6 +5,7 @@ import CreateModal from '../components/CreateModal' const mapStateToProps = (state) => { return { + editMode: state.editMode, modal: state.modal, journeyPattern: state.journeyPattern } diff --git a/app/javascript/vehicle_journeys/actions/index.js b/app/javascript/vehicle_journeys/actions/index.js index 4272c7915..95c739893 100644 --- a/app/javascript/vehicle_journeys/actions/index.js +++ b/app/javascript/vehicle_journeys/actions/index.js @@ -269,7 +269,10 @@ const actions = { type: 'RECEIVE_TOTAL_COUNT', total }), - humanOID: (oid) => oid.split(':')[2].split("-").pop(), + humanOID: (oid) => { + let shortOId = oid.split(':')[2].split("-").pop() + return shortOId.length > 10 ? `${shortOId.slice(0, 10)}...` : shortOId + }, fetchVehicleJourneys : (dispatch, currentPage, nextPage, queryString) => { if(currentPage == undefined){ currentPage = 1 @@ -458,6 +461,10 @@ const actions = { } } }, + escapeWildcardCharacters(search) { + let newSearch = search.replace(/^_/, "\\_") + return newSearch.replace(/^%/, "\\%") + } } export default actions diff --git a/app/javascript/vehicle_journeys/components/Tools.js b/app/javascript/vehicle_journeys/components/Tools.js index a717408b9..7621dfc10 100644 --- a/app/javascript/vehicle_journeys/components/Tools.js +++ b/app/javascript/vehicle_journeys/components/Tools.js @@ -1,4 +1,4 @@ -import React, { PropTypes } from 'react' +import React, { PropTypes, Component } from 'react' import actions from '../actions' import AddVehicleJourney from '../containers/tools/AddVehicleJourney' import DeleteVehicleJourneys from '../containers/tools/DeleteVehicleJourneys' @@ -8,28 +8,37 @@ import EditVehicleJourney from '../containers/tools/EditVehicleJourney' import NotesEditVehicleJourney from '../containers/tools/NotesEditVehicleJourney' import TimetablesEditVehicleJourney from '../containers/tools/TimetablesEditVehicleJourney' -export default function Tools({vehicleJourneys, onCancelSelection, filters: {policy}, editMode}) { - return ( - <div> - { - (policy['vehicle_journeys.create'] && policy['vehicle_journeys.update'] && policy['vehicle_journeys.destroy'] && editMode) && - <div className='select_toolbox'> - <ul> - <AddVehicleJourney /> - <DuplicateVehicleJourney /> - <ShiftVehicleJourney /> - <EditVehicleJourney /> - <TimetablesEditVehicleJourney /> - <NotesEditVehicleJourney /> - <DeleteVehicleJourneys /> - </ul> - <span className='info-msg'>{actions.getSelected(vehicleJourneys).length} course(s) sélectionnée(s)</span> - <button className='btn btn-xs btn-link pull-right' onClick={onCancelSelection}>Annuler la sélection</button> - </div> - } - </div> - ) +export default class Tools extends Component { + constructor(props) { + super(props) + this.hasPolicy = this.hasPolicy.bind(this) + } + + hasPolicy(key) { + // Check if the user has the policy to disable or not the action + return this.props.filters.policy[`vehicle_journeys.${key}`] + } + + render() { + let { vehicleJourneys, onCancelSelection, editMode } = this.props + return ( + <div className='select_toolbox'> + <ul> + <AddVehicleJourney disabled={this.hasPolicy("create") && !editMode} /> + <DuplicateVehicleJourney disabled={this.hasPolicy("create") && this.hasPolicy("update") && !editMode}/> + <ShiftVehicleJourney disabled={this.hasPolicy("update") && !editMode}/> + <EditVehicleJourney disabled={!this.hasPolicy("update")}/> + <TimetablesEditVehicleJourney disabled={!this.hasPolicy("update")}/> + <NotesEditVehicleJourney disabled={!this.hasPolicy("update")}/> + <DeleteVehicleJourneys disabled={this.hasPolicy("destroy") && !editMode}/> + </ul> + + <span className='info-msg'>{actions.getSelected(vehicleJourneys).length} course(s) sélectionnée(s)</span> + <button className='btn btn-xs btn-link pull-right' onClick={onCancelSelection}>Annuler la sélection</button> + </div> + ) + } } Tools.propTypes = { diff --git a/app/javascript/vehicle_journeys/components/VehicleJourney.js b/app/javascript/vehicle_journeys/components/VehicleJourney.js index cb5407f81..13f8eced2 100644 --- a/app/javascript/vehicle_journeys/components/VehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/VehicleJourney.js @@ -44,6 +44,7 @@ export default class VehicleJourney extends Component { render() { this.previousCity = undefined + let {time_tables} = this.props.value return ( <div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.errors ? ' has-error': '')}> @@ -51,39 +52,37 @@ export default class VehicleJourney extends Component { <div className='strong mb-xs'>{this.props.value.objectid ? actions.humanOID(this.props.value.objectid) : '-'}</div> <div>{actions.humanOID(this.props.value.journey_pattern.objectid)}</div> <div> - {this.props.value.time_tables.map((tt, i)=> + {time_tables.slice(0,3).map((tt, i)=> <span key={i} className='vj_tt'>{this.timeTableURL(tt)}</span> )} + {time_tables.length > 3 && <span className='vj_tt'> + {time_tables.length - 3}</span>} + </div> + <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}> + <input + id={this.props.index} + name={this.props.index} + style={{display: 'none'}} + onChange={(e) => this.props.onSelectVehicleJourney(this.props.index)} + type='checkbox' + disabled={this.props.value.deletable} + checked={this.props.value.selected} + ></input> + <label htmlFor={this.props.index}></label> </div> - - {(this.props.filters.policy['vehicle_journeys.update'] == true && this.props.editMode) && - <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}> - <input - id={this.props.index} - name={this.props.index} - style={{display: 'none'}} - onChange={(e) => this.props.onSelectVehicleJourney(this.props.index)} - type='checkbox' - disabled={this.props.value.deletable} - checked={this.props.value.selected} - ></input> - <label htmlFor={this.props.index}></label> - </div> - } - </div> {this.props.value.vehicle_journey_at_stops.map((vj, i) => <div key={i} className='td text-center'> <div className={'cellwrap' + (this.cityNameChecker(vj) ? ' headlined' : '')}> {this.props.filters.toggleArrivals && <div data-headline='Arrivée à'> - <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false) ? 'disabled ' : '') + 'input-group time'}> + <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false) ? 'disabled ' : '') + 'input-group time'}> <input type='number' min='00' max='23' className='form-control' - disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)} + disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false} + readOnly={!this.props.editMode && !vj.dummy} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', false, false)}} value={vj.arrival_time['hour']} /> @@ -93,7 +92,8 @@ export default class VehicleJourney extends Component { min='00' max='59' className='form-control' - disabled={((this.isDisabled(this.props.value.deletable), vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)} + disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false} + readOnly={!this.props.editMode && !vj.dummy} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'minute', false, false)}} value={vj.arrival_time['minute']} /> @@ -106,13 +106,14 @@ export default class VehicleJourney extends Component { } </div> <div data-headline='Départ à'> - <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false) ? 'disabled ' : '') + 'input-group time'}> + <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false) ? 'disabled ' : '') + 'input-group time'}> <input type='number' min='00' max='23' className='form-control' - disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)} + disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false} + readOnly={!this.props.editMode && !vj.dummy} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', true, this.props.filters.toggleArrivals)}} value={vj.departure_time['hour']} /> @@ -122,7 +123,8 @@ export default class VehicleJourney extends Component { min='00' max='59' className='form-control' - disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)} + disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false} + readOnly={!this.props.editMode && !vj.dummy} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, "minute", true, this.props.filters.toggleArrivals)}} value={vj.departure_time['minute']} /> diff --git a/app/javascript/vehicle_journeys/components/tools/CreateModal.js b/app/javascript/vehicle_journeys/components/tools/CreateModal.js index 5b5e2f849..2bffebdf6 100644 --- a/app/javascript/vehicle_journeys/components/tools/CreateModal.js +++ b/app/javascript/vehicle_journeys/components/tools/CreateModal.js @@ -25,7 +25,7 @@ export default class CreateModal extends Component { <li className='st_action'> <button type='button' - disabled={((this.props.filters.policy['vehicle_journeys.update'] == true) ? '' : 'disabled')} + disabled={(this.props.disabled) } data-toggle='modal' data-target='#NewVehicleJourneyModal' onClick={this.props.onOpenCreateModal} @@ -39,6 +39,7 @@ export default class CreateModal extends Component { <div className='modal-content'> <div className='modal-header'> <h4 className='modal-title'>Ajouter une course</h4> + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'create') && ( @@ -127,5 +128,6 @@ CreateModal.propTypes = { onOpenCreateModal: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired, onAddVehicleJourney: PropTypes.func.isRequired, - onSelect2JourneyPattern: PropTypes.func.isRequired + onSelect2JourneyPattern: PropTypes.func.isRequired, + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js b/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js index 0a1dedd3c..fc13ae964 100644 --- a/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js +++ b/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js @@ -1,12 +1,12 @@ import React, { PropTypes } from 'react' import actions from '../../actions' -export default function DeleteVehicleJourneys({onDeleteVehicleJourneys, vehicleJourneys, filters}) { +export default function DeleteVehicleJourneys({onDeleteVehicleJourneys, vehicleJourneys, disabled}) { return ( <li className='st_action'> <button type='button' - disabled={(actions.getSelected(vehicleJourneys).length > 0 && filters.policy['vehicle_journeys.destroy']) ? '' : 'disabled'} + disabled={(actions.getSelected(vehicleJourneys).length == 0 || disabled)} onClick={e => { e.preventDefault() onDeleteVehicleJourneys() @@ -22,5 +22,5 @@ export default function DeleteVehicleJourneys({onDeleteVehicleJourneys, vehicleJ DeleteVehicleJourneys.propTypes = { onDeleteVehicleJourneys: PropTypes.func.isRequired, vehicleJourneys: PropTypes.array.isRequired, - filters: PropTypes.object.isRequired + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js index 0c1c81114..8083defb9 100644 --- a/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js @@ -8,6 +8,7 @@ export default class DuplicateVehicleJourney extends Component { this.state = {} this.onFormChange = this.onFormChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) + this.disableValidateButton = this.disableValidateButton.bind(this) } componentWillReceiveProps() { @@ -58,16 +59,26 @@ export default class DuplicateVehicleJourney extends Component { return vjas.departure_time[type] } + disableValidateButton() { + /* We disable the button in two cases : + - if the additional_time_hh or additional_time_mm are above their input max value + - if if their is no change in the other inputs to avoid making a coping of the selected VJ + */ + let incorrectDT = isNaN(this.state.duplicate_time_hh) || isNaN(this.state.duplicate_time_mm) || this.state.duplicate_time_hh > 23 || this.state.duplicate_time_mm > 59 + let noInputChanges = this.state.additional_time == 0 && this.state.originalDT.hour == this.state.duplicate_time_hh && this.state.originalDT.minute == this.state.duplicate_time_mm + return incorrectDT || noInputChanges + } + render() { if(this.props.status.isFetching == true) { return false } - if(this.props.status.fetchSuccess == true && actions.getSelected(this.props.vehicleJourneys).length > 0) { + if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> <button type='button' - disabled={((actions.getSelected(this.props.vehicleJourneys).length >= 1 && this.props.filters.policy['vehicle_journeys.update']) ? '' : 'disabled')} + disabled={(actions.getSelected(this.props.vehicleJourneys).length == 0 || this.props.disabled)} data-toggle='modal' data-target='#DuplicateVehicleJourneyModal' onClick={this.props.onOpenDuplicateModal} @@ -83,6 +94,7 @@ export default class DuplicateVehicleJourney extends Component { <h4 className='modal-title'> Dupliquer { actions.getSelected(this.props.vehicleJourneys).length > 1 ? 'plusieurs courses' : 'une course' } </h4> + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'duplicate') && ( @@ -171,6 +183,7 @@ export default class DuplicateVehicleJourney extends Component { className={'btn btn-primary ' + (this.state.additional_time == 0 && this.state.originalDT.hour == this.state.duplicate_time_hh && this.state.originalDT.minute == this.state.duplicate_time_mm ? 'disabled' : '')} type='button' onClick={this.handleSubmit} + disabled={this.disableValidateButton()} > Valider </button> @@ -192,5 +205,5 @@ export default class DuplicateVehicleJourney extends Component { DuplicateVehicleJourney.propTypes = { onOpenDuplicateModal: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired, - filters: PropTypes.object.isRequired + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js index 3a4a57024..7ad3cf510 100644 --- a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js @@ -32,7 +32,7 @@ export default class EditVehicleJourney extends Component { <li className='st_action'> <button type='button' - disabled={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.update']) ? '' : 'disabled'} + disabled={(actions.getSelected(this.props.vehicleJourneys).length != 1 || this.props.disabled)} data-toggle='modal' data-target='#EditVehicleJourneyModal' onClick={() => this.props.onOpenEditModal(actions.getSelected(this.props.vehicleJourneys)[0])} @@ -46,6 +46,7 @@ export default class EditVehicleJourney extends Component { <div className='modal-content'> <div className='modal-header'> <h4 className='modal-title'>Informations</h4> + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'edit') && ( @@ -59,6 +60,7 @@ export default class EditVehicleJourney extends Component { type='text' ref='published_journey_name' className='form-control' + disabled={!this.props.editMode} defaultValue={this.props.modal.modalProps.vehicleJourney.published_journey_name} onKeyDown={(e) => actions.resetValidation(e.currentTarget)} /> @@ -85,6 +87,7 @@ export default class EditVehicleJourney extends Component { type='text' ref='published_journey_identifier' className='form-control' + disabled={!this.props.editMode} defaultValue={this.props.modal.modalProps.vehicleJourney.published_journey_identifier} onKeyDown={(e) => actions.resetValidation(e.currentTarget)} /> @@ -94,6 +97,7 @@ export default class EditVehicleJourney extends Component { <div className='form-group'> <label className='control-label'>Transporteur</label> <CompanySelect2 + editMode={this.props.editMode} company = {this.props.modal.modalProps.vehicleJourney.company} onSelect2Company = {(e) => this.props.onSelect2Company(e)} onUnselect2Company = {() => this.props.onUnselect2Company()} @@ -127,24 +131,26 @@ export default class EditVehicleJourney extends Component { </div> </div> </div> - - <div className='modal-footer'> - <button - className='btn btn-link' - data-dismiss='modal' - type='button' - onClick={this.props.onModalClose} + { + this.props.editMode && + <div className='modal-footer'> + <button + className='btn btn-link' + data-dismiss='modal' + type='button' + onClick={this.props.onModalClose} > - Annuler + Annuler </button> - <button - className='btn btn-primary' - type='button' - onClick={this.handleSubmit.bind(this)} + <button + className='btn btn-primary' + type='button' + onClick={this.handleSubmit.bind(this)} > - Valider + Valider </button> - </div> + </div> + } </form> )} @@ -163,5 +169,5 @@ export default class EditVehicleJourney extends Component { EditVehicleJourney.propTypes = { onOpenEditModal: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired, - filters: PropTypes.object.isRequired + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js index 1958faf5f..de97bc403 100644 --- a/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js @@ -13,21 +13,25 @@ export default class NotesEditVehicleJourney extends Component { $('#NotesEditVehicleJourneyModal').modal('hide') } - renderFootnoteButton(lf, vjArray){ - let footnote_id = undefined - vjArray.forEach((f) => { - if(f.id == lf.id){ - footnote_id = f.id - } - }) + footnotes() { + let { footnotes } = this.props.modal.modalProps.vehicleJourney + let fnIds = footnotes.map(fn => fn.id) + return { + associated: footnotes, + to_associate: window.line_footnotes.filter(fn => !fnIds.includes(fn.id)) + } + } + + renderFootnoteButton(lf) { + if (!this.props.editMode) return false - if(footnote_id){ + if (this.footnotes().associated.includes(lf)) { return <button type='button' className='btn btn-outline-danger btn-xs' onClick={() => this.props.onToggleFootnoteModal(lf, false)} ><span className="fa fa-trash"></span> Retirer</button> - }else{ + } else { return <button type='button' className='btn btn-outline-primary btn-xs' @@ -36,28 +40,64 @@ export default class NotesEditVehicleJourney extends Component { } } - filterFN() { - return _.filter(window.line_footnotes, (lf, i) => { - let bool = true - _.map(this.props.modal.modalProps.vehicleJourney.footnotes, (f, j) => { - if(lf.id === f.id) { - bool = false - } - }) - return bool - }) + renderAssociatedFN() { + if (this.footnotes().associated.length == 0) { + return <h3>Aucune note associée</h3> + } else { + return ( + <div> + <h3>Notes associées :</h3> + {this.footnotes().associated.map((lf, i) => + <div + key={i} + className='panel panel-default' + > + <div className='panel-heading'> + <h4 className='panel-title clearfix'> + <div className='pull-left' style={{ paddingTop: '3px' }}>{lf.code}</div> + <div className='pull-right'>{this.renderFootnoteButton(lf, this.props.modal.modalProps.vehicleJourney.footnotes)}</div> + </h4> + </div> + <div className='panel-body'><p>{lf.label}</p></div> + </div> + )} + </div> + ) + } + } + + renderToAssociateFN() { + if (window.line_footnotes.length == 0) return <h3>La ligne ne possède pas de notes</h3> + + if (this.footnotes().to_associate.length == 0) return false + + return ( + <div> + <h3 className='mt-lg'>Sélectionnez les notes à associer à cette course :</h3> + {this.footnotes().to_associate.map((lf, i) => + <div key={i} className='panel panel-default'> + <div className='panel-heading'> + <h4 className='panel-title clearfix'> + <div className='pull-left' style={{ paddingTop: '3px' }}>{lf.code}</div> + <div className='pull-right'>{this.renderFootnoteButton(lf)}</div> + </h4> + </div> + <div className='panel-body'><p>{lf.label}</p></div> + </div> + )} + </div> + ) } render() { - if(this.props.status.isFetching == true) { - return false - } - if(this.props.status.fetchSuccess == true) { + if (this.props.status.isFetching == true) return false + + if (this.props.status.fetchSuccess == true) { return ( <li className='st_action'> <button type='button' - disabled={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.update']) ? '' : 'disabled'} + disabled={(actions.getSelected(this.props.vehicleJourneys).length != 1 || this.props.disabled)} data-toggle='modal' data-target='#NotesEditVehicleJourneyModal' onClick={() => this.props.onOpenNotesEditModal(actions.getSelected(this.props.vehicleJourneys)[0])} @@ -71,61 +111,35 @@ export default class NotesEditVehicleJourney extends Component { <div className='modal-content'> <div className='modal-header'> <h4 className='modal-title'>Notes</h4> + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'notes_edit') && ( <form> <div className='modal-body'> - <h3>Notes associées</h3> - {(this.props.modal.modalProps.vehicleJourney.footnotes).map((lf, i) => - <div - key={i} - className='panel panel-default' - > - <div className='panel-heading'> - <h4 className='panel-title clearfix'> - <div className='pull-left' style={{paddingTop: '3px'}}>{lf.code}</div> - <div className='pull-right'>{this.renderFootnoteButton(lf, this.props.modal.modalProps.vehicleJourney.footnotes)}</div> - </h4> - </div> - <div className='panel-body'><p>{lf.label}</p></div> - </div> - )} - - <h3 className='mt-lg'>Sélectionnez les notes à associer à cette course :</h3> - {this.filterFN().map((lf, i) => - <div - key={i} - className='panel panel-default' - > - <div className='panel-heading'> - <h4 className='panel-title clearfix'> - <div className='pull-left' style={{paddingTop: '3px'}}>{lf.code}</div> - <div className='pull-right'>{this.renderFootnoteButton(lf, this.props.modal.modalProps.vehicleJourney.footnotes)}</div> - </h4> - </div> - <div className='panel-body'><p>{lf.label}</p></div> - </div> - )} + {this.renderAssociatedFN()} + {this.props.editMode && this.renderToAssociateFN()} </div> - - <div className='modal-footer'> - <button - className='btn btn-link' - data-dismiss='modal' - type='button' - onClick={this.props.onModalClose} + { + this.props.editMode && + <div className='modal-footer'> + <button + className='btn btn-link' + data-dismiss='modal' + type='button' + onClick={this.props.onModalClose} > - Annuler + Annuler </button> - <button - className='btn btn-primary' - type='button' - onClick={this.handleSubmit.bind(this)} + <button + className='btn btn-primary' + type='button' + onClick={this.handleSubmit.bind(this)} > - Valider + Valider </button> - </div> + </div> + } </form> )} @@ -146,5 +160,5 @@ NotesEditVehicleJourney.propTypes = { onModalClose: PropTypes.func.isRequired, onToggleFootnoteModal: PropTypes.func.isRequired, onNotesEditVehicleJourney: PropTypes.func.isRequired, - filters: PropTypes.object.isRequired + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js index c1e2de779..175106ac5 100644 --- a/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js @@ -34,7 +34,7 @@ export default class ShiftVehicleJourney extends Component { <li className='st_action'> <button type='button' - disabled={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.update']) ? '' : 'disabled'} + disabled={(actions.getSelected(this.props.vehicleJourneys).length > 1 || this.props.disabled)} data-toggle='modal' data-target='#ShiftVehicleJourneyModal' onClick={this.props.onOpenShiftModal} @@ -51,6 +51,7 @@ export default class ShiftVehicleJourney extends Component { {(this.props.modal.type == 'shift') && ( <em>Mettre à jour les horaires de la course {actions.humanOID(actions.getSelected(this.props.vehicleJourneys)[0].objectid)}</em> )} + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'shift') && ( @@ -110,5 +111,5 @@ export default class ShiftVehicleJourney extends Component { ShiftVehicleJourney.propTypes = { onOpenShiftModal: PropTypes.func.isRequired, onModalClose: PropTypes.func.isRequired, - filters: PropTypes.object.isRequired + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js index fd2304901..fef3cdcc9 100644 --- a/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js @@ -5,6 +5,8 @@ import TimetableSelect2 from './select2s/TimetableSelect2' export default class TimetablesEditVehicleJourney extends Component { constructor(props) { super(props) + this.handleSubmit = this.handleSubmit.bind(this) + this.timeTableURL = this.timeTableURL.bind(this) } handleSubmit() { @@ -13,6 +15,11 @@ export default class TimetablesEditVehicleJourney extends Component { $('#CalendarsEditVehicleJourneyModal').modal('hide') } + timeTableURL(tt) { + let refURL = window.location.pathname.split('/', 3).join('/') + return refURL + '/time_tables/' + tt.id + } + render() { if(this.props.status.isFetching == true) { return false @@ -22,7 +29,7 @@ export default class TimetablesEditVehicleJourney extends Component { <li className='st_action'> <button type='button' - disabled={(actions.getSelected(this.props.vehicleJourneys).length > 0 && this.props.filters.policy['vehicle_journeys.update']) ? '' : 'disabled'} + disabled={(actions.getSelected(this.props.vehicleJourneys).length != 1 || this.props.disabled)} data-toggle='modal' data-target='#CalendarsEditVehicleJourneyModal' onClick={() => this.props.onOpenCalendarsEditModal(actions.getSelected(this.props.vehicleJourneys))} @@ -36,6 +43,7 @@ export default class TimetablesEditVehicleJourney extends Component { <div className='modal-content'> <div className='modal-header'> <h4 className='modal-title'>Calendriers associés</h4> + <span type="button" className="close modal-close" data-dismiss="modal">×</span> </div> {(this.props.modal.type == 'calendars_edit') && ( @@ -57,55 +65,63 @@ export default class TimetablesEditVehicleJourney extends Component { {this.props.modal.modalProps.timetables.map((tt, i) => <div className='nested-fields' key={i}> <div className='wrapper'> - <div>{tt.comment}</div> - <div> - <a - href='#' - title='Supprimer' - className='fa fa-trash remove_fields' - style={{height: 'auto', lineHeight: 'normal'}} - onClick={(e) => { - e.preventDefault() - this.props.onDeleteCalendarModal(tt) - }} + <div> <a href={this.timeTableURL(tt)} target="_blank">{tt.comment}</a> </div> + { + this.props.editMode && + <div> + <a + href='#' + title='Supprimer' + className='fa fa-trash remove_fields' + style={{ height: 'auto', lineHeight: 'normal' }} + onClick={(e) => { + e.preventDefault() + this.props.onDeleteCalendarModal(tt) + }} ></a> - </div> + </div> + } </div> </div> )} - <div className='nested-fields'> - <div className='wrapper'> - <div> - <TimetableSelect2 - onSelect2Timetable={this.props.onSelect2Timetable} - chunkURL={'/autocomplete_time_tables.json'} - isFilter={false} - /> + { + this.props.editMode && + <div className='nested-fields'> + <div className='wrapper'> + <div> + <TimetableSelect2 + onSelect2Timetable={this.props.onSelect2Timetable} + chunkURL={'/autocomplete_time_tables.json'} + isFilter={false} + /> + </div> </div> </div> - </div> + } </div> </div> </div> </div> - - <div className='modal-footer'> - <button - className='btn btn-link' - data-dismiss='modal' - type='button' - onClick={this.props.onModalClose} + { + this.props.editMode && + <div className='modal-footer'> + <button + className='btn btn-link' + data-dismiss='modal' + type='button' + onClick={this.props.onModalClose} > - Annuler - </button> - <button - className='btn btn-primary' - type='button' - onClick={this.handleSubmit.bind(this)} + Annuler + </button> + <button + className='btn btn-primary' + type='button' + onClick={this.handleSubmit} > - Valider - </button> - </div> + Valider + </button> + </div> + } </form> )} @@ -127,5 +143,5 @@ TimetablesEditVehicleJourney.propTypes = { onTimetablesEditVehicleJourney: PropTypes.func.isRequired, onDeleteCalendarModal: PropTypes.func.isRequired, onSelect2Timetable: PropTypes.func.isRequired, - filters: PropTypes.object.isRequired + disabled: PropTypes.bool.isRequired }
\ No newline at end of file diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js index 9c259630d..0697e9141 100644 --- a/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js +++ b/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js @@ -1,6 +1,7 @@ import _ from 'lodash' import React, { PropTypes, Component } from 'react' import Select2 from 'react-select2' +import actions from '../../../actions' // get JSON full path let origin = window.location.origin @@ -20,10 +21,11 @@ export default class BSelect4 extends Component { value={(this.props.company) ? this.props.company.name : undefined} onSelect={(e) => this.props.onSelect2Company(e) } onUnselect={() => this.props.onUnselect2Company()} + disabled={!this.props.editMode} multiple={false} ref='company_id' options={{ - allowClear: true, + allowClear: this.props.editMode, theme: 'bootstrap', width: '100%', placeholder: 'Filtrer par transporteur...', @@ -34,7 +36,7 @@ export default class BSelect4 extends Component { delay: '500', data: function(params) { return { - q: {name_cont: params.term}, + q: { name_cont: actions.escapeWildcardCharacters(params.term)}, }; }, processResults: function(data, params) { diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js index e4abdd651..6069bf089 100644 --- a/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js +++ b/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js @@ -33,7 +33,7 @@ export default class BSelect4 extends Component { delay: '500', data: function(params) { return { - q: {published_name_or_objectid_or_registration_number_cont: params.term}, + q: { published_name_or_objectid_or_registration_number_cont: actions.escapeWildcardCharacters(params.term)}, }; }, processResults: function(data, params) { diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js index 606bf8511..60c3eab83 100644 --- a/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js +++ b/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js @@ -32,12 +32,9 @@ export default class BSelect4 extends Component { dataType: 'json', delay: '500', data: function(params) { - let newParmas = params.term.split(" ") return { q: { - objectid_cont_any: newParmas, - comment_cont_any: newParmas, - m: 'or' + comment_or_objectid_cont_any: actions.escapeWildcardCharacters(params.term) } }; }, diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js index e1af8816d..7cccbbc05 100644 --- a/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js +++ b/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js @@ -33,7 +33,7 @@ export default class BSelect4b extends Component { delay: '500', data: function(params) { return { - q: {objectid_cont: params.term}, + q: { objectid_cont: actions.escapeWildcardCharacters(params.term)}, }; }, processResults: function(data, params) { diff --git a/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js index b3f777448..5da0bd3e9 100644 --- a/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js +++ b/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js @@ -2,13 +2,13 @@ import actions from '../../actions' import { connect } from 'react-redux' import CreateModal from '../../components/tools/CreateModal' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { + disabled: ownProps.disabled, modal: state.modal, vehicleJourneys: state.vehicleJourneys, status: state.status, stopPointsList: state.stopPointsList, - filters: state.filters } } diff --git a/app/javascript/vehicle_journeys/containers/tools/DeleteVehicleJourneys.js b/app/javascript/vehicle_journeys/containers/tools/DeleteVehicleJourneys.js index d7d315da4..95f2eb506 100644 --- a/app/javascript/vehicle_journeys/containers/tools/DeleteVehicleJourneys.js +++ b/app/javascript/vehicle_journeys/containers/tools/DeleteVehicleJourneys.js @@ -2,10 +2,10 @@ import actions from '../../actions' import { connect } from 'react-redux' import DeleteVJComponent from '../../components/tools/DeleteVehicleJourneys' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { - vehicleJourneys: state.vehicleJourneys, - filters: state.filters + disabled: ownProps.disabled, + vehicleJourneys: state.vehicleJourneys } } diff --git a/app/javascript/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js index e9ca88040..7b23a06dc 100644 --- a/app/javascript/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js +++ b/app/javascript/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js @@ -2,8 +2,9 @@ import actions from '../../actions' import { connect } from 'react-redux' import DuplicateVJComponent from '../../components/tools/DuplicateVehicleJourney' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { + disabled: ownProps.disabled, modal: state.modal, vehicleJourneys: state.vehicleJourneys, status: state.status, diff --git a/app/javascript/vehicle_journeys/containers/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/EditVehicleJourney.js index 2d480aa0c..c2eabcc10 100644 --- a/app/javascript/vehicle_journeys/containers/tools/EditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/containers/tools/EditVehicleJourney.js @@ -2,12 +2,13 @@ import actions from '../../actions' import { connect } from 'react-redux' import EditComponent from '../../components/tools/EditVehicleJourney' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { + editMode: state.editMode, + disabled: ownProps.disabled, modal: state.modal, vehicleJourneys: state.vehicleJourneys, - status: state.status, - filters: state.filters + status: state.status } } diff --git a/app/javascript/vehicle_journeys/containers/tools/NotesEditVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/NotesEditVehicleJourney.js index 5a96ff273..6290ae3bf 100644 --- a/app/javascript/vehicle_journeys/containers/tools/NotesEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/containers/tools/NotesEditVehicleJourney.js @@ -2,12 +2,13 @@ import actions from '../../actions' import { connect } from 'react-redux' import NotesEditComponent from '../../components/tools/NotesEditVehicleJourney' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { + editMode: state.editMode, + disabled: ownProps.disabled, modal: state.modal, vehicleJourneys: state.vehicleJourneys, - status: state.status, - filters: state.filters + status: state.status } } diff --git a/app/javascript/vehicle_journeys/containers/tools/ShiftVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/ShiftVehicleJourney.js index a4b4fbe39..abd7dd145 100644 --- a/app/javascript/vehicle_journeys/containers/tools/ShiftVehicleJourney.js +++ b/app/javascript/vehicle_journeys/containers/tools/ShiftVehicleJourney.js @@ -2,12 +2,12 @@ import actions from '../../actions' import { connect } from 'react-redux' import ShiftVJComponent from '../../components/tools/ShiftVehicleJourney' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { modal: state.modal, vehicleJourneys: state.vehicleJourneys, status: state.status, - filters: state.filters + disabled: ownProps.disabled } } diff --git a/app/javascript/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js index 62150a06e..b4ba9d068 100644 --- a/app/javascript/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js @@ -2,12 +2,13 @@ import actions from '../../actions' import { connect } from 'react-redux' import TimetablesEditComponent from '../../components/tools/TimetablesEditVehicleJourney' -const mapStateToProps = (state) => { +const mapStateToProps = (state, ownProps) => { return { + editMode: state.editMode, modal: state.modal, vehicleJourneys: state.vehicleJourneys, status: state.status, - filters: state.filters + disabled: ownProps.disabled } } diff --git a/app/models/import.rb b/app/models/import.rb index 64f713914..e0aae6ef1 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -18,6 +18,7 @@ class Import < ActiveRecord::Base validates :file, presence: true validates_presence_of :workbench, :creator + validates_format_of :file, with: %r{\.zip\z}i, message: I18n.t('activerecord.errors.models.imports.wrong_file_extension') before_create :initialize_fields @@ -34,7 +35,7 @@ class Import < ActiveRecord::Base end def self.finished_statuses - symbols_with_indifferent_access(%i(successful failed aborted canceled)) + symbols_with_indifferent_access(%i(successful failed warning aborted canceled)) end def notify_parent diff --git a/app/services/zip_service.rb b/app/services/zip_service.rb index cab301b01..7a4bdad1b 100644 --- a/app/services/zip_service.rb +++ b/app/services/zip_service.rb @@ -1,10 +1,9 @@ class ZipService - # TODO: Remove me before merge https://github.com/rubyzip/rubyzip - class Subdir < Struct.new(:name, :stream) + class Subdir < Struct.new(:name, :stream, :spurious) end - attr_reader :current_key, :current_output, :yielder + attr_reader :current_key, :current_output, :current_spurious, :yielder def initialize data @zip_data = StringIO.new(data) @@ -36,6 +35,7 @@ class ZipService end def add_to_current_output entry + return if is_spurious! entry.name current_output.put_next_entry entry.name write_to_current_output entry.get_input_stream end @@ -51,7 +51,8 @@ class ZipService @yielder << Subdir.new( current_key, # Second part of the solution, yield the closed stream - current_output.close_buffer) + current_output.close_buffer, + current_spurious) end end @@ -59,10 +60,19 @@ class ZipService @current_key = entry_key # First piece of the solution, use internal way to create a Zip::OutputStream @current_output = Zip::OutputStream.new(StringIO.new(''), true, nil) + @current_spurious = [] end def entry_key entry # last dir name File.dirname.split("/").last entry.name.split('/', -1)[-2] end + + def is_spurious! entry_name + segments = entry_name.split('/', 3) + return false if segments.size < 3 + + current_spurious << segments.second + return true + end end diff --git a/app/views/calendars/edit.html.slim b/app/views/calendars/edit.html.slim index 426f27881..3463bd05c 100644 --- a/app/views/calendars/edit.html.slim +++ b/app/views/calendars/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :calendar, @calendar / PageHeader = pageheader 'modele-calendrier', t('.title', calendar: @calendar.name), diff --git a/app/views/calendars/index.html.slim b/app/views/calendars/index.html.slim index d3168fa3d..a95d54428 100644 --- a/app/views/calendars/index.html.slim +++ b/app/views/calendars/index.html.slim @@ -1,5 +1,5 @@ +- breadcrumb :calendars / PageHeader - - header_params = ['modele-calendrier', t('.title'), ''] diff --git a/app/views/calendars/new.html.slim b/app/views/calendars/new.html.slim index 2cb6f8061..146173d35 100644 --- a/app/views/calendars/new.html.slim +++ b/app/views/calendars/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :calendars / PageHeader = pageheader 'modele-calendrier', t('.title'), diff --git a/app/views/calendars/show.html.slim b/app/views/calendars/show.html.slim index eda4ef97c..b2ace0ccc 100644 --- a/app/views/calendars/show.html.slim +++ b/app/views/calendars/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :calendar, @calendar / PageHeader = pageheader 'modele-calendrier', @calendar.name, diff --git a/app/views/companies/index.html.slim b/app/views/companies/index.html.slim index dad905c60..ba061f505 100644 --- a/app/views/companies/index.html.slim +++ b/app/views/companies/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :companies, @line_referential / PageHeader = pageheader 'transporteur', t('companies.index.title'), diff --git a/app/views/companies/show.html.slim b/app/views/companies/show.html.slim index 4fb437115..668226938 100644 --- a/app/views/companies/show.html.slim +++ b/app/views/companies/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :company, @company / PageHeader = pageheader 'transporteur', @company.name, diff --git a/app/views/compliance_check_sets/index.html.slim b/app/views/compliance_check_sets/index.html.slim index 38c4babcf..4ca5a2ee7 100644 --- a/app/views/compliance_check_sets/index.html.slim +++ b/app/views/compliance_check_sets/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_check_sets, @workbench / PageHeader - header_params = ['jeux-de-donnees', t('compliance_check_sets.index.title'), diff --git a/app/views/compliance_check_sets/show.html.slim b/app/views/compliance_check_sets/show.html.slim index 4e965947d..eefa5363f 100644 --- a/app/views/compliance_check_sets/show.html.slim +++ b/app/views/compliance_check_sets/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_check_set, @workbench, @compliance_check_set / PageHeader = pageheader 'jeux-de-donnees', @compliance_check_set.referential.name @@ -8,4 +9,4 @@ .col-lg-6.col-md-6.col-sm-12.col-xs-12 = definition_list t('metadatas'), ComplianceCheckSet.human_attribute_name(:id) => @compliance_check_set.referential.id, - ComplianceCheckSet.human_attribute_name(:name) => @compliance_check_set.referential.name
\ No newline at end of file + ComplianceCheckSet.human_attribute_name(:name) => @compliance_check_set.referential.name diff --git a/app/views/compliance_control_sets/edit.html.slim b/app/views/compliance_control_sets/edit.html.slim index 649154b91..dbe537c93 100644 --- a/app/views/compliance_control_sets/edit.html.slim +++ b/app/views/compliance_control_sets/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control_set, @compliance_control_set / PageHeader = pageheader 'jeux-de-controle', t('compliance_control_sets.edit.title', name: @compliance_control_set.name) diff --git a/app/views/compliance_control_sets/index.html.slim b/app/views/compliance_control_sets/index.html.slim index 1120ed186..02d40c813 100644 --- a/app/views/compliance_control_sets/index.html.slim +++ b/app/views/compliance_control_sets/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control_sets / PageHeader - header_params = ['jeux-de-controle', t('compliance_control_sets.index.title'), @@ -53,4 +54,4 @@ = replacement_msg t('compliance_control_sets.search_no_results') -= javascript_pack_tag 'date_filters'
\ No newline at end of file += javascript_pack_tag 'date_filters' diff --git a/app/views/compliance_control_sets/new.html.slim b/app/views/compliance_control_sets/new.html.slim index 35654b4d6..d543a6395 100644 --- a/app/views/compliance_control_sets/new.html.slim +++ b/app/views/compliance_control_sets/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control_sets / PageHeader = pageheader 'jeux-de-controle', t('compliance_control_sets.index.new') diff --git a/app/views/compliance_control_sets/show.html.slim b/app/views/compliance_control_sets/show.html.slim index f45b0227a..cf236feb8 100644 --- a/app/views/compliance_control_sets/show.html.slim +++ b/app/views/compliance_control_sets/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control_set, @compliance_control_set / PageHeader = pageheader 'jeux-de-controle', t('compliance_control_sets.show.title', name: @compliance_control_set.name), diff --git a/app/views/compliance_controls/new.html.slim b/app/views/compliance_controls/new.html.slim index 181f49a15..fe32e14ee 100644 --- a/app/views/compliance_controls/new.html.slim +++ b/app/views/compliance_controls/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control_set, parent / PageHeader - header_params = ['jeux-de-controle', t('compliance_controls.new.title'), diff --git a/app/views/compliance_controls/select_type.html.slim b/app/views/compliance_controls/select_type.html.slim index 98cc5a943..ec1c360cb 100644 --- a/app/views/compliance_controls/select_type.html.slim +++ b/app/views/compliance_controls/select_type.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control_set, parent / PageHeader - header_params = ['jeux-de-controle', t('compliance_controls.select_type.title'), diff --git a/app/views/compliance_controls/show.html.slim b/app/views/compliance_controls/show.html.slim index 12a28cd4b..44d52a9f1 100644 --- a/app/views/compliance_controls/show.html.slim +++ b/app/views/compliance_controls/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :compliance_control, @compliance_control / PageHeader = pageheader 'jeux-de-controle', t('compliance_controls.show.title'), diff --git a/app/views/group_of_lines/edit.html.slim b/app/views/group_of_lines/edit.html.slim index 75d530b08..ef7a405d3 100644 --- a/app/views/group_of_lines/edit.html.slim +++ b/app/views/group_of_lines/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :group_of_line, @group_of_line = title_tag t('group_of_lines.edit.title', :group_of_line => @group_of_line.name) -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/group_of_lines/index.html.slim b/app/views/group_of_lines/index.html.slim index 69b1cd0d6..28f3ab264 100644 --- a/app/views/group_of_lines/index.html.slim +++ b/app/views/group_of_lines/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :group_of_lines, @line_referential = title_tag t('group_of_lines.index.title') = search_form_for @q, :url => line_referential_group_of_lines_path(@line_referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| diff --git a/app/views/group_of_lines/new.html.slim b/app/views/group_of_lines/new.html.slim index 36b5d6b4e..395c2b3e7 100644 --- a/app/views/group_of_lines/new.html.slim +++ b/app/views/group_of_lines/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :group_of_lines, @line_referential = title_tag t('group_of_lines.new.title') -== render 'form'
\ No newline at end of file +== render 'form' diff --git a/app/views/group_of_lines/show.html.slim b/app/views/group_of_lines/show.html.slim index b934cb1ef..de215bfa0 100644 --- a/app/views/group_of_lines/show.html.slim +++ b/app/views/group_of_lines/show.html.slim @@ -1,3 +1,5 @@ +- breadcrumb :group_of_line, @group_of_line + = title_tag t('group_of_lines.show.title', :group_of_line => @group_of_line.name ) .group_of_line_show diff --git a/app/views/imports/_form.html.slim b/app/views/imports/_form.html.slim index 0fbf578be..95d97c534 100644 --- a/app/views/imports/_form.html.slim +++ b/app/views/imports/_form.html.slim @@ -9,6 +9,6 @@ .form-group = form.label :file, t('activerecord.attributes.import.resources'), class: 'control-label col-sm-4 col-xs-5' .col-sm-8.col-xs-7 - = form.input_field :file, label: false, class: 'form-control' + = form.input :file, label: false, class: 'form-control' = form.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'wb_import_form' diff --git a/app/views/imports/index.html.slim b/app/views/imports/index.html.slim index cd236ef36..35cd666b1 100644 --- a/app/views/imports/index.html.slim +++ b/app/views/imports/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :imports, @workbench / PageHeader = pageheader 'importer', t('.title'), diff --git a/app/views/imports/new.html.slim b/app/views/imports/new.html.slim index 5d5df0857..b74d8eaf2 100644 --- a/app/views/imports/new.html.slim +++ b/app/views/imports/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :imports, @workbench / PageHeader = pageheader 'importer', t('.title') diff --git a/app/views/imports/show.html.slim b/app/views/imports/show.html.slim index 5f5974d69..69ee44f9f 100644 --- a/app/views/imports/show.html.slim +++ b/app/views/imports/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :import, @workbench, @import / PageHeader = pageheader 'importer', @import.name, diff --git a/app/views/journey_patterns_collections/show.html.slim b/app/views/journey_patterns_collections/show.html.slim index 8c0950536..7c62b69ee 100644 --- a/app/views/journey_patterns_collections/show.html.slim +++ b/app/views/journey_patterns_collections/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :journey_patterns, @referential, @route / pageheader = pageheader 'mission', "Missions de #{@route.try(:stop_points).first.try(:stop_area).name} vers #{@route.try(:stop_points).last.try(:stop_area).name}", @@ -5,8 +6,8 @@ '' - @journey_patterns.each do |jp| - jp.errors.each do |error_message| - = error_message - + = error_message + / PageContent .page_content .container-fluid diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index 1bc9de136..8c731007d 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -13,15 +13,10 @@ html lang=I18n.locale = javascript_pack_tag 'application' = javascript_include_tag 'application' - - body = render 'layouts/navigation/main_nav' - = render 'layouts/flash_messages', flash: flash - = yield - #sidebar = yield :sidebar diff --git a/app/views/layouts/navigation/_breadcrumb.html.slim b/app/views/layouts/navigation/_breadcrumb.html.slim index a101098fe..403ed6702 100644 --- a/app/views/layouts/navigation/_breadcrumb.html.slim +++ b/app/views/layouts/navigation/_breadcrumb.html.slim @@ -1,2 +1 @@ -- if @breadcrumbs.present? - = render_breadcrumbs builder: BootstrapBreadcrumbsBuilder, tag: :li, separator: '' +== breadcrumbs diff --git a/app/views/line_footnotes/show.html.slim b/app/views/line_footnotes/show.html.slim index 8138c1383..0ed1d2958 100644 --- a/app/views/line_footnotes/show.html.slim +++ b/app/views/line_footnotes/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :line_footnotes, @referential, @line / PageHeader = pageheader 'ligne', "Notes sur la ligne #{@line.name}", @@ -22,4 +23,4 @@ - else = replacement_msg 'Aucune note ne correspond à votre recherche' - + diff --git a/app/views/line_referentials/show.html.slim b/app/views/line_referentials/show.html.slim index d2527f360..b98e9d5bb 100644 --- a/app/views/line_referentials/show.html.slim +++ b/app/views/line_referentials/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :line_referential, @line_referential / PageHeader = pageheader 'synchro-ilico', t('.title'), diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim index 87c3a69e7..7e3e1cc85 100644 --- a/app/views/lines/index.html.slim +++ b/app/views/lines/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :lines, @line_referential / PageHeader = pageheader 'ligne', t('lines.index.title'), diff --git a/app/views/lines/new.html.slim b/app/views/lines/new.html.slim index 56da24d7c..f09a4b4aa 100644 --- a/app/views/lines/new.html.slim +++ b/app/views/lines/new.html.slim @@ -1,3 +1,5 @@ +- breadcrumb :lines, @line_referential + = title_tag t('lines.new.title') -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim index b16b6472a..d8f236ecc 100644 --- a/app/views/lines/show.html.slim +++ b/app/views/lines/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :line, @line / PageHeader = pageheader 'ligne', @line.name, diff --git a/app/views/networks/edit.html.slim b/app/views/networks/edit.html.slim index d4e088937..2d511e15d 100644 --- a/app/views/networks/edit.html.slim +++ b/app/views/networks/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :network, @network = title_tag t('networks.edit.title', network: @network.name) -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/networks/index.html.slim b/app/views/networks/index.html.slim index 235bdebda..e498ea35f 100644 --- a/app/views/networks/index.html.slim +++ b/app/views/networks/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :networks, @line_referential / PageHeader = pageheader 'reseau', t('networks.index.title'), diff --git a/app/views/networks/new.html.slim b/app/views/networks/new.html.slim index 7071ded33..cf04ab03f 100644 --- a/app/views/networks/new.html.slim +++ b/app/views/networks/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :networks, @line_referential = title_tag t('networks.new.title') -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/networks/show.html.slim b/app/views/networks/show.html.slim index d237351c4..9b2a0dbf8 100644 --- a/app/views/networks/show.html.slim +++ b/app/views/networks/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :network, @network / PageHeader = pageheader 'reseau', @network.name, diff --git a/app/views/organisations/edit.html.slim b/app/views/organisations/edit.html.slim index a78d59f3d..0d81b26e3 100644 --- a/app/views/organisations/edit.html.slim +++ b/app/views/organisations/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :organisation, @organisation = title_tag t('.title') = semantic_form_for @organisation, :url => organisation_path do |form| @@ -7,4 +8,4 @@ = form.actions do = form.action :submit, as: :button - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/organisations/show.html.slim b/app/views/organisations/show.html.slim index bf9f464dd..89e3b2870 100644 --- a/app/views/organisations/show.html.slim +++ b/app/views/organisations/show.html.slim @@ -1,3 +1,5 @@ +- breadcrumb :organisation, @organisation + = title_tag @organisation.name .summary diff --git a/app/views/referential_companies/index.html.slim b/app/views/referential_companies/index.html.slim index e5b7ce24a..9f5cd5d62 100644 --- a/app/views/referential_companies/index.html.slim +++ b/app/views/referential_companies/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_companies, @referential / PageHeader = pageheader 'transporteur', t('companies.index.title'), diff --git a/app/views/referential_companies/new.html.slim b/app/views/referential_companies/new.html.slim index 1acb1786f..1c7fc7297 100644 --- a/app/views/referential_companies/new.html.slim +++ b/app/views/referential_companies/new.html.slim @@ -1,2 +1,3 @@ +- breadcrumb :referential_companies, @referential = title_tag t('companies.new.title') -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/referential_companies/show.html.slim b/app/views/referential_companies/show.html.slim index 1d71c778a..0dbc3cdd0 100644 --- a/app/views/referential_companies/show.html.slim +++ b/app/views/referential_companies/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_company, @referential, @company / PageHeader = pageheader 'transporteur', @company.name, diff --git a/app/views/referential_group_of_lines/index.html.slim b/app/views/referential_group_of_lines/index.html.slim index 9fa3eb381..e782db090 100644 --- a/app/views/referential_group_of_lines/index.html.slim +++ b/app/views/referential_group_of_lines/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_group_of_lines, @referential = title_tag t('group_of_lines.index.title') = search_form_for @q, :url => referential_group_of_lines_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| diff --git a/app/views/referential_group_of_lines/new.html.slim b/app/views/referential_group_of_lines/new.html.slim index 36b5d6b4e..8807bc402 100644 --- a/app/views/referential_group_of_lines/new.html.slim +++ b/app/views/referential_group_of_lines/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_group_of_lines, @referential = title_tag t('group_of_lines.new.title') -== render 'form'
\ No newline at end of file +== render 'form' diff --git a/app/views/referential_group_of_lines/show.html.slim b/app/views/referential_group_of_lines/show.html.slim index a0635f158..504af0187 100644 --- a/app/views/referential_group_of_lines/show.html.slim +++ b/app/views/referential_group_of_lines/show.html.slim @@ -1,8 +1,9 @@ +- breadcrumb :referential_group_of_line, @referential, @group_of_line = title_tag t('group_of_lines.show.title', :group_of_line => @group_of_line.name ) .group_of_line_show = @map.to_html - + .summary p label = "#{@group_of_line.human_attribute_name('registration_number')} : " @@ -13,10 +14,10 @@ = @group_of_line.comment p.after_map - + h3.group_of_line_lines = t('.lines') .lines_detail - == render partial: "lines_detail" + == render partial: "lines_detail" - content_for :sidebar do ul.actions @@ -28,4 +29,4 @@ = link_to t('group_of_lines.actions.destroy'), referential_group_of_line_path(@referential, @group_of_line), :method => :delete, :data => {:confirm => t('group_of_lines.actions.destroy_confirm')} , class: 'remove' br - = creation_tag(@group_of_line)
\ No newline at end of file + = creation_tag(@group_of_line) diff --git a/app/views/referential_lines/edit.html.slim b/app/views/referential_lines/edit.html.slim index 0036d023b..8c51715ba 100644 --- a/app/views/referential_lines/edit.html.slim +++ b/app/views/referential_lines/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_line, @line, @referential = title_tag t('lines.edit.title', line: @line.name) -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim index df3c285ee..0ef548e89 100644 --- a/app/views/referential_lines/show.html.slim +++ b/app/views/referential_lines/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_line, @referential, @line / PageHeader = pageheader 'ligne', t('lines.index.line', line: @line.name), diff --git a/app/views/referential_networks/edit.html.slim b/app/views/referential_networks/edit.html.slim index d4e088937..dded4b176 100644 --- a/app/views/referential_networks/edit.html.slim +++ b/app/views/referential_networks/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_network, @referential, @network = title_tag t('networks.edit.title', network: @network.name) -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/referential_networks/index.html.slim b/app/views/referential_networks/index.html.slim index ca67eca8b..57d3e7f1f 100644 --- a/app/views/referential_networks/index.html.slim +++ b/app/views/referential_networks/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_networks, @referential / PageHeader = pageheader 'reseau', t('networks.index.title'), @@ -39,7 +40,7 @@ ], links: [:show], cls: 'table has-search' - + = new_pagination @networks, 'pull-right' - unless @networks.any? diff --git a/app/views/referential_networks/new.html.slim b/app/views/referential_networks/new.html.slim index 7071ded33..4a737d9f7 100644 --- a/app/views/referential_networks/new.html.slim +++ b/app/views/referential_networks/new.html.slim @@ -1,3 +1,5 @@ +- breadcrumb :referential_networks, @referential + = title_tag t('networks.new.title') -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/referential_networks/show.html.slim b/app/views/referential_networks/show.html.slim index d7095561e..eab0cd51a 100644 --- a/app/views/referential_networks/show.html.slim +++ b/app/views/referential_networks/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_network, @referential, @network / PageHeader = pageheader 'reseau', @network.name, diff --git a/app/views/referential_stop_areas/edit.html.slim b/app/views/referential_stop_areas/edit.html.slim index a999ab715..fc7220095 100644 --- a/app/views/referential_stop_areas/edit.html.slim +++ b/app/views/referential_stop_areas/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_stop_area, @referential, @stop_area = title_tag t('stop_areas.edit.title', stop_area: @stop_area.name) -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/referential_stop_areas/index.html.slim b/app/views/referential_stop_areas/index.html.slim index 7bf39eabd..718cbb472 100644 --- a/app/views/referential_stop_areas/index.html.slim +++ b/app/views/referential_stop_areas/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_stop_areas, @referential = title_tag t('stop_areas.index.title') = search_form_for @q, :url => referential_stop_areas_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| diff --git a/app/views/referential_stop_areas/new.html.slim b/app/views/referential_stop_areas/new.html.slim index 54fd59422..87ba9b657 100644 --- a/app/views/referential_stop_areas/new.html.slim +++ b/app/views/referential_stop_areas/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_stop_areas, @referential = title_tag t('stop_areas.new.title') -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/referential_stop_areas/show.html.slim b/app/views/referential_stop_areas/show.html.slim index fa383c82d..b9a1c9899 100644 --- a/app/views/referential_stop_areas/show.html.slim +++ b/app/views/referential_stop_areas/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_stop_area, @referential, @stop_area / PageHeader = pageheader 'arret', @stop_area.name, diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim index 26ce0acbb..b03fb9f53 100644 --- a/app/views/referentials/show.html.slim +++ b/app/views/referentials/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb @referential / PageHeader = pageheader 'jeux-de-donnees', @referential.name, diff --git a/app/views/route_sections/index.html.slim b/app/views/route_sections/index.html.slim index 2d36be67a..c459af73c 100644 --- a/app/views/route_sections/index.html.slim +++ b/app/views/route_sections/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_route_sections, @referential = title_tag t('.title') = form_for search, url: referential_route_sections_path(@referential), method: :get, class: 'form-inline' do |form| @@ -45,4 +46,4 @@ table.table.table-hover.table-striped = link_to t('.actions.destroy'), referential_route_section_path(@referential, route_section), method: :delete, data: { confirm: t('route_sections.actions.destroy_confirm') }, class: 'remove' .pagination - = will_paginate @route_sections, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer
\ No newline at end of file + = will_paginate @route_sections, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer diff --git a/app/views/route_sections/new.html.slim b/app/views/route_sections/new.html.slim index a41db0254..79f4cda2b 100644 --- a/app/views/route_sections/new.html.slim +++ b/app/views/route_sections/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_route_sections, @referential = title_tag t('route_sections.new.title') -== render 'form'
\ No newline at end of file +== render 'form' diff --git a/app/views/route_sections/show.html.slim b/app/views/route_sections/show.html.slim index f02f7de80..afd0ed0d6 100644 --- a/app/views/route_sections/show.html.slim +++ b/app/views/route_sections/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_route_section, @referential, @route_section = title_tag t('.title') .route_section @@ -23,4 +24,4 @@ li = link_to t('route_sections.actions.destroy'), referential_route_section_path(@referential, @route_section), :method => :delete, :data => {:confirm => t('route_sections.actions.destroy_confirm')}, class: 'remove' - = creation_tag(@route_section)
\ No newline at end of file + = creation_tag(@route_section) diff --git a/app/views/routes/edit.html.slim b/app/views/routes/edit.html.slim index 850588aef..a69c5aeff 100644 --- a/app/views/routes/edit.html.slim +++ b/app/views/routes/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :route, @referential, @route / PageHeader = pageheader 'itineraire', @route.name, diff --git a/app/views/routes/new.html.slim b/app/views/routes/new.html.slim index a68f8ae4e..3a8ceb963 100644 --- a/app/views/routes/new.html.slim +++ b/app/views/routes/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :referential_line, @referential, @line / PageHeader = pageheader 'itineraire', t('routes.new.title'), diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim index 6bd3451cd..1411a5502 100644 --- a/app/views/routes/show.html.slim +++ b/app/views/routes/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :route, @referential, @route / PageHeader = pageheader 'itineraire', t('routes.index.title', route: @route.name), @@ -78,4 +79,4 @@ = javascript_tag do | window.route = "#{URI.escape(route_json_for_edit(@route))}" -= javascript_pack_tag 'routes/show.js'
\ No newline at end of file += javascript_pack_tag 'routes/show.js' diff --git a/app/views/routing_constraint_zones/edit.html.slim b/app/views/routing_constraint_zones/edit.html.slim index 2c23344df..c9b9b0c41 100644 --- a/app/views/routing_constraint_zones/edit.html.slim +++ b/app/views/routing_constraint_zones/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :routing_constraint_zone, @referential, @line, @routing_constraint_zone / PageHeader = pageheader 'itl', t('.title', routing_constraint_zone: @routing_constraint_zone.name), diff --git a/app/views/routing_constraint_zones/index.html.slim b/app/views/routing_constraint_zones/index.html.slim index 4e2534b6a..ddad7723e 100644 --- a/app/views/routing_constraint_zones/index.html.slim +++ b/app/views/routing_constraint_zones/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :routing_constraint_zones, @referential, @line / PageHeader = pageheader 'itl', t('routing_constraint_zones.index.title'), diff --git a/app/views/routing_constraint_zones/new.html.slim b/app/views/routing_constraint_zones/new.html.slim index 1ed65335f..d15de13a4 100644 --- a/app/views/routing_constraint_zones/new.html.slim +++ b/app/views/routing_constraint_zones/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :routing_constraint_zones, @referential, @line / PageHeader = pageheader 'itl', t('.title') diff --git a/app/views/routing_constraint_zones/show.html.slim b/app/views/routing_constraint_zones/show.html.slim index dbd8464a0..d0c0619c3 100644 --- a/app/views/routing_constraint_zones/show.html.slim +++ b/app/views/routing_constraint_zones/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :routing_constraint_zone, @referential, @line, @routing_constraint_zone / PageHeader = pageheader 'itl', @routing_constraint_zone.name, diff --git a/app/views/shared/_breadcrumb.html.slim b/app/views/shared/_breadcrumb.html.slim index a101098fe..403ed6702 100644 --- a/app/views/shared/_breadcrumb.html.slim +++ b/app/views/shared/_breadcrumb.html.slim @@ -1,2 +1 @@ -- if @breadcrumbs.present? - = render_breadcrumbs builder: BootstrapBreadcrumbsBuilder, tag: :li, separator: '' +== breadcrumbs diff --git a/app/views/stif/dashboards/_dashboard.html.slim b/app/views/stif/dashboards/_dashboard.html.slim index 3142ecd5b..f3cd01f46 100644 --- a/app/views/stif/dashboards/_dashboard.html.slim +++ b/app/views/stif/dashboards/_dashboard.html.slim @@ -39,14 +39,14 @@ h3.panel-title.with_actions div = t('.referentials') - span.badge.ml-xs = @referentials.count if @referentials.present? + span.badge.ml-xs = @dashboard.referentials.count if @dashboard.referentials.present? div = link_to '', workbench_path(@dashboard.workbench), class: ' fa fa-chevron-right pull-right', title: t('.see') - - if @referentials.present? + - if @dashboard.referentials.present? .list-group - - @referentials.each_with_index do |referential, i| + - @dashboard.referentials.first(5).each_with_index do |referential, i| = link_to referential.name, referential_path(referential, workbench_id: referential.workbench_id, current_workbench_id: @dashboard.workbench.id), class: 'list-group-item' if i < 6 - else @@ -65,7 +65,7 @@ - if @dashboard.calendars.present? .list-group - - @dashboard.calendars.each_with_index do |calendar, i| + - @dashboard.calendars.first(5).each_with_index do |calendar, i| = link_to calendar.name, calendar_path(calendar), class: 'list-group-item' if i < 6 - else diff --git a/app/views/stop_area_referentials/show.html.slim b/app/views/stop_area_referentials/show.html.slim index dc90def50..896ce756e 100644 --- a/app/views/stop_area_referentials/show.html.slim +++ b/app/views/stop_area_referentials/show.html.slim @@ -1,10 +1,11 @@ +- breadcrumb :stop_area_referential, @stop_area_referential / PageHeader = pageheader 'synchro-icar', t('.title'), 'Lorem ipsum dolor sit amet', t('last_update', time: l(@stop_area_referential.updated_at, format: :short)), link_to(t('actions.sync'), sync_stop_area_referential_path(@stop_area_referential), method: :post, class: 'btn btn-default') do - + .row.mb-md .col-lg-12.text-right = link_to stop_area_referential_stop_areas_path(@stop_area_referential), class: 'btn btn-primary' do diff --git a/app/views/stop_areas/edit.html.slim b/app/views/stop_areas/edit.html.slim index 170b6bd20..8005f5a08 100644 --- a/app/views/stop_areas/edit.html.slim +++ b/app/views/stop_areas/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :stop_area, @stop_area_referential, @stop_area = title_tag t('stop_areas.edit.title', stop_area: @stop_area.name ) -== render 'form'
\ No newline at end of file +== render 'form' diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim index 95b9b1b0e..4e880f7a3 100644 --- a/app/views/stop_areas/index.html.slim +++ b/app/views/stop_areas/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :stop_areas, @stop_area_referential / PageHeader = pageheader 'arret', t('stop_areas.index.title'), diff --git a/app/views/stop_areas/new.html.slim b/app/views/stop_areas/new.html.slim index bdbd97571..e0c5b7a61 100644 --- a/app/views/stop_areas/new.html.slim +++ b/app/views/stop_areas/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :stop_areas, @stop_area_referential = title_tag t('stop_areas.new.title') -== render 'form'
\ No newline at end of file +== render 'form' diff --git a/app/views/stop_areas/show.html.slim b/app/views/stop_areas/show.html.slim index dce5bdbad..bc9cc2ac0 100644 --- a/app/views/stop_areas/show.html.slim +++ b/app/views/stop_areas/show.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :stop_area, @stop_area_referential, @stop_area / PageHeader = pageheader 'arret', @stop_area.name, diff --git a/app/views/time_tables/edit.html.slim b/app/views/time_tables/edit.html.slim index bf7573c71..a1ebb2c72 100644 --- a/app/views/time_tables/edit.html.slim +++ b/app/views/time_tables/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :time_table, @referential, @time_table / PageHeader = pageheader 'calendrier-application', @time_table.comment, diff --git a/app/views/time_tables/index.html.slim b/app/views/time_tables/index.html.slim index c71a214f1..b0f4e84c5 100644 --- a/app/views/time_tables/index.html.slim +++ b/app/views/time_tables/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :time_tables, @referential / PageHeader = pageheader 'calendrier-application', t('time_tables.index.title'), diff --git a/app/views/time_tables/new.html.slim b/app/views/time_tables/new.html.slim index 8a6930b9c..c8c2658ba 100644 --- a/app/views/time_tables/new.html.slim +++ b/app/views/time_tables/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :time_tables, @referential / PageHeader = pageheader 'calendrier-application', t("time_tables.#{params[:action]}.title"), diff --git a/app/views/time_tables/show.html.slim b/app/views/time_tables/show.html.slim index 021b55058..85de7f8ec 100644 --- a/app/views/time_tables/show.html.slim +++ b/app/views/time_tables/show.html.slim @@ -1,5 +1,5 @@ - require 'calendar_helper' - +- breadcrumb :time_table, @referential, @time_table / PageHeader = pageheader 'calendrier-application', diff --git a/app/views/timebands/edit.html.slim b/app/views/timebands/edit.html.slim index af62ae8db..c70de82ef 100644 --- a/app/views/timebands/edit.html.slim +++ b/app/views/timebands/edit.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :timeband, @referential, @timeband = title_tag t('timebands.edit.title', timeband: @timeband.name) -= render 'form'
\ No newline at end of file += render 'form' diff --git a/app/views/timebands/index.html.slim b/app/views/timebands/index.html.slim index c81c0a670..6dcf348f9 100644 --- a/app/views/timebands/index.html.slim +++ b/app/views/timebands/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :timebands, @referential = title_tag t('timebands.index.title') - if @timebands.any? diff --git a/app/views/timebands/new.html.slim b/app/views/timebands/new.html.slim index 90aa1bd2e..d9fc27823 100644 --- a/app/views/timebands/new.html.slim +++ b/app/views/timebands/new.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :timebands, @referential = title_tag t('timebands.new.title') -== render 'form'
\ No newline at end of file +== render 'form' diff --git a/app/views/timebands/show.html.slim b/app/views/timebands/show.html.slim index 100457226..d45611c56 100644 --- a/app/views/timebands/show.html.slim +++ b/app/views/timebands/show.html.slim @@ -1,8 +1,9 @@ +- breadcrumb :timeband, @referential, @timeband = title_tag t( 'timebands.show.title', timeband: @timeband.name ) .summary p label = "#{@timeband.name} : " = "#{l(@timeband.start_time, format: :hour)} - #{l(@timeband.end_time, format: :hour)}" - -== render 'sidebar'
\ No newline at end of file + +== render 'sidebar' diff --git a/app/views/vehicle_journeys/edit.html.slim b/app/views/vehicle_journeys/edit.html.slim index 8b3dbcf51..6276b2635 100644 --- a/app/views/vehicle_journeys/edit.html.slim +++ b/app/views/vehicle_journeys/edit.html.slim @@ -1,3 +1,3 @@ = title_tag edit_vehicle_title(@vehicle_journey) -== render 'form', vehicle_journey: @vehicle_journey, form_url: referential_line_route_vehicle_journey_path(@referential, @line, @route, @vehicle_journey)
\ No newline at end of file +== render 'form', vehicle_journey: @vehicle_journey, form_url: referential_line_route_vehicle_journey_path(@referential, @line, @route, @vehicle_journey) diff --git a/app/views/vehicle_journeys/index.html.slim b/app/views/vehicle_journeys/index.html.slim index f88afc398..2046ecca6 100644 --- a/app/views/vehicle_journeys/index.html.slim +++ b/app/views/vehicle_journeys/index.html.slim @@ -1,3 +1,4 @@ +- breadcrumb :vehicle_journeys, @referential, @route / PageHeader = pageheader 'horaires-des-courses', t('vehicle_journeys.index.title', route: @route.name ), diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index 32a933cc2..66eedb68d 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -1,9 +1,9 @@ +- breadcrumb @workbench / PageHeader = pageheader 'jeux-de-donnees', t('referentials.index.title'), '', '' do - / Below is secundary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right @@ -78,4 +78,4 @@ = javascript_tag do | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe}; -= javascript_pack_tag 'date_filters'
\ No newline at end of file += javascript_pack_tag 'date_filters' diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb index 994493944..300fad9e2 100644 --- a/app/workers/workbench_import_worker.rb +++ b/app/workers/workbench_import_worker.rb @@ -14,11 +14,13 @@ class WorkbenchImportWorker zip_service = ZipService.new(downloaded) upload zip_service @workbench_import.update(ended_at: Time.now) + rescue Zip::Error + handle_corrupt_zip_file end def download logger.info "HTTP GET #{import_url}" - @zipfile_data = HTTPService.get_resource( + HTTPService.get_resource( host: import_host, path: import_path, params: {token: @workbench_import.token_download}).body @@ -32,6 +34,10 @@ class WorkbenchImportWorker params: params(eg_file, eg_name)) end + def handle_corrupt_zip_file + @workbench_import.messages.create(criticity: :error, message_key: 'corrupt_zip_file', message_attributes: {import_name: @workbench_import.name}) + end + def upload zip_service entry_group_streams = zip_service.subdirs @workbench_import.update total_steps: entry_group_streams.size @@ -42,11 +48,24 @@ class WorkbenchImportWorker raise end - def upload_entry_group entry_pair, element_count - @workbench_import.update( current_step: element_count.succ ) - # status = retry_service.execute(&upload_entry_group_proc(entry_pair)) - eg_name = entry_pair.name - eg_stream = entry_pair.stream + def update_object_state entry, count + @workbench_import.update( current_step: count ) + unless entry.spurious.empty? + @workbench_import.messages.create( + criticity: :warning, + message_key: 'inconsistent_zip_file', + message_attributes: { + 'import_name' => @workbench_import.name, + 'spurious_dirs' => entry.spurious.join(', ') + }) + end + end + + def upload_entry_group entry, element_count + update_object_state entry, element_count.succ + # status = retry_service.execute(&upload_entry_group_proc(entry)) + eg_name = entry.name + eg_stream = entry.stream FileUtils.mkdir_p(Rails.root.join('tmp', 'imports')) diff --git a/config/breadcrumbs.rb b/config/breadcrumbs.rb new file mode 100644 index 000000000..a9652fc89 --- /dev/null +++ b/config/breadcrumbs.rb @@ -0,0 +1,249 @@ +crumb :root do + link I18n.t('layouts.home'), root_path +end + +crumb :workbench do |workbench| + link workbench.name, workbench_path(workbench) +end + +crumb :referential do |referential| + link referential.name, referential_path(referential) + parent :workbench, current_offer_workbench +end + +crumb :referential_companies do |referential| + link I18n.t('companies.index.title'), referential_companies_path(referential) + parent :referential, referential +end + +crumb :referential_company do |referential, company| + link company.name, referential_company_path(referential, company) + parent :referential_companies, referential +end + +crumb :referential_networks do |referential| + link I18n.t('networks.index.title'), referential_networks_path + parent :referential, referential +end + +crumb :referential_network do |referential, network| + link network.name, referential_network_path(referential, network) + parent :referential_networks, referential +end + +crumb :referential_group_of_lines do |referential| + link I18n.t('group_of_lines.index.title'), referential_networks_path(referential) + parent :referential, referential +end + +crumb :referential_group_of_line do |referential, group_of_line| + link group_of_line.name, referential_group_of_line_path(referential, group_of_line) + parent :referential_group_of_lines, referential +end + +crumb :referential_route_sections do |referential| + link I18n.t('route_sections.index.title'), referential_route_sections_path(referential) + parent :referential, referential +end + +crumb :referential_route_section do |referential, route_section| + link route_section.departure.name, referential_route_section_path(referential, route_section) + parent :referential_route_sections, referential +end + + +crumb :time_tables do |referential| + link I18n.t('time_tables.index.title'), referential_time_tables_path(referential) + parent :referential, referential +end + +crumb :time_table do |referential, time_table| + link time_table.comment, referential_time_table_path(referential, time_table) + parent :time_tables, referential +end + +crumb :timebands do |referential| + link I18n.t('timebands.index.title'), referential_timebands_path(referential) + parent :referential, referential +end + +crumb :timeband do |referential, timeband| + link timeband.name, referential_timeband_path(referential, timeband) + parent :timebands, referential +end + +crumb :compliance_check_sets do |workbench| + link I18n.t('compliance_check_sets.index.title'), workbench_compliance_check_sets_path(workbench) + parent :workbench, workbench +end + +crumb :compliance_check_set do |workbench, compliance_check_set| + link compliance_check_set.name, workbench_compliance_check_set_path(workbench, compliance_check_set) + parent :compliance_check_sets, workbench +end + +crumb :imports do |workbench| + link I18n.t('imports.index.title'), workbench_imports_path(workbench) + parent :workbench, workbench +end + +crumb :import do |workbench, import| + link import.name, workbench_import_path(workbench, import) + parent :imports, workbench +end + +crumb :organisation do |organisation| + link organisation.name, organisation_path(organisation) +end + +crumb :compliance_control_sets do + link I18n.t('compliance_control_sets.index.title'), compliance_control_sets_path +end + +crumb :compliance_control_set do |compliance_control_set| + link compliance_control_set.name, compliance_control_set_path(compliance_control_set) + parent :compliance_control_sets +end + +crumb :compliance_control do |compliance_control| + link compliance_control.name, compliance_control_set_compliance_control_path(compliance_control.compliance_control_set, compliance_control) + parent :compliance_control_set, compliance_control.compliance_control_set +end + +crumb :stop_area_referential do |stop_area_referential| + link I18n.t('stop_area_referentials.show.title'), stop_area_referential_path(stop_area_referential) +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| + link stop_area.name, stop_area_referential_stop_area_path(stop_area_referential, stop_area) + parent :stop_areas, stop_area_referential +end + +crumb :line_referential do |line_referential| + link I18n.t('line_referentials.show.title'), line_referential_path(line_referential) +end + +crumb :companies do |line_referential| + link I18n.t('companies.index.title'), line_referential_companies_path(line_referential) + parent :line_referential, line_referential +end + +crumb :company do |company| + link company.name, line_referential_company_path(company.line_referential, company) + parent :companies, company.line_referential +end + +crumb :networks do |line_referential| + link I18n.t('networks.index.title'), line_referential_networks_path(line_referential) + parent :line_referential, line_referential +end + +crumb :network do |network| + link network.name, line_referential_network_path(network.line_referential, network) + parent :networks, network.line_referential +end + +crumb :group_of_lines do |line_referential| + link I18n.t('group_of_lines.index.title'), line_referential_group_of_lines_path(line_referential) + parent :line_referential, line_referential +end + +crumb :group_of_line do |group_of_line| + link group_of_line.name, line_referential_group_of_line_path(group_of_line.line_referential, group_of_line) + parent :group_of_lines, group_of_line.line_referential +end + +crumb :lines do |line_referential| + link I18n.t('lines.index.title'), line_referential_lines_path + parent :line_referential, line_referential +end + +crumb :line do |line| + link line.name, line_referential_line_path(line.line_referential, line) + parent :lines, line.line_referential +end + +crumb :calendars do + link I18n.t('calendars.index.title'), calendars_path +end + +crumb :calendar do |calendar| + link calendar.name, calendar_path(calendar) + parent :calendars +end + +crumb :referential_line do |referential, line| + link line.name, referential_line_path(referential, line) + parent :referential, referential +end + +crumb :line_footnotes do |referential, line| + link line.name, referential_line_footnotes_path(referential, line) + parent :referential_line, referential, line +end + +crumb :routing_constraint_zones do |referential, line| + link I18n.t('routing_constraint_zones.index.title'), referential_line_routing_constraint_zones_path(referential, line) + parent :referential_line, referential, line +end + +crumb :routing_constraint_zone do |referential, line, routing_constraint_zone| + link routing_constraint_zone.name, referential_line_routing_constraint_zone_path(referential, line, routing_constraint_zone) + parent :routing_constraint_zones, referential, line +end + +crumb :route do |referential, route| + link I18n.t('routes.index.title', route: route.name), referential_line_route_path(referential, route.line, route) + parent :referential_line, referential, route.line +end + +crumb :journey_patterns do |referential, route| + link I18n.t('journey_patterns.index.title'), referential_line_route_journey_patterns_collection_path(referential, route.line, route) + parent :route, referential, route +end + +crumb :referential_stop_areas do |referential| + link I18n.t('stop_areas.index.title'), referential_stop_areas_path(referential) + parent :referential, referential +end + +crumb :referential_stop_area do |referential, stop_area| + link stop_area.name, referential_stop_area_path(referential, stop_area) + parent :referential_stop_areas, referential +end + +crumb :vehicle_journeys do |referential, route| + link I18n.t('vehicle_journeys.index.title', route: route.name), referential_line_route_vehicle_journeys_path(referential, route.line, route) + parent :route, referential, route +end + +# crumb :compliance_controls do|compliance_control_sets| +# link +# parent :compliance_control_sets, compliance_control_sets +# end + +# crumb :project do |project| +# link project.name, project_path(project) +# parent :projects +# end + +# crumb :project_issues do |project| +# link "Issues", project_issues_path(project) +# parent :project, project +# end + +# crumb :issue do |issue| +# link issue.title, issue_path(issue) +# parent :project_issues, issue.project +# end + +# If you want to split your breadcrumbs configuration over multiple files, you +# can create a folder named `config/breadcrumbs` and put your configuration +# files there. All *.rb files (e.g. `frontend.rb` or `products.rb`) in that +# folder are loaded and reloaded automatically when you change them, just like +# this file (`config/breadcrumbs.rb`). diff --git a/config/initializers/relationship.rb b/config/initializers/relationship.rb new file mode 100644 index 000000000..492aa627f --- /dev/null +++ b/config/initializers/relationship.rb @@ -0,0 +1,17 @@ +if Rails.env.development? + require 'rails_erd/domain/relationship' + + module RailsERD + class Domain + class Relationship + class << self + private + + def association_identity(association) + Set[association_owner(association), association_target(association)] + end + end + end + end + end +end diff --git a/config/locales/breadcrumbs.en.yml b/config/locales/breadcrumbs.en.yml deleted file mode 100644 index 6fec15b85..000000000 --- a/config/locales/breadcrumbs.en.yml +++ /dev/null @@ -1,7 +0,0 @@ -en: - breadcrumbs: - vehicle_journeys: "Passing times" - vehicle_journey_frequencies: "Times bands" - referentials: "Home" - users: "Users" - imports: Imports diff --git a/config/locales/breadcrumbs.fr.yml b/config/locales/breadcrumbs.fr.yml deleted file mode 100644 index 725549f14..000000000 --- a/config/locales/breadcrumbs.fr.yml +++ /dev/null @@ -1,7 +0,0 @@ -fr: - breadcrumbs: - vehicle_journeys: "Horaires" - vehicle_journey_frequencies: "Créneaux horaires" - root: "Accueil" - users: "Utilisateurs" - imports: Imports diff --git a/config/locales/compliance_control_sets.en.yml b/config/locales/compliance_control_sets.en.yml index ed7ccad5e..7361edacf 100644 --- a/config/locales/compliance_control_sets.en.yml +++ b/config/locales/compliance_control_sets.en.yml @@ -1,7 +1,7 @@ en: compliance_control_sets: clone: - prefix: 'Copie de' + prefix: 'Copy of' errors: operation_in_progress: "The clone operation is in progress. Please wait and refresh the page in a few moments" index: diff --git a/config/locales/compliance_control_sets.fr.yml b/config/locales/compliance_control_sets.fr.yml index d952567bf..19f6f08ee 100644 --- a/config/locales/compliance_control_sets.fr.yml +++ b/config/locales/compliance_control_sets.fr.yml @@ -1,7 +1,7 @@ fr: compliance_control_sets: clone: - prefix: 'Copy of' + prefix: 'Copie de' errors: operation_in_progress: "L'opération de clone est en cours. Veuillez patienter et raffraichir la page dans quelques instants" index: diff --git a/config/locales/import_messages.en.yml b/config/locales/import_messages.en.yml index 4009d7c77..2048b9794 100644 --- a/config/locales/import_messages.en.yml +++ b/config/locales/import_messages.en.yml @@ -1,6 +1,8 @@ en: import_messages: compliance_check_messages: + corrupt_zip_file: "The zip file of WorkbenchImport %{import_name} is corrupted and cannot be read" + inconsistent_zip_file: "The zip file of WorkbenchImport %{import_name} contains the following spurious directories %{spurious_dirs}, which are ignored" referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les même périodes et lignes" 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" @@ -13,6 +15,7 @@ en: 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire" 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée" 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}" + 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur" 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'" 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}" 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue" diff --git a/config/locales/import_messages.fr.yml b/config/locales/import_messages.fr.yml index 085299bb4..9f0af1faa 100644 --- a/config/locales/import_messages.fr.yml +++ b/config/locales/import_messages.fr.yml @@ -1,6 +1,8 @@ fr: import_messages: compliance_check_messages: + corrupt_zip_file: "Le fichier zip du WorkbenchImport %{import_name} est corrompu, et ne peut être lu" + inconsistent_zip_file: "Le fichier zip du WorkbenchImport %{import_name} contient les repertoirs illegeaux %{spurious_dirs} qui seront ignorés" referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les même périodes et lignes" 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" @@ -13,6 +15,7 @@ fr: 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire" 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée" 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}" + 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur" 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'" 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}" 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue" diff --git a/config/locales/imports.en.yml b/config/locales/imports.en.yml index 9bf877c86..f3bcad9e9 100644 --- a/config/locales/imports.en.yml +++ b/config/locales/imports.en.yml @@ -53,6 +53,10 @@ en: zero: "import" one: "NeTEx import" other: "imports" + errors: + models: + imports: + wrong_file_extension: "The imported file must be a zip file" attributes: import: resources: "File to import" diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml index 6998c89d2..6e74fa33c 100644 --- a/config/locales/imports.fr.yml +++ b/config/locales/imports.fr.yml @@ -53,6 +53,10 @@ fr: zero: "import" one: "import NeTEx" other: "imports" + errors: + models: + imports: + wrong_file_extension: "Le fichier importé doit être au format zip" attributes: import: resources: "Fichier à importer" diff --git a/config/locales/routes.fr.yml b/config/locales/routes.fr.yml index 83a96732d..31838f1a7 100644 --- a/config/locales/routes.fr.yml +++ b/config/locales/routes.fr.yml @@ -81,7 +81,7 @@ fr: number: "Indice" comment: "Commentaire" direction: "Direction" - wayback: "Direction" + wayback: "Sens" stop_points: "Nb arrêts" journey_patterns: "Nb missions" opposite_route: "Itinéraire associé" diff --git a/lib/bootstrap_breadcrumbs_builder.rb b/lib/bootstrap_breadcrumbs_builder.rb deleted file mode 100644 index daa154bdf..000000000 --- a/lib/bootstrap_breadcrumbs_builder.rb +++ /dev/null @@ -1,31 +0,0 @@ -# bootstrap builder for breadcrumbs_on_rails gem -class BootstrapBreadcrumbsBuilder < BreadcrumbsOnRails::Breadcrumbs::Builder - def render - @context.content_tag(:ul, class: 'breadcrumb') do - @elements.collect do |element| - render_element(element) - end.join.html_safe - end - end - - def render_element(element) - active = element.path.nil? || @context.current_page?(compute_path(element)) - # Bootstrap use '/' divider by default but you can customize it: - # divider = @context.content_tag(:span, '/'.html_safe, class: 'divider') unless active - - @context.content_tag(:li, :class => ('active' if active)) do - content = if element.path.nil? - compute_name(element) - else - @context.link_to_unless_current(compute_name(element), compute_path(element), element.options) - end - - # content + (divider || '') - content - end - end -end - - -# Usage: -# = render_breadcrumbs(builder: BootstrapBreadcrumbsBuilder)
\ No newline at end of file diff --git a/lib/compliance_control_set_cloner.rb b/lib/compliance_control_set_cloner.rb index 1cf58a38d..12e1eccb5 100644 --- a/lib/compliance_control_set_cloner.rb +++ b/lib/compliance_control_set_cloner.rb @@ -59,7 +59,6 @@ class ComplianceControlSetCloner criticity: compliance_control.criticity, name: name_of_copy(:compliance_controls, compliance_control.name), origin_code: compliance_control.origin_code, - target: compliance_control.target, type: compliance_control.type ).tap do | control | control_id_map.update compliance_control.id => control diff --git a/lib/stif/dashboard.rb b/lib/stif/dashboard.rb index fafddec62..b6b6b8284 100644 --- a/lib/stif/dashboard.rb +++ b/lib/stif/dashboard.rb @@ -5,7 +5,7 @@ module Stif end def referentials - @referentials ||= @workbench.all_referentials + @referentials ||= self.workbench.all_referentials end def calendars diff --git a/lib/tasks/erd.rake b/lib/tasks/erd.rake index 6b79967de..e2665374e 100644 --- a/lib/tasks/erd.rake +++ b/lib/tasks/erd.rake @@ -7,9 +7,9 @@ namespace :generate do sh "bundle exec rake erd only='Organisation,StopAreaReferential,StopAreaReferentialSync,StopAreaReferentialSyncMessage,StopAreaReferentialMembership,LineReferential,LineReferentialSync,LineReferentialSyncMessage,LineReferentialMembership' filename='referentiels_externes' title='Référentiels externes'" sh "bundle exec rake erd only='NetexImport,Import,WorkbenchImport,ImportResource,ImportMessage' filename='import' title='Import'" sh "bundle exec rake erd only='ComplianceControlSet,ComplianceControlBlock,ComplianceControl,ComplianceCheckSet,ComplianceCheckBlock,ComplianceCheck,ComplianceCheckResource,ComplianceCheckMessage' filename='validation' title='Validation'" + sh "bundle exec rake erd only='Organisation,Workbench,ReferentialSuite,Referential' filename='merge' title='Merge'" #sh "bundle exec rake erd only='VehicleJourney,VehicleJourneyExport' filename='export' title='Export'" - #sh "bundle exec rake erd only='' filename='intégration' title='Integration'" - #sh "bundle exec rake erd only='' filename='fusion' title='Fusion'" + #sh "bundle exec rake erd only='' filename='integration' title='Integration'" #sh "bundle exec rake erd only='' filename='publication' title='Publication'" end diff --git a/package.json b/package.json index 7e8d695ac..01b1244af 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "license": "MIT", "engines": { - "node": "6.11.4" + "node": "~6.11.4" }, "devDependencies": { "clean-webpack-plugin": "0.1.17", diff --git a/spec/controllers/compliance_controls_controller_spec.rb b/spec/controllers/compliance_controls_controller_spec.rb index 34b27530d..61e94025d 100644 --- a/spec/controllers/compliance_controls_controller_spec.rb +++ b/spec/controllers/compliance_controls_controller_spec.rb @@ -44,7 +44,7 @@ RSpec.describe ComplianceControlsController, type: :controller do describe 'POST #update' do it 'should be successful' do post :update, compliance_control_set_id: compliance_control_set.id, id: compliance_control.id, compliance_control: compliance_control.as_json.merge(type: 'GenericAttributeControl::MinMax') - expect(response).to redirect_to compliance_control_set_compliance_control_path(compliance_control_set, compliance_control) + expect(response).to redirect_to compliance_control_set_path(compliance_control_set) end end diff --git a/spec/factories/imports.rb b/spec/factories/imports.rb index 2c53106c3..e07447b60 100644 --- a/spec/factories/imports.rb +++ b/spec/factories/imports.rb @@ -5,6 +5,23 @@ FactoryGirl.define do current_step_progress 1.5 association :workbench association :referential + file {File.open(File.join(Rails.root, 'spec', 'fixtures', 'OFFRE_TRANSDEV_2017030112251.zip'))} + status :new + started_at nil + ended_at nil + creator 'rspec' + + after(:build) do |import| + import.class.skip_callback(:create, :before, :initialize_fields) + end + end + + factory :bad_import do + sequence(:name) { |n| "Import #{n}" } + current_step_id "MyString" + current_step_progress 1.5 + association :workbench + association :referential file {File.open(File.join(Rails.root, 'spec', 'fixtures', 'terminated_job.json'))} status :new started_at nil diff --git a/spec/factories/netex_imports.rb b/spec/factories/netex_imports.rb index 057e47730..9e9d836e4 100644 --- a/spec/factories/netex_imports.rb +++ b/spec/factories/netex_imports.rb @@ -1,5 +1,5 @@ FactoryGirl.define do factory :netex_import, class: NetexImport, parent: :import do - file { File.open(Rails.root.join('spec', 'fixtures', 'terminated_job.json')) } + file { File.open(Rails.root.join('spec', 'fixtures', 'OFFRE_TRANSDEV_2017030112251.zip')) } end end diff --git a/spec/factories/workbench_imports.rb b/spec/factories/workbench_imports.rb index 5cdcfd15f..466bfe688 100644 --- a/spec/factories/workbench_imports.rb +++ b/spec/factories/workbench_imports.rb @@ -1,5 +1,5 @@ FactoryGirl.define do factory :workbench_import, class: WorkbenchImport, parent: :import do - file { File.open(Rails.root.join('spec', 'fixtures', 'terminated_job.json')) } + file { File.open(Rails.root.join('spec', 'fixtures', 'OFFRE_TRANSDEV_2017030112251.zip')) } end end diff --git a/spec/fixtures/OFFRE_WITH_EXTRA.zip b/spec/fixtures/OFFRE_WITH_EXTRA.zip Binary files differnew file mode 100644 index 000000000..97ea3f513 --- /dev/null +++ b/spec/fixtures/OFFRE_WITH_EXTRA.zip diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb index cd5a30982..c06d05dab 100644 --- a/spec/models/import_spec.rb +++ b/spec/models/import_spec.rb @@ -10,6 +10,9 @@ RSpec.describe Import, type: :model do it { should validate_presence_of(:workbench) } it { should validate_presence_of(:creator) } + it { should allow_value('file.zip').for(:file).with_message(I18n.t('activerecord.errors.models.imports.wrong_file_extension')) } + it { should_not allow_values('file.json', 'file.png', 'file.pdf').for(:file) } + let(:workbench_import) { build_stubbed(:workbench_import) } let(:workbench_import_with_completed_steps) do workbench_import = build_stubbed( diff --git a/spec/services/zip_service/regression_4273_spec.rb b/spec/services/zip_service/regression_4273_spec.rb deleted file mode 100644 index 4fe0f6539..000000000 --- a/spec/services/zip_service/regression_4273_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -RSpec.describe ZipService do - describe 'Regression Issue # 4273 https://projects.af83.io/issues/4273' do - let( :zip_service ){ described_class } - let( :unzipper ){ zip_service.new(zip_data) } - let( :zip_data ){ File.read zip_file } - - context 'real test data' do - let( :subdir_names ){ %w<OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519> } - let( :expected_chksums ){ - checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'source_') } ) - } - - let( :zip_file ){ fixtures_path 'OFFRE_TRANSDEV_2017030112251.zip' } - # - # Remove potential test artefacts - before do - subdir_names.each do | subdir_name | - File.unlink( subdir_file subdir_name, suffix: '.zip' ) rescue nil - Dir.unlink( subdir_file subdir_name ) rescue nil - end - end - - it "yields the correct content" do - subdir_contents = {} - # Write ZipService Streams to files and inflate them to file system - unzipper.subdirs.each do | subdir | - File.open(subdir_file( subdir.name, suffix: '.zip' ), 'wb'){ |f| f.write subdir.stream.string } - unzip_subdir subdir - end - # Represent the inflated file_system as a checksum tree - actual_checksums = - checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'target/') } ) - expect( actual_checksums ).to eq( expected_chksums ) - end - - end - - end - - def checksum_trees *dirs - dirs.flatten.inject({},&method(:checksum_tree)) - end - def checksum_tree repr, dir - Dir.glob("#{dir}/**/*").each do |file| - if !File.directory?(file) - repr.merge!( File.basename(file) => %x{cksum #{file}}.split.first ){ |_, ov, nv| Array(ov) << nv } - end - end - repr - end - - def subdir_file( subdir, prefix: 'target_', suffix: '' ) - fixtures_path("#{prefix}#{subdir}#{suffix}") - end - - def unzip_subdir subdir - %x{unzip -oqq #{subdir_file subdir.name, suffix: '.zip'} -d #{fixture_path}/target} - end -end diff --git a/spec/services/zip_service_spec.rb b/spec/services/zip_service_spec.rb new file mode 100644 index 000000000..98cb9026d --- /dev/null +++ b/spec/services/zip_service_spec.rb @@ -0,0 +1,68 @@ +RSpec.describe ZipService do + + let( :zip_service ){ described_class } + let( :unzipper ){ zip_service.new(zip_data) } + let( :zip_data ){ File.read zip_file } + + + context 'correct test data' do + before do + subdir_names.each do | subdir_name | + File.unlink( subdir_file subdir_name, suffix: '.zip' ) rescue nil + Dir.unlink( subdir_file subdir_name ) rescue nil + end + end + let( :subdir_names ){ %w<OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519> } + let( :expected_chksums ){ + checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'source_') } ) + } + + let( :zip_file ){ fixtures_path 'OFFRE_TRANSDEV_2017030112251.zip' } + # + # Remove potential test artefacts + + it 'yields the correct content' do + # Write ZipService Streams to files and inflate them to file system + unzipper.subdirs.each do | subdir | + expect( subdir.spurious ).to be_empty + File.open(subdir_file( subdir.name, suffix: '.zip' ), 'wb'){ |f| f.write subdir.stream.string } + unzip_subdir subdir + end + # Represent the inflated file_system as a checksum tree + actual_checksums = + checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'target/') } ) + expect( actual_checksums ).to eq( expected_chksums ) + end + + end + + context 'test data with spurious directories' do + let( :zip_file ){ fixtures_path 'OFFRE_WITH_EXTRA.zip' } + + it 'returns the extra dir in the spurious field of the entry' do + expect( unzipper.subdirs.first.spurious ).to eq(%w{EXTRA}) + end + end + + + def checksum_trees *dirs + dirs.flatten.inject({},&method(:checksum_tree)) + end + def checksum_tree repr, dir + Dir.glob("#{dir}/**/*").each do |file| + if !File.directory?(file) + repr.merge!( File.basename(file) => %x{cksum #{file}}.split.first ){ |_, ov, nv| Array(ov) << nv } + end + end + repr + end + + def subdir_file( subdir, prefix: 'target_', suffix: '' ) + fixtures_path("#{prefix}#{subdir}#{suffix}") + end + + def unzip_subdir subdir + %x{unzip -oqq #{subdir_file subdir.name, suffix: '.zip'} -d #{fixture_path}/target} + end +end + diff --git a/spec/support/random.rb b/spec/support/random.rb index 59e1a1475..0ebc2ee5e 100644 --- a/spec/support/random.rb +++ b/spec/support/random.rb @@ -22,6 +22,12 @@ module Support def random_string SecureRandom.urlsafe_base64 end + + def very_random(veryness=3, joiner: '-') + raise ArgumentError, 'not very random' unless veryness > 1 + veryness.times.map{ SecureRandom.uuid }.join(joiner) + end + end end diff --git a/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb b/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb new file mode 100644 index 000000000..5e34b208a --- /dev/null +++ b/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb @@ -0,0 +1,48 @@ +RSpec.describe WorkbenchImportWorker do + + + shared_examples_for 'corrupt zipfile data' do + subject { described_class.new } + let( :workbench_import ){ create :workbench_import, status: :pending } + + before do + # Let us make sure that the name Enterprise will never be forgotten by history, + # ahem, I meant, that nothing is uploaded, by forbidding any message to be sent + # to HTTPService + expect_it.to receive(:download).and_return(downloaded) + end + + it 'does not upload' do + stub_const 'HTTPService', double('HTTPService') + subject.perform(workbench_import.id) + end + + it 'does create a message' do + expect{ subject.perform(workbench_import.id) }.to change{ workbench_import.messages.count }.by(1) + + message = workbench_import.messages.last + expect( message.criticity ).to eq('error') + expect( message.message_key ).to eq('corrupt_zip_file') + expect( message.message_attributes ).to eq( 'import_name' => workbench_import.name ) + end + + it 'does not change current step' do + expect{ subject.perform(workbench_import.id) }.not_to change{ workbench_import.current_step } + end + + it "sets the workbench_import.status to failed" do + subject.perform(workbench_import.id) + expect( workbench_import.reload.status ).to eq('failed') + end + end + + context 'empty zip file' do + let( :downloaded ){ '' } + it_should_behave_like 'corrupt zipfile data' + end + + context 'corrupt data' do + let( :downloaded ){ very_random } + it_should_behave_like 'corrupt zipfile data' + end +end diff --git a/spec/workers/workbench_import_worker_spec.rb b/spec/workers/workbench_import/workbench_import_worker_spec.rb index a349b3433..deaa1e3a5 100644 --- a/spec/workers/workbench_import_worker_spec.rb +++ b/spec/workers/workbench_import/workbench_import_worker_spec.rb @@ -5,7 +5,7 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do let( :workbench ){ import.workbench } let( :referential ){ import.referential } - let( :api_key ){ build_stubbed :api_key, referential: referential, token: "#{referential.id}-#{SecureRandom.hex}" } + let( :api_key ){ build_stubbed :api_key, referential: referential, token: "#{referential.id}-#{random_hex}" } # http://www.example.com/workbenches/:workbench_id/imports/:id/download let( :host ){ Rails.configuration.rails_host } @@ -13,16 +13,17 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do let( :downloaded_zip ){ double("downloaded zip") } let( :download_zip_response ){ OpenStruct.new( body: downloaded_zip ) } - let( :download_token ){ SecureRandom.urlsafe_base64 } - + let( :download_token ){ random_string } let( :upload_path ) { api_v1_netex_imports_path(format: :json) } + let( :spurious ){ [[], [], []] } let( :subdirs ) do entry_count.times.map do |i| ZipService::Subdir.new( "subdir #{i}", - double("subdir #{i}", rewind: 0, read: '') + double("subdir #{i}", rewind: 0, read: ''), + spurious[i] ) end end @@ -104,8 +105,44 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do expect( import ).to receive(:update).with(current_step: 3, status: 'failed') expect { worker.perform import.id }.to raise_error(StopIteration) + end + end + + context 'multireferential zipfile with spurious directories' do + let( :entry_count ){ 2 } + let( :spurious1 ){ [random_string] } + let( :spurious2 ){ [random_string, random_string] } + let( :spurious ){ [spurious1, spurious2] } + let( :messages ){ double('messages') } + let( :message_attributes ){{criticity: :warning, message_key: 'inconsistent_zip_file'}} + let( :message1_attributes ){ message_attributes.merge(message_attributes: {'import_name' => import.name, 'spurious_dirs' => spurious1.join(', ')}) } + let( :message2_attributes ){ message_attributes.merge(message_attributes: {'import_name' => import.name, 'spurious_dirs' => spurious2.join(', ')}) } + + before do + allow(import).to receive(:messages).and_return(messages) + end + + it 'downloads a zip file, cuts it, and uploads all pieces and adds messages' do + + expect(HTTPService).to receive(:get_resource) + .with(host: host, path: path, params: {token: download_token}) + .and_return( download_zip_response ) + + subdirs.each do |subdir| + mock_post subdir, post_response_ok + end + + expect( import ).to receive(:update).with(total_steps: 2) + expect( import ).to receive(:update).with(current_step: 1) + expect( messages ).to receive(:create).with(message1_attributes) + expect( import ).to receive(:update).with(current_step: 2) + expect( messages ).to receive(:create).with(message2_attributes) + expect( import ).to receive(:update).with(ended_at: Time.now) + + worker.perform import.id end + end def mock_post subdir, response |
