diff options
79 files changed, 1063 insertions, 594 deletions
@@ -54,7 +54,7 @@ gem 'bootstrap-timepicker-rails' # Format Output gem 'json' -gem 'rubyzip', :require => 'zip/zip' +gem 'rubyzip', '~> 1.1.6' gem 'roo' # Controller diff --git a/Gemfile.lock b/Gemfile.lock index 8dafca210..5f2596da1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/afimb/ninoxe.git - revision: 3727e7393fdece893e1baa49916be24140c766b9 + revision: 139f461be9a23566d242495df14331ec06308ce1 branch: sismo specs: ninoxe (1.1.0) @@ -52,8 +52,8 @@ GEM activesupport (3.2.18) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) - acts-as-taggable-on (3.3.0) - activerecord (>= 3, < 5) + acts-as-taggable-on (3.4.1) + activerecord (>= 3.2, < 5) acts_as_list (0.1.6) acts_as_tree-1.8 (1.1.0) activerecord (>= 3.0.0) @@ -89,7 +89,7 @@ GEM rack-test (>= 0.5.4) selenium-webdriver (~> 2.0) xpath (~> 0.1.4) - childprocess (0.3.9) + childprocess (0.5.3) ffi (~> 1.0, >= 1.0.11) choice (0.1.6) cocoon (1.1.2) @@ -184,10 +184,10 @@ GEM jquery-rails jquery-ui-rails (= 4.0.3) railties (>= 3.1.0) - jruby-jars (1.6.7.2) + jruby-jars (1.7.15) jruby-openssl (0.7.7) bouncy-castle-java (>= 1.5.0146.1) - jruby-rack (1.1.9) + jruby-rack (1.1.16) jruby-rack-worker (0.4-java) jruby-rack (>= 1.1.1) json (1.8.1) @@ -302,17 +302,17 @@ GEM rspec-mocks (~> 2.13.0) ruby-graphviz (1.0.9) ruby-ole (1.2.11.7) - rubyzip (0.9.9) + rubyzip (1.1.6) sass (3.3.7) sass-rails (3.2.6) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - selenium-webdriver (2.35.1) - childprocess (>= 0.2.5) + selenium-webdriver (2.43.0) + childprocess (~> 0.5) multi_json (~> 1.0) - rubyzip (< 1.0.0) - websocket (~> 1.0.4) + rubyzip (~> 1.0) + websocket (~> 1.0) shoulda-matchers (1.2.0) activesupport (>= 3.0.0) simple_form (2.1.1) @@ -343,18 +343,18 @@ GEM polyglot polyglot (>= 0.3.1) typeahead-rails (0.10.5) - tzinfo (0.3.40) + tzinfo (0.3.41) uglifier (1.2.7) execjs (>= 0.3.0) multi_json (~> 1.3) - warbler (1.3.6) - jruby-jars (>= 1.4.0) + warbler (1.4.4) + jruby-jars (>= 1.5.6, < 2.0) jruby-rack (>= 1.0.0) - rake (>= 0.8.7) - rubyzip (>= 0.9.4) + rake (>= 0.9.6) + rubyzip (>= 0.9, < 1.2) warden (1.2.1) rack (>= 1.0) - websocket (1.0.7) + websocket (1.2.1) will_paginate (3.0.5) will_paginate-bootstrap (1.0.0) will_paginate (>= 3.0.3) @@ -422,7 +422,7 @@ DEPENDENCIES remarkable_activerecord (~> 4.0.0.alpha4) roo rspec-rails (~> 2.0) - rubyzip + rubyzip (~> 1.1.6) sass-rails (~> 3.2.3) shoulda-matchers simple_form @@ -57,15 +57,17 @@ sudo apt-get install make Installation ------------ +On debian, chouette can also be installed as package : see [debian packages](http://packages.chouette.cityway.fr/debian/chouette) + Install chouette-gui-command to import, export and validate transport offer, Assume Linux user is myuser and its group mygroup (that user is the one who starts Rails server) ```sh sudo mkdir -p /usr/local/opt/chouette-command/ sudo chown -R myuser:mygroup /usr/local/opt/chouette-command/ cd /usr/local/opt/chouette-command/ -wget http://maven.chouette.cityway.fr/fr/certu/chouette/chouette-gui-command/2.4.1/chouette-gui-command-2.4.1.zip -unzip chouette-gui-command-2.4.1.zip -cd chouette-cmd_2.4.1 +wget http://maven.chouette.cityway.fr/fr/certu/chouette/chouette-gui-command/2.5.0/chouette-gui-command-2.5.0.zip +unzip chouette-gui-command-2.5.0.zip +cd chouette-cmd_2.5.0 sudo chmod a+w . ``` @@ -74,7 +76,7 @@ Install web application Get git source code : ```sh cd -git clone -b V2_4 git://github.com/afimb/chouette2 +git clone -b V2_5 git://github.com/afimb/chouette2 cd chouette2 ``` Download gem librairies diff --git a/app/assets/images/export-pending.png b/app/assets/images/export-pending.png Binary files differindex 7fc459926..d5af6a807 100644 --- a/app/assets/images/export-pending.png +++ b/app/assets/images/export-pending.png diff --git a/app/assets/images/export-processing.png b/app/assets/images/export-processing.png Binary files differnew file mode 100644 index 000000000..7fc459926 --- /dev/null +++ b/app/assets/images/export-processing.png diff --git a/app/assets/images/file-validation-completed.png b/app/assets/images/file-validation-completed.png Binary files differdeleted file mode 100644 index 242d68d3b..000000000 --- a/app/assets/images/file-validation-completed.png +++ /dev/null diff --git a/app/assets/images/file-validation-failed.png b/app/assets/images/file-validation-failed.png Binary files differdeleted file mode 100644 index e50298a77..000000000 --- a/app/assets/images/file-validation-failed.png +++ /dev/null diff --git a/app/assets/images/file-validation-pending.png b/app/assets/images/file-validation-pending.png Binary files differdeleted file mode 100644 index 2d19124c0..000000000 --- a/app/assets/images/file-validation-pending.png +++ /dev/null diff --git a/app/assets/javascripts/stop_area_imports.js.coffee b/app/assets/javascripts/stop_area_imports.js.coffee deleted file mode 100644 index e69de29bb..000000000 --- a/app/assets/javascripts/stop_area_imports.js.coffee +++ /dev/null diff --git a/app/controllers/access_links_controller.rb b/app/controllers/access_links_controller.rb index 8c6172a7c..4509de575 100644 --- a/app/controllers/access_links_controller.rb +++ b/app/controllers/access_links_controller.rb @@ -16,7 +16,15 @@ class AccessLinksController < ChouetteController def show @map = AccessLinkMap.new(resource).with_helpers(self) - show! + @access_point = Chouette::AccessPoint.find(params[:access_point_id]) + @access_link = Chouette::AccessLink.find(params[:id]) + @stop_area = @access_link.stop_area + show! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + add_breadcrumb @access_point.name, referential_stop_area_access_point_path(@referential, @stop_area,@access_point) + add_breadcrumb Chouette::AccessLink.model_name.human(:count => 2), access_links_referential_stop_area_path(@referential, @stop_area) + end end def new @@ -34,7 +42,11 @@ class AccessLinksController < ChouetteController data[:name] = name end @access_link = Chouette::AccessLink.new(data) - new! + new! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + add_breadcrumb @access_point.name, referential_stop_area_access_point_path(@referential, @stop_area,@access_point) + end end def create @@ -50,7 +62,12 @@ class AccessLinksController < ChouetteController @access_link = Chouette::AccessLink.find(params[:id]) @stop_area = @access_link.stop_area @orientation = @access_link.link_orientation_type - edit! + edit! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + add_breadcrumb @access_point.name, referential_stop_area_access_point_path(@referential, @stop_area,@access_point) + add_breadcrumb @access_link.name, referential_access_point_access_link_path(@referential, @access_point, @access_link) + end end protected diff --git a/app/controllers/access_points_controller.rb b/app/controllers/access_points_controller.rb index cf7507100..0e06bee19 100644 --- a/app/controllers/access_points_controller.rb +++ b/app/controllers/access_points_controller.rb @@ -30,13 +30,26 @@ class AccessPointsController < ChouetteController } end + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) end end + def new + new! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + end + end + def edit access_point.position ||= access_point.default_position map.editable = true - edit! + edit! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + add_breadcrumb @access_point.name, referential_stop_area_access_point_path(@referential, @stop_area,@access_point) + end end diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb index 3b5631a8f..20f84e763 100644 --- a/app/controllers/companies_controller.rb +++ b/app/controllers/companies_controller.rb @@ -14,9 +14,30 @@ class CompaniesController < ChouetteController if collection.out_of_bounds? redirect_to params.merge(:page => 1) end + add_breadcrumb Referential.model_name.human(:count => 2), referentials_path() + add_breadcrumb @referential.name, referential_path(@referential) } end end + + def show + show! do + add_breadcrumb Referential.human_attribute_name("companies"), referential_companies_path(@referential) + end + end + + def new + new! do + add_breadcrumb Referential.human_attribute_name("companies"), referential_companies_path(@referential) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("companies"), referential_companies_path(@referential) + add_breadcrumb @company.name, referential_line_path(@referential, @company) + end + end protected def collection diff --git a/app/controllers/compliance_check_tasks_controller.rb b/app/controllers/compliance_check_tasks_controller.rb index 9acce4510..bf8a670a3 100644 --- a/app/controllers/compliance_check_tasks_controller.rb +++ b/app/controllers/compliance_check_tasks_controller.rb @@ -2,6 +2,17 @@ class ComplianceCheckTasksController < ChouetteController respond_to :html, :js belongs_to :referential + def new + new! do + add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) + end + end + + def show + show! do + add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) + end + end def references @references = referential.send(params[:type]).where("name ilike ?", "%#{params[:q]}%") respond_to do |format| diff --git a/app/controllers/connection_links_controller.rb b/app/controllers/connection_links_controller.rb index 3c7dd3ab6..ca34aecdc 100644 --- a/app/controllers/connection_links_controller.rb +++ b/app/controllers/connection_links_controller.rb @@ -22,13 +22,31 @@ class ConnectionLinksController < ChouetteController def show @map = ConnectionLinkMap.new(resource).with_helpers(self) - show! + show! do + add_breadcrumb Referential.human_attribute_name("connection_links"), referential_connection_links_path(@referential) + end end + def new + new! do + add_breadcrumb Referential.human_attribute_name("connection_links"), referential_connection_links_path(@referential) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("connection_links"), referential_connection_links_path(@referential) + add_breadcrumb @connection_link.name, referential_connection_link_path(@referential, @connection_link) + end + end + + def select_areas @connection_link = connection_link @departure = connection_link.departure @arrival = connection_link.arrival + add_breadcrumb Referential.human_attribute_name("connection_links"), referential_connection_links_path(@referential) + add_breadcrumb @connection_link.name, referential_connection_link_path(@referential, @connection_link) end protected diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb index ed2ecd329..d5723ff78 100644 --- a/app/controllers/exports_controller.rb +++ b/app/controllers/exports_controller.rb @@ -7,6 +7,7 @@ class ExportsController < ChouetteController def new new! do + add_breadcrumb Referential.human_attribute_name("exports"), referential_exports_path(@referential) available_exports end end @@ -19,6 +20,7 @@ class ExportsController < ChouetteController end def show + add_breadcrumb Referential.human_attribute_name("exports"), referential_exports_path(@referential) show! do |format| format.zip { send_file @export.file, :type => :zip } end diff --git a/app/controllers/group_of_lines_controller.rb b/app/controllers/group_of_lines_controller.rb index 5bbda9b84..7167cc40e 100644 --- a/app/controllers/group_of_lines_controller.rb +++ b/app/controllers/group_of_lines_controller.rb @@ -11,7 +11,9 @@ class GroupOfLinesController < ChouetteController def show @map = GroupOfLineMap.new(resource).with_helpers(self) @lines = resource.lines.order(:name).paginate(:page => params[:page]) - show! + show! do + add_breadcrumb Referential.human_attribute_name("group_of_lines"), referential_group_of_lines_path(@referential) + end end def index @@ -23,12 +25,24 @@ class GroupOfLinesController < ChouetteController } end end + + def new + new! do + add_breadcrumb Referential.human_attribute_name("group_of_lines"), referential_group_of_lines_path(@referential) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("group_of_lines"), referential_group_of_lines_path(@referential) + add_breadcrumb @group_of_line.name, referential_group_of_line_path(@referential, @group_of_line) + end + end def name_filter respond_to do |format| format.json { render :json => filtered_group_of_lines_maps} end - end protected diff --git a/app/controllers/import_tasks_controller.rb b/app/controllers/import_tasks_controller.rb index 1d7e8c3aa..e900c79ce 100644 --- a/app/controllers/import_tasks_controller.rb +++ b/app/controllers/import_tasks_controller.rb @@ -5,12 +5,14 @@ class ImportTasksController < ChouetteController def new new! do + add_breadcrumb Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) available_imports end end def show show! do + add_breadcrumb Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) if import_task.completed? @files_stats = import_task.result["files"]["stats"] @files_list = import_task.result["files"]["list"] diff --git a/app/controllers/journey_patterns_controller.rb b/app/controllers/journey_patterns_controller.rb index 0274b9b71..084f34b03 100644 --- a/app/controllers/journey_patterns_controller.rb +++ b/app/controllers/journey_patterns_controller.rb @@ -27,7 +27,28 @@ class JourneyPatternsController < ChouetteController def show @map = JourneyPatternMap.new(journey_pattern).with_helpers(self) @stop_points = journey_pattern.stop_points.paginate(:page => params[:page]) - show! + show! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + add_breadcrumb @route.name, referential_line_route_path(@referential, @line, @route) + end + end + + def new + new! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + add_breadcrumb @route.name, referential_line_route_path(@referential, @line, @route) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + add_breadcrumb @route.name, referential_line_route_path(@referential, @line, @route) + add_breadcrumb @journey_pattern.name, referential_line_route_journey_pattern_path(@referential, @line, @route, @journey_pattern) + end end def new_vehicle_journey diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb index 3721a957d..2ff732721 100644 --- a/app/controllers/lines_controller.rb +++ b/app/controllers/lines_controller.rb @@ -22,9 +22,23 @@ class LinesController < ChouetteController @map = LineMap.new(resource).with_helpers(self) @routes = @line.routes @group_of_lines = @line.group_of_lines - show! + show! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + end end + def new + new! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + end + end # overwrite inherited resources to use delete instead of destroy # foreign keys will propagate deletion) def destroy_resource(object) diff --git a/app/controllers/networks_controller.rb b/app/controllers/networks_controller.rb index 04d565812..f99ff494b 100644 --- a/app/controllers/networks_controller.rb +++ b/app/controllers/networks_controller.rb @@ -10,7 +10,9 @@ class NetworksController < ChouetteController def show @map = NetworkMap.new(resource).with_helpers(self) - show! + show! do + add_breadcrumb Referential.human_attribute_name("networks"), referential_networks_path(@referential) + end end def index @@ -23,6 +25,19 @@ class NetworksController < ChouetteController end end + def new + new! do + add_breadcrumb Referential.human_attribute_name("networks"), referential_networks_path(@referential) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("networks"), referential_networks_path(@referential) + add_breadcrumb @network.name, referential_line_path(@referential, @network) + end + end + protected def collection diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb index 7b5e096db..7d51c47ad 100644 --- a/app/controllers/routes_controller.rb +++ b/app/controllers/routes_controller.rb @@ -18,9 +18,26 @@ class RoutesController < ChouetteController def show @map = RouteMap.new(route).with_helpers(self) @stop_points = route.stop_points.paginate(:page => params[:page]) - show! + show! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + end end + def new + new! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + end + end + + def edit + edit! do + add_breadcrumb Referential.human_attribute_name("lines"), referential_lines_path(@referential) + add_breadcrumb @line.name, referential_line_path(@referential, @line) + add_breadcrumb @route.name, referential_line_route_path(@referential, @line, @route) + end + end # overwrite inherited resources to use delete instead of destroy # foreign keys will propagate deletion) def destroy_resource(object) diff --git a/app/controllers/rule_parameter_sets_controller.rb b/app/controllers/rule_parameter_sets_controller.rb index fbd5281c8..9918e0eb5 100644 --- a/app/controllers/rule_parameter_sets_controller.rb +++ b/app/controllers/rule_parameter_sets_controller.rb @@ -6,7 +6,26 @@ class RuleParameterSetsController < ChouetteController def new @rule_parameter_set = RuleParameterSet.default( @referential) - new! + new! do + add_breadcrumb Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) + add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) + add_breadcrumb Referential.human_attribute_name("rule_parameter_sets"), referential_rule_parameter_sets_path(@referential) + end + end + + def index + index! do + add_breadcrumb Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) + add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) + end + end + + def show + show! do + add_breadcrumb Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) + add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) + add_breadcrumb Referential.human_attribute_name("rule_parameter_sets"), referential_rule_parameter_sets_path(@referential) + end end def destroy diff --git a/app/controllers/stop_area_copies_controller.rb b/app/controllers/stop_area_copies_controller.rb index dbb66c2bd..642932acd 100644 --- a/app/controllers/stop_area_copies_controller.rb +++ b/app/controllers/stop_area_copies_controller.rb @@ -8,7 +8,10 @@ class StopAreaCopiesController < ChouetteController def new @stop_area_copy = StopAreaCopy.new(:hierarchy => params[:hierarchy], :source => parent) - new! + new! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + end end def create diff --git a/app/controllers/stop_area_exports_controller.rb b/app/controllers/stop_area_exports_controller.rb deleted file mode 100644 index e675a9826..000000000 --- a/app/controllers/stop_area_exports_controller.rb +++ /dev/null @@ -1,25 +0,0 @@ -class StopAreaExportsController < ChouetteController - belongs_to :referential - - respond_to :csv, :only => [:index] - respond_to :xls, :only => [:index] - - def index - @column_names = column_names - index! do |format| - format.csv { send_data StopAreaExport.new( {:column_names => column_names, :stop_areas => collection} ).to_csv } - format.xls - end - end - - protected - - def column_names - ["id","name","longitude","latitude","area_type","parent_id", "comment","country_code","street_name","mobility_restricted_suitability","stairs_availability","lift_availability","int_user_needs"] - end - - def collection - @stop_areas ||= Chouette::StopArea.order(:country_code, :name) - end - -end diff --git a/app/controllers/stop_area_imports_controller.rb b/app/controllers/stop_area_imports_controller.rb deleted file mode 100644 index ff93dc40e..000000000 --- a/app/controllers/stop_area_imports_controller.rb +++ /dev/null @@ -1,24 +0,0 @@ -class StopAreaImportsController < ChouetteController - belongs_to :referential - - actions :new, :create - respond_to :html, :only => :new - - def new - @stop_area_import = StopAreaImport.new - new! - end - - def create - @stop_area_import = StopAreaImport.new(params[:stop_area_import]) - if @stop_area_import.save - redirect_to referential_stop_areas_path( @referential ), notice: I18n.t("stop_area_imports.new.success") - else - flash[:error] = I18n.t("stop_area_imports.errors.import_aborted") + "<br>" + @stop_area_import.errors.full_messages.join("<br>") - render :new - end - end - - protected - -end diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index e18f89cab..ca72c362b 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -19,30 +19,40 @@ class StopAreasController < ChouetteController def select_parent @stop_area = stop_area @parent = stop_area.parent + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) end def add_children @stop_area = stop_area @children = stop_area.children + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) end def add_routing_lines @stop_area = stop_area @lines = stop_area.routing_lines + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) end def add_routing_stops @stop_area = stop_area @stops = stop_area.routing_stops + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) 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 + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) end - def index + def index request.format.kml? ? @per_page = nil : @per_page = 12 @country_codes = referential.stop_areas.collect(&:country_code).compact.uniq index! do |format| @@ -51,27 +61,39 @@ class StopAreasController < ChouetteController redirect_to params.merge(:page => 1) end } - end + end + end + + def new + @map = StopAreaMap.new( Chouette::StopArea.new).with_helpers(self) + @map.editable = true + new! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + end end def show map.editable = false @access_points = @stop_area.access_points show! do |format| - unless stop_area.position or params[:default] or params[:routing] + unless stop_area.position or params[:default] or params[:routing] format.kml { - render :nothing => true, :status => :not_found + render :nothing => true, :status => :not_found } - + end + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) end end - + def edit stop_area.position ||= stop_area.default_position map.editable = true - edit! + edit! do + add_breadcrumb Referential.human_attribute_name("stop_areas"), referential_stop_areas_path(@referential) + add_breadcrumb @stop_area.name, referential_stop_area_path(@referential, @stop_area) + end end def default_geometry @@ -85,9 +107,9 @@ class StopAreasController < ChouetteController format.json { render :json => referential.stop_areas.collect(&:country_code).compact.uniq.to_json } end end - + protected - + alias_method :stop_area, :resource def map @@ -96,7 +118,7 @@ class StopAreasController < ChouetteController def collection @q = parent.present? ? parent.stop_areas.search(params[:q]) : referential.stop_areas.search(params[:q]) - @stop_areas ||= + @stop_areas ||= begin stop_areas = @q.result(:distinct => true).order(:name) stop_areas = stop_areas.paginate(:page => params[:page], :per_page => @per_page) if @per_page.present? diff --git a/app/controllers/vehicle_journey_exports_controller.rb b/app/controllers/vehicle_journey_exports_controller.rb index ed1cd61a6..0cc30f23a 100644 --- a/app/controllers/vehicle_journey_exports_controller.rb +++ b/app/controllers/vehicle_journey_exports_controller.rb @@ -6,21 +6,28 @@ class VehicleJourneyExportsController < ChouetteController end respond_to :csv, :only => [:index] - respond_to :xls, :only => [:index] + respond_to :zip, :only => [:index] + #respond_to :xls, :only => [:index] def index - @column_names = column_names index! do |format| - format.csv { send_data VehicleJourneyExport.new(:route => route, :vehicle_journeys => vehicle_journeys, :column_names => column_names).to_csv } - format.xls + format.csv { send_data VehicleJourneyExport.new(:route => route, :vehicle_journeys => vehicle_journeys).to_csv(:col_sep => ";") , :filename => t("vehicle_journey_exports.new.basename")+"_#{route.id}.csv" } + format.zip do + begin + temp_file = Tempfile.new("vehicle_journey_export") + VehicleJourneyExport.new(:route => route, :vehicle_journeys => vehicle_journeys).to_zip(temp_file,:col_sep => ";") + send_data File.read(temp_file.path), :filename => t("vehicle_journey_exports.new.basename")+"_#{route.id}.zip" + ensure + temp_file.close + temp_file.unlink + end + end + #format.xls end end protected - def column_names - ["stop_point_id", "stop_area_name"] + vehicle_journeys.collect(&:objectid) - end alias_method :route, :parent diff --git a/app/controllers/vehicle_journey_imports_controller.rb b/app/controllers/vehicle_journey_imports_controller.rb index 8246541bc..136fac6d3 100644 --- a/app/controllers/vehicle_journey_imports_controller.rb +++ b/app/controllers/vehicle_journey_imports_controller.rb @@ -16,7 +16,12 @@ class VehicleJourneyImportsController < ChouetteController def create @vehicle_journey_import = VehicleJourneyImport.new( params[:vehicle_journey_import].present? ? params[:vehicle_journey_import].merge({:route => route}) : {:route => route} ) if @vehicle_journey_import.save - redirect_to referential_line_route_path( @referential, @line, @route ), notice: I18n.t("vehicle_journey_imports.new.success") + notice = I18n.t("vehicle_journey_imports.new.success") + + "<br>" + I18n.t("vehicle_journey_imports.success.created_jp_count",:count => @vehicle_journey_import.created_journey_pattern_count) + + "<br>" + I18n.t("vehicle_journey_imports.success.created_vj_count",:count => @vehicle_journey_import.created_vehicle_journey_count) + + "<br>" + I18n.t("vehicle_journey_imports.success.updated_vj_count",:count => @vehicle_journey_import.updated_vehicle_journey_count) + + "<br>" + I18n.t("vehicle_journey_imports.success.deleted_vj_count",:count => @vehicle_journey_import.deleted_vehicle_journey_count) + redirect_to referential_line_route_path( @referential, @line, @route ), notice: notice else flash[:error] = I18n.t("vehicle_journey_imports.errors.import_aborted") + "<br>" + @vehicle_journey_import.errors.full_messages.join("<br>") render :new diff --git a/app/exporters/chouette/hub/exporter.rb b/app/exporters/chouette/hub/exporter.rb index 96e125814..2d14d3a3b 100644 --- a/app/exporters/chouette/hub/exporter.rb +++ b/app/exporters/chouette/hub/exporter.rb @@ -1,4 +1,5 @@ class Chouette::Hub::Exporter + require "zip" attr_reader :referential attr_reader :hub_export, :lines, :routes, :journey_patterns @@ -174,7 +175,7 @@ class Chouette::Hub::Exporter end - ::Zip::ZipFile.open(zip_file_path, ::Zip::ZipFile::CREATE) do |zipfile| + ::Zip::File.open(zip_file_path, ::Zip::File::CREATE) do |zipfile| Dir[File.join(temp_dir, '*.TXT')].each do |f| #Rails.logger.error("Adding File #{File.basename(f)}") zipfile.add(File.basename(f), f) diff --git a/app/exporters/chouette/kml/exporter.rb b/app/exporters/chouette/kml/exporter.rb index 06af4bc2f..5b6170edc 100644 --- a/app/exporters/chouette/kml/exporter.rb +++ b/app/exporters/chouette/kml/exporter.rb @@ -1,5 +1,7 @@ class Chouette::Kml::Exporter + require 'zip' + attr_reader :referential attr_reader :kml_export, :lines, :routes, :journey_patterns @@ -103,7 +105,7 @@ class Chouette::Kml::Exporter end - ::Zip::ZipFile.open(zip_file_path, ::Zip::ZipFile::CREATE) do |zipfile| + ::Zip::File.open(zip_file_path, ::Zip::File::CREATE) do |zipfile| Dir[File.join(temp_dir, '*.kml')].each do |f| zipfile.add(File.basename(f), f) end diff --git a/app/helpers/exports_helper.rb b/app/helpers/exports_helper.rb index 1ae59c190..9be7a5e46 100644 --- a/app/helpers/exports_helper.rb +++ b/app/helpers/exports_helper.rb @@ -1,15 +1,19 @@ module ExportsHelper def fields_for_export_type(form) - partial_name = "fields_#{form.object.type.underscore}" + #partial_name = "fields_#{form.object.type.underscore}" begin - render :partial => partial_name, :locals => { :form => form } + render :partial => export_partial_name(form), :locals => { :form => form } rescue ActionView::MissingTemplate "" end end + def export_partial_name(form) + "fields_#{form.object.type.underscore}" + end + include TypeIdsModelsHelper end diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb index 22ce8ea98..7f58b229e 100644 --- a/app/helpers/imports_helper.rb +++ b/app/helpers/imports_helper.rb @@ -2,14 +2,18 @@ module ImportsHelper def fields_for_import_task_format(form) - partial_name = "fields_#{form.object.format.underscore}_import" + #partial_name = "fields_#{form.object.format.underscore}_import" begin - render :partial => partial_name, :locals => { :form => form } + render :partial => import_partial_name(form), :locals => { :form => form } rescue ActionView::MissingTemplate "" end end + + def import_partial_name(form) + "fields_#{form.object.format.underscore}_import" + end def compliance_icon( import_task) return nil unless import_task.compliance_check_task diff --git a/app/maps/stop_area_map.rb b/app/maps/stop_area_map.rb index 3fff4a110..ee0adc0bb 100644 --- a/app/maps/stop_area_map.rb +++ b/app/maps/stop_area_map.rb @@ -10,9 +10,6 @@ class StopAreaMap < ApplicationMap end def customize_map(map, page) - page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => Design::EditStopAreaStyleMap.new(helpers).style_map) - page << map.add_layer(:edit_stop_area_layer) - if stop_area.children.present? page.assign "children_layer", kml_layer(stop_area, { :children => true }, :style_map => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:children_layer) @@ -23,27 +20,106 @@ class StopAreaMap < ApplicationMap page << map.add_control( hover_control_display_name(:routing_layer) ) page << map.zoom_to_extent(bounds.to_google.to_openlayers) if bounds else - - page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => Design::EditStopAreaStyleMap.new(helpers).style_map) + + + if stop_area.new_record? + page << <<EOF + var createStyleMap = function() { + var defProp = {strokeColor: "red"}; + var defProp = {strokeColor: "black", strokeOpacity: 1, strokeWidth: 2, fillColor: "white", fillOpacity: 1}; + var defStyle = OpenLayers.Util.applyDefaults(defProp, OpenLayers.Feature.Vector.style["default"]); + return new OpenLayers.StyleMap({'default': defStyle}); + }; + var edit_stop_area_layer = new OpenLayers.Layer.Vector( "edit_stop_area_layer", {styleMap: createStyleMap()}); + +EOF + else + page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => Design::EditStopAreaStyleMap.new(helpers).style_map) + end + + page << <<EOF + var createAddressStyleMap = function() { + var defProp = {strokeColor: "black", strokeOpacity: 1, strokeWidth: 2, fillColor: "#86b41d", fillOpacity: 1}; + var defStyle = OpenLayers.Util.applyDefaults(defProp, OpenLayers.Feature.Vector.style["default"]); + return new OpenLayers.StyleMap({'default': defStyle, }); + }; + var address_layer = new OpenLayers.Layer.Vector( "address_layer", {styleMap: createAddressStyleMap()}); + + var removeAddress = function() { + address_layer.destroyFeatures(); + }; + + var addAddress = function( lat, lng, name ) { + var wgs84point = new OpenLayers.Geometry.Point( lat, lng); + var point = transformedGeometry( wgs84point, "EPSG:4326", "EPSG:900913" ) + var feature = new OpenLayers.Feature.Vector( point, { name: name}); + address_layer.addFeatures( [feature]); + + var bounds = new OpenLayers.Bounds(); + bounds.extend( feature.geometry.getBounds()); + for (var x in edit_stop_area_layer.features) { + bounds.extend( edit_stop_area_layer.features[x].geometry.getBounds()); + } + map.zoomToExtent(bounds,true); + }; + var transformedGeometry = function( geometry, origin, target ) { + return geometry.clone().transform( new OpenLayers.Projection( origin ), new OpenLayers.Projection( target )); + } +EOF + page << map.add_layer(:address_layer) page << map.add_layer(:edit_stop_area_layer) - + if editable? - page.assign "referential_projection", projection_type.present? ? projection("EPSG:" + projection_type) : JsVar.new("undefined") - # TODO virer ce code inline + page.assign "referential_projection", projection_type.present? ? projection("EPSG:" + projection_type) : JsVar.new("undefined") + + # TODO virer ce code inline page << <<EOF - edit_stop_area_layer.events.on({ - 'afterfeaturemodified': function(event) { - geometry = event.feature.geometry.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")); - $('#stop_area_coordinates').val(geometry.y.toString()+ ","+ geometry.x.toString()); - - if(referential_projection != undefined) - { - projection_geometry = event.feature.geometry.clone().transform(new OpenLayers.Projection("EPSG:900913"), referential_projection ); - $('#stop_area_projection_xy').val(projection_geometry.x.toString()+ ","+ projection_geometry.y.toString()); } - } - }); + + var getEventWGS84 = function( event) { + return transformedGeometry( event.geometry, "EPSG:900913", "EPSG:4326"); + } + var getEventProjection = function( event, projCode) { + return transformedGeometry( event.geometry, "EPSG:900913", projCode); + } + var updateStopAreaCoordinates = function( event ) { + var geometry = getEventWGS84( event ); + $('#stop_area_coordinates').val( geometry.y.toString()+ ","+ geometry.x.toString()); + } + var updateStopAreaProjectionXY = function( event, projCode ) { + var geometry = getEventProjection( event, projCode); + $('#stop_area_projection_xy').val( geometry.x.toString()+ ","+ geometry.y.toString()); + } + + var drawControl = new OpenLayers.Control.DrawFeature( edit_stop_area_layer, OpenLayers.Handler.Point, + { featureAdded: function(event) { + console.log( "featureAdded" ); + updateStopAreaCoordinates( event); + if( typeof referential_projection !== 'undefined') { + updateStopAreaProjectionXY( event, referential_projection.projCode); + } + this.deactivate(); + } + }); + + var dragControl = new OpenLayers.Control.DragFeature( edit_stop_area_layer, + { autoActivate: true, + onComplete: function(event) { + updateStopAreaCoordinates( event); + if( typeof referential_projection !== 'undefined') { + updateStopAreaProjectionXY( event, referential_projection.projCode); + } + }, + }); + map.addControl( dragControl); + map.addControl( drawControl); EOF - page << map.add_control(OpenLayers::Control::ModifyFeature.new(:edit_stop_area_layer, :mode => 8, :autoActivate => true)) + + if stop_area.new_record? + page << <<EOF + drawControl.activate(); +EOF + end + #page << map.add_control(OpenLayers::Control::ModifyFeature.new(:edit_stop_area_layer, :mode => 8, :autoActivate => true)) elsif stop_area.children.present? page << map.add_control( hover_control_display_name(:children_layer) ) @@ -52,7 +128,7 @@ EOF page << map.set_center(center.to_google.to_openlayers, 16, false, true) end end - + def projection_type stop_area.referential.projection_type end diff --git a/app/models/export.rb b/app/models/export.rb index 98b3f0ace..4d7b5c56c 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -3,7 +3,7 @@ class Export < ActiveRecord::Base belongs_to :referential validates_presence_of :referential_id - validates_inclusion_of :status, :in => %w{ pending completed failed } + validates_inclusion_of :status, :in => %w{ pending processing completed failed } has_many :log_messages, :class_name => "ExportLogMessage", :order => :position, :dependent => :delete_all @@ -51,12 +51,7 @@ class Export < ActiveRecord::Base end def export_object_type -# case references_type -# when "Chouette::Network" -# "ptnetwork" -# else references_relation ? references_relation.singularize : "line" -# end end before_validation :define_default_attributes, :on => :create @@ -91,10 +86,19 @@ class Export < ActiveRecord::Base log_messages.create :severity => result_severity, :key => status end - @@references_types = [ Chouette::Line, Chouette::Network, Chouette::Company ] - cattr_reader :references_types - validates_inclusion_of :references_type, :in => references_types.map(&:to_s), :allow_blank => true, :allow_nil => true + def self.all_references_types + [ Chouette::Line, Chouette::Network, Chouette::Company , Chouette::StopArea] + end + + def references_types + [ Chouette::Line, Chouette::Network, Chouette::Company ] + end + + # @@references_types = [ Chouette::Line, Chouette::Network, Chouette::Company ] + # cattr_reader :references_types + + # validates_inclusion_of :references_type, :in => references_types.map(&:to_s), :allow_blank => true, :allow_nil => true def self.format_name(format) name_by_format = { @@ -107,6 +111,10 @@ class Export < ActiveRecord::Base } name_by_format[format] end + + def self.format_label(format) + I18n.t 'exchange.format.'+format.sub("Export",'').downcase + end def self.types unless Rails.env.development? diff --git a/app/models/gtfs_export.rb b/app/models/gtfs_export.rb index 9c66e778b..6f43a93eb 100644 --- a/app/models/gtfs_export.rb +++ b/app/models/gtfs_export.rb @@ -5,6 +5,10 @@ class GtfsExport < Export after_initialize :init_time_zone + def references_types + [ Chouette::Line, Chouette::Network, Chouette::Company, Chouette::StopArea ] + end + def init_time_zone if time_zone.nil? self.time_zone = "Paris" diff --git a/app/models/gtfs_import.rb b/app/models/gtfs_import.rb index af83d81a0..c2457548f 100644 --- a/app/models/gtfs_import.rb +++ b/app/models/gtfs_import.rb @@ -7,4 +7,8 @@ class GtfsImport < ImportTask option :ignore_end_chars option :max_distance_for_connection_link + def references_types + [ Chouette::StopArea ] + end + end diff --git a/app/models/import_task.rb b/app/models/import_task.rb index 90783075d..26b3808c7 100644 --- a/app/models/import_task.rb +++ b/app/models/import_task.rb @@ -15,6 +15,10 @@ class ImportTask < ActiveRecord::Base validates_presence_of :user_name validates_inclusion_of :status, :in => %w{ pending processing completed failed } + def references_types + [] + end + protected def self.option(name, type=nil) @@ -41,6 +45,10 @@ class ImportTask < ActiveRecord::Base %w{Neptune Csv Gtfs Netex} end + def self.format_label(format) + I18n.t 'exchange.format.'+format.downcase + end + def delayed_import delay.import end @@ -54,6 +62,7 @@ class ImportTask < ActiveRecord::Base option :no_save, :boolean option :format option :file_path + option :references_type validates_inclusion_of :no_save, :in => [ true, false] validates_inclusion_of :format, :in => self.formats diff --git a/app/models/referential.rb b/app/models/referential.rb index f99c65f9f..41d239961 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -41,6 +41,10 @@ class Referential < ActiveRecord::Base end end + def viewbox_left_top_right_bottom + [ lower_corner.lng, upper_corner.lat, upper_corner.lng, lower_corner.lat ].join(',') + end + def human_attribute_name(*args) self.class.human_attribute_name(*args) end diff --git a/app/models/stop_area_export.rb b/app/models/stop_area_export.rb deleted file mode 100644 index 1b9cc36a7..000000000 --- a/app/models/stop_area_export.rb +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -require "csv" - -class StopAreaExport - include ActiveModel::Validations - include ActiveModel::Conversion - extend ActiveModel::Naming - - attr_accessor :column_names, :stop_areas - - def initialize(attributes = {}) - attributes.each { |name, value| send("#{name}=", value) } - end - - def persisted? - false - end - - def to_csv(options = {}) - CSV.generate(options) do |csv| - csv << column_names - stop_areas.each do |stop_area| - csv << stop_area.attributes.values_at(*column_names) - end - end - end - -end diff --git a/app/models/stop_area_import.rb b/app/models/stop_area_import.rb deleted file mode 100644 index 52d8a94bb..000000000 --- a/app/models/stop_area_import.rb +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- - -class StopAreaImport - include ActiveModel::Validations - include ActiveModel::Conversion - extend ActiveModel::Naming - - attr_accessor :file - - validates_presence_of :file - - def initialize(attributes = {}) - attributes.each { |name, value| send("#{name}=", value) } if attributes - end - - def persisted? - false - end - - def save - begin - Chouette::StopArea.transaction do - if imported_stop_areas.map(&:valid?).all? - imported_stop_areas.each(&:save!) - true - else - imported_stop_areas.each_with_index do |imported_stop_area, index| - imported_stop_area.errors.full_messages.each do |message| - errors.add :base, I18n.t("stop_area_imports.errors.invalid_stop_area", :column => index+2, :message => message) - end - end - false - end - end - rescue Exception => exception - Rails.logger.error(exception.message) - errors.add :base, I18n.t("stop_area_imports.errors.exception") - false - end - end - - def imported_stop_areas - @imported_stop_areas ||= load_imported_stop_areas - end - - def load_imported_stop_areas - spreadsheet = open_spreadsheet(file) - header = spreadsheet.row(1) - (2..spreadsheet.last_row).map do |i| - row = Hash[[header, spreadsheet.row(i)].transpose] - stop_area = Chouette::StopArea.find_by_id(row["id"]) || Chouette::StopArea.new - stop_area.attributes = row.to_hash.slice(*Chouette::StopArea.accessible_attributes) - stop_area - end - end - - def open_spreadsheet(file) - case File.extname(file.original_filename) - when '.csv' then Roo::CSV.new(file.path) - when '.xls' then Roo::Excel.new(file.path) - when '.xlsx' then Roo::Excelx.new(file.path) - else - raise "Unknown file type: #{file.original_filename}" - end - end - -end diff --git a/app/models/vehicle_journey_export.rb b/app/models/vehicle_journey_export.rb index 7f5577e22..3de88b608 100644 --- a/app/models/vehicle_journey_export.rb +++ b/app/models/vehicle_journey_export.rb @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- require "csv" +require "zip" class VehicleJourneyExport include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming - attr_accessor :vehicle_journeys, :column_names, :route + attr_accessor :vehicle_journeys, :route def initialize(attributes = {}) attributes.each { |name, value| send("#{name}=", value) } @@ -16,20 +17,151 @@ class VehicleJourneyExport false end - def vehicle_journey_at_stops_matrix - (vehicle_journeys.collect{ |vj| vj.vehicle_journey_at_stops.collect(&:departure_time).collect{|time| time.strftime("%H:%M")} }).transpose + def label(name) + I18n.t "vehicle_journey_exports.label.#{name}" + end + + def column_names + ["", label("vehicle_journey_id")] + vehicle_journeys.collect(&:id) + end + + # produce a map stop_id => departure time for a vehicle_journey + def time_by_stops(vj) + {}.tap do |hash| + vj.vehicle_journey_at_stops.each do |vjas| + hash[ "#{vjas.stop_point_id}"] = vjas.departure_time.strftime("%H:%M") + end + end + end + + def time_tables (vj) + (vj.time_tables.collect{ |t| t.id }) + end + + def time_tables_array + (vehicle_journeys.collect{ |vj| time_tables(vj).to_s[1..-2] } ) + end + + def vehicle_journey_at_stops_array + (vehicle_journeys.collect{ |vj| time_by_stops vj } ) + end + + def boolean_code(b) + b.nil? ? "" : label("b_"+b.to_s) + end + + def number_array + (vehicle_journeys.collect{ |vj| vj.number ? vj.number.to_s : "" } ) + end + + def vehicle_identifier_array + (vehicle_journeys.collect{ |vj| vj.vehicle_type_identifier ? vj.vehicle_type_identifier : "" } ) + end + + def flexible_service_array + (vehicle_journeys.collect{ |vj| boolean_code vj.flexible_service } ) + end + + def mobility_restricted_suitability_array + (vehicle_journeys.collect{ |vj| boolean_code vj.mobility_restricted_suitability } ) + end + + def empty_array + (vehicle_journeys.collect{ |vj| "" } ) + end + + def times_of_stop(stop_id,vjas_array) + a = [] + vjas_array.each do |map| + a << (map[stop_id.to_s].present? ? map[stop_id.to_s] : "") + end + a end def to_csv(options = {}) CSV.generate(options) do |csv| csv << column_names - route.stop_points.each_with_index do |stop_point, index| - puts vehicle_journey_at_stops_matrix[index].inspect - - times = vehicle_journey_at_stops_matrix[index].present? ? vehicle_journey_at_stops_matrix[index] : [] + csv << ["", label("number")] + number_array + csv << ["", label("vehicle_identifier")] + vehicle_identifier_array + csv << ["", label("mobility")] + mobility_restricted_suitability_array + csv << ["", label("flexible_service")] + flexible_service_array + csv << ["", label("time_table_ids")] + time_tables_array + csv << [label("stop_id"), label("stop_name")] + empty_array + vjas_array = vehicle_journey_at_stops_array + route.stop_points.each_with_index do |stop_point, index| + times = times_of_stop(stop_point.id,vjas_array) csv << [stop_point.id, stop_point.stop_area.name] + times end end end + def tt_day_types(tt) + type = tt.monday ? label("monday") : ".." + type += tt.tuesday ? label("tuesday") : ".." + type += tt.wednesday ? label("wednesday") : ".." + type += tt.thursday ? label("thursday") : ".." + type += tt.friday ? label("friday") : ".." + type += tt.saturday ? label("saturday") : ".." + type += tt.sunday ? label("sunday") : ".." + type + end + + def tt_periods(tt) + periods = "" + tt.periods.each do |p| + periods += "["+p.period_start.to_s+" -> "+p.period_end.to_s+"] " + end + periods + end + + def tt_peculiar_days(tt) + days = "" + tt.included_days.each do |d| + days += d.to_s+" " + end + days + end + + def tt_excluded_days(tt) + days = "" + tt.excluded_days.each do |d| + days += d.to_s+" " + end + days + end + + def tt_data(tt) + [].tap do |array| + # code;name;tags;start;end;day types;periods;peculiar days;excluded days + array << tt.id.to_s + array << tt.comment + array << tt.tag_list + array << tt.start_date.to_s + array << tt.end_date.to_s + array << tt_day_types(tt) + array << tt_day_types(tt) + array << tt_periods(tt) + array << tt_peculiar_days(tt) + array << tt_excluded_days(tt) + end + end + + def time_tables_to_csv (options = {}) + tts = Chouette::TimeTable.all + CSV.generate(options) do |csv| + csv << label("tt_columns").split(";") + tts.each do |tt| + csv << tt_data(tt) + end + end + end + + def to_zip(temp_file,options = {}) + ::Zip::OutputStream.open(temp_file) { |zos| } + ::Zip::File.open(temp_file.path, ::Zip::File::CREATE) do |zipfile| + zipfile.get_output_stream(label("vj_filename")+route.id.to_s+".csv") { |f| f.puts to_csv(options) } + zipfile.get_output_stream(label("tt_filename")+".csv") { |f| f.puts time_tables_to_csv(options) } + end + end + end diff --git a/app/models/vehicle_journey_import.rb b/app/models/vehicle_journey_import.rb index 15569c3d4..42cc24244 100644 --- a/app/models/vehicle_journey_import.rb +++ b/app/models/vehicle_journey_import.rb @@ -6,12 +6,19 @@ class VehicleJourneyImport extend ActiveModel::Naming attr_accessor :file, :route + attr_accessor :created_vehicle_journey_count,:updated_vehicle_journey_count,:deleted_vehicle_journey_count + attr_accessor :created_journey_pattern_count,:error_count validates_presence_of :file validates_presence_of :route def initialize(attributes = {}) attributes.each { |name, value| send("#{name}=", value) } if attributes + self.created_vehicle_journey_count = 0 + self.updated_vehicle_journey_count = 0 + self.created_journey_pattern_count = 0 + self.deleted_vehicle_journey_count = 0 + self.error_count = 0 end def persisted? @@ -27,14 +34,15 @@ class VehicleJourneyImport else imported_vehicle_journeys.each_with_index do |imported_vehicle_journey, index| imported_vehicle_journey.errors.full_messages.each do |message| - errors.add :base, I18n.t("vehicle_journey_imports.errors.invalid_vehicle_journey", :column => index, :message => message) + errors.add :base, I18n.t("vehicle_journey_imports.errors.invalid_vehicle_journey", :column => index+1, :message => message) end end - false + raise end end rescue Exception => exception Rails.logger.error(exception.message) + Rails.logger.error(exception.backtrace) errors.add :base, I18n.t("vehicle_journey_imports.errors.exception") false end @@ -45,21 +53,58 @@ class VehicleJourneyImport end # Find journey pattern on stop points used in vehicle journey at stops - def find_journey_pattern_schedule(hours_by_stop_point_ids) + # if no stop_point used found, return nil to delete vehicle_journey if exists + # if only 1 stop_point used found, raise exception to stop import + def find_journey_pattern_schedule(column,hours_by_stop_point_ids) stop_points_used = hours_by_stop_point_ids.reject{ |key,value| value == nil }.keys + return nil if stop_points_used.empty? + + if stop_points_used.length == 1 + errors.add :base, I18n.t("vehicle_journey_imports.errors.one_stop_point_used", :column => column) + raise + end + journey_pattern_founded = route.journey_patterns.select{ |jp| jp.stop_points.collect(&:id) == stop_points_used }.first # If no journey pattern founded, create a new one - journey_pattern_founded ? journey_pattern_founded : route.journey_patterns.create(:stop_points => Chouette::StopPoint.find(stop_points_used) ) + self.created_journey_pattern_count += 1 if journey_pattern_founded.nil? + journey_pattern_founded ? journey_pattern_founded : route.journey_patterns.create(:stop_points => Chouette::StopPoint.find(stop_points_used) ) + end + + def as_integer(v) + v.blank? ? nil : v.to_i + end + + def as_boolean(v) + v.blank? ? nil : (v[1..1].downcase != "n") + end + + def update_time_tables(vj,tm_ids) + vj.time_tables.clear + return unless tm_ids.present? + ids = tm_ids.split(",").map(&:to_i) + vj.time_tables << Chouette::TimeTable.find(ids) end def load_imported_vehicle_journeys + spreadsheet = open_spreadsheet(file) - vehicle_journeys = [] + vehicle_journeys = [] first_column = spreadsheet.column(1) - stop_point_ids = first_column[1..spreadsheet.last_row].map(&:to_i) + + # fixed rows (first = 1) + number_row = 2 + vehicle_type_identifier_row = 3 + mobility_row = 4 + flexible_service_row = 5 + time_tables_row = 6 + + # rows in column (first = 0) + first_stop_row_index = 7 + + stop_point_ids = first_column[first_stop_row_index..spreadsheet.last_row].map(&:to_i) same_stop_points = route.stop_points.collect(&:id) == stop_point_ids unless same_stop_points @@ -68,22 +113,55 @@ class VehicleJourneyImport end (3..spreadsheet.last_column).each do |i| - vehicle_journey_at_stops = [] - vehicle_journey_objectid = spreadsheet.column(i)[0] - hours_by_stop_point_ids = Hash[[stop_point_ids, spreadsheet.column(i)[1..spreadsheet.last_row]].transpose] + vehicle_journey_id = spreadsheet.column(i)[0] + hours_by_stop_point_ids = Hash[[stop_point_ids, spreadsheet.column(i)[first_stop_row_index..spreadsheet.last_row]].transpose] + + journey_pattern = find_journey_pattern_schedule(i,hours_by_stop_point_ids) + + vehicle_journey = route.vehicle_journeys.where(:id => vehicle_journey_id, :route_id => route.id).first_or_initialize + + if journey_pattern.nil? + if vehicle_journey.id.present? + self.deleted_vehicle_journey_count += 1 + vehicle_journey.delete + end + next + end + if vehicle_journey.id.present? + self.updated_vehicle_journey_count += 1 + else + self.created_vehicle_journey_count += 1 + end + + # number + vehicle_journey.number = as_integer(spreadsheet.row(number_row)[i-1]) + + # vehicle_type_identifier + vehicle_journey.vehicle_type_identifier = spreadsheet.row(vehicle_type_identifier_row)[i-1] + + # flexible_service + vehicle_journey.flexible_service = as_boolean(spreadsheet.row(flexible_service_row)[i-1]) + + # mobility + vehicle_journey.mobility_restricted_suitability = as_boolean(spreadsheet.row(mobility_row)[i-1]) + + # time_tables + update_time_tables(vehicle_journey,spreadsheet.row(time_tables_row)[i-1]) - journey_pattern = find_journey_pattern_schedule(hours_by_stop_point_ids) - vehicle_journey = journey_pattern.vehicle_journeys.where(:objectid => vehicle_journey_objectid, :route_id => route.id, :journey_pattern_id => journey_pattern.id).first_or_initialize + # journey_pattern + vehicle_journey.journey_pattern = journey_pattern + vehicle_journey.vehicle_journey_at_stops.clear line = 0 hours_by_stop_point_ids.each_pair do |key, value| line += 1 if value.present? # Create a vehicle journey at stop when time is present begin - main_time = Time.parse(value) + # force UTC to ignore timezone effects + main_time = Time.parse(value+" UTC") if main_time.present? - vjas = { :stop_point_id => key, :vehicle_journey_id => vehicle_journey.id, :departure_time => main_time, :arrival_time => main_time } - vehicle_journey_at_stops << vjas + vjas = Chouette::VehicleJourneyAtStop.new(:stop_point_id => key, :vehicle_journey_id => vehicle_journey.id, :departure_time => main_time, :arrival_time => main_time ) + vehicle_journey.vehicle_journey_at_stops << vjas end rescue Exception => exception errors.add :base, I18n.t("vehicle_journey_imports.errors.invalid_vehicle_journey_at_stop", :column => i, :line => line, :time => value) @@ -91,7 +169,6 @@ class VehicleJourneyImport end end end - vehicle_journey.vehicle_journey_at_stops_attributes = vehicle_journey_at_stops vehicle_journeys << vehicle_journey end @@ -100,7 +177,7 @@ class VehicleJourneyImport def open_spreadsheet(file) case File.extname(file.original_filename) - when '.csv' then Roo::CSV.new(file.path) + when '.csv' then Roo::CSV.new(file.path, csv_options: {col_sep: ";"}) when '.xls' then Roo::Excel.new(file.path) when '.xlsx' then Roo::Excelx.new(file.path) else diff --git a/app/views/exports/new.html.erb b/app/views/exports/new.html.erb index 553ebe4a2..8405e2c4d 100644 --- a/app/views/exports/new.html.erb +++ b/app/views/exports/new.html.erb @@ -2,7 +2,7 @@ <%= semantic_form_for([@referential, @export], :as => :export, :url => new_referential_export_path(@referential), :method => :get) do |form| %> <%= form.inputs do %> - <%= form.input :type, :as => :radio, :collection => Export.types.map { |format| [ Export.format_name(format), format]}, :required => true, :include_blank => false %> + <%= form.input :type, :as => :radio, :collection => Export.types.map { |format| [ Export.format_label(format), format]}, :required => true, :include_blank => false %> <% end %> <% end %> @@ -14,9 +14,10 @@ <%= form.inputs do %> <%= form.input :type, :as => :hidden %> - <%= form.input :references_type, :as => :select, :collection => Export.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> + <p class="warning"><%= t('.'+export_partial_name(form)+'.warning',:default => "")%></p> + <%= form.input :references_type, :as => :select, :collection => export.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> - <% Export.references_types.each do |type| %> + <% export.references_types.each do |type| %> <%= type_ids_model_references_input(form, @export, Export, type).input %> <% end %> <% end %> diff --git a/app/views/exports/new.js.coffee b/app/views/exports/new.js.coffee index 0886f53c9..aafa70bed 100644 --- a/app/views/exports/new.js.coffee +++ b/app/views/exports/new.js.coffee @@ -1,4 +1,4 @@ jQuery -> - <% Export.references_types.map { |type| type_ids_model_references_type( Export, type)}.each do |rt| %> + <% Export.all_references_types.map { |type| type_ids_model_references_type( Export, type)}.each do |rt| %> $("textarea.<%= rt.input_class %>").tokenInput('<%= references_referential_compliance_check_tasks_path(@referential, :type => rt.relation_name, :format => :json) %>', { prePopulate: $('#').data('pre'), minChars: 1, hintText: '<%= t('search_hint') %>', noResultsText: '<%= t('no_result_text') %>', searchingText: '<%= t('searching_term') %>'}); <% end %> diff --git a/app/views/help/exports.textile b/app/views/help/exports.textile index c82f8cea2..03ae1f1d0 100644 --- a/app/views/help/exports.textile +++ b/app/views/help/exports.textile @@ -39,6 +39,9 @@ la sélection propose dès le premier caractère saisi la liste des objets dont - Fuseau horaire := fixe le fuseau horaire (paramètre obligatoire des données GTFS) la valeur proposée par défaut est celle de l'espace de données =: +- Données incluses (complément) := +le choix des arrêts permet de n'exporter que les fichiers d'arrêts (stops.txt) et de correspondances (transfers.txt) + 3 champs sont alors ajoutés : l'adresse, la localité et le code postal; ceux-ci seront exploités en retour sur l'import GTFS d'arrêts =: * *NeTex* : pas d'option particulière @@ -49,15 +52,15 @@ fixe le fuseau horaire (paramètre obligatoire des données GTFS) - Début de période := permet d'exporter uniquement les courses circulant à partir de cette date - Fin de période := permet d'exporter uniquement les courses circulant jusqu'à cette date - Fuseau horaire := -fixe le fuseau horaire (paramètre obligatoire des données GTFS) +fixe le fuseau horaire la valeur proposée par défaut est celle de l'espace de données =: - h3. Consultation des résultats p. L'export est lancé en différé; son état d'avancement est affiché sous la forme d'une icône donc la couleur dépend de l'état: +* blanc : en attente * bleu : en cours * vert : terminé correctement; un lien de téléchargement est alors disponible * rouge : terminé en échec diff --git a/app/views/help/imports.textile b/app/views/help/imports.textile index 88b780b7f..66966b515 100644 --- a/app/views/help/imports.textile +++ b/app/views/help/imports.textile @@ -41,6 +41,8 @@ format originaire de ["Google Transit":https://support.google.com/transitpartner p(olnext). - les données exportées en GTFS sont explicités ["ICI":http://www.normes-donnees-tc.org/format-dechange/autres-normes/] +p(olnext). - l'import limité au sous ensemble des arrêts permet de n'importer que les arrêts et les correspondances + h3(#com). Paramètres communs - Pas de sauvegarde := permet d'effectuer une simulation de l'import sans enregistrer les données @@ -79,6 +81,9 @@ distance maximale entre deux arrêts pour les lier par une correspondance, ces correspondances sont hors zone d'arrêt; elles viennent en supplément de celles définies dans GTFS (ce mécanisme tient compte des correspondances exclues), une distance de 0 ne génère aucune correspondance =: +- Sous-ensemble := +choix permetant de limiter l'import aux seuls fichiers stops.txt et transfers.txt +lors de l'import, les attributs d'adresse, localité et code postal ajoutés à l'export associé sont exploités =: * *CSV* : @@ -90,7 +95,7 @@ h3(#imp). l'onglet IMPORTS p. L'onglet IMPORTS contient les objets Import de l'espace de données courant. -p. Chaque objet Import est représenté par une vignette comprenant : sa date, l'utilisateur qui l'a créé, son état (bleu : en cours ; vert : terminé correctement ; rouge : terminé en échec), un lien pour télécharger le fichier importé, un lien vers le détail de l'objet, un lien vers l'objet Validation associé). +p. Chaque objet Import est représenté par une vignette comprenant : sa date, l'utilisateur qui l'a créé, son état (blanc: en attente, bleu : en cours ; vert : terminé correctement ; rouge : terminé en échec), un lien pour télécharger le fichier importé, un lien vers le détail de l'objet, un lien vers l'objet Validation associé). p=. !import.png! diff --git a/app/views/import_tasks/_fields_gtfs_import.erb b/app/views/import_tasks/_fields_gtfs_import.erb index 70ffb207a..8b9dabcc5 100644 --- a/app/views/import_tasks/_fields_gtfs_import.erb +++ b/app/views/import_tasks/_fields_gtfs_import.erb @@ -1,7 +1,7 @@ <%= form.input :object_id_prefix, :input_html => { :value => @referential.prefix } %> -<%= form.input :max_distance_for_commercial , :as => :number , :input_html => { :title => t("formtastic.titles.import_task.max_distance_for_commercial"), :value => 50 } %> +<%= form.input :max_distance_for_commercial , :as => :number , :input_html => { :title => t("formtastic.titles.import_task.max_distance_for_commercial"), :value => 0 } %> <%= form.input :ignore_last_word , :as => :boolean , :input_html => { :title => t("formtastic.titles.import_task.ignore_last_word"), :value => false }%> <%= form.input :ignore_end_chars , :as => :number , :input_html => { :title => t("formtastic.titles.import_task.ignore_end_chars"), :value => 0 }%> -<%= form.input :max_distance_for_connection_link , :as => :number , :input_html => { :title => t("formtastic.titles.import_task.max_distance_for_connection_link"), :value => 100 }%> +<%= form.input :max_distance_for_connection_link , :as => :number , :input_html => { :title => t("formtastic.titles.import_task.max_distance_for_connection_link"), :value => 0 }%> diff --git a/app/views/import_tasks/new.html.erb b/app/views/import_tasks/new.html.erb index 13888ad39..65daee0ca 100644 --- a/app/views/import_tasks/new.html.erb +++ b/app/views/import_tasks/new.html.erb @@ -2,7 +2,7 @@ <%= semantic_form_for([@referential, @import_task], :as => :import_task, :url => new_referential_import_task_path(@referential), :method => :get) do |form| %> <%= form.inputs do %> - <%= form.input :format, :as => :radio, :collection => ImportTask.formats, :required => true, :include_blank => false %> + <%= form.input :format, :as => :radio, :collection => ImportTask.formats.map { |format| [ ImportTask.format_label(format), format]}, :required => true, :include_blank => false %> <% end %> <% end %> @@ -19,6 +19,12 @@ <%= form.input :rule_parameter_set_id, :as => :select, :collection => @referential.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => true %> <%= form.input :resources, :as => :file %> + + <% unless import_task.references_types.empty? %> + <p class="warning"><%= t('.'+import_partial_name(form)+'.warning')%></p> + <%= form.input :references_type, :as => :select, :collection => import_task.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> + <% end %> + <% end %> <%= form.actions do %> diff --git a/app/views/referentials/index.html.erb b/app/views/referentials/index.html.erb index 220fc17ba..cf4eaa245 100644 --- a/app/views/referentials/index.html.erb +++ b/app/views/referentials/index.html.erb @@ -1,4 +1,4 @@ -<%= title_tag Referential.model_name.human.pluralize %> +<%= title_tag Referential.model_name.human(:count => 2) %> <div class="referentials paginated_content"> <%= paginated_content @referentials %> diff --git a/app/views/routes/show.html.erb b/app/views/routes/show.html.erb index 5621f7a36..b935a6f34 100644 --- a/app/views/routes/show.html.erb +++ b/app/views/routes/show.html.erb @@ -97,6 +97,7 @@ <li><%= link_to t('journey_patterns.actions.new'), new_referential_line_route_journey_pattern_path(@referential, @line, @route), :class => "add" %></li> <% end %> <li><%= link_to t('vehicle_journey_imports.new.title'), new_referential_line_route_vehicle_journey_import_path( @referential, @line, @route ), :class => "import" %></li> + <li><%= link_to image_tag("icons/file_csv.png") + t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, :format => :zip), :class => "with_fa" %></li> <% if @route.journey_patterns.size > 0 %> <li> <i class="fa fa-clock-o fa-fw"></i><%= link_to t('vehicle_journeys.actions.index'), [@referential, @line, @route, :vehicle_journeys], :class => "with_fa" %> diff --git a/app/views/rule_parameter_sets/show.html.erb b/app/views/rule_parameter_sets/show.html.erb index f2427e36e..f4ca5e912 100644 --- a/app/views/rule_parameter_sets/show.html.erb +++ b/app/views/rule_parameter_sets/show.html.erb @@ -97,13 +97,12 @@ <% content_for :sidebar do %> <ul class="actions"> + <li><%= link_to t('rule_parameter_sets.actions.new'), new_referential_rule_parameter_set_path(@referential), :class => "add" %></li> <% if @rule_parameter_set.persisted? %> - <li><%= link_to t('rule_parameter_sets.actions.index'), referential_rule_parameter_sets_path(@referential), :class => "link" %></li> <li><%= link_to t('rule_parameter_sets.actions.edit'), edit_referential_rule_parameter_set_path(@referential, @rule_parameter_set), :class => "edit" %></li> <% if @referential.rule_parameter_sets.size > 1 %> <li><%= link_to t('rule_parameter_sets.actions.destroy'), referential_rule_parameter_set_path(@referential, @rule_parameter_set), :method => :delete, :data => {:confirm => t('rule_parameter_sets.actions.destroy_confirm')}, :class => "remove" %></li> <% end %> - <li><%= link_to t('rule_parameter_sets.actions.new'), new_referential_rule_parameter_set_path(@referential), :class => "add" %></li> <% end %> </ul> <% end %> diff --git a/app/views/stop_area_exports/index.xls.erb b/app/views/stop_area_exports/index.xls.erb deleted file mode 100644 index e48a97fe0..000000000 --- a/app/views/stop_area_exports/index.xls.erb +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0"?> -<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" - xmlns:o="urn:schemas-microsoft-com:office:office" - xmlns:x="urn:schemas-microsoft-com:office:excel" - xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" - xmlns:html="http://www.w3.org/TR/REC-html40"> - <Worksheet ss:Name="Sheet1"> - <Table> - <Row> - <% @column_names.each do |column_name|%> - <Cell><Data ss:Type="String"><%= column_name %></Data></Cell> - <% end %> - </Row> - <% @stop_areas.each do |stop_area| %> - <Row> - <Cell><Data ss:Type="Number"><%= stop_area.id %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.name %></Data></Cell> - <Cell><Data ss:Type="Number"><%= stop_area.longitude %></Data></Cell> - <Cell><Data ss:Type="Number"><%= stop_area.latitude %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.area_type %></Data></Cell> - <Cell><Data ss:Type="Number"><%= stop_area.parent_id %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.comment %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.country_code %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.street_name %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.mobility_restricted_suitability %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.stairs_availability %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.lift_availability %></Data></Cell> - <Cell><Data ss:Type="String"><%= stop_area.int_user_needs %></Data></Cell> - </Row> - <% end %> - </Table> - </Worksheet> -</Workbook> diff --git a/app/views/stop_area_imports/new.html.erb b/app/views/stop_area_imports/new.html.erb deleted file mode 100644 index d94f1c08b..000000000 --- a/app/views/stop_area_imports/new.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -<%= title_tag t('stop_area_imports.new.title') %> - -<%= semantic_form_for [@referential, @stop_area_import] do |form| %> - <br> - <%= form.inputs do %> - <%= form.input :file, :as => :file, :input_html => { :title => "#{t('.tooltip.file')}", :'data-placement' => "right", :'data-toggle' => "tooltip", :'data-trigger' =>"hover" } %> - <% end %> - <%= form.actions do %> - <%= form.action :submit, :as => :button , :label => t( 'formtastic.import' ) %> - <%= form.action :cancel, :as => :link %> - <% end %> -<% end %> diff --git a/app/views/stop_areas/_form.html.erb b/app/views/stop_areas/_form.html.erb index 4a1ba1c97..5a612614b 100644 --- a/app/views/stop_areas/_form.html.erb +++ b/app/views/stop_areas/_form.html.erb @@ -1,54 +1,52 @@ <%= semantic_form_for [@referential, @stop_area] do |form| %> <div class="row"> - <div class="col-md-6"> + <div class="col-md-6"> <%= form.inputs do %> <%= form.input :id, :as => :hidden %> <%= form.input :name %> <%= form.input :stop_area_type, :as => :select, :input_html => { :disabled => !@stop_area.new_record? }, :collection => Chouette::StopArea.stop_area_types, :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } %> <div class="location_info"> <h3><%= t("stop_areas.stop_area.localisation") %></h3> - <% if @stop_area.new_record? %> <div id="prefetch"> <label><%= t('.geolocalize') %></label> - <input class="typeahead form-control input-lg" maxlength="255" type="text" placeholder="<%= t('.address') %>" /> + <input class="typeahead form-control input-lg" maxlength="255" type="text" placeholder="<%= t('.address') %>" /> </div> - <% end %> <% unless @referential.projection_type_label.empty? %> - <%= form.input :projection_xy, :label => t("projection_xy", :projection => @referential.projection_type_label), :input_html => { :title => t("formtastic.titles.stop_area.projection_xy")} %> + <%= form.input :projection_xy, :label => t("projection_xy", :projection => @referential.projection_type_label), :input_html => { :title => t("formtastic.titles.stop_area.projection_xy")} %> <% end %> <%= form.input :coordinates, :input_html => { :title => t("formtastic.titles.stop_area.coordinates")} %> - <%= form.input :street_name %> - <%= form.input :country_code %> - <%= form.input :zip_code %> + <%= form.input :street_name %> + <%= form.input :country_code %> + <%= form.input :zip_code %> <%= form.input :city_name %> - <% end %> + <% end %> </div> <div class="col-md-6"> <% if !manage_itl && @map %> - <%= @map.to_html %> + <%= @map.to_html %> <% end %> </div> </div> <div class="stop_areas.stop_area.general_info"> - <h3><%= t("stop_area.general") %></h3> + <h3><%= t("stop_area.general") %></h3> <%= form.inputs do %> - <%= form.input :objectid, :required => !@stop_area.new_record?, :input_html => { :title => t("formtastic.titles.stop_area.objectid")} %> - <%= form.input :registration_number, :input_html => { :title => t("formtastic.titles.stop_area.registration_number")} %> - <%= form.input :fare_code, :as => :number %> - <%= form.input :nearest_topic_name %> + <%= form.input :objectid, :required => !@stop_area.new_record?, :input_html => { :title => t("formtastic.titles.stop_area.objectid")} %> + <%= form.input :registration_number, :input_html => { :title => t("formtastic.titles.stop_area.registration_number")} %> + <%= form.input :fare_code, :as => :number %> + <%= form.input :nearest_topic_name %> <%= form.input :comment, :as => :text, :input_html => { :rows => 5 } %> <% end %> - </div> + </div> <div class="pmr_info"> - <h3><%= t("stop_areas.stop_area.accessibility") %></h3> + <h3><%= t("stop_areas.stop_area.accessibility") %></h3> <%= form.inputs do %> <% if !manage_itl %> <%= form.input :mobility_restricted_suitability,:as => :boolean %> <%= form.input :stairs_availability,:as => :boolean %> - <%= form.input :lift_availability,:as => :boolean %> - <% end %> + <%= form.input :lift_availability,:as => :boolean %> + <% end %> <% end %> - </div> + </div> <%= form.actions do %> <%= form.action :submit, :as => :button %> @@ -57,77 +55,92 @@ <% end %> <script> - var address_display = function( address ) { - var name = ""; - if ( address.house_number) { - name += address.house_number+" "; - } - name += address.road+", "; - if ( address.postalcode) { - name += address.postalcode+" "; - } - if ( address.city) { - name += address.city; - } else if ( address.county ) { - name += address.county; - } else if ( address.country ) { - name += address.country; - } + $(document).ready(function() { + var address_display = function( address ) { + var name = ""; + if ( address.house_number) { + name += address.house_number+" "; + } + name += address.road+", "; + if ( address.suburb) { + name += address.suburb+", "; + } + if ( address.postcode) { + name += address.postcode+" "; + } + if ( address.city) { + name += address.city; + } else if ( address.county ) { + name += address.county; + } else if ( address.country ) { + name += address.country; + } - return name; - }; - var filtering = function(list) { - var selection = $.grep( list, function(item) { - return (item.type == "house" || item.type == "residential") && item.address.road ; - }); - return $.map( selection, function( d) { - return { postcode: d.address.postcode, - road: d.address.road, - lon: d.lon, lat: d.lat, - city: d.address.city, - postcode: d.address.postcode, - the_key: address_display( d.address)}; - }); - }; + return name; + }; + var filtering = function(list) { + // update map view + removeAddress(); - var addressesEngine = new Bloodhound({ - datumTokenizer: function(d) { - return Bloodhound.tokenizers.whitespace(d.id+" : "+d.road); - }, - queryTokenizer: function(d) { - return Bloodhound.tokenizers.whitespace(d.id+" :: "+d.road); - }, - limit: 10, - remote: { - url: 'http://nominatim.openstreetmap.org/search?q=%QUERY&format=json&addressdetails=1', - filter: filtering, - } - }); + var selection = $.grep( list, function(item) { + return (item.type == "house" || item.type == "residential" || + item.type == "tertiary" || item.type == "primary" || + item.type == "secondary") && item.address.road ; + }); + return $.map( selection, function( d) { + return { postcode: d.address.postcode, + road: d.address.road, + lon: d.lon, lat: d.lat, + suburb: d.address.suburb, + city: d.address.city, + postcode: d.address.postcode, + the_key: address_display( d.address)}; + }); + }; + + var addressesEngine = new Bloodhound({ + datumTokenizer: function(d) { + return Bloodhound.tokenizers.whitespace(d.id+" : "+d.road); + }, + queryTokenizer: function(d) { + return Bloodhound.tokenizers.whitespace(d.id+" :: "+d.road); + }, + limit: 10, + remote: { + url: 'http://nominatim.openstreetmap.org/search?q=%QUERY&format=json&addressdetails=1&bounded=1&viewbox='+ + '<%= @referential.viewbox_left_top_right_bottom %>', + filter: filtering, + } + }); - // kicks off the loading/processing of `local` and `prefetch` - var promise = addressesEngine.initialize(); + // kicks off the loading/processing of `local` and `prefetch` + var promise = addressesEngine.initialize(); - // passing in `null` for the `options` arguments will result in the default - // options being used - $('#prefetch .typeahead').typeahead( - { - hint: true, - highlight: true, - minLength: 1 - }, - { - name: 'addresses', - displayKey: 'the_key', - source: addressesEngine.ttAdapter(), - } - ); + // passing in `null` for the `options` arguments will result in the default + // options being used + $('#prefetch .typeahead').typeahead( + { + hint: true, + highlight: true, + minLength: 1 + }, + { + name: 'addresses', + displayKey: 'the_key', + source: addressesEngine.ttAdapter(), + } + ); - $('.typeahead').on('typeahead:selected', function($e, datum) { - $('input[name="stop_area[coordinates]"]').val(datum.lat+","+datum.lon); - $('input[name="stop_area[coordinates]"]').change(); - $('input[name="stop_area[street_name]"]').val(datum.road); - $('input[name="stop_area[zip_code]"]').val(datum.postcode); - $('input[name="stop_area[city_name]"]').val(datum.city); - }) + $('.typeahead').on('typeahead:selected', function($e, datum) { + // update map view + addAddress( datum.lon, datum.lat, datum.road); + // update form fields + <% if @stop_area.new_record? %> + $('input[name="stop_area[street_name]"]').val(datum.road); + $('input[name="stop_area[zip_code]"]').val(datum.postcode); + $('input[name="stop_area[city_name]"]').val(datum.city); + <% end %> + }) + }); </script> diff --git a/app/views/stop_areas/index.html.erb b/app/views/stop_areas/index.html.erb index 3398b8ab7..915e4523a 100644 --- a/app/views/stop_areas/index.html.erb +++ b/app/views/stop_areas/index.html.erb @@ -33,18 +33,6 @@ <ul class="actions"> <li><%= link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), :class => "add" %></li> <li><%= link_to t('stop_areas.actions.default_geometry'), default_geometry_referential_stop_areas_path(@referential), :method => :put, :class => "calculator_edit" %></li> - <li> - <%= link_to t('stop_area_imports.new.title'), new_referential_stop_area_import_path( @referential ), :class => "import" %> - </li> </ul> - <div class="btn-group"> - <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> - <%= t('stop_area_imports.new.export_stop_areas') %><span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - <li><%= link_to image_tag("icons/file_csv.png") + " Csv" , referential_stop_area_exports_path(@referential, :format => :csv) %></li> - <li><%= link_to image_tag("icons/file_excel.png") + " Excel", referential_stop_area_exports_path(@referential, :format => :xls) %></li> - </ul> - </div> <% end %> diff --git a/app/views/vehicle_journeys/index.html.erb b/app/views/vehicle_journeys/index.html.erb index 74cd73d29..212c06bbf 100644 --- a/app/views/vehicle_journeys/index.html.erb +++ b/app/views/vehicle_journeys/index.html.erb @@ -56,16 +56,19 @@ <li><%= link_to t('vehicle_journeys.actions.new'), new_referential_line_route_vehicle_journey_path(@referential, @line, @route), :class => "add" %></li> <li><%= link_to t('.timeless'), timeless_referential_line_route_vehicle_journeys_path(@referential, @line, @route), :class => "link" %></li> <li><%= link_to t('vehicle_journey_imports.new.title'), new_referential_line_route_vehicle_journey_import_path( @referential, @line, @route ), :class => "import" %></li> + <li><%= link_to image_tag("icons/file_csv.png") + t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, :format => :zip), :class => "with_fa" %></li> </ul> + <!-- <div class="btn-group"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> - <%= t('vehicle_journey_imports.new.export_vehicle_journeys') %><span class="caret"></span> + <%= t('vehicle_journey_exports.new.title') %><span class="caret"></span> </button> <ul class="dropdown-menu" role="menu"> <li><%= link_to image_tag("icons/file_csv.png") + " Csv" , referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, :format => :csv) %></li> <li><%= link_to image_tag("icons/file_excel.png") + " Excel", referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, :format => :xls) %></li> </ul> </div> + --> <h4><%= t(".selection") %></h4> <h5><%= Chouette::JourneyPattern.model_name.human.pluralize %></h5> diff --git a/app/views/vehicle_journeys/show.html.erb b/app/views/vehicle_journeys/show.html.erb index 1bd1c5ca7..c7ab1e073 100644 --- a/app/views/vehicle_journeys/show.html.erb +++ b/app/views/vehicle_journeys/show.html.erb @@ -115,4 +115,5 @@ <li><font color="#D98F3B"><i class="fa fa-cubes fa-fw"></i></font><%= link_to t('.translation_form'), new_referential_line_route_vehicle_journey_vehicle_translation_path(@referential, @line, @route, @vehicle_journey), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal_translation', :class => "with_fa" } %></li> <% end %> </ul> + <%= creation_tag(@vehicle_journey) %> <% end %> diff --git a/config/locales/exchange.yml b/config/locales/exchange.yml new file mode 100644 index 000000000..882e1feb0 --- /dev/null +++ b/config/locales/exchange.yml @@ -0,0 +1,18 @@ +en: + exchange: + format: + neptune: "Neptune (French normalized format based on European Trident Standard)" + gtfs: "GTFS (General Transit Feed Specification)" + csv: "CSV (Chouette format)" + netex: "NeTEx (experimental Neptune local agreement for Network Exchange CEN standard)" + hub: "HUB (Specific Cityway Format)" + kml: "KML (line and route drawings on Keyhole Markup Language format)" +fr: + exchange: + format: + neptune: "Neptune (Format normalisé français basé sur le standard européen Trident)" + gtfs: "GTFS (General Transit Feed Specification définit par Google)" + csv: "CSV (format spéficique à Chouette)" + netex: "NeTEx (Profil expérimental de Neptune sur le standard européen 'Network Exchange' )" + hub: "HUB (format spécifique Cityway)" + kml: "KML (tracés de lignes et de séquences d'arrêts en 'Keyhole Markup Language')" diff --git a/config/locales/exports.yml b/config/locales/exports.yml index 9f7e59e43..75002cc22 100644 --- a/config/locales/exports.yml +++ b/config/locales/exports.yml @@ -10,6 +10,8 @@ en: all: "All" flash: "Export task on queue, refresh page to see progression" flash2: "On success, a link for download will be displayed" + fields_gtfs_export: + warning: "Stop areas choice provide only stops and transfers gtfs files, with extra data" index: title: "Exports" warning: "" @@ -123,13 +125,15 @@ fr: all: "Toutes" flash: "La demande d'export est mise en file d'attente, veuillez rafraichir régulièrement la page pour le suivre" flash2: "Une fois l'export terminé, un lien sera disponible pour télécharger le résultat" + fields_gtfs_export: + warning: "Le filtre sur arrêts produit uniquement les fichiers GTFS stops et transfers gtfs, ceux-ci contenant alors des attributs supplémentaires" index: title: "Exports" warning: "" show: report: "Rapport" statuses: - pending: "En attente ou en cours ..." + pending: "En attente ..." processing: "En cours ..." completed: "Achevé" failed: "Echoué" diff --git a/config/locales/import_tasks.yml b/config/locales/import_tasks.yml index f76e56d64..a4f9ba2a5 100644 --- a/config/locales/import_tasks.yml +++ b/config/locales/import_tasks.yml @@ -6,7 +6,10 @@ en: destroy_confirm: "Are you sure you want destroy this import?" new: title: "New import" + all: "All" flash: "Import task on queue, refresh page to see progression" + fields_gtfs_import: + warning: "Filter on stop areas import only GTFS stops and transfers files, these may contain extra attributes" index: title: "Imports" warning: "" @@ -76,6 +79,7 @@ en: resources: "File to import" created_at: "Created on" status: "Status" + references_type: "subset" no_save: "No save" rule_parameter_set_id: "Rule parameter set for compliance check" object_id_prefix: "Neptune Id prefix" @@ -98,7 +102,10 @@ fr: destroy_confirm: "Etes vous sûr de supprimer cet import ?" new: title: "Nouvel import" + all: "Tout" flash: "La demande d'import est mise en file d'attente, veuillez rafraichir régulièrement la page pour le suivre" + fields_gtfs_import: + warning: "Le filtre sur arrêts importe uniquement les fichiers GTFS stops et transfers gtfs, ceux-ci pouvant contenir des attributs supplémentaires" index: title: "Imports" warning: "" @@ -183,6 +190,7 @@ fr: created_at: "Créé le" status: "Status" no_save: "Pas de sauvegarde" + references_type: "Sous ensemble" rule_parameter_set_id: "Jeu de paramètres pour validation" object_id_prefix: "Préfixe d'identifiants" max_distance_for_commercial: "Distance max pour créer les zones" diff --git a/config/locales/layouts.yml b/config/locales/layouts.yml index 342e052b8..d1b479254 100644 --- a/config/locales/layouts.yml +++ b/config/locales/layouts.yml @@ -7,8 +7,8 @@ en: profile: "My Profile" sign_out: "Sign out" navbar: - return_to_referentials: "Return to referentials" - select_referential: "Select referential" + return_to_referentials: "Return to data spaces" + select_referential: "Select data space" select_referential_datas: "Select datas" return_to_dashboard: "Return to Dashboard" referential_datas: "Datas" @@ -49,8 +49,8 @@ fr: profile: "Mon Profil" sign_out: "Déconnexion" navbar: - return_to_referentials: "Retour à la liste des référentiels" - select_referential: "Sélection du référentiel" + return_to_referentials: "Retour à la liste des espaces de données" + select_referential: "Sélection de l'espace de données" select_referential_datas: "Sélection des données" return_to_dashboard: "Retour au Tableau de Bord" referential_datas: "Données" diff --git a/config/locales/referentials.yml b/config/locales/referentials.yml index 8353c1e9e..0d3a63498 100644 --- a/config/locales/referentials.yml +++ b/config/locales/referentials.yml @@ -65,6 +65,7 @@ en: import_tasks: "Imports" export_tasks: "Exports" compliance_check_tasks: "Validations" + rule_parameter_sets: "Rule parameters sets" formtastic: titles: referential: @@ -140,6 +141,7 @@ fr: import_tasks: "Imports" export_tasks: "Exports" compliance_check_tasks: "Validations" + rule_parameter_sets: "Jeux de paramètres" formtastic: titles: referential: diff --git a/config/locales/stop_area_imports.yml b/config/locales/stop_area_imports.yml deleted file mode 100644 index 94d09975e..000000000 --- a/config/locales/stop_area_imports.yml +++ /dev/null @@ -1,33 +0,0 @@ -en: - stop_area_imports: - new: - title: "Import stop areas" - export_stop_areas: "Export existing stop_areas" - success: "Import is a success" - tooltip: - file: "Select a CSV or Excel file" - errors: - import_aborted: "Errors prohibited this import from completing: " - invalid_stop_area: "Error column %{column}, stop_area is invalid : %{message}" - exception: "Invalid file, you must provide valid csv, xls or xlsx file" - activemodel: - attributes: - stop_area_import: - file: "File" -fr: - stop_area_imports: - new: - title: "Import des arrêts" - export_stop_areas: "Exporter les arrêts existants" - success: "L'import des données est un succès" - tooltip: - file: "Sélectionner un fichier CSV ou Excel" - errors: - import_aborted: "Des erreurs ont empéché le bon déroulement de l'import: " - invalid_stop_area: "Erreur colonne %{column}, l'arrêt est invalide : %{message}" - exception: "Le fichier est invalide, vous devez fournir un fichier csv, xls ou xlsx valide" - activemodel: - attributes: - stop_area_import: - file: "Fichier" -
\ No newline at end of file diff --git a/config/locales/vehicle_journey_exports.yml b/config/locales/vehicle_journey_exports.yml new file mode 100644 index 000000000..bcfc04e9a --- /dev/null +++ b/config/locales/vehicle_journey_exports.yml @@ -0,0 +1,52 @@ +en: + vehicle_journey_exports: + new: + title: "Export existing vehicle journey at stops" + basename: "vehicle_journeys" + label: + vehicle_journey_id: "vj id (empty for new vj)" + number: "number" + time_table_ids: "timetables" + flexible_service: "on demand (Y(es)|N(o)|empty for unknown)" + vehicle_identifier: "vehicle identifier" + mobility: "wheel_chairs (Y(es)|N(o)|empty for unknown)" + stop_id: "stop id" + stop_name: "stop name" + b_true: "Yes" + b_false: "No" + tt_columns: "code;name;tags;start;end;day types;periods;peculiar days;excluded days" + monday: "Mo" + tuesday: "Tu" + wednesday: "We" + thursday: "Th" + friday: "Fr" + saturday: "Sa" + sunday: "Su" + vj_filename: "vehicle_journeys_" + tt_filename: "time_tables" +fr: + vehicle_journey_exports: + new: + title: "Exporter les horaires existants" + basename: "courses" + label: + vehicle_journey_id: "id course (vide si nouvelle)" + number: "numéro" + time_table_ids: "calendriers" + flexible_service: "TAD (O(ui)|N(on)|vide si inconnu)" + vehicle_identifier: "identifiant véhicule" + mobility: "PMR (O(ui)|N(on)|vide si inconnu)" + stop_id: "id arrêt" + stop_name: "nom arrêt" + b_true: "Oui" + b_false: "Non" + tt_columns: "code;nom;étiquettes;début;fin;types de jour;périodes;jours particuliers;jours exclus" + monday: "Lu" + tuesday: "Ma" + wednesday: "Me" + thursday: "Je" + friday: "Ve" + saturday: "Sa" + sunday: "Di" + vj_filename: "courses_" + tt_filename: "calendriers" diff --git a/config/locales/vehicle_journey_imports.yml b/config/locales/vehicle_journey_imports.yml index e3f3f6855..fd442d5eb 100644 --- a/config/locales/vehicle_journey_imports.yml +++ b/config/locales/vehicle_journey_imports.yml @@ -9,9 +9,15 @@ en: errors: import_aborted: "Errors prohibited this import from completing: " not_same_stop_points: "Error column 1 : Not same stop points than in route %{route}" + one_stop_point_used: "Error column %{column} : only one stop scheduled" invalid_vehicle_journey_at_stop: "Error column %{column} line %{line} : vehicle journey at stop invalid %{time}" invalid_vehicle_journey: "Error column %{column}, vehicle journey is invalid : %{message}" exception: "Invalid file, you must provide valid csv, xls or xlsx file" + success: + created_jp_count: "%{count} journey patterns created" + created_vj_count: "%{count} vehicle journeys created" + updated_vj_count: "%{count} vehicle journeys updated" + deleted_vj_count: "%{count} vehicle journeys deleted" activemodel: attributes: vehicle_journey_import: @@ -27,9 +33,15 @@ fr: errors: import_aborted: "Des erreurs ont empéché le bon déroulement de l'import: " not_same_stop_points: "Erreur colonne 1 : Pas les mêmes points d'arrêt que sur l'itinéraire %{route}" + one_stop_point_used: "Erreur colonne %{column} : un seul arrêt desservi" invalid_vehicle_journey_at_stop: "Erreur colonne %{column} ligne %{line} : horaire à l'arrêt invalide %{time}" invalid_vehicle_journey: "Erreur colonne %{column}, la course est invalide : %{message}" exception: "Le fichier est invalide, vous devez fournir un fichier csv, xls ou xlsx valide" + success: + created_jp_count: "%{count} mission(s) ajoutée(s)" + created_vj_count: "%{count} course(s) ajoutée(s)" + updated_vj_count: "%{count} course(s) mise(s) à jour" + deleted_vj_count: "%{count} course(s) supprimée(s)" activemodel: attributes: vehicle_journey_import: diff --git a/config/routes.rb b/config/routes.rb index 86f59a516..442538868 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,8 +37,6 @@ ChouetteIhm::Application.routes.draw do end resources :referentials do - resources :stop_area_imports - resources :stop_area_exports resources :api_keys resources :rule_parameter_sets resources :stop_point_areas diff --git a/spec/exporters/chouette/kml/exporter_spec.rb b/spec/exporters/chouette/kml/exporter_spec.rb index 2135c0b91..a996b0746 100644 --- a/spec/exporters/chouette/kml/exporter_spec.rb +++ b/spec/exporters/chouette/kml/exporter_spec.rb @@ -28,25 +28,25 @@ describe Chouette::Kml::Exporter do it "should return a zip file with nothing inside with no objects in arguments" do subject.export(zip_file_path, {:export_id => 1, :o => "line"} ) File.exists?(zip_file_path).should be_true - ::Zip::ZipFile.open(zip_file_path).size.should == 6 + ::Zip::File.open(zip_file_path).size.should == 6 end it "should return a zip file with 4 kml files" do subject.export(zip_file_path, {:export_id => 1, :o => "line", :id => "#{line.id}" } ) File.exists?(zip_file_path).should be_true - ::Zip::ZipFile.open(zip_file_path).size.should == 4 + ::Zip::File.open(zip_file_path).size.should == 4 end it "should return a zip file with 6 kml files" do subject.export(zip_file_path, {:export_id => 1, :o => "line", :id => "#{line.id},#{line2.id}" } ) File.exists?(zip_file_path).should be_true - ::Zip::ZipFile.open(zip_file_path).size.should == 6 + ::Zip::File.open(zip_file_path).size.should == 6 end it "should return a zip file with 6 kml files" do subject.export(zip_file_path, {:export_id => 1, :o => "", :id => "" } ) File.exists?(zip_file_path).should be_true - ::Zip::ZipFile.open(zip_file_path).size.should == 6 + ::Zip::File.open(zip_file_path).size.should == 6 end end diff --git a/spec/fixtures/stop_area_import_invalid.csv b/spec/fixtures/stop_area_import_invalid.csv deleted file mode 100644 index 379c33012..000000000 --- a/spec/fixtures/stop_area_import_invalid.csv +++ /dev/null @@ -1,7 +0,0 @@ -"id","name","longitude","latitude","area_type","parent_id","comment","country_code","street_name","mobility_restricted_suitability","stairs_availability","lift_availability","int_user_needs" -,"StopArea1","0.1","0.1",,,"Comment",,,,,, -,"StopArea2","0.2","0.2",,,"Comment",,,,,, -,"StopArea3","0.3","0.3",,,"Comment",,,,,, -,"StopArea4","0.4","0.4",,,"Comment",,,,,, -,"StopArea5","0.5","0.5",,,"Comment",,,,,, -,"StopArea6","0.6","0.6",,,"Comment",,,,,, diff --git a/spec/fixtures/stop_area_import_valid.csv b/spec/fixtures/stop_area_import_valid.csv deleted file mode 100644 index d3d2c6974..000000000 --- a/spec/fixtures/stop_area_import_valid.csv +++ /dev/null @@ -1,7 +0,0 @@ -"id","name","longitude","latitude","area_type","parent_id","comment","country_code","street_name","mobility_restricted_suitability","stairs_availability","lift_availability","int_user_needs" -,"StopArea1","0.1","0.1","Quay",,"Comment",,,,,, -,"StopArea2","0.2","0.2","Quay",,"Comment",,,,,, -,"StopArea3","0.3","0.3","Quay",,"Comment",,,,,, -,"StopArea4","0.4","0.4","Quay",,"Comment",,,,,, -,"StopArea5","0.5","0.5","Quay",,"Comment",,,,,, -,"StopArea6","0.6","0.6","Quay",,"Comment",,,,,, diff --git a/spec/fixtures/vehicle_journey_imports_valid.csv b/spec/fixtures/vehicle_journey_imports_valid.csv index b20d58ab5..13b59b102 100644 --- a/spec/fixtures/vehicle_journey_imports_valid.csv +++ b/spec/fixtures/vehicle_journey_imports_valid.csv @@ -1,6 +1,12 @@ -"stop area id","stop area name","import:VehicleJourney:1","import:VehicleJourney:2","import:VehicleJourney:3","" -1,"Arrêt 1","9:00:00",,"11:10:00","12:10:00" -2,"Arrêt 2","9:05:00","10:05:00","11:15:00","12:15:00" -3,"Arrêt 3","9:10:00",,"11:20:00","12:20:00" -4,"Arrêt 4","9:15:00","10:20:00","11:25:00","12:25:00" -5,"Arrêt 5","9:20:00",,"11:30:00","12:30:00" +;id course;import:VehicleJourney:1;import:VehicleJourney:2;import:VehicleJourney:3; +;numéro;1;2;3;4 +;identifiant véhicule;11;12;13;14 +;PMR (O(ui)|N(on)|vide si inconnu);Oui;;; +;TAD (O(ui)|N(on)|vide si inconnu);Oui;;; +;calendriers;;;; +id arrêt;nom arrêt;;;; +1;Arrêt 1;9:00:00;;11:10:00;12:10:00 +2;Arrêt 2;9:05:00;10:05:00;11:15:00;12:15:00 +3;Arrêt 3;9:10:00;;11:20:00;12:20:00 +4;Arrêt 4;9:15:00;10:20:00;11:25:00;12:25:00 +5;Arrêt 5;9:20:00;;11:30:00;12:30:00 diff --git a/spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv b/spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv index 1b7aeb731..34fbbb6bb 100644 --- a/spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv +++ b/spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv @@ -1,6 +1,12 @@ -"stop area id","stop area name",invalid vj,"import:VehicleJourney:2","import:VehicleJourney:3" -1,"Arrêt 1","9:00:00","10:05:00","11:10:00" -2,"Arrêt 2","11:05:00",,"11:15:00" -3,"Arrêt 3","11:10:00","10:20:00","11:20:00" -4,"Arrêt 4","11:15:00",,"11:25:00" -5,"Arrêt 5","9:20:00","10:30:00","11:30:00" +;id course;9999;import:VehicleJourney:2;import:VehicleJourney:3 +;numéro;1;2;3 +;identifiant véhicule;11;12;13 +;PMR (O(ui)|N(on)|vide si inconnu);Oui;; +;TAD (O(ui)|N(on)|vide si inconnu);Oui;; +;calendriers;;; +id arrêt;nom arrêt;;; +1;Arrêt 1;9:00:00;10:05:00;11:10:00 +2;Arrêt 2;11:05:00;;11:15:00 +3;Arrêt 3;11:10:00;10:20:00;11:20:00 +4;Arrêt 4;11:15:00;;11:25:00 +5;Arrêt 5;9:20:00;10:30:00;11:30:00 diff --git a/spec/fixtures/vehicle_journey_imports_with_vjas_bad_order.csv b/spec/fixtures/vehicle_journey_imports_with_vjas_bad_order.csv index 4096616ab..6dc20cfeb 100644 --- a/spec/fixtures/vehicle_journey_imports_with_vjas_bad_order.csv +++ b/spec/fixtures/vehicle_journey_imports_with_vjas_bad_order.csv @@ -1,6 +1,12 @@ -"stop area id","stop area name","import:VehicleJourney:1","import:VehicleJourney:2","" -1,"Arrêt 1","9:05:00","10:05:00","11:10:00" -2,"Arrêt 2","11:05:00",,"11:15:00" -3,"Arrêt 3","9:10:00","10:20:00","11:20:00" -4,"Arrêt 4","9:15:00","10:25:00","11:25:00" -5,"Arrêt 5","9:20:00","10:30:00","11:30:00" +;id course;import:VehicleJourney:1;import:VehicleJourney:2; +;numéro;1;2;3 +;identifiant véhicule;11;12;13 +;PMR (O(ui)|N(on)|vide si inconnu);Oui;; +;TAD (O(ui)|N(on)|vide si inconnu);Oui;; +;calendriers;;; +id arrêt;nom arrêt;;; +1;Arrêt 1;9:05:00;10:05:00;11:10:00 +2;Arrêt 2;11:05:00;;11:15:00 +3;Arrêt 3;9:10:00;10:20:00;11:20:00 +4;Arrêt 4;9:15:00;10:25:00;11:25:00 +5;Arrêt 5;9:20:00;10:30:00;11:30:00 diff --git a/spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv b/spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv index c5e9e32b1..c7745849f 100644 --- a/spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv +++ b/spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv @@ -1,6 +1,12 @@ -"stop area id","stop area name","import:VehicleJourney:1","import:VehicleJourney:2","" -1,"Arrêt 1",invalid time,"10:05:00","11:10:00" -2,"Arrêt 2","9:05:00",,"11:15:00" -3,"Arrêt 3","9:10:00","10:20:00","11:20:00" -4,"Arrêt 4","9:15:00",,"11:25:00" -5,"Arrêt 5","9:20:00","10:30:00","11:30:00" +;id course;import:VehicleJourney:1;import:VehicleJourney:2; +;numéro;1;2;3 +;identifiant véhicule;11;12;13 +;PMR (O(ui)|N(on)|vide si inconnu);Oui;; +;TAD (O(ui)|N(on)|vide si inconnu);Oui;; +;calendriers;;;; +id arrêt;nom arrêt;;; +1;Arrêt 1;invalid time;10:05:00;11:10:00 +2;Arrêt 2;9:05:00;;11:15:00 +3;Arrêt 3;9:10:00;10:20:00;11:20:00 +4;Arrêt 4;9:15:00;;11:25:00 +5;Arrêt 5;9:20:00;10:30:00;11:30:00 diff --git a/spec/models/stop_area_import_spec.rb b/spec/models/stop_area_import_spec.rb deleted file mode 100644 index 07f3a111b..000000000 --- a/spec/models/stop_area_import_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -require 'spec_helper' - -describe StopAreaImport do - - let(:valid_file) { - csv_file = File.open(Rails.root.join("spec", "fixtures", "stop_area_import_valid.csv").to_s, "r") - mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) ) - } - - let(:invalid_file) { - csv_file = File.open(Rails.root.join("spec", "fixtures", "stop_area_import_invalid.csv").to_s, "r") - mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) ) - } - - subject { StopAreaImport.new(:file => valid_file) } - - describe ".save" do - - it "should validate presence of file" do - expect(StopAreaImport.new.save).to be_false - end - - it "should import stop areas and create the right number of objects" do - expect(StopAreaImport.new(:file => valid_file).save).to be_true - expect(Chouette::StopArea.all.size).to eq(6) - end - - it "should not import vehicle_journeys and not create objects when vehicle journey at stops are not in ascendant order" do - expect(StopAreaImport.new(:file => invalid_file).save).to be_false - expect(Chouette::StopArea.all.size).to eq(0) - end - - end - - describe ".load_imported_stop_areas" do - - # it "should return errors when stop_areas in file are invalid" do - # stop_area_import = StopAreaImport.new(:referential => referential, :file => invalid_file) - # expect { stop_area_import.load_imported_stop_areas }.to raise_exception - # end - - it "should load stop ateas" do - expect(subject.load_imported_stop_areas.size).to eq(6) - expect(subject.errors.messages).to eq({}) - end - - end - -end diff --git a/spec/models/vehicle_journey_export_spec.rb b/spec/models/vehicle_journey_export_spec.rb new file mode 100644 index 000000000..5ce3b9bfc --- /dev/null +++ b/spec/models/vehicle_journey_export_spec.rb @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +require 'spec_helper' + +describe VehicleJourneyExport do + + let!(:route) { create(:route) } + let!(:other_route) { create(:route) } + + let!(:journey_pattern) { create(:journey_pattern, :route => route) } + let!(:other_journey_pattern) { create(:journey_pattern_even, :route => route) } + + let!(:vehicle_journey1) { create(:vehicle_journey_common, :objectid => "export:VehicleJourney:1", :route_id => route.id, :journey_pattern_id => journey_pattern.id) } + let!(:vehicle_journey2) { create(:vehicle_journey_common, :objectid => "export:VehicleJourney:2", :route_id => route.id, :journey_pattern_id => other_journey_pattern.id) } + let!(:vehicle_journey3) { create(:vehicle_journey_common, :objectid => "export:VehicleJourney:3", :route_id => route.id, :journey_pattern_id => journey_pattern.id) } + + let!(:stop_point0) { route.stop_points[0] } + let!(:stop_point1) { route.stop_points[1] } + let!(:stop_point2) { route.stop_points[2] } + let!(:stop_point3) { route.stop_points[3] } + let!(:stop_point4) { route.stop_points[4] } + + let!(:time_table) { create(:time_table)} + + subject { VehicleJourneyExport.new(:vehicle_journeys => route.vehicle_journeys, :route => route) } + + describe ".tt_day_types" do + + it "should return no day_type" do + time_table.int_day_types = 0 + expect(subject.tt_day_types(time_table)).to eq("..............") + end + + it "should return all days" do + time_table.int_day_types = 4|8|16|32|64|128|256 + expect(subject.tt_day_types(time_table)).to eq("LuMaMeJeVeSaDi") + end + + end + + describe ".tt_periods" do + + it "should return empty period" do + time_table.periods.clear + expect(subject.tt_periods(time_table)).to eq("") + end + + it "should return periods" do + time_table.periods.clear + time_table.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,8)) + expect(subject.tt_periods(time_table)).to eq("[2014-08-01 -> 2014-08-08] ") + end + + end + + describe ".tt_included_days" do + + it "should return empty included dates" do + time_table.dates.clear + expect(subject.tt_peculiar_days(time_table)).to eq("") + end + + it "should return included date" do + time_table.dates.clear + time_table.dates << Chouette::TimeTableDate.new(:date => Date.new(2014,8,1), :in_out => true) + expect(subject.tt_peculiar_days(time_table)).to eq("2014-08-01 ") + end + + end + + describe ".tt_excluded_days" do + + it "should return empty excluded dates" do + time_table.dates.clear + expect(subject.tt_excluded_days(time_table)).to eq("") + end + + it "should return excluded date" do + time_table.dates.clear + time_table.dates << Chouette::TimeTableDate.new(:date => Date.new(2014,8,1), :in_out => false) + expect(subject.tt_excluded_days(time_table)).to eq("2014-08-01 ") + end + + end + +end diff --git a/spec/models/vehicle_journey_import_spec.rb b/spec/models/vehicle_journey_import_spec.rb index 07cd921bb..68f8669e0 100644 --- a/spec/models/vehicle_journey_import_spec.rb +++ b/spec/models/vehicle_journey_import_spec.rb @@ -4,13 +4,22 @@ require 'spec_helper' describe VehicleJourneyImport do def update_csv_file_with_factory_data(filename) - csv_file = CSV.open("/tmp/#{filename}", "wb") do |csv| + csv_file = CSV.open("/tmp/#{filename}", "wb",{ :col_sep => ";"}) do |csv| counter = 0 - CSV.foreach( Rails.root.join("spec", "fixtures", "#{filename}").to_s ) do |row| + CSV.foreach( Rails.root.join("spec", "fixtures", "#{filename}").to_s , {:col_sep => ";"}) do |row| if counter == 0 + row2 = [] + row.each do |cell| + cell = vehicle_journey1.id.to_s if cell == "import:VehicleJourney:1" + cell = vehicle_journey2.id.to_s if cell == "import:VehicleJourney:2" + cell = vehicle_journey3.id.to_s if cell == "import:VehicleJourney:3" + row2 << cell + end + csv << row2 + elsif counter < 7 csv << row else - csv << ( row[0] = route.stop_points[counter - 1].id; row) + csv << ( row[0] = route.stop_points[counter - 7].id; row) end counter += 1 end @@ -93,14 +102,14 @@ describe VehicleJourneyImport do describe ".find_journey_pattern_schedule" do it "should return journey pattern with same stop points" do - expect(subject.find_journey_pattern_schedule( { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => "9:10", stop_point3.id => "9:15", stop_point4.id => "9:20"} )).to eq(journey_pattern) - expect(subject.find_journey_pattern_schedule( { stop_point1.id => "9:00", stop_point3.id => "9:10" } )).to eq(other_journey_pattern) + expect(subject.find_journey_pattern_schedule( 1, { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => "9:10", stop_point3.id => "9:15", stop_point4.id => "9:20"} )).to eq(journey_pattern) + expect(subject.find_journey_pattern_schedule( 1, { stop_point1.id => "9:00", stop_point3.id => "9:10" } )).to eq(other_journey_pattern) end it "should return new journey_pattern if no journey pattern with same stop points is founded" do - expect(subject.find_journey_pattern_schedule( { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => nil, stop_point3.id => "9:15", stop_point4.id => "9:20"} )).to be_true - expect(subject.find_journey_pattern_schedule( { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => nil, stop_point3.id => "9:15", stop_point4.id => "9:20"} ).id).not_to eq(journey_pattern.id) - expect(subject.find_journey_pattern_schedule( { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => nil, stop_point3.id => "9:15", stop_point4.id => "9:20"} ).id).not_to eq(other_journey_pattern.id) + expect(subject.find_journey_pattern_schedule( 1, { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => nil, stop_point3.id => "9:15", stop_point4.id => "9:20"} )).to be_true + expect(subject.find_journey_pattern_schedule( 1, { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => nil, stop_point3.id => "9:15", stop_point4.id => "9:20"} ).id).not_to eq(journey_pattern.id) + expect(subject.find_journey_pattern_schedule( 1, { stop_point0.id => "9:00", stop_point1.id => "9:05", stop_point2.id => nil, stop_point3.id => "9:15", stop_point4.id => "9:20"} ).id).not_to eq(other_journey_pattern.id) end end diff --git a/spec/requests/referentials_spec.rb b/spec/requests/referentials_spec.rb index c57192d9b..975248375 100644 --- a/spec/requests/referentials_spec.rb +++ b/spec/requests/referentials_spec.rb @@ -8,7 +8,7 @@ describe "Referentials" do it "should support no referential" do visit referentials_path - page.should have_content("Espace de Données") + page.should have_content("Espaces de Données") end context "when several referentials exist" do diff --git a/spec/requests/stop_area_imports_spec.rb b/spec/requests/stop_area_imports_spec.rb deleted file mode 100644 index c0da1edac..000000000 --- a/spec/requests/stop_area_imports_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -require 'spec_helper' - -describe "StopAreaImports" do - login_user - - let!(:line) { create :line } - let!(:valid_file_path) { Rails.root + "spec/fixtures/stop_area_import_valid.csv" } - let!(:invalid_file_path) { Rails.root + "spec/fixtures/stop_area_import_invalid.csv" } - - describe "new" do - it "should create stop areas and return to stop areas index page" do - visit new_referential_stop_area_import_path(referential) - attach_file('Fichier', valid_file_path) - click_button "Lancer l'import" - expect(page).to have_content(I18n.t("stop_area_imports.new.success")) - expect(page).to have_content("StopArea1") - end - - it "should return error messages when file is invalid" do - visit new_referential_stop_area_import_path(referential) - attach_file('Fichier', invalid_file_path) - click_button "Lancer l'import" - expect(page).to have_content(I18n.t("stop_area_imports.errors.import_aborted")) - end - - it "should return error message when file missing on upload" do - visit new_referential_stop_area_import_path(referential) - click_button "Lancer l'import" - expect(page).to have_content(I18n.t("stop_area_imports.errors.import_aborted")) - end - end - -end diff --git a/spec/requests/vehicle_journey_imports_spec.rb b/spec/requests/vehicle_journey_imports_spec.rb index c7a772fd3..68fe04e0b 100644 --- a/spec/requests/vehicle_journey_imports_spec.rb +++ b/spec/requests/vehicle_journey_imports_spec.rb @@ -17,13 +17,22 @@ describe "VehicleJourneyImports" do } def update_csv_file_with_factory_data(filename) - csv_file = CSV.open("/tmp/#{filename}", "wb") do |csv| + csv_file = CSV.open("/tmp/#{filename}", "wb",{ :col_sep => ";"}) do |csv| counter = 0 - CSV.foreach( Rails.root.join("spec", "fixtures", "#{filename}").to_s ) do |row| + CSV.foreach( Rails.root.join("spec", "fixtures", "#{filename}").to_s , {:col_sep => ";"}) do |row| if counter == 0 + row2 = [] + row.each do |cell| + cell = "" if cell == "import:VehicleJourney:1" + cell = "" if cell == "import:VehicleJourney:2" + cell = "" if cell == "import:VehicleJourney:3" + row2 << cell + end + csv << row2 + elsif counter < 7 csv << row else - csv << ( row[0] = route.stop_points[counter - 1].id; row) + csv << ( row[0] = route.stop_points[counter - 7].id; row) end counter += 1 end @@ -34,7 +43,7 @@ describe "VehicleJourneyImports" do end describe "new" do - it "should create stop areas and return to stop areas index page" do + it "should create vehicle journey file and return to route show page" do visit new_referential_line_route_vehicle_journey_import_path(referential, route.line, route) attach_file('Fichier', valid_file_path) click_button "Lancer l'import" |
