aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.ruby-version2
-rw-r--r--.travis.yml4
-rw-r--r--CHANGELOG.md24
-rw-r--r--Gemfile41
-rw-r--r--Gemfile.lock150
-rw-r--r--README.md13
-rw-r--r--app/assets/images/cityway.pngbin0 -> 8809 bytes
-rw-r--r--app/assets/images/compliance_check_task-pending.pngbin1373 -> 1311 bytes
-rw-r--r--app/assets/images/export-pending.pngbin1373 -> 1311 bytes
-rw-r--r--app/assets/images/export-processing.pngbin0 -> 1373 bytes
-rw-r--r--app/assets/images/file-validation-completed.pngbin5658 -> 0 bytes
-rw-r--r--app/assets/images/file-validation-failed.pngbin6715 -> 0 bytes
-rw-r--r--app/assets/images/file-validation-pending.pngbin7767 -> 0 bytes
-rw-r--r--app/assets/images/import_task-pending.pngbin1373 -> 1311 bytes
-rw-r--r--app/assets/images/logo_chouette.pngbin5631 -> 2539 bytes
-rw-r--r--app/assets/images/welcome.jpgbin0 -> 161221 bytes
-rw-r--r--app/assets/javascripts/access_points.js.coffee62
-rw-r--r--app/assets/javascripts/application.js16
-rw-r--r--app/assets/javascripts/bootstrap.js.coffee3
-rw-r--r--app/assets/javascripts/compliance_check_tasks/index.js.coffee5
-rw-r--r--app/assets/javascripts/exports/index.js.coffee1
-rw-r--r--app/assets/javascripts/group_of_line.js.coffee8
-rw-r--r--app/assets/javascripts/import_tasks.js.coffee2
-rw-r--r--app/assets/javascripts/import_tasks/index.js.coffee1
-rw-r--r--app/assets/javascripts/journey_pattern.js.coffee7
-rw-r--r--app/assets/javascripts/lines/index.js.coffee1
-rw-r--r--app/assets/javascripts/multiple_selection.js.coffee6
-rw-r--r--app/assets/javascripts/plugins.js1
-rw-r--r--app/assets/javascripts/plugins/bootstrap_timepicker_activation.coffee11
-rw-r--r--app/assets/javascripts/plugins/formtastic.qtip2.min.js2
-rw-r--r--app/assets/javascripts/plugins/jquery.qtip.min.js2
-rw-r--r--app/assets/javascripts/plugins/jquery.readyselector.js17
-rw-r--r--app/assets/javascripts/plugins/jquery.tipsy.js258
-rw-r--r--app/assets/javascripts/plugins/jquery.ui.datepicker-i18n.js78
-rw-r--r--app/assets/javascripts/plugins/tooltip.js.coffee2
-rw-r--r--app/assets/javascripts/route.js.coffee24
-rw-r--r--app/assets/javascripts/stop_areas.js.coffee45
-rw-r--r--app/assets/javascripts/stop_areas/edit.js.coffee31
-rw-r--r--app/assets/javascripts/stop_areas/index.js.coffee25
-rw-r--r--app/assets/javascripts/time_tables.js.coffee21
-rw-r--r--app/assets/javascripts/vehicle_journey.js.coffee55
-rw-r--r--app/assets/javascripts/vehicle_journey_import.js.coffee0
-rw-r--r--app/assets/javascripts/vehicle_journeys/index.js.coffee7
-rw-r--r--app/assets/javascripts/vehicle_journeys/show.js.coffee8
-rw-r--r--app/assets/stylesheets/application.css.scss.erb26
-rw-r--r--app/assets/stylesheets/main/access_points.css.scss51
-rw-r--r--app/assets/stylesheets/main/api_keys.css.scss19
-rw-r--r--app/assets/stylesheets/main/calendar.css.scss103
-rw-r--r--app/assets/stylesheets/main/companies.css.scss4
-rw-r--r--app/assets/stylesheets/main/compliance_check_tasks.css.scss46
-rw-r--r--app/assets/stylesheets/main/connection_links.css.scss4
-rw-r--r--app/assets/stylesheets/main/exports.css.scss40
-rw-r--r--app/assets/stylesheets/main/group_of_lines.css.scss52
-rw-r--r--app/assets/stylesheets/main/help.css.scss30
-rw-r--r--app/assets/stylesheets/main/import_tasks.css.scss48
-rw-r--r--app/assets/stylesheets/main/layout.css.scss325
-rw-r--r--app/assets/stylesheets/main/lines.css.scss39
-rw-r--r--app/assets/stylesheets/main/networks.css.scss6
-rw-r--r--app/assets/stylesheets/main/organisations.css.scss18
-rw-r--r--app/assets/stylesheets/main/referentials.css.scss67
-rw-r--r--app/assets/stylesheets/main/routes.css.scss105
-rw-r--r--app/assets/stylesheets/main/rule_parameter_sets.css.scss35
-rw-r--r--app/assets/stylesheets/main/stop_areas.css.scss45
-rw-r--r--app/assets/stylesheets/main/time_table_combinations.css.scss14
-rw-r--r--app/assets/stylesheets/main/time_tables.css.scss271
-rw-r--r--app/assets/stylesheets/main/vehicle_journeys.css.scss90
-rw-r--r--app/assets/stylesheets/main/vehicle_translation.css.scss15
-rw-r--r--app/assets/stylesheets/modules/devise.css.scss75
-rw-r--r--app/assets/stylesheets/modules/icons.css.scss101
-rw-r--r--app/assets/stylesheets/modules/index_item.css.scss85
-rw-r--r--app/assets/stylesheets/modules/search.css.scss19
-rw-r--r--app/assets/stylesheets/partials/footer.css.scss15
-rw-r--r--app/assets/stylesheets/partials/header.css.scss48
-rw-r--r--app/assets/stylesheets/vendor/bootstrap_changes.css.scss34
-rw-r--r--app/assets/stylesheets/vendor/formtastic.css.scss20
-rw-r--r--app/assets/stylesheets/vendor/formtastic_changes.css.scss46
-rw-r--r--app/assets/stylesheets/vendor/jquery.qtip.min.css1
-rw-r--r--app/assets/stylesheets/vendor/map_layers.css.scss1
-rw-r--r--app/assets/stylesheets/vendor/pagination.css.scss21
-rw-r--r--app/assets/stylesheets/vendor/simple_form.css.scss6
-rw-r--r--app/assets/stylesheets/vendor/tipsy.css25
-rw-r--r--app/assets/stylesheets/vendor/token-input.css (renamed from app/assets/stylesheets/main/token-input.css)32
-rw-r--r--app/assets/stylesheets/vendor/typeahead.css.scss49
-rw-r--r--app/controllers/access_links_controller.rb15
-rw-r--r--app/controllers/access_points_controller.rb7
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/breadcrumb_controller.rb41
-rw-r--r--app/controllers/chouette_controller.rb7
-rw-r--r--app/controllers/companies_controller.rb3
-rw-r--r--app/controllers/compliance_check_tasks_controller.rb10
-rw-r--r--app/controllers/connection_link_areas_controller.rb8
-rw-r--r--app/controllers/connection_links_controller.rb7
-rw-r--r--app/controllers/exports_controller.rb7
-rw-r--r--app/controllers/group_of_lines_controller.rb10
-rw-r--r--app/controllers/help_controller.rb9
-rw-r--r--app/controllers/import_tasks_controller.rb9
-rw-r--r--app/controllers/journey_patterns_controller.rb15
-rw-r--r--app/controllers/lines_controller.rb25
-rw-r--r--app/controllers/networks_controller.rb6
-rw-r--r--app/controllers/organisations_controller.rb4
-rw-r--r--app/controllers/referentials_controller.rb9
-rw-r--r--app/controllers/registrations_controller.rb16
-rw-r--r--app/controllers/routes_controller.rb4
-rw-r--r--app/controllers/rule_parameter_sets_controller.rb6
-rw-r--r--app/controllers/stop_area_children_controller.rb10
-rw-r--r--app/controllers/stop_area_copies_controller.rb30
-rw-r--r--app/controllers/stop_area_parents_controller.rb10
-rw-r--r--app/controllers/stop_areas_controller.rb61
-rw-r--r--app/controllers/stop_point_areas_controller.rb8
-rw-r--r--app/controllers/time_table_combinations_controller.rb46
-rw-r--r--app/controllers/time_tables_controller.rb69
-rw-r--r--app/controllers/users_controller.rb4
-rw-r--r--app/controllers/vehicle_journey_exports_controller.rb43
-rw-r--r--app/controllers/vehicle_journey_imports_controller.rb38
-rw-r--r--app/controllers/vehicle_journeys_controller.rb51
-rw-r--r--app/controllers/vehicle_translations_controller.rb35
-rw-r--r--app/exporters/chouette/hub/city_code_exporter.rb35
-rw-r--r--app/exporters/chouette/hub/commercial_stop_area_exporter.rb36
-rw-r--r--app/exporters/chouette/hub/company_exporter.rb35
-rw-r--r--app/exporters/chouette/hub/connection_link_exporter.rb40
-rw-r--r--app/exporters/chouette/hub/direction_exporter.rb39
-rw-r--r--app/exporters/chouette/hub/exporter.rb249
-rw-r--r--app/exporters/chouette/hub/group_of_lines_exporter.rb35
-rw-r--r--app/exporters/chouette/hub/journey_pattern_exporter.rb49
-rw-r--r--app/exporters/chouette/hub/line_exporter.rb40
-rw-r--r--app/exporters/chouette/hub/network_exporter.rb35
-rw-r--r--app/exporters/chouette/hub/physical_stop_area_exporter.rb47
-rw-r--r--app/exporters/chouette/hub/route_exporter.rb44
-rw-r--r--app/exporters/chouette/hub/time_table_exporter.rb49
-rw-r--r--app/exporters/chouette/hub/transport_mode_exporter.rb35
-rw-r--r--app/exporters/chouette/hub/vehicle_journey_at_stop_exporter.rb58
-rw-r--r--app/exporters/chouette/hub/vehicle_journey_exporter.rb75
-rw-r--r--app/exporters/chouette/hub/vehicle_journey_operation_exporter.rb100
-rw-r--r--app/exporters/chouette/kml/exporter.rb4
-rw-r--r--app/helpers/application_helper.rb42
-rw-r--r--app/helpers/breadcrumb_helper.rb207
-rw-r--r--app/helpers/exports_helper.rb35
-rw-r--r--app/helpers/history_helper.rb14
-rw-r--r--app/helpers/imports_helper.rb35
-rw-r--r--app/helpers/pagination_helper.rb7
-rw-r--r--app/helpers/remote_bootstrap_pagination_link_renderer.rb8
-rw-r--r--app/helpers/time_tables_helper.rb15
-rw-r--r--app/helpers/users_helper.rb4
-rw-r--r--app/helpers/vehicle_journeys_helper.rb7
-rw-r--r--app/inputs/check_boxes_input.rb17
-rw-r--r--app/inputs/extended_time_picker_input.rb13
-rw-r--r--app/inputs/search_stop_area_input.rb40
-rw-r--r--app/inputs/search_time_table_input.rb55
-rw-r--r--app/inputs/tags_input.rb19
-rw-r--r--app/maps/access_link_map.rb2
-rw-r--r--app/maps/access_point_map.rb10
-rw-r--r--app/maps/application_map.rb24
-rw-r--r--app/maps/stop_area_map.rb121
-rw-r--r--app/models/export.rb31
-rw-r--r--app/models/gtfs_export.rb4
-rw-r--r--app/models/gtfs_import.rb4
-rw-r--r--app/models/hub_export.rb35
-rw-r--r--app/models/import_task.rb9
-rw-r--r--app/models/organisation.rb3
-rw-r--r--app/models/referential.rb63
-rw-r--r--app/models/rule_parameter_set.rb34
-rw-r--r--app/models/stop_area_copy.rb68
-rw-r--r--app/models/time_table_combination.rb47
-rw-r--r--app/models/user.rb14
-rw-r--r--app/models/vehicle_filter.rb57
-rw-r--r--app/models/vehicle_journey_export.rb154
-rw-r--r--app/models/vehicle_journey_import.rb158
-rw-r--r--app/models/vehicle_translation.rb107
-rw-r--r--app/views/access_link_pairs/_access_link_pair.html.erb105
-rw-r--r--app/views/access_links/_form.html.erb28
-rw-r--r--app/views/access_links/show.html.erb16
-rw-r--r--app/views/access_points/_access_point.html.erb47
-rw-r--r--app/views/access_points/_form.html.erb18
-rw-r--r--app/views/access_points/show.html.erb65
-rw-r--r--app/views/api/hub/arrets_generiques.hub.erb1
-rw-r--r--app/views/api/hub/arrets_physiques.hub.erb1
-rw-r--r--app/views/api/hub/chemins.hub.erb1
-rw-r--r--app/views/api/hub/communes.hub.erb1
-rw-r--r--app/views/api/hub/correspondances.hub.erb1
-rw-r--r--app/views/api/hub/courses.hub.erb1
-rw-r--r--app/views/api/hub/courses_operations.hub.erb1
-rw-r--r--app/views/api/hub/directions.hub.erb1
-rw-r--r--app/views/api/hub/groupe_de_lignes.hub.erb1
-rw-r--r--app/views/api/hub/horaires.hub.erb1
-rw-r--r--app/views/api/hub/lignes.hub.erb1
-rw-r--r--app/views/api/hub/modes_transports.hub.erb1
-rw-r--r--app/views/api/hub/periodes.hub.erb1
-rw-r--r--app/views/api/hub/reseaux.hub.erb1
-rw-r--r--app/views/api/hub/schemas.hub.erb1
-rw-r--r--app/views/api/hub/transporteurs.hub.erb1
-rw-r--r--app/views/api_keys/_api_key.html.erb38
-rw-r--r--app/views/companies/_companies.erb9
-rw-r--r--app/views/companies/_company.erb35
-rw-r--r--app/views/companies/_form.erb4
-rw-r--r--app/views/companies/index.html.erb30
-rw-r--r--app/views/companies/index.js.erb1
-rw-r--r--app/views/companies/show.html.erb11
-rw-r--r--app/views/compliance_check_results/index.html.erb6
-rw-r--r--app/views/compliance_check_results/index.js.coffee10
-rw-r--r--app/views/compliance_check_tasks/_compliance_check_task.erb22
-rw-r--r--app/views/compliance_check_tasks/_compliance_check_task.html.erb34
-rw-r--r--app/views/compliance_check_tasks/_compliance_check_tasks.html.erb9
-rw-r--r--app/views/compliance_check_tasks/index.html.erb11
-rw-r--r--app/views/compliance_check_tasks/index.js.erb1
-rw-r--r--app/views/compliance_check_tasks/show.js.coffee3
-rw-r--r--app/views/connection_links/_connection_link.erb39
-rw-r--r--app/views/connection_links/_connection_links.erb9
-rw-r--r--app/views/connection_links/_form.erb10
-rw-r--r--app/views/connection_links/index.html.erb49
-rw-r--r--app/views/connection_links/index.js.erb1
-rw-r--r--app/views/connection_links/select_areas.html.erb35
-rw-r--r--app/views/connection_links/show.html.erb11
-rw-r--r--app/views/devise/_links.erb2
-rw-r--r--app/views/devise/passwords/new.html.erb20
-rw-r--r--app/views/devise/registrations/new.html.erb36
-rw-r--r--app/views/devise/sessions/new.html.erb78
-rw-r--r--app/views/exports/_export.erb46
-rw-r--r--app/views/exports/_exports.html.erb9
-rw-r--r--app/views/exports/_fields_gtfs_export.erb2
-rw-r--r--app/views/exports/_fields_hub_export.erb2
-rw-r--r--app/views/exports/_fields_neptune_export.erb4
-rw-r--r--app/views/exports/index.html.erb19
-rw-r--r--app/views/exports/index.js.erb1
-rw-r--r--app/views/exports/new.html.erb7
-rw-r--r--app/views/exports/new.js.coffee2
-rw-r--r--app/views/group_of_lines/_form.erb4
-rw-r--r--app/views/group_of_lines/_group_of_line.erb34
-rw-r--r--app/views/group_of_lines/_group_of_lines.erb9
-rw-r--r--app/views/group_of_lines/_lines_detail.html.erb13
-rw-r--r--app/views/group_of_lines/index.html.erb30
-rw-r--r--app/views/group_of_lines/index.js.erb1
-rw-r--r--app/views/group_of_lines/show.html.erb20
-rw-r--r--app/views/group_of_lines/show.kml.erb1
-rw-r--r--app/views/help/access_links.textile69
-rw-r--r--app/views/help/access_points.textile76
-rw-r--r--app/views/help/access_points_links.textile88
-rw-r--r--app/views/help/browser.textile17
-rw-r--r--app/views/help/companies.textile97
-rw-r--r--app/views/help/connection.textile28
-rw-r--r--app/views/help/connection_links.textile101
-rw-r--r--app/views/help/dataspaces.textile77
-rw-r--r--app/views/help/documentation.textile8
-rw-r--r--app/views/help/edit.textile20
-rw-r--r--app/views/help/export_format.textile37
-rw-r--r--app/views/help/exports.textile17
-rw-r--r--app/views/help/faq.textile8
-rw-r--r--app/views/help/group_of_lines.textile89
-rw-r--r--app/views/help/import_formats.textile39
-rw-r--r--app/views/help/imports.textile61
-rw-r--r--app/views/help/index.textile27
-rw-r--r--app/views/help/introduction.textile20
-rw-r--r--app/views/help/journey_patterns.textile78
-rw-r--r--app/views/help/lines.textile115
-rw-r--r--app/views/help/maps.textile14
-rw-r--r--app/views/help/metadata.textile39
-rw-r--r--app/views/help/navigation.textile61
-rw-r--r--app/views/help/networks.textile38
-rw-r--r--app/views/help/normalisation.textile46
-rw-r--r--app/views/help/parametersets.textile118
-rw-r--r--app/views/help/prerequisite.textile18
-rw-r--r--app/views/help/relationship.textile46
-rw-r--r--app/views/help/routes.textile104
-rw-r--r--app/views/help/schema.textile8
-rw-r--r--app/views/help/search_filter.textile18
-rw-r--r--app/views/help/startingfromscratch.textile60
-rw-r--r--app/views/help/stop_areas.textile180
-rw-r--r--app/views/help/stopsmanagement.textile19
-rw-r--r--app/views/help/temporaryline.textile23
-rw-r--r--app/views/help/time_tables.textile65
-rw-r--r--app/views/help/toc.textile83
-rw-r--r--app/views/help/tutorial.textile15
-rw-r--r--app/views/help/vehicle_journeys.textile147
-rw-r--r--app/views/import_tasks/_fields_gtfs_import.erb8
-rw-r--r--app/views/import_tasks/_import_task.erb32
-rw-r--r--app/views/import_tasks/_import_tasks.html.erb9
-rw-r--r--app/views/import_tasks/index.html.erb12
-rw-r--r--app/views/import_tasks/index.js.erb1
-rw-r--r--app/views/import_tasks/new.html.erb8
-rw-r--r--app/views/journey_patterns/_form.html.erb2
-rw-r--r--app/views/journey_patterns/_journey_pattern.html.erb41
-rw-r--r--app/views/journey_patterns/edit.html.erb13
-rw-r--r--app/views/journey_patterns/show.html.erb15
-rw-r--r--app/views/journey_patterns/show.js.erb4
-rw-r--r--app/views/layouts/application.html.erb96
-rw-r--r--app/views/layouts/devise.html.erb40
-rw-r--r--app/views/layouts/without_sidebar.html.erb126
-rw-r--r--app/views/lines/_form.erb6
-rw-r--r--app/views/lines/_line.erb57
-rw-r--r--app/views/lines/_lines.html.erb9
-rw-r--r--app/views/lines/index.html.erb90
-rw-r--r--app/views/lines/index.js.erb1
-rw-r--r--app/views/lines/show.html.erb49
-rw-r--r--app/views/lines/show.kml.erb1
-rw-r--r--app/views/networks/_form.erb4
-rw-r--r--app/views/networks/_network.erb28
-rw-r--r--app/views/networks/_networks.erb9
-rw-r--r--app/views/networks/index.html.erb35
-rw-r--r--app/views/networks/index.js.erb1
-rw-r--r--app/views/networks/show.html.erb9
-rw-r--r--app/views/networks/show.kml.erb1
-rw-r--r--app/views/organisations/show.html.erb10
-rw-r--r--app/views/referentials/_clean.html.erb2
-rw-r--r--app/views/referentials/_form.erb8
-rw-r--r--app/views/referentials/_referential.erb46
-rw-r--r--app/views/referentials/index.html.erb2
-rw-r--r--app/views/referentials/show.html.erb9
-rw-r--r--app/views/referentials/show.js.erb40
-rw-r--r--app/views/routes/_form.html.erb14
-rw-r--r--app/views/routes/_route.html.erb43
-rw-r--r--app/views/routes/_stop_point_fields.html.erb2
-rw-r--r--app/views/routes/_stop_points_detail.html.erb10
-rw-r--r--app/views/routes/show.html.erb32
-rw-r--r--app/views/routes/show.js.erb4
-rw-r--r--app/views/routes/show.kml.erb1
-rw-r--r--app/views/rule_parameter_sets/_form.html.erb29
-rw-r--r--app/views/rule_parameter_sets/_mode_fields.html.erb13
-rw-r--r--app/views/rule_parameter_sets/_rule_parameter_set.html.erb23
-rw-r--r--app/views/rule_parameter_sets/index.html.erb14
-rw-r--r--app/views/rule_parameter_sets/show.html.erb71
-rw-r--r--app/views/shared/_breadcrumb.erb3
-rw-r--r--app/views/shared/_footer.erb16
-rw-r--r--app/views/shared/_header.erb100
-rw-r--r--app/views/stop_area_copies/new.html.erb22
-rw-r--r--app/views/stop_areas/_form.html.erb202
-rw-r--r--app/views/stop_areas/_genealogical.html.erb6
-rw-r--r--app/views/stop_areas/_stop_area.html.erb44
-rw-r--r--app/views/stop_areas/_stop_areas.html.erb9
-rw-r--r--app/views/stop_areas/access_links.html.erb65
-rw-r--r--app/views/stop_areas/add_children.html.erb15
-rw-r--r--app/views/stop_areas/index.html.erb58
-rw-r--r--app/views/stop_areas/index.js.erb1
-rw-r--r--app/views/stop_areas/index.kml.erb1
-rw-r--r--app/views/stop_areas/index.rabl9
-rw-r--r--app/views/stop_areas/select_parent.html.erb18
-rw-r--r--app/views/stop_areas/show.html.erb37
-rw-r--r--app/views/stop_areas/show.rabl9
-rw-r--r--app/views/stop_points/_stop_point.html.erb32
-rw-r--r--app/views/time_table_combinations/_combine.html.erb12
-rw-r--r--app/views/time_table_combinations/_combine_form.html.erb14
-rw-r--r--app/views/time_table_combinations/create_failure.js.erb5
-rw-r--r--app/views/time_table_combinations/create_success.js.erb8
-rw-r--r--app/views/time_table_combinations/new.js.erb4
-rw-r--r--app/views/time_tables/_date_fields.erb8
-rw-r--r--app/views/time_tables/_dates.html.erb2
-rw-r--r--app/views/time_tables/_excluded_date_fields.erb6
-rw-r--r--app/views/time_tables/_excluded_dates.html.erb7
-rw-r--r--app/views/time_tables/_form.erb90
-rw-r--r--app/views/time_tables/_period_fields.erb10
-rw-r--r--app/views/time_tables/_periods.html.erb35
-rw-r--r--app/views/time_tables/_show_time_table.html.erb101
-rw-r--r--app/views/time_tables/_time_table.erb19
-rw-r--r--app/views/time_tables/_time_table.html.erb35
-rw-r--r--app/views/time_tables/_time_tables.html.erb9
-rw-r--r--app/views/time_tables/edit.html.erb1
-rw-r--r--app/views/time_tables/index.html.erb45
-rw-r--r--app/views/time_tables/index.js.erb1
-rw-r--r--app/views/time_tables/index.json.rabl9
-rw-r--r--app/views/time_tables/show.html.erb106
-rw-r--r--app/views/time_tables/time_tables.json.rabl5
-rw-r--r--app/views/users/_form.html.erb2
-rw-r--r--app/views/users/_user.html.erb22
-rw-r--r--app/views/users/edit.html.erb1
-rw-r--r--app/views/vehicle_journey_exports/index.xls.erb26
-rw-r--r--app/views/vehicle_journey_imports/new.html.erb22
-rw-r--r--app/views/vehicle_journeys/_form.html.erb86
-rw-r--r--app/views/vehicle_journeys/_route_popover.html.erb6
-rw-r--r--app/views/vehicle_journeys/_show_popover.html.erb26
-rw-r--r--app/views/vehicle_journeys/_sidebar.html.erb6
-rw-r--r--app/views/vehicle_journeys/_time_table.html.erb12
-rw-r--r--app/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb13
-rw-r--r--app/views/vehicle_journeys/_vehicle_journeys.html.erb39
-rw-r--r--app/views/vehicle_journeys/edit.html.erb13
-rw-r--r--app/views/vehicle_journeys/index.html.erb161
-rw-r--r--app/views/vehicle_journeys/index.js.erb2
-rw-r--r--app/views/vehicle_journeys/new.html.erb13
-rw-r--r--app/views/vehicle_journeys/select_journey_pattern.js.erb3
-rw-r--r--app/views/vehicle_journeys/show.html.erb76
-rw-r--r--app/views/vehicle_journeys/timeless.html.erb28
-rw-r--r--app/views/vehicle_translations/_translate_form.html.erb24
-rw-r--r--app/views/vehicle_translations/new.js.erb4
-rw-r--r--config/application.rb4
-rw-r--r--config/deploy.rb6
-rw-r--r--config/deploy/sismo.rb2
-rw-r--r--config/deploy/unstable.rb2
-rw-r--r--config/environment.rb2
-rw-r--r--config/environments/development.rb16
-rw-r--r--config/environments/production.rb20
-rw-r--r--config/initializers/devise.rb29
-rw-r--r--config/initializers/formtastic.rb96
-rw-r--r--config/initializers/rabl_config.rb22
-rw-r--r--config/initializers/remove_simple_form_bootstrap3_inputs.rb32
-rw-r--r--config/initializers/simple_form.rb142
-rw-r--r--config/initializers/simple_form_bootstrap.rb58
-rw-r--r--config/locales/access_links.yml4
-rw-r--r--config/locales/access_points.yml16
-rw-r--r--config/locales/breadcrumbs.yml10
-rw-r--r--config/locales/clean_ups.yml18
-rw-r--r--config/locales/companies.yml12
-rw-r--r--config/locales/compliance_check_results.yml21
-rw-r--r--config/locales/compliance_check_tasks.yml6
-rw-r--r--config/locales/connection_links.yml8
-rw-r--r--config/locales/devise.en.yml4
-rw-r--r--config/locales/devise.fr.yml8
-rw-r--r--config/locales/exchange.yml18
-rw-r--r--config/locales/exports.yml64
-rw-r--r--config/locales/formtastic.yml32
-rw-r--r--config/locales/group_of_lines.yml8
-rw-r--r--config/locales/import_tasks.yml22
-rw-r--r--config/locales/journey_patterns.yml4
-rw-r--r--config/locales/layouts.yml26
-rw-r--r--config/locales/lines.yml62
-rw-r--r--config/locales/networks.yml8
-rw-r--r--config/locales/referentials.yml14
-rw-r--r--config/locales/routes.yml12
-rw-r--r--config/locales/rule_parameter_sets.yml83
-rw-r--r--config/locales/simple_form.en.yml26
-rw-r--r--config/locales/stop_area_copies.yml29
-rw-r--r--config/locales/stop_areas.yml50
-rw-r--r--config/locales/stop_points.yml4
-rw-r--r--config/locales/time_table_combinations.yml31
-rw-r--r--config/locales/time_tables.yml87
-rw-r--r--config/locales/transport_modes.yml2
-rw-r--r--config/locales/vehicle_journey_exports.yml52
-rw-r--r--config/locales/vehicle_journey_imports.yml41
-rw-r--r--config/locales/vehicle_journeys.yml74
-rw-r--r--config/locales/vehicle_translations.yml29
-rw-r--r--config/routes.rb38
-rw-r--r--db/migrate/20140617141550_add_on_demand_transportation_to_line.ninoxe_engine.rb6
-rw-r--r--db/migrate/20140617141551_add_details_to_vehicle_journey.ninoxe_engine.rb7
-rw-r--r--db/migrate/20140618072859_fix_column_name.ninoxe_engine.rb12
-rw-r--r--db/migrate/20140626081657_add_in_out_to_timetable_date.ninoxe_engine.rb6
-rw-r--r--db/migrate/20140626081658_set_in_out_to_timetable_date.ninoxe_engine.rb9
-rw-r--r--db/migrate/20140721080943_acts_as_taggable_on_migration.ninoxe_engine.rb32
-rw-r--r--db/migrate/20140721080944_add_missing_unique_indices.ninoxe_engine.rb21
-rw-r--r--db/migrate/20140721080945_add_taggings_counter_cache_to_tags.ninoxe_engine.rb16
-rw-r--r--db/migrate/20140721080946_add_missing_taggable_index.ninoxe_engine.rb11
-rw-r--r--db/migrate/20140820074843_add_zip_code_and_city_name_to_stop_area.ninoxe_engine.rb9
-rw-r--r--db/migrate/20140820074844_add_zip_code_and_city_name_to_access_point.ninoxe_engine.rb9
-rw-r--r--db/schema.rb42
-rw-r--r--lib/bootstrap_breadcrumbs_builder.rb31
-rw-r--r--public/help/2014-10-30_172801.pngbin0 -> 2405 bytes
-rw-r--r--public/help/2014-10-30_174529.pngbin0 -> 21155 bytes
-rw-r--r--public/help/2014-10-30_175216.pngbin0 -> 7580 bytes
-rw-r--r--public/help/2014-10-30_180131.pngbin0 -> 13188 bytes
-rw-r--r--public/help/2014-10-30_180211.pngbin0 -> 445555 bytes
-rw-r--r--public/help/2014-10-30_180356.pngbin0 -> 53387 bytes
-rw-r--r--public/help/2014-10-30_180447.pngbin0 -> 3263 bytes
-rw-r--r--public/help/2014-10-30_180536.pngbin0 -> 4078 bytes
-rw-r--r--public/help/2014-10-30_182229.pngbin0 -> 1553 bytes
-rw-r--r--public/help/2014-10-31_112140.pngbin0 -> 388235 bytes
-rw-r--r--public/help/2014-10-31_112324.pngbin0 -> 7118 bytes
-rw-r--r--public/help/2014-10-31_112543.pngbin0 -> 6438 bytes
-rw-r--r--public/help/2014-10-31_113648.pngbin0 -> 344550 bytes
-rw-r--r--public/help/2014-10-31_113803.pngbin0 -> 7612 bytes
-rw-r--r--public/help/2014-10-31_113958.pngbin0 -> 27583 bytes
-rw-r--r--public/help/2014-10-31_114336.pngbin0 -> 9521 bytes
-rw-r--r--public/help/2014-10-31_114422.pngbin0 -> 2188 bytes
-rw-r--r--public/help/2014-10-31_114639.pngbin0 -> 14612 bytes
-rw-r--r--public/help/2014-10-31_115014.pngbin0 -> 397153 bytes
-rw-r--r--public/help/2014-10-31_120428.pngbin0 -> 22238 bytes
-rw-r--r--spec/controllers/vehicle_journey_imports_controller_spec.rb7
-rw-r--r--spec/exporters/chouette/kml/exporter_spec.rb8
-rw-r--r--spec/factories.rb6
-rw-r--r--spec/fixtures/vehicle_journey_imports_valid.csv17
-rw-r--r--spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv17
-rw-r--r--spec/fixtures/vehicle_journey_imports_with_vjas_bad_order.csv12
-rw-r--r--spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv17
-rw-r--r--spec/models/export_spec.rb2
-rw-r--r--spec/models/stop_area_copy_spec.rb40
-rw-r--r--spec/models/time_table_combination_spec.rb90
-rw-r--r--spec/models/vehicle_journey_export_spec.rb85
-rw-r--r--spec/models/vehicle_journey_import_spec.rb156
-rw-r--r--spec/models/vehicle_translation_spec.rb46
-rw-r--r--spec/requests/referentials_spec.rb2
-rw-r--r--spec/requests/time_tables_spec.rb12
-rw-r--r--spec/requests/vehicle_journey_imports_spec.rb68
-rw-r--r--spec/views/time_tables/show.html.erb_spec.rb1
-rw-r--r--spec/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb_spec.rb4
-rw-r--r--spec/views/vehicle_journeys/edit.html.erb_spec.rb6
-rw-r--r--spec/views/vehicle_journeys/new.html.erb_spec.rb6
480 files changed, 9335 insertions, 4920 deletions
diff --git a/.ruby-version b/.ruby-version
index 8e1735244..c82eec79e 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-ruby-1.9.3-p448
+1.9.3-p448
diff --git a/.travis.yml b/.travis.yml
index 3b34b286e..09934e79d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,11 +8,13 @@ jdk:
matrix:
exclude:
- rvm: 1.9.3
- jdk: openjdk7
+ - jdk: openjdk7
notifications:
+ email:
- mflorisson@cityway.fr
- ldonnet@cityway.fr
- metienne@cityway.fr
+ - zbouziane@cityway.fr
before_install:
- sudo apt-get update
- sudo apt-get install build-essential ruby-dev libproj-dev libgeos-dev libffi-dev libsparsehash-dev zlib1g-dev libxslt1-dev libxml2-dev libbz2-dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 14b6c6846..72dfe74ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,27 @@
+# Version 2.5.0 (en cours)
+* Nouvelles foctionnalités
+ * Ajout d'un lien de création d'objet dans la page de consultation (Mantis 26415)
+ * Ajout d'un lien vers l'accueil dans le bandeau (Mantis 26820)
+ * Fournir plus de détails pour identifier un arrêt dans les listes de choix (Mantis 26821)
+ * Possibilité de créer un arrêt en édition d'une séquence d'arrêts (Mantis 26824)
+ * Localisation d'un arrêt par résolution d'adresse (Mantis 26825)
+ * Saisie des coordonnées sur un seul champ (Mantis 26827)
+ * Filtres de recherche des arrêts enrichi (Mantis 26829)
+ * Cloner un arrêt pour en faire un parent ou un fils (Mantis 26830)
+ * Import d'arrêts en CSV/Excel (Mantis 26832)
+ * Ajout d'étiquettes sur les calendriers (Mantis 26833)
+ * Filtres de recherche des calendriers enrichi (Mantis 26834)
+ * Attributs vacances et jours fériés : comme étiquette (Mantis 26835)
+ * Affichage du format lors de la saisie d'une date (Mantis 26836)
+ * Gestion de dates exclues dans les calendriers (Mantis 26837)
+ * Fonctions de combinaisons de calendriers : inclusion, exclusions, duplication (Mantis 26838)
+ * Clonage de course avec heure de départ (Mantis 26839)
+ * Décaler les horaires d'une course (Mantis 26840)
+ * Import CSV d'horaires pour une séquence d'arrêts (Mantis 26843)
+ * Améliorations affichage de l'état des exports (Mantis 26845)
+ * Attributs TAD et PMR sur les lignes et les courses (Mantis 26846
+ * Export au format HUB (Mantis 27173)
+
# Version 2.4.1 (13/08/14)
* Corrections d'anomalies
* L'export GTFS exige que l'indice de ligne soit renseigné (Mantis 26726)
diff --git a/Gemfile b/Gemfile
index eef087238..0af970b6c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,10 +1,10 @@
source 'http://rubygems.org'
+source 'https://rails-assets.org'
gem 'rails', '3.2.18'
platforms :jruby do
- gem 'activerecord-jdbcpostgresql-adapter', '1.2.9'
- gem 'activerecord-jdbcsqlite3-adapter'
+ gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.3'
gem 'jruby-openssl'
gem "jruby-rack-worker"
gem 'warbler'
@@ -28,13 +28,20 @@ gem "map_layers", "0.0.4"
gem "georuby-ext", "0.0.5"
# User interface
-gem 'language_engine', '0.0.4'
+gem 'language_engine', '0.0.5'
gem 'gravatar_image_tag'
gem 'calendar_helper', "0.2.5"
gem 'cocoon', "1.1.2"
-gem 'formtastic'
+gem 'formtastic', "2.3.1"
gem 'RedCloth'
+# some views use coffee script
+gem 'coffee-rails', '~> 3.2.1'
+gem 'coffee-script-source'
+
+gem 'sass-rails', '~> 3.2.3'
+gem 'uglifier', '>= 1.0.3'
+
# Javascript
gem 'jquery-rails', '2.2.1'
gem 'jquery-ui-sass-rails'
@@ -43,14 +50,20 @@ gem 'morrisjs-rails'
gem 'raphael-rails'
# Use twitter bootstrap resources
-gem 'bootstrap-sass', '~> 3.1.1'
-gem 'bootswatch-rails'
-gem 'font-awesome-sass'
+gem 'rails-assets-bootstrap-sass-official', '~> 3.3.0'
+gem 'font-awesome-sass', '~> 4.2.0'
gem 'will_paginate-bootstrap'
+gem 'simple_form', "2.1.1"
+gem 'rails-assets-tagmanager', '~> 3.0.1.0'
+gem 'rails-assets-typeahead.js', '~> 0.10.5'
+gem "breadcrumbs_on_rails"
+gem 'rails-assets-typeahead.js-bootstrap3.less'
+gem 'rails-assets-respond'
+gem 'rails-assets-eonasdan-bootstrap-datetimepicker', '~> 3.1.3'
# Format Output
gem 'json'
-gem 'rubyzip', :require => 'zip/zip'
+gem 'rubyzip', '~> 1.1.6'
gem 'roo'
# Controller
@@ -61,9 +74,7 @@ gem 'google-analytics-rails'
gem 'will_paginate', '~> 3.0'
gem 'ransack'
gem 'squeel'
-
-gem 'ninoxe', :git => 'https://github.com/afimb/ninoxe.git'
-#gem 'ninoxe',:path => '~/projects/ninoxe'
+gem 'ninoxe', :git => 'https://github.com/afimb/ninoxe.git', :branch => :sismo
#gem 'ninoxe',:path => '~/workspace/chouette/ninoxe'
#gem 'ninoxe', '~> 1.0.3'
@@ -76,13 +87,6 @@ gem 'rabl'
gem 'delayed_job_active_record'
gem 'dr-apartment', :require => "apartment"
-# some views use coffee script
-gem 'coffee-rails', '~> 3.2.1'
-gem 'coffee-script-source'
-
-gem 'sass-rails', '~> 3.2.3'
-gem 'uglifier', '>= 1.0.3'
-
group :development do
gem 'capistrano'
gem 'capistrano-ext'
@@ -109,3 +113,4 @@ group :production do
gem "daemons"
end
+
diff --git a/Gemfile.lock b/Gemfile.lock
index 3e4e987b5..47272cc14 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,16 +1,20 @@
GIT
remote: https://github.com/afimb/ninoxe.git
- revision: 8e51f48524cfbe4aea48e574a4ba11546cf0f722
+ revision: 9a9563cc869e0353d6b073ce5aacc3d07a7217c0
+ branch: sismo
specs:
- ninoxe (1.0.1)
- activerecord (>= 3.1.3, < 4.0)
+ ninoxe (1.1.0)
+ activerecord (~> 3.2.13)
+ acts-as-taggable-on (>= 3)
acts_as_list (>= 0.1.6)
acts_as_tree (>= 1.1.0)
+ deep_cloneable (~> 2.0.0)
foreigner (= 1.6.0)
georuby-ext (= 0.0.5)
GEM
remote: http://rubygems.org/
+ remote: https://rails-assets.org/
specs:
RedCloth (4.2.9)
RedCloth (4.2.9-java)
@@ -38,33 +42,30 @@ GEM
activesupport (= 3.2.18)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
- activerecord-jdbc-adapter (1.2.9)
- activerecord-jdbcpostgresql-adapter (1.2.9)
- activerecord-jdbc-adapter (~> 1.2.9)
- jdbc-postgres (>= 9.1, < 9.3)
- activerecord-jdbcsqlite3-adapter (1.2.1)
- activerecord-jdbc-adapter (~> 1.2.1)
- jdbc-sqlite3 (~> 3.7.2)
+ activerecord-jdbc-adapter (1.3.9)
+ activerecord (>= 2.2)
+ activerecord-jdbcpostgresql-adapter (1.3.9)
+ activerecord-jdbc-adapter (~> 1.3.9)
+ jdbc-postgres (>= 9.1)
activeresource (3.2.18)
activemodel (= 3.2.18)
activesupport (= 3.2.18)
activesupport (3.2.18)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
+ acts-as-taggable-on (3.4.2)
+ activerecord (>= 3.2, < 5)
acts_as_list (0.1.6)
- acts_as_tree (1.6.1)
- activerecord (>= 3.0.0)
acts_as_tree-1.8 (1.1.0)
activerecord (>= 3.0.0)
+ acts_as_tree (2.1.0)
+ activerecord (>= 3.0.0)
addressable (2.3.5)
arel (3.0.3)
bcrypt-ruby (3.0.1)
bcrypt-ruby (3.0.1-java)
- bootstrap-sass (3.1.1.1)
- sass (~> 3.2)
- bootswatch-rails (3.1.1.1)
- railties (>= 3.1)
bouncy-castle-java (1.5.0146.1)
+ breadcrumbs_on_rails (2.3.0)
builder (3.0.4)
calendar_helper (0.2.5)
open4
@@ -83,7 +84,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)
@@ -97,6 +98,8 @@ GEM
daemons (1.1.9)
dbf (2.0.7)
fastercsv (~> 1.5.4)
+ deep_cloneable (2.0.0)
+ activerecord (>= 3.1.0, < 5.0.0)
delayed_job (3.0.3)
activesupport (~> 3.0)
delayed_job_active_record (0.3.2)
@@ -127,19 +130,19 @@ GEM
factory_girl (~> 2.6.0)
railties (>= 3.0.0)
fastercsv (1.5.5)
- ffi (1.9.3)
- ffi (1.9.3-java)
+ ffi (1.9.6)
+ ffi (1.9.6-java)
ffi-geos (1.0.0)
ffi (>= 1.0.0)
- font-awesome-sass (4.1.0)
+ font-awesome-sass (4.2.0)
sass (~> 3.2)
foreigner (1.6.0)
activerecord (>= 3.0.0)
- formtastic (2.2.1)
+ formtastic (2.3.1)
actionpack (>= 3.0)
geokit (1.6.7)
multi_json (>= 1.3.2)
- georuby (2.2.1)
+ georuby (2.3.0)
georuby-ext (0.0.5)
activesupport (>= 3.2.6)
dbf
@@ -149,7 +152,7 @@ GEM
georuby (>= 1.9.8)
rgeo (>= 0.3.20)
google-analytics-rails (0.0.4)
- gravatar_image_tag (1.1.3)
+ gravatar_image_tag (1.2.0)
guard (1.3.2)
listen (>= 0.4.2)
thor (>= 0.14.6)
@@ -160,12 +163,11 @@ GEM
activesupport (>= 3.2, < 5)
highline (1.6.15)
hike (1.2.3)
- i18n (0.6.9)
+ i18n (0.6.11)
inherited_resources (1.4.1)
has_scope (~> 0.6.0.rc)
responders (~> 1.0.0.rc)
- jdbc-postgres (9.2.1002.1)
- jdbc-sqlite3 (3.7.2.1)
+ jdbc-postgres (9.3.1101)
journey (1.0.4)
jquery-rails (2.2.1)
railties (>= 3.0, < 5.0)
@@ -177,15 +179,15 @@ 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)
json (1.8.1-java)
- language_engine (0.0.4)
+ language_engine (0.0.5)
rails (~> 3.2.18)
launchy (2.3.0)
addressable (~> 2.3)
@@ -215,8 +217,8 @@ GEM
open4 (1.3.0)
orm_adapter (0.4.0)
pg (0.11.0)
- polyamorous (0.5.0)
- activerecord (~> 3.0)
+ polyamorous (1.1.0)
+ activerecord (>= 3.0)
polyglot (0.3.5)
rabl (0.7.8)
activesupport (>= 2.3.14)
@@ -236,6 +238,24 @@ GEM
activesupport (= 3.2.18)
bundler (~> 1.0)
railties (= 3.2.18)
+ rails-assets-bootstrap (3.1.1)
+ rails-assets-jquery (>= 1.9.0)
+ rails-assets-bootstrap-sass-official (3.3.0)
+ rails-assets-jquery (>= 1.9.0)
+ rails-assets-eonasdan-bootstrap-datetimepicker (3.1.3)
+ rails-assets-bootstrap (>= 3.0)
+ rails-assets-jquery (>= 1.8.3)
+ rails-assets-moment (>= 2.8.0)
+ rails-assets-jquery (2.1.1)
+ rails-assets-moment (2.8.3)
+ rails-assets-respond (1.4.2)
+ rails-assets-tagmanager (3.0.1)
+ rails-assets-jquery (>= 1.0.0)
+ rails-assets-typeahead.js (0.10.5)
+ rails-assets-jquery (>= 1.7)
+ rails-assets-typeahead.js-bootstrap3.less (0.2.3)
+ rails-assets-bootstrap (~> 3.1.0)
+ rails-assets-typeahead.js (~> 0.10.0)
rails-erd (1.1.0)
activerecord (>= 3.0)
activesupport (>= 3.0)
@@ -249,10 +269,12 @@ GEM
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.3.2)
- ransack (0.7.0)
- actionpack (~> 3.0)
- activerecord (~> 3.0)
- polyamorous (~> 0.5.0)
+ ransack (1.4.1)
+ actionpack (>= 3.0)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
+ i18n
+ polyamorous (~> 1.1)
raphael-rails (2.1.2)
rb-fchange (0.0.5)
ffi
@@ -294,31 +316,34 @@ GEM
rspec-mocks (~> 2.13.0)
ruby-graphviz (1.0.9)
ruby-ole (1.2.11.7)
- rubyzip (0.9.9)
- sass (3.3.7)
+ rubyzip (1.1.6)
+ sass (3.4.5)
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)
+ actionpack (~> 3.0)
+ activemodel (~> 3.0)
spreadsheet (0.9.7)
ruby-ole (>= 1.0)
- sprockets (2.2.2)
+ sprockets (2.2.3)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6)
- squeel (1.0.9)
- activerecord (~> 3.0)
- activesupport (~> 3.0)
- polyamorous (~> 0.5.0)
+ squeel (1.2.1)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
+ polyamorous (~> 1.1.0)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
therubyrhino (2.0.1)
@@ -329,18 +354,18 @@ GEM
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
- tzinfo (0.3.39)
+ 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)
@@ -355,12 +380,10 @@ DEPENDENCIES
RedCloth
SyslogLogger
active_enum
- activerecord-jdbcpostgresql-adapter (= 1.2.9)
- activerecord-jdbcsqlite3-adapter
+ activerecord-jdbcpostgresql-adapter (~> 1.3.3)
acts_as_list (= 0.1.6)
acts_as_tree-1.8 (= 1.1.0)
- bootstrap-sass (~> 3.1.1)
- bootswatch-rails
+ breadcrumbs_on_rails
calendar_helper (= 0.2.5)
capistrano
capistrano-ext
@@ -376,8 +399,8 @@ DEPENDENCIES
devise_invitable
dr-apartment
factory_girl_rails (= 1.7)
- font-awesome-sass
- formtastic
+ font-awesome-sass (~> 4.2.0)
+ formtastic (= 2.3.1)
georuby-ext (= 0.0.5)
google-analytics-rails
gravatar_image_tag
@@ -389,7 +412,7 @@ DEPENDENCIES
jruby-openssl
jruby-rack-worker
json
- language_engine (= 0.0.4)
+ language_engine (= 0.0.5)
launchy
map_layers (= 0.0.4)
modernizr-rails (~> 2.0.6)
@@ -398,6 +421,12 @@ DEPENDENCIES
pg (~> 0.11.0)
rabl
rails (= 3.2.18)
+ rails-assets-bootstrap-sass-official (~> 3.3.0)
+ rails-assets-eonasdan-bootstrap-datetimepicker (~> 3.1.3)
+ rails-assets-respond
+ rails-assets-tagmanager (~> 3.0.1.0)
+ rails-assets-typeahead.js (~> 0.10.5)
+ rails-assets-typeahead.js-bootstrap3.less
rails-erd
ransack
raphael-rails
@@ -407,9 +436,10 @@ 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 (= 2.1.1)
sqlite3
squeel
therubyracer (~> 0.10.2)
diff --git a/README.md b/README.md
index ddc7960a6..cc60251f0 100644
--- a/README.md
+++ b/README.md
@@ -65,9 +65,9 @@ Assume Linux user is myuser and its group mygroup (that user is the one who star
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 .
```
@@ -76,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
@@ -187,3 +187,8 @@ Support
-------
Users looking for support should file an issue on the GitHub [issue tracking page](../../issues), or file a [pull request](../../pulls) if you have a fix available.
+
+Credits
+-------
+
+Thanks to Ingolf for his [photo](https://www.flickr.com/photos/ingolfbln/7663851694) under CC BY-SA 2.0 license
diff --git a/app/assets/images/cityway.png b/app/assets/images/cityway.png
new file mode 100644
index 000000000..edce405ea
--- /dev/null
+++ b/app/assets/images/cityway.png
Binary files differ
diff --git a/app/assets/images/compliance_check_task-pending.png b/app/assets/images/compliance_check_task-pending.png
index 21a702d4f..d5af6a807 100644
--- a/app/assets/images/compliance_check_task-pending.png
+++ b/app/assets/images/compliance_check_task-pending.png
Binary files differ
diff --git a/app/assets/images/export-pending.png b/app/assets/images/export-pending.png
index 7fc459926..d5af6a807 100644
--- a/app/assets/images/export-pending.png
+++ b/app/assets/images/export-pending.png
Binary files differ
diff --git a/app/assets/images/export-processing.png b/app/assets/images/export-processing.png
new file mode 100644
index 000000000..7fc459926
--- /dev/null
+++ b/app/assets/images/export-processing.png
Binary files differ
diff --git a/app/assets/images/file-validation-completed.png b/app/assets/images/file-validation-completed.png
deleted file mode 100644
index 242d68d3b..000000000
--- a/app/assets/images/file-validation-completed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/file-validation-failed.png b/app/assets/images/file-validation-failed.png
deleted file mode 100644
index e50298a77..000000000
--- a/app/assets/images/file-validation-failed.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/file-validation-pending.png b/app/assets/images/file-validation-pending.png
deleted file mode 100644
index 2d19124c0..000000000
--- a/app/assets/images/file-validation-pending.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/import_task-pending.png b/app/assets/images/import_task-pending.png
index cfdb7b421..d5af6a807 100644
--- a/app/assets/images/import_task-pending.png
+++ b/app/assets/images/import_task-pending.png
Binary files differ
diff --git a/app/assets/images/logo_chouette.png b/app/assets/images/logo_chouette.png
index f5064d3cd..2b2040113 100644
--- a/app/assets/images/logo_chouette.png
+++ b/app/assets/images/logo_chouette.png
Binary files differ
diff --git a/app/assets/images/welcome.jpg b/app/assets/images/welcome.jpg
new file mode 100644
index 000000000..3fe50d97b
--- /dev/null
+++ b/app/assets/images/welcome.jpg
Binary files differ
diff --git a/app/assets/javascripts/access_points.js.coffee b/app/assets/javascripts/access_points.js.coffee
index 5cff80b7c..56ae24d1e 100644
--- a/app/assets/javascripts/access_points.js.coffee
+++ b/app/assets/javascripts/access_points.js.coffee
@@ -1,46 +1,32 @@
jQuery ->
x_y_change = (event) ->
- if referential_projection != undefined
- referential_point = new OpenLayers.Geometry.Point($('input#access_point_longitude').val(), $('input#access_point_latitude').val()).transform(new OpenLayers.Projection("EPSG:4326"), referential_projection )
-
- $('input#access_point_projection_x').val(referential_point.x)
- $('input#access_point_projection_y').val(referential_point.y)
-
- feature = map.getLayersByName("access_point")[0].getFeatureByFid($('input#access_point_id').val())
- google_point = new OpenLayers.LonLat($('input#access_point_longitude').val(), $('input#access_point_latitude').val()).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
- feature.move(google_point)
- map.setCenter(google_point, 16, false, true)
+ c = $('input#access_point_coordinates').val().split(",")
+ if c.length == 2
+ if referential_projection != undefined
+ referential_point = new OpenLayers.Geometry.Point(c[1], c[0]).transform(new OpenLayers.Projection("EPSG:4326"), referential_projection )
+
+ $('input#access_point_projection_xy').val(referential_point.x.toString()+","+referential_point.y.toString())
+
+ feature = map.getLayersByName("access_point")[0].getFeatureByFid($('input#access_point_id').val())
+ google_point = new OpenLayers.LonLat(c[1], c[0]).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
+ feature.move(google_point)
+ map.setCenter(google_point, 16, false, true)
- $('input#access_point_longitude').change(x_y_change)
- $('input#access_point_latitude').change(x_y_change)
+ $('input#access_point_coordinates').change(x_y_change)
lon_lat_change = (event) ->
- if referential_projection != undefined
- wgs84_point = new OpenLayers.Geometry.Point($('input#access_point_projection_x').val(), $('input#access_point_projection_y').val()).transform(referential_projection, new OpenLayers.Projection("EPSG:4326"))
-
- $('input#access_point_longitude').val( wgs84_point.x)
- $('input#access_point_latitude').val( wgs84_point.y)
-
- feature = map.getLayersByName("stop_area")[0].getFeatureByFid($('input#access_point_id').val())
- google_point = new OpenLayers.LonLat(wgs84_point.x, wgs84_point.y).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
- feature.move(google_point)
- map.setCenter(google_point, 16, false, true)
-
- $('input#access_point_projection_x').change(lon_lat_change)
- $('input#access_point_projection_y').change(lon_lat_change)
-
+ c = $('input#access_point_projection_xy').val().split(",")
+ if c.length == 2
+ if referential_projection != undefined
+ wgs84_point = new OpenLayers.Geometry.Point(c[0], c[1]).transform(referential_projection, new OpenLayers.Projection("EPSG:4326"))
+
+ $('input#access_point_coordinates').val( wgs84_point.y.toString()+","+wgs84_point.x)
- # switch visibility of access_links
- switch_generics = (event) ->
- event.preventDefault()
- $('.access_points .generics.content').toggle('slow')
- $('a.generics .switcher').toggle()
+ feature = map.getLayersByName("access_point")[0].getFeatureByFid($('input#access_point_id').val())
+ google_point = new OpenLayers.LonLat(wgs84_point.x, wgs84_point.y).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
+ feature.move(google_point)
+ map.setCenter(google_point, 16, false, true)
- $('.access_points a.generics').click(switch_generics)
-
- switch_details = (event) ->
- event.preventDefault()
- $('.access_points .details.content').toggle('slow')
- $('a.details .switcher').toggle()
+ $('input#access_point_projection_xy').change(lon_lat_change)
+
- $('.access_points a.details').click(switch_details)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index fa99d193c..01142c849 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -6,10 +6,22 @@
//
//= require jquery
//= require jquery_ujs
-//= require jquery-ui
+//= require jquery.ui.all
//= require modernizr
//= require cocoon
//= require raphael
//= require morris
-//= require bootstrap
+//= require bootstrap-sass-official
+//= require typeahead.js
+//= require moment
+//= require moment/locale/fr
+//= require eonasdan-bootstrap-datetimepicker
+//= require tagmanager
+//= require_directory ./plugins
//= require_directory .
+//= require_directory ./stop_areas
+//= require_directory ./vehicle_journeys
+//= require_directory ./import_tasks
+//= require_directory ./compliance_check_tasks
+//= require_directory ./exports
+//= require_directory ./lines
diff --git a/app/assets/javascripts/bootstrap.js.coffee b/app/assets/javascripts/bootstrap.js.coffee
new file mode 100644
index 000000000..4cd869397
--- /dev/null
+++ b/app/assets/javascripts/bootstrap.js.coffee
@@ -0,0 +1,3 @@
+jQuery ->
+
+
diff --git a/app/assets/javascripts/compliance_check_tasks/index.js.coffee b/app/assets/javascripts/compliance_check_tasks/index.js.coffee
new file mode 100644
index 000000000..01ca11e12
--- /dev/null
+++ b/app/assets/javascripts/compliance_check_tasks/index.js.coffee
@@ -0,0 +1,5 @@
+$(".compliance_check_tasks.index").ready ->
+ $(".progress-bar.failed").addClass("progress-bar-danger").prepend("100%")
+ $(".progress-bar.pending").addClass("progress-bar-info").prepend("10%")
+ $(".progress-bar.processing").addClass("progress-bar-info").prepend("50%")
+ $(".progress-bar.completed").addClass("progress-bar-success").prepend("100%") \ No newline at end of file
diff --git a/app/assets/javascripts/exports/index.js.coffee b/app/assets/javascripts/exports/index.js.coffee
new file mode 100644
index 000000000..655819507
--- /dev/null
+++ b/app/assets/javascripts/exports/index.js.coffee
@@ -0,0 +1 @@
+$(".exports.index").ready -> \ No newline at end of file
diff --git a/app/assets/javascripts/group_of_line.js.coffee b/app/assets/javascripts/group_of_line.js.coffee
index 315fb19e6..737f343ba 100644
--- a/app/assets/javascripts/group_of_line.js.coffee
+++ b/app/assets/javascripts/group_of_line.js.coffee
@@ -1,13 +1,5 @@
jQuery ->
- switch_lines = (event) ->
- event.preventDefault()
- $('.group_of_lines.show .lines_detail').toggle('slow')
- $('a.lines .switcher').toggle()
-
- $('.group_of_lines.show a.lines').click(switch_lines)
-
-
make_ajax_pagination = () ->
$.get(this.href, null, null, 'script')
false
diff --git a/app/assets/javascripts/import_tasks.js.coffee b/app/assets/javascripts/import_tasks.js.coffee
index 66adac461..b273bce8b 100644
--- a/app/assets/javascripts/import_tasks.js.coffee
+++ b/app/assets/javascripts/import_tasks.js.coffee
@@ -6,8 +6,6 @@ jQuery ->
$("#import_task_format_input :radio[name='import_task[format]']").change(import_format_change)
- $('.import_tasks [title]').tipsy({gravity: 'w'})
-
import_check_change = (event) ->
import_task_type = $("input:radio:checked").attr("value")
format_class = '#' + import_task_type + "_new"
diff --git a/app/assets/javascripts/import_tasks/index.js.coffee b/app/assets/javascripts/import_tasks/index.js.coffee
new file mode 100644
index 000000000..8966a2960
--- /dev/null
+++ b/app/assets/javascripts/import_tasks/index.js.coffee
@@ -0,0 +1 @@
+$(".import_tasks.index").ready -> \ No newline at end of file
diff --git a/app/assets/javascripts/journey_pattern.js.coffee b/app/assets/javascripts/journey_pattern.js.coffee
index 062fc611e..0f203397b 100644
--- a/app/assets/javascripts/journey_pattern.js.coffee
+++ b/app/assets/javascripts/journey_pattern.js.coffee
@@ -3,6 +3,7 @@ jQuery ->
if (event.type == 'mouseenter')
if event.target.id.match(/^stop_point_(\w+)$/)
stopAreaId = $("#"+event.target.id+" a").attr('href').match(/\d+$/)[0]
+ console.log(stopAreaId)
placeMark = selectFeature.layer.getFeatureByFid( stopAreaId)
selectFeature.unselectAll()
selectFeature.select( placeMark)
@@ -11,9 +12,3 @@ jQuery ->
$(document).on("hover", '.journey_patterns.show div.stop_points .stop_point', select_stop_on_map)
- make_ajax_pagination = () ->
- $.get(this.href, null, null, 'script')
- false
-
- $(document).on("click", '.stop_points_detail .pagination a', make_ajax_pagination)
-
diff --git a/app/assets/javascripts/lines/index.js.coffee b/app/assets/javascripts/lines/index.js.coffee
new file mode 100644
index 000000000..164c0e6be
--- /dev/null
+++ b/app/assets/javascripts/lines/index.js.coffee
@@ -0,0 +1 @@
+$(".lines.index").ready ->
diff --git a/app/assets/javascripts/multiple_selection.js.coffee b/app/assets/javascripts/multiple_selection.js.coffee
index 86b260fb7..fc81fd5d0 100644
--- a/app/assets/javascripts/multiple_selection.js.coffee
+++ b/app/assets/javascripts/multiple_selection.js.coffee
@@ -3,7 +3,8 @@ jQuery ->
event.preventDefault()
$('#multiple_selection_menu div.enabled').show()
$('#multiple_selection_menu div.disabled').hide()
- $('input[type=checkbox].multiple_selection').fadeIn()
+ $('input[type=checkbox].multiple_selection').show()
+ $('.line_number').hide()
$('#multiple_selection_menu a.enable').click(enable_multiple_selection)
@@ -11,7 +12,8 @@ jQuery ->
event.preventDefault()
$('#multiple_selection_menu div.enabled').hide()
$('#multiple_selection_menu div.disabled').show()
- $('input[type=checkbox].multiple_selection').fadeOut()
+ $('input[type=checkbox].multiple_selection').hide()
+ $('.line_number').show()
$('#multiple_selection_menu a.disable').click(disable_multiple_selection)
diff --git a/app/assets/javascripts/plugins.js b/app/assets/javascripts/plugins.js
deleted file mode 100644
index 6f6a902ae..000000000
--- a/app/assets/javascripts/plugins.js
+++ /dev/null
@@ -1 +0,0 @@
-//= require_directory ./plugins
diff --git a/app/assets/javascripts/plugins/bootstrap_timepicker_activation.coffee b/app/assets/javascripts/plugins/bootstrap_timepicker_activation.coffee
new file mode 100644
index 000000000..1c40ebdb5
--- /dev/null
+++ b/app/assets/javascripts/plugins/bootstrap_timepicker_activation.coffee
@@ -0,0 +1,11 @@
+jQuery ->
+ if(!(Modernizr.inputtypes && Modernizr.inputtypes.time))
+ $('.timepicker_basic').datetimepicker({
+ pickDate: false,
+ language: $(".dropdown.languages > a > img").attr("data-locale") || 'en',
+ })
+ $('.timepicker_seconds').datetimepicker({
+ pickDate: false,
+ language: $(".dropdown.languages > a > img").attr("data-locale") || 'en',
+ useSeconds: true,
+ }) \ No newline at end of file
diff --git a/app/assets/javascripts/plugins/formtastic.qtip2.min.js b/app/assets/javascripts/plugins/formtastic.qtip2.min.js
deleted file mode 100644
index 52a1ef1f7..000000000
--- a/app/assets/javascripts/plugins/formtastic.qtip2.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-// formtastic.qtip2.min.js Copyright (C) 2012 Gyorgy Schreiber (gydotschreiberatmobilitydothu) - MIT & GPL licenses apply
-$(".inline-hints").hide();$(".inline-hints").each(function(){var input = $(this.parentNode);input.qtip({position: {at: "bottom middle", my: "top middle"},content: {text: function(api) {var hinttext = $(this)[0].lastChild.firstChild.parentElement.attributes[0].nodeName == 'class' && $(this)[0].lastChild.firstChild.parentElement.attributes[0].nodeValue == 'inline-errors' ? $(this)[0].children[$(this)[0].children.length-2].firstChild.wholeText : $(this)[0].lastChild.firstChild.wholeText;return hinttext;}}});});
diff --git a/app/assets/javascripts/plugins/jquery.qtip.min.js b/app/assets/javascripts/plugins/jquery.qtip.min.js
deleted file mode 100644
index 1ed034ee3..000000000
--- a/app/assets/javascripts/plugins/jquery.qtip.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! qTip2 v2.0.1 (includes: svg ajax tips modal viewport imagemap ie6 / basic css3) | qtip2.com | Licensed MIT, GPL | Mon Dec 31 2012 14:55:17 */
-(function(e,t,n){(function(e){"use strict";typeof define=="function"&&define.amd?define(["jquery"],e):jQuery&&!jQuery.fn.qtip&&e(jQuery)})(function(r){function _(n){E={pageX:n.pageX,pageY:n.pageY,type:"mousemove",scrollX:e.pageXOffset||t.body.scrollLeft||t.documentElement.scrollLeft,scrollY:e.pageYOffset||t.body.scrollTop||t.documentElement.scrollTop}}function D(e){var t=function(e){return e===o||"object"!=typeof e},n=function(e){return!r.isFunction(e)&&(!e&&!e.attr||e.length<1||"object"==typeof e&&!e.jquery&&!e.then)};if(!e||"object"!=typeof e)return s;t(e.metadata)&&(e.metadata={type:e.metadata});if("content"in e){if(t(e.content)||e.content.jquery)e.content={text:e.content};n(e.content.text||s)&&(e.content.text=s),"title"in e.content&&(t(e.content.title)&&(e.content.title={text:e.content.title}),n(e.content.title.text||s)&&(e.content.title.text=s))}return"position"in e&&t(e.position)&&(e.position={my:e.position,at:e.position}),"show"in e&&t(e.show)&&(e.show=e.show.jquery?{target:e.show}:{event:e.show}),"hide"in e&&t(e.hide)&&(e.hide=e.hide.jquery?{target:e.hide}:{event:e.hide}),"style"in e&&t(e.style)&&(e.style={classes:e.style}),r.each(w,function(){this.sanitize&&this.sanitize(e)}),e}function P(u,a,f,l){function q(e){var t=0,n,r=a,i=e.split(".");while(r=r[i[t++]])t<i.length&&(n=r);return[n||a,i.pop()]}function R(e){return T.concat("").join(e?"-"+e+" ":" ")}function U(){var e=a.style.widget,t=H.hasClass(j);H.removeClass(j),j=e?"ui-state-disabled":"qtip-disabled",H.toggleClass(j,t),H.toggleClass("ui-helper-reset "+R(),e).toggleClass(C,a.style.def&&!e),F.content&&F.content.toggleClass(R("content"),e),F.titlebar&&F.titlebar.toggleClass(R("header"),e),F.button&&F.button.toggleClass(S+"-icon",!e)}function z(e){F.title&&(F.titlebar.remove(),F.titlebar=F.title=F.button=o,e!==s&&m.reposition())}function W(){var e=a.content.title.button,t=typeof e=="string",n=t?e:"Close tooltip";F.button&&F.button.remove(),e.jquery?F.button=e:F.button=r("<a />",{"class":"qtip-close "+(a.style.widget?"":S+"-icon"),title:n,"aria-label":n}).prepend(r("<span />",{"class":"ui-icon ui-icon-close",html:"&times;"})),F.button.appendTo(F.titlebar||H).attr("role","button").click(function(e){return H.hasClass(j)||m.hide(e),s})}function X(){var e=y+"-title";F.titlebar&&z(),F.titlebar=r("<div />",{"class":S+"-titlebar "+(a.style.widget?R("header"):"")}).append(F.title=r("<div />",{id:e,"class":S+"-title","aria-atomic":i})).insertBefore(F.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(e){r(this).toggleClass("ui-state-active ui-state-focus",e.type.substr(-4)==="down")}).delegate(".qtip-close","mouseover mouseout",function(e){r(this).toggleClass("ui-state-hover",e.type==="mouseover")}),a.content.title.button&&W()}function V(e){var t=F.button;if(!m.rendered)return s;e?W():t.remove()}function J(e,t){var n=F.title;if(!m.rendered||!e)return s;r.isFunction(e)&&(e=e.call(u,I.event,m));if(e===s||!e&&e!=="")return z(s);e.jquery&&e.length>0?n.empty().append(e.css({display:"block"})):n.html(e),t!==s&&m.rendered&&H[0].offsetWidth>0&&m.reposition(I.event)}function K(e){e&&r.isFunction(e.done)&&e.done(function(e){Q(e,null,s)})}function Q(e,t,i){function f(e){function a(n){n&&(delete u[n.src],clearTimeout(m.timers.img[n.src]),r(n).unbind(B)),r.isEmptyObject(u)&&(t!==s&&m.reposition(I.event),e())}var i,u={};if((i=o.find("img[src]:not([height]):not([width])")).length===0)return a();i.each(function(e,t){if(u[t.src]!==n)return;var i=0,s=3;(function o(){if(t.height||t.width||i>s)return a(t);i+=1,m.timers.img[t.src]=setTimeout(o,700)})(),r(t).bind("error"+B+" load"+B,function(){a(this)}),u[t.src]=t})}var o=F.content;return!m.rendered||!e?s:(r.isFunction(e)&&(e=e.call(u,I.event,m)||""),i!==s&&K(a.content.deferred),e.jquery&&e.length>0?o.empty().append(e.css({display:"block"})):o.html(e),m.rendered<0?H.queue("fx",f):(P=0,f(r.noop)),m)}function G(){function h(e){if(H.hasClass(j))return s;clearTimeout(m.timers.show),clearTimeout(m.timers.hide);var t=function(){m.toggle(i,e)};a.show.delay>0?m.timers.show=setTimeout(t,a.show.delay):t()}function p(e){if(H.hasClass(j)||A||P)return s;var t=r(e.relatedTarget||e.target),i=t.closest(N)[0]===H[0],u=t[0]===o.show[0];clearTimeout(m.timers.show),clearTimeout(m.timers.hide);if(n.target==="mouse"&&i||a.hide.fixed&&/mouse(out|leave|move)/.test(e.type)&&(i||u)){try{e.preventDefault(),e.stopImmediatePropagation()}catch(f){}return}a.hide.delay>0?m.timers.hide=setTimeout(function(){m.hide(e)},a.hide.delay):m.hide(e)}function d(e){if(H.hasClass(j))return s;clearTimeout(m.timers.inactive),m.timers.inactive=setTimeout(function(){m.hide(e)},a.hide.inactive)}function v(e){m.rendered&&H[0].offsetWidth>0&&m.reposition(e)}var n=a.position,o={show:a.show.target,hide:a.hide.target,viewport:r(n.viewport),document:r(t),body:r(t.body),window:r(e)},l={show:r.trim(""+a.show.event).split(" "),hide:r.trim(""+a.hide.event).split(" ")},c=r.browser.msie&&parseInt(r.browser.version,10)===6;H.bind("mouseenter"+B+" mouseleave"+B,function(e){var t=e.type==="mouseenter";t&&m.focus(e),H.toggleClass(L,t)}),/mouse(out|leave)/i.test(a.hide.event)&&a.hide.leave==="window"&&o.window.bind("mouseout"+B+" blur"+B,function(e){!/select|option/.test(e.target.nodeName)&&!e.relatedTarget&&m.hide(e)}),a.hide.fixed?(o.hide=o.hide.add(H),H.bind("mouseover"+B,function(){H.hasClass(j)||clearTimeout(m.timers.hide)})):/mouse(over|enter)/i.test(a.show.event)&&o.hide.bind("mouseleave"+B,function(e){clearTimeout(m.timers.show)}),(""+a.hide.event).indexOf("unfocus")>-1&&n.container.closest("html").bind("mousedown"+B+" touchstart"+B,function(e){var t=r(e.target),n=m.rendered&&!H.hasClass(j)&&H[0].offsetWidth>0,i=t.parents(N).filter(H[0]).length>0;t[0]!==u[0]&&t[0]!==H[0]&&!i&&!u.has(t[0]).length&&!t.attr("disabled")&&m.hide(e)}),"number"==typeof a.hide.inactive&&(o.show.bind("qtip-"+f+"-inactive",d),r.each(b.inactiveEvents,function(e,t){o.hide.add(F.tooltip).bind(t+B+"-inactive",d)})),r.each(l.hide,function(e,t){var n=r.inArray(t,l.show),i=r(o.hide);n>-1&&i.add(o.show).length===i.length||t==="unfocus"?(o.show.bind(t+B,function(e){H[0].offsetWidth>0?p(e):h(e)}),delete l.show[n]):o.hide.bind(t+B,p)}),r.each(l.show,function(e,t){o.show.bind(t+B,h)}),"number"==typeof a.hide.distance&&o.show.add(H).bind("mousemove"+B,function(e){var t=I.origin||{},n=a.hide.distance,r=Math.abs;(r(e.pageX-t.pageX)>=n||r(e.pageY-t.pageY)>=n)&&m.hide(e)}),n.target==="mouse"&&(o.show.bind("mousemove"+B,_),n.adjust.mouse&&(a.hide.event&&(H.bind("mouseleave"+B,function(e){(e.relatedTarget||e.target)!==o.show[0]&&m.hide(e)}),F.target.bind("mouseenter"+B+" mouseleave"+B,function(e){I.onTarget=e.type==="mouseenter"})),o.document.bind("mousemove"+B,function(e){m.rendered&&I.onTarget&&!H.hasClass(j)&&H[0].offsetWidth>0&&m.reposition(e||E)}))),(n.adjust.resize||o.viewport.length)&&(r.event.special.resize?o.viewport:o.window).bind("resize"+B,v),o.window.bind("scroll"+B,v)}function Y(){var n=[a.show.target[0],a.hide.target[0],m.rendered&&F.tooltip[0],a.position.container[0],a.position.viewport[0],a.position.container.closest("html")[0],e,t];m.rendered?r([]).pushStack(r.grep(n,function(e){return typeof e=="object"})).unbind(B):a.show.target.unbind(B+"-create")}var m=this,g=t.body,y=S+"-"+f,A=0,P=0,H=r(),B=".qtip-"+f,j="qtip-disabled",F,I;m.id=f,m.rendered=s,m.destroyed=s,m.elements=F={target:u},m.timers={img:{}},m.options=a,m.checks={},m.plugins={},m.cache=I={event:{},target:r(),disabled:s,attr:l,onTarget:s,lastClass:""},m.checks.builtin={"^id$":function(e,t,n){var o=n===i?b.nextid:n,u=S+"-"+o;o!==s&&o.length>0&&!r("#"+u).length&&(H[0].id=u,F.content[0].id=u+"-content",F.title[0].id=u+"-title")},"^content.text$":function(e,t,n){Q(a.content.text)},"^content.deferred$":function(e,t,n){K(a.content.deferred)},"^content.title.text$":function(e,t,n){if(!n)return z();!F.title&&n&&X(),J(n)},"^content.title.button$":function(e,t,n){V(n)},"^position.(my|at)$":function(e,t,n){"string"==typeof n&&(e[t]=new w.Corner(n))},"^position.container$":function(e,t,n){m.rendered&&H.appendTo(n)},"^show.ready$":function(){m.rendered?m.toggle(i):m.render(1)},"^style.classes$":function(e,t,n){H.attr("class",S+" qtip "+n)},"^style.width|height":function(e,t,n){H.css(t,n)},"^style.widget|content.title":U,"^events.(render|show|move|hide|focus|blur)$":function(e,t,n){H[(r.isFunction(n)?"":"un")+"bind"]("tooltip"+t,n)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){var e=a.position;H.attr("tracking",e.target==="mouse"&&e.adjust.mouse),Y(),G()}},r.extend(m,{_triggerEvent:function(e,t,n){var i=r.Event("tooltip"+e);return i.originalEvent=(n?r.extend({},n):o)||I.event||o,H.trigger(i,[m].concat(t||[])),!i.isDefaultPrevented()},render:function(e){if(m.rendered)return m;var t=a.content.text,n=a.content.title,o=a.position;return r.attr(u[0],"aria-describedby",y),H=F.tooltip=r("<div/>",{id:y,"class":[S,C,a.style.classes,S+"-pos-"+a.position.my.abbrev()].join(" "),width:a.style.width||"",height:a.style.height||"",tracking:o.target==="mouse"&&o.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":s,"aria-describedby":y+"-content","aria-hidden":i}).toggleClass(j,I.disabled).data("qtip",m).appendTo(a.position.container).append(F.content=r("<div />",{"class":S+"-content",id:y+"-content","aria-atomic":i})),m.rendered=-1,A=1,n.text?(X(),r.isFunction(n.text)||J(n.text,s)):n.button&&W(),(!r.isFunction(t)||t.then)&&Q(t,s),m.rendered=i,U(),r.each(a.events,function(e,t){r.isFunction(t)&&H.bind(e==="toggle"?"tooltipshow tooltiphide":"tooltip"+e,t)}),r.each(w,function(){this.initialize==="render"&&this(m)}),G(),H.queue("fx",function(t){m._triggerEvent("render"),A=0,(a.show.ready||e)&&m.toggle(i,I.event,s),t()}),m},get:function(e){var t,n;switch(e.toLowerCase()){case"dimensions":t={height:H.outerHeight(s),width:H.outerWidth(s)};break;case"offset":t=w.offset(H,a.position.container);break;default:n=q(e.toLowerCase()),t=n[0][n[1]],t=t.precedance?t.string():t}return t},set:function(e,t){function h(e,t){var n,r,i;for(n in l)for(r in l[n])if(i=(new RegExp(r,"i")).exec(e))t.push(i),l[n][r].apply(m,t)}var n=/^position\.(my|at|adjust|target|container)|style|content|show\.ready/i,u=/^content\.(title|attr)|style/i,f=s,l=m.checks,c;return"string"==typeof e?(c=e,e={},e[c]=t):e=r.extend(i,{},e),r.each(e,function(t,i){var s=q(t.toLowerCase()),o;o=s[0][s[1]],s[0][s[1]]="object"==typeof i&&i.nodeType?r(i):i,e[t]=[s[0],s[1],i,o],f=n.test(t)||f}),D(a),A=1,r.each(e,h),A=0,m.rendered&&H[0].offsetWidth>0&&f&&m.reposition(a.position.target==="mouse"?o:I.event),m},toggle:function(e,n){function b(){e?(r.browser.msie&&H[0].style.removeAttribute("filter"),H.css("overflow",""),"string"==typeof u.autofocus&&r(u.autofocus,H).focus(),u.target.trigger("qtip-"+f+"-inactive")):H.css({display:"",visibility:"",opacity:"",left:"",top:""}),m._triggerEvent(e?"visible":"hidden")}if(n){if(/over|enter/.test(n.type)&&/out|leave/.test(I.event.type)&&a.show.target.add(n.target).length===a.show.target.length&&H.has(n.relatedTarget).length)return m;I.event=r.extend({},n)}if(!m.rendered)return e?m.render(1):m;var o=e?"show":"hide",u=a[o],l=a[e?"hide":"show"],c=a.position,h=a.content,p=H[0].offsetWidth>0,d=e||u.target.length===1,v=!n||u.target.length<2||I.target[0]===n.target,g,y;return(typeof e).search("boolean|number")&&(e=!p),!H.is(":animated")&&p===e&&v?m:m._triggerEvent(o,[90])?(r.attr(H[0],"aria-hidden",!e),e?(I.origin=r.extend({},E),m.focus(n),r.isFunction(h.text)&&Q(h.text,s),r.isFunction(h.title.text)&&J(h.title.text,s),!M&&c.target==="mouse"&&c.adjust.mouse&&(r(t).bind("mousemove.qtip",_),M=i),m.reposition(n,arguments[2]),!u.solo||r(N,u.solo).not(H).qtip("hide",r.Event("tooltipsolo"))):(clearTimeout(m.timers.show),delete I.origin,M&&!r(N+'[tracking="true"]:visible',u.solo).not(H).length&&(r(t).unbind("mousemove.qtip"),M=s),m.blur(n)),u.effect===s||d===s?(H[o](),b.call(H)):r.isFunction(u.effect)?(H.stop(1,1),u.effect.call(H,m),H.queue("fx",function(e){b(),e()})):H.fadeTo(90,e?1:0,b),e&&u.target.trigger("qtip-"+f+"-inactive"),m):m},show:function(e){return m.toggle(i,e)},hide:function(e){return m.toggle(s,e)},focus:function(e){if(!m.rendered)return m;var t=r(N),n=parseInt(H[0].style.zIndex,10),i=b.zindex+t.length,s=r.extend({},e),o;return H.hasClass(k)||m._triggerEvent("focus",[i],s)&&(n!==i&&(t.each(function(){this.style.zIndex>n&&(this.style.zIndex=this.style.zIndex-1)}),t.filter("."+k).qtip("blur",s)),H.addClass(k)[0].style.zIndex=i),m},blur:function(e){return H.removeClass(k),m._triggerEvent("blur",[H.css("zIndex")],e),m},reposition:function(n,i){if(!m.rendered||A)return m;A=1;var o=a.position.target,u=a.position,f=u.my,l=u.at,g=u.adjust,y=g.method.split(" "),b=H.outerWidth(s),S=H.outerHeight(s),x=0,T=0,N=H.css("position"),C=u.viewport,k={left:0,top:0},L=u.container,O=H[0].offsetWidth>0,M=n&&n.type==="scroll",_=r(e),D,P;if(r.isArray(o)&&o.length===2)l={x:h,y:c},k={left:o[0],top:o[1]};else if(o==="mouse"&&(n&&n.pageX||I.event.pageX))l={x:h,y:c},n=E&&E.pageX&&(g.mouse||!n||!n.pageX)?{pageX:E.pageX,pageY:E.pageY}:(!n||n.type!=="resize"&&n.type!=="scroll"?n&&n.pageX&&n.type==="mousemove"?n:!g.mouse&&I.origin&&I.origin.pageX&&a.show.distance?I.origin:n:I.event)||n||I.event||E||{},N!=="static"&&(k=L.offset()),k={left:n.pageX-k.left,top:n.pageY-k.top},g.mouse&&M&&(k.left-=E.scrollX-_.scrollLeft(),k.top-=E.scrollY-_.scrollTop());else{o==="event"&&n&&n.target&&n.type!=="scroll"&&n.type!=="resize"?I.target=r(n.target):o!=="event"&&(I.target=r(o.jquery?o:F.target)),o=I.target,o=r(o).eq(0);if(o.length===0)return m;o[0]===t||o[0]===e?(x=w.iOS?e.innerWidth:o.width(),T=w.iOS?e.innerHeight:o.height(),o[0]===e&&(k={top:(C||o).scrollTop(),left:(C||o).scrollLeft()})):w.imagemap&&o.is("area")?D=w.imagemap(m,o,l,w.viewport?y:s):w.svg&&o[0].ownerSVGElement?D=w.svg(m,o,l,w.viewport?y:s):(x=o.outerWidth(s),T=o.outerHeight(s),k=w.offset(o,L)),D&&(x=D.width,T=D.height,P=D.offset,k=D.position);if(w.iOS>3.1&&w.iOS<4.1||w.iOS>=4.3&&w.iOS<4.33||!w.iOS&&N==="fixed")k.left-=_.scrollLeft(),k.top-=_.scrollTop();k.left+=l.x===d?x:l.x===v?x/2:0,k.top+=l.y===p?T:l.y===v?T/2:0}return k.left+=g.x+(f.x===d?-b:f.x===v?-b/2:0),k.top+=g.y+(f.y===p?-S:f.y===v?-S/2:0),w.viewport?(k.adjusted=w.viewport(m,k,u,x,T,b,S),P&&k.adjusted.left&&(k.left+=P.left),P&&k.adjusted.top&&(k.top+=P.top)):k.adjusted={left:0,top:0},m._triggerEvent("move",[k,C.elem||C],n)?(delete k.adjusted,i===s||!O||isNaN(k.left)||isNaN(k.top)||o==="mouse"||!r.isFunction(u.effect)?H.css(k):r.isFunction(u.effect)&&(u.effect.call(H,m,r.extend({},k)),H.queue(function(e){r(this).css({opacity:"",height:""}),r.browser.msie&&this.style.removeAttribute("filter"),e()})),A=0,m):m},disable:function(e){return"boolean"!=typeof e&&(e=!H.hasClass(j)&&!I.disabled),m.rendered?(H.toggleClass(j,e),r.attr(H[0],"aria-disabled",e)):I.disabled=!!e,m},enable:function(){return m.disable(s)},destroy:function(){var e=u[0],t=r.attr(e,O),n=u.data("qtip");m.destroyed=i,m.rendered&&(H.stop(1,0).remove(),r.each(m.plugins,function(){this.destroy&&this.destroy()})),clearTimeout(m.timers.show),clearTimeout(m.timers.hide),Y();if(!n||m===n)r.removeData(e,"qtip"),a.suppress&&t&&(r.attr(e,"title",t),u.removeAttr(O)),u.removeAttr("aria-describedby");return u.unbind(".qtip-"+f),delete x[m.id],u}})}function H(e,n){var u,a,f,l,c,h=r(this),p=r(t.body),d=this===t?p:h,v=h.metadata?h.metadata(n.metadata):o,m=n.metadata.type==="html5"&&v?v[n.metadata.name]:o,g=h.data(n.metadata.name||"qtipopts");try{g=typeof g=="string"?r.parseJSON(g):g}catch(y){}l=r.extend(i,{},b.defaults,n,typeof g=="object"?D(g):o,D(m||v)),a=l.position,l.id=e;if("boolean"==typeof l.content.text){f=h.attr(l.content.attr);if(l.content.attr===s||!f)return s;l.content.text=f}a.container.length||(a.container=p),a.target===s&&(a.target=d),l.show.target===s&&(l.show.target=d),l.show.solo===i&&(l.show.solo=a.container.closest("body")),l.hide.target===s&&(l.hide.target=d),l.position.viewport===i&&(l.position.viewport=a.container),a.container=a.container.eq(0),a.at=new w.Corner(a.at),a.my=new w.Corner(a.my);if(r.data(this,"qtip"))if(l.overwrite)h.qtip("destroy");else if(l.overwrite===s)return s;return l.suppress&&(c=r.attr(this,"title"))&&r(this).removeAttr("title").attr(O,c).attr("title",""),u=new P(h,l,e,!!f),r.data(this,"qtip",u),h.bind("remove.qtip-"+e+" removeqtip.qtip-"+e,function(){u.destroy()}),u}function B(e){var t=this,n=e.elements.tooltip,o=e.options.content.ajax,u=b.defaults.content.ajax,a=".qtip-ajax",f=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,l=i,c=s,h;e.checks.ajax={"^content.ajax":function(e,r,i){r==="ajax"&&(o=i),r==="once"?t.init():o&&o.url?t.load():n.unbind(a)}},r.extend(t,{init:function(){return o&&o.url&&n.unbind(a)[o.once?"one":"bind"]("tooltipshow"+a,t.load),t},load:function(n){function g(){var t;if(e.destroyed)return;l=s,v&&(c=i,e.show(n.originalEvent)),(t=u.complete||o.complete)&&r.isFunction(t)&&t.apply(o.context||e,arguments)}function y(t,n,i){var s;if(e.destroyed)return;d&&"string"==typeof t&&(t=r("<div/>").append(t.replace(f,"")).find(d)),(s=u.success||o.success)&&r.isFunction(s)?s.call(o.context||e,t,n,i):e.set("content.text",t)}function b(t,n,r){if(e.destroyed||t.status===0)return;e.set("content.text",n+": "+r)}if(c){c=s;return}var a=o.url.lastIndexOf(" "),p=o.url,d,v=!o.loading&&l;if(v)try{n.preventDefault()}catch(m){}else if(n&&n.isDefaultPrevented())return t;h&&h.abort&&h.abort(),a>-1&&(d=p.substr(a),p=p.substr(0,a)),h=r.ajax(r.extend({error:u.error||b,context:e},o,{url:p,success:y,complete:g}))},destroy:function(){h&&h.abort&&h.abort(),e.destroyed=i}}),t.init()}function j(e,t,n){var r=Math.ceil(t/2),i=Math.ceil(n/2),s={bottomright:[[0,0],[t,n],[t,0]],bottomleft:[[0,0],[t,0],[0,n]],topright:[[0,n],[t,0],[t,n]],topleft:[[0,0],[0,n],[t,n]],topcenter:[[0,n],[r,0],[t,n]],bottomcenter:[[0,0],[t,0],[r,n]],rightcenter:[[0,0],[t,i],[0,n]],leftcenter:[[t,0],[t,n],[0,i]]};return s.lefttop=s.bottomright,s.righttop=s.bottomleft,s.leftbottom=s.topright,s.rightbottom=s.topleft,s[e.string()]}function F(e,t){function A(e){var t=E.is(":visible");E.show(),e(),E.toggle(t)}function O(){x.width=g.height,x.height=g.width}function M(){x.width=g.width,x.height=g.height}function _(t,r,o,f){if(!b.tip)return;var l=m.corner.clone(),w=o.adjusted,E=e.options.position.adjust.method.split(" "),x=E[0],T=E[1]||E[0],N={left:s,top:s,x:0,y:0},C,k={},L;m.corner.fixed!==i&&(x===y&&l.precedance===u&&w.left&&l.y!==v?l.precedance=l.precedance===u?a:u:x!==y&&w.left&&(l.x=l.x===v?w.left>0?h:d:l.x===h?d:h),T===y&&l.precedance===a&&w.top&&l.x!==v?l.precedance=l.precedance===a?u:a:T!==y&&w.top&&(l.y=l.y===v?w.top>0?c:p:l.y===c?p:c),l.string()!==S.corner.string()&&(S.top!==w.top||S.left!==w.left)&&m.update(l,s)),C=m.position(l,w),C[l.x]+=P(l,l.x),C[l.y]+=P(l,l.y),C.right!==n&&(C.left=-C.right),C.bottom!==n&&(C.top=-C.bottom),C.user=Math.max(0,g.offset);if(N.left=x===y&&!!w.left)l.x===v?k["margin-left"]=N.x=C["margin-left"]:(L=C.right!==n?[w.left,-C.left]:[-w.left,C.left],(N.x=Math.max(L[0],L[1]))>L[0]&&(o.left-=w.left,N.left=s),k[C.right!==n?d:h]=N.x);if(N.top=T===y&&!!w.top)l.y===v?k["margin-top"]=N.y=C["margin-top"]:(L=C.bottom!==n?[w.top,-C.top]:[-w.top,C.top],(N.y=Math.max(L[0],L[1]))>L[0]&&(o.top-=w.top,N.top=s),k[C.bottom!==n?p:c]=N.y);b.tip.css(k).toggle(!(N.x&&N.y||l.x===v&&N.y||l.y===v&&N.x)),o.left-=C.left.charAt?C.user:x!==y||N.top||!N.left&&!N.top?C.left:0,o.top-=C.top.charAt?C.user:T!==y||N.left||!N.left&&!N.top?C.top:0,S.left=w.left,S.top=w.top,S.corner=l.clone()}function D(){var t=g.corner,n=e.options.position,r=n.at,o=n.my.string?n.my.string():n.my;return t===s||o===s&&r===s?s:(t===i?m.corner=new w.Corner(o):t.string||(m.corner=new w.Corner(t),m.corner.fixed=i),S.corner=new w.Corner(m.corner.string()),m.corner.string()!=="centercenter")}function P(e,t,n){t=t?t:e[e.precedance];var r=b.titlebar&&e.y===c,i=r?b.titlebar:E,s="border-"+t+"-width",o=function(e){return parseInt(e.css(s),10)},u;return A(function(){u=(n?o(n):o(b.content)||o(i)||o(E))||0}),u}function H(e){var t=b.titlebar&&e.y===c,n=t?b.titlebar:b.content,i=r.browser.mozilla,s=i?"-moz-":r.browser.webkit?"-webkit-":"",o="border-radius-"+e.y+e.x,u="border-"+e.y+"-"+e.x+"-radius",a=function(e){return parseInt(n.css(e),10)||parseInt(E.css(e),10)},f;return A(function(){f=a(u)||a(s+u)||a(s+o)||a(o)||0}),f}function B(e){function N(e,t,n){var r=e.css(t)||p;return n&&r===e.css(n)?s:f.test(r)?s:r}var t,n,o,u=b.tip.css("cssText",""),a=e||m.corner,f=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,l="border-"+a[a.precedance]+"-color",h="background-color",p="transparent",d=" !important",y=b.titlebar,w=y&&(a.y===c||a.y===v&&u.position().top+x.height/2+g.offset<y.outerHeight(i)),S=w?y:b.content;A(function(){T.fill=N(u,h)||N(S,h)||N(b.content,h)||N(E,h)||u.css(h),T.border=N(u,l,"color")||N(S,l,"color")||N(b.content,l,"color")||N(E,l,"color")||E.css(l),r("*",u).add(u).css("cssText",h+":"+p+d+";border:0"+d+";")})}function F(e){var t=e.precedance===a,n=x[t?f:l],r=x[t?l:f],i=e.string().indexOf(v)>-1,s=n*(i?.5:1),o=Math.pow,u=Math.round,c,h,p,d=Math.sqrt(o(s,2)+o(r,2)),m=[N/s*d,N/r*d];return m[2]=Math.sqrt(o(m[0],2)-o(N,2)),m[3]=Math.sqrt(o(m[1],2)-o(N,2)),c=d+m[2]+m[3]+(i?0:m[0]),h=c/d,p=[u(h*r),u(h*n)],{height:p[t?0:1],width:p[t?1:0]}}function I(e,t,n){return"<qvml:"+e+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(t||"")+' style="behavior: url(#default#VML); '+(n||"")+'" />'}var m=this,g=e.options.style.tip,b=e.elements,E=b.tooltip,S={top:0,left:0},x={width:g.width,height:g.height},T={},N=g.border||0,C=".qtip-tip",k=!!(r("<canvas />")[0]||{}).getContext,L;m.corner=o,m.mimic=o,m.border=N,m.offset=g.offset,m.size=x,e.checks.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){m.init()||m.destroy(),e.reposition()},"^style.tip.(height|width)$":function(){x={width:g.width,height:g.height},m.create(),m.update(),e.reposition()},"^content.title.text|style.(classes|widget)$":function(){b.tip&&b.tip.length&&m.update()}},r.extend(m,{init:function(){var e=D()&&(k||r.browser.msie);return e&&(m.create(),m.update(),E.unbind(C).bind("tooltipmove"+C,_)),e},create:function(){var e=x.width,t=x.height,n;b.tip&&b.tip.remove(),b.tip=r("<div />",{"class":"qtip-tip"}).css({width:e,height:t}).prependTo(E),k?r("<canvas />").appendTo(b.tip)[0].getContext("2d").save():(n=I("shape",'coordorigin="0,0"',"position:absolute;"),b.tip.html(n+n),r("*",b.tip).bind("click mousedown",function(e){e.stopPropagation()}))},update:function(e,t){var n=b.tip,f=n.children(),l=x.width,y=x.height,C=g.mimic,L=Math.round,A,_,D,H,q;e||(e=S.corner||m.corner),C===s?C=e:(C=new w.Corner(C),C.precedance=e.precedance,C.x==="inherit"?C.x=e.x:C.y==="inherit"?C.y=e.y:C.x===C.y&&(C[e.precedance]=e[e.precedance])),A=C.precedance,e.precedance===u?O():M(),b.tip.css({width:l=x.width,height:y=x.height}),B(e),T.border!=="transparent"?(N=P(e,o),g.border===0&&N>0&&(T.fill=T.border),m.border=N=g.border!==i?g.border:N):m.border=N=0,D=j(C,l,y),m.size=q=F(e),n.css(q).css("line-height",q.height+"px"),e.precedance===a?H=[L(C.x===h?N:C.x===d?q.width-l-N:(q.width-l)/2),L(C.y===c?q.height-y:0)]:H=[L(C.x===h?q.width-l:0),L(C.y===c?N:C.y===p?q.height-y-N:(q.height-y)/2)],k?(f.attr(q),_=f[0].getContext("2d"),_.restore(),_.save(),_.clearRect(0,0,3e3,3e3),_.fillStyle=T.fill,_.strokeStyle=T.border,_.lineWidth=N*2,_.lineJoin="miter",_.miterLimit=100,_.translate(H[0],H[1]),_.beginPath(),_.moveTo(D[0][0],D[0][1]),_.lineTo(D[1][0],D[1][1]),_.lineTo(D[2][0],D[2][1]),_.closePath(),N&&(E.css("background-clip")==="border-box"&&(_.strokeStyle=T.fill,_.stroke()),_.strokeStyle=T.border,_.stroke()),_.fill()):(D="m"+D[0][0]+","+D[0][1]+" l"+D[1][0]+","+D[1][1]+" "+D[2][0]+","+D[2][1]+" xe",H[2]=N&&/^(r|b)/i.test(e.string())?parseFloat(r.browser.version,10)===8?2:1:0,f.css({coordsize:l+N+" "+(y+N),antialias:""+(C.string().indexOf(v)>-1),left:H[0],top:H[1],width:l+N,height:y+N}).each(function(e){var t=r(this);t[t.prop?"prop":"attr"]({coordsize:l+N+" "+(y+N),path:D,fillcolor:T.fill,filled:!!e,stroked:!e}).toggle(!!N||!!e),!e&&t.html()===""&&t.html(I("stroke",'weight="'+N*2+'px" color="'+T.border+'" miterlimit="1000" joinstyle="miter"'))})),t!==s&&m.position(e)},position:function(e){var t=b.tip,n={},i=Math.max(0,g.offset),o,p,d;return g.corner===s||!t?s:(e=e||m.corner,o=e.precedance,p=F(e),d=[e.x,e.y],o===u&&d.reverse(),r.each(d,function(t,r){var s,u,d;r===v?(s=o===a?h:c,n[s]="50%",n["margin-"+s]=-Math.round(p[o===a?f:l]/2)+i):(s=P(e,r),u=P(e,r,b.content),d=H(e),n[r]=t?u:i+(d>s?d:-s))}),n[e[o]]-=p[o===u?f:l],t.css({top:"",bottom:"",left:"",right:"",margin:""}).css(n),n)},destroy:function(){b.tip&&b.tip.remove(),b.tip=!1,E.unbind(C)}}),m.init()}function I(n){function y(){m=r(v,f).not("[disabled]").map(function(){return typeof this.focus=="function"?this:null})}function b(e){m.length<1&&e.length?e.not("body").blur():m.first().focus()}function E(e){var t=r(e.target),n=t.closest(".qtip"),i;i=n.length<1?s:parseInt(n[0].style.zIndex,10)>parseInt(f[0].style.zIndex,10),!i&&r(e.target).closest(N)[0]!==f[0]&&b(t)}var o=this,u=n.options.show.modal,a=n.elements,f=a.tooltip,l="#qtip-overlay",c=".qtipmodal",h=c+n.id,p="is-modal-qtip",d=r(t.body),v=w.modal.focusable.join(","),m={},g;n.checks.modal={"^show.modal.(on|blur)$":function(){o.init(),a.overlay.toggle(f.is(":visible"))},"^content.text$":function(){y()}},r.extend(o,{init:function(){return u.on?(g=o.create(),f.attr(p,i).css("z-index",w.modal.zindex+r(N+"["+p+"]").length).unbind(c).unbind(h).bind("tooltipshow"+c+" tooltiphide"+c,function(e,t,n){var i=e.originalEvent;if(e.target===f[0])if(i&&e.type==="tooltiphide"&&/mouse(leave|enter)/.test(i.type)&&r(i.relatedTarget).closest(g[0]).length)try{e.preventDefault()}catch(s){}else(!i||i&&!i.solo)&&o[e.type.replace("tooltip","")](e,n)}).bind("tooltipfocus"+c,function(e){if(e.isDefaultPrevented()||e.target!==f[0])return;var t=r(N).filter("["+p+"]"),n=w.modal.zindex+t.length,i=parseInt(f[0].style.zIndex,10);g[0].style.zIndex=n-2,t.each(function(){this.style.zIndex>i&&(this.style.zIndex-=1)}),t.end().filter("."+k).qtip("blur",e.originalEvent),f.addClass(k)[0].style.zIndex=n;try{e.preventDefault()}catch(s){}}).bind("tooltiphide"+c,function(e){e.target===f[0]&&r("["+p+"]").filter(":visible").not(f).last().qtip("focus",e)}),u.escape&&r(t).unbind(h).bind("keydown"+h,function(e){e.keyCode===27&&f.hasClass(k)&&n.hide(e)}),u.blur&&a.overlay.unbind(h).bind("click"+h,function(e){f.hasClass(k)&&n.hide(e)}),y(),o):o},create:function(){function i(){g.css({height:n.height(),width:n.width()})}var t=r(l),n=r(e);return t.length?a.overlay=t.insertAfter(r(N).last()):(g=a.overlay=r("<div />",{id:l.substr(1),html:"<div></div>",mousedown:function(){return s}}).hide().insertAfter(r(N).last()),n.unbind(c).bind("resize"+c,i),i(),g)},toggle:function(e,t,n){if(e&&e.isDefaultPrevented())return o;var a=u.effect,l=t?"show":"hide",c=g.is(":visible"),v=r("["+p+"]").filter(":visible").not(f),m;return g||(g=o.create()),g.is(":animated")&&c===t&&g.data("toggleState")!==s||!t&&v.length?o:(t?(g.css({left:0,top:0}),g.toggleClass("blurs",u.blur),u.stealfocus!==s&&(d.bind("focusin"+h,E),b(r("body :focus")))):d.unbind("focusin"+h),g.stop(i,s).data("toggleState",t),r.isFunction(a)?a.call(g,t):a===s?g[l]():g.fadeTo(parseInt(n,10)||90,t?1:0,function(){t||r(this).hide()}),t||g.queue(function(e){g.css({left:"",top:""}).removeData("toggleState"),e()}),o)},show:function(e,t){return o.toggle(e,i,t)},hide:function(e,t){return o.toggle(e,s,t)},destroy:function(){var e=g;return e&&(e=r("["+p+"]").not(f).length<1,e?(a.overlay.remove(),r(t).unbind(c)):a.overlay.unbind(c+n.id),d.unbind("focusin"+h)),f.removeAttr(p).unbind(c)}}),o.init()}function q(n){var o=this,u=n.elements,a=n.options,c=u.tooltip,h=".ie6-"+n.id,p=r("select, object").length<1,d=0,v=s,m;n.checks.ie6={"^content|style$":function(e,t,n){redraw()}},r.extend(o,{init:function(){var n=r(e),s;p&&(u.bgiframe=r('<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>'),u.bgiframe.appendTo(c),c.bind("tooltipmove"+h,o.adjustBGIFrame)),m=r("<div/>",{id:"qtip-rcontainer"}).appendTo(t.body),o.redraw(),u.overlay&&!v&&(s=function(){u.overlay[0].style.top=n.scrollTop()+"px"},n.bind("scroll.qtip-ie6, resize.qtip-ie6",s),s(),u.overlay.addClass("qtipmodal-ie6fix"),v=i)},adjustBGIFrame:function(){var e=n.get("dimensions"),t=n.plugins.tip,r=u.tip,i,s;s=parseInt(c.css("border-left-width"),10)||0,s={left:-s,top:-s},t&&r&&(i=t.corner.precedance==="x"?["width","left"]:["height","top"],s[i[1]]-=r[i[0]]()),u.bgiframe.css(s).css(e)},redraw:function(){if(n.rendered<1||d)return o;var e=a.style,t=a.position.container,r,i,s,u;return d=1,e.height&&c.css(l,e.height),e.width?c.css(f,e.width):(c.css(f,"").appendTo(m),i=c.width(),i%2<1&&(i+=1),s=c.css("max-width")||"",u=c.css("min-width")||"",r=(s+u).indexOf("%")>-1?t.width()/100:0,s=(s.indexOf("%")>-1?r:1)*parseInt(s,10)||i,u=(u.indexOf("%")>-1?r:1)*parseInt(u,10)||0,i=s+u?Math.min(Math.max(i,u),s):i,c.css(f,Math.round(i)).appendTo(t)),d=0,o},destroy:function(){p&&u.bgiframe.remove(),c.unbind(h)}}),o.init()}var i=!0,s=!1,o=null,u="x",a="y",f="width",l="height",c="top",h="left",p="bottom",d="right",v="center",m="flip",g="flipinvert",y="shift",b,w,E,S="qtip",x={},T=["ui-widget","ui-tooltip"],N="div.qtip."+S,C=S+"-default",k=S+"-focus",L=S+"-hover",A="_replacedByqTip",O="oldtitle",M;b=r.fn.qtip=function(e,t,u){var a=(""+e).toLowerCase(),f=o,l=r.makeArray(arguments).slice(1),c=l[l.length-1],h=this[0]?r.data(this[0],"qtip"):o;if(!arguments.length&&h||a==="api")return h;if("string"==typeof e)return this.each(function(){var e=r.data(this,"qtip");if(!e)return i;c&&c.timeStamp&&(e.cache.event=c);if(a!=="option"&&a!=="options"||!t)e[a]&&e[a].apply(e[a],l);else{if(!r.isPlainObject(t)&&u===n)return f=e.get(t),s;e.set(t,u)}}),f!==o?f:this;if("object"==typeof e||!arguments.length)return h=D(r.extend(i,{},e)),b.bind.call(this,h,c)},b.bind=function(e,t){return this.each(function(o){function p(e){function t(){c.render(typeof e=="object"||u.show.ready),a.show.add(a.hide).unbind(l)}if(c.cache.disabled)return s;c.cache.event=r.extend({},e),c.cache.target=e?r(e.target):[n],u.show.delay>0?(clearTimeout(c.timers.show),c.timers.show=setTimeout(t,u.show.delay),f.show!==f.hide&&a.hide.bind(f.hide,function(){clearTimeout(c.timers.show)})):t()}var u,a,f,l,c,h;h=r.isArray(e.id)?e.id[o]:e.id,h=!h||h===s||h.length<1||x[h]?b.nextid++:x[h]=h,l=".qtip-"+h+"-create",c=H.call(this,h,e);if(c===s)return i;u=c.options,r.each(w,function(){this.initialize==="initialize"&&this(c)}),a={show:u.show.target,hide:u.hide.target},f={show:r.trim(""+u.show.event).replace(/ /g,l+" ")+l,hide:r.trim(""+u.hide.event).replace(/ /g,l+" ")+l},/mouse(over|enter)/i.test(f.show)&&!/mouse(out|leave)/i.test(f.hide)&&(f.hide+=" mouseleave"+l),a.show.bind("mousemove"+l,function(e){_(e),c.cache.onTarget=i}),a.show.bind(f.show,p),(u.show.ready||u.prerender)&&p(t)}).attr("data-hasqtip",i)},w=b.plugins={Corner:function(e){e=(""+e).replace(/([A-Z])/," $1").replace(/middle/gi,v).toLowerCase(),this.x=(e.match(/left|right/i)||e.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(e.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase();var t=e.charAt(0);this.precedance=t==="t"||t==="b"?a:u,this.string=function(){return this.precedance===a?this.y+this.x:this.x+this.y},this.abbrev=function(){var e=this.x.substr(0,1),t=this.y.substr(0,1);return e===t?e:this.precedance===a?t+e:e+t},this.invertx=function(e){this.x=this.x===h?d:this.x===d?h:e||this.x},this.inverty=function(e){this.y=this.y===c?p:this.y===p?c:e||this.y},this.clone=function(){return{x:this.x,y:this.y,precedance:this.precedance,string:this.string,abbrev:this.abbrev,clone:this.clone,invertx:this.invertx,inverty:this.inverty}}},offset:function(e,n){function c(e,t){i.left+=t*e.scrollLeft(),i.top+=t*e.scrollTop()}var i=e.offset(),s=e.closest("body"),o=r.browser.msie&&t.compatMode!=="CSS1Compat",u=n,a,f,l;if(u){do u.css("position")!=="static"&&(f=u.position(),i.left-=f.left+(parseInt(u.css("borderLeftWidth"),10)||0)+(parseInt(u.css("marginLeft"),10)||0),i.top-=f.top+(parseInt(u.css("borderTopWidth"),10)||0)+(parseInt(u.css("marginTop"),10)||0),!a&&(l=u.css("overflow"))!=="hidden"&&l!=="visible"&&(a=u));while((u=r(u[0].offsetParent)).length);(a&&a[0]!==s[0]||o)&&c(a||s,1)}return i},iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||s,fn:{attr:function(e,t){if(this.length){var n=this[0],i="title",s=r.data(n,"qtip");if(e===i&&s&&"object"==typeof s&&s.options.suppress)return arguments.length<2?r.attr(n,O):(s&&s.options.content.attr===i&&s.cache.attr&&s.set("content.text",t),this.attr(O,t))}return r.fn["attr"+A].apply(this,arguments)},clone:function(e){var t=r([]),n="title",i=r.fn["clone"+A].apply(this,arguments);return e||i.filter("["+O+"]").attr("title",function(){return r.attr(this,O)}).removeAttr(O),i}}},r.each(w.fn,function(e,t){if(!t||r.fn[e+A])return i;var n=r.fn[e+A]=r.fn[e];r.fn[e]=function(){return t.apply(this,arguments)||n.apply(this,arguments)}}),r.ui||(r["cleanData"+A]=r.cleanData,r.cleanData=function(e){for(var t=0,i;(i=e[t])!==n;t++)try{r(i).triggerHandler("removeqtip")}catch(s){}r["cleanData"+A](e)}),b.version="2.0.1",b.nextid=0,b.inactiveEvents="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),b.zindex=15e3,b.defaults={prerender:s,id:s,overwrite:i,suppress:i,content:{text:i,attr:"title",deferred:s,title:{text:s,button:s}},position:{my:"top left",at:"bottom right",target:s,container:s,viewport:s,adjust:{x:0,y:0,mouse:i,resize:i,method:"flipinvert flipinvert"},effect:function(e,t,n){r(this).animate(t,{duration:200,queue:s})}},show:{target:s,event:"mouseenter",effect:i,delay:90,solo:s,ready:s,autofocus:s},hide:{target:s,event:"mouseleave",effect:i,delay:0,fixed:s,inactive:s,leave:"window",distance:s},style:{classes:"",widget:s,width:s,height:s,def:i},events:{render:o,move:o,show:o,hide:o,toggle:o,visible:o,hidden:o,focus:o,blur:o}},w.svg=function(e,n,i,s){var o=r(t),u=n[0],a={width:0,height:0,position:{top:1e10,left:1e10}},f,l,c,h,p;while(!u.getBBox)u=u.parentNode;if(u.getBBox&&u.parentNode){f=u.getBBox(),l=u.getScreenCTM(),c=u.farthestViewportElement||u;if(!c.createSVGPoint)return a;h=c.createSVGPoint(),h.x=f.x,h.y=f.y,p=h.matrixTransform(l),a.position.left=p.x,a.position.top=p.y,h.x+=f.width,h.y+=f.height,p=h.matrixTransform(l),a.width=p.x-a.position.left,a.height=p.y-a.position.top,a.position.left+=o.scrollLeft(),a.position.top+=o.scrollTop()}return a},w.ajax=function(e){var t=e.plugins.ajax;return"object"==typeof t?t:e.plugins.ajax=new B(e)},w.ajax.initialize="render",w.ajax.sanitize=function(e){var t=e.content,n;t&&"ajax"in t&&(n=t.ajax,typeof n!="object"&&(n=e.content.ajax={url:n}),"boolean"!=typeof n.once&&n.once&&(n.once=!!n.once))},r.extend(i,b.defaults,{content:{ajax:{loading:i,once:i}}}),w.tip=function(e){var t=e.plugins.tip;return"object"==typeof t?t:e.plugins.tip=new F(e)},w.tip.initialize="render",w.tip.sanitize=function(e){var t=e.style,n;t&&"tip"in t&&(n=e.style.tip,typeof n!="object"&&(e.style.tip={corner:n}),/string|boolean/i.test(typeof n.corner)||(n.corner=i),typeof n.width!="number"&&delete n.width,typeof n.height!="number"&&delete n.height,typeof n.border!="number"&&n.border!==i&&delete n.border,typeof n.offset!="number"&&delete n.offset)},r.extend(i,b.defaults,{style:{tip:{corner:i,mimic:s,width:6,height:6,border:i,offset:0}}}),w.modal=function(e){var t=e.plugins.modal;return"object"==typeof t?t:e.plugins.modal=new I(e)},w.modal.initialize="render",w.modal.sanitize=function(e){e.show&&(typeof e.show.modal!="object"?e.show.modal={on:!!e.show.modal}:typeof e.show.modal.on=="undefined"&&(e.show.modal.on=i))},w.modal.zindex=b.zindex-200,w.modal.focusable=["a[href]","area[href]","input","select","textarea","button","iframe","object","embed","[tabindex]","[contenteditable]"],r.extend(i,b.defaults,{show:{modal:{on:s,effect:i,blur:i,stealfocus:i,escape:i}}}),w.viewport=function(n,r,i,s,o,m,b){function j(e,t,n,i,s,o,u,a,f){var l=r[s],c=x[e],h=T[e],p=n===y,d=-O.offset[s]+A.offset[s]+A["scroll"+s],m=c===s?f:c===o?-f:-f/2,b=h===s?a:h===o?-a:-a/2,w=_&&_.size?_.size[u]||0:0,E=_&&_.corner&&_.corner.precedance===e&&!p?w:0,S=d-l+E,N=l+f-A[u]-d+E,C=m-(x.precedance===e||c===x[t]?b:0)-(h===v?a/2:0);return p?(E=_&&_.corner&&_.corner.precedance===t?w:0,C=(c===s?1:-1)*m-E,r[s]+=S>0?S:N>0?-N:0,r[s]=Math.max(-O.offset[s]+A.offset[s]+(E&&_.corner[e]===v?_.offset:0),l-C,Math.min(Math.max(-O.offset[s]+A.offset[s]+A[u],l+C),r[s]))):(i*=n===g?2:0,S>0&&(c!==s||N>0)?(r[s]-=C+i,H["invert"+e](s)):N>0&&(c!==o||S>0)&&(r[s]-=(c===v?-C:C)+i,H["invert"+e](o)),r[s]<d&&-r[s]>N&&(r[s]=l,H=x.clone())),r[s]-l}var w=i.target,E=n.elements.tooltip,x=i.my,T=i.at,N=i.adjust,C=N.method.split(" "),k=C[0],L=C[1]||C[0],A=i.viewport,O=i.container,M=n.cache,_=n.plugins.tip,D={left:0,top:0},P,H,B;if(!A.jquery||w[0]===e||w[0]===t.body||N.method==="none")return D;P=E.css("position")==="fixed",A={elem:A,height:A[(A[0]===e?"h":"outerH")+"eight"](),width:A[(A[0]===e?"w":"outerW")+"idth"](),scrollleft:P?0:A.scrollLeft(),scrolltop:P?0:A.scrollTop(),offset:A.offset()||{left:0,top:0}},O={elem:O,scrollLeft:O.scrollLeft(),scrollTop:O.scrollTop(),offset:O.offset()||{left:0,top:0}};if(k!=="shift"||L!=="shift")H=x.clone();return D={left:k!=="none"?j(u,a,k,N.x,h,d,f,s,m):0,top:L!=="none"?j(a,u,L,N.y,c,p,l,o,b):0},H&&M.lastClass!==(B=S+"-pos-"+H.abbrev())&&E.removeClass(n.cache.lastClass).addClass(n.cache.lastClass=B),D},w.imagemap=function(e,t,n,i){function E(e,t,n){var r=0,i=1,s=1,o=0,u=0,a=e.width,f=e.height;while(a>0&&f>0&&i>0&&s>0){a=Math.floor(a/2),f=Math.floor(f/2),n.x===h?i=a:n.x===d?i=e.width-a:i+=Math.floor(a/2),n.y===c?s=f:n.y===p?s=e.height-f:s+=Math.floor(f/2),r=t.length;while(r--){if(t.length<2)break;o=t[r][0]-e.position.left,u=t[r][1]-e.position.top,(n.x===h&&o>=i||n.x===d&&o<=i||n.x===v&&(o<i||o>e.width-i)||n.y===c&&u>=s||n.y===p&&u<=s||n.y===v&&(u<s||u>e.height-s))&&t.splice(r,1)}}return{left:t[0][0],top:t[0][1]}}t.jquery||(t=r(t));var s=e.cache.areas={},o=(t[0].shape||t.attr("shape")).toLowerCase(),u=t[0].coords||t.attr("coords"),a=u.split(","),f=[],l=r('img[usemap="#'+t.parent("map").attr("name")+'"]'),m=l.offset(),g={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10}},y=0,b=0,w;m.left+=Math.ceil((l.outerWidth()-l.width())/2),m.top+=Math.ceil((l.outerHeight()-l.height())/2);if(o==="poly"){y=a.length;while(y--)b=[parseInt(a[--y],10),parseInt(a[y+1],10)],b[0]>g.position.right&&(g.position.right=b[0]),b[0]<g.position.left&&(g.position.left=b[0]),b[1]>g.position.bottom&&(g.position.bottom=b[1]),b[1]<g.position.top&&(g.position.top=b[1]),f.push(b)}else{y=-1;while(y++<a.length)f.push(parseInt(a[y],10))}switch(o){case"rect":g={width:Math.abs(f[2]-f[0]),height:Math.abs(f[3]-f[1]),position:{left:Math.min(f[0],f[2]),top:Math.min(f[1],f[3])}};break;case"circle":g={width:f[2]+2,height:f[2]+2,position:{left:f[0],top:f[1]}};break;case"poly":g.width=Math.abs(g.position.right-g.position.left),g.height=Math.abs(g.position.bottom-g.position.top),n.abbrev()==="c"?g.position={left:g.position.left+g.width/2,top:g.position.top+g.height/2}:(s[n+u]||(g.position=E(g,f.slice(),n),i&&(i[0]==="flip"||i[1]==="flip")&&(g.offset=E(g,f.slice(),{x:n.x===h?d:n.x===d?h:v,y:n.y===c?p:n.y===p?c:v}),g.offset.left-=g.position.left,g.offset.top-=g.position.top),s[n+u]=g),g=s[n+u]),g.width=g.height=0}return g.position.left+=m.left,g.position.top+=m.top,g},w.ie6=function(e){var t=r.browser,n=e.plugins.ie6;return!t.msie||(""+t.version).charAt(0)!=="6"?s:"object"==typeof n?n:e.plugins.ie6=new q(e)},w.ie6.initialize="render"})})(window,document); \ No newline at end of file
diff --git a/app/assets/javascripts/plugins/jquery.readyselector.js b/app/assets/javascripts/plugins/jquery.readyselector.js
new file mode 100644
index 000000000..ea75e1230
--- /dev/null
+++ b/app/assets/javascripts/plugins/jquery.readyselector.js
@@ -0,0 +1,17 @@
+(function ($) {
+ var ready = $.fn.ready;
+ $.fn.ready = function (fn) {
+ if (this.context === undefined) {
+ // The $().ready(fn) case.
+ ready(fn);
+ } else if (this.selector) {
+ ready($.proxy(function(){
+ $(this.selector, this.context).each(fn);
+ }, this));
+ } else {
+ ready($.proxy(function(){
+ $(this).each(fn);
+ }, this));
+ }
+ }
+})(jQuery);
diff --git a/app/assets/javascripts/plugins/jquery.tipsy.js b/app/assets/javascripts/plugins/jquery.tipsy.js
deleted file mode 100644
index f95c063fd..000000000
--- a/app/assets/javascripts/plugins/jquery.tipsy.js
+++ /dev/null
@@ -1,258 +0,0 @@
-// tipsy, facebook style tooltips for jquery
-// version 1.0.0a
-// (c) 2008-2010 jason frame [jason@onehackoranother.com]
-// released under the MIT license
-
-(function($) {
-
- function maybeCall(thing, ctx) {
- return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
- };
-
- function isElementInDOM(ele) {
- while (ele = ele.parentNode) {
- if (ele == document) return true;
- }
- return false;
- };
-
- function Tipsy(element, options) {
- this.$element = $(element);
- this.options = options;
- this.enabled = true;
- this.fixTitle();
- };
-
- Tipsy.prototype = {
- show: function() {
- var title = this.getTitle();
- if (title && this.enabled) {
- var $tip = this.tip();
-
- $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
- $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
- $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
-
- var pos = $.extend({}, this.$element.offset(), {
- width: this.$element[0].offsetWidth,
- height: this.$element[0].offsetHeight
- });
-
- var actualWidth = $tip[0].offsetWidth,
- actualHeight = $tip[0].offsetHeight,
- gravity = maybeCall(this.options.gravity, this.$element[0]);
-
- var tp;
- switch (gravity.charAt(0)) {
- case 'n':
- tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
- break;
- case 's':
- tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
- break;
- case 'e':
- tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
- break;
- case 'w':
- tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
- break;
- }
-
- if (gravity.length == 2) {
- if (gravity.charAt(1) == 'w') {
- tp.left = pos.left + pos.width / 2 - 15;
- } else {
- tp.left = pos.left + pos.width / 2 - actualWidth + 15;
- }
- }
-
- $tip.css(tp).addClass('tipsy-' + gravity);
- $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
- if (this.options.className) {
- $tip.addClass(maybeCall(this.options.className, this.$element[0]));
- }
-
- if (this.options.fade) {
- $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
- } else {
- $tip.css({visibility: 'visible', opacity: this.options.opacity});
- }
- }
- },
-
- hide: function() {
- if (this.options.fade) {
- this.tip().stop().fadeOut(function() { $(this).remove(); });
- } else {
- this.tip().remove();
- }
- },
-
- fixTitle: function() {
- var $e = this.$element;
- if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
- $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
- }
- },
-
- getTitle: function() {
- var title, $e = this.$element, o = this.options;
- this.fixTitle();
- var title, o = this.options;
- if (typeof o.title == 'string') {
- title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
- } else if (typeof o.title == 'function') {
- title = o.title.call($e[0]);
- }
- title = ('' + title).replace(/(^\s*|\s*$)/, "");
- return title || o.fallback;
- },
-
- tip: function() {
- if (!this.$tip) {
- this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
- this.$tip.data('tipsy-pointee', this.$element[0]);
- }
- return this.$tip;
- },
-
- validate: function() {
- if (!this.$element[0].parentNode) {
- this.hide();
- this.$element = null;
- this.options = null;
- }
- },
-
- enable: function() { this.enabled = true; },
- disable: function() { this.enabled = false; },
- toggleEnabled: function() { this.enabled = !this.enabled; }
- };
-
- $.fn.tipsy = function(options) {
-
- if (options === true) {
- return this.data('tipsy');
- } else if (typeof options == 'string') {
- var tipsy = this.data('tipsy');
- if (tipsy) tipsy[options]();
- return this;
- }
-
- options = $.extend({}, $.fn.tipsy.defaults, options);
-
- function get(ele) {
- var tipsy = $.data(ele, 'tipsy');
- if (!tipsy) {
- tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
- $.data(ele, 'tipsy', tipsy);
- }
- return tipsy;
- }
-
- function enter() {
- var tipsy = get(this);
- tipsy.hoverState = 'in';
- if (options.delayIn == 0) {
- tipsy.show();
- } else {
- tipsy.fixTitle();
- setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
- }
- };
-
- function leave() {
- var tipsy = get(this);
- tipsy.hoverState = 'out';
- if (options.delayOut == 0) {
- tipsy.hide();
- } else {
- setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
- }
- };
-
- if (!options.live) this.each(function() { get(this); });
-
- if (options.trigger != 'manual') {
- var binder = options.live ? 'live' : 'bind',
- eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
- eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
- this[binder](eventIn, enter)[binder](eventOut, leave);
- }
-
- return this;
-
- };
-
- $.fn.tipsy.defaults = {
- className: null,
- delayIn: 0,
- delayOut: 0,
- fade: false,
- fallback: '',
- gravity: 'n',
- html: false,
- live: false,
- offset: 0,
- opacity: 0.8,
- title: 'title',
- trigger: 'hover'
- };
-
- $.fn.tipsy.revalidate = function() {
- $('.tipsy').each(function() {
- var pointee = $.data(this, 'tipsy-pointee');
- if (!pointee || !isElementInDOM(pointee)) {
- $(this).remove();
- }
- });
- };
-
- // Overwrite this method to provide options on a per-element basis.
- // For example, you could store the gravity in a 'tipsy-gravity' attribute:
- // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
- // (remember - do not modify 'options' in place!)
- $.fn.tipsy.elementOptions = function(ele, options) {
- return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
- };
-
- $.fn.tipsy.autoNS = function() {
- return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
- };
-
- $.fn.tipsy.autoWE = function() {
- return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
- };
-
- /**
- * yields a closure of the supplied parameters, producing a function that takes
- * no arguments and is suitable for use as an autogravity function like so:
- *
- * @param margin (int) - distance from the viewable region edge that an
- * element should be before setting its tooltip's gravity to be away
- * from that edge.
- * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
- * if there are no viewable region edges effecting the tooltip's
- * gravity. It will try to vary from this minimally, for example,
- * if 'sw' is preferred and an element is near the right viewable
- * region edge, but not the top edge, it will set the gravity for
- * that element's tooltip to be 'se', preserving the southern
- * component.
- */
- $.fn.tipsy.autoBounds = function(margin, prefer) {
- return function() {
- var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
- boundTop = $(document).scrollTop() + margin,
- boundLeft = $(document).scrollLeft() + margin,
- $this = $(this);
-
- if ($this.offset().top < boundTop) dir.ns = 'n';
- if ($this.offset().left < boundLeft) dir.ew = 'w';
- if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
- if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
-
- return dir.ns + (dir.ew ? dir.ew : '');
- }
- };
-
-})(jQuery);
diff --git a/app/assets/javascripts/plugins/jquery.ui.datepicker-i18n.js b/app/assets/javascripts/plugins/jquery.ui.datepicker-i18n.js
new file mode 100644
index 000000000..fb152408a
--- /dev/null
+++ b/app/assets/javascripts/plugins/jquery.ui.datepicker-i18n.js
@@ -0,0 +1,78 @@
+/* French initialisation for the jQuery UI date picker plugin. */
+/* Written by Keith Wood (kbwood{at}iinet.com.au) and Stéphane Nahmani (sholby@sholby.net). */
+$(function() {
+
+ $.datepicker.regional['fr'] = {
+ closeText: 'Fermer',
+ prevText: '&#x3c;Préc',
+ nextText: 'Suiv&#x3e;',
+ currentText: 'Courant',
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
+ monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
+ 'Jul','Aoû','Sep','Oct','Nov','Déc'],
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
+ dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
+ weekHeader: 'Sm',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+
+ $.datepicker.regional['en'] = {
+ closeText: 'Done',
+ prevText: 'Prev',
+ nextText: 'Next',
+ currentText: 'Today',
+ monthNames: ['January','February','March','April','May','June',
+ 'July','August','September','October','November','December'],
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+
+ if(!(Modernizr.inputtypes && Modernizr.inputtypes.date))
+ {
+ $.datepicker.setDefaults($.datepicker.regional[ "" ]);
+ $("input[type='date']").each( function(index, element)
+ {
+ $(element).datepicker(
+ {
+ dateFormat: "dd/mm/yy",
+ dayNamesShort: $.datepicker.regional[ $('html').attr('lang') ].dayNamesShort,
+ dayNames: $.datepicker.regional[ $('html').attr('lang') ].dayNames,
+ monthNamesShort: $.datepicker.regional[ $('html').attr('lang') ].monthNamesShort,
+ monthNames: $.datepicker.regional[ $('html').attr('lang') ].monthNames
+ } );
+ if ($(element).val().indexOf('/') >= 0)
+ {
+ $(element).datepicker("setDate", $.datepicker.parseDate('dd/mm/yy', $(element).val() ) );
+ }
+ else
+ {
+ $(element).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $(element).val() ) );
+ }
+ });
+
+ $("form").submit(function(event) {
+ var $this = $(event.target);
+ $this.find("input[type='date']").each(
+ function(index, element)
+ {
+ var date = $.datepicker.formatDate('yy-mm-dd', $.datepicker.parseDate('dd/mm/yy', $(element).val() ) );
+ $(element).val(date);
+ }
+ );
+ });
+ }
+
+});
diff --git a/app/assets/javascripts/plugins/tooltip.js.coffee b/app/assets/javascripts/plugins/tooltip.js.coffee
new file mode 100644
index 000000000..ca521279e
--- /dev/null
+++ b/app/assets/javascripts/plugins/tooltip.js.coffee
@@ -0,0 +1,2 @@
+jQuery ->
+ $('input').tooltip() \ No newline at end of file
diff --git a/app/assets/javascripts/route.js.coffee b/app/assets/javascripts/route.js.coffee
index b679f1893..ea2984d02 100644
--- a/app/assets/javascripts/route.js.coffee
+++ b/app/assets/javascripts/route.js.coffee
@@ -1,22 +1,10 @@
-jQuery ->
- switch_journey_patterns = (event) ->
- event.preventDefault()
- $('.routes.show .journey_patterns.content').toggle('slow')
- $('a.journey_patterns .switcher').toggle()
-
- $('.routes.show a.journey_patterns').click(switch_journey_patterns)
-
- switch_stop_points = (event) ->
- event.preventDefault()
- $('.routes.show .stop_points_detail').toggle('slow')
- $('a.stop_points .switcher').toggle()
-
- $('.routes.show a.stop_points').click(switch_stop_points)
-
+jQuery ->
select_stop_on_map = (event) ->
if (event.type == 'mouseenter')
if event.target.id.match(/^stop_point_(\w+)$/)
+ console.log(event.target.id)
stopAreaId = $("#"+event.target.id+" a").attr('href').match(/\d+$/)[0]
+ console.log(stopAreaId)
placeMark = selectFeature.layer.getFeatureByFid( stopAreaId)
selectFeature.unselectAll()
selectFeature.select( placeMark)
@@ -24,9 +12,3 @@ jQuery ->
selectFeature.unselectAll()
$(document).on("hover", '.routes.show div.stop_points .stop_point', select_stop_on_map)
-
- make_ajax_pagination = () ->
- $.get(this.href, null, null, 'script')
- false
-
- $(document).on("click", '.routes.show .stop_points_detail .pagination a', make_ajax_pagination)
diff --git a/app/assets/javascripts/stop_areas.js.coffee b/app/assets/javascripts/stop_areas.js.coffee
deleted file mode 100644
index 255c4c707..000000000
--- a/app/assets/javascripts/stop_areas.js.coffee
+++ /dev/null
@@ -1,45 +0,0 @@
-jQuery ->
- x_y_change = (event) ->
- if referential_projection != undefined
- referential_point = new OpenLayers.Geometry.Point($('input#stop_area_longitude').val(), $('input#stop_area_latitude').val()).transform(new OpenLayers.Projection("EPSG:4326"), referential_projection )
-
- $('input#stop_area_projection_x').val(referential_point.x)
- $('input#stop_area_projection_y').val(referential_point.y)
-
- feature = map.getLayersByName("stop_area")[0].getFeatureByFid($('input#stop_area_id').val())
- google_point = new OpenLayers.LonLat($('input#stop_area_longitude').val(), $('input#stop_area_latitude').val()).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
- feature.move(google_point)
- map.setCenter(google_point, 16, false, true)
-
- $('input#stop_area_longitude').change(x_y_change)
- $('input#stop_area_latitude').change(x_y_change)
-
- lon_lat_change = (event) ->
- if referential_projection != undefined
- wgs84_point = new OpenLayers.Geometry.Point($('input#stop_area_projection_x').val(), $('input#stop_area_projection_y').val()).transform(referential_projection, new OpenLayers.Projection("EPSG:4326"))
-
- $('input#stop_area_longitude').val( wgs84_point.x)
- $('input#stop_area_latitude').val( wgs84_point.y)
-
- feature = map.getLayersByName("stop_area")[0].getFeatureByFid($('input#stop_area_id').val())
- google_point = new OpenLayers.LonLat(wgs84_point.x, wgs84_point.y).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
- feature.move(google_point)
- map.setCenter(google_point, 16, false, true)
-
- $('input#stop_area_projection_x').change(lon_lat_change)
- $('input#stop_area_projection_y').change(lon_lat_change)
-
- # switch visibility of access_links
- switch_generics = (event) ->
- event.preventDefault()
- $('.stop_areas .generics.content').toggle('slow')
- $('a.generics .switcher').toggle()
-
- $('.stop_areas a.generics').click(switch_generics)
-
- switch_details = (event) ->
- event.preventDefault()
- $('.stop_areas .details.content').toggle('slow')
- $('a.details .switcher').toggle()
-
- $('.stop_areas a.details').click(switch_details)
diff --git a/app/assets/javascripts/stop_areas/edit.js.coffee b/app/assets/javascripts/stop_areas/edit.js.coffee
new file mode 100644
index 000000000..d1d945ebf
--- /dev/null
+++ b/app/assets/javascripts/stop_areas/edit.js.coffee
@@ -0,0 +1,31 @@
+$(".stop_areas.edit").ready ->
+
+ x_y_change = (event) ->
+ c = $('input#stop_area_coordinates').val().split(",")
+ if c.length == 2
+ if referential_projection != undefined
+ referential_point = new OpenLayers.Geometry.Point(c[1], c[0]).transform(new OpenLayers.Projection("EPSG:4326"), referential_projection )
+
+ $('input#stop_area_projection_xy').val(referential_point.x.toString()+","+referential_point.y.toString())
+
+ feature = map.getLayersByName("stop_area")[0].getFeatureByFid($('input#stop_area_id').val())
+ google_point = new OpenLayers.LonLat(c[1], c[0]).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
+ feature.move(google_point)
+ map.setCenter(google_point, 16, false, true)
+
+ $('input#stop_area_coordinates').change(x_y_change)
+
+ lon_lat_change = (event) ->
+ c = $('input#stop_area_projection_xy').val().split(",")
+ if c.length == 2
+ if referential_projection != undefined
+ wgs84_point = new OpenLayers.Geometry.Point(c[0], c[1]).transform(referential_projection, new OpenLayers.Projection("EPSG:4326"))
+
+ $('input#stop_area_coordinates').val( wgs84_point.y.toString()+","+wgs84_point.x)
+
+ feature = map.getLayersByName("stop_area")[0].getFeatureByFid($('input#stop_area_id').val())
+ google_point = new OpenLayers.LonLat(wgs84_point.x, wgs84_point.y).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject())
+ feature.move(google_point)
+ map.setCenter(google_point, 16, false, true)
+
+ $('input#stop_area_projection_xy').change(lon_lat_change)
diff --git a/app/assets/javascripts/stop_areas/index.js.coffee b/app/assets/javascripts/stop_areas/index.js.coffee
new file mode 100644
index 000000000..dff016666
--- /dev/null
+++ b/app/assets/javascripts/stop_areas/index.js.coffee
@@ -0,0 +1,25 @@
+$(".stop_areas.index").ready ->
+ # Autocomplete input to choose postal code in stop_areas index
+ # constructs the suggestion engine
+ country_codes = new Bloodhound(
+ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value')
+ queryTokenizer: Bloodhound.tokenizers.whitespace
+ local: $.map( JSON.parse($('#country_codes').text() ), (country_code) ->
+ value: country_code
+ )
+ )
+
+ country_codes.initialize()
+ # kicks off the loading/processing of `local` and `prefetch`
+ $('#search .typeahead').typeahead(
+ {
+ hint: true,
+ highlight: true,
+ minLength: 1
+ },
+ {
+ name: 'country_codes',
+ displayKey: 'value',
+ source: country_codes.ttAdapter(),
+ }
+ ) \ No newline at end of file
diff --git a/app/assets/javascripts/time_tables.js.coffee b/app/assets/javascripts/time_tables.js.coffee
index 27bcd39f4..ccc4fe0fe 100644
--- a/app/assets/javascripts/time_tables.js.coffee
+++ b/app/assets/javascripts/time_tables.js.coffee
@@ -1,25 +1,4 @@
jQuery ->
-# add trigger to hide/show application dates and periods
- switch_calendars = (event) ->
- event.preventDefault()
- $('.time_tables .calendars.content').toggle('slow')
- $('a.calendars .switcher').toggle()
-
- $('.time_tables a.calendars').click(switch_calendars)
-
- switch_dates = (event) ->
- event.preventDefault()
- $('.time_tables .dates.content').toggle('slow')
- $('a.dates .switcher').toggle()
-
- $('.time_tables a.dates').click(switch_dates)
-
- switch_periods = (event) ->
- event.preventDefault()
- $('.time_tables .periods.content').toggle('slow')
- $('a.periods .switcher').toggle()
-
- $('.time_tables a.periods').click(switch_periods)
# add trigger when creating new date or period entries to activate datepicker
tt_datepickerI18n = (index, element) ->
diff --git a/app/assets/javascripts/vehicle_journey.js.coffee b/app/assets/javascripts/vehicle_journey.js.coffee
index 94c45602c..54b359b7a 100644
--- a/app/assets/javascripts/vehicle_journey.js.coffee
+++ b/app/assets/javascripts/vehicle_journey.js.coffee
@@ -1,34 +1,75 @@
jQuery ->
- swap_hour_minute = ( from, to) ->
- rows = $('.vehicle_journeys tbody.journey_pattern_dependent_list tr')
- for row in rows
+ swap_hour_minute = ( from, to) ->
+ rows = $('.vehicle_journeys tbody.journey_pattern_dependent_list tr.time')
+ for row in rows
do (row) ->
$(row).find( to).find('.hour')[0].value = $(row).find( from).find('.hour')[0].value
$(row).find( to).find('.minute')[0].value = $(row).find( from).find('.minute')[0].value
- copy_departures_to_arrivals = (event) ->
+ copy_departures_to_arrivals = (event) ->
event.preventDefault()
swap_hour_minute( '.departure_time', '.arrival_time')
$(document).on("click", '.vehicle_journeys a.to_arrivals', copy_departures_to_arrivals)
- copy_arrivals_to_departures = (event) ->
+ copy_arrivals_to_departures = (event) ->
event.preventDefault()
swap_hour_minute( '.arrival_time', '.departure_time')
$(document).on("click", '.vehicle_journeys a.to_departures', copy_arrivals_to_departures)
- switch_vehicle_journey_at_stops = (event) ->
+ switch_vehicle_journey_at_stops = (event) ->
event.preventDefault()
$('.vehicle_journeys.show .vehicle_journey_at_stops.content').toggle('slow')
$('a.vehicle_journey_at_stops .switcher').toggle()
$('.vehicle_journeys.show a.vehicle_journey_at_stops').click(switch_vehicle_journey_at_stops)
- switch_time_tables = (event) ->
+ switch_time_tables = (event) ->
event.preventDefault()
$('.vehicle_journeys.show .vehicle_journey_time_tables.content').toggle('slow')
$('a.vehicle_journey_time_tables .switcher').toggle()
$('.vehicle_journeys.show a.vehicle_journey_time_tables').click(switch_time_tables)
+ convert = (val) ->
+ if (val < 10)
+ return "0" + val.toString()
+ else
+ return val.toString()
+
+ slide_to = ( col, duration) ->
+ rows = $('.vehicle_journeys tbody.journey_pattern_dependent_list .time')
+ for row in rows
+ do (row) ->
+
+ oldHour = parseInt( $( $(row).find( col).find('.hour')).val())
+ oldMinute = parseInt( $( $(row).find( col).find('.minute')).val())
+ aTime = (((oldHour - 1) * 60) + oldMinute + duration) * 60000
+ newValue = new Date(aTime)
+ $( $(row).find( col).find('select.hour')).prop( "selectedIndex", convert(newValue.getHours()))
+ $( $(row).find( col).find('select.minute')).prop( "selectedIndex", convert(newValue.getMinutes()))
+
+ slide = (event) ->
+ event.preventDefault()
+ hour = parseInt( $(".vehicle_journey_at_stops select#date_hour").val())
+ minute = parseInt( $(".vehicle_journey_at_stops select#date_minute").val())
+ departure_or_arrival = $(".departure_or_arrival option:selected").val()
+
+ selector_prefix = ".vehicle_journey_at_stops .journey_pattern_dependent_list"
+ if (departure_or_arrival == "departure")
+ vjas_hour_selector = selector_prefix + " .departure_time select.hour"
+ vjas_minute_selector = selector_prefix + " .departure_time select.minute"
+ else
+ vjas_hour_selector = selector_prefix + " .arrival_time select.hour"
+ vjas_minute_selector = selector_prefix + " .arrival_time select.minute"
+
+ vjas_hour = $( vjas_hour_selector).prop( "selectedIndex" )
+ vjas_minute = $( vjas_minute_selector).prop( "selectedIndex" )
+
+ duration = (hour - vjas_hour) * 60 + (minute - vjas_minute)
+
+ slide_to( '.departure_time', duration)
+ slide_to( '.arrival_time', duration)
+
+ $(document).on("click", '.vehicle_journeys a.slide', slide) \ No newline at end of file
diff --git a/app/assets/javascripts/vehicle_journey_import.js.coffee b/app/assets/javascripts/vehicle_journey_import.js.coffee
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/app/assets/javascripts/vehicle_journey_import.js.coffee
diff --git a/app/assets/javascripts/vehicle_journeys/index.js.coffee b/app/assets/javascripts/vehicle_journeys/index.js.coffee
new file mode 100644
index 000000000..e89c3f519
--- /dev/null
+++ b/app/assets/javascripts/vehicle_journeys/index.js.coffee
@@ -0,0 +1,7 @@
+$(".vehicle_journeys.index").ready ->
+
+ $( 'body' ).popover({html: true, trigger: "focus", selector: 'thead th button'})
+ .on("show.bs.popover", (event)->
+ $(event.target).data("bs.popover").tip().css("maxWidth", "350px"))
+
+ \ No newline at end of file
diff --git a/app/assets/javascripts/vehicle_journeys/show.js.coffee b/app/assets/javascripts/vehicle_journeys/show.js.coffee
new file mode 100644
index 000000000..103937d7b
--- /dev/null
+++ b/app/assets/javascripts/vehicle_journeys/show.js.coffee
@@ -0,0 +1,8 @@
+$(".vehicle_journeys.show").ready ->
+ clean_content = (event) ->
+ $(event.target).find('#translate_form').contents().remove()
+
+ $('#modal_translation').on( 'hide.bs.modal', clean_content )
+
+
+
diff --git a/app/assets/stylesheets/application.css.scss.erb b/app/assets/stylesheets/application.css.scss.erb
index bcea7ca92..31fa15758 100644
--- a/app/assets/stylesheets/application.css.scss.erb
+++ b/app/assets/stylesheets/application.css.scss.erb
@@ -1,38 +1,44 @@
// First import journal variables
-// @import "bootswatch/cerulean/variables";
$brand-primary: <%= ChouetteIhm::Application.config.company_theme %>;
$navbar-default-bg: $brand-primary;
$navbar-default-link-color: white;
$body-bg: #eee;
// Then bootstrap itself
-@import "bootstrap";
-
-// And finally bootswatch style itself
-// @import "bootswatch/cerulean/bootswatch";
+@import "bootstrap-sass-official/_bootstrap-sprockets.scss";
+@import "bootstrap-sass-official";
// Whatever application styles you have go last
// Modules and Variables
-// @import "modules/base";
+@import "modules/search";
+@import "modules/index_item";
+@import "modules/icons";
+@import "modules/devise";
// Partials
-// @import "partials/reset";
+@import "partials/header";
+@import "partials/footer";
// Third-party
+@import "tagmanager/tagmanager.scss";
+@import "font-awesome-sprockets";
@import "font-awesome";
@import "jquery.ui.all";
@import "morris";
@import "formtastic";
+@import 'eonasdan-bootstrap-datetimepicker';
@import "vendor/openlayers_style";
@import "vendor/openlayers_ie6-style";
@import "vendor/openlayers_google";
@import "vendor/openlayers_framedCloud";
-@import "vendor/formtastic";
-@import "vendor/jquery.qtip.min";
-@import "vendor/tipsy";
+@import "vendor/formtastic_changes";
@import "vendor/pagination";
@import "vendor/map_layers";
+@import "vendor/token-input";
+@import "vendor/typeahead";
+@import "vendor/bootstrap_changes";
+@import "vendor/simple_form";
// Main css
@import "main/*";
diff --git a/app/assets/stylesheets/main/access_points.css.scss b/app/assets/stylesheets/main/access_points.css.scss
index 7be2cb39b..af6a09ee7 100644
--- a/app/assets/stylesheets/main/access_points.css.scss
+++ b/app/assets/stylesheets/main/access_points.css.scss
@@ -3,26 +3,7 @@
// You can use Sass (SCSS) here: http://sass-lang.com/
#workspace.access_points.index
-{
- .access_point {
- /* to create multi-column index */
- width: 250px;
- float: left;
- padding-right: 10px;
-
- .access_type {
- width: 25px;
- height: 64px;
- float: left;
- margin-right: 10px;
-
-
- a {
- text-decoration: none;
- }
- }
-
- }
+{
}
#workspace.access_points.edit,#workspace.access_points.new,#workspace.access_points.create,#workspace.access_points.update
@@ -51,35 +32,41 @@
}
.access_link_pairs {
+
+ table{
+ border: 0px;
+ border-collapse: separate;
+ border-spacing: 3px;
+ }
.link {
- border: 2px solid black;
+ border: 2px solid black;
}
+
.access_point{
- float: left;
padding: 3px 15px 0px 3px;
height: 25px;
* { vertical-align:middle; }
span { margin-left: 7px; }
img { margin: 0px 5px 0px 5px;}
}
+
.stop_area{
- float: left;
padding: 3px 15px 0px 3px;
height: 25px;
* { vertical-align:middle; }
span { margin-left: 7px; }
img { margin: 0px 5px 0px 5px;}
}
-
- .info {
- font-size: 10px;
- color: #777;
- font-weight: normal;
- padding-top: 0px;
- padding-left: 45px;
- padding-right: 3px;
- padding-bottom: 3px;
+
+ .info {
+ font-size: 10px;
+ color: #777;
+ font-weight: normal;
+ padding-top: 10px;
+ padding-left: 45px;
+ padding-right: 3px;
+ padding-bottom: 3px;
}
}
diff --git a/app/assets/stylesheets/main/api_keys.css.scss b/app/assets/stylesheets/main/api_keys.css.scss
index e78c7bda0..5ac873da7 100644
--- a/app/assets/stylesheets/main/api_keys.css.scss
+++ b/app/assets/stylesheets/main/api_keys.css.scss
@@ -2,24 +2,7 @@
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
-#workspace.referentials.show
+#workspace.api_keys.show
{
-
- .api_keys {
- margin-top: 20px;
- }
-
- .api_key {
-
- /* to create multi-column index */
- width: 350px;
- padding-right: 10px;
-
- .name {
- line-height: 16px;
- float: left;
- }
-
- }
}
diff --git a/app/assets/stylesheets/main/calendar.css.scss b/app/assets/stylesheets/main/calendar.css.scss
index f9f5fd913..b8c04b6f4 100644
--- a/app/assets/stylesheets/main/calendar.css.scss
+++ b/app/assets/stylesheets/main/calendar.css.scss
@@ -10,12 +10,15 @@
white: ffffff
*/
-/* TODO */
+$selected_period_color: #ffbd2b;
+$selected_date_color: #8fc861;
+$excluded_date_color: #ff8f85;
+$overlap_date_color: #c082f4;
.year_choice{
font-size: 16px;
font-weight: bold;
- margin: 20px 0 0 0;
+ margin: 10px 0 0 0;
text-align: center;
.year{
@@ -25,80 +28,86 @@
}
-.calendar_helper{
-
+.calendar_helper{
padding: auto;
}
.calendar {
- color: white;
- text-align: center;
- margin-left: 30px;
- display: inline-table;
+ font-size: 10px;
+ color: white;
+ text-align: center;
+ margin-left: 15px;
+ display: inline-table;
}
thead tr {
- color: black;
+ color: black;
}
- th.monthName {
- font-weight: bold;
- text-align: center;
- padding-top: 1em;
- padding-bottom: 0.7em;
- color: black;
+th.monthName {
+ font-size: 12px;
+ font-weight: bold;
+ text-align: center;
+ padding-top: 1em;
+ padding-bottom: 0.7em;
+ color: black;
}
.dayName th {
- font-size: 0.7em;
- text-align: center;
- padding-top: 0.6em;
- padding-bottom: 0.3em;
- background-color: #303030;
- color: white;
- border-bottom: 1px solid white;
+ text-align: center;
+ padding-top: 0.6em;
+ padding-bottom: 0.3em;
+ background-color: #303030;
+ color: white;
+ border-bottom: 1px solid white;
}
.otherMonth {
- color: #999999;
- background-color: #4f4f5b;
- padding: 0.7em;
- border-right: 1px solid #111111;
- border-bottom: 1px solid #111111;
+ color: #999999;
+ background-color: #4f4f5b;
+ padding: 0.7em;
+ border-right: 1px solid #111111;
+ border-bottom: 1px solid #111111;
}
-.day { background-color: #333333; }
+.day {
+ background-color: #333333;
+}
-.day, .specialDay, .selected_period, .selected_date, .overlap_date {
- border-bottom: 1px solid #111111;
- padding: 0.7em;
- border-right: 1px solid #111111;
- border-bottom: 1px solid #111111;
+.day, .specialDay {
+ border-bottom: 1px solid #111111;
+ padding: 0.7em;
+ border-right: 1px solid #111111;
+ border-bottom: 1px solid #111111;
}
.specialDay { background-color: #a8a8a8 !important; }
-.selected_period { background-color: #ffbd2b !important; }
+.selected_period { background-color: $selected_period_color !important; }
-.selected_date { background-color: #8fc861 !important; }
+.selected_date { background-color: $selected_date_color !important; }
-.overlap_date { background-color: #ffbd2b !important; }
+.excluded_date { background-color: $excluded_date_color !important; }
-.specialDay, .selected_period, .selected_date, .overlap_date {
+.overlaped_date { background-color: $overlap_date_color !important; }
+
+.specialDay, .selected_period, .selected_date, .overlaped_date, .excluded_date {
a, a:visited, a:hover {
- color: white;
- text-decoration: none;
- }
+ color: white;
+ text-decoration: none;
+ }
}
-.specialDay a:hover, selected_period a:hover, selected_date a:hover, overlap_date a:hover {
- color: black;
-}
+.specialDay a:hover, selected_period a:hover, selected_date a:hover, excluded_date a:hover, overlaped_date a:hover{
+ color: black;
+ }
.weekendDay {
- background-color: #787888;
+ background-color: #787888;
}
.today {
- background-color: white;
- color: black;
-} \ No newline at end of file
+ background-color: white;
+ color: black;
+}
+
+
diff --git a/app/assets/stylesheets/main/companies.css.scss b/app/assets/stylesheets/main/companies.css.scss
index daf4da488..481b2ee7b 100644
--- a/app/assets/stylesheets/main/companies.css.scss
+++ b/app/assets/stylesheets/main/companies.css.scss
@@ -4,10 +4,6 @@
#workspace.companies.index
{
-
- .companies {
- margin-top: 20px;
- }
}
#workspace.companies.show
diff --git a/app/assets/stylesheets/main/compliance_check_tasks.css.scss b/app/assets/stylesheets/main/compliance_check_tasks.css.scss
index c81153848..13ab1e674 100644
--- a/app/assets/stylesheets/main/compliance_check_tasks.css.scss
+++ b/app/assets/stylesheets/main/compliance_check_tasks.css.scss
@@ -10,46 +10,6 @@
#workspace.compliance_check_tasks.index
{
-
- .compliance_check_tasks {
- margin-top: 20px;
- }
-
- .compliance_check_task {
-
- div.icon{
- float: left;
- }
-
- div.resume{
- float: right;
- width: 70%;
-
- ul.header{
- font-size: 14px;
- padding-left: 0px;
-
- .title{ float: left; }
- .remove{
- float: right;
- padding-right: 10px;
- color: #494949;
- }
- }
-
- .links {
- font-size: 10px;
- p { margin: 3px 0px 0px 0px !important; }
- img { margin-right: 10px;}
- }
-
- .history {
- color: $gray-light;
- margin-top: 5px;
- font-size: 10px;
- }
- }
- }
}
#workspace.compliance_check_tasks.show {
@@ -182,9 +142,9 @@
}
.td_error {
- width: 30%;
-
- i { margin-right: 10px; }
+ width: 30%;
+
+ .title_error i { margin-right: 5px; }
div.details_error{
margin: 0px 0px 0px 3px !important;
diff --git a/app/assets/stylesheets/main/connection_links.css.scss b/app/assets/stylesheets/main/connection_links.css.scss
index d4672cd31..5e5186ccf 100644
--- a/app/assets/stylesheets/main/connection_links.css.scss
+++ b/app/assets/stylesheets/main/connection_links.css.scss
@@ -4,10 +4,6 @@
#workspace.connection_links.index
{
-
- .connection_links {
- margin-top: 20px;
- }
}
diff --git a/app/assets/stylesheets/main/exports.css.scss b/app/assets/stylesheets/main/exports.css.scss
index 10d39db19..6b11e8b7f 100644
--- a/app/assets/stylesheets/main/exports.css.scss
+++ b/app/assets/stylesheets/main/exports.css.scss
@@ -4,46 +4,6 @@
#workspace.exports.index
{
-
- .exports {
- margin-top: 20px;
- }
-
- .export {
-
- div.icon{
- float: left;
- }
-
- div.resume{
- float: right;
- width: 70%;
-
- ul.header{
- font-size: 14px;
- padding-left: 0px;
-
- .title{ float: left; }
- .remove{
- float: right;
- padding-right: 10px;
- color: #494949;
- }
- }
-
- .links {
- font-size: 10px;
- p { margin: 3px 0px 0px 0px !important; }
- img { margin-right: 10px;}
- }
-
- .history {
- color: $gray-light;
- margin-top: 5px;
- font-size: 10px;
- }
- }
- }
}
#workspace.exports.show {
diff --git a/app/assets/stylesheets/main/group_of_lines.css.scss b/app/assets/stylesheets/main/group_of_lines.css.scss
index f56f76e44..7e8b7590d 100644
--- a/app/assets/stylesheets/main/group_of_lines.css.scss
+++ b/app/assets/stylesheets/main/group_of_lines.css.scss
@@ -4,10 +4,6 @@
#workspace.group_of_lines.index
{
-
- .group_of_lines {
- margin-top: 20px;
- }
}
#workspace.group_of_lines.show
@@ -23,53 +19,5 @@
margin-top: 10px;
}
- .group_of_line_lines {
- clear: both;
- margin: 0px;
- padding: 0px;
- a {
- cursor: pointer;
- }
- }
-
- .line {
- /* to create multi-column index */
- width: 250px;
- float: left;
- padding-right: 10px;
-
- .position {
- width: 25px;
- height: 20px;
- float: left;
- background-color: #61970B;
- font-weight: bold;
- color: white;
- margin-right: 10px;
- padding-left: 4px;
- }
- .color {
- background-color: white;
- width: 64px;
- height: 64px;
- float: left;
- margin-right: 10px;
- border: 1px solid #999;
-
- a {
- text-decoration: none;
- }
- }
-
- .number {
- font-size: 16px;
- text-align: center;
- font-weight: bold;
- padding-top: 21px;
- }
- .name a {
- display: inline;
- }
- }
}
diff --git a/app/assets/stylesheets/main/help.css.scss b/app/assets/stylesheets/main/help.css.scss
index 2597222cd..ebffedc92 100644
--- a/app/assets/stylesheets/main/help.css.scss
+++ b/app/assets/stylesheets/main/help.css.scss
@@ -1,18 +1,4 @@
#workspace.help {
-h2 {
- font-size: 17px;
-}
-
-h3 {
- font-size: 15px;
-}
-
-h4 {
- text-decoration: underline;
- font-weight: bold;
- padding: 7px 0;
- font-size: 14px;
-}
ul li {
list-style: circle;
@@ -98,6 +84,22 @@ dt {
dd {
padding-left: 10px;
}
+
+
+ table.meta {
+ width:50%;
+ }
+ table.meta th {
+ border-width:1px;
+ border-style:solid;
+ border-color:black;
+ }
+ table.meta td {
+ border-width:1px;
+ border-style:solid;
+ border-color:black;
+ }
+
}
#sidebarhelp.help {
h2 {
diff --git a/app/assets/stylesheets/main/import_tasks.css.scss b/app/assets/stylesheets/main/import_tasks.css.scss
index dabd84ae6..198f83129 100644
--- a/app/assets/stylesheets/main/import_tasks.css.scss
+++ b/app/assets/stylesheets/main/import_tasks.css.scss
@@ -1,53 +1,5 @@
-.status {
- margin-left: 10px;
-}
-
-.status_failed { color: #a94442;}
-.status_pending { color: #31708f;}
-.status_processing { color: #31708f;}
-.status_completed { color: #3c763d;}
-
#workspace.import_tasks.index
{
-
- .import_tasks {
- margin-top: 20px;
- }
-
- .import_task {
-
- div.icon{
- float: left;
- }
-
- div.resume{
- float: right;
- width: 70%;
-
- ul.header{
- font-size: 14px;
- padding-left: 0px;
-
- .title{ float: left; }
- .remove{
- float: right;
- padding-right: 10px;
- }
- }
-
- .links {
- font-size: 10px;
- p { margin: 3px 0px 0px 0px !important; }
- img { margin-right: 10px;}
- }
-
- .history {
- color: $gray-light;
- margin-top: 5px;
- font-size: 10px;
- }
- }
- }
}
#workspace.import_tasks.show {
diff --git a/app/assets/stylesheets/main/layout.css.scss b/app/assets/stylesheets/main/layout.css.scss
index faf5c1e7d..0a9ade3a8 100644
--- a/app/assets/stylesheets/main/layout.css.scss
+++ b/app/assets/stylesheets/main/layout.css.scss
@@ -1,5 +1,5 @@
body {
- padding-top: 55px;
+ padding-top: 50px;
}
h1{ color: white;}
@@ -17,74 +17,11 @@ ol.breadcrumb{
margin-top: 10px;
}
-#header {
-
- .navbar-brand{
- padding-top: 5px;
- padding-bottom: 5px;
- line-height: 40px;
-
- img {
- height: 40px;
- }
-
- .version
- {
- margin-left: 10px;
- vertical-align: text-top;
- color: white;
- font-size: 13px;
- }
- }
-
- background: $brand_primary url(image-path('header.png')) no-repeat;
-
- .gravatar {
- margin-right: 5px;
- img{
- width: 25px;
- height: 25px;
- }
- }
-
- .language{
- width: 40px;
- }
-
- .language.selected
- {
- border-bottom: 1px solid white;
- }
-
- .dropdown-menu{
- min-width: 230px;
-
- .badge{
- background-color: #DADADA
- }
- }
-}
-
-#footer{
- padding: 20px;
- background-color: $gray-darker;
- color: $gray-light;
- font-size: 12px;
- min-height: 200px;
-
- a { color: $gray-light; }
-
- h4 { color: $gray-lighter; }
-
- .logo > img {
- margin-left: 20px;
- }
-}
-
#middle{
min-height: 500px;
-webkit-box-shadow: 0 0 5px 2px rgba(0, 0, 0, .2);
box-shadow: 0 0 5px 2px rgba(0, 0, 0, .2);
+ padding-top: 10px;
padding-bottom: 10px;
margin-top: 20px;
margin-bottom: 20px;
@@ -113,6 +50,10 @@ ol.breadcrumb{
.actions {
margin-bottom: 20px;
+
+ li{
+ margin-bottom: 5px;
+ }
}
p {
@@ -198,257 +139,3 @@ ol.breadcrumb{
}
}
}
-
-/* #body #workspace { */
-/* width: 70%; */
-/* background: white; */
-/* margin: 0px 30px; */
-/* padding: 0 15px 10px 15px; */
-
-/* -moz-box-shadow: 3px 3px 4px #BBB; */
-/* -webkit-box-shadow: 3px 3px 4px #BBB; */
-/* box-shadow: 3px 3px 4px #BBB; */
-/* border-right: 1px solid #BBB; */
-/* border-bottom: 1px solid #BBB; */
-
-/* li span.author { */
-/* float: right; */
-/* font-size: 12px; */
-/* } */
-
-/* .site_summary { */
-/* float: left; */
-/* margin-bottom: 20px; */
-/* width: 100%; */
-
-/* img { */
-/* float: left; */
-/* margin-right: 20px; */
-/* } */
-/* a { */
-/* display: block; */
-/* margin: 25px 0 0; */
-/* } */
-/* } */
-/* .site_summary:after { */
-/* content: " "; */
-/* display: block; */
-/* height: 0; */
-/* clear: both; */
-/* visibility: hidden; */
-/* } */
-
-/* fieldset.buttons{ */
-/* margin: 10px; */
-/* } */
-
-/* form { */
-/* label { */
-/* color: #555555; */
-/* font-size: 100%; */
-/* text-align: right; */
-/* } */
-
-
-/* } */
-
-/* } */
-
-/* #body
-
-/* #body #sidebar { */
-/* width: 20%; */
-/* padding-top: 20px; */
-
-/* label { */
-/* color: #555555; */
-/* font-weight: normal; */
-/* font-size: 100%; */
-/* } */
-
-/* a { */
-/* color: #666; */
-/* } */
-
-/* .actions { */
-/* margin-bottom: 20px; */
-/* } */
-
-/* p { */
-/* font-size: 12px; */
-/* } */
-
-/* fieldset */
-/* { */
-/* border-color: white; */
-
-/* p{ */
-/* margin-top: 5px; */
-/* label{ font-size: 12px;} */
-/* span{ */
-/* font-style: oblique; */
-/* font-size:12px; */
-/* } */
-/* } */
-/* } */
-
-/* ol { */
-/* padding: 0px; */
-
-/* li { */
-/* list-style: none; */
-/* } */
-/* } */
-
-/* ul { */
-/* padding: 0px; */
-
-/* li { */
-/* list-style: none; */
-/* } */
-/* } */
-
-/* ul.selection li { */
-/* a { */
-/* padding-left: 20px; */
-/* } */
-/* a.current { */
-/* text-decoration: none; */
-/* color: black !important; */
-/* background: url(image-path('icons/accept.png')) no-repeat; */
-/* } */
-/* a.all { */
-/* background-image: none; */
-/* } */
-/* } */
-
-/* div#compact_form { */
-/* form { */
-/* border-bottom: 1px solid #BBB; */
-/* fieldset { */
-/* padding: 0; */
-/* border: 0; */
-/* li { */
-/* padding: 0; */
-/* label { padding-left: 20px; */
-/* width: 70%;} */
-/* input { width: 20px; } */
-/* } */
-/* } */
-/* fieldset.actions { */
-/* margin-bottom: 0; */
-/* padding-left: 20px; */
-/* } */
-/* fieldset.inputs { */
-/* padding-top: 16px; */
-/* } */
-/* } */
-/* } */
-/* } */
-
-.info {
- font-size: 10px;
- color: #777;
- font-weight: normal;
- line-height: 14px;
- margin-top: 5px;
-
- a {
- display:inline;
- color: #777;
- }
-
- .actions {
- margin-top: 10px;
- a {
- color: #666;
- padding-left: 12px;
- }
-
- a.link {
- background: url(image-path('icons/link-small.png')) no-repeat 0% 50%;
- }
- a.edit {
- background: url(image-path('icons/edit-small.png')) no-repeat 0% 50%;
- }
- a.remove {
- background: url(image-path('icons/remove-small.png')) no-repeat 0% 50%;
- }
- a.download {
- background: url(image-path('download-small.png')) no-repeat 0% 50%;
- }
- }
-}
-
-.actions {
- a {
- padding-left: 20px;
- }
-
- /* Hack with font icon */
- a.vehicle_journeys{
- padding-left: 4px;
- }
-
- a.visit_site{
- background: url(image-path('icons/site.png')) no-repeat;
- }
-
- a.visit_event{
- background: url(image-path('icons/event.png')) no-repeat;
- }
-
- a.visit_page{
- background: url(image-path('icons/page.png')) no-repeat;
- }
-
- a.add {
- background: url(image-path('icons/add.png')) no-repeat;
- }
- a.edit {
- background: url(image-path('icons/edit.png')) no-repeat;
- }
- a.remove {
- background: url(image-path('icons/remove.png')) no-repeat;
- }
- a.export {
- background: url(image-path('icons/export.png')) no-repeat;
- }
- li {
- margin: 10px 0;
- }
-
- a.add_children {
- background: url(image-path('icons/add.png')) no-repeat;
- }
-
- a.add_fields {
- background: url(image-path('icons/add.png')) no-repeat;
- }
-
- a.link {
- background: url(image-path('icons/link.png')) no-repeat;
- }
-
- a.select_parent {
- background: url(image-path('icons/select_parent.png')) no-repeat;
- }
-
- a.select_areas {
- background: url(image-path('icons/select_parent.png')) no-repeat;
- }
-
- a.calculator_edit {
- background: url(image-path('icons/calculator_edit.png')) no-repeat;
- }
- a.import {
- background: url(image-path('icons/import-small.png')) no-repeat;
- }
- a.export {
- background: url(image-path('icons/export-small.png')) no-repeat;
- }
- a.kml {
- background: url(image-path('icons/kml.png')) no-repeat;
- }
-
-}
diff --git a/app/assets/stylesheets/main/lines.css.scss b/app/assets/stylesheets/main/lines.css.scss
index 2817ec19d..3ce3c50e0 100644
--- a/app/assets/stylesheets/main/lines.css.scss
+++ b/app/assets/stylesheets/main/lines.css.scss
@@ -4,36 +4,21 @@
#workspace.lines.index
{
+ input[type="checkbox"].multiple_selection{
+ vertical-align: middle;
+ }
- .lines {
- margin-top: 20px;
- }
-
- .line {
-
- .color {
- background-color: white;
- width: 64px;
- height: 64px;
- float: left;
- margin-right: 10px;
- border: 1px solid #999;
+ #search {
- a {
- text-decoration: none;
- }
- }
+ label{
+ margin-bottom: 0px;
+ }
- .number {
- font-size: 16px;
- text-align: center;
- font-weight: bold;
- padding-top: 21px;
- }
- .name a {
- display: inline;
- }
- }
+ input[type="checkbox"]{
+ margin-left: 3px;
+ }
+
+ }
}
#workspace.lines.edit, #workspace.lines.new, #workspace.lines.create, #workspace.lines.update
diff --git a/app/assets/stylesheets/main/networks.css.scss b/app/assets/stylesheets/main/networks.css.scss
index 3730d6668..c8533699e 100644
--- a/app/assets/stylesheets/main/networks.css.scss
+++ b/app/assets/stylesheets/main/networks.css.scss
@@ -3,11 +3,7 @@
// You can use Sass (SCSS) here: http://sass-lang.com/
#workspace.networks.index
-{
- .networks {
- margin-top: 20px;
- }
-
+{
}
#workspace.networks.show
diff --git a/app/assets/stylesheets/main/organisations.css.scss b/app/assets/stylesheets/main/organisations.css.scss
index aaecbe30f..b3ef5b5f4 100644
--- a/app/assets/stylesheets/main/organisations.css.scss
+++ b/app/assets/stylesheets/main/organisations.css.scss
@@ -4,23 +4,5 @@
#workspace.organisations.show
{
-
- .users {
- margin-top: 20px;
- }
-
- .user {
-
- /* to create multi-column index */
- width: 350px;
- float: left;
- padding-right: 10px;
- position: relative;
-
- img.preview {
- width: 64px;
- height: 64px;
- }
- }
}
diff --git a/app/assets/stylesheets/main/referentials.css.scss b/app/assets/stylesheets/main/referentials.css.scss
index 715b152e8..8b6ae4b66 100644
--- a/app/assets/stylesheets/main/referentials.css.scss
+++ b/app/assets/stylesheets/main/referentials.css.scss
@@ -4,21 +4,8 @@
#workspace.referentials.index
{
-
- .referentials {
- margin-top: 20px;
- }
-
- .referential {
-
- /* to create multi-column index */
- width: 350px;
- float: left;
- padding-right: 10px;
- position: relative;
-
- }
}
+
#workspace.referentials.show
{
.summary p label {
@@ -35,41 +22,27 @@
padding: 5px 15px;
}
}
-
+
}
#sidebar div#clean_up {
- form {
- fieldset {
- padding: 0;
- border: 0;
- li.date {
- padding: 0;
- label { padding-left: 10px;
- width: 40%;}
- input { width: 42%; }
- }
- li {
- padding: 0;
- label { padding-left: 10px;
- width: 90%;}
- input { width: 12%; }
- }
- }
- fieldset.actions {
- margin-bottom: 0;
- padding-left: 20px;
- }
- fieldset.inputs {
- padding-top: 16px;
- }
- }
-}
+ form {
+ fieldset {
+ li{
+ margin-bottom: 0px;
+ }
+
+ li.date {
+
+ input{
+ width: 125px;
+ font-size: 12px;
+ height: 25px
+ }
+ label{
+ width: 35%;
+ }
+ }
+ }
-ul.logos {
- margin: 30px 30px 0 0;
-
- li {
- display: inline;
- margin: 0 3px;
}
}
diff --git a/app/assets/stylesheets/main/routes.css.scss b/app/assets/stylesheets/main/routes.css.scss
index 83ff13547..2d2d53a7b 100644
--- a/app/assets/stylesheets/main/routes.css.scss
+++ b/app/assets/stylesheets/main/routes.css.scss
@@ -3,39 +3,7 @@
// You can use Sass (SCSS) here: http://sass-lang.com/
#workspace.lines.show
-{
-
- .routes{
- margin-top: 20px;
-
- .route{
-
- .header{
- font-weight: bold;
-
- .wayback{
- float: right;
- }
- }
-
- .body {
- margin: 10px;
- font-size: 11px;
-
- p{ margin: 0 0 5px;}
-
- i{
- margin-right: 10px;
- font-size: 12px;
- }
-
- img{
- margin-right: 10px;
- }
- }
- }
- }
-
+{
}
#workspace.routes.edit, #workspace.routes.new, #workspace.routes.create, #workspace.routes.update
@@ -68,75 +36,6 @@
}
#workspace.routes.show
-{
- .page_info {
- margin: 10px 0 10px 0;
- }
-
- .route_color{ color: white;
- font-weight: bold;
- padding: 0 5px 0 5px;}
-
- .summary p label {
- font-weight: bold;
- }
-
- .stop_points_detail div.page_info {
- margin-top: 0px;
- }
-
- .stop_points {
- margin-top: 10px;
- }
-
- .route_journey_patterns {
- a {
- cursor: pointer;
- }
- }
-
- .route_stop_points {
- clear: both;
- margin: 0px;
- padding: 0px;
- a {
- cursor: pointer;
- }
- }
-
- .stop_point {
- /* to create multi-column index */
- width: 250px;
- float: left;
- padding-right: 10px;
-
- .position {
- width: 25px;
- height: 20px;
- float: left;
- background-color: #61970B;
- font-weight: bold;
- color: white;
- margin-right: 10px;
- padding-left: 4px;
- }
- }
-
- .journey_patterns {
- margin-top: 10px;
- }
-
- .journey_pattern {
- /* to create multi-column index */
- width: 350px;
- padding-right: 10px;
- height: 80px;
- float: left;
-
- .name {
- line-height: 16px;
- }
-
- }
+{
}
diff --git a/app/assets/stylesheets/main/rule_parameter_sets.css.scss b/app/assets/stylesheets/main/rule_parameter_sets.css.scss
index 682631ce5..7df394190 100644
--- a/app/assets/stylesheets/main/rule_parameter_sets.css.scss
+++ b/app/assets/stylesheets/main/rule_parameter_sets.css.scss
@@ -4,41 +4,6 @@
#workspace.rule_parameter_sets.index
{
- .rule_parameter_sets {
- margin-top: 20px;
- }
-
- .rule_parameter_set {
-
- /* to create multi-column index */
- width: 350px;
- float: left;
- padding-right: 10px;
- position: relative;
-
- .color {
- background-color: white;
- width: 64px;
- height: 64px;
- float: left;
- margin-right: 10px;
- border: 1px solid #999;
-
- a {
- text-decoration: none;
- }
- }
-
- .number {
- font-size: 16px;
- text-align: center;
- font-weight: bold;
- padding-top: 21px;
- }
- .name a {
- display: inline;
- }
- }
}
#workspace.rule_parameter_sets.show, #workspace.compliance_check_tasks.rule_parameter_set
diff --git a/app/assets/stylesheets/main/stop_areas.css.scss b/app/assets/stylesheets/main/stop_areas.css.scss
index 384b412a7..59c243c26 100644
--- a/app/assets/stylesheets/main/stop_areas.css.scss
+++ b/app/assets/stylesheets/main/stop_areas.css.scss
@@ -4,30 +4,27 @@
#workspace.stop_areas.index
{
-
- .stop_area {
-
- .area_type {
- width: 25px;
- height: 64px;
- float: left;
- margin-right: 10px;
-
-
- a {
- text-decoration: none;
- }
- }
-
- }
+ #country_codes { display: none; }
}
-#workspace.stop_areas.edit {
+#workspace.stop_areas.edit, #workspace.stop_areas.new, #workspace.stop_areas.update, #workspace.stop_areas.create {
legend { padding-bottom: 20px; }
+ #prefetch {
+ padding: 10px 10px 20px 10px;
+
+ label{
+ font-size: 16px;
+ margin-right: 25px;
+ }
+
+ input{ width: 330px; }
+ }
+
#map{
float:none;
width: 100%;
+ height: 450px;
}
}
@@ -104,21 +101,7 @@
height: 25px;
}
}
- .access_point {
-
- .access_type {
- width: 25px;
- height: 64px;
- float: left;
- margin-right: 10px;
-
- a {
- text-decoration: none;
- }
- }
-
- }
}
#workspace.stop_areas.select_parent
diff --git a/app/assets/stylesheets/main/time_table_combinations.css.scss b/app/assets/stylesheets/main/time_table_combinations.css.scss
new file mode 100644
index 000000000..70dc2e535
--- /dev/null
+++ b/app/assets/stylesheets/main/time_table_combinations.css.scss
@@ -0,0 +1,14 @@
+#modal_combine{
+ .time_table_combination{
+
+ .radio input[type="radio"]{
+ position: inherit !important;
+ }
+
+ .inputs{
+
+ overflow: visible !important;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/main/time_tables.css.scss b/app/assets/stylesheets/main/time_tables.css.scss
index 5ea1f993f..bc1f48810 100644
--- a/app/assets/stylesheets/main/time_tables.css.scss
+++ b/app/assets/stylesheets/main/time_tables.css.scss
@@ -4,172 +4,157 @@
#workspace.time_tables.index
{
+}
+
+
+#workspace.time_tables.show
+{
+ .modal-body{overflow-y: visible;}
- .time_tables {
+ .summary{
margin-top: 20px;
+
+ p label {
+ font-weight: bold;
+ }
}
-
- .time_table {
-
- .state-code {
- width: 25px;
- height: 64px;
- float: left;
- margin-right: 10px;
-
- .validity_out {
- background-color: #FC4903;
- width: 25px;
- height: 25px;
- }
- .validity_out_soon {
- background-color: orange;
- width: 25px;
- height: 25px;
- }
-
- .validity_regular {
- background-color: #86B41D;
- width: 25px;
- height: 25px;
- }
+ .legend{
+ margin-top: 20px;
+
+ .title{ font-weight: bold; }
+
+ .excluded_date, .overlaped_date, .selected_date, .selected_period{
+ margin-left: 20px;
+ margin-right: 5px;
}
}
-}
+
+ .typeahead.dropdown-menu {
+ z-index: 100001;
+ }
+
+ .validity_out {
+ color: $brand-danger;
+ }
+
+ .validity_out_soon {
+ color: $brand-warning;
+ }
+
+ .validity_regular {
+ color: $brand-success;
+ }
-#workspace.time_tables.show
-{
- .day_type {
- border-style:solid;
- border-width:1px;
- }
- .period {
+ span.included_day_type {
+ font-weight: bolder;
+ margin-right: 3px;
+ }
+
+ span.excluded_day_type {
+ margin-right: 3px;
+ }
+
+ .period {
padding-left:50px;
padding-right:450px;
- }
- .date {
+ }
+
+ .date {
padding-left:50px;
- }
- .odd {
+ }
+
+ .odd {
padding-left:50px;
padding-right:450px;
- }
- .even {
+ }
+
+ .even {
padding-left:50px;
padding-right:450px;
- }
- .actions {
- float: right;
}
- .summary p label {
- font-weight: bold;
+ .actions {
+ float: right;
}
+}
+
+#workspace.time_tables.edit,#workspace.time_tables.new,#workspace.time_tables.create,#workspace.time_tables.update,#workspace.time_tables.duplicate
+{
+ fieldset.inputs{
+ overflow: visible !important;
- .resume {
- .validity {
- float: left;
- width: 20px;
- height: 20px;
- margin-right: 10px;
+ .tags{
+ overflow: visible !important;
}
- .validity.validity_out {
- background-color: #FC4903;
+ }
+
+ h3 {
+ .dates {
+ cursor: pointer;
}
- .validity.validity_out_soon {
- background-color: orange;
+ .periods {
+ cursor: pointer;
}
- .validity.validity_regular {
- background-color: #86B41D;
+ .excluded_dates {
+ cursor: pointer;
}
}
-}
-#workspace.time_tables.edit,#workspace.time_tables.new,#workspace.time_tables.create,#workspace.time_tables.update
-{
- h3 {
- .dates {
- cursor: pointer;
- }
- .periods {
- cursor: pointer;
- }
- }
-
-
- .day_type ol {
- float: left;
- margin: 0;
- padding: 0 0 0 0;
- width: 100%;
- list_style: none outside none;
- margin-top: 0.5em;
- margin-bottom: 1em;
- }
- .day_type ol li {
- float: left;
- margin: 0 O 0 0;
- width: auto;
- padding: 0;
- }
- .day_type_label {
- float: left;
- margin-top: 0;
- width: 25%;
- }
- .day_type ol li label {
- padding-left: 10%;
- }
-
- .dates ol {
- margin-top: -0.3em;
- margin-bottom: 1em;
- margin-left: 25%;
- padding: 0;
- width: 75%;
- }
- .dates ol li { padding : 0.3em 0; }
-
- .dates ol li label {
- width: 40%;
- margin-top: -0.3em;
- }
- .dates ol li.fl1 {float: left; width: 30% ;}
- .dates ol li.fl1 label {width: 40%; margin-top: -0.3em; }
- .dates ol li.fl1 input { width: 50%; }
-
-
- .periods ol {
- margin-top: -0.3em;
- margin-bottom: 1em;
- margin-left: 25%;
- padding: 0;
- width: 75%;
- }
- .periods ol li { padding : 0.3em 0; }
-
- .periods ol li label {
- width: 40%;
- margin-top: -0.3em;
- }
- .periods ol li.fl1 {float: left; width: 30% ;}
- .periods ol li.fl1 label {width: 40%; margin-top: -0.3em; }
- .periods ol li.fl1 input { width: 50%; }
-
- .periods ol li.fl2 {float: left; width: 30% ;}
- .periods ol li.fl2 label {width: 40%; margin-top: -0.3em;}
- .periods ol li.fl2 input { width: 50%; }
- a.add_fields {
- margin-left: 25%;
- color: #666;
- padding-left: 18px;
- background: url(image-path('user_interface/ui/add.png')) no-repeat 0% 50%;
- }
- a.remove_fields {
- color: #666;
- padding-left: 18px;
- background: url(image-path('user_interface/ui/remove.png')) no-repeat 0% 50%;
- }
+ #dates,#excluded_dates,#periods{
+ .nested-fields {
+ margin: 5px;
+
+ ol {
+ li {
+ display: inline;
+ }
+ }
+ }
+
+ margin-left: 25%;
+ }
+
+ .day_type ol {
+ float: left;
+ margin: 0;
+ padding: 0 0 0 0;
+ width: 100%;
+ list_style: none outside none;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ }
+ .day_type ol li {
+ float: left;
+ margin: 0 O 0 0;
+ width: auto;
+ padding: 0;
+ }
+ .day_type_label {
+ float: left;
+ margin-top: 0;
+ width: 25%;
+ }
+ .day_type ol li label {
+ padding-left: 10%;
+ margin-top: 0;
+ }
+
+ a.add_fields {
+ margin-left: 25%;
+ margin-top: 20px;
+ padding-left: 18px;
+ background: url(image-path('icons/add.png')) no-repeat 0% 50%;
+ }
+
+ a.remove_fields {
+ margin-left: 10px;
+ padding-left: 18px;
+ background: url(image-path('icons/remove.png')) no-repeat 0% 50%;
+ }
+
+ .actions{
+ margin-top: 20px;
+ }
}
diff --git a/app/assets/stylesheets/main/vehicle_journeys.css.scss b/app/assets/stylesheets/main/vehicle_journeys.css.scss
index 0a2fce05a..580874df4 100644
--- a/app/assets/stylesheets/main/vehicle_journeys.css.scss
+++ b/app/assets/stylesheets/main/vehicle_journeys.css.scss
@@ -4,18 +4,56 @@
#workspace.vehicle_journeys.edit, #workspace.vehicle_journeys.update, #workspace.vehicle_journeys.create, #workspace.vehicle_journeys.new
{
- #route_color{ width: 100px;
- color: white;
- font-weight: bold;}
+ #route_color{
+ width: 100px;
+ color: white;
+ font-weight: bold;
+ }
+
.journey_pattern_dependent_list {
tr.no_stop { display: none; }
}
+
.time_table_list { padding-left: 25%; }
- .vehicle_journey_at_stops { margin-left: 25%; }
+
+ .vehicle_journey_at_stops {
+ margin-left: 25%;
+
+ .title{
+ font-weight: bold;
+ margin-bottom: 20px;
+ }
+
+ span{
+ margin-left: 10px;
+ margin-right: 10px;
+ }
+
+ .slide{
+ margin-left: 30px;
+
+ }
+ }
}
#workspace.vehicle_journeys.index
{
+ #search{
+
+ ul.token-input-list{
+ display: inline-block;
+ vertical-align: middle;
+ margin-left: 15px;
+ }
+
+ .advanced_search{ margin-left: 40px; }
+
+ .time_tables_id_eq{ margin-left: 20px; }
+
+ .vehicle_journey_at_stops_departure_time_gt{ margin-left: 20px; }
+
+ }
+
table{
margin: 20px 0 0 0;
@@ -25,47 +63,46 @@
}
.stop_area{ width: 200px; }
- }
-
+
+ td.hours{
+ text-align: center;
+ }
+
+ tr th.vehicle_journey{
+ text-align: center;
+ }
+ }
+
}
-#workspace.vehicle_journeys.show, #workspace.vehicle_journeys.edit, #workspace.vehicle_journeys.update, #workspace.vehicle_journeys.create, #workspace.vehicle_journeys.new {
-
+#workspace.vehicle_journeys.show, #workspace.vehicle_journeys.edit, #workspace.vehicle_journeys.update, #workspace.vehicle_journeys.create, #workspace.vehicle_journeys.new {
+
.to_departures {
cursor: pointer;
}
-
+
.to_arrivals {
cursor: pointer;
- }
+ }
+
+ .slide {
+ cursor: pointer;
+ }
}
#workspace.vehicle_journeys.show
{
.summary p label {
font-weight: bold;
- }
-
- .time_tables {
- margin-top: 20px;
- }
-
- .time_table {
- span.included_day_type {
- font-weight: bolder;
- color: black;
- }
- span.excluded_day_type {
- }
}
-}
+}
#workspace.vehicle_journeys.timeless
{
.summary p label {
font-weight: bold;
}
-
+
.vehicle_journeys {
margin-top: 20px;
}
@@ -74,12 +111,11 @@
span.included_day_type {
font-weight: bolder;
- color: black;
}
span.excluded_day_type {
}
}
-}
+}
diff --git a/app/assets/stylesheets/main/vehicle_translation.css.scss b/app/assets/stylesheets/main/vehicle_translation.css.scss
new file mode 100644
index 000000000..f399d1a4a
--- /dev/null
+++ b/app/assets/stylesheets/main/vehicle_translation.css.scss
@@ -0,0 +1,15 @@
+#translate_form{
+ .repeat_cloning{
+ margin-top: 30px;
+ }
+
+ .modal-footer{
+ .actions {
+ padding-left: 75%;
+
+ li {
+ margin: 0px 0px;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/modules/devise.css.scss b/app/assets/stylesheets/modules/devise.css.scss
new file mode 100644
index 000000000..8236366ce
--- /dev/null
+++ b/app/assets/stylesheets/modules/devise.css.scss
@@ -0,0 +1,75 @@
+#devise{
+ background-color: $gray-light;
+
+ .front_bg{
+ background: url(image-path('welcome.jpg')) no-repeat center center;
+ background-size: cover;
+
+ #devise_middle{
+ min-height: 620px;
+ padding: 30px 20px 0px 20px;
+
+ #registrations_new{
+
+ .form-group{
+ margin-bottom: 5px;
+ }
+
+ }
+
+ #sessions_new{
+
+ .btn{
+ font-weight: bold;
+ }
+
+ .product_summary{
+ padding: 30px 60px 0 60px;
+
+ color: white;
+ text-shadow: 0 0 1px rgba(0,0,0,.6);
+
+ p{
+ font-size: 21px;
+ }
+
+ ul > li{ font-size: 21px; }
+ }
+
+ .login{
+ padding-top: 30px;
+
+ .form-group{
+ margin-bottom: 5px;
+ }
+
+ .options{
+ .new_password{
+ padding-top: 7px;
+ }
+
+ .checkbox{
+ font-weight: normal;
+
+ input[type="checkbox"]{
+ margin-left: 0px !important;
+ position: relative;
+ margin: 0px 4px 0px 0px;
+ }
+ }
+
+ .form-group{
+ margin-bottom: 0px;
+ }
+
+ font-size: 12px;
+ }
+ }
+ }
+ }
+
+ #footer{
+ background-color: rgba(0, 0, 0, 0.8);
+ }
+ }
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/modules/icons.css.scss b/app/assets/stylesheets/modules/icons.css.scss
new file mode 100644
index 000000000..3da56d1c9
--- /dev/null
+++ b/app/assets/stylesheets/modules/icons.css.scss
@@ -0,0 +1,101 @@
+a:before {
+ font-family: FontAwesome;
+ display: inline-block;
+ padding-right: 3px;
+ vertical-align: middle;
+}
+
+a.add:before { // fa-plus-circle
+ content: "\f055";
+ color: $brand-success;
+ }
+
+a.edit:before { // fa-pencil
+ content: "\f040";
+ color: $brand-warning;
+ }
+
+a.remove:before { // fa-trash
+ content: "\f1f8";
+ color: $brand-danger;
+ }
+
+a.export:before { // fa-upload
+ content: "\f093";
+ color: $brand-info;
+ }
+
+a.import:before { // fa-download
+ content: "\f019";
+ color: $brand-info;
+ }
+
+a.clone:before { // fa-copy
+ content: "\f0c5";
+ color: $brand-success;
+ }
+
+a.link:before { // fa-external-link
+ content: "\f08e";
+ }
+
+a.select:before {// fa-select
+ content: "\f0a6";
+ color: $brand-warning;
+
+ }
+
+a.calculator:before { // fa-calculator
+ content: "\f1ec";
+ color: $brand-warning;
+ }
+
+a.parent:before { // fa-arrow-up
+ content: "\f062";
+ color: $brand-warning;
+ }
+
+a.children:before { // fa-sitemap
+ content: "\f0e8";
+ color: $brand-warning;
+ }
+
+a.access_link:before { // fa-exchange
+ content: "\f0ec";
+ color: $brand-warning;
+ }
+
+a.merge:before { // fa-link
+ content: "\f0c1";
+ color: $brand-warning;
+ }
+
+a.clock:before { // fa-clock-o
+ content: "\f017";
+ }
+
+/* first-child makes sure to grab the first element inside
+your fa-stack. The top margin shifts the inner icon down */
+.fa-stack-1x { top: .25em; }
+
+.fa-stack {
+ /* sizes whole .fa-stack down to make them the regular sized */
+ font-size: .5em;
+ /* makes sure regular and stacked icons vertically align */
+ vertical-align: -16%;
+}
+
+/* Styles text for doc type. Oswald is a great condensed
+Google Web Font */
+.filetype-text {
+ font-size: .7em;
+ font-weight: 700;
+ font-family: 'Oswald';
+}
+
+a.kml:before {
+ content: "<span class='fa-stack'>
+<span class='fa-stack-1x filetype-text'>KML</span>
+<i class='fa fa-file-o fa-stack-2x'></i>
+</span>";
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/modules/index_item.css.scss b/app/assets/stylesheets/modules/index_item.css.scss
new file mode 100644
index 000000000..2404c879a
--- /dev/null
+++ b/app/assets/stylesheets/modules/index_item.css.scss
@@ -0,0 +1,85 @@
+#index_item{
+
+
+ .panel-heading{
+ @extend .clearfix;
+
+ .validity_out {
+ color: $brand-danger;
+ }
+
+ .validity_out_soon {
+ color: $brand-warning;
+ }
+
+ .validity_regular {
+ color: $brand-success;
+ }
+
+ button {
+ margin-left:3px;
+ }
+
+ .date {
+ font-size:10px;
+ color: gray;
+ text-align: center;
+ }
+
+ .label{
+ margin-right: 5px;
+ }
+
+ h5{
+ margin: 0px;
+ padding-top: 4.5px;
+ }
+
+ }
+
+ .panel-body{
+ p {
+ margin: 0 0 3px;
+ font-size: 12px;
+ }
+
+ img{
+ margin-right: 5px;
+ }
+
+ i{
+ margin-right: 5px;
+ }
+
+ span.included_day_type {
+ font-weight: bolder;
+ margin-right: 3px;
+ }
+
+ span.excluded_day_type {
+ margin-right: 3px;
+ }
+
+ }
+
+ .panel-footer{
+ text-align: center;
+
+
+ .progress {
+ margin-bottom: 5px;
+
+ .progress-bar.failed { width: 100%;}
+ .progress-bar.pending { width: 10%;}
+ .progress-bar.processing { width: 50%;}
+ .progress-bar.completed { width: 100%;}
+ }
+
+ .history{
+ color: $gray;
+ font-size: 10px;
+ }
+ }
+
+}
+
diff --git a/app/assets/stylesheets/modules/search.css.scss b/app/assets/stylesheets/modules/search.css.scss
new file mode 100644
index 000000000..eeb35a8a5
--- /dev/null
+++ b/app/assets/stylesheets/modules/search.css.scss
@@ -0,0 +1,19 @@
+#search{
+
+ #advanced_search{
+
+ .form-control{
+ display: inline !important;
+ }
+
+ .panel-body{
+ div{
+ margin-bottom: 10px;
+ }
+ }
+ }
+
+ // Fix for typeahead css to remove
+ span.twitter-typeahead { display: inline !important;}
+
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/partials/footer.css.scss b/app/assets/stylesheets/partials/footer.css.scss
new file mode 100644
index 000000000..a6b38b76d
--- /dev/null
+++ b/app/assets/stylesheets/partials/footer.css.scss
@@ -0,0 +1,15 @@
+#footer{
+ padding: 20px;
+ background-color: $gray-darker;
+ color: $gray-light;
+ font-size: 12px;
+ min-height: 200px;
+
+ a { color: $gray-light; }
+
+ h4 { color: $gray-lighter; }
+
+ .logo > img {
+ margin-left: 20px;
+ }
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/partials/header.css.scss b/app/assets/stylesheets/partials/header.css.scss
new file mode 100644
index 000000000..6f7b777f1
--- /dev/null
+++ b/app/assets/stylesheets/partials/header.css.scss
@@ -0,0 +1,48 @@
+#header {
+
+ .navbar-brand{
+ padding-top: 5px;
+ padding-bottom: 5px;
+ line-height: 40px;
+
+ img {
+ height: 40px;
+ }
+ }
+
+ .navbar-text{
+ margin-top: 10px;
+ margin-bottom: 10px;
+ margin-left: 0px;
+
+ .brand_name{
+ color: white;
+ font-weight: bold;
+ font-size: 20px;
+ }
+
+ .version
+ {
+ margin-left: 5px;
+ color: white;
+ font-size: 12px;
+ }
+ }
+
+ background: $brand_primary url(image-path('header.png')) no-repeat;
+
+ .gravatar {
+ margin-right: 5px;
+ img{
+ width: 25px;
+ height: 25px;
+ }
+ }
+
+ .dropdown.languages{
+ .dropdown-menu{
+ min-width: 56px;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/bootstrap_changes.css.scss b/app/assets/stylesheets/vendor/bootstrap_changes.css.scss
new file mode 100644
index 000000000..597c9897d
--- /dev/null
+++ b/app/assets/stylesheets/vendor/bootstrap_changes.css.scss
@@ -0,0 +1,34 @@
+.popover{
+
+ li{
+ list-style: inherit !important;
+ }
+
+ .time_table_info{
+ color: $gray;
+ font-size: 11px;
+ }
+
+ span.included_day_type {
+ color: black;
+ }
+ span.excluded_day_type {
+ }
+
+ span.bounding{
+ font-size: 11px;
+ margin-left: 5px;
+ }
+
+ .validity_out {
+ color: $brand-danger;
+ }
+
+ .validity_out_soon {
+ color: $brand-warning;
+ }
+
+ .validity_regular {
+ color: $brand-success;
+ }
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/formtastic.css.scss b/app/assets/stylesheets/vendor/formtastic.css.scss
deleted file mode 100644
index 078cf41ab..000000000
--- a/app/assets/stylesheets/vendor/formtastic.css.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-fieldset.inputs {
-
- a.action { float: right; }
-}
-
-.formtastic .choices .label, .formtastic .fragments .label {
- width: 25%;
- border: 0px;
-
- label {
- position: relative;
- font-size: 14px;
- }
-}
-
-/* Hack to remove!!!! */
-.formtastic .inputs input[type="file"] {
- display: initial;
-}
-/* Hack to remove!!!! */ \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/formtastic_changes.css.scss b/app/assets/stylesheets/vendor/formtastic_changes.css.scss
new file mode 100644
index 000000000..d64d6925f
--- /dev/null
+++ b/app/assets/stylesheets/vendor/formtastic_changes.css.scss
@@ -0,0 +1,46 @@
+.formtastic{
+
+ .label{
+ white-space: normal;
+ text-align: right;
+ }
+
+ .stringish input{
+ width: auto;
+ }
+
+ fieldset.inputs {
+
+ a.action { float: right; }
+ }
+
+ .choices .label, .formtastic .fragments .label {
+ width: 25%;
+ border: 0px;
+
+ label {
+ position: relative;
+ font-size: 14px;
+ }
+ }
+
+ .choices legend.label label{
+ @extend .label;
+ font-size: 14px !important;
+ width: 100% !important;
+ }
+
+ .choice label input{
+ margin: 0px 0px 0px -20px !important;
+ }
+
+ .token-input-list {
+ display: inline-block;
+ }
+
+ /* Hack to remove!!!! */
+ .inputs input[type="file"] {
+ display: initial;
+ }
+ /* Hack to remove!!!! */
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/jquery.qtip.min.css b/app/assets/stylesheets/vendor/jquery.qtip.min.css
deleted file mode 100644
index 9e1ab087d..000000000
--- a/app/assets/stylesheets/vendor/jquery.qtip.min.css
+++ /dev/null
@@ -1 +0,0 @@
-/*! qTip2 v2.0.1 (includes: svg ajax tips modal viewport imagemap ie6 / basic css3) | qtip2.com | Licensed MIT, GPL | Mon Dec 31 2012 14:55:17 */.qtip,.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr}.qtip-content{position:relative;padding:5px 9px;overflow:hidden;text-align:left;word-wrap:break-word}.qtip-titlebar{position:relative;padding:5px 35px 5px 10px;overflow:hidden;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;cursor:pointer;outline:medium none;border-width:1px;border-style:solid;border-color:transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-titlebar .ui-icon,.qtip-icon .ui-icon{display:block;text-indent:-1000em;direction:ltr;vertical-align:middle}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;text-align:center;text-indent:0;font:normal bold 10px/13px Tahoma,sans-serif;color:inherit;background:transparent none no-repeat -100em -100em}.qtip-focus{}.qtip-hover{}.qtip-default{border-width:1px;border-style:solid;border-color:#F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}/*! Light tooltip style */.qtip-light{background-color:#fff;border-color:#E2E2E2;color:#454545}.qtip-light .qtip-titlebar{background-color:#f1f1f1}/*! Dark tooltip style */.qtip-dark{background-color:#505050;border-color:#303030;color:#f3f3f3}.qtip-dark .qtip-titlebar{background-color:#404040}.qtip-dark .qtip-icon{border-color:#444}.qtip-dark .qtip-titlebar .ui-state-hover{border-color:#303030}/*! Cream tooltip style */.qtip-cream{background-color:#FBF7AA;border-color:#F9E98E;color:#A27D35}.qtip-cream .qtip-titlebar{background-color:#F0DE7D}.qtip-cream .qtip-close .qtip-icon{background-position:-82px 0}/*! Red tooltip style */.qtip-red{background-color:#F78B83;border-color:#D95252;color:#912323}.qtip-red .qtip-titlebar{background-color:#F06D65}.qtip-red .qtip-close .qtip-icon{background-position:-102px 0}.qtip-red .qtip-icon{border-color:#D95252}.qtip-red .qtip-titlebar .ui-state-hover{border-color:#D95252}/*! Green tooltip style */.qtip-green{background-color:#CAED9E;border-color:#90D93F;color:#3F6219}.qtip-green .qtip-titlebar{background-color:#B0DE78}.qtip-green .qtip-close .qtip-icon{background-position:-42px 0}/*! Blue tooltip style */.qtip-blue{background-color:#E5F6FE;border-color:#ADD9ED;color:#5E99BD}.qtip-blue .qtip-titlebar{background-color:#D0E9F5}.qtip-blue .qtip-close .qtip-icon{background-position:-2px 0}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-rounded,.qtip-tipsy,.qtip-bootstrap{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border-width:0;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,black));background-image:-webkit-linear-gradient(top,#4A4A4A 0,black 100%);background-image:-moz-linear-gradient(top,#4A4A4A 0,black 100%);background-image:-ms-linear-gradient(top,#4A4A4A 0,black 100%);background-image:-o-linear-gradient(top,#4A4A4A 0,black 100%)}.qtip-youtube .qtip-titlebar{background-color:#4A4A4A;background-color:rgba(0,0,0,0)}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-linear-gradient(top,#717171,#232323);background-image:-ms-linear-gradient(top,#717171,#232323);background-image:-o-linear-gradient(top,#717171,#232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323)"}.qtip-jtools .qtip-titlebar,.qtip-jtools .qtip-content{background:transparent;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px black}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qtip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D);background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-ms-linear-gradient(top,#3A79B8,#2E629D);background-image:-o-linear-gradient(top,#3A79B8,#2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-size:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:transparent}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml{position:absolute;color:#123456;background:transparent;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}#qtip-overlay{position:fixed;left:-10000em;top:-10000em}#qtip-overlay.blurs{cursor:pointer}#qtip-overlay div{position:absolute;left:0;top:0;width:100%;height:100%;background-color:#000;opacity:.7;filter:alpha(opacity=70);-ms-filter:"alpha(Opacity=70)"}.qtipmodal-ie6fix{position:absolute!important} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/map_layers.css.scss b/app/assets/stylesheets/vendor/map_layers.css.scss
index 7d9972038..835417ddc 100644
--- a/app/assets/stylesheets/vendor/map_layers.css.scss
+++ b/app/assets/stylesheets/vendor/map_layers.css.scss
@@ -6,4 +6,5 @@ p.after_map {
float: right;
width: 400px;
height: 400px;
+ border: 1px solid gray;
} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/pagination.css.scss b/app/assets/stylesheets/vendor/pagination.css.scss
index 87eb905e8..eb994f308 100644
--- a/app/assets/stylesheets/vendor/pagination.css.scss
+++ b/app/assets/stylesheets/vendor/pagination.css.scss
@@ -7,20 +7,6 @@
margin: 20px 0 0 0;
}
-.paginated_content > .row {
- margin-top: 10px;
-
- .col-md-4 > div{
- padding: 5px;
- background-color: $gray-lighter;
- border: 1px solid $brand-primary;
- @include border-top-radius(5px);
- @include border-right-radius(5px);
- @include border-left-radius(5px);
- @include border-bottom-radius(5px);
- }
-}
-
.page_info {
margin: 20px 0 0 0;
height: 30px;
@@ -38,4 +24,11 @@
b {
padding: 0.1em 0.25em;
}
+}
+
+.paginated_content{
+
+ .row{
+ margin-top: 15px;
+ }
} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/simple_form.css.scss b/app/assets/stylesheets/vendor/simple_form.css.scss
new file mode 100644
index 000000000..ea5e4d528
--- /dev/null
+++ b/app/assets/stylesheets/vendor/simple_form.css.scss
@@ -0,0 +1,6 @@
+.simple_form{
+
+ .help-inline{
+ color:#cc0000;
+ }
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/tipsy.css b/app/assets/stylesheets/vendor/tipsy.css
deleted file mode 100644
index f170fb710..000000000
--- a/app/assets/stylesheets/vendor/tipsy.css
+++ /dev/null
@@ -1,25 +0,0 @@
-.tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; }
- .tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; }
-
- /* Rounded corners */
- .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
-
- /* Uncomment for shadow */
- /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/
-
- .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
-
- /* Rules to colour arrows */
- .tipsy-arrow-n { border-bottom-color: #000; }
- .tipsy-arrow-s { border-top-color: #000; }
- .tipsy-arrow-e { border-left-color: #000; }
- .tipsy-arrow-w { border-right-color: #000; }
-
- .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
- .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
- .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
- .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
- .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
- .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
- .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
- .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
diff --git a/app/assets/stylesheets/main/token-input.css b/app/assets/stylesheets/vendor/token-input.css
index 55a7f5656..89dbd802e 100644
--- a/app/assets/stylesheets/main/token-input.css
+++ b/app/assets/stylesheets/vendor/token-input.css
@@ -7,8 +7,8 @@ ul.token-input-list {
border: 1px solid #999;
cursor: text;
font-size: 12px;
- font-family: Verdana;
- z-index: 999;
+ font-family: Verdana, sans-serif;
+ z-index: 1061;
margin: 0;
padding: 0;
background-color: #fff;
@@ -28,13 +28,28 @@ ul.token-input-list li input {
-webkit-appearance: caret;
}
+ul.token-input-disabled,
+ul.token-input-disabled li input {
+ background-color: #E8E8E8;
+}
+
+ul.token-input-disabled li.token-input-token {
+ background-color: #D9E3CA;
+ color: #7D7D7D
+}
+
+ul.token-input-disabled li.token-input-token span {
+ color: #CFCFCF;
+ cursor: default;
+}
+
li.token-input-token {
overflow: hidden;
height: auto !important;
height: 1%;
margin: 3px;
padding: 3px 5px;
- background-color: #d0efa0;
+ background-color: $gray-lighter;
color: #000;
font-weight: bold;
cursor: default;
@@ -72,8 +87,8 @@ div.token-input-dropdown {
border-bottom: 1px solid #ccc;
cursor: default;
font-size: 12px;
- font-family: Verdana;
- z-index: 1;
+ font-family: Verdana, sans-serif;
+ z-index: 1061;
}
div.token-input-dropdown p {
@@ -108,9 +123,10 @@ div.token-input-dropdown ul li em {
}
div.token-input-dropdown ul li.token-input-selected-dropdown-item {
- background-color: #d0efa0;
+ background-color: $gray-lighter;
}
-form.formtastic .token-input-list {
-display: inline-block;
+ul.token-input-list .info{
+ font-size: 0.8em;
+ color: $gray;
} \ No newline at end of file
diff --git a/app/assets/stylesheets/vendor/typeahead.css.scss b/app/assets/stylesheets/vendor/typeahead.css.scss
new file mode 100644
index 000000000..56653de9d
--- /dev/null
+++ b/app/assets/stylesheets/vendor/typeahead.css.scss
@@ -0,0 +1,49 @@
+.twitter-typeahead .tt-query,
+.twitter-typeahead .tt-hint {
+ margin-bottom: 0;
+}
+
+.tt-dropdown-menu {
+ min-width: 160px;
+ margin-top: 2px;
+ padding: 5px 0;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0,0,0,.2);
+ *border-right-width: 2px;
+ *border-bottom-width: 2px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+.tt-suggestion {
+ display: block;
+ padding: 3px 20px;
+}
+
+.tt-suggestion.tt-is-under-cursor {
+ color: #fff;
+ background-color: #0081c2;
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)
+}
+
+.tt-suggestion.tt-is-under-cursor a {
+ color: #fff;
+}
+
+.tt-suggestion p {
+ margin: 0;
+} \ No newline at end of file
diff --git a/app/controllers/access_links_controller.rb b/app/controllers/access_links_controller.rb
index 8c6172a7c..b22dd75a8 100644
--- a/app/controllers/access_links_controller.rb
+++ b/app/controllers/access_links_controller.rb
@@ -16,7 +16,12 @@ 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 |format|
+ format.html {build_breadcrumb :show}
+ end
end
def new
@@ -34,7 +39,9 @@ class AccessLinksController < ChouetteController
data[:name] = name
end
@access_link = Chouette::AccessLink.new(data)
- new!
+ new! do
+ build_breadcrumb :new
+ end
end
def create
@@ -50,7 +57,9 @@ 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
+ build_breadcrumb :edit
+ end
end
protected
diff --git a/app/controllers/access_points_controller.rb b/app/controllers/access_points_controller.rb
index 309550148..ca8e0b156 100644
--- a/app/controllers/access_points_controller.rb
+++ b/app/controllers/access_points_controller.rb
@@ -6,7 +6,6 @@ class AccessPointsController < ChouetteController
end
respond_to :html, :kml, :xml, :json
- layout "without_sidebar", :only => [:edit, :update]
def index
request.format.kml? ? @per_page = nil : @per_page = 12
@@ -31,13 +30,17 @@ class AccessPointsController < ChouetteController
}
end
+ format.html {build_breadcrumb :show}
end
end
+
def edit
access_point.position ||= access_point.default_position
map.editable = true
- edit!
+ edit! do
+ build_breadcrumb :edit
+ end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 64a706557..04dd281d5 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -21,6 +21,6 @@ class ApplicationController < ActionController::Base
# Overwriting the sign_out redirect path method
def after_sign_out_path_for(resource_or_scope)
new_user_session_path
- end
+ end
end
diff --git a/app/controllers/breadcrumb_controller.rb b/app/controllers/breadcrumb_controller.rb
new file mode 100644
index 000000000..143651b52
--- /dev/null
+++ b/app/controllers/breadcrumb_controller.rb
@@ -0,0 +1,41 @@
+class BreadcrumbController < InheritedResources::Base
+
+ include BreadcrumbHelper
+
+ def show
+ show! do
+ build_breadcrumb :show
+ end
+ end
+
+ def index
+ index! do
+ build_breadcrumb :index
+ end
+ end
+
+ def edit
+ edit! do
+ build_breadcrumb :edit
+ end
+ end
+
+ def update
+ update! do |success, failure|
+ build_breadcrumb :edit
+ end
+ end
+
+ def new
+ new! do
+ build_breadcrumb :new
+ end
+ end
+
+ def create
+ create! do |success, failure|
+ build_breadcrumb :new
+ end
+ end
+
+end
diff --git a/app/controllers/chouette_controller.rb b/app/controllers/chouette_controller.rb
index f9f832f37..df082d8cd 100644
--- a/app/controllers/chouette_controller.rb
+++ b/app/controllers/chouette_controller.rb
@@ -1,9 +1,10 @@
-class ChouetteController < InheritedResources::Base
+class ChouetteController < BreadcrumbController
include ApplicationHelper
+ include BreadcrumbHelper
before_filter :switch_referential
-
+
def switch_referential
Apartment::Database.switch(referential.slug)
end
@@ -11,5 +12,5 @@ class ChouetteController < InheritedResources::Base
def referential
@referential ||= current_organisation.referentials.find params[:referential_id]
end
-
+
end
diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb
index 27f0f9235..025c0fdee 100644
--- a/app/controllers/companies_controller.rb
+++ b/app/controllers/companies_controller.rb
@@ -3,6 +3,7 @@ class CompaniesController < ChouetteController
respond_to :html
respond_to :xml
respond_to :json
+ respond_to :js, :only => :index
belongs_to :referential, :parent_class => Referential
@@ -14,8 +15,10 @@ class CompaniesController < ChouetteController
redirect_to params.merge(:page => 1)
end
}
+ build_breadcrumb :index
end
end
+
protected
def collection
diff --git a/app/controllers/compliance_check_tasks_controller.rb b/app/controllers/compliance_check_tasks_controller.rb
index 45794199a..d28ca34ae 100644
--- a/app/controllers/compliance_check_tasks_controller.rb
+++ b/app/controllers/compliance_check_tasks_controller.rb
@@ -1,7 +1,10 @@
class ComplianceCheckTasksController < ChouetteController
+ defaults :resource_class => ComplianceCheckTask
+
respond_to :html, :js
belongs_to :referential
+
def references
@references = referential.send(params[:type]).where("name ilike ?", "%#{params[:q]}%")
respond_to do |format|
@@ -13,9 +16,16 @@ class ComplianceCheckTasksController < ChouetteController
def rule_parameter_set
@rule_parameter_set = compliance_check_task.rule_parameter_set_archived
+ build_breadcrumb :edit
render "rule_parameter_sets/show"
end
+ def create
+ create! do |success, failure|
+ success.html { flash[:notice] = I18n.t('compliance_check_tasks.new.flash'); redirect_to referential_compliance_check_tasks_path(@referential) }
+ end
+ end
+
protected
alias_method :compliance_check_task, :resource
diff --git a/app/controllers/connection_link_areas_controller.rb b/app/controllers/connection_link_areas_controller.rb
index 40f029801..eceb1b0fc 100644
--- a/app/controllers/connection_link_areas_controller.rb
+++ b/app/controllers/connection_link_areas_controller.rb
@@ -10,7 +10,13 @@ class ConnectionLinkAreasController < ChouetteController
def areas_maps
areas.collect do |area|
- { :id => area.id.to_s, :name => "#{area.name} #{area.country_code}" }
+ { :id => area.id.to_s,
+ :name => area.name,
+ :country_code => area.country_code,
+ :zip_code => area.zip_code || "",
+ :city_name => area.city_name || "",
+ :area_type => t("area_types.label.#{area.area_type.underscore}")
+ }
end
end
diff --git a/app/controllers/connection_links_controller.rb b/app/controllers/connection_links_controller.rb
index 6f225af1f..9f08babf0 100644
--- a/app/controllers/connection_links_controller.rb
+++ b/app/controllers/connection_links_controller.rb
@@ -8,6 +8,7 @@ class ConnectionLinksController < ChouetteController
respond_to :html, :xml, :json
respond_to :kml, :only => :show
+ respond_to :js, :only => :index
def index
index! do |format|
@@ -15,19 +16,23 @@ class ConnectionLinksController < ChouetteController
if collection.out_of_bounds?
redirect_to params.merge(:page => 1)
end
+ build_breadcrumb :index
}
end
end
def show
@map = ConnectionLinkMap.new(resource).with_helpers(self)
- show!
+ show! do
+ build_breadcrumb :show
+ end
end
def select_areas
@connection_link = connection_link
@departure = connection_link.departure
@arrival = connection_link.arrival
+ build_breadcrumb :show
end
protected
diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb
index 2f14ab359..cb555a3dd 100644
--- a/app/controllers/exports_controller.rb
+++ b/app/controllers/exports_controller.rb
@@ -1,5 +1,6 @@
class ExportsController < ChouetteController
-
+ defaults :resource_class => Export
+
respond_to :html, :xml, :json, :js
respond_to :zip, :only => :show
@@ -7,6 +8,7 @@ class ExportsController < ChouetteController
def new
new! do
+ build_breadcrumb :new
available_exports
end
end
@@ -14,13 +16,14 @@ class ExportsController < ChouetteController
def create
create! do |success, failure|
available_exports
- success.html { redirect_to referential_exports_path(@referential) }
+ success.html { flash[:notice] = I18n.t('exports.new.flash')+"<br/>"+I18n.t('exports.new.flash2'); redirect_to referential_exports_path(@referential) }
end
end
def show
show! do |format|
format.zip { send_file @export.file, :type => :zip }
+ build_breadcrumb :show
end
end
diff --git a/app/controllers/group_of_lines_controller.rb b/app/controllers/group_of_lines_controller.rb
index a38b22c10..3b91f8dd6 100644
--- a/app/controllers/group_of_lines_controller.rb
+++ b/app/controllers/group_of_lines_controller.rb
@@ -4,13 +4,16 @@ class GroupOfLinesController < ChouetteController
respond_to :xml
respond_to :json
respond_to :kml, :only => :show
+ respond_to :js, :only => :index
belongs_to :referential
def show
@map = GroupOfLineMap.new(resource).with_helpers(self)
- @lines = resource.lines.order(:name).paginate(:page => params[:page])
- show!
+ @lines = resource.lines.order(:name)
+ show! do
+ build_breadcrumb :show
+ end
end
def index
@@ -19,15 +22,16 @@ class GroupOfLinesController < ChouetteController
if collection.out_of_bounds?
redirect_to params.merge(:page => 1)
end
+ build_breadcrumb :index
}
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/help_controller.rb b/app/controllers/help_controller.rb
index 91e8088de..7d4c3409d 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -1,4 +1,11 @@
-class HelpController < ApplicationController
+class HelpController < ActionController::Base
+ layout "application"
+ protect_from_forgery
+ before_filter :set_locale
+
+ def set_locale
+ I18n.locale = session[:language] || I18n.default_locale
+ end
def show
@page = HelpPage.find(slug)
diff --git a/app/controllers/import_tasks_controller.rb b/app/controllers/import_tasks_controller.rb
index 36710bb69..bee70d196 100644
--- a/app/controllers/import_tasks_controller.rb
+++ b/app/controllers/import_tasks_controller.rb
@@ -1,16 +1,19 @@
class ImportTasksController < ChouetteController
+ defaults :resource_class => ImportTask
respond_to :html, :xml, :json
- respond_to :js, :only => :show
+ respond_to :js, :only => [:show, :index]
belongs_to :referential
def new
new! do
+ build_breadcrumb :new
available_imports
end
end
def show
show! do
+ build_breadcrumb :show
if import_task.completed?
@files_stats = import_task.result["files"]["stats"]
@files_list = import_task.result["files"]["list"]
@@ -25,9 +28,9 @@ class ImportTasksController < ChouetteController
end
def create
- create! do |success, failure|
+ create! do |success, failure|
available_imports
- success.html { redirect_to referential_import_tasks_path(@referential) }
+ success.html { flash[:notice] = I18n.t('import_tasks.new.flash'); redirect_to referential_import_tasks_path(@referential) }
end
end
diff --git a/app/controllers/journey_patterns_controller.rb b/app/controllers/journey_patterns_controller.rb
index 0274b9b71..18e7ee28b 100644
--- a/app/controllers/journey_patterns_controller.rb
+++ b/app/controllers/journey_patterns_controller.rb
@@ -2,6 +2,7 @@ class JourneyPatternsController < ChouetteController
defaults :resource_class => Chouette::JourneyPattern
respond_to :html
+ respond_to :json, :only => :index
respond_to :js, :only => [:new_vehicle_journey, :show]
respond_to :kml, :only => :show
@@ -14,7 +15,7 @@ class JourneyPatternsController < ChouetteController
alias_method :route, :parent
alias_method :journey_pattern, :resource
- def index
+ def index
index! do |format|
format.html { redirect_to referential_line_route_path(@referential,@line,@route) }
end
@@ -27,7 +28,9 @@ 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
+ build_breadcrumb :show
+ end
end
def new_vehicle_journey
@@ -35,10 +38,16 @@ class JourneyPatternsController < ChouetteController
@vehicle_journey.update_journey_pattern(resource)
render "vehicle_journeys/select_journey_pattern"
end
- # overwrite inherited resources to use delete instead of destroy
+ # overwrite inherited resources to use delete instead of destroy
# foreign keys will propagate deletion)
def destroy_resource(object)
object.delete
end
+
+ def collection
+ @q = route.journey_patterns.search( params[:q])
+ @journey_patterns ||= @q.result(:distinct => true).order(:name)
+ end
+
end
diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb
index effb0deba..aee3f8c67 100644
--- a/app/controllers/lines_controller.rb
+++ b/app/controllers/lines_controller.rb
@@ -4,6 +4,7 @@ class LinesController < ChouetteController
respond_to :xml
respond_to :json
respond_to :kml, :only => :show
+ respond_to :js, :only => :index
belongs_to :referential
@@ -13,16 +14,18 @@ class LinesController < ChouetteController
if collection.out_of_bounds?
redirect_to params.merge(:page => 1)
end
+ build_breadcrumb :index
}
end
end
-
def show
@map = LineMap.new(resource).with_helpers(self)
@routes = @line.routes
@group_of_lines = @line.group_of_lines
- show!
+ show! do
+ build_breadcrumb :show
+ end
end
# overwrite inherited resources to use delete instead of destroy
@@ -34,7 +37,8 @@ class LinesController < ChouetteController
def destroy_all
objects =
get_collection_ivar || set_collection_ivar(end_of_association_chain.where(:id => params[:ids]))
- objects.destroy_all
+ #objects.destroy_all
+ objects.each { |object| object.delete }
respond_with(objects, :location => smart_collection_url)
end
@@ -58,6 +62,21 @@ class LinesController < ChouetteController
end
def collection
+ if params[:q] && params[:q]["network_id_eq"] == "-1"
+ params[:q]["network_id_eq"] = ""
+ params[:q]["network_id_blank"] = "1"
+ end
+
+ if params[:q] && params[:q]["company_id_eq"] == "-1"
+ params[:q]["company_id_eq"] = ""
+ params[:q]["company_id_blank"] = "1"
+ end
+
+ if params[:q] && params[:q]["group_of_lines_id_eq"] == "-1"
+ params[:q]["group_of_lines_id_eq"] = ""
+ params[:q]["group_of_lines_id_blank"] = "1"
+ end
+
@q = referential.lines.search(params[:q])
@lines ||= @q.result(:distinct => true).order(:number).paginate(:page => params[:page]).includes([:network, :company])
end
diff --git a/app/controllers/networks_controller.rb b/app/controllers/networks_controller.rb
index b911ab603..25c4caaac 100644
--- a/app/controllers/networks_controller.rb
+++ b/app/controllers/networks_controller.rb
@@ -4,12 +4,15 @@ class NetworksController < ChouetteController
respond_to :xml
respond_to :json
respond_to :kml, :only => :show
+ respond_to :js, :only => :index
belongs_to :referential
def show
@map = NetworkMap.new(resource).with_helpers(self)
- show!
+ show! do
+ build_breadcrumb :show
+ end
end
def index
@@ -19,6 +22,7 @@ class NetworksController < ChouetteController
redirect_to params.merge(:page => 1)
end
}
+ build_breadcrumb :index
end
end
diff --git a/app/controllers/organisations_controller.rb b/app/controllers/organisations_controller.rb
index 7e2edb220..9faea18a5 100644
--- a/app/controllers/organisations_controller.rb
+++ b/app/controllers/organisations_controller.rb
@@ -1,4 +1,6 @@
-class OrganisationsController < InheritedResources::Base
+class OrganisationsController < BreadcrumbController
+
+ defaults :resource_class => Organisation
respond_to :html
def update
diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb
index de0b209ca..9cf4a5f62 100644
--- a/app/controllers/referentials_controller.rb
+++ b/app/controllers/referentials_controller.rb
@@ -1,4 +1,7 @@
-class ReferentialsController < InheritedResources::Base
+class ReferentialsController < BreadcrumbController
+
+ defaults :resource_class => Referential
+
respond_to :html
respond_to :json, :only => :show
respond_to :js, :only => :show
@@ -13,6 +16,8 @@ class ReferentialsController < InheritedResources::Base
:time_tables_count => resource.time_tables.count,
:referential_id => resource.id}
}
+ format.html { build_breadcrumb :show}
+
end
end
@@ -21,7 +26,7 @@ class ReferentialsController < InheritedResources::Base
@referential ||= current_organisation.referentials.find_by_id(params[:id])
end
def collection
- @referentials ||= current_organisation.referentials
+ @referentials ||= current_organisation.referentials.order(:name)
end
def build_resource
super.tap do |referential|
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
new file mode 100644
index 000000000..b02d3217a
--- /dev/null
+++ b/app/controllers/registrations_controller.rb
@@ -0,0 +1,16 @@
+ class RegistrationsController < Devise::RegistrationsController
+
+ prepend_before_filter :accept_user_creation, :only => [:new, :create]
+
+ private
+
+ def accept_user_creation
+ if !Rails.application.config.accept_user_creation
+ redirect_to root_path
+ return false
+ else
+ return true
+ end
+ end
+
+ end
diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb
index 7b5e096db..391a14d88 100644
--- a/app/controllers/routes_controller.rb
+++ b/app/controllers/routes_controller.rb
@@ -18,7 +18,9 @@ class RoutesController < ChouetteController
def show
@map = RouteMap.new(route).with_helpers(self)
@stop_points = route.stop_points.paginate(:page => params[:page])
- show!
+ show! do
+ build_breadcrumb :show
+ end
end
# overwrite inherited resources to use delete instead of destroy
diff --git a/app/controllers/rule_parameter_sets_controller.rb b/app/controllers/rule_parameter_sets_controller.rb
index fbd5281c8..a422bed15 100644
--- a/app/controllers/rule_parameter_sets_controller.rb
+++ b/app/controllers/rule_parameter_sets_controller.rb
@@ -1,4 +1,5 @@
class RuleParameterSetsController < ChouetteController
+ defaults :resource_class => RuleParameterSet
respond_to :html
respond_to :js, :only => [ :mode ]
@@ -6,9 +7,12 @@ class RuleParameterSetsController < ChouetteController
def new
@rule_parameter_set = RuleParameterSet.default( @referential)
- new!
+ new! do
+ build_breadcrumb :new
+ end
end
+
def destroy
if @referential.rule_parameter_sets.count == 1
flash[:alert] = "Suppression impossible, le referentiel doit compter au minimum un jeu de parametre."
diff --git a/app/controllers/stop_area_children_controller.rb b/app/controllers/stop_area_children_controller.rb
index 111fcb93c..f115ff35a 100644
--- a/app/controllers/stop_area_children_controller.rb
+++ b/app/controllers/stop_area_children_controller.rb
@@ -11,8 +11,14 @@ class StopAreaChildrenController < ChouetteController
protected
def children_maps
- children.collect do |child|
- { :id => child.id.to_s, :name => "#{child.name} #{child.country_code}" }
+ children.collect do |area|
+ { :id => area.id.to_s,
+ :name => area.name,
+ :country_code => area.country_code,
+ :zip_code => area.zip_code || "",
+ :city_name => area.city_name || "",
+ :area_type => t("area_types.label.#{area.area_type.underscore}")
+ }
end
end
diff --git a/app/controllers/stop_area_copies_controller.rb b/app/controllers/stop_area_copies_controller.rb
new file mode 100644
index 000000000..7c1fac8d9
--- /dev/null
+++ b/app/controllers/stop_area_copies_controller.rb
@@ -0,0 +1,30 @@
+class StopAreaCopiesController < ChouetteController
+ defaults :resource_class => StopAreaCopy
+ belongs_to :referential do
+ belongs_to :stop_area, :parent_class => Chouette::StopArea
+ end
+
+ actions :new, :create
+ respond_to :html, :only => :new
+
+ def new
+ @stop_area_copy = StopAreaCopy.new(:hierarchy => params[:hierarchy], :source => parent)
+ new! do
+ build_breadcrumb :new
+ end
+ end
+
+ def create
+ @stop_area_copy = StopAreaCopy.new(params[:stop_area_copy])
+ @stop_area = parent
+ if @stop_area_copy.save
+ redirect_to referential_stop_area_path( @referential,parent ), notice: I18n.t("stop_area_copies.new.success")
+ else
+ flash[:error] = I18n.t("stop_area_copies.errors.copy_aborted") + "<br>" + @stop_area_copy.errors.full_messages.join("<br>")
+ render :action => :new
+ end
+ end
+
+ protected
+
+end
diff --git a/app/controllers/stop_area_parents_controller.rb b/app/controllers/stop_area_parents_controller.rb
index 526c1cd42..1dbb0796c 100644
--- a/app/controllers/stop_area_parents_controller.rb
+++ b/app/controllers/stop_area_parents_controller.rb
@@ -9,8 +9,14 @@ class StopAreaParentsController < ChouetteController
end
def parents_maps
- parents.collect do |parent|
- { :id => parent.id.to_s, :name => "#{parent.name} #{parent.country_code}" }
+ parents.collect do |area|
+ { :id => area.id.to_s,
+ :name => area.name,
+ :country_code => area.country_code,
+ :zip_code => area.zip_code || "",
+ :city_name => area.city_name || "",
+ :area_type => t("area_types.label.#{area.area_type.underscore}")
+ }
end
end
diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb
index c433546b9..b164f4bc8 100644
--- a/app/controllers/stop_areas_controller.rb
+++ b/app/controllers/stop_areas_controller.rb
@@ -9,8 +9,7 @@ class StopAreasController < ChouetteController
end
respond_to :html, :kml, :xml, :json
-
- layout "without_sidebar", :only => [:edit, :update]
+ respond_to :js, :only => :index
# def complete
# @stop_areas = line.stop_areas
@@ -20,59 +19,89 @@ class StopAreasController < ChouetteController
def select_parent
@stop_area = stop_area
@parent = stop_area.parent
+ build_breadcrumb :edit
end
def add_children
@stop_area = stop_area
@children = stop_area.children
+ build_breadcrumb :edit
end
def add_routing_lines
@stop_area = stop_area
@lines = stop_area.routing_lines
+ build_breadcrumb :edit
end
def add_routing_stops
@stop_area = stop_area
@stops = stop_area.routing_stops
+ build_breadcrumb :edit
end
def access_links
@stop_area = stop_area
@generic_access_links = stop_area.generic_access_link_matrix
@detail_access_links = stop_area.detail_access_link_matrix
+ build_breadcrumb :edit
end
- def index
+ def index
request.format.kml? ? @per_page = nil : @per_page = 12
-
+ @country_codes = referential.stop_areas.collect(&:country_code).compact.uniq
index! do |format|
format.html {
if collection.out_of_bounds?
redirect_to params.merge(:page => 1)
end
+ build_breadcrumb :index
}
- end
+ end
+ end
+
+ def new
+ @map = StopAreaMap.new( Chouette::StopArea.new).with_helpers(self)
+ @map.editable = true
+ new! do
+ build_breadcrumb :show
+ end
+ end
+
+ def create
+ @map = StopAreaMap.new( Chouette::StopArea.new).with_helpers(self)
+ @map.editable = true
+
+ create!
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
+ build_breadcrumb :show
end
end
-
+
def edit
- stop_area.position ||= stop_area.default_position
+ edit! do
+ stop_area.position ||= stop_area.default_position
+ map.editable = true
+ build_breadcrumb :edit
+ end
+ end
+ def update
+ stop_area.position ||= stop_area.default_position
map.editable = true
- edit!
+
+ update!
end
def default_geometry
@@ -81,8 +110,14 @@ class StopAreasController < ChouetteController
redirect_to referential_stop_areas_path(@referential)
end
+ def country_codes
+ respond_to do |format|
+ format.json { render :json => referential.stop_areas.collect(&:country_code).compact.uniq.to_json }
+ end
+ end
+
protected
-
+
alias_method :stop_area, :resource
def map
@@ -91,7 +126,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/stop_point_areas_controller.rb b/app/controllers/stop_point_areas_controller.rb
index b307936f0..9544d0fe6 100644
--- a/app/controllers/stop_point_areas_controller.rb
+++ b/app/controllers/stop_point_areas_controller.rb
@@ -10,7 +10,13 @@ class StopPointAreasController < ChouetteController
def areas_maps
areas.collect do |area|
- { :id => area.id.to_s, :name => "#{area.name} #{area.country_code}" }
+ { :id => area.id.to_s,
+ :name => area.name,
+ :country_code => area.country_code,
+ :zip_code => area.zip_code || "",
+ :city_name => area.city_name || "",
+ :area_type => t("area_types.label.#{area.area_type.underscore}")
+ }
end
end
diff --git a/app/controllers/time_table_combinations_controller.rb b/app/controllers/time_table_combinations_controller.rb
new file mode 100644
index 000000000..ebae9f225
--- /dev/null
+++ b/app/controllers/time_table_combinations_controller.rb
@@ -0,0 +1,46 @@
+class TimeTableCombinationsController < ChouetteController
+ respond_to :js, :only => [:new,:create]
+
+ belongs_to :referential do
+ belongs_to :time_table, :parent_class => Chouette::TimeTable
+ end
+ after_filter :clean_flash
+
+ def clean_flash
+ # only run this in case it's an Ajax request.
+ return unless request.xhr?
+ flash.discard
+ end
+
+ def new
+ @time_table_combination = TimeTableCombination.new(:source_id => parent.id)
+ render :action => :new
+ end
+
+
+ def create
+ Rails.logger.warn( params.inspect)
+ @time_table_combination = TimeTableCombination.new( params[:time_table_combination].merge( :source_id => parent.id))
+ Rails.logger.warn( @time_table_combination.inspect)
+ @year = params[:year] ? params[:year].to_i : Date.today.cwyear
+ if @time_table_combination.valid?
+ begin
+ @time_table = @time_table_combination.combine
+ flash[:notice] = t('time_table_combinations.success')
+ render "create_success"
+ rescue => e
+ Rails.logger.error( "TimeTableCombination error, @time_table_combination=#{@time_table_combination.inspect}")
+ Rails.logger.error( e.inspect)
+ flash[:error] = t('time_table_combinations.failure')
+ render "create_failure"
+ end
+ else
+ render "create_failure"
+ end
+
+ end
+ protected
+
+ alias_method :time_table_combination, :resource
+
+end
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb
index 00109aa76..be1738060 100644
--- a/app/controllers/time_tables_controller.rb
+++ b/app/controllers/time_tables_controller.rb
@@ -1,24 +1,37 @@
class TimeTablesController < ChouetteController
+ include TimeTablesHelper
defaults :resource_class => Chouette::TimeTable
respond_to :html
respond_to :xml
respond_to :json
+ respond_to :js, :only => :index
belongs_to :referential
def show
+
@year = params[:year] ? params[:year].to_i : Date.today.cwyear
- show!
+ @time_table_combination = TimeTableCombination.new
+ show! do
+ build_breadcrumb :show
+ end
+ end
+
+ def new
+ @autocomplete_items = ActsAsTaggableOn::Tag.all
+ new! do
+ build_breadcrumb :new
+ end
end
- def comment_filter
- respond_to do |format|
- format.json { render :json => filtered_time_tables_maps}
- end
-
+ def edit
+ edit! do
+ build_breadcrumb :edit
+ @autocomplete_items = ActsAsTaggableOn::Tag.all
+ end
end
- def index
+ def index
request.format.kml? ? @per_page = nil : @per_page = 12
index! do |format|
@@ -26,27 +39,47 @@ class TimeTablesController < ChouetteController
if collection.out_of_bounds?
redirect_to params.merge(:page => 1)
end
+ build_breadcrumb :index
}
- end
+ end
end
+ def duplicate
+ @time_table = Chouette::TimeTable.find params[:id]
+ # prepare breadcrumb before prepare data for new timetable
+ build_breadcrumb :edit
+ @time_table = @time_table.duplicate
+ render :new
+ end
- protected
-
- def filtered_time_tables_maps
- filtered_time_tables.collect do |time_table|
- { :id => time_table.id, :name => time_table.comment }
+ def tags
+ @tags = ActsAsTaggableOn::Tag.where("tags.name LIKE ?", "%#{params[:tag]}%")
+ respond_to do |format|
+ format.json { render :json => @tags.map{|t| {:id => t.id, :name => t.name }} }
end
end
- def filtered_time_tables
- referential.time_tables.select{ |t| t.comment =~ /#{params[:q]}/i }
- end
- def collection
- @q = referential.time_tables.search(params[:q])
+ protected
+
+ def collection
+ ransack_params = params[:q]
+ # Hack to delete params can't be used by ransack
+ tag_search = ransack_params["tag_search"].split(",").collect(&:strip) if ransack_params.present? && ransack_params["tag_search"].present?
+ ransack_params.delete("tag_search") if ransack_params.present?
+
+ selected_time_tables = tag_search ? select_time_tables.tagged_with(tag_search, :wild => true, :any => true) : select_time_tables
+ @q = selected_time_tables.search(ransack_params)
@time_tables ||= @q.result(:distinct => true).order(:comment).paginate(:page => params[:page])
end
+ def select_time_tables
+ if params[:route_id]
+ referential.time_tables.joins( vehicle_journeys: :route).where( "routes.id IN (#{params[:route_id]})")
+ else
+ referential.time_tables
+ end
+ end
+
def resource_url(time_table = nil)
referential_time_table_path(referential, time_table || resource)
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index b57b9d54a..2b1c2bd14 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1,4 +1,6 @@
-class UsersController < InheritedResources::Base
+class UsersController < BreadcrumbController
+
+ defaults :resource_class => User
def create
@user = current_organisation.users.build(params[:user])
diff --git a/app/controllers/vehicle_journey_exports_controller.rb b/app/controllers/vehicle_journey_exports_controller.rb
index f29cd01aa..0cc30f23a 100644
--- a/app/controllers/vehicle_journey_exports_controller.rb
+++ b/app/controllers/vehicle_journey_exports_controller.rb
@@ -5,32 +5,35 @@ class VehicleJourneyExportsController < ChouetteController
end
end
- respond_to :csv, :only => [:new, :index]
- respond_to :xls, :only => [:new, :index]
-
- def new
- new! do |format|
- @vehicle_journey_export = VehicleJourneyExport.new(:route => @route)
-
- format.csv { render text: @vehicle_journey_export.to_csv }
- format.xls { render text: @vehicle_journey_export.to_csv(col_sep: "\t") }
- end
- end
+ respond_to :csv, :only => [:index]
+ respond_to :zip, :only => [:index]
+ #respond_to :xls, :only => [:index]
- def index
- index! do |format|
- @vehicle_journey_export = VehicleJourneyExport.new(:route => @route)
-
- format.csv { render text: @vehicle_journey_export.to_csv }
- format.xls { render text: @vehicle_journey_export.to_csv(col_sep: "\t") }
+ def index
+ index! do |format|
+ 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
+ protected
+
+
alias_method :route, :parent
-
+
def collection
- @vehicle_journey_exports = []
+ @vehicle_journeys ||= route.vehicle_journeys.includes(:vehicle_journey_at_stops).order("vehicle_journey_at_stops.departure_time")
end
+ alias_method :vehicle_journeys, :collection
end
diff --git a/app/controllers/vehicle_journey_imports_controller.rb b/app/controllers/vehicle_journey_imports_controller.rb
index e3a6dde77..7ce0aca23 100644
--- a/app/controllers/vehicle_journey_imports_controller.rb
+++ b/app/controllers/vehicle_journey_imports_controller.rb
@@ -1,4 +1,6 @@
class VehicleJourneyImportsController < ChouetteController
+ defaults :resource_class => VehicleJourneyImport
+
belongs_to :referential do
belongs_to :line, :parent_class => Chouette::Line do
belongs_to :route, :parent_class => Chouette::Route
@@ -10,36 +12,22 @@ class VehicleJourneyImportsController < ChouetteController
def new
@vehicle_journey_import = VehicleJourneyImport.new(:route => route)
- flash[:notice] = "A CSV or Excel file can be used to import records. The first row should be the column name.
-<p>
-The following columns are allowed :
-<ul>
- <li>
- <strong>stop_point_id</strong> -
- Integer type
- </li>
- <li>
- <strong>stop_area_name</strong> -
- String type
- </li>
- <li>
- <strong>published_journey_name </strong> -
- String type
- </li>
- <li>
- <strong>published_journey_name </strong> -
- String type ....
- </li>
-</ul>
-</p>"
- new!
+ new! do
+ build_breadcrumb :new
+ end
end
def create
- @vehicle_journey_import = VehicleJourneyImport.new(params[:vehicle_journey_import].merge({:route => route}))
+ @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: "Import successful"
+ 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
end
end
diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb
index 848fda507..9e809a719 100644
--- a/app/controllers/vehicle_journeys_controller.rb
+++ b/app/controllers/vehicle_journeys_controller.rb
@@ -1,7 +1,7 @@
class VehicleJourneysController < ChouetteController
defaults :resource_class => Chouette::VehicleJourney
- respond_to :js, :only => [:select_journey_pattern, :edit, :new]
+ respond_to :js, :only => [:select_journey_pattern, :edit, :new, :index]
belongs_to :referential do
belongs_to :line, :parent_class => Chouette::Line do
@@ -9,10 +9,6 @@ class VehicleJourneysController < ChouetteController
end
end
- def timeless
- @vehicle_journeys = parent.vehicle_journeys.timeless
- end
-
def select_journey_pattern
if params[:journey_pattern_id]
selected_journey_pattern = Chouette::JourneyPattern.find( params[:journey_pattern_id])
@@ -30,31 +26,46 @@ class VehicleJourneysController < ChouetteController
update!(:alert => t('activerecord.errors.models.vehicle_journey.invalid_times'))
end
- def index
- index! do |format|
- format.html {
- @matrix ||= matrix
- if collection.out_of_bounds?
- redirect_to params.merge(:page => 1)
- end
- }
- end
+ def index
+ index! do
+ @matrix ||= matrix
+ if collection.out_of_bounds?
+ redirect_to params.merge(:page => 1)
+ end
+ build_breadcrumb :index
+ end
end
- # overwrite inherited resources to use delete instead of destroy
+ # overwrite inherited resources to use delete instead of destroy
# foreign keys will propagate deletion)
def destroy_resource(object)
object.delete
end
protected
-
+
alias_method :vehicle_journey, :resource
-
+
def collection
- @q = parent.sorted_vehicle_journeys.search(params[:q])
- @vehicle_journeys ||= @q.result.order( "vehicle_journey_at_stops.departure_time").paginate(:page => params[:page], :per_page => 8)
+ @vehicle_filter = VehicleFilter.new( adapted_params)
+ @q = @vehicle_filter.vehicle_journeys.search( @vehicle_filter.filtered_params)
+ @vehicle_journeys ||= @q.result( :distinct => true ).order( "vehicle_journey_at_stops.departure_time").paginate(:page => params[:page], :per_page => 8)
+ end
+
+ def adapted_params
+ params.tap do |adapted_params|
+ adapted_params.merge!( :route => parent)
+ hour_entry = "vehicle_journey_at_stops_departure_time_gt(4i)".to_sym
+ if params[:q] && params[:q][ hour_entry]
+ adapted_params[:q].merge! hour_entry => (params[:q][ hour_entry].to_i - utc_offset)
+ end
+ end
+ end
+ def utc_offset
+ # Ransack Time eval - utc eval
+ sample = [2001,1,1,10,0]
+ Time.zone.local(*sample).utc.hour - Time.utc(*sample).hour
end
def matrix
@@ -62,7 +73,7 @@ class VehicleJourneysController < ChouetteController
Chouette::VehicleJourney.find( @vehicle_journeys.map { |v| v.id } ).
each do |vj|
vj.vehicle_journey_at_stops.each do |vjas|
- hash[ "#{vj.id}-#{vjas.stop_point_id}"] = vjas
+ hash[ "#{vj.id}-#{vjas.stop_point_id}"] = vjas
end
end
end
diff --git a/app/controllers/vehicle_translations_controller.rb b/app/controllers/vehicle_translations_controller.rb
index af54001ae..65a0db7fe 100644
--- a/app/controllers/vehicle_translations_controller.rb
+++ b/app/controllers/vehicle_translations_controller.rb
@@ -1,5 +1,5 @@
class VehicleTranslationsController < ChouetteController
- respond_to :html, :only => [:create]
+ respond_to :js, :only => [:new, :create]
belongs_to :referential do
belongs_to :line, :parent_class => Chouette::Line do
@@ -8,17 +8,36 @@ class VehicleTranslationsController < ChouetteController
end
end
end
+ after_filter :clean_flash
+
+ def clean_flash
+ # only run this in case it's an Ajax request.
+ return unless request.xhr?
+
+ flash.discard
+ end
+
+ def new
+ @vehicle_translation = VehicleTranslation.new( :vehicle_journey_id => parent.id, :count => 1, :duration => 1)
+ render :action => :new
+ end
def create
+ @vehicle_translation = VehicleTranslation.new( params[:vehicle_translation].merge( :vehicle_journey_id => parent.id))
+
begin
- translation = VehicleTranslation.new( params[:vehicle_translation].merge( :vehicle_journey_id => parent.id))
- translation.translate
- flash[:notice] = t('vehicle_translations.success', :count => translation.count)
- rescue
+ if @vehicle_translation.valid?
+ @vehicle_translation.translate
+ flash[:notice] = t('vehicle_translations.success', :count => @vehicle_translation.count)
+ else
+ flash[:alert] = @vehicle_translation.errors[ :vehicle_journey_id] unless @vehicle_translation.errors[ :vehicle_journey_id].empty?
+ end
+ rescue => e
+ Rails.logger.error( "VehicleTranslation error, @vehicle_translation=#{@vehicle_translation.inspect}")
+ Rails.logger.error( e.inspect)
flash[:alert] = t('vehicle_translations.failure')
end
- redirect_to referential_line_route_vehicle_journeys_path(@referential, @line, @route)
-
+ render :action => :new
end
-
+
end
diff --git a/app/exporters/chouette/hub/city_code_exporter.rb b/app/exporters/chouette/hub/city_code_exporter.rb
new file mode 100644
index 000000000..1279313eb
--- /dev/null
+++ b/app/exporters/chouette/hub/city_code_exporter.rb
@@ -0,0 +1,35 @@
+class Chouette::Hub::CityCodeExporter
+ include ERB::Util
+ attr_accessor :city_code, :city_name, :directory, :template
+
+ def initialize(city_code, city_name, directory)
+ @city_code = city_code
+ @city_name = city_name
+ @directory = directory
+ @template = File.open('app/views/api/hub/communes.hub.erb' ){ |f| f.read }
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/COMMUNES.TXT"
+ end
+
+ def self.save( city_codes, directory, hub_export)
+ city_codes.keys.sort.each do |key|
+ self.new( key, city_codes[key], directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|COMMUNE_COUNT", :arguments => {"0" => city_codes.keys.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("COMMUNES\u000D\u000A") if f.size == 0
+ f.write(render)
+ end
+ end
+end
diff --git a/app/exporters/chouette/hub/commercial_stop_area_exporter.rb b/app/exporters/chouette/hub/commercial_stop_area_exporter.rb
new file mode 100644
index 000000000..da134a08f
--- /dev/null
+++ b/app/exporters/chouette/hub/commercial_stop_area_exporter.rb
@@ -0,0 +1,36 @@
+class Chouette::Hub::CommercialStopAreaExporter
+ include ERB::Util
+ attr_accessor :stop_area, :directory, :template
+
+ def initialize(stop_area, directory)
+ @stop_area = stop_area
+ @directory = directory
+ @template = File.open('app/views/api/hub/arrets_generiques.hub.erb' ){ |f| f.read }
+ @type = "ONNNNNNNNNNNNNNNNN"
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/ARRET.TXT"
+ end
+
+ def self.save( stop_areas, directory, hub_export)
+ stop_areas.each do |stop_area|
+ self.new( stop_area, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|COMMERCIAL_STOP_AREA_COUNT", :arguments => {"0" => stop_areas.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("ARRET\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if stop_area.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/company_exporter.rb b/app/exporters/chouette/hub/company_exporter.rb
new file mode 100644
index 000000000..142853b22
--- /dev/null
+++ b/app/exporters/chouette/hub/company_exporter.rb
@@ -0,0 +1,35 @@
+class Chouette::Hub::CompanyExporter
+ include ERB::Util
+ attr_accessor :company, :directory, :template
+
+ def initialize(company, directory)
+ @company = company
+ @directory = directory
+ @template = File.open('app/views/api/hub/transporteurs.hub.erb' ){ |f| f.read }
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/TRANSPORTEUR.TXT"
+ end
+
+ def self.save( companies, directory, hub_export)
+ companies.each do |company|
+ self.new( company, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|COMPANY_COUNT", :arguments => {"0" => companies.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("TRANSPORTEUR\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if company.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/connection_link_exporter.rb b/app/exporters/chouette/hub/connection_link_exporter.rb
new file mode 100644
index 000000000..0db286434
--- /dev/null
+++ b/app/exporters/chouette/hub/connection_link_exporter.rb
@@ -0,0 +1,40 @@
+class Chouette::Hub::ConnectionLinkExporter
+ include ERB::Util
+ attr_accessor :connection_link, :directory, :template
+
+ def initialize(connection_link, directory, count)
+ @connection_link = connection_link
+ @directory = directory
+ @count = count
+ @template = File.open('app/views/api/hub/correspondances.hub.erb' ){ |f| f.read }
+ @departure = Chouette::StopArea.find(@connection_link.departure_id) if @connection_link.departure_id
+ @arrival = Chouette::StopArea.find(@connection_link.arrival_id) if @connection_link.arrival_id
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/CORRESPONDANCE.TXT"
+ end
+
+ def self.save( connection_links, directory, hub_export)
+ count = 1
+ connection_links.each do |connection_link|
+ self.new( connection_link, directory, count).tap do |specific_exporter|
+ specific_exporter.save
+ count += 1
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|CONNECTION_LINK_COUNT", :arguments => {"0" => connection_links.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("CORRESPONDANCE\u000D\u000A") if f.size == 0
+ f.write(render) if (connection_link.present? && connection_link.link_distance.present?)
+ end
+ end
+end
+
diff --git a/app/exporters/chouette/hub/direction_exporter.rb b/app/exporters/chouette/hub/direction_exporter.rb
new file mode 100644
index 000000000..03c4c8c85
--- /dev/null
+++ b/app/exporters/chouette/hub/direction_exporter.rb
@@ -0,0 +1,39 @@
+class Chouette::Hub::DirectionExporter
+ include ERB::Util
+ attr_accessor :journey_pattern, :directory, :template
+
+ def initialize(journey_pattern, directory)
+ @journey_pattern = journey_pattern
+ @directory = directory
+ @template = File.open('app/views/api/hub/directions.hub.erb' ){ |f| f.read }
+ #@arrival_stop_point = Chouette::StopPoint.find(@journey_pattern.arrival_stop_point_id) if @journey_pattern.arrival_stop_point_id
+ #@direction = Chouette::StopArea.find(@arrival_stop_point.stop_area_id) if @arrival_stop_point
+ route = Chouette::Route.find(@journey_pattern.route_id) if @journey_pattern.route_id
+ @line = Chouette::Line.find(route.line_id) if route
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/DIRECTION.TXT"
+ end
+
+ def self.save( journey_patterns, directory, hub_export)
+ journey_patterns.each do |journey_pattern|
+ self.new( journey_pattern, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|DIRECTION_COUNT", :arguments => {"0" => journey_patterns.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("DIRECTION\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if journey_pattern.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/exporter.rb b/app/exporters/chouette/hub/exporter.rb
new file mode 100644
index 000000000..58454a0cb
--- /dev/null
+++ b/app/exporters/chouette/hub/exporter.rb
@@ -0,0 +1,249 @@
+class Chouette::Hub::Exporter
+ require "zip"
+
+ attr_reader :referential
+ attr_reader :hub_export, :lines, :routes, :journey_patterns
+ attr_reader :time_tables, :vehicle_journeys
+
+ def initialize(referential, hub_export)
+ @referential = referential
+ @hub_export = hub_export
+ @lines = nil
+ @routes = nil
+ @journey_patterns = nil
+ @time_tables = nil
+ @vehicle_journeys = nil
+ end
+
+ def select_time_tables(start_date, end_date)
+ #TODO considere options[:o], options[:id]
+ all_time_tables = Chouette::TimeTable.all
+ time_tables = []
+ s_date = Date.strptime(start_date, "%Y-%m-%d")
+ e_date = Date.strptime(end_date, "%Y-%m-%d")
+ while s_date <= e_date
+ (all_time_tables - time_tables).each { |time_table| time_tables << time_table if time_table.include_day?(s_date) }
+ s_date = s_date.next_day
+ end
+ return time_tables
+ end
+
+ def select_lines(object, ids)
+ if object == "network"
+ ids.present? ? Chouette::Line.includes(:routes).where( :network_id => ids.split(",")).order(:objectid) :
+ Chouette::Line.joins(:network).includes(:routes).order(:objectid)
+ elsif object == "company"
+ ids.present? ? Chouette::Line.includes(:routes).where( :company_id => ids.split(",")).order(:objectid) :
+ Chouette::Line.joins(:company).includes(:routes).order(:objectid)
+ elsif object == "line" && ids.present?
+ Chouette::Line.includes(:routes).where( :id => ids.split(",")).order(:objectid)
+ else
+ Chouette::Line.includes(:routes).order(:objectid)
+ end
+ end
+
+ def time_tables_exportable?
+ time_tables
+ end
+
+ def routes_exportable?
+ routes # && routes.size < 150
+ end
+
+ def lines_exportable?
+ lines # && lines.size < 150
+ end
+
+ def journey_patterns_exportable?
+ journey_patterns # && journey_patterns.size < 150
+ end
+
+ def vehicle_journeys_exportable?
+ vehicle_journeys
+ end
+
+ def log_overflow_warning( target_class)
+ hub_export.log_messages.create( :severity => "warning", :key => "EXPORT_ERROR|EXCEPTION",
+ :arguments => {"0" => I18n.t( 'export_log_messages.messages.overflow',
+ :count => 150, :data => target_class.model_name.human.pluralize)})
+ end
+
+ def export(zip_file_path, options = {})
+ begin
+ referential.switch
+
+ FileUtils.rm(zip_file_path) if File.exists? zip_file_path
+
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT", :arguments => {"0" => "HUB"})
+
+ Dir.mktmpdir(nil, "/tmp"){ |temp_dir|
+
+ @time_tables = select_time_tables(options[:start_date], options[:end_date])
+
+ @lines = select_lines( options[:o], options[:id] )
+
+ @routes = []
+ if @lines
+ @lines.each { |line| @routes << Chouette::Route.where( "line_id = ?", line.id ).order(:wayback) }
+ end
+
+ @journey_patterns = []
+ if @routes
+ @routes.each { |subroutes| @journey_patterns << Chouette::JourneyPattern.where( :route_id => subroutes.map(&:id) ).order(:objectid) }
+ end
+ @journey_patterns = @journey_patterns.flatten
+
+ @routes = @routes.flatten
+ @vehicle_journeys = Chouette::VehicleJourney.where(:route_id => @routes.map(&:id)).order(:objectid) if routes_exportable?
+
+ rts = []
+ jps = []
+ vjs = []
+ tts = []
+ @vehicle_journeys.each do |vj|
+ unless (vj.time_tables & @time_tables).empty?
+ vjs << vj
+ tts << (vj.time_tables & @time_tables)
+ rts << vj.route_id
+ jps << vj.journey_pattern_id
+ end
+ end
+ @time_tables = tts.flatten.uniq
+ @vehicle_journeys = vjs.uniq
+ rts = rts.flatten.uniq
+ jps = jps.flatten.uniq
+
+ @routes.delete_if {|r| !(rts.include?(r.id)) }
+ @journey_patterns.delete_if {|jp| !(jps.include?(jp.id)) }
+
+
+ vehicle_journey_at_stops = Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => @vehicle_journeys.map(&:id) ) #.order(:id) if vehicle_journeys_exportable?
+
+ if time_tables_exportable?
+ Chouette::Hub::TimeTableExporter.save(@time_tables, temp_dir, hub_export)
+ else
+ log_overflow_warning(Chouette::TimeTable)
+ end
+
+ if journey_patterns_exportable?
+ Chouette::Hub::RouteExporter.save(@routes, temp_dir, hub_export)
+ Chouette::Hub::JourneyPatternExporter.save(@journey_patterns, temp_dir, hub_export)
+ Chouette::Hub::DirectionExporter.save(@journey_patterns, temp_dir, hub_export)
+ else
+ log_overflow_warning(Chouette::JourneyPattern) if routes_exportable?
+ end
+
+ if vehicle_journeys_exportable?
+ Chouette::Hub::VehicleJourneyExporter.save(@vehicle_journeys, temp_dir, hub_export)
+ Chouette::Hub::VehicleJourneyOperationExporter.save(@vehicle_journeys, temp_dir, hub_export)
+ #Chouette::Hub::VehicleJourneyAtStopExporter.save(vehicle_journey_at_stops, temp_dir, hub_export)
+ Chouette::Hub::VehicleJourneyAtStopExporter.save(@vehicle_journeys, temp_dir, hub_export, vehicle_journey_at_stops.count)
+ else
+ log_overflow_warning(Chouette::VehicleJourney)
+ end
+
+ stop_points = Chouette::StopPoint.where( :id => vehicle_journey_at_stops.map(&:stop_point_id)) #.order(:id)
+ physical_stop_areas = Chouette::StopArea.where( :id => stop_points.map(&:stop_area_id)) #.order(:parent_id)
+ commercial_stop_areas = Chouette::StopArea.where( :id => physical_stop_areas.map(&:parent_id)).order(:objectid)
+
+ physical_stop_areas = []
+ commercial_stop_areas.each { |commercial_stop_area| physical_stop_areas << Chouette::StopArea.where( :parent_id => [commercial_stop_area.id] ).order(:objectid) }
+ physical_stop_areas = physical_stop_areas.flatten
+
+ city_codes = Hash.new
+ commercial_stop_areas.each { |commercial_stop_area| city_codes[commercial_stop_area.zip_code] = commercial_stop_area.city_name if commercial_stop_area.zip_code }
+ physical_stop_areas.each { |physical_stop_area| city_codes[physical_stop_area.zip_code] = physical_stop_area.city_name if physical_stop_area.zip_code }
+
+ Chouette::Hub::CityCodeExporter.save(city_codes, temp_dir, hub_export)
+ Chouette::Hub::CommercialStopAreaExporter.save(commercial_stop_areas, temp_dir, hub_export)
+ Chouette::Hub::PhysicalStopAreaExporter.save(physical_stop_areas, temp_dir, hub_export)
+
+ connection_links = Chouette::ConnectionLink.where( "departure_id IN (?) AND arrival_id IN (?)", (physical_stop_areas.map(&:id) + commercial_stop_areas.map(&:id)), (physical_stop_areas.map(&:id) + commercial_stop_areas.map(&:id)) ).order(:id)
+
+ Chouette::Hub::ConnectionLinkExporter.save(connection_links, temp_dir, hub_export)
+
+
+ if lines_exportable?
+ Chouette::Hub::LineExporter.save(@lines, temp_dir, hub_export)
+
+ transport_modes = Hash.new
+ @lines.each do |l|
+ if l.transport_mode_name
+ case l.transport_mode_name
+ when "Coach"
+ if transport_modes["CAR"]
+ transport_modes["CAR"] += "|"+l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')
+ else
+ transport_modes["CAR"] = l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')
+ end
+ when "Bus"
+ if transport_modes["BUS"]
+ transport_modes["BUS"] += "|"+l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')
+ else
+ transport_modes["BUS"] = l.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')
+ end
+ end
+ end
+ end
+ Chouette::Hub::TransportModeExporter.save(transport_modes, temp_dir, hub_export)
+ networks = Chouette::Network.where( :id => @lines.map(&:network_id))
+ companies = Chouette::Company.where( :id => @lines.map(&:company_id))
+ groups_of_lines = []
+ @lines.each { |l| groups_of_lines << l.group_of_lines }
+ groups_of_lines = groups_of_lines.flatten.uniq
+ Chouette::Hub::GroupOfLinesExporter.save(groups_of_lines, temp_dir, hub_export)
+ Chouette::Hub::NetworkExporter.save(networks, temp_dir, hub_export)
+ Chouette::Hub::CompanyExporter.save(companies, temp_dir, hub_export)
+ else
+ log_overflow_warning(Chouette::Line)
+ end
+
+ #if routes_exportable?
+ # Chouette::Hub::RouteExporter.save( routes, temp_dir, hub_export)
+ #else
+ # log_overflow_warning(Chouette::Route) if lines_exportable?
+ #end
+
+ # if too many lines
+ # there may be too many stop_areas
+ if lines_exportable?
+ stop_areas = Chouette::StopArea.joins( :stop_points => [:route => :line]).where(:lines => {:id => lines.map(&:id)}).uniq.order(:name)
+ #Chouette::Hub::StopAreaExporter.save( stop_areas, temp_dir, hub_export, "Quay")
+
+ commercial_stop_areas = Chouette::StopArea.where( :id => stop_areas.map(&:parent_id).compact.uniq).order(:name)
+ #Chouette::Hub::StopAreaExporter.save( commercial_stop_areas, temp_dir, hub_export, "CommercialStopPoint")
+ end
+
+ if( options[:o] == "line" and not options[:id].present?) # Add all objects
+ stop_places = referential.stop_areas.stop_place.order(:name)
+ #Chouette::Hub::StopAreaExporter.save( stop_places, temp_dir, hub_export, "StopPlace")
+
+ itls = referential.stop_areas.itl.order(:name)
+ #Chouette::Hub::StopAreaExporter.save( itls, temp_dir, hub_export, "ITL")
+
+ connection_links = referential.connection_links.order(:name)
+ #Chouette::Hub::ConnectionLinkExporter.save( connection_links, temp_dir, hub_export)
+
+ access_links = referential.access_links.order(:name)
+ #Chouette::Hub::AccessLinkExporter.save(access_links, temp_dir, hub_export)
+
+ access_points = referential.access_points.order(:name)
+ #Chouette::Hub::AccessPointExporter.save(access_points, temp_dir, hub_export)
+
+ end
+
+ ::Zip::File.open(zip_file_path, ::Zip::File::CREATE) do |zipfile|
+ Dir[File.join(temp_dir, '*.TXT')].each do |f|
+ #Rails.logger.error("Adding File #{File.basename(f)}")
+ zipfile.add(File.basename(f), f)
+ end
+ end
+ }
+ ensure
+ # Always cleanup files
+ #FileUtils.remove_entry(temp_directory)
+ end
+ end
+
+end
+
diff --git a/app/exporters/chouette/hub/group_of_lines_exporter.rb b/app/exporters/chouette/hub/group_of_lines_exporter.rb
new file mode 100644
index 000000000..2b07d7c4d
--- /dev/null
+++ b/app/exporters/chouette/hub/group_of_lines_exporter.rb
@@ -0,0 +1,35 @@
+class Chouette::Hub::GroupOfLinesExporter
+ include ERB::Util
+ attr_accessor :group_of_lines, :directory, :template
+
+ def initialize(group_of_lines, directory)
+ @group_of_lines = group_of_lines
+ @directory = directory
+ @template = File.open('app/views/api/hub/groupe_de_lignes.hub.erb' ){ |f| f.read }
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/GROUPELIGNE.TXT"
+ end
+
+ def self.save( groups_of_lines, directory, hub_export)
+ groups_of_lines.each do |group_of_lines|
+ self.new( group_of_lines, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|GROUP_OF_LINES_COUNT", :arguments => {"0" => groups_of_lines.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("GROUPELIGNE\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if group_of_lines.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/journey_pattern_exporter.rb b/app/exporters/chouette/hub/journey_pattern_exporter.rb
new file mode 100644
index 000000000..97cbab41d
--- /dev/null
+++ b/app/exporters/chouette/hub/journey_pattern_exporter.rb
@@ -0,0 +1,49 @@
+class Chouette::Hub::JourneyPatternExporter
+ include ERB::Util
+ attr_accessor :journey_pattern, :directory, :template
+
+ def initialize(journey_pattern, directory)
+ @journey_pattern = journey_pattern
+ @directory = directory
+ @template = File.open('app/views/api/hub/chemins.hub.erb' ){ |f| f.read }
+ @type = "COM"
+ if @journey_pattern.route
+ if @journey_pattern.route.line_id
+ @line = Chouette::Line.find(@journey_pattern.route.line_id)
+ end
+ end
+ @stop_areas = []
+ if @journey_pattern.stop_points
+ @stop_points = @journey_pattern.stop_points.order(:position)
+ if @stop_points
+ @stop_points.each { |sp| @stop_areas << Chouette::StopArea.find(sp.stop_area_id) }
+ end
+ end
+ @stop_areas = @stop_areas.flatten
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/CHEMIN.TXT"
+ end
+
+ def self.save( journey_patterns, directory, hub_export)
+ journey_patterns.each do |journey_pattern|
+ self.new( journey_pattern, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|JOURNEY_PATTERN_COUNT", :arguments => {"0" => journey_patterns.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("CHEMIN\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if journey_pattern.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/line_exporter.rb b/app/exporters/chouette/hub/line_exporter.rb
new file mode 100644
index 000000000..622f7a924
--- /dev/null
+++ b/app/exporters/chouette/hub/line_exporter.rb
@@ -0,0 +1,40 @@
+class Chouette::Hub::LineExporter
+ include ERB::Util
+ attr_accessor :line, :directory, :template
+
+ def initialize(line, directory)
+ @line = line
+ @directory = directory
+ @template = File.open('app/views/api/hub/lignes.hub.erb' ){ |f| f.read }
+ @company = @line.company
+ @network = @line.network
+ if (line.group_of_lines.count > 0)
+ @group_of_line = line.group_of_lines[0].objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2')
+ end
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/LIGNE.TXT"
+ end
+
+ def self.save( lines, directory, hub_export)
+ lines.each do |line|
+ self.new( line, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|LINE_COUNT", :arguments => {"0" => lines.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("LIGNE\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if line.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/network_exporter.rb b/app/exporters/chouette/hub/network_exporter.rb
new file mode 100644
index 000000000..fc77a84fc
--- /dev/null
+++ b/app/exporters/chouette/hub/network_exporter.rb
@@ -0,0 +1,35 @@
+class Chouette::Hub::NetworkExporter
+ include ERB::Util
+ attr_accessor :network, :directory, :template
+
+ def initialize(network, directory)
+ @network = network
+ @directory = directory
+ @template = File.open('app/views/api/hub/reseaux.hub.erb' ){ |f| f.read }
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/RESEAU.TXT"
+ end
+
+ def self.save( networks, directory, hub_export)
+ networks.each do |network|
+ self.new( network, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|NETWORK_COUNT", :arguments => {"0" => networks.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("RESEAU\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if network.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/physical_stop_area_exporter.rb b/app/exporters/chouette/hub/physical_stop_area_exporter.rb
new file mode 100644
index 000000000..a8d992735
--- /dev/null
+++ b/app/exporters/chouette/hub/physical_stop_area_exporter.rb
@@ -0,0 +1,47 @@
+class Chouette::Hub::PhysicalStopAreaExporter
+ include ERB::Util
+ attr_accessor :stop_area, :directory, :template
+
+ def initialize(stop_area, directory)
+ @stop_area = stop_area
+ @directory = directory
+ @template = File.open('app/views/api/hub/arrets_physiques.hub.erb' ){ |f| f.read }
+ @type = "NNNNNNNNNNNNNNNNNN"
+ if @stop_area.parent_id
+ @parent = Chouette::StopArea.find(@stop_area.parent_id)
+ end
+ @stop_area.referential.projection_type = "27562"
+
+ wgs84 = '+proj=lonlat +datum=WGS84 +ellps=WGS84'
+ @from_projection = RGeo::CoordSys::Proj4.new(wgs84)
+
+ lambert2_extended = '+proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs'
+ @to_projection = RGeo::CoordSys::Proj4.new(lambert2_extended)
+
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/ARRET.TXT"
+ end
+
+ def self.save( stop_areas, directory, hub_export)
+ stop_areas.each do |stop_area|
+ self.new( stop_area, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|PHYSICAL_STOP_AREA_COUNT", :arguments => {"0" => stop_areas.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("ARRET\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if stop_area.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/route_exporter.rb b/app/exporters/chouette/hub/route_exporter.rb
new file mode 100644
index 000000000..e94780329
--- /dev/null
+++ b/app/exporters/chouette/hub/route_exporter.rb
@@ -0,0 +1,44 @@
+class Chouette::Hub::RouteExporter
+ include ERB::Util
+ attr_accessor :route, :directory, :template
+
+ def initialize(route, directory)
+ @route = route
+ @directory = directory
+ @template = File.open('app/views/api/hub/schemas.hub.erb' ){ |f| f.read }
+ @line = Chouette::Line.find(@route.line_id) if @route.line_id
+ @stop_areas = []
+ if @route.stop_points
+ @stop_points = @route.stop_points.order(:position)
+ if @stop_points
+ @stop_points.each { |sp| @stop_areas << Chouette::StopArea.find(sp.stop_area_id) }
+ end
+ end
+ @stop_areas = @stop_areas.flatten
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/SCHEMA.TXT"
+ end
+
+ def self.save( routes, directory, hub_export)
+ routes.each do |route|
+ self.new( route, directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|SCHEMA_COUNT", :arguments => {"0" => routes.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("SCHEMA\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if route.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/time_table_exporter.rb b/app/exporters/chouette/hub/time_table_exporter.rb
new file mode 100644
index 000000000..2553128cd
--- /dev/null
+++ b/app/exporters/chouette/hub/time_table_exporter.rb
@@ -0,0 +1,49 @@
+class Chouette::Hub::TimeTableExporter
+ include ERB::Util
+ attr_accessor :time_table, :directory, :template, :start_date, :end_date, :identifier
+
+ def initialize(time_table, directory, identifier)
+ @time_table = time_table
+ @directory = directory
+ @identifier = identifier
+ @template = File.open('app/views/api/hub/periodes.hub.erb' ){ |f| f.read }
+ @calendar = ""
+ s_date = @time_table.start_date
+ e_date = @time_table.end_date
+ while s_date <= e_date
+ if time_table.include_day?(s_date)
+ @calendar += "1"
+ else
+ @calendar += "0"
+ end
+ s_date = s_date.next_day
+ end
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/PERIODE.TXT"
+ end
+
+ def self.save(time_tables, directory, hub_export)
+ identifier = 1
+ time_tables.each do |time_table|
+ self.new(time_table, directory, identifier).tap do |specific_exporter|
+ specific_exporter.save
+ identifier += 1
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|TIME_TABLE_COUNT", :arguments => {"0" => time_tables.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("PERIODE\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if time_table.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/transport_mode_exporter.rb b/app/exporters/chouette/hub/transport_mode_exporter.rb
new file mode 100644
index 000000000..46d116eec
--- /dev/null
+++ b/app/exporters/chouette/hub/transport_mode_exporter.rb
@@ -0,0 +1,35 @@
+class Chouette::Hub::TransportModeExporter
+ include ERB::Util
+ attr_accessor :transport_mode, :transport_lines, :directory, :template
+
+ def initialize(transport_mode, transport_lines, directory)
+ @transport_mode = transport_mode
+ @transport_lines = transport_lines
+ @directory = directory
+ @template = File.open('app/views/api/hub/modes_transports.hub.erb' ){ |f| f.read }
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/MODETRANSPORT.TXT"
+ end
+
+ def self.save( transport_modes, directory, hub_export)
+ transport_modes.keys.sort.each do |key|
+ self.new( key, transport_modes[key], directory).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|TRANSPORT_MODE_COUNT", :arguments => {"0" => transport_modes.keys.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("MODETRANSPORT\u000D\u000A") if f.size == 0
+ f.write(render)
+ end
+ end
+end
diff --git a/app/exporters/chouette/hub/vehicle_journey_at_stop_exporter.rb b/app/exporters/chouette/hub/vehicle_journey_at_stop_exporter.rb
new file mode 100644
index 000000000..1c4b4c620
--- /dev/null
+++ b/app/exporters/chouette/hub/vehicle_journey_at_stop_exporter.rb
@@ -0,0 +1,58 @@
+class Chouette::Hub::VehicleJourneyAtStopExporter
+ include ERB::Util
+ attr_accessor :vehicle_journey_at_stop, :directory, :template
+
+ def initialize(vehicle_journey_at_stop, directory, index, id)
+ @vehicle_journey_at_stop = vehicle_journey_at_stop
+ @directory = directory
+ @vehicle_journey_num = index
+ @vehicle_journey_id = id
+ @template = File.open('app/views/api/hub/horaires.hub.erb' ) { |f| f.read }
+ stop_point = @vehicle_journey_at_stop.stop_point
+ stop_area = stop_point.stop_area
+ @stop_area_code = stop_area.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if stop_area
+ @stop_area_id = stop_area.registration_number if stop_area
+ #Time.zone = ActiveSupport::TimeZone.new('Atlantic/Azores')
+ arrival_time = @vehicle_journey_at_stop.arrival_time
+ @arrival_time = arrival_time.sec + 60 * arrival_time.min + 60 * 60 * arrival_time.hour if arrival_time
+ @arrival_type = "A"
+ departure_time = @vehicle_journey_at_stop.departure_time
+ @departure_time = departure_time.sec + 60 * departure_time.min + 60 * 60 * departure_time.hour if departure_time
+ @departure_type = "D"
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/HORAIRE.TXT"
+ end
+
+ def self.save( vehicle_journeys, directory, hub_export, vehicle_journey_at_stops_count)
+ id = 1
+ vehicle_journeys.each_index do |index|
+ vehicle_journey_at_stops = Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => vehicle_journeys[index].id ).order(:arrival_time)
+ vehicle_journey_at_stops.each do |vehicle_journey_at_stop|
+ self.new( vehicle_journey_at_stop, directory, index, id).tap do |specific_exporter|
+ specific_exporter.save
+ id += 1
+ end
+ end
+ end
+ #vehicle_journey_at_stops.each do |vehicle_journey_at_stop|
+ # self.new( vehicle_journey_at_stop, directory).tap do |specific_exporter|
+ # specific_exporter.save
+ # end
+ #end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|VEHICLE_JOURNEY_AT_STOP_COUNT", :arguments => {"0" => vehicle_journey_at_stops_count})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("HORAIRE\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if vehicle_journey_at_stop.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/vehicle_journey_exporter.rb b/app/exporters/chouette/hub/vehicle_journey_exporter.rb
new file mode 100644
index 000000000..e1d7fce58
--- /dev/null
+++ b/app/exporters/chouette/hub/vehicle_journey_exporter.rb
@@ -0,0 +1,75 @@
+class Chouette::Hub::VehicleJourneyExporter
+ include ERB::Util
+ attr_accessor :vehicle_journey, :directory, :template
+
+ def initialize(vehicle_journey, directory, index)
+ @vehicle_journey = vehicle_journey
+ @directory = directory
+ @template = File.open('app/views/api/hub/courses.hub.erb' ) { |f| f.read }
+ @numero = index
+ @journey_pattern = Chouette::JourneyPattern.find(@vehicle_journey.journey_pattern_id)
+ @route = Chouette::Route.find(@vehicle_journey.route_id)
+ @line = Chouette::Line.find(@route.line_id)
+ @departure_stop_point = Chouette::StopPoint.find(@journey_pattern.departure_stop_point_id)
+ @departure_stop_area = Chouette::StopArea.find(@departure_stop_point.stop_area_id)
+ @arrival_stop_point = Chouette::StopPoint.find(@journey_pattern.arrival_stop_point_id)
+ @arrival_stop_area = Chouette::StopArea.find(@arrival_stop_point.stop_area_id)
+
+ #Time.zone = ActiveSupport::TimeZone.new('Atlantic/Azores')
+ departure_time = Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => @vehicle_journey.id ).where( :stop_point_id => @departure_stop_point.id )[0].departure_time
+ # Time.zone.parse(Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => @vehicle_journey.id ).where( :stop_point_id => @departure_stop_point.id )[0].departure_time.to_s)
+ arrival_time = Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => @vehicle_journey.id ).where( :stop_point_id => @arrival_stop_point.id )[0].arrival_time
+ #Time.zone.parse(Chouette::VehicleJourneyAtStop.where( :vehicle_journey_id => @vehicle_journey.id ).where( :stop_point_id => @arrival_stop_point.id )[0].arrival_time.to_s)
+
+ @departure_time_sec = departure_time.sec + ( departure_time.min + departure_time.hour * 60 ) * 60
+ @arrival_time_sec = arrival_time.sec + ( arrival_time.min + arrival_time.hour * 60 ) * 60
+ @validity = 0
+ @vehicle_journey.time_tables.map(&:int_day_types).each { |v| @validity |= v }
+
+ periods = Chouette::TimeTable.where( :id => @vehicle_journey.time_tables.map(&:id) ).map(&:objectid)
+ @periods = ""
+ unless periods.empty?
+ @periods += periods[0].sub(/(\w*\:\w*\:)(\w*)/, '\2')
+ periods.shift
+ end
+ unless periods.empty?
+ periods.each { |p| @periods += "|" + p.sub(/(\w*\:\w*\:)(\w*)/, '\2') }
+ end
+ # USE @renvoi for PMR and TAD and create RENVOI.TXT File
+ @renvoi = ""
+ if @vehicle_journey.mobility_restricted_suitability
+ @renvoi = "1"
+ end
+ File.open(directory + "/RENVOI.TXT" , "a:ISO_8859_1") do |f|
+ if f.size == 0
+ f.write("RENVOI\u000D\u000A")
+ f.write("a;PMR;1\u000D\u000A")
+ end
+ end
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/COURSE.TXT"
+ end
+
+ def self.save( vehicle_journeys, directory, hub_export)
+ vehicle_journeys.each_index do |index|
+ self.new( vehicle_journeys[index], directory, index).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|VEHICLE_JOURNEY_COUNT", :arguments => {"0" => vehicle_journeys.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("COURSE\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if vehicle_journey.present?
+ end
+end
+
diff --git a/app/exporters/chouette/hub/vehicle_journey_operation_exporter.rb b/app/exporters/chouette/hub/vehicle_journey_operation_exporter.rb
new file mode 100644
index 000000000..533f0628e
--- /dev/null
+++ b/app/exporters/chouette/hub/vehicle_journey_operation_exporter.rb
@@ -0,0 +1,100 @@
+class Chouette::Hub::VehicleJourneyOperationExporter
+ include ERB::Util
+ attr_accessor :vehicle_journey, :directory, :template
+
+ def initialize(vehicle_journey, directory, index)
+ @vehicle_journey = vehicle_journey
+ @number = index
+ @directory = directory
+ @template = File.open('app/views/api/hub/courses_operations.hub.erb' ) { |f| f.read }
+ # HUB TMode vs. Neptune TMode
+ # transport_mode = "TAD_PMR" if (@vehicle_journey.flexible_service && @vehicle_journey.mobility_restricted_suitability) # SISMO profile : NO TAD_PMR MODE.
+ if @vehicle_journey.flexible_service
+ transport_mode = "TAD"
+ else
+ case @vehicle_journey.transport_mode
+ when "Interchange"
+ transport_mode = ""
+ when "Unknown"
+ transport_mode = ""
+ when "Coach"
+ if @vehicle_journey.mobility_restricted_suitability
+ transport_mode = "CAR_PMR"
+ else
+ transport_mode = "CAR"
+ end
+ when "Air"
+ transport_mode = "AVION"
+ when "Waterborne"
+ transport_mode = "BATEAU"
+ when "Bus"
+ if @vehicle_journey.mobility_restricted_suitability
+ transport_mode = "BUS_PMR"
+ else
+ transport_mode = "BUS"
+ end
+ when "Ferry"
+ transport_mode = "BATEAU"
+ when "Walk"
+ transport_mode = ""
+ when "Metro"
+ transport_mode = "METRO"
+ when "Shuttle"
+ transport_mode = ""
+ when "RapidTransit"
+ transport_mode = ""
+ when "Taxi"
+ transport_mode = "TAXIBUS"
+ when "LocalTrain"
+ transport_mode = "TRAIN"
+ when "Train"
+ transport_mode = "TRAIN"
+ when "LongDistance_train"
+ transport_mode = "TRAIN"
+ when "Tramway"
+ transport_mode = "TRAM"
+ when "Trolleybus"
+ transport_mode = "TROLLEY"
+ when "PrivateVehicle"
+ transport_mode = ""
+ when "Bicycle"
+ transport_mode = "VELO"
+ when "Other"
+ transport_mode = ""
+ else
+ transport_mode = ""
+ end
+ end
+ @transport_mode = transport_mode
+ end
+
+ def render()
+ ERB.new(@template).result(binding)
+ end
+
+ def hub_name
+ "/COURSE_OPERATION.TXT"
+ end
+
+ def self.save( vehicle_journeys, directory, hub_export)
+ vehicle_journeys.each_index do |index|
+ self.new( vehicle_journeys[index], directory, index).tap do |specific_exporter|
+ specific_exporter.save
+ end
+ end
+ #vehicle_journeys.each do |vehicle_journey|
+ # self.new( vehicle_journey, directory).tap do |specific_exporter|
+ # specific_exporter.save
+ # end
+ #end
+ hub_export.log_messages.create( :severity => "ok", :key => "EXPORT|VEHICLE_JOURNEY_OPERATION_COUNT", :arguments => {"0" => vehicle_journeys.size})
+ end
+
+ def save
+ File.open(directory + hub_name , "a:ISO_8859_1") do |f|
+ f.write("COURSE_OPERATION\u000D\u000A") if f.size == 0
+ f.write(render)
+ end if vehicle_journey.present?
+ end
+end
+
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/application_helper.rb b/app/helpers/application_helper.rb
index 8e655c68d..a3808cfc1 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -20,7 +20,47 @@ module ApplicationHelper
end
def help_path
- url_for(:controller => "/help", :action => "show") + '/'
+ path = request.env['PATH_INFO']
+ target = case
+ when path.include?("/help")
+ ""
+ when path.include?("/networks")
+ "networks"
+ when path.include?("/companies")
+ "companies"
+ when path.include?("/group_of_lines")
+ "group_of_lines"
+ when path.include?("/vehicle_journeys")
+ "vehicle_journeys"
+ when path.include?("/journey_patterns")
+ "journey_patterns"
+ when path.include?("/routes")
+ "routes"
+ when path.include?("/lines")
+ "lines"
+ when path.include?("/access_points")
+ "access_points"
+ when path.include?("/access_links")
+ "access_links"
+ when path.include?("/stop_areas")
+ "stop_areas"
+ when path.include?("/connection_links")
+ "connection_links"
+ when path.include?("/time_tables")
+ "time_tables"
+ when path.include?("/rule_parameter_set")
+ "parametersets"
+ when path.include?("/import_tasks")
+ "imports"
+ when path.include?("/exports")
+ "exports"
+ when path.include?("/compliance_check_tasks")
+ "validations"
+ else
+ ""
+ end
+
+ url_for(:controller => "/help", :action => "show") + '/' + target
end
diff --git a/app/helpers/breadcrumb_helper.rb b/app/helpers/breadcrumb_helper.rb
new file mode 100644
index 000000000..34e03383c
--- /dev/null
+++ b/app/helpers/breadcrumb_helper.rb
@@ -0,0 +1,207 @@
+module BreadcrumbHelper
+
+ def build_breadcrumb(action)
+ case resource_class.to_s
+ when "Chouette::Network"
+ network_breadcrumb action
+ when "Chouette::Company"
+ company_breadcrumb action
+ when "Chouette::GroupOfLine"
+ group_of_line_breadcrumb action
+ when "Chouette::Line"
+ line_breadcrumb action
+ when "Chouette::Route"
+ route_breadcrumb action
+ when "Chouette::JourneyPattern"
+ journey_pattern_breadcrumb action
+ when "Chouette::VehicleJourney"
+ vehicle_journey_breadcrumb action
+ when "VehicleJourneyImport"
+ vehicle_journey_import_breadcrumb action
+ when "Chouette::StopArea"
+ stop_area_breadcrumb action
+ when "Chouette::AccessPoint"
+ access_point_breadcrumb action
+ when "Chouette::AccessLink"
+ access_link_breadcrumb action
+ when "Chouette::ConnectionLink"
+ connection_link_breadcrumb action
+ when "Chouette::TimeTable"
+ time_table_breadcrumb action
+ when "StopAreaCopy"
+ stop_area_copy_breadcrumb action
+ when "ImportTask"
+ import_breadcrumb action
+ when "Export"
+ export_breadcrumb action
+ when "ComplianceCheckTask"
+ compliance_breadcrumb action
+ when "RuleParameterSet"
+ rule_parameter_breadcrumb action
+ when "User"
+ user_breadcrumb action
+ when "Referential"
+ referential_breadcrumb action
+ when "Organisation"
+ organisation_breadcrumb action
+ when "Api::V1::ApiKey"
+ referential_breadcrumb
+ else
+ Rails.logger.info "---------"
+ Rails.logger.info ">>>>>>> "+resource_class.to_s+" unmapped"
+ Rails.logger.info "---------"
+ organisation_breadcrumb :index
+ end
+ end
+
+
+ def network_breadcrumb(action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::Network.model_name.human(:count => 2), referential_networks_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@network), referential_line_path(@referential, @network),:title => breadcrumb_tooltip(@network) if action == :edit
+ end
+
+ def group_of_line_breadcrumb(action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::GroupOfLine.model_name.human(:count => 2), referential_group_of_lines_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@group_of_line), referential_group_of_line_path(@referential, @group_of_line),:title => breadcrumb_tooltip(@group_of_line) if action == :edit
+ end
+
+ def stop_area_breadcrumb(action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::StopArea.model_name.human(:count => 2), referential_stop_areas_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@stop_area), referential_stop_area_path(@referential, @stop_area),:title => breadcrumb_tooltip(@stop_area) if action == :edit
+ end
+
+ def stop_area_copy_breadcrumb(action)
+ stop_area_breadcrumb :edit
+ end
+
+ def access_point_breadcrumb(action)
+ stop_area_breadcrumb :edit
+ add_breadcrumb breadcrumb_label(@access_point), referential_stop_area_access_point_path(@referential, @access_point.stop_area,@access_point),:title => breadcrumb_tooltip(@access_point) if action == :edit
+ end
+
+ def access_link_breadcrumb(action)
+ access_point_breadcrumb :edit
+ add_breadcrumb Chouette::AccessLink.model_name.human(:count => 2), access_links_referential_stop_area_path(@referential, @stop_area)
+ add_breadcrumb breadcrumb_label(@access_link), referential_access_point_access_link_path(@referential, @access_point,@access_link),:title => breadcrumb_tooltip(@access_link) if action == :edit
+ end
+
+ def connection_link_breadcrumb(action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::ConnectionLink.model_name.human(:count => 2), referential_connection_links_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@connection_link), referential_connection_link_path(@referential, @connection_link),:title => breadcrumb_tooltip(@connection_link) if action == :edit
+ end
+
+ def time_table_breadcrumb(action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::TimeTable.model_name.human(:count => 2), referential_time_tables_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@time_table), referential_time_table_path(@referential, @time_table),:title => breadcrumb_tooltip(@time_table) if action == :edit
+ end
+
+ def line_breadcrumb(action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::Line.model_name.human(:count => 2), referential_lines_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@line), referential_line_path(@referential, @line),:title => breadcrumb_tooltip(@line) if action == :edit
+ end
+
+ def route_breadcrumb(action)
+ line_breadcrumb :edit
+ add_breadcrumb breadcrumb_label(@route), referential_line_route_path(@referential, @line,@route),:title => breadcrumb_tooltip(@route) if action == :edit
+ end
+
+ def journey_pattern_breadcrumb(action)
+ route_breadcrumb :edit
+ add_breadcrumb breadcrumb_label(@journey_pattern), referential_line_route_journey_pattern_path(@referential, @line,@route,@journey_pattern),:title => breadcrumb_tooltip(@journey_pattern) if action == :edit
+ end
+
+ def vehicle_journey_breadcrumb(action)
+ route_breadcrumb :edit
+ add_breadcrumb I18n.t("breadcrumbs.vehicle_journeys"), referential_line_route_vehicle_journeys_path(@referential, @line,@route) unless action == :index
+ add_breadcrumb breadcrumb_label(@vehicle_journey), referential_line_route_vehicle_journey_path(@referential, @line,@route,@vehicle_journey),:title => breadcrumb_tooltip(@vehicle_journey) if action == :edit
+ end
+
+ def vehicle_journey_import_breadcrumb (action)
+ route_breadcrumb :edit
+ end
+
+ def company_breadcrumb (action)
+ referential_breadcrumb
+ add_breadcrumb Chouette::Company.model_name.human(:count => 2), referential_companies_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@company), referential_company_path(@referential, @company),:title => breadcrumb_tooltip(@company) if action == :edit
+ end
+
+ def import_breadcrumb (action)
+ referential_breadcrumb
+ add_breadcrumb Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) unless action == :index
+ end
+
+ def export_breadcrumb (action)
+ referential_breadcrumb
+ add_breadcrumb Referential.human_attribute_name("exports"), referential_exports_path(@referential) unless action == :index
+ end
+
+ def compliance_breadcrumb (action)
+ referential_breadcrumb
+ add_breadcrumb Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) unless action == :index
+ add_breadcrumb breadcrumb_label(@compliance_check_task), referential_compliance_check_task_path(@referential, @compliance_check_task),:title => breadcrumb_tooltip(@compliance_check_task) if action == :edit
+ end
+
+ def rule_parameter_breadcrumb (action)
+ referential_breadcrumb
+ 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) unless action == :index
+ end
+
+ def referential_breadcrumb (action = :edit)
+ organisation_breadcrumb
+ add_breadcrumb breadcrumb_label(@referential), referential_path(@referential),:title => breadcrumb_tooltip(@referential) if action == :edit || action == :show || action == :update
+ end
+
+ def organisation_breadcrumb (action = :index)
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb breadcrumb_label(@organisation), organisation_path,:title => breadcrumb_tooltip(@organisation) unless action == :index
+ end
+
+ def user_breadcrumb (action)
+ organisation_breadcrumb
+ add_breadcrumb I18n.t("breadcrumbs.users"), organisation_path unless action == :index
+ add_breadcrumb breadcrumb_label(@user), organisation_user_path(@user),:title => breadcrumb_tooltip(@user) if action == :edit
+ end
+
+ def breadcrumb_label(obj)
+ label = breadcrumb_name(obj)
+ if label.blank?
+ label = obj.class.model_name.human+" "+obj.id.to_s
+ end
+
+ if label.length > 20
+ label[0..16]+"..."
+ else
+ label
+ end
+ end
+
+ def breadcrumb_tooltip(obj)
+ label = breadcrumb_name(obj)
+ if label.blank?
+ label = obj.class.model_name.human+" ("+obj.id.to_s+")"
+ else
+ label = obj.class.model_name.human+" : "+label
+ end
+ label
+ end
+
+ def breadcrumb_name(obj)
+ label = ""
+ if obj.respond_to?('name')
+ label = obj.name
+ elsif obj.respond_to?('comment')
+ label = obj.comment
+ end
+ label
+ end
+
+end
diff --git a/app/helpers/exports_helper.rb b/app/helpers/exports_helper.rb
index 1ae59c190..d9b975297 100644
--- a/app/helpers/exports_helper.rb
+++ b/app/helpers/exports_helper.rb
@@ -1,15 +1,46 @@
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
+ def export_progress_bar_tag(export)
+
+ if export.status == "failed"
+ div_class = "progress-bar progress-bar-danger"
+ percentage_progress = "100"
+ elsif export.status == "pending"
+ div_class = "progress-bar progress-bar-info"
+ percentage_progress = "10"
+ elsif export.status == "processing"
+ div_class = "progress-bar progress-bar-info"
+ percentage_progress = "50"
+ elsif export.status == "completed"
+ div_class = "progress-bar progress-bar-success"
+ percentage_progress = "100"
+ else
+ div_class = ""
+ percentage_progress = ""
+ end
+
+ content_tag :div, :class => "progress" do
+ content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => percentage_progress, :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{percentage_progress}%;" do
+ percentage_progress + "% " + I18n.t("exports.statuses.#{export.status}")
+ end
+ end
+
+ end
+
end
diff --git a/app/helpers/history_helper.rb b/app/helpers/history_helper.rb
index 88c6b8da3..ccc6374a1 100644
--- a/app/helpers/history_helper.rb
+++ b/app/helpers/history_helper.rb
@@ -1,7 +1,7 @@
module HistoryHelper
def creation_tag(object)
- field_set_tag t("layouts.creation_tag.title"), :class => "history_tag" do
+ field_set_tag t("layouts.history_tag.title"), :class => "history_tag" do
content_tag :ul do
[(content_tag :li do
if object.has_attribute?(:creation_time)
@@ -12,7 +12,17 @@ module HistoryHelper
end),
(content_tag :li do
if object.has_attribute?(:creator_id)
- object.human_attribute_name('creator_id') + ' : ' + object.creator_id if object.creator_id
+ object.human_attribute_name('creator_id') + ' : ' + object.creator_id if object.creator_id
+ end
+ end),
+ (content_tag :li do
+ if object.has_attribute?(:objectid)
+ object.human_attribute_name('objectid') + ' : ' + object.objectid if object.objectid
+ end
+ end),
+ (content_tag :li do
+ if object.has_attribute?(:object_version)
+ object.human_attribute_name('object_version') + ' : ' + object.object_version.to_s if object.object_version
end
end)].join.html_safe
end
diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb
index 22ce8ea98..fbb9c13df 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
@@ -22,4 +26,31 @@ module ImportsHelper
end
end
+ def import_progress_bar_tag(export)
+
+ if export.status == "failed"
+ div_class = "progress-bar progress-bar-danger"
+ percentage_progress = "100"
+ elsif export.status == "pending"
+ div_class = "progress-bar progress-bar-info"
+ percentage_progress = "10"
+ elsif export.status == "processing"
+ div_class = "progress-bar progress-bar-info"
+ percentage_progress = "50"
+ elsif export.status == "completed"
+ div_class = "progress-bar progress-bar-success"
+ percentage_progress = "100"
+ else
+ div_class = ""
+ percentage_progress = ""
+ end
+
+ content_tag :div, :class => "progress" do
+ content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => percentage_progress, :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{percentage_progress}%;" do
+ percentage_progress + "% " + I18n.t("exports.statuses.#{export.status}")
+ end
+ end
+
+ end
+
end
diff --git a/app/helpers/pagination_helper.rb b/app/helpers/pagination_helper.rb
index b85137b85..68c3d462f 100644
--- a/app/helpers/pagination_helper.rb
+++ b/app/helpers/pagination_helper.rb
@@ -1,5 +1,8 @@
module PaginationHelper
- def paginated_content(models, default_partial_name = nil)
+ def paginated_content(models, default_partial_name = nil, options = {})
+ default_options = {:delete => true, :edit => true}
+ options = default_options.merge(options)
+
return "" if models.blank?
html = ""
@@ -7,7 +10,7 @@ module PaginationHelper
html += '<div class="row">'
row_models.each do |model|
partial_name = default_partial_name || model.class.name.underscore.gsub("chouette/", "")
- html += '<div class="col-md-4">' + (render :partial => partial_name, :object => model).to_s + '</div>'
+ html += '<div class="col-md-4">' + (render :partial => partial_name, :object => model, :locals => options).to_s + '</div>'
end
html += '</div>'
end
diff --git a/app/helpers/remote_bootstrap_pagination_link_renderer.rb b/app/helpers/remote_bootstrap_pagination_link_renderer.rb
new file mode 100644
index 000000000..fe7f2d06b
--- /dev/null
+++ b/app/helpers/remote_bootstrap_pagination_link_renderer.rb
@@ -0,0 +1,8 @@
+# remote link for will paginate, using bootstrap as renderer
+class RemoteBootstrapPaginationLinkRenderer < BootstrapPagination::Rails
+ def link (text,target, attributes = {})
+ attributes["data-remote"] = true
+ super
+ end
+
+end
diff --git a/app/helpers/time_tables_helper.rb b/app/helpers/time_tables_helper.rb
index b6dc3de48..e0c1fc2db 100644
--- a/app/helpers/time_tables_helper.rb
+++ b/app/helpers/time_tables_helper.rb
@@ -8,9 +8,12 @@ module TimeTablesHelper
"validity_regular"
end
end
+ def tag_list_shortened(time_table)
+ time_table.tags.join(', ').truncate(30, separator: ',')
+ end
def bounding_info(time_table)
return t('time_tables.time_table.empty') if time_table.bounding_dates.empty?
- t('time_tables.time_table.bounding',
+ t('time_tables.time_table.bounding',
:start => l(time_table.bounding_dates.min),
:end => l(time_table.bounding_dates.max))
end
@@ -37,10 +40,18 @@ module TimeTablesHelper
elsif time_table.periods.empty?
t('time_tables.time_table.dates_count', :count => time_table.dates.count)
else
- t('time_tables.time_table.periods_dates_count',
+ t('time_tables.time_table.periods_dates_count',
:dates_count => time_table.dates.count,
:periods_count => time_table.periods.count)
end
end
+
+ def time_table_description(time_table)
+ if time_table.bounding_dates.empty?
+ "#{time_table.comment} (vide)"
+ else
+ "#{time_table.comment} : #{time_table_bounding( time_table)} - #{composition_info(time_table)}"
+ end
+ end
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 6ebb20fc5..0ddea8356 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -1,7 +1,7 @@
module UsersHelper
- def user_gravatar_image_tag(user)
- gravatar_image_tag user.email, :alt => user.name, :class => "preview", :gravatar => { :default => user_default_avatar , :size => 64 }
+ def user_gravatar_image_tag(user, size = 64)
+ gravatar_image_tag user.email, :alt => "", :class => "preview", :gravatar => { :default => user_default_avatar , :size => size }
end
def user_default_avatar
diff --git a/app/helpers/vehicle_journeys_helper.rb b/app/helpers/vehicle_journeys_helper.rb
index 1ecfe12b5..2ee8123b5 100644
--- a/app/helpers/vehicle_journeys_helper.rb
+++ b/app/helpers/vehicle_journeys_helper.rb
@@ -8,6 +8,7 @@ module VehicleJourneysHelper
journey_pattern.id
end
end
+
def vehicle_name( vehicle)
if !vehicle.published_journey_name.blank?
vehicle.published_journey_name.first(8)
@@ -19,22 +20,25 @@ module VehicleJourneysHelper
vehicle.id
end
end
+
def missing_time_check( is_present)
return "missing" if (is_present && is_present.departure_time.nil?)
end
+
def vehicle_departure(vehicle)
first_vjas = vehicle.vehicle_journey_at_stops.first
return "" unless first_vjas.departure_time
l(first_vjas.departure_time, :format => :hour).gsub( / /, ' ')
end
+
def vehicle_title( vehicle)
return t('vehicle_journeys.vehicle_journey.title_stopless', :name => vehicle_name( vehicle)) if vehicle.vehicle_journey_at_stops.empty?
first_vjas = vehicle.vehicle_journey_at_stops.first
t('vehicle_journeys.vehicle_journey.title',
- :name => vehicle_name( vehicle),
:stop => first_vjas.stop_point.stop_area.name,
:time => vehicle_departure(vehicle))
end
+
def edit_vehicle_title( vehicle)
return t('vehicle_journeys.edit.title_stopless', :name => vehicle_name( vehicle)) if vehicle.vehicle_journey_at_stops.empty?
first_vjas = vehicle.vehicle_journey_at_stops.first
@@ -43,5 +47,6 @@ module VehicleJourneysHelper
:stop => first_vjas.stop_point.stop_area.name,
:time => vehicle_departure(vehicle))
end
+
end
diff --git a/app/inputs/check_boxes_input.rb b/app/inputs/check_boxes_input.rb
new file mode 100644
index 000000000..83137c224
--- /dev/null
+++ b/app/inputs/check_boxes_input.rb
@@ -0,0 +1,17 @@
+class CheckBoxesInput < Formtastic::Inputs::CheckBoxesInput
+
+ def selected_values
+ if object.respond_to?(method)
+ selected_items = [object.send(method)].compact.flatten
+
+ # FIX for ids only
+ return selected_items.map(&:to_s).compact if selected_items.all?{ |i| i.is_a? Integer}
+
+ [*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
+ else
+ []
+ end
+ end
+
+end
+
diff --git a/app/inputs/extended_time_picker_input.rb b/app/inputs/extended_time_picker_input.rb
new file mode 100644
index 000000000..2298c0185
--- /dev/null
+++ b/app/inputs/extended_time_picker_input.rb
@@ -0,0 +1,13 @@
+class ExtendedTimePickerInput < Formtastic::Inputs::TimePickerInput
+
+ def value
+ return options[:input_html][:value] if options[:input_html] && options[:input_html].key?(:value)
+ val = object.send(method)
+ puts val.to_s
+ return "00:00:00" if val.is_a?(Date)
+ return val.strftime("%H:%M:%S") if val.is_a?(Time)
+ return "00:00:00" if val.nil?
+ val.to_s
+ end
+
+end
diff --git a/app/inputs/search_stop_area_input.rb b/app/inputs/search_stop_area_input.rb
new file mode 100644
index 000000000..1feb58d00
--- /dev/null
+++ b/app/inputs/search_stop_area_input.rb
@@ -0,0 +1,40 @@
+class SearchStopAreaInput < Formtastic::Inputs::SearchInput
+
+ def search
+ if options[:json]
+ tokenLimit = options[:tokenLimit].present? ? options[:tokenLimit] : "null"
+ template.content_tag( :script,
+ ("$(document).ready(function() {
+ $('##{dom_id}').tokenInput('#{options[:json]}', {
+ crossDomain: false,
+ tokenLimit: #{tokenLimit},
+ minChars: 2,
+ preventDuplicates: true,
+ hintText: '#{options[:hint_text]}',
+ noResultsText: '#{options[:no_result_text]}',
+ searchingText: '#{options[:searching_text]}',
+ resultsFormatter: function(item){ return '<li><div class=\"name\">' + item.name + '</div><div class=\"info\">' + item.area_type + '</div><div class=\"info\">' + item.zip_code + ' ' + item.city_name + '</div></li>' },
+ tokenFormatter: function(item){ return '<li><div class=\"name\">' + item.name + '</div><div class=\"info\">' + item.area_type + '</div><div class=\"info\">' + item.zip_code + ' ' + item.city_name + '</div></li>' },
+ });
+ });").html_safe)
+ end
+ end
+
+ def to_html
+ input_wrapping do
+ label_html <<
+ builder.search_field(method, input_html_options) <<
+ search
+ end
+ end
+
+ def input_html_options
+ super.merge({
+ :required => nil,
+ :autofocus => nil,
+ :class => 'token-input',
+ 'data-model-name' => object.class.model_name.human
+ })
+ end
+
+end
diff --git a/app/inputs/search_time_table_input.rb b/app/inputs/search_time_table_input.rb
new file mode 100644
index 000000000..6f40d7e1e
--- /dev/null
+++ b/app/inputs/search_time_table_input.rb
@@ -0,0 +1,55 @@
+class SearchTimeTableInput < Formtastic::Inputs::SearchInput
+
+ def search
+ if options[:json]
+ tokenLimit = options[:tokenLimit].present? ? options[:tokenLimit] : "null"
+ template.content_tag( :script,
+ ("$(document).ready(function() {
+ var time_table_formatter = function(item){
+ var day_types = '';
+ if ( item.day_types.length >0 ){
+ day_types = '<span class=\"day_types\">' + item.day_types + '</span>' ;
+ }
+ var tags = '';
+ if ( item.tags.length >0 ){
+ tags = '<div class=\"info\">' + item.tags + '</div>' ;
+ }
+ return '<li><div class=\"comment\">' + item.comment +
+ '</div><div class=\"info\">' + item.time_table_bounding + day_types + '</div>' +
+ tags + '</li>';
+ };
+ $('##{dom_id}').tokenInput('#{options[:json]}', {
+ crossDomain: false,
+ tokenLimit: #{tokenLimit},
+ minChars: 2,
+ propertyToSearch: 'comment',
+ preventDuplicates: true,
+ queryParam: 'q[comment_cont]',
+ hintText: '#{options[:hint_text]}',
+ noResultsText: '#{options[:no_result_text]}',
+ searchingText: '#{options[:searching_text]}',
+ resultsFormatter: time_table_formatter,
+ tokenFormatter: time_table_formatter,
+ });
+ });").html_safe)
+ end
+ end
+
+ def to_html
+ input_wrapping do
+ label_html <<
+ builder.search_field(method, input_html_options) <<
+ search
+ end
+ end
+
+ def input_html_options
+ super.merge({
+ :required => nil,
+ :autofocus => nil,
+ :class => 'token-input',
+ 'data-model-name' => object.class.model_name.human
+ })
+ end
+
+end
diff --git a/app/inputs/tags_input.rb b/app/inputs/tags_input.rb
new file mode 100644
index 000000000..4fbf0465f
--- /dev/null
+++ b/app/inputs/tags_input.rb
@@ -0,0 +1,19 @@
+class TagsInput < Formtastic::Inputs::StringInput
+
+ def to_html
+ input_wrapping do
+ label_html <<
+ '<span id="tagsContainer"></span>'.html_safe <<
+ builder.text_field(method, input_html_options)
+ end
+ end
+
+ def input_html_options
+ super.merge({
+ :required => nil,
+ :autofocus => nil,
+ :class => 'tm-input',
+ })
+ end
+
+end
diff --git a/app/maps/access_link_map.rb b/app/maps/access_link_map.rb
index 35873a9b1..544a1e792 100644
--- a/app/maps/access_link_map.rb
+++ b/app/maps/access_link_map.rb
@@ -23,7 +23,7 @@ class AccessLinkMap < ApplicationMap
end
def bounds
- @bounds ||= GeoRuby::SimpleFeatures::Point.bounds([access_link.stop_area.geometry,access_link.access_point.geometry])
+ @bounds ||= GeoRuby::SimpleFeatures::Point.bounds([access_link.stop_area.geometry,access_link.access_point.geometry].compact)
end
end
diff --git a/app/maps/access_point_map.rb b/app/maps/access_point_map.rb
index f31dcf5a3..0103d9edb 100644
--- a/app/maps/access_point_map.rb
+++ b/app/maps/access_point_map.rb
@@ -10,10 +10,10 @@ class AccessPointMap < ApplicationMap
end
def customize_map(map, page)
- page.assign "parent_layer", kml_layer(access_point.stop_area, :style_map => Design::StopAreasStyleMap.new(helpers).style_map)
- page << map.add_layer(:parent_layer)
page.assign "edit_access_point_layer", kml_layer(access_point, { :default => editable? }, :style_map => Design::EditAccessPointStyleMap.new(helpers).style_map)
page << map.add_layer(:edit_access_point_layer)
+ page.assign "parent_layer", kml_layer(access_point.stop_area, :style_map => Design::StopAreasStyleMap.new(helpers).style_map)
+ page << map.add_layer(:parent_layer)
if editable?
@@ -23,14 +23,12 @@ class AccessPointMap < ApplicationMap
edit_access_point_layer.events.on({
'afterfeaturemodified': function(event) {
geometry = event.feature.geometry.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
- $('#access_point_longitude').val(geometry.x);
- $('#access_point_latitude').val(geometry.y);
+ $('#access_point_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 );
- $('#access_point_projection_x').val(projection_geometry.x);
- $('#access_point_projection_y').val(projection_geometry.y); }
+ $('#access_point_projection_xy').val(projection_geometry.x.toString()+ ","+ projection_geometry.y.toString()); }
}
});
EOF
diff --git a/app/maps/application_map.rb b/app/maps/application_map.rb
index 78141b535..ac5450197 100644
--- a/app/maps/application_map.rb
+++ b/app/maps/application_map.rb
@@ -56,11 +56,11 @@ class ApplicationMap
end
page << map.add_layer(MapLayers::OSM_MAPNIK)
- #page << map.add_layers([geoportail_scans, geoportail_ortho])
- page << map.add_layer(google_physical)
- page << map.add_layer(google_streets)
- page << map.add_layer(google_hybrid)
- page << map.add_layer(google_satellite)
+ #page << map.add_layers([geoportail_scans, geoportail_ortho])
+ page << map.add_layer(google_physical)
+ page << map.add_layer(google_streets)
+ page << map.add_layer(google_hybrid)
+ page << map.add_layer(google_satellite)
customize_map(map,page) if respond_to?( :customize_map)
end
@@ -121,13 +121,13 @@ class ApplicationMap
def google_hybrid
OpenLayers::Layer::Google.new I18n.t("maps.google_hybrid"), :type => :"google.maps.MapTypeId.HYBRID", :numZoomLevels => 20
end
-
+
def google_satellite
OpenLayers::Layer::Google.new I18n.t("maps.google_satellite"), :type => :"google.maps.MapTypeId.SATELLITE", :numZoomLevels => 22
end
def hover_control_display_name(layer)
- OpenLayers::Control::SelectFeature.new( layer, {
+ OpenLayers::Control::SelectFeature.new( layer, {
:autoActivate => true,
:hover => true,
:renderIntent => "temporary",
@@ -136,10 +136,10 @@ class ApplicationMap
var feature = e.feature ;
if (feature.attributes.inactive != undefined)
return;
- var popup = new OpenLayers.Popup.AnchoredBubble('chicken',
+ var popup = new OpenLayers.Popup.Anchored('chicken',
new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y),
null,
- \"<div class='popup_hover'><b>\" + feature.attributes.name +\"</b></div> \", null, false, null);
+ \"<div class='popup_hover'><p><b>\" + feature.attributes.name +\"</b><p>\" + feature.attributes.stop_area_type_label + \"</div> \", null, false, null);
popup.autoSize = true;
popup.displayClass = 'popup_hover';
@@ -152,12 +152,12 @@ class ApplicationMap
return;
map.removePopup(feature.popup);
feature.popup.destroy();
- feature.popup = null;
+ feature.popup = null;
}")
} } )
end
- def kml_layer(url_or_object, options_or_url_options = {}, options = nil)
+ def kml_layer(url_or_object, options_or_url_options = {}, options = nil)
unless options
url_options = {}
options = options_or_url_options
@@ -176,7 +176,7 @@ class ApplicationMap
else
helpers.polymorphic_path_patch( helpers.polymorphic_path([url_or_object.referential, url_or_object], url_options))
end
-
+
protocol = OpenLayers::Protocol::HTTP.new :url => url, :format => kml
OpenLayers::Layer::Vector.new name, {:projection => projection("EPSG:4326"), :strategies => [strategy_fixed], :protocol => protocol, :displayInLayerSwitcher => false}.merge(options)
end
diff --git a/app/maps/stop_area_map.rb b/app/maps/stop_area_map.rb
index 6c3dd5feb..93ec9ecdb 100644
--- a/app/maps/stop_area_map.rb
+++ b/app/maps/stop_area_map.rb
@@ -10,12 +10,10 @@ 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)
+ page << map.add_control( hover_control_display_name(:children_layer) )
end
if stop_area.routing_stops.present?
page.assign "routing_layer", kml_layer(stop_area, { :routing => true }, :style_map => Design::StopAreasStyleMap.new(helpers).style_map)
@@ -23,38 +21,111 @@ 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 = {fill: false, stroke: false, label: "\uf041", labelAlign: "cb", labelXOffset: 0, labelYOffset: 0, fontSize:"20px", fontOpacity: 1, fontFamily: "FontAwesome", labelOutlineWidth: 2};
+ 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_longitude').val(geometry.x);
- $('#stop_area_latitude').val(geometry.y);
-
- if(referential_projection != undefined)
- {
- projection_geometry = event.feature.geometry.clone().transform(new OpenLayers.Projection("EPSG:900913"), referential_projection );
- $('#stop_area_projection_x').val(projection_geometry.x);
- $('#stop_area_projection_y').val(projection_geometry.y); }
- }
- });
+
+ 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))
- elsif stop_area.children.present?
- page << map.add_control( hover_control_display_name(:children_layer) )
+ if stop_area.new_record?
+ page << <<EOF
+ drawControl.activate();
+EOF
+ end
end
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 f684ddef5..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 = {
@@ -102,17 +106,22 @@ class Export < ActiveRecord::Base
"CsvExport" => "CSV",
"GtfsExport" => "GTFS",
"NetexExport" => "NeTEx",
- "KmlExport" => "KML"
+ "KmlExport" => "KML",
+ "HubExport" => "HUB"
}
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?
subclasses.map(&:to_s)
else
# FIXME
- %w{NeptuneExport CsvExport GtfsExport NetexExport KmlExport}
+ %w{NeptuneExport CsvExport GtfsExport NetexExport KmlExport HubExport}
end
end
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/hub_export.rb b/app/models/hub_export.rb
new file mode 100644
index 000000000..3d93cbfae
--- /dev/null
+++ b/app/models/hub_export.rb
@@ -0,0 +1,35 @@
+class HubExport < Export
+
+ option :start_date
+ option :end_date
+
+ after_initialize :init_period
+
+ def init_period
+ unless Chouette::TimeTable.start_validity_period.nil?
+ if start_date.nil?
+ self.start_date = Chouette::TimeTable.start_validity_period
+ end
+ if end_date.nil?
+ self.end_date = Chouette::TimeTable.end_validity_period
+ end
+ end
+ end
+
+ def export_options
+ if (start_date.empty? && end_date.empty?)
+ super.merge(:format => :hub).except(:start_date).except(:end_date)
+ elsif start_date.empty?
+ super.merge(:format => :hub, :end_date => end_date).except(:start_date)
+ elsif end_date.empty?
+ super.merge(:format => :hub, :start_date => start_date).except(:end_date)
+ else
+ super.merge(:format => :hub, :start_date => start_date, :end_date => end_date)
+ end
+ end
+
+ def exporter
+ exporter ||= ::Chouette::Hub::Exporter.new(referential, self)
+ 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/organisation.rb b/app/models/organisation.rb
index 17cf9a8f2..f4b2e35f8 100644
--- a/app/models/organisation.rb
+++ b/app/models/organisation.rb
@@ -3,6 +3,5 @@ class Organisation < ActiveRecord::Base
has_many :users, :dependent => :destroy
has_many :referentials, :dependent => :destroy
- validates_presence_of :name
- validates_uniqueness_of :name
+ validates :name, :presence => true, :uniqueness => true
end
diff --git a/app/models/referential.rb b/app/models/referential.rb
index 6e0b13ef6..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
@@ -191,6 +195,7 @@ end
Rails.application.config.after_initialize do
+
Chouette::TridentActiveRecord
class Chouette::TridentActiveRecord
@@ -211,7 +216,7 @@ Rails.application.config.after_initialize do
class Chouette::StopArea
- attr_accessible :projection_x,:projection_y
+ attr_accessible :projection_x,:projection_y,:projection_xy
# override default_position method to add referential envelope when no stoparea is positioned
def default_position
@@ -220,24 +225,13 @@ Rails.application.config.after_initialize do
end
# add projection_type set on pre-insert and pre_update action
- before_validation :set_projections
+ before_save :set_projections
def set_projections
- if ! self.latitude.nil? && ! self.longitude.nil?
+ if ! self.coordinates.blank?
self.long_lat_type = 'WGS84'
else
self.long_lat_type = nil
end
-# if ! self.referential.projection_type.nil? && !self.referential.projection_type.empty?
-# if ! self.x.nil? && ! self.y.nil?
-# self.projection_type = referential.projection_type_label
-# else
-# self.projection_type = nil
-# end
-# else
-# self.projection_type = nil
-# self.x = nil
-# self.y = nil
-# end
end
def projection
@@ -254,7 +248,6 @@ Rails.application.config.after_initialize do
nil
else
@point ||= GeoRuby::SimpleFeatures::Point::from_lat_lng(Geokit::LatLng.new(self.latitude,self.longitude)).project_to(self.projection.to_i)
-
@point.x
end
end
@@ -266,39 +259,39 @@ Rails.application.config.after_initialize do
@point.y
end
end
+ def projection_xy
+ if self.long_lat_type.nil? || self.projection.nil?
+ nil
+ else
+ @point ||= GeoRuby::SimpleFeatures::Point::from_lat_lng(Geokit::LatLng.new(self.latitude,self.longitude)).project_to(self.projection.to_i)
+ @point.x.to_s+","+@point.y.to_s
+ end
+ end
def projection_x=(dummy)
# dummy method
end
def projection_y=(dummy)
# dummy method
end
+ def projection_xy=(dummy)
+ # dummy method
+ end
end
Chouette::AccessPoint
class Chouette::AccessPoint
- attr_accessible :projection_x,:projection_y
+ attr_accessible :projection_x,:projection_y,:projection_xy
# add projection_type set on pre-insert and pre_update action
- before_validation :set_projections
+ before_save :set_projections
def set_projections
- if ! self.latitude.nil? && ! self.longitude.nil?
+ if ! self.coordinates.blank?
self.long_lat_type = 'WGS84'
else
self.long_lat_type = nil
end
-# if ! self.referential.projection_type.nil? && !self.referential.projection_type.empty?
-# if ! self.x.nil? && ! self.y.nil?
-# self.projection_type = referential.projection_type_label
-# else
-# self.projection_type = nil
-# end
-# else
-# self.projection_type = nil
-# self.x = nil
-# self.y = nil
-# end
end
def projection
@@ -315,7 +308,6 @@ Rails.application.config.after_initialize do
nil
else
@point ||= GeoRuby::SimpleFeatures::Point::from_lat_lng(Geokit::LatLng.new(self.latitude,self.longitude)).project_to(self.projection.to_i)
-
@point.x
end
end
@@ -327,12 +319,23 @@ Rails.application.config.after_initialize do
@point.y
end
end
+ def projection_xy
+ if self.long_lat_type.nil? || self.projection.nil?
+ nil
+ else
+ @point ||= GeoRuby::SimpleFeatures::Point::from_lat_lng(Geokit::LatLng.new(self.latitude,self.longitude)).project_to(self.projection.to_i)
+ @point.x.to_s+","+@point.y.to_s
+ end
+ end
def projection_x=(dummy)
# dummy method
end
def projection_y=(dummy)
# dummy method
end
+ def projection_xy=(dummy)
+ # dummy method
+ end
end
end
diff --git a/app/models/rule_parameter_set.rb b/app/models/rule_parameter_set.rb
index 5177d6ecc..0c7a98300 100644
--- a/app/models/rule_parameter_set.rb
+++ b/app/models/rule_parameter_set.rb
@@ -9,13 +9,14 @@ class RuleParameterSet < ActiveRecord::Base
attr_accessible :name, :referential_id
def self.mode_attribute_prefixes
- %w( inter_stop_area_distance_min inter_stop_area_distance_max speed_max speed_min inter_stop_duration_variation_max)
+ %w( allowed_transport inter_stop_area_distance_min inter_stop_area_distance_max speed_max speed_min inter_stop_duration_variation_max)
end
def self.general_attributes
%w( inter_stop_area_distance_min parent_stop_area_distance_max stop_areas_area inter_access_point_distance_min
inter_connection_link_distance_max walk_default_speed_max
walk_occasional_traveller_speed_max walk_frequent_traveller_speed_max walk_mobility_restricted_traveller_speed_max
- inter_access_link_distance_max inter_stop_duration_max facility_stop_area_distance_max)
+ inter_access_link_distance_max inter_stop_duration_max facility_stop_area_distance_max
+ vehicle_journey_number_max vehicle_journey_number_min check_allowed_transport_modes)
end
def self.all_modes
Chouette::TransportMode.all.map { |m| m.to_s}
@@ -75,7 +76,8 @@ class RuleParameterSet < ActiveRecord::Base
:walk_mobility_restricted_traveller_speed_max => 1,
:inter_access_link_distance_max => 300,
:inter_stop_duration_max => 40,
- :facility_stop_area_distance_max => 300
+ :facility_stop_area_distance_max => 300,
+ :check_allowed_transport_modes => false
}
if mode && self.mode_default_params[ mode.to_sym]
base.merge!( self.mode_default_params[ mode.to_sym])
@@ -85,108 +87,126 @@ class RuleParameterSet < ActiveRecord::Base
def self.mode_default_params
{
:coach => {
+ :allowed_transport_mode_coach => false,
:inter_stop_area_distance_min_mode_coach => 500,
:inter_stop_area_distance_max_mode_coach => 10000,
:speed_max_mode_coach => 90,
:speed_min_mode_coach => 40,
:inter_stop_duration_variation_max_mode_coach => 20},
:air => {
+ :allowed_transport_mode_air => false,
:inter_stop_area_distance_min_mode_air => 200,
:inter_stop_area_distance_max_mode_air => 10000,
:speed_max_mode_air => 800,
:speed_min_mode_air => 700,
:inter_stop_duration_variation_max_mode_air => 60},
:waterborne => {
+ :allowed_transport_mode_waterborne => false,
:inter_stop_area_distance_min_mode_waterborne => 200,
:inter_stop_area_distance_max_mode_waterborne => 10000,
:speed_max_mode_waterborne => 40,
:speed_min_mode_waterborne => 5,
:inter_stop_duration_variation_max_mode_waterborne => 60},
:bus => {
+ :allowed_transport_mode_bus => false,
:inter_stop_area_distance_min_mode_bus => 100,
:inter_stop_area_distance_max_mode_bus => 10000,
:speed_max_mode_bus => 60,
:speed_min_mode_bus => 10,
:inter_stop_duration_variation_max_mode_bus => 15},
:ferry => {
+ :allowed_transport_mode_ferry => false,
:inter_stop_area_distance_min_mode_ferry => 200,
:inter_stop_area_distance_max_mode_ferry => 10000,
:speed_max_mode_ferry => 40,
:speed_min_mode_ferry => 5,
:inter_stop_duration_variation_max_mode_ferry => 60},
:walk => {
+ :allowed_transport_mode_walk => false,
:inter_stop_area_distance_min_mode_walk => 1,
:inter_stop_area_distance_max_mode_walk => 10000,
:speed_max_mode_walk => 6,
:speed_min_mode_walk => 1,
:inter_stop_duration_variation_max_mode_walk => 10},
:metro => {
+ :allowed_transport_mode_metro => false,
:inter_stop_area_distance_min_mode_metro => 300,
:inter_stop_area_distance_max_mode_metro => 2000,
:speed_max_mode_metro => 60,
:speed_min_mode_metro => 30,
:inter_stop_duration_variation_max_mode_metro => 30},
:shuttle => {
+ :allowed_transport_mode_shuttle => false,
:inter_stop_area_distance_min_mode_shuttle => 500,
:inter_stop_area_distance_max_mode_shuttle => 10000,
:speed_max_mode_shuttle => 80,
:speed_min_mode_shuttle => 20,
:inter_stop_duration_variation_max_mode_shuttle => 10},
:rapid_transit => {
+ :allowed_transport_mode_rapid_transit => false,
:inter_stop_area_distance_min_mode_rapid_transit => 2000,
:inter_stop_area_distance_max_mode_rapid_transit => 500000,
:speed_max_mode_rapid_transit => 300,
:speed_min_mode_rapid_transit => 20,
:inter_stop_duration_variation_max_mode_rapid_transit => 60},
:taxi => {
+ :allowed_transport_mode_taxi => false,
:inter_stop_area_distance_min_mode_taxi => 500,
:inter_stop_area_distance_max_mode_taxi => 300000,
:speed_max_mode_taxi => 130,
:speed_min_mode_taxi => 20,
:inter_stop_duration_variation_max_mode_taxi => 60},
:local_train => {
+ :allowed_transport_mode_local_train => false,
:inter_stop_area_distance_min_mode_local_train => 2000,
:inter_stop_area_distance_max_mode_local_train => 500000,
:speed_max_mode_local_train => 300,
:speed_min_mode_local_train => 20,
:inter_stop_duration_variation_max_mode_local_train => 60},
:train => {
+ :allowed_transport_mode_train => false,
:inter_stop_area_distance_min_mode_train => 2000,
:inter_stop_area_distance_max_mode_train => 500000,
:speed_max_mode_train => 300,
:speed_min_mode_train => 20,
:inter_stop_duration_variation_max_mode_train => 60},
:long_distance_train => {
+ :allowed_transport_mode_long_distance_train => false,
:inter_stop_area_distance_min_mode_long_distance_train => 2000,
:inter_stop_area_distance_max_mode_long_distance_train => 500000,
:speed_max_mode_long_distance_train => 300,
:speed_min_mode_long_distance_train => 20,
:inter_stop_duration_variation_max_mode_long_distance_train => 60},
:tramway => {
+ :allowed_transport_mode_tramway => false,
:inter_stop_area_distance_min_mode_tramway => 300,
:inter_stop_area_distance_max_mode_tramway => 2000,
:speed_max_mode_tramway => 50,
:speed_min_mode_tramway => 20,
:inter_stop_duration_variation_max_mode_tramway => 30},
:trolleybus => {
+ :allowed_transport_mode_trolleybus => false,
:inter_stop_area_distance_min_mode_trolleybus => 300,
:inter_stop_area_distance_max_mode_trolleybus => 2000,
:speed_max_mode_trolleybus => 50,
:speed_min_mode_trolleybus => 20,
:inter_stop_duration_variation_max_mode_trolleybus => 30},
:private_vehicle => {
+ :allowed_transport_mode_private_vehicle => false,
:inter_stop_area_distance_min_mode_private_vehicle => 500,
:inter_stop_area_distance_max_mode_private_vehicle => 300000,
:speed_max_mode_private_vehicle => 130,
:speed_min_mode_private_vehicle => 20,
:inter_stop_duration_variation_max_mode_private_vehicle => 60},
:bicycle => {
+ :allowed_transport_mode_bicycle => false,
:inter_stop_area_distance_min_mode_bicycle => 300,
:inter_stop_area_distance_max_mode_bicycle => 30000,
:speed_max_mode_bicycle => 40,
:speed_min_mode_bicycle => 10,
:inter_stop_duration_variation_max_mode_bicycle => 10},
:other => {
+ :allowed_transport_mode_other => false,
:inter_stop_area_distance_min_mode_other => 300,
:inter_stop_area_distance_max_mode_other => 30000,
:speed_max_mode_other => 40,
@@ -208,6 +228,12 @@ class RuleParameterSet < ActiveRecord::Base
:name => "valeurs par defaut"
}.merge( mode_attributes))
end
+
+ def allowed(mode)
+ return true unless self.check_allowed_transport_modes
+ puts "#{mode} = "+self.send("allowed_transport_mode_#{mode}").to_s
+ return self.send("allowed_transport_mode_#{mode}") == "1"
+ end
all_modes.each do |mode|
mode_attribute_prefixes.each do |prefix|
@@ -217,7 +243,7 @@ class RuleParameterSet < ActiveRecord::Base
general_attributes.each do |attribute|
parameter attribute.to_sym
- unless attribute == "stop_areas_area"
+ unless attribute == "stop_areas_area" || attribute == "check_allowed_transport_modes"
validates attribute.to_sym, :numericality => true, :allow_nil => true, :allow_blank => true
end
end
diff --git a/app/models/stop_area_copy.rb b/app/models/stop_area_copy.rb
new file mode 100644
index 000000000..796aba567
--- /dev/null
+++ b/app/models/stop_area_copy.rb
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+
+class StopAreaCopy
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+ extend ActiveModel::Naming
+
+ attr_accessor :source_id, :hierarchy, :area_type, :source
+
+ validates_presence_of :source_id, :hierarchy, :area_type
+
+ validates :hierarchy, inclusion: { in: %w(child parent) }
+
+
+ def initialize(attributes = {})
+ attributes.each { |name, value| send("#{name}=", value) } if attributes
+ if self.area_type.blank? && self.source != nil
+ self.source_id = self.source.id
+ if self.hierarchy == "child"
+ if self.source.area_type.underscore == "stop_place"
+ self.area_type="commercial_stop_point"
+ else
+ self.area_type="boarding_position"
+ end
+ else
+ if self.source.area_type.underscore == "stop_place" || self.source.area_type.underscore == "commercial_stop_point"
+ self.area_type="stop_place"
+ else
+ self.area_type="commercial_stop_point"
+ end
+ end
+ end
+ end
+
+ def persisted?
+ false
+ end
+
+ def save
+ begin
+ if self.valid?
+ self.source ||= Chouette::StopArea.find self.source_id
+ copy = source.duplicate
+ copy.name = source.name
+ copy.area_type = self.area_type.camelcase
+ Chouette::StopArea.transaction do
+ if self.hierarchy == "child"
+ copy.parent_id = source.id
+ end
+ copy.save!
+ if self.hierarchy == "parent"
+ source.parent_id = copy.id
+ source.save!
+ end
+ end
+ true
+ else
+ false
+ end
+ rescue Exception => exception
+ Rails.logger.error(exception.message)
+ errors.add :base, I18n.t("stop_area_copies.errors.exception")
+ false
+ end
+ end
+
+
+end
diff --git a/app/models/time_table_combination.rb b/app/models/time_table_combination.rb
new file mode 100644
index 000000000..1fa497d73
--- /dev/null
+++ b/app/models/time_table_combination.rb
@@ -0,0 +1,47 @@
+class TimeTableCombination
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+ extend ActiveModel::Naming
+
+ attr_accessor :source_id, :combined_id, :operation
+
+ validates_presence_of :source_id, :combined_id, :operation
+ validates_inclusion_of :operation, :in => %w( union intersection disjunction)
+
+ def clean
+ self.source_id = nil
+ self.combined_id = nil
+ self.operation = nil
+ self.errors.clear
+ end
+
+ def self.operations
+ %w( union intersection disjunction)
+ end
+
+ def initialize(attributes = {})
+ attributes.each do |name, value|
+ send("#{name}=", value)
+ end
+ end
+
+ def persisted?
+ false
+ end
+
+ def combine
+ source = Chouette::TimeTable.find( source_id)
+ combined = Chouette::TimeTable.find( combined_id)
+ if operation == "union"
+ source.merge! combined
+ elsif operation == "intersection"
+ source.intersect! combined
+ elsif operation == "disjunction"
+ source.disjoin! combined
+ else
+ raise "unknown operation"
+ end
+ source
+ end
+
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index ae6cceeee..6c14b93fb 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -6,14 +6,16 @@ class User < ActiveRecord::Base
:confirmable, :invitable
# Setup accessible (or protected) attributes for your model
- attr_accessible :email, :password, :current_password, :password_confirmation, :remember_me, :name
+ attr_accessible :email, :password, :current_password, :password_confirmation, :remember_me, :name, :organisation_attributes
belongs_to :organisation
-
- validates_presence_of :email
- validates_presence_of :name
- validates_presence_of :password
- validates_presence_of :password_confirmation
+
+ accepts_nested_attributes_for :organisation
+
+ validates :organisation, :presence => true
+ validates :email, :presence => true, :uniqueness => true
+ validates :name, :presence => true
+ validates :password, :presence => true, :confirmation => true
before_validation(:on => :create) do
self.password ||= Devise.friendly_token.first(6)
diff --git a/app/models/vehicle_filter.rb b/app/models/vehicle_filter.rb
new file mode 100644
index 000000000..ba8cce867
--- /dev/null
+++ b/app/models/vehicle_filter.rb
@@ -0,0 +1,57 @@
+class VehicleFilter
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+ extend ActiveModel::Naming
+
+ attr_accessor :route
+ attr_accessor :q
+
+ def initialize(attributes = {})
+ attributes.each do |name, value|
+ send("#{name}=", value) if self.respond_to? name.to_sym
+ end
+ end
+
+ def without_any_time_table?
+ q && q[ "time_tables_id_not_eq" ] && q[ "time_tables_id_not_eq" ]=="1"
+ end
+ def without_any_passing_time?
+ q && q[ "vehicle_journey_at_stops_departure_time_not_eq" ] &&
+ q[ "vehicle_journey_at_stops_departure_time_not_eq" ]=="1"
+ end
+ def vehicles_passing_time_filtered
+ if without_any_passing_time?
+ route.vehicle_journeys.includes( :vehicle_journey_at_stops).where( :vehicle_journey_at_stops => { :id => nil})
+ else
+ route.sorted_vehicle_journeys
+ end
+ end
+ def vehicle_journeys
+ if without_any_time_table?
+ vehicles_passing_time_filtered.includes( :time_tables).where( :time_tables => { :id => nil})
+ elsif time_table_ids.empty?
+ vehicles_passing_time_filtered
+ else
+ vehicles_passing_time_filtered.joins( :time_tables).where( "time_tables_vehicle_journeys.time_table_id" => time_table_ids)
+ end
+ end
+ def time_table_ids
+ return [] unless q && q[ "time_tables_id_eq" ]
+ q[ "time_tables_id_eq" ].split(',')
+ end
+ def filtered_params
+ return {} unless q
+ q.tap do |filtered_params|
+ if without_any_passing_time?
+ 1.upto( 5 ) do |index|
+ q.delete "vehicle_journey_at_stops_departure_time_gt(#{index}i)"
+ end
+ end
+ q.delete "time_tables_id_eq"
+ q.delete "time_tables_id_not_eq"
+ q.delete "vehicle_journey_at_stops_departure_time_not_eq"
+ end
+ end
+
+
+end
diff --git a/app/models/vehicle_journey_export.rb b/app/models/vehicle_journey_export.rb
index 8fe7869f1..4c2c62fa8 100644
--- a/app/models/vehicle_journey_export.rb
+++ b/app/models/vehicle_journey_export.rb
@@ -1,14 +1,13 @@
# -*- coding: utf-8 -*-
require "csv"
+require "zip"
class VehicleJourneyExport
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
- attr_accessor :route
-
- validates_presence_of :route
+ attr_accessor :vehicle_journeys, :route
def initialize(attributes = {})
attributes.each { |name, value| send("#{name}=", value) }
@@ -17,17 +16,152 @@ class VehicleJourneyExport
def persisted?
false
end
+
+ 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 published_journey_name_array
+ (vehicle_journeys.collect{ |vj| vj.published_journey_name ? vj.published_journey_name : "" } )
+ 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|
- vehicle_journeys_sorted = route.vehicle_journeys.includes(:vehicle_journey_at_stops).order("vehicle_journey_at_stops.departure_time")
-
- vehicle_journey_at_stops_matrix = (vehicle_journeys_sorted.collect{ |vj| vj.vehicle_journey_at_stops.collect(&:departure_time).collect{|time| time.strftime("%H:%M")} }).transpose
- csv << ["stop_point_id", "stop_area_name"] + vehicle_journeys_sorted.collect(&:objectid)
- route.stop_points.each_with_index do |stop_point, index|
- csv << [stop_point.id, stop_point.stop_area.name] + vehicle_journey_at_stops_matrix[index]
+ CSV.generate(options) do |csv|
+ csv << column_names
+ csv << ["", label("number")] + number_array
+ csv << ["", label("published_journey_name")] + published_journey_name_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 5419a40b9..f710eeab7 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) }
+ 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?
@@ -20,21 +27,23 @@ class VehicleJourneyImport
def save
begin
- Chouette::VehicleJourney.transaction do
- if imported_vehicle_journeys.map(&:valid?).all?
+ Chouette::VehicleJourney.transaction do
+ if imported_vehicle_journeys.map(&:valid?).all?
imported_vehicle_journeys.each(&:save!)
true
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
- errors.add :base, I18n.t("vehicle_journey_imports.errors.exception", :message => exception.message)
+ Rails.logger.error(exception.message)
+ Rails.logger.error(exception.backtrace)
+ errors.add :base, I18n.t("vehicle_journey_imports.errors.exception")
false
end
end
@@ -44,61 +53,136 @@ 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 = []
first_column = spreadsheet.column(1)
- stop_point_ids = first_column[1..spreadsheet.last_row].map(&:to_i)
- same_stop_points = route.stop_points.collect(&:id) == stop_point_ids
- unless same_stop_points
+ # fixed rows (first = 1)
+ number_row = 2
+ published_journey_name_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)
+ # blank lines at end of file will produce id = 0 ; ignore them
+ last_stop_row_index = stop_point_ids.length + 6
+ while stop_point_ids.last == 0
+ stop_point_ids = stop_point_ids[0..-2]
+ last_stop_row_index -= 1
+ end
+
+ unless route.stop_points.collect(&:id) == stop_point_ids
errors.add :base, I18n.t("vehicle_journey_imports.errors.not_same_stop_points", :route => route.id)
- return vehicle_journeys
+ raise
end
-
- Chouette::VehicleJourney.transaction do
- (3..spreadsheet.last_column).each do |i|
- vehicle_journey_objectid = spreadsheet.column(i)[0]
- hours_by_stop_point_ids = Hash[[stop_point_ids, spreadsheet.column(i)[1..spreadsheet.last_row]].transpose]
-
- journey_pattern = find_journey_pattern_schedule(hours_by_stop_point_ids)
- #puts "journey_pattern #{journey_pattern.inspect}"
- vehicle_journey = journey_pattern.vehicle_journeys.where(:objectid => vehicle_journey_objectid, :route_id => route.id, :journey_pattern_id => journey_pattern.id).first_or_create
- #puts "vehicle_journey #{vehicle_journey.inspect}"
+
+ (3..spreadsheet.last_column).each do |i|
+ vehicle_journey_id = spreadsheet.column(i)[0]
+ hours_by_stop_point_ids = Hash[[stop_point_ids, spreadsheet.column(i)[first_stop_row_index..last_stop_row_index]].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])
+
+ # published_name
+ vehicle_journey.published_journey_name = spreadsheet.row(published_journey_name_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
+ 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
- main_time = Time.parse(value)
+ 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
+ # force UTC to ignore timezone effects
+ main_time = Time.parse(value+" UTC")
if main_time.present?
- vjas = Chouette::VehicleJourneyAtStop.where(:vehicle_journey_id => vehicle_journey.id, :stop_point_id => key).first_or_create(:departure_time => main_time, :arrival_time => main_time)
- #puts "vjas #{vjas.inspect}"
- else
- errors.add :base, I18n.t("vehicle_journey_imports.errors.invalid_vehicle_journey", :column => i, :line => line, :time => value)
+ 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
- end
- end
-
- vehicle_journeys << vehicle_journey
+ rescue Exception => exception
+ errors.add :base, I18n.t("vehicle_journey_imports.errors.invalid_vehicle_journey_at_stop", :column => i, :line => line, :time => value)
+ raise exception
+ end
+ end
end
+ vehicle_journeys << vehicle_journey
end
-
+
vehicle_journeys
end
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/models/vehicle_translation.rb b/app/models/vehicle_translation.rb
index 5fc7117eb..f89c127ab 100644
--- a/app/models/vehicle_translation.rb
+++ b/app/models/vehicle_translation.rb
@@ -1,45 +1,96 @@
class VehicleTranslation
- include ActiveModel::Validations
- include ActiveModel::Conversion
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
extend ActiveModel::Naming
-
-
+
attr_accessor :vehicle_journey_id, :count, :duration
-
- validates_presence_of :count, :duration
-
- def initialize(attributes = {})
- attributes.each do |name, value|
- send("#{name}=", value)
- end
- end
-
- def persisted?
- false
- end
+ attr_accessor :first_stop_time, :departure_or_arrival
+ attr_accessor :delta
+
+ validates_presence_of :count, :duration, :first_stop_time, :departure_or_arrival
+ validates_inclusion_of :departure_or_arrival, :in => %w( departure arrival)
+ validates_numericality_of :count, greater_than: 0
+ validates_numericality_of :duration, greater_than: 0
+ validate :firts_stop_time_format
+ validate :vehicle_has_stop_times
+
+ def initialize(attributes = {})
+ attributes.each do |name, value|
+ send("#{name}=", value)
+ end
+ end
+
+ def firts_stop_time_format
+ if first_stop_time.blank?
+ errors.add :first_stop_time, I18n.t('activemodel.errors.models.vehicle_translation.unreadable_time') unless self.class.time_format_text?( self.first_stop_time)
+ end
+ end
+
+ def self.time_format_text?( text)
+ begin
+ Time.parse text
+ rescue
+ false
+ end
+ end
+
+ def vehicle_has_stop_times
+ if vehicle_journey.vehicle_journey_at_stops.empty?
+ errors.add :vehicle_journey_id, I18n.t('activemodel.errors.models.vehicle_translation.uncompiliant_vehicle')
+ end
+ end
+
+ def persisted?
+ false
+ end
+
+ def move_time_in_current_time_zone( time )
+ Time.parse( "#{time.hour}:#{time.min}")
+ end
+ def evaluate_delta( actual_time)
+ Time.parse( first_stop_time) - move_time_in_current_time_zone( actual_time)
+ end
+ def vjas_time_attribute
+ "#{departure_or_arrival}_time"
+ end
+ def first_vjas_time
+ vehicle_journey.vehicle_journey_at_stops.first.send( vjas_time_attribute)
+ end
+ def first_delta
+ evaluate_delta( first_vjas_time)
+ end
def translate
- vehicle = vehicle_journey
copied_attributes = vehicle_journey.attributes
copied_attributes.delete( "id")
copied_attributes.delete( "objectid")
- 1.upto( count.to_i) do |index|
- translated = Chouette::VehicleJourney.create( copied_attributes)
- translated.time_tables = vehicle.time_tables
- vehicle.vehicle_journey_at_stops.each do |vjas|
- vjas_attributes = vjas.attributes.merge( "vehicle_journey_id" => translated.id)
- vjas_attributes.merge! "departure_time" => ( vjas_attributes[ "departure_time"] + (index * duration.to_i.minutes) ),
- "arrival_time" => ( vjas_attributes[ "arrival_time"] + (index * duration.to_i.minutes) )
+ # time shift for current duplicated vehicle
+ delta = first_delta
- Chouette::VehicleJourneyAtStop.create( vjas_attributes)
- end
+ vehicle_journey.transaction do
+ 1.upto( count.to_i) do |index|
+ translated = Chouette::VehicleJourney.create( copied_attributes)
+ translated.time_tables = vehicle_journey.time_tables
+ vehicle_journey.vehicle_journey_at_stops.each do |vjas|
+ vjas_attributes = vjas.attributes.merge( "vehicle_journey_id" => translated.id)
+ vjas_attributes.merge! "departure_time" => ( vjas_attributes[ "departure_time"] + delta),
+ "arrival_time" => ( vjas_attributes[ "arrival_time"] + delta)
+
+ Chouette::VehicleJourneyAtStop.create( vjas_attributes)
+ end
+ delta += duration.to_i.minutes
+ end
end
end
-
+
+ def first_stop_name
+ @first_stop_name ||= vehicle_journey.vehicle_journey_at_stops.first.stop_point.stop_area.name
+ end
+
def vehicle_journey
- Chouette::VehicleJourney.find( vehicle_journey_id)
+ @vehicle_journey ||= Chouette::VehicleJourney.find( vehicle_journey_id)
end
def self.from_vehicle( vehicle)
diff --git a/app/views/access_link_pairs/_access_link_pair.html.erb b/app/views/access_link_pairs/_access_link_pair.html.erb
index 588b276b9..3e0d8a4fe 100644
--- a/app/views/access_link_pairs/_access_link_pair.html.erb
+++ b/app/views/access_link_pairs/_access_link_pair.html.erb
@@ -1,57 +1,56 @@
-<%= div_for(access_link_pair) do %>
- <tr>
- <td class="link">
- <div class="access_point">
- <%= link_to([@referential, @stop_area, access_link_pair.access_point]) do %>
+<tr>
+ <td>
+ <div class="link">
+ <div class="access_point">
+ <%= link_to([@referential, @stop_area, access_link_pair.access_point]) do %>
<%= image_tag "map/access_" + access_link_pair.access_point.access_point_type + ".png" %><span><%= access_link_pair.access_point.name %></span>
- <% end %>
+ <% end %>
+ </div>
+ <div class="info">
+ <%= t("access_types.label.#{access_link_pair.access_point.access_point_type}") %>
+ </div>
</div>
- <br/><br/>
- <div class="info">
- <%= t("access_types.label.#{access_link_pair.access_point.access_point_type}") %>
- </div>
- </td>
- <td>
- <% if access_link_pair.out_valid? %>
- <% if access_link_pair.out_exists? %>
- <%= link_to(referential_access_point_access_link_path(@referential, access_link_pair.access_point,:access_link => {:stop_area_id => access_link_pair.stop_area.id, :link_orientation_type => 'stop_area_to_access_point'})) do %>
- <%= image_tag "icons/green_left_arrow.png" %>
- <% end %>
- <% else %>
- <%= link_to(new_referential_access_point_access_link_path(@referential, access_link_pair.access_point, :access_link => {:stop_area_id => access_link_pair.stop_area.id, :link_orientation_type => 'stop_area_to_access_point'})) do %>
- <%= image_tag "icons/gray_left_arrow.png" %>
- <% end %>
- <% end %>
- <% else %>
- <%= image_tag "icons/disabled_left_arrow.png" %>
- <% end %>
- </td>
- <td>
- <% if access_link_pair.in_valid? %>
- <% if access_link_pair.in_exists? %>
- <%= link_to(referential_access_point_access_link_path(@referential, access_link_pair.access_point, access_link_pair.from_access_point)) do %>
- <%= image_tag "icons/green_right_arrow.png" %>
- <% end %>
- <% else %>
- <%= link_to(new_referential_access_point_access_link_path(@referential, access_link_pair.access_point, :access_link => {:stop_area_id => access_link_pair.stop_area.id, :link_orientation_type => 'access_point_to_stop_area'})) do %>
- <%= image_tag "icons/gray_right_arrow.png" %>
- <% end %>
- <% end %>
- <% else %>
- <%= image_tag "icons/disabled_right_arrow.png" %>
- <% end %>
- </td>
- <td class="link">
- <div class="stop_area">
- <%= link_to([@referential, access_link_pair.stop_area]) do %>
+ </td>
+ <td>
+ <% if access_link_pair.out_valid? %>
+ <% if access_link_pair.out_exists? %>
+ <%= link_to(referential_access_point_access_link_path(@referential, access_link_pair.access_point,:access_link => {:stop_area_id => access_link_pair.stop_area.id, :link_orientation_type => 'stop_area_to_access_point'})) do %>
+ <%= image_tag "icons/green_left_arrow.png" %>
+ <% end %>
+ <% else %>
+ <%= link_to(new_referential_access_point_access_link_path(@referential, access_link_pair.access_point, :access_link => {:stop_area_id => access_link_pair.stop_area.id, :link_orientation_type => 'stop_area_to_access_point'})) do %>
+ <%= image_tag "icons/gray_left_arrow.png" %>
+ <% end %>
+ <% end %>
+ <% else %>
+ <%= image_tag "icons/disabled_left_arrow.png" %>
+ <% end %>
+ </td>
+ <td>
+ <% if access_link_pair.in_valid? %>
+ <% if access_link_pair.in_exists? %>
+ <%= link_to(referential_access_point_access_link_path(@referential, access_link_pair.access_point, access_link_pair.from_access_point)) do %>
+ <%= image_tag "icons/green_right_arrow.png" %>
+ <% end %>
+ <% else %>
+ <%= link_to(new_referential_access_point_access_link_path(@referential, access_link_pair.access_point, :access_link => {:stop_area_id => access_link_pair.stop_area.id, :link_orientation_type => 'access_point_to_stop_area'})) do %>
+ <%= image_tag "icons/gray_right_arrow.png" %>
+ <% end %>
+ <% end %>
+ <% else %>
+ <%= image_tag "icons/disabled_right_arrow.png" %>
+ <% end %>
+ </td>
+ <td>
+ <div class="link">
+ <div class="stop_area">
+ <%= link_to([@referential, access_link_pair.stop_area]) do %>
<%= image_tag "map/" + access_link_pair.stop_area.stop_area_type + ".png" %><span><%= access_link_pair.stop_area.name %></span>
- <% end %>
+ <% end %>
+ </div>
+ <div class="info">
+ <%= t("area_types.label.#{access_link_pair.stop_area.stop_area_type}") %>
+ </div>
</div>
- <br/><br/>
- <div class="info">
- <%= t("area_types.label.#{access_link_pair.stop_area.stop_area_type}") %>
- </div>
- </td>
- </tr>
- <tr><td colspan=4>&nbsp;</td></tr>
-<% end %>
+ </td>
+</tr>
diff --git a/app/views/access_links/_form.html.erb b/app/views/access_links/_form.html.erb
index a5145adc7..2ce44542f 100644
--- a/app/views/access_links/_form.html.erb
+++ b/app/views/access_links/_form.html.erb
@@ -6,29 +6,17 @@
<%= form.input :name %>
<%= form.input :access_link_type, :as => :select, :collection => Chouette::AccessLink.access_link_types, :include_blank => false, :member_label => Proc.new { |type| t("connection_link_types.label.#{type}") } %>
<%= form.input :comment %>
- <%= form.input :link_distance %>
- <%= form.inputs :name => t('access_links.show.durations') do %>
- <%= form.input "default_duration(1i)", :as => :hidden ,:input_html => { :value => "2000" } %>
- <%= form.input "default_duration(2i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input "default_duration(3i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input :default_duration, :ignore_date=>true,:include_seconds=>true, :label => @access_link.human_attribute_name("default_duration")%>
- <%= form.input "frequent_traveller_duration(1i)", :as => :hidden ,:input_html => { :value => "2000" } %>
- <%= form.input "frequent_traveller_duration(2i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input "frequent_traveller_duration(3i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input :frequent_traveller_duration, :ignore_date=>true,:include_seconds=>true, :label => @access_link.human_attribute_name("frequent_traveller_duration")%>
- <%= form.input "occasional_traveller_duration(1i)", :as => :hidden ,:input_html => { :value => "2000" } %>
- <%= form.input "occasional_traveller_duration(2i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input "occasional_traveller_duration(3i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input :occasional_traveller_duration, :ignore_date=>true,:include_seconds=>true, :label => @access_link.human_attribute_name("occasional_traveller_duration")%>
- <%= form.input "mobility_restricted_traveller_duration(1i)", :as => :hidden ,:input_html => { :value => "2000" } %>
- <%= form.input "mobility_restricted_traveller_duration(2i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input "mobility_restricted_traveller_duration(3i)", :as => :hidden ,:input_html => { :value => "1" } %>
- <%= form.input :mobility_restricted_traveller_duration, :ignore_date=>true,:include_seconds=>true, :label => @access_link.human_attribute_name("mobility_restricted_traveller_duration")%>
- <% end %>
+ <%= form.input :link_distance %>
<%= form.input :mobility_restricted_suitability,:as => :boolean %>
<%= form.input :stairs_availability,:as => :boolean %>
<%= form.input :lift_availability,:as => :boolean %>
- <%= form.input :objectid, :required => !@access_link.new_record? %>
+ <%= form.input :objectid, :required => !@access_link.new_record?, :input_html => { :title => t("formtastic.titles.access_link.objectid")} %>
+ <%= form.inputs :name => t('access_links.show.durations') do %>
+ <%= form.input :default_duration, :as => :extended_time_picker, :size => 8, :step => :seconds, :label => @access_link.human_attribute_name("default_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :frequent_traveller_duration, :as => :extended_time_picker, :size => 8, :step => :seconds, :include_seconds => true, :label => @access_link.human_attribute_name("frequent_traveller_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :occasional_traveller_duration, :as => :extended_time_picker, :size => 8, :include_seconds => true, :label => @access_link.human_attribute_name("occasional_traveller_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :mobility_restricted_traveller_duration, :as => :extended_time_picker,:size => 8, :include_seconds => true, :label => @access_link.human_attribute_name("mobility_restricted_traveller_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <% end %>
<% end %>
<%= form.actions do %>
<%= form.action :submit, :as => :button %>
diff --git a/app/views/access_links/show.html.erb b/app/views/access_links/show.html.erb
index a318a84c6..3999b0287 100644
--- a/app/views/access_links/show.html.erb
+++ b/app/views/access_links/show.html.erb
@@ -5,18 +5,6 @@
<div class="summary">
<p>
- <label><%= @access_link.human_attribute_name(:access_point) %>: </label>
- <%= link_to @access_link.access_point.name, [@referential, @access_link.access_point.stop_area, @access_link.access_point] %>
- </p>
- <p>
- <label><%= @access_link.human_attribute_name(:stop_area) %>: </label>
- <%= link_to @access_link.stop_area.name, [@referential, @access_link.stop_area] %>
- </p>
- <p>
- <label><%= @access_link.human_attribute_name("name") %>: </label>
- <%= @access_link.name %>
- </p>
- <p>
<label><%= @access_link.human_attribute_name("access_link_type") %>: </label>
<%= t("connection_link_types.label.#{@access_link.access_link_type}") %>
</p>
@@ -67,10 +55,6 @@
<label><%= @access_link.human_attribute_name("lift_availability") %>: </label>
<%= t((@access_link.lift_availability == true).to_s) %>
</p>
- <p>
- <label><%= @access_link.human_attribute_name("objectid") %>: </label>
- <%= @access_link.objectid %>
- </p>
</div>
</div>
diff --git a/app/views/access_points/_access_point.html.erb b/app/views/access_points/_access_point.html.erb
index 2890cc124..020d9bd58 100644
--- a/app/views/access_points/_access_point.html.erb
+++ b/app/views/access_points/_access_point.html.erb
@@ -1,20 +1,29 @@
-<%= div_for(access_point) do %>
- <%= link_to([@referential, @stop_area, access_point], :class => "preview") do %>
- <div class="access_point_type">
- <%= image_tag "map/access_" + access_point.access_point_type + ".png" %>
- </div>
- <% end %>
- <%= link_to access_point.name, [@referential, @stop_area, access_point] %>
- <div class="info">
- <p>
- <% unless access_point.geometry %>
- <span class="warning"><%= t('.no_position') %></span> -
- <% end %>
- </p>
- <p><%= t("access_types.label.#{access_point.access_point_type}") %></p>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_stop_area_access_point_path(@referential, @stop_area, access_point), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_stop_area_access_point_path(@referential, @stop_area, access_point), :method => :delete, :data => {:confirm => t('access_points.actions.destroy_confirm')}, :class => "remove" %>
- </div>
+<div id="index_item" class="panel panel-default access_point">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_stop_area_access_point_path(@referential, @stop_area, access_point), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_stop_area_access_point_path(@referential, @stop_area, access_point), :method => :delete, :data => {:confirm => t('access_points.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, @stop_area, access_point], :class => "preview", :title => "#{Chouette::StopArea.model_name.human.capitalize} #{access_point.name}") do %>
+ <span class="name">
+ <%= image_tag "map/access_" + access_point.access_point_type + ".png" %> <%= truncate(access_point.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
-<% end %>
+ <div class="panel-body">
+ <% unless access_point.geometry %>
+ <p>
+ <span class="warning"><%= t('.no_position') %></span> -
+ </p>
+ <% end %>
+ <p><%= t("access_types.label.#{access_point.access_point_type}") %></p>
+ </div>
+</div>
diff --git a/app/views/access_points/_form.html.erb b/app/views/access_points/_form.html.erb
index f70b03ac3..adbfd0348 100644
--- a/app/views/access_points/_form.html.erb
+++ b/app/views/access_points/_form.html.erb
@@ -9,29 +9,29 @@
:collection => Chouette::AccessPoint.access_point_types, :include_blank => false, :member_label => Proc.new { |access_point_type| t("access_types.label.#{access_point_type}") } %>
<%= form.input :street_name %>
<%= form.input :country_code %>
- <%= form.input :comment %>
- <%= form.input :openning_time, :as => :time_select %>
- <%= form.input :closing_time, :as => :time_select %>
+ <%= form.input :zip_code %>
+ <%= form.input :city_name %>
+ <%= form.input :comment %>
+ <%= form.input :openning_time, :as => :time_picker, :input_html => { :class => "form-control input-sm timepicker_basic"}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :closing_time, :as => :time_picker, :input_html => { :class => "form-control input-sm timepicker_basic"}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
<%= form.input :mobility_restricted_suitability,:as => :boolean %>
<%= form.input :stairs_availability,:as => :boolean %>
<%= form.input :lift_availability,:as => :boolean %>
- <%= form.input :objectid, :required => !@access_point.new_record? %>
+ <%= form.input :objectid, :required => !@access_point.new_record?, :input_html => { :title => t("formtastic.titles.access_point.objectid")} %>
<%= form.inputs :name => t('access_points.show.geographic_data') do %>
<% if ! @referential.projection_type_label.empty? %>
<div class="panel panel-default">
- <div class="panel-heading">@referential.projection_type_label</div>
+ <div class="panel-heading"><%= @referential.projection_type_label %></div>
<div class="panel-body">
- <%= form.input :projection_x %>
- <%= form.input :projection_y %>
+ <%= form.input :projection_xy, :input_html => { :title => t("formtastic.titles.access_point.projection_xy")} %>
</div>
</div>
<% end %>
<div class="panel panel-default">
<div class="panel-heading">WGS84</div>
<div class="panel-body">
- <%= form.input :longitude %>
- <%= form.input :latitude %>
+ <%= form.input :coordinates, :input_html => { :title => t("formtastic.titles.access_point.coordinates")} %>
</div>
</div>
<% end %>
diff --git a/app/views/access_points/show.html.erb b/app/views/access_points/show.html.erb
index d674ef88b..9f5e600e6 100644
--- a/app/views/access_points/show.html.erb
+++ b/app/views/access_points/show.html.erb
@@ -5,14 +5,6 @@
<% end %>
<div class="summary">
<p>
- <label><%= @access_point.human_attribute_name(:stop_area) %>: </label>
- <%= link_to @stop_area.name, [@referential, @stop_area] %>
- </p>
- <p>
- <label><%= @access_point.human_attribute_name("name") %>: </label>
- <%= @access_point.name %>
- </p>
- <p>
<label><%= @access_point.human_attribute_name("comment") %>: </label>
<%= @access_point.comment %>
</p>
@@ -25,6 +17,14 @@
<%= @access_point.country_code %>
</p>
<p>
+ <label><%= @access_point.human_attribute_name("zip_code") %>: </label>
+ <%= @access_point.zip_code %>
+ </p>
+ <p>
+ <label><%= @access_point.human_attribute_name("city_name") %>: </label>
+ <%= @access_point.city_name %>
+ </p>
+ <p>
<label><%= @access_point.human_attribute_name("access_point_type") %>: </label>
<%= t("access_types.label.#{@access_point.access_point_type}") %>
</p>
@@ -85,54 +85,29 @@
</p>
<% end %>
<% end %>
- <p>
- <label><%= @access_point.human_attribute_name("objectid") %>: </label>
- <%= @access_point.objectid %>
- </p>
- </div>
-
+ </div>
</div>
-
-<p class="after_map" />
-<div>
- <h3 class="access_point_generics">
- <a class="generics"><%= t('.generic_access_links') %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
-
- </h3>
- <div class="generics content">
+<div>
+ <h3 class="access_point_generics"><%= t('.generic_access_links') %></h3>
<div class="access_link_pairs">
- <table>
- <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@generic_access_links) %>
- </table>
- </div>
-
+ <table>
+ <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@generic_access_links) %>
+ </table>
</div>
- <h3 class="access_point_details">
- <a class="details"><%= t('.detail_access_links') %>
- <%= image_tag("icons/plus.png" , :class => "switcher") %>
- <%= image_tag("icons/minus.png" , :class => "switcher", :style => "display: none;" ) %>
- </a>
-
- </h3>
- <div class="details content" style="display: none;">
-
+ <h3 class="access_point_details"><%= t('.detail_access_links') %></h3>
<div class="access_link_pairs">
- <table>
- <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@detail_access_links) %>
- </table>
- </div>
-
- </div>
+ <table>
+ <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@detail_access_links) %>
+ </table>
+ </div>
</div>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('access_points.actions.new'), new_referential_stop_area_access_point_path(@referential,@stop_area), :class => "add" %></li>
<li><%= link_to t('access_points.actions.edit'), edit_referential_stop_area_access_point_path(@referential, @stop_area, @access_point), :class => "edit" %></li>
<li><%= link_to t('access_points.actions.destroy'), referential_stop_area_access_point_path(@referential, @stop_area, @access_point), :method => :delete, :data => {:confirm => t('access_points.actions.destroy_confirm')}, :class => "remove" %></li>
</ul>
diff --git a/app/views/api/hub/arrets_generiques.hub.erb b/app/views/api/hub/arrets_generiques.hub.erb
new file mode 100644
index 000000000..00f041552
--- /dev/null
+++ b/app/views/api/hub/arrets_generiques.hub.erb
@@ -0,0 +1 @@
+<%= @stop_area.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @stop_area.objectid %>;<%= @stop_area.name.encode(Encoding::ISO_8859_1) if @stop_area.name %>;<%= @stop_area.nearest_topic_name.encode(Encoding::ISO_8859_1) if @stop_area.nearest_topic_name %>;<%= @type %>;;<%= (@stop_area.latitude && @stop_area.longitude) ? RGeo::CoordSys::Proj4::transform_coords(@from_projection, @to_projection, @stop_area.longitude, @stop_area.latitude)[0].to_i : '' %>;<%= (@stop_area.latitude && @stop_area.longitude) ? RGeo::CoordSys::Proj4::transform_coords(@from_projection, @to_projection, @stop_area.longitude, @stop_area.latitude)[1].to_i : '' %>;<%= @stop_area.city_name.encode(Encoding::ISO_8859_1) if @stop_area.city_name %>;<%= @stop_area.zip_code if @stop_area.zip_code %>;<%= @stop_area.comment.encode(Encoding::ISO_8859_1) if @stop_area.comment %>;<%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/arrets_physiques.hub.erb b/app/views/api/hub/arrets_physiques.hub.erb
new file mode 100644
index 000000000..02cb11238
--- /dev/null
+++ b/app/views/api/hub/arrets_physiques.hub.erb
@@ -0,0 +1 @@
+<%= @stop_area.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @stop_area.objectid %>;<%= @stop_area.name.encode(Encoding::ISO_8859_1) if @stop_area.name %>;<%= @stop_area.nearest_topic_name.encode(Encoding::ISO_8859_1) if @stop_area.nearest_topic_name %>;<%= @type %>;<%= @parent.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @parent %>;<%= (@stop_area.latitude && @stop_area.longitude) ? RGeo::CoordSys::Proj4::transform_coords(@from_projection, @to_projection, @stop_area.longitude, @stop_area.latitude)[0].to_i : -1 %>;<%= (@stop_area.latitude && @stop_area.longitude) ? RGeo::CoordSys::Proj4::transform_coords(@from_projection, @to_projection, @stop_area.longitude, @stop_area.latitude)[1].to_i : -1 %>;<%= @stop_area.city_name.encode(Encoding::ISO_8859_1) if @stop_area.city_name %>;<%= @stop_area.zip_code if @stop_area.zip_code %>;<%= @stop_area.comment.encode(Encoding::ISO_8859_1) if @stop_area.comment %>;<%= @stop_area.registration_number %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/chemins.hub.erb b/app/views/api/hub/chemins.hub.erb
new file mode 100644
index 000000000..f5408c51f
--- /dev/null
+++ b/app/views/api/hub/chemins.hub.erb
@@ -0,0 +1 @@
+<%= @line.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @line %>;<%= @journey_pattern.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @journey_pattern.objectid %>;<%= @journey_pattern.registration_number if @journey_pattern.registration_number %>;<%= @journey_pattern.name.encode(Encoding::ISO_8859_1) if @journey_pattern.name %>;<%= (@journey_pattern.route.wayback == 'A' ? 1 : 2) if @journey_pattern.route %>;<%= @type %>;<% @stop_areas.each do |s| %>;<%= s.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if s.objectid %>;<%= s.registration_number %>;;<% end %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/communes.hub.erb b/app/views/api/hub/communes.hub.erb
new file mode 100644
index 000000000..265271c54
--- /dev/null
+++ b/app/views/api/hub/communes.hub.erb
@@ -0,0 +1 @@
+<%= @city_code %>;<%= @city_name.encode(Encoding::ISO_8859_1) if @city_name %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/correspondances.hub.erb b/app/views/api/hub/correspondances.hub.erb
new file mode 100644
index 000000000..3e2076947
--- /dev/null
+++ b/app/views/api/hub/correspondances.hub.erb
@@ -0,0 +1 @@
+<%= @departure.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @departure %>;<%= @departure.registration_number if @departure %>;<%= @arrival.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @arrival %>;<%= @arrival.registration_number if @arrival %>;<%= @connection_link.link_distance %>;<%= @connection_link.default_duration %>;<%= @count %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/courses.hub.erb b/app/views/api/hub/courses.hub.erb
new file mode 100644
index 000000000..416cd5ec2
--- /dev/null
+++ b/app/views/api/hub/courses.hub.erb
@@ -0,0 +1 @@
+<%= @numero %>;;;<%= @departure_stop_area.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @departure_stop_area %>;<%= @departure_time_sec %>;<%= @line.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @line %>;<%= @journey_pattern.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @journey_pattern %>;<%= "D" %>;<%= (@route.wayback == "R") ? 2 : 1 %>;<%= @validity %>;;<%= @departure_stop_area.registration_number if @departure_stop_area %>;<%= @renvoi %>;<%= @periods %>;<%= 1 %>;<%= @vehicle_journey.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %><%= "\u000D\u000A" %><%= @numero %>;;;<%= @arrival_stop_area.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @arrival_stop_area %>;<%= @arrival_time_sec %>;<%= @line.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @line %>;<%= @journey_pattern.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @journey_pattern %>;<%= "A" %>;<%= (@route.wayback == "R") ? 2 : 1 %>;<%= @validity %>;;<%= @arrival_stop_area.registration_number if @arrival_stop_area %>;<%= @renvoi %>;<%= @periods %>;<%= 1 %>;<%= @vehicle_journey.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/courses_operations.hub.erb b/app/views/api/hub/courses_operations.hub.erb
new file mode 100644
index 000000000..5c293a2ad
--- /dev/null
+++ b/app/views/api/hub/courses_operations.hub.erb
@@ -0,0 +1 @@
+<%= @number %>;<%= @vehicle_journey.published_journey_identifier %>;;;<%= @transport_mode %>;;<%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/directions.hub.erb b/app/views/api/hub/directions.hub.erb
new file mode 100644
index 000000000..dd069968d
--- /dev/null
+++ b/app/views/api/hub/directions.hub.erb
@@ -0,0 +1 @@
+<%= @journey_pattern.name.encode(Encoding::ISO_8859_1) if @journey_pattern.name %>;<%= @line.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @line %>;<%= (@journey_pattern.route.wayback == 'A' ? 1 : 2) if @journey_pattern.route %>;<%= @journey_pattern.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @journey_pattern.objectid %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/groupe_de_lignes.hub.erb b/app/views/api/hub/groupe_de_lignes.hub.erb
new file mode 100644
index 000000000..2547c1e11
--- /dev/null
+++ b/app/views/api/hub/groupe_de_lignes.hub.erb
@@ -0,0 +1 @@
+<%= @group_of_lines.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %>;<%= @group_of_lines.name.encode(Encoding::ISO_8859_1) if @group_of_lines.name %>;<%= @group_of_lines.id %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/horaires.hub.erb b/app/views/api/hub/horaires.hub.erb
new file mode 100644
index 000000000..1497588af
--- /dev/null
+++ b/app/views/api/hub/horaires.hub.erb
@@ -0,0 +1 @@
+<%= @stop_area_code %>;<%= @arrival_time %>;<%= @arrival_type %>;<%= @vehicle_journey_num %>;<%= @vehicle_journey_at_stop.vehicle_journey.journey_pattern_id %>;<%= @stop_area_id %>;<%= 2 * @vehicle_journey_id - 1 %><%= "\u000D\u000A" %><%= @stop_area_code %>;<%= @departure_time %>;<%= @departure_type %>;<%= @vehicle_journey_num %>;<%= @vehicle_journey_at_stop.vehicle_journey.journey_pattern_id %>;<%= @stop_area_id %>;<%= 2 * @vehicle_journey_id %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/lignes.hub.erb b/app/views/api/hub/lignes.hub.erb
new file mode 100644
index 000000000..921eb7056
--- /dev/null
+++ b/app/views/api/hub/lignes.hub.erb
@@ -0,0 +1 @@
+<%= @line.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @line.objectid %>;<%= @line.number %>;<%= @line.name.encode(Encoding::ISO_8859_1) if @line.name %>;;;<%= @company.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @company %>;<%= @network.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @network %>;<%= @group_of_line %>;<%= @line.id %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/modes_transports.hub.erb b/app/views/api/hub/modes_transports.hub.erb
new file mode 100644
index 000000000..742f8033e
--- /dev/null
+++ b/app/views/api/hub/modes_transports.hub.erb
@@ -0,0 +1 @@
+<%= @transport_mode %>;;<%= @transport_lines %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/periodes.hub.erb b/app/views/api/hub/periodes.hub.erb
new file mode 100644
index 000000000..2bb3e8368
--- /dev/null
+++ b/app/views/api/hub/periodes.hub.erb
@@ -0,0 +1 @@
+<%= Chouette::TimeTable.find(@time_table.id).objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %>;<%= @time_table.comment.encode(Encoding::ISO_8859_1) if @time_table.comment %>;<%= @time_table.start_date.strftime("%d/%m/%Y") %>;<%= @time_table.end_date.strftime("%d/%m/%Y") %>;<%= @calendar %>;<%= @identifier %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/reseaux.hub.erb b/app/views/api/hub/reseaux.hub.erb
new file mode 100644
index 000000000..95ab8d547
--- /dev/null
+++ b/app/views/api/hub/reseaux.hub.erb
@@ -0,0 +1 @@
+<%= @network.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %>;<%= @network.name.encode(Encoding::ISO_8859_1) if @network.name %>;<%= @network.id %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/schemas.hub.erb b/app/views/api/hub/schemas.hub.erb
new file mode 100644
index 000000000..f2759a871
--- /dev/null
+++ b/app/views/api/hub/schemas.hub.erb
@@ -0,0 +1 @@
+<%= @line.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if @line %>;<%= @route.wayback == 'A' ? 1 : 2 %>;<%= @route.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %><% @stop_areas.each do |s| %>;<%= s.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') if s.objectid %>;<%= s.registration_number if s.registration_number %><% end %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api/hub/transporteurs.hub.erb b/app/views/api/hub/transporteurs.hub.erb
new file mode 100644
index 000000000..595d3b5fb
--- /dev/null
+++ b/app/views/api/hub/transporteurs.hub.erb
@@ -0,0 +1 @@
+<%= @company.objectid.sub(/(\w*\:\w*\:)(\w*)/, '\2') %>;<%= @company.name.encode(Encoding::ISO_8859_1) if @company.name %>;<%= @company.id %><%= "\u000D\u000A" %> \ No newline at end of file
diff --git a/app/views/api_keys/_api_key.html.erb b/app/views/api_keys/_api_key.html.erb
index 6492af3b0..c81953311 100644
--- a/app/views/api_keys/_api_key.html.erb
+++ b/app/views/api_keys/_api_key.html.erb
@@ -1,12 +1,30 @@
-<%= div_for(api_key) do %>
- <%= api_key.token %>
- <div class="info">
- <%= api_key.class.human_attribute_name('name') %> <%= api_key.name %> -
- <%= api_key.class.human_attribute_name('updated_at') %> <%= l(api_key.updated_at) %>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_api_key_path(@referential, api_key), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_api_key_path(@referential, api_key), :method => :delete, :data => {:confirm => t('api_keys.actions.destroy_confirm')}, :class => "remove" %>
- </div>
+<div id="index_item" class="panel panel-default api_key">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_api_key_path(@referential, api_key), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_api_key_path(@referential, api_key), :method => :delete, :data => {:confirm => t('api_keys.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, api_key], :class => "preview", :title => "#{Chouette::StopArea.model_name.human.capitalize} #{api_key.name}") do %>
+ <span class="name">
+ <%= truncate(api_key.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
-<% end %>
+ <div class="panel-body">
+ <p>
+ <%= api_key.class.human_attribute_name('token') %> <%= truncate(api_key.token, :length => 20) %>
+ </p>
+ <p>
+ <%= api_key.class.human_attribute_name('updated_at') %> <%= l(api_key.updated_at) %>
+ </p>
+ </div>
+</div>
diff --git a/app/views/companies/_companies.erb b/app/views/companies/_companies.erb
new file mode 100644
index 000000000..fb36a86af
--- /dev/null
+++ b/app/views/companies/_companies.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @companies %>
+</div>
+<div class="companies paginated_content">
+ <%= paginated_content(@companies) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @companies, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/companies/_company.erb b/app/views/companies/_company.erb
index 4955dec8b..534c4c7a6 100644
--- a/app/views/companies/_company.erb
+++ b/app/views/companies/_company.erb
@@ -1,11 +1,26 @@
-<%= div_for(company) do %>
- <%= link_to company.name, [@referential, company] %>
- <div class="info">
- <%= company.human_attribute_name('code') %> <%= company.code %>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_company_path(@referential, company), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_company_path(@referential, company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, :class => "remove" %>
- </div>
-
+<div id="index_item" class="company panel panel-default">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_company_path(@referential, company), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_company_path(@referential, company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, company], :class => "preview", :title => "#{Chouette::Company.model_name.human.capitalize} #{company.name}") do %>
+ <span class="name">
+ <%= truncate(company.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
-<% end %>
+ <div class="panel-body">
+ <p>
+ <%= company.human_attribute_name('code') %> <%= company.code %>
+ </p>
+ </div>
+</div>
diff --git a/app/views/companies/_form.erb b/app/views/companies/_form.erb
index c4fb90ee1..6f89edbbc 100644
--- a/app/views/companies/_form.erb
+++ b/app/views/companies/_form.erb
@@ -8,8 +8,8 @@
<%= form.input :phone, :as => :phone %>
<%= form.input :fax, :as => :phone %>
<%= form.input :email, :as => :email %>
- <%= form.input :registration_number %>
- <%= form.input :objectid, :required => !@company.new_record? %>
+ <%= form.input :registration_number, :input_html => { :title => t("formtastic.titles.company.registration_number")} %>
+ <%= form.input :objectid, :required => !@company.new_record?, :input_html => { :title => t("formtastic.titles.company.objectid")} %>
<% end %>
<%= form.actions do %>
diff --git a/app/views/companies/index.html.erb b/app/views/companies/index.html.erb
index 74f5790d4..c28eaa8bc 100644
--- a/app/views/companies/index.html.erb
+++ b/app/views/companies/index.html.erb
@@ -1,22 +1,22 @@
<%= title_tag t('companies.index.title') %>
-<%= search_form_for @q, :url => referential_companies_path(@referential), :html => {:method => :get} do |f| %>
- <%= f.label :name_cont, "#{t('.name')} :" %>
- <%= f.text_field :name_cont %>
-
- <%= f.submit t('actions.search') %> <%= t("or") %>
- <%= link_to t("cancel"), referential_companies_path(@referential) %>
+<%= search_form_for @q, :url => referential_companies_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-12">
+ <%= f.text_field :name_cont, :placeholder => "#{t('.name')}", :class => "form-control" %>
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <!-- <a data-toggle="collapse" data-parent="#search" href="#advanced_search"> -->
+ <!-- <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %> -->
+ <!-- </a> -->
+ </div>
+</div>
<% end %>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @companies %>
-</div>
-<div class="companies paginated_content">
- <%= paginated_content(@companies) %>
-</div>
-<div class="pagination">
- <%= will_paginate @companies, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+<div id="companies"><%= render 'companies' %></div>
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/companies/index.js.erb b/app/views/companies/index.js.erb
new file mode 100644
index 000000000..3afe2b9c5
--- /dev/null
+++ b/app/views/companies/index.js.erb
@@ -0,0 +1 @@
+$('#companies').html('<%= escape_javascript(render("companies")) %>'); \ No newline at end of file
diff --git a/app/views/companies/show.html.erb b/app/views/companies/show.html.erb
index 844832ee1..0c8585a6c 100644
--- a/app/views/companies/show.html.erb
+++ b/app/views/companies/show.html.erb
@@ -1,13 +1,9 @@
<%= title_tag t('companies.show.title', :company => @company.name) %>
-<div class="line_show">
+<div class="company_show">
<div class="summary">
<p>
- <label><%= Chouette::Company.human_attribute_name("name") %>: </label>
- <%= @company.name %>
- </p>
- <p>
<label><%= Chouette::Company.human_attribute_name("short_name") %>: </label>
<%= @company.short_name %>
</p>
@@ -39,15 +35,12 @@
<label><%= Chouette::Company.human_attribute_name("registration_number") %>: </label>
<%= @company.registration_number %>
</p>
- <p>
- <label><%= Chouette::Company.human_attribute_name("objectid") %>: </label>
- <%= @company.objectid %>
- </p>
</div>
</div>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('companies.actions.new'), new_referential_company_path(@referential), :class => "add" %></li>
<li><%= link_to t('companies.actions.edit'), edit_referential_company_path(@referential, @company), :class => "edit" %></li>
<li><%= link_to t('companies.actions.destroy'), referential_company_path(@referential, @company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, :class => "remove" %></li>
<br>
diff --git a/app/views/compliance_check_results/index.html.erb b/app/views/compliance_check_results/index.html.erb
index 3a73f2146..3abd9cc65 100644
--- a/app/views/compliance_check_results/index.html.erb
+++ b/app/views/compliance_check_results/index.html.erb
@@ -17,7 +17,7 @@
<td><%= status_icon( compliance_check_result.status, compliance_check_result.severity ) %> </td>
<td><%= t compliance_check_result.severity, :scope => "compliance_check_result.severities" %></td>
<td>
- <%= image_tag "icons/notice.png", :"data-content" => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code), :"data-title" => t("activerecord.attributes.compliance_check_result.detail"), :class =>"notice" %>
+ <button data-content='<%= ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) %>' data-title='<%= t("activerecord.attributes.compliance_check_result.detail") %>' rel="popover" data-toggle="popover" class="notice btn btn-info btn-xs" ><i class="fa fa-info"></i></button>
<%= link_to compliance_check_result.rule_code, test_definition(compliance_check_result.rule_code), :title => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code), :target => "validation" %></td>
<% if @compliance_check_results && @compliance_check_results.first.status == "nok" %>
<td class="td_error">
@@ -29,9 +29,9 @@
<% compliance_check_result.detail["detail"].first(10).each do |error| %>
<p class="detail_error">
<% if error["messageArgs"] %>
- |- <%= image_tag "icons/notice.png", :"data-content" => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) + t("compliance_check_result.details." + error["messageKey"], error["messageArgs"].symbolize_keys ), :"data-title" => t("activerecord.attributes.compliance_check_result.detail"), :class =>"notice" %>
+ |- <button data-content='<%= ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) + t("compliance_check_result.details." + error["messageKey"], error["messageArgs"].symbolize_keys ) %>' data-title='<%= t("activerecord.attributes.compliance_check_result.detail") %>' data-toggle="popover" class="notice btn btn-info btn-xs"><i class="fa fa-info"></i></button>
<% else %>
- |- <%= image_tag "icons/notice.png", :"data-content" => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) + t("compliance_check_result.details." + error["messageKey"]), :"data-title" => t("activerecord.attributes.compliance_check_result.detail"), :class =>"notice" %>
+ |- <button data-content='<%= ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) + t("compliance_check_result.details." + error["messageKey"] ) %>' data-title='<%= t("activerecord.attributes.compliance_check_result.detail") %>' data-toggle="popover" class="notice btn btn-info btn-xs"><i class="fa fa-info"></i></button>
<% end %>
<% if error["location"]["url"].present? %>
<%= link_to error["objectId"], referential_path(@referential) + "/" + error["location"]["url"] %>
diff --git a/app/views/compliance_check_results/index.js.coffee b/app/views/compliance_check_results/index.js.coffee
index 203e2ca8e..10821a031 100644
--- a/app/views/compliance_check_results/index.js.coffee
+++ b/app/views/compliance_check_results/index.js.coffee
@@ -1,13 +1,5 @@
jQuery ->
- $(".notice").popover({ container: "body", trigger: "click", html: false, placement: "bottom" })
-
- $("body").click (e) ->
- $(".notice").each ->
- #the 'is' for buttons that trigger popups
- #the 'has' for icons within a button that triggers a popup
- if not $(this).is(e.target) and $(this).has(e.target).length is 0 and $(".popover").has(e.target).length is 0
- if( $(this).data('bs.popover').tip().hasClass('in') )
- $(this).popover('toggle')
+ $(".notice").popover({ container: "body", html: false, trigger: "focus", placement: "bottom" })
# Hide and show error details
$(".title_error").each ->
diff --git a/app/views/compliance_check_tasks/_compliance_check_task.erb b/app/views/compliance_check_tasks/_compliance_check_task.erb
deleted file mode 100644
index b3b62e1f5..000000000
--- a/app/views/compliance_check_tasks/_compliance_check_task.erb
+++ /dev/null
@@ -1,22 +0,0 @@
-<%= div_for(compliance_check_task, :class => "compliance_check_task clearfix") do %>
- <div class="icon">
- <%= link_to image_tag("compliance_check_task-#{compliance_check_task.status}.png"), referential_compliance_check_task_path(@referential, compliance_check_task) %>
- </div>
- <div class="resume">
- <ul class="header clearfix">
- <li class="title"><%= link_to(compliance_check_task.name, referential_compliance_check_task_path(@referential, compliance_check_task)) %></li>
- <li class="remove"><%= link_to "<i class='fa fa-trash-o'></i>".html_safe, referential_compliance_check_task_path(@referential, compliance_check_task), :method => :delete, :class => "delete", :data => {:confirm => t('compliance_check_tasks.actions.destroy_confirm')} %></li>
- </ul>
- <div class="links">
- <% if compliance_check_task.import_task.present? %>
- <p><%= link_to( image_tag('icons/link_page.png') + t("compliance_check_tasks.import_task"), referential_import_task_path(@referential, compliance_check_task.import_task)) %></p>
- <% end %>
- <% if compliance_check_task.parameter_set %>
- <p><%= link_to( image_tag('icons/link_page.png') + t("compliance_check_tasks.actions.rule_parameter_set"), rule_parameter_set_referential_compliance_check_task_path(@referential, compliance_check_task)) %></p>
- <% end %>
- </div>
- <div class="history">
- <%= l compliance_check_task.created_at, :format => "%d/%m/%Y %H:%M" %> | <%= compliance_check_task.user_name %>
- </div>
- </div>
-<% end %>
diff --git a/app/views/compliance_check_tasks/_compliance_check_task.html.erb b/app/views/compliance_check_tasks/_compliance_check_task.html.erb
new file mode 100644
index 000000000..ac652c470
--- /dev/null
+++ b/app/views/compliance_check_tasks/_compliance_check_task.html.erb
@@ -0,0 +1,34 @@
+<div id="index_item" class="panel panel-default">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to referential_compliance_check_task_path(@referential, compliance_check_task), :method => :delete, :data => {:confirm => t('compliance_check_tasks.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to( referential_compliance_check_task_path(@referential, compliance_check_task), :class => "preview", :title => "#{ComplianceCheckTask.model_name.human.capitalize} #{compliance_check_task.name}") do %>
+ <span class="name">
+ <%= truncate(compliance_check_task.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
+ <% if compliance_check_task.import_task.present? %>
+ <p><%= link_to( image_tag('icons/link_page.png') + t("compliance_check_tasks.import_task"), referential_import_task_path(@referential, compliance_check_task.import_task)) %></p>
+ <% end %>
+ <% if compliance_check_task.parameter_set %>
+ <p><%= link_to( image_tag('icons/link_page.png') + t("compliance_check_tasks.actions.rule_parameter_set"), rule_parameter_set_referential_compliance_check_task_path(@referential, compliance_check_task)) %></p>
+ <% end %>
+ </div>
+ <div class="panel-footer">
+ <div class="progress">
+ <div class="progress-bar <%= compliance_check_task.status %>" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"> <%= t("compliance_check_tasks.statuses.#{compliance_check_task.status}") %></div>
+ </div>
+ <div class="history">
+ <%= l compliance_check_task.created_at, :format => "%d/%m/%Y %H:%M" %> | <%= compliance_check_task.user_name %>
+ </div>
+ </div>
+</div>
diff --git a/app/views/compliance_check_tasks/_compliance_check_tasks.html.erb b/app/views/compliance_check_tasks/_compliance_check_tasks.html.erb
new file mode 100644
index 000000000..9cb805b90
--- /dev/null
+++ b/app/views/compliance_check_tasks/_compliance_check_tasks.html.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @compliance_check_tasks %>
+</div>
+<div class="compliance_check_tasks paginated_content">
+ <%= paginated_content @compliance_check_tasks %>
+</div>
+<div class="pagination">
+ <%= will_paginate @compliance_check_tasks, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/compliance_check_tasks/index.html.erb b/app/views/compliance_check_tasks/index.html.erb
index 8a659070c..fe05b3cdc 100644
--- a/app/views/compliance_check_tasks/index.html.erb
+++ b/app/views/compliance_check_tasks/index.html.erb
@@ -1,14 +1,7 @@
<%= title_tag t('.title') %>
<div class="warning"><%= t('.warning') %> </div>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @compliance_check_tasks %>
-</div>
-<div class="compliance_check_tasks paginated_content">
- <%= paginated_content @compliance_check_tasks %>
-</div>
-<div class="pagination">
- <%= will_paginate @compliance_check_tasks, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+
+<div id="compliance_check_tasks"><%= render 'compliance_check_tasks' %></div>
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/compliance_check_tasks/index.js.erb b/app/views/compliance_check_tasks/index.js.erb
new file mode 100644
index 000000000..08ddf1dc5
--- /dev/null
+++ b/app/views/compliance_check_tasks/index.js.erb
@@ -0,0 +1 @@
+$('#compliance_check_tasks').html('<%= escape_javascript(render("compliance_check_tasks")) %>'); \ No newline at end of file
diff --git a/app/views/compliance_check_tasks/show.js.coffee b/app/views/compliance_check_tasks/show.js.coffee
index 5a6073e23..ae9daa6d8 100644
--- a/app/views/compliance_check_tasks/show.js.coffee
+++ b/app/views/compliance_check_tasks/show.js.coffee
@@ -49,7 +49,4 @@ jQuery ->
$(".resume .col2 .caption").click ->
get_compliance_check_results( $(".report"), null, "warning")
- $('img[title]').tipsy({gravity: 'w'})
- $('a[title]').tipsy({gravity: 'w'})
-
diff --git a/app/views/connection_links/_connection_link.erb b/app/views/connection_links/_connection_link.erb
index 0cdcd6f34..7996eb0f3 100644
--- a/app/views/connection_links/_connection_link.erb
+++ b/app/views/connection_links/_connection_link.erb
@@ -1,7 +1,26 @@
-<%= div_for(connection_link) do %>
- <%= link_to truncate(connection_link.name, :length => 35), [@referential, connection_link], :title => "#{Chouette::TimeTable.model_name.human} #{connection_link.name}" %>
- <div class="info">
- <%= t('.from') %>
+<div id="index_item" class="panel panel-default connection_link">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_connection_link_path(@referential, connection_link), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_connection_link_path(@referential, connection_link), :method => :delete, :data => {:confirm => t('connection_links.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, connection_link], :class => "preview", :title => "#{Chouette::ConnectionLink.model_name.human.capitalize} #{connection_link.name}") do %>
+ <span class="name">
+ <%= truncate(connection_link.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
+ <p>
+ <%= t('.from') %>
<% if connection_link.departure.present? %>
<%= link_to_if connection_link.departure, truncate(connection_link.departure.name, :length => 15) , referential_stop_area_path(@referential, connection_link.departure), :title => "#{connection_link.human_attribute_name('departure')} #{connection_link.departure.name}" %>
<% else %>
@@ -12,12 +31,10 @@
<%= link_to_if( connection_link.arrival, truncate(connection_link.arrival.name, :length => 15), referential_stop_area_path(@referential, connection_link.arrival), :title => "#{connection_link.human_attribute_name('arrival')} #{connection_link.arrival.name}" ) %>
<% else %>
<%= connection_link.human_attribute_name("undefined") %>
- <% end %> -
+ <% end %>
+ </p>
+ <p>
<%= connection_link.human_attribute_name('default_duration').capitalize %>: <%= connection_link.default_duration ? connection_link.default_duration.strftime('%Mm %Ss') : connection_link.human_attribute_name("undefined") %>
-
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_connection_link_path(@referential, connection_link), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_connection_link_path(@referential, connection_link), :method => :delete, :data => {:confirm => t('connection_links.actions.destroy_confirm')}, :class => "remove" %>
- </div>
+ </p>
</div>
-<% end %>
+</div> \ No newline at end of file
diff --git a/app/views/connection_links/_connection_links.erb b/app/views/connection_links/_connection_links.erb
new file mode 100644
index 000000000..cfc1d45f4
--- /dev/null
+++ b/app/views/connection_links/_connection_links.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @connection_links %>
+</div>
+<div class="connection_links paginated_content">
+ <%= paginated_content(@connection_links) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @connection_links, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/connection_links/_form.erb b/app/views/connection_links/_form.erb
index 52f49d852..54ac7088e 100644
--- a/app/views/connection_links/_form.erb
+++ b/app/views/connection_links/_form.erb
@@ -9,13 +9,13 @@
<%= form.input :stairs_availability,:as => :boolean %>
<%= form.input :lift_availability,:as => :boolean %>
- <%= form.input :objectid, :required => !@connection_link.new_record? %>
+ <%= form.input :objectid, :required => !@connection_link.new_record?, :input_html => { :title => t("formtastic.titles.connection_link.objectid")} %>
<% end %>
<%= form.inputs :name => t('connection_links.show.durations') do %>
- <%= form.input :default_duration, :as => :time_select, :size => 8, :include_seconds=>true, :label => @connection_link.human_attribute_name("default_duration"), :input_html => { :placeholder => "HH:MM" } %>
- <%= form.input :frequent_traveller_duration, :as => :time_select, :size => 8, :include_seconds=>true, :label => @connection_link.human_attribute_name("frequent_traveller_duration"), :input_html => { :placeholder => "HH:MM:SS" } %>
- <%= form.input :occasional_traveller_duration, :as => :time_select, :size => 8, :include_seconds=>true, :label => @connection_link.human_attribute_name("occasional_traveller_duration"), :input_html => { :placeholder => "HH:MM:SS" } %>
- <%= form.input :mobility_restricted_traveller_duration, :as => :time_select, :include_seconds=>true, :label => @connection_link.human_attribute_name("mobility_restricted_traveller_duration"), :input_html => { :placeholder => "HH:MM:SS" } %>
+ <%= form.input :default_duration, :as => :extended_time_picker, :size => 8, :step => :seconds, :label => @connection_link.human_attribute_name("default_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :frequent_traveller_duration, :as => :extended_time_picker, :size => 8, :step => :seconds, :include_seconds => true, :label => @connection_link.human_attribute_name("frequent_traveller_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :occasional_traveller_duration, :as => :extended_time_picker, :size => 8, :include_seconds => true, :label => @connection_link.human_attribute_name("occasional_traveller_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
+ <%= form.input :mobility_restricted_traveller_duration, :as => :extended_time_picker,:size => 8, :include_seconds => true, :label => @connection_link.human_attribute_name("mobility_restricted_traveller_duration"), :input_html => { :class => "form-control input-sm timepicker_seconds", :step => 1}, :wrapper_html => { :class => "input-append bootstrap-timepicker" } %>
<% end %>
<%= form.actions do %>
diff --git a/app/views/connection_links/index.html.erb b/app/views/connection_links/index.html.erb
index 5f4ec09d4..151ce2d89 100644
--- a/app/views/connection_links/index.html.erb
+++ b/app/views/connection_links/index.html.erb
@@ -1,41 +1,22 @@
<%= title_tag t('connection_links.index.title') %>
-<%= search_form_for @q, :url => referential_connection_links_path(@referential), :html => {:method => :get} do |f| %>
- <%= f.label :name_cont, "#{t('.name')} :" %>
- <%= f.text_field :name_cont %>
-
-<!--
- <%= f.hidden_field :departure_id_eq %>
- <%= f.hidden_field :arrival_id_eq %>
--->
-
- <%= f.submit t('actions.search') %> <%= t("or") %>
- <%= link_to t("cancel"), referential_connection_links_path(@referential) %>
-<% end %>
-
-<!--
-<% if @q.departure_id_eq.present? %>
-<p>
- <%= Chouette::ConnectionLink.human_attribute_name('departure') %> : <%= @referential.stop_areas.find(@q.departure_id_eq).name %>
-</p>
-<% end %>
-
-<% if @q.arrival_id_eq.present? %>
-<p>
- <%= Chouette::ConnectionLink.human_attribute_name('arrival') %> : <%= @referential.stop_areas.find(@q.arrival_id_eq).name %>
-</p>
+<%= search_form_for @q, :url => referential_connection_links_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-12">
+ <%= f.text_field :name_cont, :placeholder => "#{t('.name')}", :class => "form-control" %>
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <!-- <a data-toggle="collapse" data-parent="#search" href="#advanced_search"> -->
+ <!-- <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %> -->
+ <!-- </a> -->
+ </div>
+</div>
<% end %>
--->
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @connection_links %>
-</div>
-<div class="connection_links paginated_content">
- <%= paginated_content(@connection_links) %>
-</div>
-<div class="pagination">
- <%= will_paginate @connection_links, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+<div id="connection_links"><%= render 'connection_links' %></div>
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/connection_links/index.js.erb b/app/views/connection_links/index.js.erb
new file mode 100644
index 000000000..c01f09b97
--- /dev/null
+++ b/app/views/connection_links/index.js.erb
@@ -0,0 +1 @@
+$('#connection_links').html('<%= escape_javascript(render("connection_links")) %>'); \ No newline at end of file
diff --git a/app/views/connection_links/select_areas.html.erb b/app/views/connection_links/select_areas.html.erb
index ac1a95dab..ee93d1d0d 100644
--- a/app/views/connection_links/select_areas.html.erb
+++ b/app/views/connection_links/select_areas.html.erb
@@ -3,8 +3,8 @@
<%= semantic_form_for [@referential, @connection_link] do |form| %>
<div>
<%= form.inputs do %>
- <%= form.input :departure_id, :as => :text, :input_html => { :"data-pre" => ( @departure.present? ? [ { :id => @departure.id.to_s, :name => "#{@departure.name} [#{@departure.country_code}]" } ]: [] ).to_json } %>
- <%= form.input :arrival_id, :as => :text, :input_html => { :"data-pre" => ( @arrival.present? ? [ { :id => @arrival.id.to_s, :name => "#{@arrival.name} [#{@arrival.country_code}]" } ]: [] ).to_json } %>
+ <%= form.input :departure_id, :as => :search_stop_area, :json => referential_connection_link_connection_link_areas_path(@referential, @connection_link, :format => :json), :tokenLimit => 1, :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :input_html => { :"data-pre" => Rabl::Renderer.new('stop_areas/show', [@departure].compact, :view_path => 'app/views', :format => :json).render } %>
+ <%= form.input :arrival_id, :as => :search_stop_area, :json => referential_connection_link_connection_link_areas_path(@referential, @connection_link, :format => :json), :tokenLimit => 1, :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :input_html => { :"data-pre" => Rabl::Renderer.new('stop_areas/show', [@arrival].compact, :view_path => 'app/views', :format => :json).render } %>
<% end %>
<%= form.actions do %>
@@ -13,34 +13,3 @@
<% end %>
</div>
<% end %>
-
-<script>
- $(function() {
- $( "#connection_link_departure_id" ).tokenInput('<%= referential_connection_link_connection_link_areas_path(@referential, @connection_link, :format => :json) %>', {
- crossDomain: false,
- prePopulate: $('#connection_link_departure_id').data('pre'),
- tokenLimit: 1,
- minChars: 3,
- hintText: '<%= t('search_hint') %>',
- noResultsText: '<%= t('no_result_text') %>',
- searchingText: '<%= t('searching_term') %>'
- });
- });
-
- $(function() {
- $( "#connection_link_arrival_id" ).tokenInput('<%= referential_connection_link_connection_link_areas_path(@referential, @connection_link, :format => :json) %>', {
- crossDomain: false,
- prePopulate: $('#connection_link_arrival_id').data('pre'),
- tokenLimit: 1,
- minChars: 3,
- hintText: '<%= t('search_hint') %>',
- noResultsText: '<%= t('no_result_text') %>',
- searchingText: '<%= t('searching_term') %>'
- });
- });
-</script>
-
-<% content_for :sidebar do %>
-<ul class="actions">
-</ul>
-<% end %>
diff --git a/app/views/connection_links/show.html.erb b/app/views/connection_links/show.html.erb
index a41112621..58649d245 100644
--- a/app/views/connection_links/show.html.erb
+++ b/app/views/connection_links/show.html.erb
@@ -21,10 +21,6 @@
<% end %>
</p>
<p>
- <label><%= @connection_link.human_attribute_name("name") %>: </label>
- <%= @connection_link.name %>
- </p>
- <p>
<label><%= @connection_link.human_attribute_name("connection_link_type") %>: </label>
<%= t("connection_link_types.label.#{@connection_link.connection_link_type}") %>
</p>
@@ -75,18 +71,15 @@
<label><%= @connection_link.human_attribute_name("lift_availability") %>: </label>
<%= t((@connection_link.lift_availability == true).to_s) %>
</p>
- <p>
- <label><%= @connection_link.human_attribute_name("objectid") %>: </label>
- <%= @connection_link.objectid %>
- </p>
</div>
</div>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('connection_links.actions.new'), new_referential_connection_link_path(@referential), :class => "add" %></li>
<li><%= link_to t('connection_links.actions.edit'), edit_referential_connection_link_path(@referential, @connection_link), :class => "edit" %></li>
<li><%= link_to t('connection_links.actions.destroy'), referential_connection_link_path(@referential, @connection_link), :method => :delete, :data => {:confirm => t('connection_links.actions.destroy_confirm')}, :class => "remove" %></li>
- <li><%= link_to t('connection_links.actions.select_areas'), select_areas_referential_connection_link_path(@referential, @connection_link), :class => "select_areas" %></li>
+ <li><%= link_to t('connection_links.actions.select_areas'), select_areas_referential_connection_link_path(@referential, @connection_link), :class => "select" %></li>
<br>
</ul>
<%= creation_tag(@connection_link) %>
diff --git a/app/views/devise/_links.erb b/app/views/devise/_links.erb
index 3381b2e8e..e2a1bf3ef 100644
--- a/app/views/devise/_links.erb
+++ b/app/views/devise/_links.erb
@@ -7,7 +7,7 @@
</li>
<li>
- <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
+ <%- if devise_mapping.registerable? && controller_name != 'registrations' && Rails.application.config.accept_user_creation %>
<%= link_to t(".sign_up"), new_registration_path(resource_name) %><br />
<% end -%>
</li>
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
index f285a0f6d..68fd8c22a 100644
--- a/app/views/devise/passwords/new.html.erb
+++ b/app/views/devise/passwords/new.html.erb
@@ -1,13 +1,13 @@
-<%= title_tag t('.title') %>
+<div class="panel panel-default">
+ <div class="panel-heading"><%= t('.title') %></div>
+ <div class="panel-body">
+ <%= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name)) do |form| %>
+ <%= form.input :email %>
-<%= semantic_form_for(resource, :as => resource_name, :url => password_path(resource_name)) do |form| %>
- <%= form.inputs :email %>
-
- <%= form.actions do %>
- <%= form.action :submit, :as => :button, :label => t('.commit') %>
- <%= form.action :cancel, :as => :link %>
- <% end %>
+ <%= link_to t("cancel"), root_path, :class => "btn btn-default" %>
+ <%= form.button :submit, :value => t("devise.passwords.new.commit") %>
+ <% end %>
+ </div>
+</div>
-<% end %>
-<%= render "links" %>
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
index f699ae6f9..9c780cba3 100644
--- a/app/views/devise/registrations/new.html.erb
+++ b/app/views/devise/registrations/new.html.erb
@@ -1,16 +1,26 @@
-<%= title_tag t('.title') %>
+<div id="registrations_new" class="col-lg-offset-4 col-lg-4">
-<%= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |form| %>
- <%= form.inputs do %>
- <%= form.input :email %>
- <%= form.input :password, :as => :password %>
- <%= form.input :password_confirmation, :as => :password %>
- <% end %>
+ <% if Rails.application.config.accept_user_creation %>
+ <div class="panel panel-default">
+ <div class="panel-heading"><%= t("devise.registrations.new.title") %></div>
+ <div class="panel-body">
+ <%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :wrapper => "form_without_label" ) do |form| %>
+ <%= form.simple_fields_for :organisation, Organisation.new do |organisation| %>
+ <%= organisation.input :name, :label => false, :placeholder => t("helpers.label.user.organisation_name"), input_html: { :class => "form-control" } %>
+ <% end %>
+ <% if resource.respond_to?( :name) %>
+ <%= form.input :name, :label => false, :placeholder => t("helpers.label.user.name"), input_html: { :class => "form-control" } %>
+ <% end %>
+ <%= form.input :email, :label => false, :placeholder => t("helpers.label.user.email"), input_html: { :class => "form-control" } %>
+ <%= form.input :password, :as => :password, :label => false, :placeholder => t("helpers.label.user.password"), input_html: { :class => "form-control" } %>
+ <%= form.input :password_confirmation, :as => :password, :label => false, :placeholder => t("helpers.label.user.password_confirmation"), input_html: { :class => "form-control" } %>
+
+ <%= form.button :submit, :class => "btn-primary" %>
+ <% end %>
+ </div>
+ </div>
+ <% end %>
+
+</div>
- <%= form.actions do %>
- <%= form.action :submit, :as => :button, :label => t('.commit') %>
- <%= form.action :cancel, :as => :link %>
- <% end %>
-<% end %>
-<%= render "links" %>
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
index a6c13df5d..dc06a3ea2 100644
--- a/app/views/devise/sessions/new.html.erb
+++ b/app/views/devise/sessions/new.html.erb
@@ -1,19 +1,65 @@
-<%= title_tag t('.title') %>
+<div id="sessions_new" class="row">
+ <div class="col-md-8 product_summary">
+ <h2>Bienvenue sur Chouette</h2>
+ <p>
+ Chouette est un logiciel Open Source de saisie, de visualisation et d'échange d'offre de transport public planifiée.
+ </p>
+ <p>
+ Ce logiciel est déployé en mode Saas et se veut ouvert :
+ </p>
+ <ul>
+ <li>- choix de plusieurs fonds cartographiques</li>
+ <li>- échange de données en différents normes (Neptune, ...) et standard (GTFS, ...)</li>
+ </ul>
+ </div>
+ <div class="col-md-4 login">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name), :wrapper => "form_without_label" ) do |form| %>
+ <%= form.input :email, :label => false, :placeholder => t("helpers.label.user.email"), input_html: { :class => "form-control" } %>
+ <div class="row">
+ <div class="col-md-6">
+ <%= form.input :password, :as => :password, :label => false, :placeholder => t("helpers.label.user.password"), input_html: { :class => "form-control" } %>
+ </div>
+ <div class="col-md-6">
+ <%= form.button :submit, t("devise.sessions.new.commit"), :class => "btn-primary" %>
+ </div>
+ </div>
+ <div class="row options">
+ <div class="col-md-6">
+ <% if devise_mapping.rememberable? %>
+ <%= form.input :remember_me, :as => :boolean, :label => false, :inline_label => t("helpers.label.user.remember_me") if devise_mapping.rememberable? %>
+ <% end %>
+ </div>
+ <div class="col-md-6 new_password">
+ <%= link_to t("devise.links.new_password"), new_password_path(resource_name) %>
+ </div>
+ </div>
+ <% end %>
+ </div>
+ </div>
-<%= semantic_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |form| %>
- <%= form.inputs do %>
- <%= form.input :email %>
- <%= form.input :password, :as => :password %>
-
- <% if devise_mapping.rememberable? -%>
- <%= form.input :remember_me, :as => :boolean %>
+ <% if Rails.application.config.accept_user_creation %>
+ <div class="panel panel-default">
+ <div class="panel-heading"><%= t("devise.registrations.new.title") %></div>
+ <div class="panel-body">
+ <%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :wrapper => "form_without_label" ) do |form| %>
+ <%= form.simple_fields_for :organisation, Organisation.new do |organisation| %>
+ <%= organisation.input :name, :label => false, :placeholder => t("helpers.label.user.organisation_name"), input_html: { :class => "form-control" } %>
+ <% end %>
+ <% if resource.respond_to?( :name) %>
+ <%= form.input :name, :label => false, :placeholder => t("helpers.label.user.name"), input_html: { :class => "form-control" } %>
+ <% end %>
+ <%= form.input :email, :label => false, :placeholder => t("helpers.label.user.email"), input_html: { :class => "form-control" } %>
+ <%= form.input :password, :as => :password, :label => false, :placeholder => t("helpers.label.user.password"), input_html: { :class => "form-control" } %>
+ <%= form.input :password_confirmation, :as => :password, :label => false, :placeholder => t("helpers.label.user.password_confirmation"), input_html: { :class => "form-control" } %>
+
+ <%= form.button :submit, t("devise.registrations.new.commit"), :class => "btn-info" %>
+ <% end %>
+ </div>
+ </div>
<% end %>
- <% end %>
-
-
- <%= form.actions do %>
- <%= form.action :submit, :as => :button, :label => t('.commit') %>
- <% end %>
-<% end %>
+
+ </div>
+</div>
-<%= render "links" %>
diff --git a/app/views/exports/_export.erb b/app/views/exports/_export.erb
index 3d312c266..a139e3171 100644
--- a/app/views/exports/_export.erb
+++ b/app/views/exports/_export.erb
@@ -1,21 +1,33 @@
-<%= div_for(export, :class => "export clearfix") do %>
- <div class="icon">
- <%= link_to image_tag("export-#{export.status}.png"), referential_export_path(@referential, export) %>
+<div id="index_item" class="panel panel-default">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to referential_export_path(@referential, export), :method => :delete, :data => {:confirm => t('exports.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to( referential_export_path(@referential, export), :class => "preview", :title => "#{Export.model_name.human.capitalize} #{export.name}") do %>
+ <span class="name">
+ <%= truncate(export.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
- <div class="resume">
- <ul class="header clearfix">
- <li class="title">
- <%= link_to(export.name, referential_export_path(@referential, export)) %>
- </li>
- <li class="remove"><%= link_to "<i class='fa fa-trash-o'></i>".html_safe, referential_export_path(@referential, export), :method => :delete, :data => {:confirm => t('exports.actions.destroy_confirm')}, :class => "remove" %></li>
- </ul>
- <div class="links">
- <% if export.status == 'completed' %>
- <%= link_to t("exports.actions.download"), referential_export_path(@referential, export, :format => :zip), :class => "download" %>
- <% end %>
- </div>
+ <div class="panel-body">
+ <p>
+ <% if export.status == 'completed' %>
+ <%= link_to image_tag("icons/file_zip.png") + t(".exported_file"), referential_export_path(@referential, export, :format => :zip), :class => "download" %>
+ <% else %>
+ &nbsp;
+ <% end %>
+ </p>
+ </div>
+ <div class="panel-footer">
+ <%= export_progress_bar_tag(export) %>
<div class="history">
- <%= l export.created_at, :format => "%d/%m/%Y %H:%M" %>
+ <%= l export.created_at, :format => "%d/%m/%Y %H:%M" %>
</div>
</div>
-<% end %>
+</div>
diff --git a/app/views/exports/_exports.html.erb b/app/views/exports/_exports.html.erb
new file mode 100644
index 000000000..9417cfed6
--- /dev/null
+++ b/app/views/exports/_exports.html.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @exports %>
+</div>
+<div class="exports paginated_content">
+ <%= paginated_content @exports, "export" %>
+</div>
+<div class="pagination">
+ <%= will_paginate @exports, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/exports/_fields_gtfs_export.erb b/app/views/exports/_fields_gtfs_export.erb
index 89d7bbf37..60ffd21c8 100644
--- a/app/views/exports/_fields_gtfs_export.erb
+++ b/app/views/exports/_fields_gtfs_export.erb
@@ -1 +1 @@
-<%= form.input :time_zone, :as => :time_zone %>
+<%= form.input :time_zone, :as => :time_zone, :input_html => { :title => t("formtastic.titles.export.time_zone")} %>
diff --git a/app/views/exports/_fields_hub_export.erb b/app/views/exports/_fields_hub_export.erb
new file mode 100644
index 000000000..fc7cf7112
--- /dev/null
+++ b/app/views/exports/_fields_hub_export.erb
@@ -0,0 +1,2 @@
+<%= form.input :start_date, :as => :date_picker, :input_html => { :title => t("formtastic.titles.export.start_date")} %>
+<%= form.input :end_date, :as => :date_picker, :input_html => { :title => t("formtastic.titles.export.end_date")} %>
diff --git a/app/views/exports/_fields_neptune_export.erb b/app/views/exports/_fields_neptune_export.erb
index 3ed863c20..d4debb6f2 100644
--- a/app/views/exports/_fields_neptune_export.erb
+++ b/app/views/exports/_fields_neptune_export.erb
@@ -1,2 +1,2 @@
- <%= form.input :start_date, :as => :date_picker %>
- <%= form.input :end_date, :as => :date_picker %>
+ <%= form.input :start_date, :as => :date_picker, :input_html => { :title => t("formtastic.titles.export.start_date")} %>
+ <%= form.input :end_date, :as => :date_picker, :input_html => { :title => t("formtastic.titles.export.end_date")} %>
diff --git a/app/views/exports/index.html.erb b/app/views/exports/index.html.erb
index 2f89b9458..35b19be62 100644
--- a/app/views/exports/index.html.erb
+++ b/app/views/exports/index.html.erb
@@ -1,22 +1,7 @@
<%= title_tag t('.title') %>
<div class="warning"><%= t('.warning') %> </div>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @exports %>
-</div>
-<div class="exports paginated_content">
- <% @exports.each_slice(3) do |row_exports| %>
- <div class="row">
- <% row_exports.each do |export| %>
- <div class="col-md-4">
- <%= render :partial => "export", locals: { export: export } %>
- </div>
- <% end %>
- </div>
- <% end %>
-</div>
-<div class="pagination">
- <%= will_paginate @exports, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+<div id="exports"><%= render 'exports' %></div>
+
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/exports/index.js.erb b/app/views/exports/index.js.erb
new file mode 100644
index 000000000..e9f06f09e
--- /dev/null
+++ b/app/views/exports/index.js.erb
@@ -0,0 +1 @@
+$('#exports').html('<%= escape_javascript(render("exports")) %>'); \ No newline at end of file
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/group_of_lines/_form.erb b/app/views/group_of_lines/_form.erb
index b92fa1ea1..a0ef4a4c4 100644
--- a/app/views/group_of_lines/_form.erb
+++ b/app/views/group_of_lines/_form.erb
@@ -2,11 +2,11 @@
<%= form.inputs do %>
<%= form.input :name %>
<%= form.input :comment %>
- <%= form.input :objectid, :required => !@group_of_line.new_record? %>
+ <%= form.input :objectid, :required => !@group_of_line.new_record?, :input_html => { :title => t("formtastic.titles.group_of_line.objectid")} %>
<% end %>
<%= form.inputs do %>
- <%= form.input :line_tokens, :label => t('.lines'), :as => :text, :input_html => { :"data-pre" => ( @group_of_line.lines.map { |line| { :id => line.id, :name => line.published_name } } ).to_json } %>
+ <%= form.input :line_tokens, :label => t('.lines'), :as => :text, :input_html => { :"data-pre" => ( @group_of_line.lines.map { |line| { :id => line.id, :name => line.name } } ).to_json } %>
<% end %>
<%= form.actions do %>
diff --git a/app/views/group_of_lines/_group_of_line.erb b/app/views/group_of_lines/_group_of_line.erb
index a1933744a..d3a254ba9 100644
--- a/app/views/group_of_lines/_group_of_line.erb
+++ b/app/views/group_of_lines/_group_of_line.erb
@@ -1,12 +1,24 @@
-<%= div_for(group_of_line) do %>
- <%= link_to group_of_line.name, [@referential, group_of_line] %>
- <div class="info">
- <%= group_of_line.human_attribute_name('line_count') %>:<%= group_of_line.lines.count %>
- <% if @line.nil? %>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_group_of_line_path(@referential, group_of_line), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_group_of_line_path(@referential, group_of_line), :method => :delete, :data => {:confirm => t('group_of_lines.actions.destroy_confirm')}, :class => "remove" %>
- </div>
- <% end %>
+<div id="index_item" class="panel panel-default">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_group_of_line_path(@referential, group_of_line), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to('<span class="fa fa-trash-o"></span>'.html_safe, referential_group_of_line_path(@referential, group_of_line), :method => :delete, :data => {:confirm => t('group_of_lines.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm") if delete %>
+ </span>
+ <h5>
+ <%= link_to([@referential, group_of_line], :class => "preview", :title => "#{Chouette::GroupOfLine.model_name.human.capitalize} #{group_of_line.name}") do %>
+ <span class="name">
+ <%= truncate(group_of_line.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
-<% end %>
+ <div class="panel-body">
+ <p>
+ <%= group_of_line.human_attribute_name('line_count') %> <%= group_of_line.lines.count %>
+ </p>
+ </div>
+</div>
diff --git a/app/views/group_of_lines/_group_of_lines.erb b/app/views/group_of_lines/_group_of_lines.erb
new file mode 100644
index 000000000..212507d01
--- /dev/null
+++ b/app/views/group_of_lines/_group_of_lines.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @group_of_lines %>
+</div>
+<div class="group_of_lines paginated_content">
+ <%= paginated_content(@group_of_lines) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @group_of_lines, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/group_of_lines/_lines_detail.html.erb b/app/views/group_of_lines/_lines_detail.html.erb
index 4d4058540..210ecd4b5 100644
--- a/app/views/group_of_lines/_lines_detail.html.erb
+++ b/app/views/group_of_lines/_lines_detail.html.erb
@@ -1,10 +1,3 @@
- <div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.list") %></span> <%= page_entries_info @lines %>
- </div>
- <div class="lines paginated_content">
- <%= render :partial => "lines/line", :collection => @lines %>
- </div>
- <div class="pagination">
- <%= will_paginate @lines, :container => false %>
- </div>
-
+<div class="lines paginated_content">
+ <%= paginated_content @lines, "lines/line" %>
+</div>
diff --git a/app/views/group_of_lines/index.html.erb b/app/views/group_of_lines/index.html.erb
index 25bf782a2..2257096bd 100644
--- a/app/views/group_of_lines/index.html.erb
+++ b/app/views/group_of_lines/index.html.erb
@@ -1,22 +1,22 @@
<%= title_tag t('group_of_lines.index.title') %>
-<%= search_form_for @q, :url => referential_group_of_lines_path(@referential), :html => {:method => :get} do |f| %>
- <%= f.label :name_cont, "#{t('.name')} :" %>
- <%= f.text_field :name_cont %>
-
- <%= f.submit t('actions.search') %> <%= t("or") %>
- <%= link_to t("cancel"), referential_group_of_lines_path(@referential) %>
+<%= search_form_for @q, :url => referential_group_of_lines_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-12">
+ <%= f.text_field :name_cont, :placeholder => "#{t('.name')}", :class => "form-control" %>
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <!-- <a data-toggle="collapse" data-parent="#search" href="#advanced_search"> -->
+ <!-- <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %> -->
+ <!-- </a> -->
+ </div>
+</div>
<% end %>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @group_of_lines %>
-</div>
-<div class="group_of_lines paginated_content">
- <%= paginated_content(@group_of_lines) %>
-</div>
-<div class="pagination">
- <%= will_paginate @group_of_lines, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+<div id="group_of_lines"><%= render 'group_of_lines' %></div>
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/group_of_lines/index.js.erb b/app/views/group_of_lines/index.js.erb
new file mode 100644
index 000000000..fe3e96b5e
--- /dev/null
+++ b/app/views/group_of_lines/index.js.erb
@@ -0,0 +1 @@
+$('#group_of_lines').html('<%= escape_javascript(render("group_of_lines")) %>'); \ No newline at end of file
diff --git a/app/views/group_of_lines/show.html.erb b/app/views/group_of_lines/show.html.erb
index 5e77bfe78..07527f209 100644
--- a/app/views/group_of_lines/show.html.erb
+++ b/app/views/group_of_lines/show.html.erb
@@ -4,33 +4,21 @@
<%= @map.to_html %>
<div class="summary">
<p>
- <label><%= @group_of_line.human_attribute_name("name") %>: </label>
- <%= @group_of_line.name %>
- </p>
- <p>
<label><%= @group_of_line.human_attribute_name("comment") %>: </label>
<%= @group_of_line.comment %>
</p>
- <p>
- <label><%= @group_of_line.human_attribute_name("objectid") %>: </label>
- <%= @group_of_line.objectid %>
- </p>
</div>
<p class="after_map" />
- <h3 class="group_of_line_lines">
- <a class="lines"><%= t('.lines') %>
- <%= image_tag("icons/plus.png" , :class => "switcher") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" , :style => "display: none;") %>
- </a>
- </h3>
- <div class="lines_detail" style="display: none;">
- <%= render :partial => "lines_detail" %>
+ <h3 class="group_of_line_lines"><%= t('.lines') %></h3>
+ <div class="lines_detail">
+ <%= render :partial => "lines_detail" %>
</div>
</div>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('group_of_lines.actions.new'), new_referential_group_of_line_path(@referential), :class => "add" %></li>
<li><%= link_to t('group_of_lines.actions.edit'), edit_referential_group_of_line_path(@referential, @group_of_line), :class => "edit" %></li>
<li><%= link_to t('group_of_lines.actions.destroy'), referential_group_of_line_path(@referential, @group_of_line), :method => :delete, :data => {:confirm => t('group_of_lines.actions.destroy_confirm')} , :class => "remove" %></li>
<br>
diff --git a/app/views/group_of_lines/show.kml.erb b/app/views/group_of_lines/show.kml.erb
index 6b1a34688..6952db240 100644
--- a/app/views/group_of_lines/show.kml.erb
+++ b/app/views/group_of_lines/show.kml.erb
@@ -5,6 +5,7 @@
<Placemark id="<%= stop_area.id %>" >
<name><%= stop_area.name %></name>
<stop_area_type><%= stop_area.area_type.underscore %></stop_area_type>
+ <stop_area_type_label><%= t("area_types.label.#{stop_area.stop_area_type}") %></stop_area_type_label>
<%= (stop_area.position or stop_area.default_position).kml_representation.html_safe %>
</Placemark>
<% end %>
diff --git a/app/views/help/access_links.textile b/app/views/help/access_links.textile
deleted file mode 100644
index 1ae69e050..000000000
--- a/app/views/help/access_links.textile
+++ /dev/null
@@ -1,69 +0,0 @@
----
-layout: default
-title: Liens entre arrêts et accès
----
-
-* "Définition":#def
-* "Attributs":#attr
-* "Mode opératoire":#ope
-
-h3(#def). Définition
-
-Un *lien arrêt-accès* est, dans un voyage en transports en commun, le cheminement piéton permettant dans une infrastructure lourde de passer de la voirie à l'arrêt physique (point d'embarquement ou quai) et vice versa.
-
-Le lien permet de définir les caractéristiques du parcours entre un arrêt physique et un accès
-Cette liaison n'existe qu'au sein d'une zone d'arrêts (arrêt commercial ou pôle d'échange)
-Si la liaison est générique sur la zone, elle s'applique à tous les arrêts (selon le sens) qui n'ont pas un lien spécifique
-
-La liaison est orientée, il est donc nécessaire dans le cas où l'accès est bi-directionnel de définir 2 liens, un pour chaque sens
-
-h3(#attr). Attributs
-
-- Accès := nom de l'accès
-- Arrêt := nom de l'arrêt
-- Nom := nom du lien ( par défaut, chouette propose de le nommer _nom de la source -> nom de la cible_)
-- Type := liste de choix parmi << Aérien >>, << Souterrain>> ou mixte << Aérien et souterrain >>
-- Commentaire := zone de texte libre
-- Distance := distance en mètres
-- Durée moyenne := champ de type horaire hh:mm
-- Durée pour un voyageur à mobilité réduite := champ de type horaire hh:mm
-- Durée pour un voyageur occasionnel := champ de type horaire hh:mm
-- Durée pour un habitué := champ de type horaire hh:mm
-- Ascenseur := indicateur (Oui ou Non)
-- Accès pour personne à mobilité réduite := indicateur (Oui ou Non)
-- Escalator disponible := indicateur (Oui ou Non)
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la correspondance pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = AccessLink : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3(#ope). Mode opératoire
-
-h4. Création/consultation
-
-Lors de la consultation d'une zone d'arrêts possédant au moins un accès,
-l'action <<Gérer les liens arrêt-accès>> affiche deux matrices :
-
-* _Liens génériques_ : les différentes combinaisons de liens entre les accès et la zone;
-* _Liens détaillés_ : les différentes combinaisons de liens entre les accès et les arrêts inclus dans la zone.
-
-Chaque lien est représenté par une flèche orientée représentant l'existence ou non de ce lien:
-
-* !gray_left_arrow.png! ou !gray_right_arrow.png! lien non défini; la flèche est un lien vers l'écran de création de ce lien
-* !green_left_arrow.png! ou !green_right_arrow.png! lien existant; la flèche est un lien vers l'écran de consultation/modification/suppression de ce lien
-* !disabled_left_arrow.png! ou !disabled_right_arrow.png! lien interdit; la flèche est inopérante dans le sens qui contredirait le type d'accès (entrée ou sortie seule)
-
-Lors de la consultation d'un accès, les liens arrêt-accès de cet accès sont affichés selon la même présentation
diff --git a/app/views/help/access_points.textile b/app/views/help/access_points.textile
deleted file mode 100644
index f8d38f085..000000000
--- a/app/views/help/access_points.textile
+++ /dev/null
@@ -1,76 +0,0 @@
----
-layout: default
-title: Accès
----
-
-* "Définition":#def
-* "Attributs":#attr
-* "Mode opératoire":#ope
-
-h3(#def). Définition
-
-Un *accès* est un élément d'infrastructure donnant sur la voirie et permettant d'accéder à un ou plusieurs arrêts physiques (point d'embarquement ou quai) non accessibles directement.
-
-Dans Chouette, les accès sont rattachés à une zone d'arrêt (arrêt commercial ou pôle d'échange) et peuvent être reliés par des liens arrêt-accès :
-
-* sous forme générique à la zone; ce qui donnera des valeurs par défaut pour tous les arrêts de celle-ci
-* sous forme spécifique à tout ou partie des arrêts physiques de cette zone, pour ceux qui nécessitent des précisions par rapport au cas général.
-
-h3(#attr). Attributs
-
-- Zone d'arrêt := nom de la zone d'arrêt contenant l'accès
-- Nom := nom de l'accès
-- Commentaire := zone de texte libre
-- Nom de la rue := nom de la rue de l'accès
-- Code INSEE := code INSEE de la commune de l'accès
-- Type d'accès := sens de circulation de l'accès
-
-* !access_in.png! entrée
-* !access_out.png! sortie
-* !access_in_out.png! entrée-sortie
-
-- Horaire d'ouverture := horaire d'ouverture de l'accès (hh:mm)
-- Horaire de fermeture := horaire d'ouverture de l'accès (hh:mm)
-- Ascenseur := indicateur (Oui ou Non)
-- Accès pour personne à mobilité réduite := indicateur (Oui ou Non)
-- Escalator disponible := indicateur (Oui ou Non)
-
-p(attr_data). Données géographiques :
-
-- Position X := coordonnée horizontale de l'accès dans le référentiel de projection de l'espace de données
-- Position Y := coordonnée verticale de l'accès dans le référentiel de projection de l'espace de données
-- Longitude := longitude de l'accès dans le référentiel WGS84
-- latitude := latitude de l'accès dans le référentiel WGS84
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la ligne pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = AccessPoint : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3(#ope). Mode opératoire
-
-h4. Création
-
-la création est accessible dans l'écran de consultation d'une zone d'arrêt;
-lors de la création, la carte n'est pas disponible; pour localiser un accès sur la carte, il faut le créer puis le modifier.
-en modification, si l'accès n'a pas été positionné, il est proposé à l'emplacement de la zone d'arrêt associée ou par défaut au centre géographique de l'emprise de l'espace de données.
-
-h4. Déplacement sur la carte
-
-* activer le déplacement en cliquant sur l'accès -> le curseur prend la forme d'une quadruple flèche
-* appuyer sur le bouton gauche de la souris et maintenir appuyer lors du déplacement -> l'accès suit la souris
-* relâcher le bouton -> l'accès a une nouvelle position fixe
-* cliquer sur la carte -> sortie du mode déplacement; les coordonnées sont actualisées dans le formulaire
-
diff --git a/app/views/help/access_points_links.textile b/app/views/help/access_points_links.textile
new file mode 100644
index 000000000..1bf479c36
--- /dev/null
+++ b/app/views/help/access_points_links.textile
@@ -0,0 +1,88 @@
+---
+layout: default
+title: Gestion des accès et liens associés
+---
+
+Au sein d'un arrêt commercial ou d'un pôle d'échange, il est possible de décrire en détail des accès à ces lieux.
+
+Des liens _"ajouter un accès"_ et _"gérer les liens arrêt-accès"_ sont accessibles dans le menu latéral à droite de l'écran.
+
+h3. Créer un accès
+
+Depuis la page d'un arrêt auquel l'accès se rapporte, cliquer sur _"ajouter un accès"_. Un formulaire de création permet de décrire l'accès.
+
+!2014-10-30_181251.png! Création d'un accès
+
+Le champ de localisation par coordonnées est disponible dès la création et permet de localiser un accès avec des données chiffrées. A noter que les données doivent être saisies dans un champ unique, séparée par une virgule. Cette configuration permet de faire des copier coller directs depuis googlemaps notamment.
+
+La carte n'est pas disponible au moment de la création. Elle apparaît lors de la modification. Il faut donc créer un accès puis le modifier si l'on souhaite localiser l'accès sur la cartographie plutôt que par les coordonnées.
+
+Si l'accès n'a pas été positionné, il est positionné par défaut à l'emplacement de la zone d'arrêt associée ou par défaut au centre géographique de l'emprise de l'espace de données.
+
+h4. Attributs de l'accès
+
+* Zone d'arrêt : nom de la zone d'arrêt contenant l'accès
+* Nom : nom de l'accès
+* Commentaire : zone de texte libre
+* Nom de la rue : nom de la rue de l'accès
+* Code INSEE : code INSEE de la commune de l'accès
+* Type d'accès : sens de circulation de l'accès
+** !access_in.png! entrée
+** !access_out.png! sortie
+** !access_in_out.png! entrée-sortie
+* Horaire d'ouverture : horaire d'ouverture de l'accès (hh:mm)
+* Horaire de fermeture : horaire d'ouverture de l'accès (hh:mm)
+* Ascenseur : indicateur (Oui ou Non)
+* Accès pour personne à mobilité réduite : indicateur (Oui ou Non)
+* Escalator disponible : indicateur (Oui ou Non)
+
+h4. Données géographiques :
+
+* Position X : coordonnée horizontale de l'accès dans le référentiel de projection de l'espace de données
+* Position Y : coordonnée verticale de l'accès dans le référentiel de projection de l'espace de données
+* Longitude : longitude de l'accès dans le référentiel WGS84
+* latitude : latitude de l'accès dans le référentiel WGS84
+
+h3. Modifier un accès
+
+Cliquer sur le pictogramme de modification de l'accès ou sur _"Modifier l'accès"_ dans le menu de droite permet d'afficher en modification le formulaire de création. La cartographie apparaît et il est possible d'y déplacer l'accès.
+
+h3. Consulter les accès existants
+
+Les accès existants sont listés en bas de la page de l'arrêt sous forme d'éléments de liste. Cliquer sur le nom de l'accès ou sur le lien _"Gérer les liens arrêt-accès"_ affiche la vue détaillée de l'accès qui permet notamment son paramétrage complet.
+
+Les liens entre l'accès et l'arrêt global est présenté en premier, suivi d'une liste entre l'accès et les arrêts fils. Chacune de ses relations est figurée par une double flèche qui permet de savoir si les accès sont valables et si oui, dans quel sens exactement.
+
+!2014-10-30_181326.png! Liste des accès d'un arrêt, située en bas de la page de l'arrêt
+
+h3. Paramétrer les accès
+
+Cliquer sur l'une des flèches affiche le formulaire de paramétrage détaillé de l'accès pour le sens de circulation correspondant à la flèche.
+
+!2014-10-30_181422.png! Définition des sens d'accès
+
+h4. Attributs du lien Accès / Arrêt
+
+* Nom : Le nom est généré automatiquement à partir du nom de l'accès et de l'arrêt. Il est descriptif du lien mais peut être modifié.
+* Type : Il n'est pas possible de modifier un type une fois qu'il a été défini. Le type est une liste à choix fermés :
+** Souterrain
+** Mixte
+** Aérien
+* Commentaire : zone de texte libre
+* Distance : la distance de l'accès en mètres
+* Accès pour voyageurs à mobilité réduite : indicateur (oui ou non)
+* Présence d'un escalator : indicateur (oui ou non)
+* Présence d'un ascenseur : indicateur (oui ou non)
+
+h4. Attributs de durées
+
+Ces attributs permettent de définir le temps qu'il faut pour emprunter l'accès (en heures/minutes/secondes). Les champs sont :
+
+* moyenne : le temps moyen tous cas confondus
+* pour un habitué : le temps moyen pour un voyageur régulier connaissant les lieux
+* pour un voyageur occasionnel : le temps moyen pour un voyageur régulier ne connaissant pas les lieux
+* pour un voyageur à mobilité réduite : le temps moyen pour un voyageur à mobilité réduite
+
+h3. Supprimer un accès
+
+Un accès peut-être supprimé en cliquant sur le pictogramme de suppression dans la liste des accès d'un arrêt ou bien en cliquant sur _"Supprimer cet accès"_ dans le menu latéral de droite dans la page de l'accès à supprimer.
diff --git a/app/views/help/browser.textile b/app/views/help/browser.textile
new file mode 100644
index 000000000..8796c25cb
--- /dev/null
+++ b/app/views/help/browser.textile
@@ -0,0 +1,17 @@
+---
+layout: default
+title: Navigateur
+---
+
+h3. Navigateur prérequis
+
+L’utilisation de l’application nécessite de disposer d’un navigateur ayant les caractéristiques suivantes :
+
+* Internet Explorer (Version 8 et +)
+* Mozilla FireFox (Version 12 et +)
+* Chrome (Version 8 et +)
+
+h3. Paramétrage du navigateur
+Le navigateur doit autoriser l’exécution de Javascript.
+
+L'application s'affiche de façon lisible sur toutes les tailles d'écran, même si le confort d'utilisation est supérieur avec un poste de travail ayant une résolution d'au moins 1280x1024. \ No newline at end of file
diff --git a/app/views/help/companies.textile b/app/views/help/companies.textile
index e991ae67c..26fcc1882 100644
--- a/app/views/help/companies.textile
+++ b/app/views/help/companies.textile
@@ -1,46 +1,51 @@
----
-layout: default
-title: Transporteurs
----
-
-h3. Définition
-
-Dans la réalité, le *transporteur* est l'entité en charge de l'exploitation d'une ou plusieurs lignes de transport.
-Ce principe se retrouve dans le logiciel CHOUETTE.
-
-* Il s'agit de l'exploitant de la ligne; chaque ligne est rattachée à un seul transporteur, un transporteur pouvant évidemment gérer plusieurs lignes.
-* Chaque transporteur dispose d'un identifiant fonctionnel (<< numéro d'enregistrement >>) qui est utilisé dans les échanges XML pour identifier le transporteur et le mettre à jour. Cet identifiant est unique pour toute la base CHOUETTE, quel que soit le réseau ; il est donc important que le gestionnaire de la base CHOUETTE le renseigne d'une manière bien définie et pérenne.
-
-h3. Attributs
-
-- Nom := nom du transporteur
-- Nom court := nom abrégé du transporteur
-- Nom d'unité := nom de l'unité de gestion dans la société de transport
-- Nom du département := nom du département dans la société de transport
-- Code postal := code postal de l'adresse de la société de transport
-- Numéro de téléphone := Numéro de téléphone de l'unité de gestion
-- Numéro de fax := Numéro de fax de l'unité de gestion
-- Email := adresse électronique de l'unité de gestion de l'unité de gestion
-- Numéro d'enregistrement := code référençant un transporteur au sein d'une autorité supérieure
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant le transporteur pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = Company : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Transporteurs
+---
+
+h3. Définition
+
+Dans la réalité, le _"transporteur"_ est l'entité en charge de l'exploitation d'une ou plusieurs lignes de transport.
+Ce principe se retrouve dans le logiciel CHOUETTE.
+
+* Il s'agit de l'exploitant de la ligne; chaque ligne est rattachée à un seul transporteur, un transporteur pouvant évidemment gérer plusieurs lignes.
+* Chaque transporteur dispose d'un identifiant fonctionnel, une sorte de _"numéro d'enregistrement"_, qui est utilisé dans les échanges XML pour l'identifier et le mettre à jour. Cet identifiant est unique pour toute la base CHOUETTE, quel que soit le réseau ; il est donc important que le gestionnaire de la base CHOUETTE le renseigne d'une manière bien définie et pérenne sans quoi des erreurs risquent fort de survenir lors de l'export des données vers des systèmes tiers les exploitants..
+
+h4. Liste des transporteurs
+
+Sélectionner _"Transporteurs"_ dans le menu _"Données"_ affiche la liste des Transporteurs existants dans l'espace de données.
+
+!2014-10-30_175216.png! Liste des transporteurs
+
+h4. Ajouter un transporteur
+
+Depuis la liste des transporteurs, cliquer sur _"Ajouter un transporteur"_ dans la partie droite de l'écran. Il est également possible de créer un nouveau transporteur depuis la page de n'importe quel transporteur.
+
+Un formulaire s'affiche. Les champs obligatoires sont signalés par des astérisques.
+
+h4. Afficher un transporteur existant
+
+Pour afficher un transporteur existant il suffit de cliquer sur le nom du transporteur depuis la liste des transporteurs existants.
+
+h4. Modifier un transporteur
+
+On peut modifier un transporteur en cliquant sur le bouton de modification directement depuis la liste des transporteurs ou depuis la page d'un transporteur particulier.
+
+h4. Supprimer un transporteur
+
+On peut modifier un transporteur en cliquant sur le bouton de modification directement depuis la liste des transporteurs ou depuis la page d'un transporteur particulier. A noter que les éléments rattachés à ce transporteur (lignes notamment) ne seront pas supprimés. Il sera toujours possible de les rattacher à un autre transporteur par la suite en les modifiant.
+
+h3. Attributs d'un transporteur
+
+* Nom : nom du transporteur
+* Nom court : nom abrégé du transporteur
+* Nom d'unité : nom de l'unité de gestion dans la société de transport
+* Nom du département : nom du département dans la société de transport
+* Code postal : code postal de l'adresse de la société de transport
+* Numéro de téléphone : Numéro de téléphone de l'unité de gestion
+* Numéro de fax : Numéro de fax de l'unité de gestion
+* Email : adresse électronique de l'unité de gestion de l'unité de gestion
+* Numéro d'enregistrement : code référençant un transporteur au sein d'une autorité supérieure
+
+
+
diff --git a/app/views/help/connection.textile b/app/views/help/connection.textile
new file mode 100644
index 000000000..85398329f
--- /dev/null
+++ b/app/views/help/connection.textile
@@ -0,0 +1,28 @@
+---
+layout: default
+title: Accès
+---
+
+h3. Adresse d'accès
+
+L’utilisateur peut utiliser l’application CHOUETTE depuis le site www.chouette.mobi (recommandé) ou bien procéder à l’installation du logiciel directement sur son environnement personnel, en tant que serveur ou machine virtuelle. CHOUETTE est également disponible sans la web application, en ligne de commande (documentation séparée).
+
+CHOUETTE est une application web, elle peut donc être utilisée depuis n'importe quel poste relié à Internet.
+
+h3. Utilisateurs et organisations
+
+Lorsqu’un utilisateur s’enregistre dans l’application, il crée alors une organisation qui lui appartient.
+
+Il peut ensuite inviter des personnes à y accéder en créant leur compte dans l’onglet Organisation.
+
+!2014-10-30_173033.png! Accès au menu organisation
+
+Un utilisateur ne peut pas appartenir à plusieurs organisations.
+
+h3. Identification
+
+L'accès à CHOUETTE se fait par une identification par identifiant / mot de passe.
+
+Une fois identifié, l’utilisateur accède à un écran organisé autour des données à gérer. Chacune d'entre-elle se présente sous la forme d'un espace de données. A l'intérieur de chaque espace de données, des menus permettent de gérer (créer, modifier, supprimer) chaque type de données.
+
+L’application est disponible également en version anglaise et comprend le glossaire du présent manuel en ligne.
diff --git a/app/views/help/connection_links.textile b/app/views/help/connection_links.textile
index a4865465f..a23f23867 100644
--- a/app/views/help/connection_links.textile
+++ b/app/views/help/connection_links.textile
@@ -1,48 +1,53 @@
----
-layout: default
-title: Correspondances
----
-
-h3. Définition
-
-Une *correspondance* ou un changement est, dans un voyage en transports en commun, une étape nécessitant de changer de ligne. Le changement peut se faire soit au sein du même réseau, soit de manière intermodale, c'est-à-dire en changeant également de mode de transport.
-La correspondance permet d'établir une liaison entre un arrêt physique (ou une zone d'arrêt de type << arrêt commercial >> ou de type << pôle d'échange >>) et un autre arrêt physique (ou une autre zone d'arrêt de type << arrêt commercial >> ou de type << pôle d'échange >>).
-Cette liaison définit aussi une durée de parcours entre les arrêts (ou zones) reliés.
-
-h3. Attributs
-
-- Nom := nom de la correspondances
-- Commentaire := zone de texte libre
-- Distance := distance en mètres
-- Type := liste de choix parmi << Aérien >>, << Souterrain>> ou mixte << Aérien et souterrain >>
-- Départ := arrêt de départ de la correspondance
-- Arrivée := arrêt d'arrivée de la correspondance
-- Durée moyenne := champ de type horaire hh:mm
-- Durée pour un voyageur à mobilité réduite := champ de type horaire hh:mm
-- Durée pour un voyageur occasionnel := champ de type horaire hh:mm
-- Durée pour un habitué := champ de type horaire hh:mm
-- Ascenseur := indicateur (Oui ou Non)
-- Accès pour personne à mobilité réduite := indicateur (Oui ou Non)
-- Escalator disponible := indicateur (Oui ou Non)
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la correspondance pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = ConnectionLink : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Correspondances
+---
+
+h3. Définition
+
+Une *correspondance* ou un changement est, dans un voyage en transports en commun, une étape nécessitant de changer de ligne. Le changement peut se faire soit au sein du même réseau, soit de manière intermodale, c'est-à-dire en changeant également de mode de transport.
+
+La correspondance permet d'établir une liaison entre un arrêt physique (ou une zone d'arrêt de type << arrêt commercial >> ou de type << pôle d'échange >>) et un autre arrêt physique (ou une autre zone d'arrêt de type << arrêt commercial >> ou de type << pôle d'échange >>). Elle permet notamment de préciser la distance et le temps de parcours de la correspondance.
+
+!2014-10-31_115014.png! Correspondance entre deux arrêts
+
+h3. Créer une correspondance
+
+La page des correspondance est accessible depuis le menu _"Données"_. Elle présente la liste des correspondances avec un champ de recherche par le nom. Dans le menu latéral, cliquer sur _"Ajouter une correspondance"_ permet d'afficher le formulaire de création d'une nouvelle correspondance.
+
+Seul le nom de la correspondance est obligatoire.
+
+Il est également possible de créer une nouvelle correspondance depuis la page de n'importe quelle correspondance existante. Il s'agira bien d'une nouvelle correspondance telle qu'elel pourrait être créée depuis la page des correspondances. Elle n'a aucun rapport avec la correspondance depuis laquelle elle a été créee.
+
+Une fois le formulaire enregistré, la page de la correspondance permet de définir les arrêts reliés par celle-ci. Les correspondances sont définies entre deux arrêts uniquement. Ils doivent être sélectionnés parmi les arrêts existants en base. La saisie d'éléments correspondant au nom de l'arrêt fera remonter des propositions correspondantes par l'auto-complétion.
+
+h3. Modifier une correspondance
+
+La modification d'une correspondance peut se faire soit depuis un élément de la liste des correspondances en cliquant sur le pictogramme de modification, soit par la page de la correspondance en cliquant sur _"Modifier cette correspondance"_.
+
+La modification de la correspondance permet de modifier le formulaire décrivant la correspondance.
+
+La modification des arrêts de départ et d'arrivée se fait uniquement depuis la page de la correspondance en cliquant sur _"Modifier les départs/arrivées"_. Une petite croix dans le coin de chaque arrêt en correspondance permet de les supprimer pour en re-paramétrer d'autres à la place.
+
+h3. Supprimer une correspondance
+
+La suppression d'une correspondance peut se faire soit depuis un élément de la liste des correspondances en cliquant sur le pictogramme de suppression, soit par la page de la correspondance en cliquant sur _"Supprimer cette correspondance"_. La suppression de la correspondance supprime également les départs/arrivées paramétrés.
+
+Il est possible de ne supprimer que les départs/arrivées en cliquant sur _"Modifier les départs/arrivées"_. Une petite croix dans le coin de chaque arrêt en correspondance permet de les supprimer.
+
+h3. Attributs
+
+* Nom : nom de la correspondances
+* Commentaire : zone de texte libre
+* Distance : distance en mètres
+* Type : liste de choix parmi << Aérien >>, << Souterrain>> ou mixte << Aérien et souterrain >>
+* Départ : arrêt de départ de la correspondance
+* Arrivée : arrêt d'arrivée de la correspondance
+* Durée moyenne : champ de type horaire hh:mm
+* Durée pour un voyageur à mobilité réduite : champ de type horaire hh:mm
+* Durée pour un voyageur occasionnel : champ de type horaire hh:mm
+* Durée pour un habitué : champ de type horaire hh:mm
+* Ascenseur : indicateur (Oui ou Non)
+* Accès pour personne à mobilité réduite : indicateur (Oui ou Non)
+* Escalator disponible : indicateur (Oui ou Non)
+
diff --git a/app/views/help/dataspaces.textile b/app/views/help/dataspaces.textile
index d138f26d7..8aca2f47b 100644
--- a/app/views/help/dataspaces.textile
+++ b/app/views/help/dataspaces.textile
@@ -1,32 +1,45 @@
----
-layout: default
-title: Espaces de données
----
-
-h3. Définition
-
-p. Un *espace de données* est le lieu de stockage d'un ensemble de données de transport connectées entre elles. Plusieurs attributs sont définis au niveau d'un espace de données.
-
-h3. Attributs
-
-- Nom := nom de l'espace de données
-- Code := code de l'espace de données (voir implémentation)
-- Préfixe Neptune := préfixe utilisé par défaut lors la génération de nouveaux identifiants Neptune
-- Projection géographique := référentiel de projection des coordonnées cartographiques en complément du WGS84
-- Fuseau horaire := fuseau horaire applicable pour les horaires des courses. (cf "Tz_database":http://fr.wikipedia.org/wiki/Tz_database)
-- Emprise par défaut := emprise (en WGS84) utilisée pour positionner les cartes lorsqu'il n'y a pas d'élément à afficher.
-
-h3. Implémentation
-
-p. L'espace de données est concrétisé dans la base de données par un schéma au sens SQL portant le nom défini par l'attribut code.
-
-p. Les attributs de l'espace de données sont enregistrés dans la table REFERENTIALS du schéma 'public'
-
-p. Le préfixe Neptune est utilisé dans la génération des identifiants de l'ensemble des objets du modèle; sa modification n'a d'effet que sur les objets créés après.
-
-p. La projection géographique permet un affichage et l'export des coordonnées selon un système géographique secondaires; les coordonnées de ce système ne sont pas conservés dans la base.
-
-p. Les limitations de PosgreSQL imposent qu'un nom de schéma soit en minuscule et commence par une lettre; les préfixes *pg&#95;* ainsi que *public* sont réservés.
-
-p. Les noms et codes des espaces de données sont uniques quelque soit l'organisation; une erreur de doublon peut donc arriver si une autre organisation a déjà utilisé le même terme.
-
+---
+layout: default
+title: Espace de données
+---
+
+h3. Définition
+
+Un espace de données est le lieu de stockage d’un ensemble de données de transport connectées entre elles. Un espace de données correspond généralement à un territoire géographique homogène, partageant notamment tout ou partie de ses arrêts sur un ou plusieurs réseaux.
+
+Plusieurs attributs sont définis au niveau d’un espace de données.
+
+!2014-10-30_174529.png! Espace de données
+
+h3. Créer un nouvel espace de données
+
+A l'issue de l'identification, la page d'accueil listant tous les espaces de données s'affichent. Cette même page est accessible en cliquant sur le pictogramme Chouette situé en haut de la page. Cliquer sur le lien _"Ajouter un espace de données"_ situé dans le menu latéral affiche le formulaire de création d'espace de données.
+
+h3. Modifier un espace de données.
+
+Pour modifier un espace de données, il convient de cliquer sur le pictogramme en forme de crayon de l'espace de données.
+
+Il est également possible de le modifier depuis la page d'accueil de l'espace de données proprement dit en cliquant sur le lien _"Modifier cet espace de données"_ situé dans le menu latéral droit.
+
+Sur la page d'un espace de données, deux fonctions spécifiques sont disponibles :
+
+* Ajouter une clé d'accès API : La clé API permet à une application tierce de récupérer des données directement dans l'application pour les exploiter pour son propre fonctionnement. La clé, fournie par le prestataire chargé de la maintenance du système, permet au système tiers de s'identifier auprès de CHOUETTE.
+* Purge des données obsolètes : Cette fonction permet de supprimer tous les calendriers échus avant la date renseignée. Une fois les calendriers supprimés, CHOUETTE supprimera toutes les courses dépourvues de calendrier, puis les missions dépourvues de courses etc... Cela permet de nettoyer la base de toutes ses informations obsolètes. Il est possible de ne pas supprimer certaines catégories d'objets en cliquant les options correspondantes, notamment dans les cas où la modification est saisonnière et où les objets conservés seront utilisés ultérieurement. Purger les données permet de conserver une base de taille raisonnable. Autrement, toutes les données obsolètes resteront dans la base sans pour autant servir à quoi que ce soit.
+
+h3. Supprimer un espace de données
+
+Pour supprimer un espace de données, il convient de cliquer sur le pictogramme en forme de poubelle de l'espace de données.
+
+Il est également possible de le supprimer depuis la page d'accueil de l'espace de données proprement dit en cliquant sur le lien _"Supprimer cet espace de données"_ situé dans le menu latéral droit.
+
+h3. Attributs d'un espace de données
+
+Tous les champs sont obligatoires.
+
+* Nom : nom de l’espace de données
+* Code : code de l’espace de données (voir implémentation)
+* Préfixe Neptune : préfixe utilisé par défaut lors la génération de nouveaux identifiants Neptune
+* Projection géographique : référentiel de projection des coordonnées cartographiques en complément du WGS84
+* Fuseau horaire : fuseau horaire applicable pour les horaires des courses. (cf Tz_database)
+* Emprise par défaut : emprise (en WGS84) utilisée pour positionner les cartes lorsqu’il n’y a pas d’élément à afficher. Lors de la création, chacun des points défini un carré pour l'affichage par défaut de la cartographie.
+
diff --git a/app/views/help/documentation.textile b/app/views/help/documentation.textile
deleted file mode 100644
index 5896ed7a0..000000000
--- a/app/views/help/documentation.textile
+++ /dev/null
@@ -1,8 +0,0 @@
----
-layout: default
-title: Documentation
----
-
-La documentation de Chouette (y compris le présent manuel utilisateur) est disponible sur le site "Chouette.mobi":http://www.chouette.mobi/docs
-
-Le présent manuel Utilisateur est par ailleurs livré sous forme d'aide en ligne avec l'application web. \ No newline at end of file
diff --git a/app/views/help/edit.textile b/app/views/help/edit.textile
new file mode 100644
index 000000000..77ea00336
--- /dev/null
+++ b/app/views/help/edit.textile
@@ -0,0 +1,20 @@
+---
+layout: default
+title: Edition et suppression d'un élément
+---
+
+L'un des principes de fonctionnement de l'application pour la création, la modification et la supression d'un élément est de pouvoir utiliser deux méthodes différentes.
+
+L'une consiste à passer par les listes d'éléments et d'utiliser les boutons de modification et de suppression directement sur l'élément de la liste.
+
+!2014-10-30_174647.png! Modification d'un espace de données depuis un élément de liste.
+
+!2014-10-30_174728.png! Modification d'un espace de données depuis sa page.
+
+L'autre méthode consiste à utiliser les fonctions du menu latéral directement dans la page de l'élément à éditer.
+
+!2014-10-30_175041.png! Suppression d'un élément depuis la liste.
+
+!2014-10-30_175002.png! Suppression d'un élément depuis le menu latéral accessible dans sa page.
+
+
diff --git a/app/views/help/export_format.textile b/app/views/help/export_format.textile
new file mode 100644
index 000000000..5e3c5b108
--- /dev/null
+++ b/app/views/help/export_format.textile
@@ -0,0 +1,37 @@
+---
+layout: default
+title: Formats d'exports
+---
+
+h3. Rôle
+
+p. L'export permet d'extraire de la base un ensemble de données selon plusieurs formats.
+
+h3. Formats disponibles
+
+* Neptune : format d'échange de données de transport en commun pour la France (cf "Normalisation":normalisation)
+* NeTEx : format d'échange de données de transport en commun expérimental sur la future norme européenne ["NeTEx":http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/] mais limité au sous-ensemble des données définies dans le format Neptune
+* CSV : format tabulaire spécifique à Chouette (cf "CSV":csv)
+* GTFS : format destiné à ["Google Transit":https://developers.google.com/transit/gtfs/?hl=fr] ; les données exportées en GTFS sont explicités ["ICI":http://www.normes-donnees-tc.org/format-dechange/autres-normes/]
+* KML : format contenant l'ensemble des données cartographiées pouvant ainsi être importée dans un SIG
+* HUB : format tabulaire interne Transdev
+
+h3. Options des formats
+
+Les options des différents formats apparaissent en fonction de celui qui a été choisi.
+
+* *tout format* :
+** Type de données incluses :sélection des lignes exportées. Le choix porte sur toutes, les lignes d'une sélection de réseaux, de transporteurs ou directement sélectionnées =:
+** Données incluses : liste des données selon le type choisi; ce champs n'apparait pas pour le choix 'toutes' la sélection propose dès le premier caractère saisi la liste des objets dont le nom contient le texte.
+* *Neptune* :
+** 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
+* *GTFS* :
+** 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
+* *CSV* : pas d'option particulière
+* *HUB* :
+** 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, la valeur proposée par défaut est celle de l'espace de données.
diff --git a/app/views/help/exports.textile b/app/views/help/exports.textile
index c1da06a11..8f4511365 100644
--- a/app/views/help/exports.textile
+++ b/app/views/help/exports.textile
@@ -9,11 +9,12 @@ p. L'export permet d'extraire de la base un ensemble de données selon un format
h3. Formats disponibles
-- Neptune := format normalisé des échanges de données de transport en commun pour la France (cf "Normalisation":normalisation)
-- NeTEx := format d'échanges de données de transport en commun expérimental sur la norme européenne ["NeTEx":http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/] mais limité aux données définies dans la norme Neptune
+- Neptune := format d'échange de données de transport en commun pour la France (cf "Normalisation":normalisation)
+- NeTEx := format d'échange de données de transport en commun expérimental sur la future norme européenne ["NeTEx":http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/] mais limité au sous-ensemble des données définies dans le format Neptune
- CSV := format tabulaire spécifique à Chouette (cf "CSV":csv)
- GTFS := format destiné à ["Google Transit":https://developers.google.com/transit/gtfs/?hl=fr] ; les données exportées en GTFS sont explicités ["ICI":http://www.normes-donnees-tc.org/format-dechange/autres-normes/]
- KML := format contenant l'ensemble des données cartographiées pouvant ainsi être importée dans un SIG
+- HUB := format tabulaire interne Transdev
h3. Options des formats
@@ -38,16 +39,28 @@ 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
* *CSV* : pas d'option particulière
+* *HUB* :
+
+- 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
+ 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/faq.textile b/app/views/help/faq.textile
deleted file mode 100644
index e438d4bd2..000000000
--- a/app/views/help/faq.textile
+++ /dev/null
@@ -1,8 +0,0 @@
----
-layout: default
-title: Foire aux questions
----
-
-N'hésitez pas à nous solliciter pour toute question, nous compléterons la FAQ progressivement !
-
-"Forum de chouette.mobi":http://forum.chouette.mobi \ No newline at end of file
diff --git a/app/views/help/group_of_lines.textile b/app/views/help/group_of_lines.textile
index 05121ff46..0b1f0975b 100644
--- a/app/views/help/group_of_lines.textile
+++ b/app/views/help/group_of_lines.textile
@@ -1,39 +1,50 @@
----
-layout: default
-title: Groupes de lignes
----
-
-h3. Définition
-
-Un groupe de lignes regroupe un ensemble de lignes assurant un type de service commun ; ces lignes ne sont pas forcément du même réseau.
-Note 1: dans NeTex, le réseau est un groupe de ligne parmi les autres.
-
-Note 2: dans Neptune, une ligne ne peut appartenir qu'à un seul groupe de ligne; donc dans l'export Neptune, un seul groupe sera exporté.
-
-
-h3. Attributs
-
-- Nom := nom du groupe de lignes
-- Lignes := liste des "lignes":lines affectées au groupe
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant le groupe de lignes pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = GroupOfLine : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Groupe de lignes
+---
+
+h3. Définition
+
+Un groupe de lignes regroupe un ensemble de lignes assurant un type de service commun. Ces lignes ne font pas forcément partie du même réseau.
+
+Dans le format NeTex, le réseau est un groupe de lignes parmi les autres.
+
+Dans le format Neptune, une lignes ne peut appartenir qu'à un seul groupe de lignes ; donc dans l'export Neptune, un seul groupe sera exporté.
+
+h4. Liste des groupes de lignes
+
+Sélectionner _"groupes de lignes"_ dans le menu _"Données"_ affiche la liste des groupes de lignes existants dans l'espace de données.
+
+h4. Ajouter un groupe de lignes
+
+Depuis la liste des groupe de lignes, cliquer sur _"Ajouter un groupe de lignes"_ dans la partie droite de l'écran. Il est également possible de créer un nouveau groupe de lignes depuis la page de n'importe quel groupe de lignes.
+
+!2014-10-30_182229.png! Création d'un nouveau groupe de lignes depuis la liste des lignes
+
+Un formulaire s'affiche. Les champs obligatoires sont signalés par des astérisques.
+
+Dans le champs, _"Lignes associées"_, saisir les premiers caractères d'une ligne. L'auto-complétion présentera les lignes correspondant à la saisie. Taper sur _"Entrée"_ valide la proposition. Il est à noter que ces associations fonctionnent dans les deux sens et qu'il est également possible d'associer une ligne à un groupe de ligne depuis la page d'une ligne.
+
+h4. Afficher un groupe de lignes existant
+
+Pour afficher un groupe de lignes existant il suffit de cliquer sur le nom du groupe de lignes depuis la liste des groupes de lignes existants.
+
+Les arrêts des lignes du groupe sont affichés sur la cartographie.
+
+En bas de la page, un lien _"Liste des lignes"_ permet d'afficher la liste des lignes du groupe.
+
+h4. Modifier un groupe de lignes
+
+On peut modifier un groupe de lignes en cliquant sur le bouton de modification directement depuis la liste des groupes de lignes ou depuis la page d'un groupe de lignes particulier.
+
+h4. Supprimer un groupe de lignes
+
+On peut modifier un groupe de lignes en cliquant sur le bouton de suppression directement depuis la liste des groupes de lignes ou depuis la page d'un groupe de lignes particulier. Il est à noter que les lignes rattachées à ce groupe de lignes ne seront pas supprimés. Il sera toujours possible de les rattacher à un autre groupe de lignes par la suite en les modifiant.
+
+h3. Attributs d'un groupe de lignes
+
+* Nom : nom du groupe de lignes
+* Commentaire : Champs de saisie libre pour identifier l'usage du groupe de lignes.
+
+
+
diff --git a/app/views/help/import_formats.textile b/app/views/help/import_formats.textile
new file mode 100644
index 000000000..0cd3b63b0
--- /dev/null
+++ b/app/views/help/import_formats.textile
@@ -0,0 +1,39 @@
+---
+layout: default
+title: Formats d'imports
+---
+
+h3(#fmt). Formats disponibles
+
+* Neptune : format d'échange de données de transport en commun pour la France (cf "Normalisation":normalisation)
+* NeTEx : format d'échange de données de transport en commun expérimental sur la future norme européenne ["NeTEx":http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/] mais limité au sous-ensemble des données définies dans le format Neptune
+* CSV : format tabulaire spécifique à Chouette (cf "CSV":csv)
+* GTFS : format originaire de ["Google Transit":https://support.google.com/transitpartners/], à condition que le fichier soit préalablement validé avec l'outil Feed Validator =:
+
+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
+p(ddnext). - active donc les tests de validation de niveau 1 et 2
+* Jeu de paramètres pour validation := paramètres définissant les seuils des tests de niveau 3 (indisponible si l'option 'pas de sauvegarde' est cochée)
+p(ddnext). - les jeux de paramètres sont créés via le lien ["Jeux de paramètres":parametersets] disponible sur les vues des listes d'imports et de validations
+* Fichier à importer := fichier (plat ou zip selon format)
+
+h3(#opt). Options des formats
+
+Les options des différents formats apparaissent en fonction de celui qui a été choisi.
+
+* *Neptune* : pas d'option particulière
+* *NeTex* : pas d'option particulière
+* *GTFS* :
+** Préfixe d'identifiants : préfixe à utiliser pour générer les identifiants Neptune des objets importés, initialisé à la valeur définie pour l'espace de données.
+** Distance max pour créer les zones : distance maximale entre deux arrêts homonymes pour les regrouper au sein d'un arrêt commercial de même nom, ces zones viennent en supplément de celles définies dans GTFS, une distance de 0 ne génère aucune zone.
+** ignorer le dernier mot : lors de la comparaison des noms d'arrêts, cette option permet de ne pas prendre en compte le dernier mot du nom de l'arrêt (sauf si celui-ci n'est composé que d'un seul mot).
+** ignorer les n derniers caractères : lors de la comparaison des noms d'arrêts, cette option permet de ne pas prendre en compte les derniers caractères du nom de l'arrêt (sauf si celui-ci n'a pas assez de caractères pour cela)
+** Distance max pour créer les correspondances : 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 permettant 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* :
+** Préfixe d'identifiants : préfixe à utiliser pour générer les identifiants Neptune des objets importés, initialisé à la valeur définie pour l'espace de données. \ No newline at end of file
diff --git a/app/views/help/imports.textile b/app/views/help/imports.textile
index 88b780b7f..ddc93edc0 100644
--- a/app/views/help/imports.textile
+++ b/app/views/help/imports.textile
@@ -5,9 +5,6 @@ title: Imports
* "Rôle":#rol
* "Validation":#val
-* "Formats disponibles":#fmt
-* "Paramètres communs":#com
-* "Options des formats":#opt
* "l’onglet IMPORTS":#imp
* "Nouvel Import":#new
* "Paramètres de validation":pvl
@@ -19,6 +16,8 @@ h3(#rol). Rôle
p. L’import permet d’enregistrer dans la base un jeu de données d'offre TC, selon un format au choix. Des tests de validation des données sont exécutés avant l'import en base de données (plus détaillées dans le cas du format Neptune). Il est possible d'importer sans sauver en base, uniquement pour jouer les tests de vérification de conformité. Dans ce cas les tests en base de données (auxquels sont associés les jeux de paramètres) ne seront pas exécutés (et donc aucun test ne sera exécuté, pour des données CSV, GTFS, ou Netex).
+!2014-10-31_151613.png! Page des imports
+
h3(#val). Validation
p. Lors de l'import, des tests sont effectués :
@@ -31,66 +30,12 @@ p(olnext). - nécessite la fourniture d'un jeu de paramètres définissant les s
p(note). Les tests de niveau 1 et 2 ne sont actuellement implémentés que pour le format Neptune
-h3(#fmt). Formats disponibles
-
-- Neptune := format normalisé des échanges de données de transport en commun pour la France (cf "Normalisation":normalisation)
-- NeTEx := format d'échange de données de transport en commun expérimental sur la norme européenne ["NeTEx":http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/] mais limité au sous-ensemble des données définies dans la norme Neptune
-- CSV := format tabulaire spécifique à Chouette (cf "CSV":csv)
-- GTFS :=
-format originaire de ["Google Transit":https://support.google.com/transitpartners/], à condition que le fichier soit préalablement validé avec l'outil Feed Validator =:
-
-p(olnext). - les données exportées en GTFS sont explicités ["ICI":http://www.normes-donnees-tc.org/format-dechange/autres-normes/]
-
-h3(#com). Paramètres communs
-
-- Pas de sauvegarde := permet d'effectuer une simulation de l'import sans enregistrer les données
-
-p(ddnext). - active donc les tests de validation de niveau 1 et 2
-
-- Jeu de paramètres pour validation := paramètres définissant les seuils des tests de niveau 3 (indisponible si l'option 'pas de sauvegarde' est cochée)
-
-p(ddnext). - les jeux de paramètres sont créés via le lien ["Jeux de paramètres":parametersets] disponible sur les vues des listes d'imports et de validations
-
-- Fichier à importer := fichier (plat ou zip selon format)
-
-h3(#opt). Options des formats
-
-Les options des différents formats apparaissent en fonction de celui qui a été choisi.
-
-* *Neptune* : pas d'option particulière
-
-* *NeTex* : pas d'option particulière
-
-* *GTFS* :
-
-- Préfixe d'identifiants :=
-préfixe à utiliser pour générer les identifiants Neptune des objets importés,
-initialisé à la valeur définie pour l'espace de données =:
-- Distance max pour créer les zones :=
-distance maximale entre deux arrêts homonymes pour les regrouper au sein d'un arrêt commercial de même nom,
-ces zones viennent en supplément de celles définies dans GTFS,
-une distance de 0 ne génère aucune zone =:
-- ignorer le dernier mot :=
-lors de la comparaison des noms d'arrêts, cette option permet de ne pas prendre en compte le dernier mot du nom de l'arrêt (sauf si celui-ci n'est composé que d'un seul mot) =:
-- ignorer les n derniers caractères :=
-lors de la comparaison des noms d'arrêts, cette option permet de ne pas prendre en compte les derniers caractères du nom de l'arrêt (sauf si celui-ci n'a pas assez de caractères pour cela) =:
-- Distance max pour créer les correspondances :=
-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 =:
-
-* *CSV* :
-
-- Préfixe d'identifiants :=
-préfixe à utiliser pour générer les identifiants Neptune des objets importés,
-initialisé à la valeur définie pour l'espace de données =:
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/help/index.textile b/app/views/help/index.textile
index 3e0af420b..1ac92d989 100644
--- a/app/views/help/index.textile
+++ b/app/views/help/index.textile
@@ -3,7 +3,7 @@ layout: default
title: Chouette v2
---
-Version 2.4.1
+Version 2.5.0
h3. Logiciel libre propriété de :
@@ -24,6 +24,31 @@ A cet égard l'attention de l'utilisateur est attirée sur les risques associé
h3. Notes de version
+h4. Version 2.5.0
+
+* Nouvelles foctionnalités :
+** Ajout d'un lien de création d'objet dans la page de consultation (Mantis 26415)
+** Ajout d'un lien vers l'accueil dans le bandeau (Mantis 26820)
+** Fournir plus de détails pour identifier un arrêt dans les listes de choix (Mantis 26821)
+** Possibilité de créer un arrêt en édition d'une séquence d'arrêts (Mantis 26824)
+** Localisation d'un arrêt par résolution d'adresse (Mantis 26825)
+** Saisie des coordonnées sur un seul champ (Mantis 26827)
+** Filtres de recherche des arrêts enrichi (Mantis 26829)
+** Cloner un arrêt pour en faire un parent ou un fils (Mantis 26830)
+** Import d'arrêts en CSV/Excel (Mantis 26832)
+** Ajout d'étiquettes sur les calendriers (Mantis 26833)
+** Filtres de recherche des calendriers enrichi (Mantis 26834)
+** Attributs vacances et jours fériés : comme étiquette (Mantis 26835)
+** Affichage du format lors de la saisie d'une date (Mantis 26836)
+** Gestion de dates exclues dans les calendriers (Mantis 26837)
+** Fonctions de combinaisons de calendriers : inclusion, exclusions, duplication (Mantis 26838)
+** Clonage de course avec heure de départ (Mantis 26839)
+** Décaler les horaires d'une course (Mantis 26840)
+** Import CSV d'horaires pour une séquence d'arrêts (Mantis 26843)
+** Améliorations affichage de l'état des exports (Mantis 26845)
+** Attributs TAD et PMR sur les lignes et les courses (Mantis 26846
+** Export au format HUB (Mantis 27173)
+
h4. Version 2.4.1
* Corrections des anomalies suivantes :
diff --git a/app/views/help/introduction.textile b/app/views/help/introduction.textile
index ffa00ae49..050c2f0c4 100644
--- a/app/views/help/introduction.textile
+++ b/app/views/help/introduction.textile
@@ -1,9 +1,23 @@
---
layout: default
-title: Introduction
+title: Présentation
---
CHOUETTE est un logiciel libre développé à l'initiative du ministère français chargé des transports (et du développement durable), dans le but de faciliter l'échange de données d'offre (théorique) de transport collectif (TC), en s'appuyant pour cela sur la norme NFP 99506, dite Neptune, qui spécifie un profil d'échange XML.
-Les utilisateurs visés sont les collectivités locales Autorités Organisatrices de Transport (AOT), les exploitants des réseaux TC ,et leurs prestataires (bureaux d'étude ou société de services).
-D'autres utilisateurs potentiels sont néanmoins identifiés : services de l'état, éditeurs de logiciels, opérateurs de services d'information, chercheurs...
+!2014-10-30_172801.png!
+
+CHOUETTE est une application web. Elle permet de saisir, éditer, tester des données théoriques de transport public depuis un navigateur internet. Afin de faciliter la création de réseaux complets. Elle est dotée de fonctions d'import, soit depuis d'autres formats d'applications équivalentes, soit au travers d'un fichier CSV qui permet de mener des imports massifs plutôt que de saisir tous les éléments un a un dans les formulaires adhoc.
+
+h3. A qui s'adresse ce manuel ?
+
+Ce manuel s’adresse aux utilisateurs de CHOUETTE. Les utilisateurs visés sont les collectivités locales Autorités Organisatrices de Transport (AOT), les exploitants des réseaux TC et leurs prestataires (bureaux d'étude ou société de services).
+D'autres utilisateurs potentiels sont également identifiés : services de l'état, éditeurs de logiciels, opérateurs de services d'information, chercheurs...
+
+h3. Ce que vous trouverez dans ce manuel
+
+Vous trouverez dans ce document, toutes les informations nécessaires à la prise en main de l’application.
+Le manuel couvre la version 2.5.0.
+
+
+
diff --git a/app/views/help/journey_patterns.textile b/app/views/help/journey_patterns.textile
index b6a67e0e1..1eb45b5fe 100644
--- a/app/views/help/journey_patterns.textile
+++ b/app/views/help/journey_patterns.textile
@@ -1,37 +1,41 @@
----
-layout: default
-title: Missions
----
-
-h3. Définition
-
-Une *mission* se définit comme une suite extraite de la suite ordonnée des arrêts d’une "séquence d’arrêts":routes. Autrement dit, toutes les courses d'une séquence d'arrêts qui desservent les mêmes arrêts et dans le même ordre, à des horaires différents éventuellement, référencent la même mission. La mission correspond donc à une suite ordonnée d'arrêts de la séquence d'arrêts.
-
-h3. Attributs
-
-- Nom := nom de la mission
-- Nom public := nom public pour les voyageurs
-- Numéro d'enregistrement := Le numéro d'enregistrement est unique. Aucune règle de nommage ne s'applique sur ce numéro. Celui-ci doit être unique sur l'ensemble des missions de la ligne.
-- Commentaire := zone de texte libre
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la mission pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = JourneyPattern : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Missions
+---
+
+h3. Définition
+
+Une _"Mission"_ est une sélection ordonnée d'arrêts issue d'une séquence d'arrêts de à partir de laquelle il sera possible de créer des courses, c'est à dire d'associer différents horaires à la mission. Les arrêts de la mission sont toute ou partie des arrêts de la séquence d'arrêts.
+
+Une mission est spécifique à une _"séquence d'arrêts"_. Une même séquence d'arrêts peut contenir plusieurs missions différentes.
+
+Les différentes missions peuvent regrouper des arrêts communs et comporter des doublons d'arrêts.
+
+h3. Créer une mission
+
+La création d'une mission se fait depuis la page d'une séquence d'arrêt. Pour créer une mission il convient de cliquer sur _"Ajouter une mission"_ dans le menu latéral à droite. Un formulaire de création s'affiche alors.
+
+En bas du formulaire les arrêts sélectionnés dans la séquence d'arrêts sont sélectionnables par des cases à cocher.
+
+!2014-10-31_113803.png! Sélection des arrêts d'une mission
+
+h3. Modifier une mission
+
+On peut modifier une mission en cliquant sur le bouton de modification directement depuis la liste des lignes ou depuis la page de la séquence d'arrêts que l'on souhaite modifier. Dans le premier cas, on clique sur le pictogramme de modification dans la liste, dans le second cas, le lien _"Modifier cette mission"_ est situé dans le menu latéral de droite.
+
+h3. Supprimer une séquence d'arrêts
+
+Il est possible de supprimer une mission depuis la page de la séquence d'arrêt. Chaque élément de la liste des missions en bas de la page est dotée d'un pictogramme de suppression. Il est à noter que la suppression de la mission ne supprime par les arrêts qu'elle contient.
+
+La suppression de la mission est également possible depuis la page de la séquence elle-même. Le lien _"Supprimer cette mission"_ efface la mission courante.
+
+h3. Attributs
+
+* Nom := nom de la mission
+* Nom public := nom public pour les voyageurs
+* Numéro d'enregistrement := Le numéro d'enregistrement est unique. Aucune règle de nommage ne s'applique sur ce numéro. Celui-ci doit être unique sur l'ensemble des missions de la ligne.
+* Commentaire := zone de texte libre
+
+
+
+
diff --git a/app/views/help/lines.textile b/app/views/help/lines.textile
index 4b35d2b61..9c6b13d57 100644
--- a/app/views/help/lines.textile
+++ b/app/views/help/lines.textile
@@ -1,49 +1,66 @@
----
-layout: default
-title: Lignes
----
-
-h3. Définition
-
-Une *ligne* référence un réseau et un transporteur; par ailleurs la ligne se compose d'un ou plusieurs itinéraires.
-La ligne dispose aussi d'un identifiant fonctionnel (<< numéro d'enregistrement >>) qui est utilisé dans les échanges XML pour identifier la ligne et la mettre à jour; il est donc important que le gestionnaire de la base CHOUETTE le renseigne d'une manière bien définie et pérenne.
-
-h3. Attributs
-
-- Réseau := réseau d'appartenance de la ligne
-- Transporteur :=
-transporteur principal exploitant la ligne
-les autres transporteurs de la lignes peuvent être référencés au niveau de chaque course
-=:
-- Nom := nom de la ligne
-- Nom public := nom de la ligne connu des usagers
-- Numéro d'enregistrement := code référençant une ligne au sein d'une autorité supérieure
-- Indice := indice de la ligne
-- Mode de transport :=
-mode de transport principal de la ligne
-d'autres modes de transports particuliers peuvent être indiqués au niveau de chaque course
-=:
-- Commentaire := zone de texte libre sur la ligne
-- Groupes de lignes := "groupes de lignes":group_of_lines auxquels appartient la ligne
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la ligne pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = Line : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Lignes
+---
+
+h3. Définition
+
+Une _"ligne"_ se compose d'un ou plusieurs itinéraires et est associée avec un réseau et un transporteur.
+
+La ligne dispose d'un identifiant fonctionnel, une sorte de _"numéro d'enregistrement"_ qui est utilisé dans les échanges XML pour identifier la ligne et la mettre à jour; il est donc important que le gestionnaire de la base CHOUETTE le renseigne d'une manière bien définie et pérenne.
+
+h4. Liste des groupes de lignes
+
+Sélectionner _"Lignes"_ dans le menu _"Données"_ affiche la liste des lignes existants dans l'espace de données.
+
+h4. Ajouter une ligne
+
+Depuis la liste des groupe de lignes, cliquer sur _"Ajouter une ligne"_ dans la partie droite de l'écran. Il est également possible de créer une nouvelle ligne depuis la page de n'importe quelle ligne.
+
+Un formulaire s'affiche. Les champs obligatoires sont signalés par des astérisques.
+
+Dans le champs, _"Groupes de lignes associés"_, saisir les premiers caractères d'une ligne. L'auto-complétion présentera les groupes de lignes correspondant à la saisie. Taper sur _"Entrée"_ valide la proposition. Il est à noter que ces associations fonctionne dans les deux sens et qu'il est également possible de rajouter une ligne dans un groupe de ligne depuis la page d'un groupe de lignes.
+
+h4. Afficher une ligne existante
+
+Le nombre de lignes pouvant être assez important, il est probable que toutes les lignes ne puissent pas s'afficher sur la page des lignes. Des fonctions de recherche situées en haut de la page permettent de faire une recherche par le nom ou le numéro d'indice. Cliquer sur _"recherche avancée"_ permet de sélectionner des critères de recherche :
+
+* Réseau
+* Transporteur
+* Groupe de lignes
+
+Pour afficher une ligne existante, il suffit de cliquer sur le nom de la ligne depuis la liste des lignes existantes.
+
+Sur la page d'une ligne, les arrêts des lignes du groupe sont affichés sur la cartographie. Au survol des arrêts avec le curseur le nom de l'arrêt s'affiche dans une infobulle.
+
+En bas de la page, un lien _"Liste des arrêts de la ligne"_ affiche la liste des séquences d'arrêts de la ligne, d'y accéder, de les éditer et d'en créer de nouvelles.
+
+Les arrêts des différentes séquences d'arrêts apparaissent sur la cartographie. Une infobulle permet de connaître le nom de l'arrêt et rappelle le type d'arrêt.
+
+!2014-10-31_112140.png! Vue d'une ligne.
+
+h4. Modifier une lignes
+
+On peut modifier une ligne en cliquant sur le bouton de modification directement depuis la liste des lignes ou depuis la page d'une ligne particulière.
+
+h4. Supprimer une ligne
+
+On peut supprimer une ligne en cliquant sur le bouton de suppression directement depuis la liste des lignes ou depuis la page d'une ligne particulière. Il est à noter que les itinéraires rattachés à ce groupe de lignes ne seront pas supprimés [à vérifier]. Il sera toujours possible de les rattacher à une autre ligne par la suite.
+
+Dans le menu latéral situé à droite, un lien _"activer la sélection multiple"_ permet d'afficher des cases à cocher sur chacun des éléments de la liste. Ces cases permettent de définir les lignes qui pourront être supprimées en même temps. Une fois la sélection multiple activiée, deux raccourcis permettent de tout sélectionner et de tout déselectionner.
+
+h3. Attributs d'une ligne
+
+* Réseau : réseau d'appartenance de la ligne
+* Transporteur : transporteur principal exploitant la ligne. Dans le cas où plusieurs transporteurs assurent le service d'une même ligne, les autres transporteurs peuvent être référencés au niveau de chaque course
+* Nom : nom de la ligne
+* Nom public : nom de la ligne connu des usagers
+* Numéro d'enregistrement : code référençant une ligne au sein d'une autorité supérieure
+* Indice : indice de la ligne [préciser]
+* Mode de transport : mode de transport principal de la ligne. Le cas échéant, d'autres modes de transports particuliers peuvent être indiqués au niveau de chaque course.
+* Accessibilité PMR : précise si la ligne est équipée PMR
+* Transport à la demande : précise si la ligne est en exploitation à la demande ou pas [préciser si c'est également définissable au niveau de la course]
+* Commentaire : zone de texte libre sur la ligne
+* Groupes de lignes : _"groupes de lignes"_ auxquels appartient la ligne
+
+
diff --git a/app/views/help/maps.textile b/app/views/help/maps.textile
new file mode 100644
index 000000000..c0a1f2ac1
--- /dev/null
+++ b/app/views/help/maps.textile
@@ -0,0 +1,14 @@
+---
+layout: default
+title: Cartographie
+---
+
+h3. Cartographie
+
+Les éléments géolocalisés sont affichés sur une cartographie. Il est possible de naviguer dans la cartographie à l'aide de la souris avec un cliquer-glisser pour faire défiler la cartographie et avec la molette pour zoomer ou dé-zoomer. Ces fonctions sont également disponibles par les boutons affichés sur la cartographie.
+
+Le fond cartographique par défaut est la vue aérienne du géoportail mais il est possible de sélectionner un autre fond cartographique de son choix en cliquant sur le petit "_+_" situé à droite de la cartographie.
+
+Sur la vue des lignes, le nom de l'arrêt s'affiche lorsque l'on place le curseur au-dessus de celui-ci.
+
+Lorsque l'on modifie un arrêt, il est possible de le déplacer directement sur la cartographie à l'aide de la souris. Sa géolocalisation est alors remise à jour automatiquement. \ No newline at end of file
diff --git a/app/views/help/metadata.textile b/app/views/help/metadata.textile
new file mode 100644
index 000000000..a405db3f3
--- /dev/null
+++ b/app/views/help/metadata.textile
@@ -0,0 +1,39 @@
+---
+layout: default
+title: Métadonnées
+---
+
+Tous les éléments définis dans CHOUETTE sont identifiés par des métadonnées Neptune spécifiques. Ces métadonnées peuvent être générées automatiquement à la création de l'objet de telle sorte qu'il n'est pas nécessaire de les renseigner. Il reste toutefois possible de leur attribuer une valeur manuellement si nécessaire.
+
+Chaque type est identifié par une clé qui permet de déterminer quel est sa nature (arrêt, ligne, transporteur etc...). La norme suggère des clés types qui sont résumées dans le tableau ci-dessous.
+
+h3. Métadonnées d'un transporteur
+
+* Identifiant Neptune : Il s'agit d'un clé unique pérenne identifiant le transporteur pour les échanges Neptune. Cet identifiant est composé de 3 parties :
+** préfixe : clé identifiant un producteur de données unique
+** type = Company : clé identifiant le type d'objet (valeur imposée)
+** id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur. Ce champ obligatoire est automatiquement généré s'il n'est pas renseigné. Il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
+* Date de création : date à laquelle l'objet a été créé ou modifié pour la dernière fois
+* Version : version de l'objet (auto incrémenté à chaque modification)
+* Créé par : compte utilisateur ayant procédé à la dernière modification
+
+!2014-10-30_175715.png! Exemple d'identifiant Neptune
+
+h3. Clés
+
+table(meta).
+|_. Donnée|_. Clé|
+|Réseau|GroupOfLine|
+|Transporteur|Company|
+|Groupe de lignes|GroupOfLine|
+|Arrêt|StopArea|
+|Accès|AccessPoint|
+|Lien d'accès|AccessLink|
+|Correspondance|ConnectionLink|
+|Ligne|Line|
+|Séquence d'arrêts|Route|
+|Mission|JourneyPattern|
+|Course|VehicleJourney|
+|Calendrier|Timetable|
+
+
diff --git a/app/views/help/navigation.textile b/app/views/help/navigation.textile
new file mode 100644
index 000000000..fa51bd5d9
--- /dev/null
+++ b/app/views/help/navigation.textile
@@ -0,0 +1,61 @@
+---
+layout: default
+title: Navigation
+---
+
+La navigation dans CHOUETTE se fait à la souris sans utilisation du clic droit.
+
+h3. Bandeau supérieur
+
+Le bandeau supérieur regroupe l'essentiel des liens de navigation :
+
+* Le logo CHOUETTE situé à gauche dans le bandeau supérieur permet de revenir à tout moment à l'accueil de CHOUETTE.
+* L'espace de travail où l'utilisateur se trouve actuellement et qui permet de passer d'un espace de travail à un autre par une liste déroulante quelle que soit la page active.
+* Toutes les rubriques de l'espace de données courant.
+* L'accès à la page d'aide qui s'ouvre un nouvel onglet.
+* Les préférences utilisateurs, notamment le choix de langue et les paramètres du compte.
+
+!2014-10-30_173410.png! Bandeau supérieur de CHOUETTE
+
+h3. Listes d'éléments
+
+Les listes prennent la forme de "_boites_" rangées côte à côte. Dans le cas où le titre de l'élément est trop long pour être affiché entièrement, une infobulle complète apparaît au survol du titre.
+
+Les éléments de l'application qui apparaissent sous la forme de liens sont ceux qui peuvent faire l'objet d'un paramétrage détaillés. Il s'accompagnent dans les listes de pictogramme de modification et de suppression. Le pictogramme de modification ne concerne que les propriétés générales de l'élément et non pas les informations spécifiques qu'il regroupe. Il faut cliquer sur le lien proprement dit pour pouvoir consulter et éditer les informations correspondantes. Le pictogramme de suppression permet de supprimer effectivement toutes les informations correspondant à l'élément.
+
+!2014-10-30_173506.png! Exemple de liste d'éléments
+
+Les listes d'éléments peuvent dans certains cas être réduites afin de ne pas surcharger la page. Cliquer sur le titre de la liste permet d'afficher la liste des éléments.
+
+h3. Fonctions d'édition
+
+Les fonctions d'édition des données proprement dites se situent à droite de l'affichage principal.
+
+!2014-10-30_173604.png! Fonctions d'édition des arrêts
+
+h3. Déplacement d'un objet sur la cartographie
+
+CHOUETTE permet de déplacer élément, arrêt ou accès par exemple, sur la cartographie. Pour cela il convient :
+
+* d'activer le déplacement en cliquant sur l'arrêt. Le curseur prend alors la forme d'une quadruple flèche
+* d'appuyer ensuite sur le bouton gauche de la souris et le maintenir appuyé lors du déplacement. L'arrêt peut alors être déplacé avec la souris
+* de relâcher le bouton, l'arrêt est positionné sur une nouvelle position fixe.
+* de cliquer sur la carte permet de sortir du mode déplacement et de finaliser le déplacement en mettant les coordonnées à jour dans le formulaire
+
+!2014-10-30_173740.png! Déplacement d'un arrêt sur la cartographie
+
+h3. Auto-complétion
+
+De nombreux champs de CHOUETTE font appel à des fonctions d'auto-complétion de telle sorte que des éléments tapés dans le champs font automatiquement remonter des éléments pertinents déjà connus du système.
+
+!2014-10-30_173913.png! Auto-complétion sur la sélection d'un arrêt.
+
+h3. Architecture de l'interface de CHOUETTE
+
+Un certain nombre d'éléments constitutifs de la base de données sont accessibles en tant que sous éléments de menus accessibles depuis la page. Il en va ainsi par exemple des horaires qui sont accessibles au travers des lignes puis des séquences d'arrêts. Il est conseillé à l'utilisateur débutant de se reporter au chapitre _"Créer un réseau à partir de zéro"_ situé en annexe pour un rappel de l'ordre dans lequel il faut créer les éléments du réseau.
+
+!navigation.png! Navigation au sein de l'application CHOUETTE
+
+
+
+
diff --git a/app/views/help/networks.textile b/app/views/help/networks.textile
index cd21ddda9..e91ac0f19 100644
--- a/app/views/help/networks.textile
+++ b/app/views/help/networks.textile
@@ -5,39 +5,17 @@ title: Réseaux
h3. Définition
-Un *réseau* est constitué par les "lignes":lines, les "séquences d'arrêts":routes, les "Interdictions de Trafic Local":stop_areas (ITL), les "horaires":vehicle_journeys, et les "courses":vehicle_journeys qui le définissent.
+Un _"réseau"_ est défini dans la page correspondante. A chaque réseau s'associent des "lignes":lines, des "séquences d'arrêts":routes, des "Interdictions de Trafic Local":stop_areas (ITL), des "horaires":vehicle_journeys, et des "courses":vehicle_journeys. Il convient donc de définir un réseau avant de créer ces éléments.
Chaque réseau dispose d'un identifiant fonctionnel (<< numéro d'enregistrement >>) qui est utilisé dans les échanges XML pour identifier le réseau et le mettre à jour. Il est très important que le gestionnaire le renseigne d'une manière bien définie et pérenne.
-
h3. Attributs
-- Nom := nom du réseau
-- Numéro d'enregistrement := code référençant un réseau au sein d'une autorité supérieure
-- Commentaire := zone de texte libre sur le réseau
-- Date de version := date de mise en référence de l'ensemble des constituants du réseau
-- Description := description du réseau
-- Nom du système origine := nom du système ayant produit les données du réseau
-- Identifiant du système origine := identifiant du système ayant produit les données du réseau
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant le réseau pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = GroupOfLine : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
+* Nom :nom du réseau
+* Numéro d'enregistrement : code référençant un réseau au sein d'une autorité supérieure
+* Commentaire : zone de texte libre sur le réseau
+* Date de version : date de mise en référence de l'ensemble des constituants du réseau
+* Description : description du réseau
+* Nom du système origine : nom du système ayant produit les données du réseau
+* Identifiant du système origine : identifiant du système ayant produit les données du réseau
diff --git a/app/views/help/normalisation.textile b/app/views/help/normalisation.textile
deleted file mode 100644
index 97f69419d..000000000
--- a/app/views/help/normalisation.textile
+++ /dev/null
@@ -1,46 +0,0 @@
----
-layout: default
-title: Normalisation
----
-
-Le projet Chouette a été développé dans le cadre de la normalisation de l'information sur les transports publics (AFNOR/BNEVT CN03/GT7), en vue de faciliter l'interopérabilité des systèmes et en particulier les échanges de données entre Systèmes d'Information Multimodale.
-
-Le site web "www.normes-donnees-tc.org":http://www.normes-donnees-tc.org, maintenu en parallèle du site "www.chouette.mobi":http://www.chouette.mobi, est un bon point d'entrée pour trouver les informations concernant la normalisation des données pour les transports publics.
-
-h3. TRANSMODEL (EN12896)
-
-La norme européenne TRANSMODEL constitue le modèle conceptuel de données sur lequel s'appuie l'ensemble des travaux normatifs (Neptune, SIRI, IFOPT, NETEX) . Elle est actuellement validée dans sa version 5.1.
-
-Elle a pour objectif de décrire les différents concepts utilisés au sein des multiples métiers du transport public (aussi bien dans le domaine de l'exploitation, de la régulation que dans celui de l'information voyageur) en usant de la modélisation UML. Cette description a abouti à la constitution d'un "dictionnaire" dans lequel chacun peut venir piocher la terminologie adéquate pour pouvoir désigner, quels que soient la structure et le métier de l'intéressé, de façon homogène et non ambiguë les concepts qu'il va décliner dans son application.
-
-h3. de TRIDENT à NEPTUNE (PR NF P99-506)
-
-Dans le cadre de la "commission de normalisation CN03 pour les applications télématiques dans les transports publics":http://www2.afnor.org/espace_normalisation/structure.aspx?commid=86672, miroir du groupe européen CEN TC278 / WG3, un groupe de travail GT7 a été créé en 2002 pour normaliser les échanges de données concernant l'information aux voyageurs entre exploitants et Autorités Organisatrices de transport.
-
-Après examen des travaux en cours au niveau européen, il est apparu au groupe que les spécifications d'échange élaborées dans le cadre du projet européen TRIDENT étaient la meilleure base de travail sur laquelle s'appuyer pour la normalisation.
-Ces spécifications d'échange couvrent l'information VP et TC, théorique et en situation perturbée; elles s'appuient sur :
-
-* un modèle d'échange pair à pair entre fournisseur et client, avec possibilité d'abonnement ;
-* un modèle de données orienté objets décrit en UML, reprenant pour ce qui concerne les transports publics, le modèle conceptuel de données Transmodel V4.0, normalisé au niveau européen ;
-* un format d'échange XML spécifié sous forme de schémas XSD.
-
-Les spécifications TRIDENT ont été implémentées dans plusieurs pays européens, et en France ont été mises en oeuvre par la RATP pour son système d'information sur les situations perturbées SIPRE, et également pour les échanges d'information au niveau francilien en cours entre les systèmes de la RATP et du STIF, pour ce qui concerne l'information théorique.
-
-Le travail du groupe GT7 a abouti à des spécifications de profil d'échange TRIDENT / Chouette en 2006, qui ont servi de référence pour implémenter le logiciel CHOUETTE et sont utilisées depuis lors par plusieurs projets de SIM en France.
-
-Lors des discussions précédant l'enquête probatoire AFNOR en 2009 en vue faire de ces spécifications une norme française, ces spécifications ont été complétées par quelques éléments de données relatifs à l'accessibilité des transports : le nouveau profil d'échange baptisé *NEPTUNE* (PR NF99-506 Décembre 2009) a été adopté en janvier 2010. Il y a compatibilité ascendante avec les fichiers au profil Trident/Chouette dont Neptune est une extension.
-
-h3. Le profil d'échange NEPTUNE
-
-Le développement des Systèmes d'Information Multimodale a conduit les acteurs des transports publics en France (AOT et opérateurs, représentants d'utilisateurs et administrations publiques) dans leur ensemble à demander l'inscription de ce profil d'échange en tant que 'norme pleine'. L'adoption de ce statut de norme est d'autant plus important aujourd'hui, que les outils précités vont connaître des périodes d'évolution et d'adaptation.
-
-Dans le cadre du processus de normalisation, le profil d'échange a été rebaptisé NEPTUNE et complété. Le processus s'est conclu début 2010 par l'adoption d'un document AFNOR (cf. PR NF P99-506) .
-
-En pratique, l'essentiel est de savoir que le profil TRIDENT/CHOUETTE est compatible avec NEPTUNE : Neptune reprend l'essentiel de Trident profil Chouette, et n'a été complété qu'en ce qui concerne l'information sur l'accessibilité aux Personnes à Mobilité Réduite et les accès. En particulier, le nommage des éléments de données du profil XSD n'a pas été modifié.
-
-Ce profil résulte d'un consensus entre les différentes parties prenantes participant au groupe de travail de normalisation CN03/GT7. Il est rédigé en français. Dans certains cas, pour éviter des confusions ou des contre-sens, les concepts de la norme TRANSMODEL qui ont été manipulés sont rappelés dans leur terminologie, voire leur définition en anglais dans le texte original de la norme TRANSMODEL V5.1 qui vaut référence. Les rapprochements nécessaires ont été faits avec la version provisoire en français de la norme TRANSMODEL en cours de validation.
-
-Ce profil sera sans doute amené à évoluer en fonction des travaux réalisés dans le cadre des travaux de normalisation européens ou internationaux en cours. Ceux-ci touchent tout à la fois la représentation topographique des réseaux de transport, les interfaces entre les données d'exploitation et l'information diffusée vers le voyageur avant et pendant le voyage (NeTEX), la description des points d'arrêts et points fixes (IFOPT) , les interfaces avec la billettique et les autres échanges de données envisageables dans les métiers des transports publics (TRANSMODEL).
-
-Le profil d'échange NEPTUNE (PR NF P99-506 Décembre 2009) et donc l'outil CHOUETTE se limitent aux échanges d'information concernant la description " statique " de l'offre TC (réseau, horaires), et ne couvrent pas l'information en temps réel.
-
diff --git a/app/views/help/parametersets.textile b/app/views/help/parametersets.textile
index e5a9c0045..f3cc61e87 100644
--- a/app/views/help/parametersets.textile
+++ b/app/views/help/parametersets.textile
@@ -1,61 +1,57 @@
----
-layout: default
-title: Jeux de paramètres de validation
----
-
-h3. Définition
-
-La phase 3 de la validation nécessite de définir des paramètres afin d'adapter les tests au plus proche de la réalité du terrain.
-
-Afin de rejouer facilement les tests dans différent contextes, il est possible de définir plusieurs jeux qui sont conservés indépendamment des validations.
-
-Un jeu de paramètre est proposé par défaut à la création du référentiel; celui-ci peut être modifié ou détruit; il n'est alors pas possible de le recréer.
-
-h3. Paramètres généraux
-
-- Nom := Nom du jeu de données (nom utilisé pour sa sélection dans les imports et validations)
-- Délimitation géographique des arrêts :=
-Emprise géographique du réseau (tous les arrêts testés devront être inclus dans cette zone)
-Le format de ce champs est un ensemble de points formant une polyligne fermée:
-[[longitude1,latitude1],[longitude2,latitude2],,,[longitudeN,latitudeN],[longitude1,latitude1]]
-Les longitudes et latitudes sont exprimées en degré, décimaux positifs à l'est et au nord
-=:
-- Durée maximum de stationnement à un arrêt (en secondes) := écart de temps maximal autorisé entre l'heure d'arrivée et l'heure de départ à un arrêt
-
-p. *Distance minimum entre :* (en mètres)
-
-- 2 arrêts n'ayant pas le même parent := distance en deçà de laquelle 2 arrêts devraient être regroupés dans la même zone
-- 2 accès de noms différents pour un même arrêt := distance en deçà de laquelle 2 accès d'un même arrêt devraient en être qu'un
-
-p. *Distance maximum entre :* (en mètres)
-
-- un arrêt et son parent := distance au delà de laquelle un arrêt ne devrait pas être rattaché à une zone
-- les arrêts en correspondance := distance au delà de laquelle la correspondance entre 2 arrêts ne devraient pas être possible
-- liaison accès - arrêt := distance au delà de laquelle l'accès à un arrêt ne devrait pas être possible
-- un arrêt et un équipement := distance au delà de laquelle un équipement ne devrait pas être rattaché à un arrêt
-
-p. *Vitesse de marche maximum d'un voyageur :* (en kilomètres/heure)
-vitesse maximale admise dans les correspondances et les liaisons arrêt - accès pour :
-
-- un voyageur ordinaire := qui a un connaissance théorique du réseau
-- un voyageur occasionnel := qui ne connaît pas le réseau
-- un voyageur habituel := qui connaît bien le réseau
-- un voyageur à mobilité réduite := qui a des difficultés de déplacement
-
-
-h3. Paramètres par mode de transport.
-
-p. les paramètres suivants sont à définir pour chaque mode de transport disponible dans le réseau à tester.
-
-- Distance minimum entre 2 arrêts (en mètres) := distance minimale de parcours d'un véhicule entre 2 arrêts.
-- Distance maximum entre 2 arrêts (en mètres) := distance maximale de parcours d'un véhicule entre 2 arrêts.
-- Vitesse minimum (en kilomètres/heure) := vitesse minimale attendue entre 2 arrêts d'une course
-- Vitesse maximum (en kilomètres/heure) := vitesse maximale attendue entre 2 arrêts d'une course
-- Écart maximum de durée de trajet entre 2 arrêts successifs pour les différentes courses (en secondes) :=
-la différence de temps de trajet entre 2 arrêts successifs de 2 courses d'une même mission ne doit pas dépasser ce seuil =:
-
-h3. Remarques
-
-p. Les distances sont calculées _à vol d'oiseau_ et les vitesses sont déterminées par rapport à ces distances.
-Les résultats des tests utilisant ces valeurs sont donc à prendre avec les réserves adéquates.
-
+---
+layout: default
+title: Jeux de paramètres de validation
+---
+
+h3. Définition
+
+CHOUETTE intègre un outil de validation de la base de données qui permet de détecter les erreurs les plus grossières qui auraient pu être laissée dans la base de données. Un ensemble de tests est disponible mais il n'est pas obligatoire de les passer tous. L'utilisateur peut créer son propre jeu de tests au travers d'un _"jeu de paramètres"_ dans le menu validation.
+
+Les paramètres de tests peuvent donc être choisis afin d'adapter les tests à la réalité du terrain.
+
+Afin de rejouer facilement les tests dans différent contextes, il est possible de définir plusieurs jeux qui sont conservés indépendamment des validations.
+
+Un jeu de paramètre est proposé par défaut à la création du référentiel; celui-ci peut être modifié ou détruit; il n'est alors pas possible de le recréer.
+
+h3. Paramètres généraux
+
+* Nom : Nom du jeu de données (nom utilisé pour sa sélection dans les imports et validations)
+* Délimitation géographique des arrêts : Emprise géographique du réseau (tous les arrêts testés devront être inclus dans cette zone). Le format de ce champs est un ensemble de points formant une polyligne fermée:[[longitude1,latitude1],[longitude2,latitude2],,,[longitudeN,latitudeN],[longitude1,latitude1]], Les longitudes et latitudes sont exprimées en degré, décimaux positifs à l'est et au nord. Il s'agit du format WGS84 normé également utilisé dans googlemaps ou open street map.
+* Durée maximum de stationnement à un arrêt (en secondes) := écart de temps maximal autorisé entre l'heure d'arrivée et l'heure de départ à un arrêt
+
+p. *Distance minimum entre :* (en mètres)
+
+* 2 arrêts n'ayant pas le même parent := distance en deçà de laquelle 2 arrêts devraient être regroupés dans la même zone
+* 2 accès de noms différents pour un même arrêt := distance en deçà de laquelle 2 accès d'un même arrêt devraient en être qu'un
+
+p. *Distance maximum entre :* (en mètres)
+
+* un arrêt et son parent : distance au delà de laquelle un arrêt ne devrait pas être rattaché à une zone
+* les arrêts en correspondance : distance au delà de laquelle la correspondance entre 2 arrêts ne devraient pas être possible
+* liaison accès - arrêt : distance au delà de laquelle l'accès à un arrêt ne devrait pas être possible
+* un arrêt et un équipement : distance au delà de laquelle un équipement ne devrait pas être rattaché à un arrêt
+
+p. *Vitesse de marche maximum d'un voyageur :* (en kilomètres/heure)
+vitesse maximale admise dans les correspondances et les liaisons arrêt - accès pour :
+
+* un voyageur ordinaire : voyageur qui a un connaissance théorique du réseau
+* un voyageur occasionnel : voyageur qui ne connaît pas le réseau
+* un voyageur habituel : voyageur qui connaît bien le réseau
+* un voyageur à mobilité réduite : voyageur qui a des difficultés de déplacement
+
+
+h3. Paramètres par mode de transport.
+
+p. les paramètres suivants sont à définir pour chaque mode de transport disponible dans le réseau à tester.
+
+* Distance minimum entre 2 arrêts (en mètres) : distance minimale de parcours d'un véhicule entre 2 arrêts.
+* Distance maximum entre 2 arrêts (en mètres) : distance maximale de parcours d'un véhicule entre 2 arrêts.
+* Vitesse minimum (en kilomètres/heure) : vitesse minimale attendue entre 2 arrêts d'une course
+* Vitesse maximum (en kilomètres/heure) : vitesse maximale attendue entre 2 arrêts d'une course
+* Écart maximum de durée de trajet entre 2 arrêts successifs pour les différentes courses (en secondes) : la différence de temps de trajet entre 2 arrêts successifs de 2 courses d'une même mission ne doit pas dépasser ce seuil =:
+
+h3. Remarques
+
+p. Les distances sont calculées _à vol d'oiseau_ et les vitesses sont déterminées par rapport à ces distances.
+Les résultats des tests utilisant ces valeurs sont donc à prendre avec les réserves adéquates.
+
diff --git a/app/views/help/prerequisite.textile b/app/views/help/prerequisite.textile
deleted file mode 100644
index 463a93009..000000000
--- a/app/views/help/prerequisite.textile
+++ /dev/null
@@ -1,18 +0,0 @@
----
-layout: default
-title: Pré-requis (Navigateur Internet)
----
-
-L'utilisation de l'application nécessite de disposer d'un navigateur ayant les caractéristiques suivantes :
-
-* Internet Explorer (Version 8 et +)
-* Mozilla FireFox (Version 12 et +)
-* Chrome (Version 8 et +)
-
-Le navigateur doit autoriser l'exécution de Javascript.
-
-L'utilisateur peut utiliser l'application CHOUETTE depuis le site www.chouette.mobi ou bien procéder à l'installation du logiciel directement sur son environnement personnel, en tant que serveur ou machine virtuelle. CHOUETTE est également disponible sans la web application, en ligne de commande (documentation séparée).
-
-Une fois identifié, l'utilisateur accède à un écran organisé autour des données à gérer : un onglet permet de gérer (créer, modifier, supprimer) chaque type de données. L'application est disponible également en version anglaise et comprend la présente aide en ligne (en français uniquement).
-
-Le manuel Utilisateur est organisé par sections correspond aux principales données gérées par l'application Chouette : Utilisateurs et Organisations, Espace de données, Réseaux, Transporteurs, Lignes, Arrêts, Correspondances, Calendriers, complété par des points divers : jeux de données, format CSV, FAQ. \ No newline at end of file
diff --git a/app/views/help/relationship.textile b/app/views/help/relationship.textile
new file mode 100644
index 000000000..dce0e7acf
--- /dev/null
+++ b/app/views/help/relationship.textile
@@ -0,0 +1,46 @@
+---
+layout: default
+title: Relation de parenté entre arrêts
+---
+
+h3. Regroupements des différents niveaux d'arrêts
+
+Les arrêts de différents niveaux hiérarchiques peuvent être liés ensemble.
+
+Ainsi on obtient les possibilités de regroupements suivants:
+
+* un arrêt physique regroupe plusieurs arrêts sur itinéraire (ou séquence d'arrêts).
+* un arrêt commercial regroupe plusieurs arrêts physiques (quai, embarquement).
+* un pôle d'échange regroupe plusieurs arrêts commerciaux.
+
+Pour ne pas aboutir à un système trop complexe, les règles suivantes sont posées:
+
+* un pôle d'échange peut contenir des arrêts commerciaux et/ou des pôles d'échanges (qui ne peuvent pas en contenir d'autres).
+* un arrêt commercial ne peut contenir que des arrêts physiques.
+
+!2014-10-30_180536.png! Exemple d'arrêt commercial contenant un arrêt physique
+
+h3. Création et modification des relations de parenté
+
+Les liens de parentalité entre les arrêts se créent depuis un arrêt déjà existant, qu'il soit parent ou fils. Il peut s'agir de mettre en relation deux arrêts déjà existants ou bien de créer un nouvel arrêt en relation à partir de l'arrêt courant.
+
+* Gérer le parent : Cette fonction affiche soit un champ de recherche pour rechercher et définir le parent si le lien n'existe pas encore, soit le nom du parent pour consultation avec une petite croix pour supprimer le lien de parenté si le lien est déjà établi. Supprimer le lien de parenté ne supprime pas l'arrêt proprement dit.
+* Cloner pour créer un père : Cette fonction crée un arrêt identique de niveau hiérarchique supérieur.
+* Gérer les fils : Cette fonction affiche un champ de recherche pour rechercher et définir le ou les arrêts fils si le lien et le cas échéant le nom du ou des arrêts fils déjà définis. Cette liste permet de consulter les arrêts fils, chacun est accompagné d'une petite croix permettant de supprimer le lien de parenté. Supprimer le lien de filiation ne supprime pas l'arrêt proprement dit.
+* Cloner pour créer un fils : cette fonction crée un arrêt identique de niveau hiérarchique inférieur.
+
+h4. Depuis les niveaux _"point d'embarquement"_ ou _"quai"_
+
+!boardingposition.png! ou !quay.png!
+
+Les niveaux _"point d'embarquement"_ et _"quai"_ étant les plus bas, ils ne peuvent pas être reliés à des arrêts fils. En conséquence seul un bouton _"Gérer le parent"_ est systématiquement disponible. Le bouton _"cloner pour créer un père"_ apparaît s'il existe déjà un arrêt parent.
+
+!2014-10-30_180955.png! Gestion d'un arrêt parent
+
+h4. Depuis le niveau _"arrêt commercial"_ ou _"Pôle d'échange"_
+
+!commercialstoppoint.png! ou !stopplace.png!
+
+Ces deux niveaux permettent à la fois de définir de nouveaux fils et de rattacher l'arrêt commercial à un parent de type "pôle d'échange". Ils disposent donc à la fois des fonctions de gestion et de clonage de parents et de fils. A noter que les arrêts de niveaux pôle d'échange qui sont hiérarchiquement les plus élevés peuvent avoir un et un seul autre pôle d'échange comme parent. Deux pôles d'échange peuvent être parents l'un de l'autre.
+
+!2014-10-30_181044.png! Gestion de relation père-fils depuis un arrêt commercial \ No newline at end of file
diff --git a/app/views/help/routes.textile b/app/views/help/routes.textile
index c422be1ad..f15c390a7 100644
--- a/app/views/help/routes.textile
+++ b/app/views/help/routes.textile
@@ -1,42 +1,62 @@
----
-layout: default
-title: Séquence d'arrêts
----
-
-h3. Définition
-
-La *séquence d'arrêts* est une sélection ordonnée de références aux "points d'arrêt":stop_areas (exemple: itinéraires aller et retour d'une ligne). Une séquence d'arrêts est spécifique à une "ligne":lines; les séquences d'arrêts peuvent référencer des arrêts communs.
-
-(Dans les versions antérieures de Chouette jusqu'à la 1.6, la séquence d'arrêts était intitulée 'itinéraire')
-
-h3. Attributs
-
-- Nom := nom de la séquence d'arrêts
-- Nom public := nom public pour les voyageurs
-- Commentaire := zone de texte libre sur le réseau
-- Direction := orientation principale (points cardinaux, circulaire ou aller/retour)
-- Indice := numéro de la séquence d'arrêts
-- Sens := aller ou retour
-- Itinéraire associé en sens opposé := référence de l'itinéraire de sens opposé associé
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la séquence d'arrêts pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = Route : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Séquence d'arrêts
+---
+
+h3. Définition
+
+Une _"séquence d'arrêts"_ est une sélection ordonnée d'arrêts à partir de laquelle il sera possible de créer des missions comprenant tout ou partie des arrêts de la séquence. Sur ces missions, se rajouterons pour finir les horaires des différentes courses.
+
+Une séquence d'arrêts est spécifique à une _"ligne"_. Une même ligne peut contenir plusieurs séquences d'arrêts différentes. On retrouve les séquences d'arrêts d'une ligne en bas de la page de la ligne en question. Les séquences d'arrêts n’apparaissent donc pas dans le menu de navigation de CHOUETTE. Il convient de se rendre sur la page de la ligne pour les consulter et les éditer.
+
+!2014-10-31_112324.png! Liste des séquences d'arrêts d'une ligne.
+
+Dans la page de la ligne, la séquence d'arrêts apparaît sur la cartographie. Le nom et le type de chaque arrêt est accessible par une infobulle. Le premier arrêt de la ligne est signalé par la couleur verte, le dernier par du rouge.
+
+!2014-10-31_113648.png! Vue cartographique des séquences d'arrêts
+
+Les différentes séquences d'arrêts peuvent regrouper des arrêts communs et comporter des doublons d'arrêts.
+
+(Dans les versions antérieures de Chouette jusqu'à la 1.6, la séquence d'arrêts était intitulée 'itinéraire')
+
+h3. Créer une séquence d'arrêts
+
+La création d'une séquence d'arrêt se fait depuis la page d'une ligne. Pour créer une séquence d'arrêt il convient de cliquer sur _"Ajouter une séquence d'arrêts"_ dans le menu latéral à droite. Un formulaire de création s'affiche alors.
+
+En bas du formulaire deux liens permettent soit de rajouter des arrêts à la séquence, soit de créer un nouvel arrêt pour le rajouter à la séquence.
+
+h4. Créer un nouvel arrêt pour l'ajouter
+
+Cliquer sur créer un nouvel arrêt renvoie l'utilisateur à la page de création d'arrêt. Il est à noter qu'il devra retourner par lui même dans sur l'interface de création de séquence d'arrêt pour reprendre son travail. La création d'un arrêt depuis la page de création de séquence d'arrêt ne s'inscrit pas dans un workflow intégré. Il est donc préférable de s'assurer que tous les arrêts nécessaires à la création de la séquence sont déjà saisis avant de commencer à créer la séquence.
+
+h4. Ajouter un arrêt
+
+Ajouter un arrêt fait apparaître un champ de saisie doté de deux pictogrammes. Pour sélectionner un arrêt, il convient de saisir les premières lettres de l'arrêt que l'on souhaite rajouter à la séquence dans le champ. L'auto-complétion proposera les arrêts correspondant présents dans la base. Il suffit alors de sélectionner l'arrêt.
+
+Le pictogramme en forme de poubelle en début de ligne permet de supprimer l'étape dans la séquence d'arrêts.
+
+Le pictogramme en forme de flèches (dans les 4 directions) permet de modifier l'ordre des arrêts dans la séquence. Il faut bien entendu au moins deux arrêts pour pouvoir modifier l'ordre des arrêts.
+
+Une fois qu'un arrêt est sélectionné, une petite croix apparait au bout de la zone contenant le nom de l'arrêt. Cliquer sur cette croix efface l'arrêt sélectionné et permet d'en saisir un nouveau.
+
+h3. Modifier une séquence d'arrêts
+
+On peut modifier une séquence d'arrêts en cliquant sur le bouton de modification directement depuis la liste des lignes ou depuis la page de la séquence d'arrêts que l'on souhaite modifier. L'ordre des arrêts de la séquence peut être modifié par glisser-déposer.
+
+!2014-10-31_112543.png! Modification des arrêts d'une séquence
+
+h3. Supprimer une séquence d'arrêts
+
+Il est possible de supprimer une séquence d'arrêt depuis la page de la ligne. Chaque élément de la liste des séquences d'arrêt en bas de la page est dotée d'un pictogramme de suppression. Il est à noter que la suppression de la séquence d'arrêts ne supprime par les arrêts qu'elle contient.
+
+La suppression de la séquence est également possible depuis la page de la séquence elle-même. Le lien _"Supprimer cette séquence d'arrêts"_ efface la séquence courante.
+
+h3. Attributs
+
+* Nom : nom de la séquence d'arrêts
+* Nom public : nom public pour les voyageurs
+* Commentaire : zone de texte libre sur le réseau
+* Direction : orientation principale (points cardinaux, circulaire ou aller/retour)
+* Indice : numéro de la séquence d'arrêts
+* Sens : aller ou retour
+* Séquence d'arrêts associée en sens opposé : référence de la séquence d'arrêts de sens opposé associée
diff --git a/app/views/help/schema.textile b/app/views/help/schema.textile
deleted file mode 100644
index 8ac1ad6fa..000000000
--- a/app/views/help/schema.textile
+++ /dev/null
@@ -1,8 +0,0 @@
----
-layout: default
-title: Vue d'ensemble
----
-
-L'IHM ne reflète pas l'intégralité des données existant en base.
-
-Par ailleurs lorsque l'application est utilisée par un administrateur central traitant de plusieurs réseaux, il sera utile d'établir lors d'une discussion initiale des accords locaux entre les partenaires pour une dénomination et des processus de saisie homogènes. \ No newline at end of file
diff --git a/app/views/help/search_filter.textile b/app/views/help/search_filter.textile
new file mode 100644
index 000000000..56488db4b
--- /dev/null
+++ b/app/views/help/search_filter.textile
@@ -0,0 +1,18 @@
+---
+layout: default
+title: Recherche et filtrage
+---
+
+h3. Étiquettes
+
+Afin d'organiser les calendriers dont le nombre peut être assez important, une fonction permet d'y adjoindre une ou plusieurs étiquettes. Pour créer une nouvelle étiquettes, il suffit de taper son nom dans le champ "_étiquettes_" puis de cliquer sur entrée. Il est possible de les supprimer en cliquant sur la petite croix de l'étiquette déjà existante. Pour adjoindre une étiquette déjà existante, taper les premières lettres de l'étiquette permettra de la faire apparaître par auto-complétion et de la sélectionner.
+
+!2014-10-30_173913.png! Sélection et création d'étiquettes
+
+h3. Recherche et filtrage
+
+Certaines listes sont trop longues, notamment pour les arrêts, pour être affichées sur une seule page. CHOUETTE propose alors des champs de recherche et de filtrage permettant de retrouver l'élément rechercher. Afin d'offrir une vue compacte, les fonctions avancées sont cachées et se révèlent lorsque l'on clique sur le lien de "_recherche avancée_".
+
+La recherche des périodes permet de rechercher par plage de dates de validité et par étiquette. Il suffit pour cela de sélectionner la ou les étiquette souhaitées en utilisant l'auto-complétion dans le champ correspondant.
+
+!2014-10-30_174251.png! Filtre de recherche des arrêts \ No newline at end of file
diff --git a/app/views/help/startingfromscratch.textile b/app/views/help/startingfromscratch.textile
new file mode 100644
index 000000000..7b003d1f9
--- /dev/null
+++ b/app/views/help/startingfromscratch.textile
@@ -0,0 +1,60 @@
+---
+layout: default
+title: Créer un réseau à partir de zéro
+---
+
+h3. Créer un nouvel espace de données
+
+Chaque réseau est généralement intégré dans un espace de donnée spécifique. Dans le cas où l'on cherche à créer une nouvelle ligne par exemple, on devra créer les éléments dans l'espace de données correspondant.
+
+h3. Définir les attributs du réseau
+
+La première étape passe par la création dans un premier temps des attributs généraux :
+
+* Réseaux : Le ou les réseaux de l'espace de données.
+* Transporteur : le ou les transporteurs qui opéreront les lignes du réseau
+
+Chacun des ces éléments est indépendant de l'autre. On peut définir plusieurs réseaux et plusieurs transporteurs.
+
+!navigation.png! Navigation au sein de l'application CHOUETTE
+
+h3. Création des calendriers
+
+Les calendriers sont associés aux courses. Ils devront donc être créés avant l'étape de création des courses. Ils nécessitent généralement un travail de mise à plat en fonction des horaires tels qu'ils ont été conçus. Un calendrier étant une série de date permettant de couvrir à la fois les plages de dates et les jours de la semaine auxquels la course fonctionne, il n'est pas rare que la création d'un nouveau réseau nécessite un nombre important de calendriers. Les fonctions d'étiquettes permettent de mieux les organiser dans CHOUETTE, toutefois, une étape préalable de conception des calendriers est généralement nécessaire pour saisir un nouveau réseau avec rigueur.
+
+h3. Création des arrêts et des correspondances
+
+Les arrêts du réseaux peuvent ensuite être créés, soit directement par saisie dans le formulaire de CHOUETTE,soit par import. Dans l'hypothèse où le nouvel espace de donnée reprend des arrêts déjà existants dans un autre espace de données, il est possible de les exporter, de les compléter pour les réimporter ensuite.
+
+Les correspondances étant des liens entre deux arrêts il est possible de les déclarer dès l'étape de création des arrêts.
+
+h3. Création des lignes
+
+La création des lignes en elle même n'est pas conditionnée à l'existence d'arrêts. La ligne permet de nommer la ligne et de définir un ensemble de paramètres de la ligne.
+
+h4. Séquences d'arrêts
+
+A l'intérieur de l'interface de ligne, l'étape suivante consiste à définir les séquences d'arrêts . Celles-ci sont constituées d'un ensemble d'arrêts ordonnés qui permettront de déterminer une ou plusieurs missions , c'est à dire un sous-ensemble de la séquence d'arrêts comportant tout ou partie de ses arrêts.
+
+Typiquement, une ligne aura deux séquences d'arrêts, une par sens de circulation. Il est tout à fait possible d'en créer d'autres, y compris avec des arrêts totalement différents d'une séquence à l'autre.
+
+h4. Missions
+
+Les missions définissent des trajets effectifs réalisés par les véhicules. Elles se définissent à l'intérieur de l'interface de gestion des séquences d'arrêts, elle-même étant un sous-élément de l'interface des lignes.
+
+On peut créer autant de mission que nécessaire au sein d'une séquence d'arrêts. Chaque mission est néanmoins contrainte par les arrêts composant la séquence d'arrêts. On peut ne pas en retenir certains mais pas en rajouter qui ne serait pas dans la séquence. Par ailleurs, l'ordre des arrêts est contraint par celui défini dans la séquence d'arrêts.
+
+h3. Horaires
+
+Les horaires ne peuvent être définis qu'à la condition d'avoir paramétré les autres critères. L'interface de consultation et de saisie des horaires se situe au niveau de la mission. Pour retrouver les horaires, il convient donc de sélectionner Ligne>Séquence d'arrêts>horaire des courses.
+
+Les horaires des courses peuvent être saisis directement dans l'interface Chouette ou bien encore être édité dans un tableau par le biais d'une fonction "d'import / export" spécifique. Disponible depuis l'interface des horaires, elle ne concerne que ceux-ci. Il ne faut pas la confondre avec les imports / export de base de données dans le système. Il s'agit d'une fonction qui permet l'édition externe et les copier/coller massifs depuis un tableur.
+
+A noter que l'édition directement dans CHOUETTE peut se faire au clavier. Le curseur placé dans le premier champ, la saisie sur le pavé numérique permet de saisir la valeur voulue. La touche tabulation permet passer du champ heure au champ minute puis de renseigner la suite de la fiche en colonne. Les liens _"Copier arrivées vers départs"_ ou inversement permettent de dupliquer les données saisies dans le cas le plus fréquent où les horaires de départ et d'arrivé à l'arrêt sont confondus.
+
+L'export se fait au format .zip et comporte des fichier .csv des calendriers et des courses. Les versions modifiées doivent être uploadées en retour individuellement au format .csv. Il convient de ne surtout pas changer la structure des fichiers et de s'assurer que le format .csv n'ait pas été modifié par le tableur. Les saisies manuelles augmentant le risque d'erreur de saisie, il est fortement recommander de valider les données après un import .csv dans le menu _"Validations"_.
+
+h3. Groupe de lignes
+
+Les groupes de lignes sont facultatifs et peuvent être créés dès lors que des lignes existent.
+
diff --git a/app/views/help/stop_areas.textile b/app/views/help/stop_areas.textile
index 43b7be200..f171e7d76 100644
--- a/app/views/help/stop_areas.textile
+++ b/app/views/help/stop_areas.textile
@@ -1,94 +1,86 @@
----
-layout: default
-title: Arrêts
----
-
-* "Définition":#def
-* "Attributs":#attr
-* "Mode opératoire":#ope
-
-h3(#def). Définitions
-
-Le référentiel des arrêts constitue un maillon essentiel du réseau, et se compose de plusieurs éléments de niveaux différents.
-
-On recense tout d'abord les arrêts physiques, qualifiés de *point d'embarquement* ou de *quai*.
-
-Du fait de l'existence de deux concepts dans le schéma TRIDENT, cet arrêt physique sera considéré par l'application comme une *zone d'arrêt de premier niveau*. Cette notion est nécessaire pour gérer les *points d'arrêts sur itinéraire* utilisés par certains réseaux.
-
-L'application gère ensuite les points d'arrêts sur itinéraire à partir de ces arrêts physiques, en assurant le regroupement des points d'arrêt sur itinéraire dans un arrêt physique (cas de plusieurs lignes passant par le même arrêt physique).
-
-Par la suite, on peut regrouper deux (ou plus) arrêts physiques au sein d'un *arrêt commercial* (par exemple pour regrouper les points d'arrêt physiques correspondant à deux poteaux d'arrêt de la même ligne situés de part et d'autre d'une chaussée mais aussi pour regrouper l'ensemble des points d'arrêt physiques d'un quai de gare routière pour lesquels on considère que le temps de correspondance est nul). Vous aurez ainsi constitué une *zone d'arrêt*, avec qualification *arrêt commercial*, de deuxième niveau.
-
-Enfin, CHOUETTE offre la possibilité de regrouper les lieux d'arrêt agglomérés ainsi créés au sein d'une *zone d'arrêt de troisième niveau* pour constituer des *pôles d'échange*.
-
-Ainsi on obtient les possibilités de regroupements suivants:
-
-* un arrêt physique regroupe plusieurs arrêts sur itinéraire (ou séquence d'arrêts).
-* un arrêt commercial regroupe plusieurs arrêts physiques (quai, embarquement).
-* un pôle d'échange regroupe plusieurs arrêts commerciaux.
-
-Pour ne pas aboutir à un système trop complexe, les règles suivantes sont posées:
-
-* un pôle d'échange peut contenir des arrêts commerciaux et/ou des pôles d'échanges (qui ne peuvent pas en contenir d'autres).
-* un arrêt commercial ne peut contenir que des arrêts physiques.
-
-Un dernier regroupement est *l'ITL* :
-
-*L'interdiction de trafic local* est l'interdiction faite à un service routier de prendre et de laisser un même voyageur à l'intérieur du périmètre des transports urbains (cf. Décret n°49-1473 du 14 novembre 1949) .
-
-Ainsi dans CHOUETTE:
-
-* Une ITL est un regroupement d'arrêts représentant le périmètre d'interdiction.
-* Une ITL est associée à une ou plusieurs lignes
-
-h3(#attr). Attributs
-
-- Type d'arrêt := catégorie de l'arrêt
-
-* !boardingposition.png! point d'embarquement
-* !quay.png! quai
-* !commercialstoppoint.png! arrêt commercial
-* !stopplace.png! pôle d'échange
-* !itl.png! ITL
-
-- Nom := nom de l'arrêt
-- Commentaire := zone de texte libre
-- Point d'intérêt le plus proche := nom du lieu desservi par l'arrêt
-- Nom de la rue := nom de la rue de l'arrêt
-- Code INSEE := code INSEE de la commune de l'arrêt
-- Zone tarifaire := zone de tarification applicable à cet arrêt
-- Numéro d'enregistrement := code référençant un arrêt au sein d'une autorité supérieure
-
-p(attr_data). Données géographiques :
-
-- Position X := coordonnée horizontale de l'arrêt dans le référentiel de projection de l'espace de données
-- Position Y := coordonnée verticale de l'arrêt dans le référentiel de projection de l'espace de données
-- Longitude := longitude de l'arrêt dans le référentiel WGS84
-- latitude := latitude de l'arrêt dans le référentiel WGS84
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la ligne pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = StopArea : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3(#ope). Mode opératoire
-
-h4. Déplacement sur la carte
-
-* activer le déplacement en cliquant sur l'arrêt -> le curseur prend la forme d'une quadruple flèche
-* appuyer sur le bouton gauche de la souris et maintenir appuyé lors du déplacement -> l'arrêt suit la souris
-* relâcher le bouton -> l'arrêt a une nouvelle position fixe
-* cliquer sur la carte -> sortie du mode déplacement; les coordonnées sont actualisées dans le formulaire
-
+---
+layout: default
+title: Arrêts
+---
+
+h3. Définition
+
+Le référentiel des arrêts constitue un maillon essentiel du réseau, et se compose de plusieurs éléments de niveaux différents.
+
+On recense tout d'abord les arrêts physiques, qualifiés de _"point d'embarquement"_ ou de _"quai"_.
+
+Du fait de l'existence de deux concepts dans le schéma TRIDENT, cet arrêt physique sera considéré par l'application comme une _"zone d'arrêt de premier niveau"_. Cette notion est nécessaire pour gérer les _"points d'arrêts sur itinéraire"_ utilisés par certains réseaux.
+
+L'application gère ensuite les points d'arrêts sur itinéraire à partir de ces arrêts physiques, en assurant le regroupement des points d'arrêt sur itinéraire dans un arrêt physique. Cela permet notamment de prendre en compte les cas de plusieurs lignes passant par le même arrêt physique.
+
+Par la suite, on peut regrouper deux (ou plus) arrêts physiques au sein d'un _"arrêt commercial"_. Cela permet par exemple de regrouper les points d'arrêt physiques correspondant à deux poteaux d'arrêt de la même ligne situés de part et d'autre d'une chaussée mais aussi de regrouper l'ensemble des points d'arrêt physiques d'un quai de gare routière pour lesquels on considère que le temps de correspondance est nul. Un tel cas correspond à une _"zone d'arrêt"_, avec qualification _"arrêt commercial"_, de deuxième niveau.
+
+CHOUETTE offre la possibilité de regrouper les lieux d'arrêt agglomérés ainsi créés au sein d'une _"zone d'arrêt de troisième niveau_" pour constituer des _"Pôles d'échange"_.
+
+Un dernier regroupement est *l'ITL*. L'interdiction de trafic local* est l'interdiction faite à un service routier de prendre et de laisser un même voyageur à l'intérieur du périmètre des transports urbains (cf. Décret n°49-1473 du 14 novembre 1949) .
+
+Ainsi dans CHOUETTE une ITL est un regroupement d'arrêts représentant le périmètre d'interdiction. Une ITL est associée à une ou plusieurs lignes. Il ne s'agit pas à proprement parler d'un type d'arrêt mais bien d'un regroupement d'arrêts. [pourquoi ne pas le traiter dans les groupes d'arrêts du coup ?]
+
+[Créer diagramme hiérarchique des arrêts]
+
+Des pictogrammes permettent d'identifier les différents types de d'arrêts.
+
+* !boardingposition.png! point d'embarquement
+* !quay.png! quai
+* !commercialstoppoint.png! arrêt commercial
+* !stopplace.png! pôle d'échange
+* !itl.png! ITL
+
+h3. Créer un arrêt
+
+La création d'un arrêt se fait en cliquant sur _"Ajouter un arrêt"_ dans le menu de droite de la page des arrêts. Il est également possible de créer un nouvel arrêt depuis la page de n'importe quel arrêt.
+
+!2014-10-30_180131.png! Création d'un arrêt depuis la liste des arrêts
+
+!2014-10-30_180211.png! Création d'un arrêt depuis la page de n'importe quel autre arrêt
+
+Un formulaire de création s'affiche. La géolocalisation peut se faire par pointage sur la cartographie et par rapprochement d'adresse postale.
+
+!2014-10-30_180356.png! Géolocalisation de l'arrêt par pointage cartographique
+
+Saisir l'adresse postale de l'arrêt proposera une géolocalisation qu'il sera toujours possible de modifier manuellement en faisant glisser l'arrêt sur la cartographie.
+
+h3. Consultation et édition d'un arrêt
+
+Le nombre d'arrêts étant la plus part du temps assez important, il est probable que tous les arrêts ne puissent pas s'afficher sur la page des lignes. Des fonctions de recherche situées en haut de la page permettent de faire une recherche par le nom. Cliquer sur _"recherche avancée"_ permet de sélectionner des critères de recherche spécifiques par code postal et type d'arrêt.
+
+Pour afficher un arrêt existant, il suffit de cliquer sur le nom de l'arrêt depuis la liste des lignes existantes.
+
+!2014-10-30_180447.png! Sélection d'un arrêt dans la liste des arrêts
+
+Une fois sur la page d'un arrêt, les arrêts de niveau hiérarchique différent et liés à l'arrêt consulté sont affichés sur la cartographie. Au survol des arrêts avec le curseur le nom de l'arrêt s'affiche dans une infobulle.
+
+!2014-10-30_180536.png! Hiérarchie des arrêts
+
+On retrouve également en bas de la page, un lien _"Liens entre arrêts"_ qui affiche les liens hiérarchiques entre l'arrêt consulté et les autres arrêts auquel il est lié. Cet affichage permet d'accéder aux autres arrêts liés en cliquant les arrêts. Dans le cas d'un arrêt physique, il affiche également la séquence d'arrêt à laquelle il est rattaché. Autant les liens de parentalité sont définis dans les pages arrêts, autant la séquence d'arrêt est définie dans les pages _"lignes"_.
+
+h4. Modifier un arrêt
+
+On peut modifier un arrêt en cliquant sur le bouton de modification directement depuis la liste des arrêts ou depuis le menu de droite de la page de l'arrêt proprement dit. Il est également possible de le déplacer sur la cartographie.
+
+h4. Supprimer un arrêt
+
+On peut supprimer une ligne en cliquant sur le bouton de suppression directement depuis la liste des lignes ou depuis la page d'une ligne particulière. Il est à noter que les itinéraires rattachés à ce groupe de lignes ne seront pas supprimés [à vérifier]. Il sera toujours possible de les rattacher à une autre ligne par la suite.
+
+h3. Attributs d'un arrêt
+
+* Nom : nom de l'arrêt
+* Commentaire : zone de texte libre
+* Point d'intérêt le plus proche : nom du lieu desservi par l'arrêt
+* Nom de la rue : nom de la rue de l'arrêt
+* Code INSEE : code INSEE de la commune de l'arrêt
+* Zone tarifaire : zone de tarification applicable à cet arrêt
+* Numéro d'enregistrement : code référençant un arrêt au sein d'une autorité supérieure
+
+* Position X : coordonnée horizontale de l'arrêt dans le référentiel de projection de l'espace de données
+* Position Y : coordonnée verticale de l'arrêt dans le référentiel de projection de l'espace de données
+* Longitude : longitude de l'arrêt dans le référentiel WGS84
+* latitude : latitude de l'arrêt dans le référentiel WGS84
+
+
+
diff --git a/app/views/help/stopsmanagement.textile b/app/views/help/stopsmanagement.textile
new file mode 100644
index 000000000..40b170d4f
--- /dev/null
+++ b/app/views/help/stopsmanagement.textile
@@ -0,0 +1,19 @@
+---
+layout: default
+title: Modification des arrêts d'une ligne
+---
+
+h3. Nouvel arrêt ou modification d'arrêt existant
+
+Avec le temps, un ou plusieurs arrêts sont susceptibles de changer au sein d'une même ligne. Il est conseillé de faire la distinction entre les nouveaux arrêts et les arrêts modifiés. Si un arrêt est retiré d'une ligne et remplacé par un autre arrêt, il est conseillé de créer un nouvel arrêt correspondant et de faire la substitution dans la ligne. Il serait certes plus rapide de simplement changer le nom et la géolocalisation de l'arrêt désormais obsolète, mais la modification sera plus difficile à suivre et à comprendre. Il est également possible que cet arrêt resserve ultérieurement ou bien encore qu'il apparaisse dans d'autres bases de données exploitées par d'autres systèmes. Une simple modification de nom générerait alors de l’ambiguïté et des problèmes potentiels d'exploitations de ces données.
+
+Dans le cas où il s'agit bien du même arrêt mais qui change soit de nom, soit de localisation, la modification est effectivement la marche à suivre. Il est conseillé de noter ces modifications en commentaire. En effet, il n'est pas rare qu'un même arrêt partagé par plusieurs réseaux possède plusieurs noms commerciaux et qu'un changement de nom ne soit pas connu de tous les partenaires transports. Annoter les modifications dans CHOUETTE facilitera la levée des ambiguïtés.
+
+h3. Vérifier la cohérence des données de géolocalisation
+
+L'une des erreurs les plus fréquentes sont les erreurs de géolocalisation. Dès lors qu'un arrêt fait partie d'une ligne, des vérifications automatiques seront menées, notamment pour vérifier que l'arrêt est effectivement géolocalisé et qu'il n'y a pas de distance aberrante entre deux arrêts. Une vérification visuelle permet également de vérifier la cohérence des données :
+
+* L'arrêt est-il bien placé sur une voirie sur le fond cartographique ?
+* Les arrêts sont-ils bien placés sur la bonne commune ?
+* La séquence d'arrêt visible depuis l'interface des lignes dessine-t-elle un trajet cohérent ?
+
diff --git a/app/views/help/temporaryline.textile b/app/views/help/temporaryline.textile
new file mode 100644
index 000000000..6b71a0748
--- /dev/null
+++ b/app/views/help/temporaryline.textile
@@ -0,0 +1,23 @@
+---
+layout: default
+title: Itinéraire valables le temps d'une saison
+---
+
+h3. Nouvelle ligne ou nouvelle séquence d'arrêts
+
+Certains réseaux mettent parfois en œuvre des lignes spécifiques à un événement saisonnier. C'est par exemple le cas des services destinés aux touristes pendant la saison estivale. Plusieurs cas sont possibles pour ces nouvelles lignes :
+
+* Il s'agit d'une ligne à part entière disposant de son propre nom
+* Il s'agit d'un service rattaché à une ligne commerciale existante, même si l'itinéraire est différent.
+
+Le traitement de cette nouvelle ligne se fera en accord avec le type de cas rencontré. Dans le premier cas, une nouvelle ligne devra être créée avec des calendriers adaptés. Ce faisant, il faudra anticiper l'emploi de la base de donnée dans les systèmes situés en aval de CHOUETTE. S'il s'agit par exemple d'un site internet, une nouvelle ligne, dotée d'identifiants neptune spécifique nécessitera une prise en compte dans le site internet avec probablement un macaron spécifique.
+
+Dans le second cas, la définition d'une séquence d'arrêts spécifique permettra de traiter le cas particulier au sein d'une même ligne, même si les itinéraires sont très différents des trajets commerciaux. Créer une séquence d'arrêt spécifique est préférable à la création d'une nouvelle ligne qui porterait un suffixe "été" par exemple car les identifiants de la ligne seront les mêmes et l'intégration de ce nouveau parcours au sein de la ligne dans les systèmes exploitant la base de données se fera plus facilement.
+
+L'avantage de pouvoir définir autant de séquences d'arrêts que nécessaire, est de pouvoir traiter tous les cas spécifiques sans alourdir les données du cas standard.
+
+h3. Création de calendriers spécifiques
+
+Outre la création d'une nouvelle séquence d'arrêts et des parcours afférents, il convient également de créer des calendriers adaptés. Ces lignes dont la durée de vie est limitée dans le temps doivent disposer de leurs propres calendriers dont la date d'expiration permettra leur désactivation automatique à l'échéance prévue. Il ne sera en conséquence pas nécessaire de faire une mise à jour pour prendre en compte la fin de validité de ces lignes.
+
+Le choix du nom de ces calendriers ainsi que l'usage d’étiquettes spécifiques, comme par exemple une étiquette _"Ligne été"_ permettra une meilleure lisibilité de l'offre dans CHOUETTE. \ No newline at end of file
diff --git a/app/views/help/time_tables.textile b/app/views/help/time_tables.textile
index 87e04b37f..114b0509f 100644
--- a/app/views/help/time_tables.textile
+++ b/app/views/help/time_tables.textile
@@ -11,46 +11,57 @@ Les calendriers d'application sont donc définis indépendamment des lignes, à
La manière de définir un calendrier d'application est restreinte.
Les calendriers sont caractérisés par :
-* une liste de quantièmes (jours calendaires dans l'année)
+* une liste de jours calendaires dans l'année
* une liste de jours d'application (lundis, mardis, etc.)
-* une liste de périodes sur lesquelles s'appliquent les jours d'application
+* une liste de plages de dates sur lesquelles s'appliquent les jours d'application
+* une liste de dates à exclure des périodes.
-L'utilisateur doit donc faire attention au nommage de ses différents calendriers d'application.
+L'utilisateur doit faire attention au nommage de ses différents calendriers d'application, car il doit gérer un calendrier pour chaque cas de courses. Ainsi, si au sein d'une même ligne, il existe des courses fonctionnant du lundi au vendredi et d'autres les samedis, dimanche et fêtes sur la même période de temps, il faudra deux calendriers pour couvrir les deux cas.
Plusieurs courses peuvent référencer le même calendrier.
Ainsi, il est possible de construire des calendriers d'application qui sont ensuite référencés par des courses de lignes différentes.
+Une même course peut également posséder plusieurs calendriers. Ainsi, si une ligne possède des courses fonctionnant du lundi au vendredi, d'autres fonctionnant les samedis dimanches et fêtes et d'autre fonctionnant tous les jours, le troisième type de course ne nécessitera pas une période spécifique, lui associer les deux calendriers permettra de définir son fonctionnement.
+
+!2014-10-31_120428.png! Définition d'un calendrier
+
+h3. Étiquettes
+
+Afin de faciliter la gestion des calendriers qui peuvent être nombreux, CHOUETTE permet d'identifier les calendriers par une ou plusieurs étiquettes. L'auto-complétion permet de choisir des étiquettes déjà existantes pour les associer au calendrier. Une nouvelle étiquette peut être créée à tout moment en saisissant un nouveau texte et en tapant sur _"entrée"_. Les étiquettes permettent ensuite de faire des recherches au sein des calendriers sur ces étiquettes.
+
+!2014-10-31_120905.png! Exemple d'étiquette
+
h3. Attributs
-- Commentaire := Description du calendrier
-- Version := version du calendrier (différent de la version de l'objet)
-- Jours d'application := jours de la semaine effectivement applicables dans le cas où des périodes sont définies dans le calendrier
-- Périodes d'application := périodes calendaires durant lesquelles le calendrier est applicable
-- Dates d'application :=
-dates spécifiques pour lesquelles le calendrier est applicable;
-ces dates peuvent être ajoutées dans ou en dehors des périodes calendaires.
-Un calendrier peut n'avoir que des dates calendaires, auquel cas les jours d'applications n'ont pas de signification
-=:
+* Nom : Description du calendrier
+* Abréviation : Code abrégé
+* Étiquettes : Marqueurs caractérisant le calendrier (pour simplifier la recherche). Afin d'être enregistrées, les étiquettes doivent être saisies séparées par une ',' (virgule) et la touche 'tab' permet d'activer la dernière. Un assistant propose les étiquettes déjà saisies sur d'autres calendriers.
+* Périodes d'application : périodes calendaires durant lesquelles le calendrier est applicable
+* Jours d'application : jours de la semaine effectivement applicables dans le cas où des périodes sont définies dans le calendrier
+* Dates particulières : dates spécifiques pour lesquelles le calendrier est applicable ; ces dates peuvent être ajoutées dans ou en dehors des périodes calendaires. Un calendrier peut n'avoir que des dates calendaires, auquel cas les jours d'applications n'ont pas de signification.
+* Dates exclues : dates spécifiques à retirer des dates définies par les périodes et les jours d'application ; une même date calendaire ne peut pas être à la fois particulière et exclue;
+une date exclue hors périodes et jours d'application n'a aucun effet.
+
+h3. Opérations particulières
+
+Lors de la consultation d'un calendrier, 2 opérations particulières sont disponibles : *Dupliquer* et *Combiner*
+
+h4. Duplication
-p(attr_data). Données de gestion :
+La duplication d'un calendrier consiste à créer un calendrier copie conforme du calendrier consulté à l'exception du nom et de l'identifiant Neptune
-- Identifiant Neptune :=
-clé unique pérenne identifiant le réseau pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
+* le nom est précédé de "Copie de"
+* l'identifiant Neptune est complété par un numéro secondaire "_n" où n est la valeur minimale non présente dans l'Espace de données.
-* préfixe : clé identifiant un producteur de données unique
-* type = Timetable : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
+Une fois la duplication effectuée, le double est enregistré en base et affiché en mode édition afin de permettre à l'opérateur de l'adapter à ses besoins.
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
+h4. Combinaisons
-h3. Implémentation
+La combinaison de calendriers consiste à modifier le calendrier consulté à l'aide d'un autre; les opérations sont :
-p. TODO
+* ajouter les dates : les dates et périodes du second calendrier sont ajoutées au premier
+* conserver les dates commune : seules les dates et périodes communes aux 2 calendriers sont conservées
+* soustraire les dates : les dates communes aux 2 calendriers sont retirées du premier
+L'opération est effectuée en base et ne nécessite pas d'action de sauvegarde.
diff --git a/app/views/help/toc.textile b/app/views/help/toc.textile
index a88d73afd..ffe99da9d 100644
--- a/app/views/help/toc.textile
+++ b/app/views/help/toc.textile
@@ -1,38 +1,45 @@
----
-layout: default
-title: Sommaire
----
-
-h3. Sommaire
-
-# "Généralités":introduction
-## "Normalisation":normalisation
-## "Documentation":documentation
-## "Vue d'ensemble":schema
-## "Pré-requis":prerequisite
-# "Utilisateurs et Organisations":users
-# "Espaces de données":dataspaces
-# "Réseaux":networks
-# "Groupes de lignes":group_of_lines
-# "Transporteurs":companies
-# "Lignes":lines
-## "Séquences d'arrêts":routes
-## "Missions":journey_patterns
-## "Courses/Horaires":vehicle_journeys
-# "Arrêts":stop_areas
-## "Correspondances":connection_links
-## "Accès":access_points
-## "Liens Arrêts-Accès":access_links
-# "Calendriers d'application":time_tables
-# Outils
-## "Imports":imports
-## "Exports":exports
-## "Validation":validations
-## "Jeux de paramètres":parametersets
-# Divers
-## "Tutoriel/Démonstrateur":tutorial
-## "API Rest":restapis
-## "Export KML":kml_exports
-## "format d'échange CSV":csv
-## "FAQ":faq
-
+---
+layout: default
+title: Sommaire
+---
+
+h3. Sommaire
+
+# Introduction
+## "Présentation":introduction
+# Accès à Chouette
+## "Choix et paramètres du navigateur":browser
+## "Accéder à l'application":connection
+# Principes de l'interface
+## "Navigation":navigation
+## "Recherche et filtrage":search_filter
+## "Édition et suppression d'un élément":edit
+## "Métadonnées":metadata
+# Données
+## "Espace de données":dataspaces
+## "Réseaux":networks
+## "Transporteurs":companies
+## "Arrêts":stop_areas
+## "Relation de parenté entre arrêts":relationship
+## "Gestion des accès et liens associés":access_points_links
+## "Groupes de lignes":group_of_lines
+## "Lignes":lines
+## "Séquences d'arrêts":routes
+## "Missions":journey_patterns
+## "Courses et horaires":vehicle_journeys
+## "Correspondances":connection_links
+## "Calendrier":time_tables
+# Imports
+## "Imports":imports
+## "Formats d'import":import_formats
+# Exports
+## "Formats d'export normalisé":export_format
+## "Export de données":exports
+# Validations
+## "Paramètres de validation":parametersets
+## "Valider des données":validations
+# Annexes
+## "Créer un réseau à partir de zéro":startingfromscratch
+## "Modification des arrêts d'une ligne":stopsmanagement
+## "Itinéraire valables le temps d'une saison":temporaryline
+## "glossaire":terms
diff --git a/app/views/help/tutorial.textile b/app/views/help/tutorial.textile
deleted file mode 100644
index ff1567272..000000000
--- a/app/views/help/tutorial.textile
+++ /dev/null
@@ -1,15 +0,0 @@
----
-layout: default
-title: Tutoriel / Démonstrateur / Jeux de données
----
-
-Afin que l'utilisateur puisse se familiariser rapidement avec l'environnement de l'outil CHOUETTE, un réseau de transport « fictif » , « Tatrobus », a été créé.
-Ce réseau est composé d'un réseau principal, « LE GRAND RESEAU », et d'un réseau secondaire « LE PETIT METRO » opérés par un transporteur « TATROBUS ».
-Les deux réseaux comprennent plusieurs lignes, qui s'organisent autour d'un référentiel d'arrêts prédéfini qui inclut de nombreux pôles d'échanges.
-Des courses, horaires, missions, Interdictions de Trafic Local et calendriers d'application s'attachant à ces lignes ont également été renseignés.
-
-L'utilisateur a alors la possibilité de découvrir et de modifier à souhait ces éléments afin d'expérimenter les différentes fonctions et possibilités de l'outil CHOUETTE.
-
-La démonstration est disponible en ligne sur "www.chouette.mobi":www.chouette.mobi
-Les données 'Tatrobus' sont disponibles ["ici":http://www.chouette.mobi/docs/]
-A noter également que des données Neptune sont disponibles au format Neptune sous licence open data, cf. par exemple ["ici":http://www.chouette.mobi/docs/] \ No newline at end of file
diff --git a/app/views/help/vehicle_journeys.textile b/app/views/help/vehicle_journeys.textile
index d5186cf57..1c5de220f 100644
--- a/app/views/help/vehicle_journeys.textile
+++ b/app/views/help/vehicle_journeys.textile
@@ -1,39 +1,108 @@
----
-layout: default
-title: Courses
----
-
-h3. Définition
-
-Une *course* décrit le déplacement d'un véhicule de transport public sur une "séquence d'arrêts":routes de la "ligne":lines. La course parcourt les arrêts de la séquence d'arrêts dans l'ordre, sans nécessairement s'arrêter à chacun des arrêts. A chaque arrêt desservi, la course précise l'horaire de passage.
-De plus, la course est rattachée à un nombre variable de "calendriers d'application":time_tables.
-
-h3. Attributs
-
-- Nom := nom de la course
-- Nom public := nom public pour les voyageurs
-- Commentaire := zone de texte libre
-- Mode de transport := mode de transport pour la course; par défaut, c'est le mode de transport de la ligne qui est appliqué
-- Particularité := champs libre pouvant préciser des modes de fonctionnement (TAD par exemple)
-
-p(attr_data). Données de gestion :
-
-- Identifiant Neptune :=
-clé unique pérenne identifiant la course pour les échanges Neptune
-cet identifiant est composé de 3 parties : préfixe:type:id_technique
-
-* préfixe : clé identifiant un producteur de données unique
-* type = VehicleJourney : clé identifiant le type d'objet (valeur imposée)
-* id_technique : valeur identifiant un seul objet d'un type donné pour un même producteur
-
-ce champ obligatoire est automatiquement généré s'il n'est pas renseigné
-il est possible aussi de ne renseigner que l'identifiant technique, auquel cas la valeur sera complétée automatiquement.
-=:
-- Date de création := date à laquelle l'objet a été créé ou modifié pour la dernière fois
-- Version := version de l'objet (auto incrémenté à chaque modification)
-- Créé par := compte utilisateur ayant procédé à la dernière modification
-
-h3. Implémentation
-
-p. TODO
-
+---
+layout: default
+title: Courses et horaires
+---
+h3. Définition
+
+Une *course* décrit le passage d'un véhicule de transport public sur une _"séquence d'arrêts"_ de la _"ligne"_. La course parcourt les arrêts de la séquence d'arrêts dans l'ordre, sans nécessairement s'arrêter à chacun des arrêts. A chaque arrêt desservi, la course précise l'horaire de passage du véhicule.
+
+La course est rattachée à un nombre variable de "calendriers d'application" qui permettent de déterminer si la course est assurée à une date particulière.
+
+h3. Consulter les courses
+
+L'accès à la page des courses se fait depuis la page de la séquence d'arrêts. Dans le menu latéral, cliquer sur _"horaire des courses"_ affiche la page des courses de la séquence d'arrêts courante. Un tableau présente les horaires de passage aux arrêts pour chacune des courses.
+
+Un filtre de recherche permet de sélectionner les courses en fonction de différents critères :
+
+* La mission
+* Les courses sans calendriers
+* Par nom de calendrier
+* Les courses sans horaires
+* Sur l'heure de départ de la course
+
+Dans le tableau des courses, le lien en en-tête de colonne permet de sélectionner un autre séquence d'arrêt de la ligne ce qui permet de passer d'une séquence à l'autre directement sans avoir besoin de revenir à la page de la séquence d'arrêt. Cela permet par exemple d'accéder directement à la séquence d'arrêt retour de la séquence d'arrêt courante.
+
+L'en-tête de chaque course propose un bouton qui permet d'accéder à des fonctions relative à la course :
+
+* Afficher la page de la course pour en consulter le détail ou l'éditer
+* Accéder directement à l'édition des horaires de la course
+* Consulter la mission assurée par la course et accéder directement à sa page.
+* Consulter les calendriers associés à la course et accéder directement à leur page.
+
+!2014-10-31_113958.png! Affichage des raccourcis de modification d'une course
+
+h3. Créer une course
+
+Il n'est possible de créer une course qu'à la condition d'avoir créé une mission au préalable.
+
+La création d'une nouvelle course se fait en cliquant _"Ajouter une course"_ dans le menu latéral. Il est également possible de créer de nouvelles courses par l'import d'un fichier .csv édité dans un tableur.
+
+h4. Ajouter une course depuis CHOUETTE
+
+Le bouton ajouter une course affiche un formulaire permettant de décrire la nouvelle course.
+
+Dans le champ calendrier, saisir quelques lettres du nom d'un calendrier à affecter à la ligne permet d'afficher des propositions issues de l'auto-complétion. L'opération peut être renouvelée autant que nécessaire pour affecter plusieurs calendriers à la course.
+
+Dès lors que la mission est sélectionnée, la liste des arrêts à desservir s'affiche en bas de la page. Elle comprend deux rangées d'horaires, l'un pour le départ, l'autre pour l'arrivée. Pour faciliter la saisie, il est possible de passer d'un champ de saisie horaire avec la touche tabulation et de saisir les données horaires avec le pavé numérique du clavier. Dans le cas où les horaires de départ et d'arrivée à l'arrêt sont confondus, les liens _"Copier vers départs"_ et _"Copier vers arrivée"_ permettent de ne saisir les horaires qu'une seule fois.
+
+!2014-10-31_114336.png! Edition des horaires dans CHOUETTE
+
+h4. Ajouter une course par import .csv
+
+L'import d'une ou plusieurs courses par un fichier .csv permet d'ajouter des courses éditées dans un tableur. La forme du tableau étant très spécifique, il convient de récupérer le modèle en cliquant sur _"Export des horaires aux arrêts"_ puis de compléter les horaires dans le tableur. Le séparateur retenu pour le fichier .csv est le point-virgule. L'export fournit un fichier .zip comprenant le fichier des horaires et les calendrier.
+
+!2014-10-31_114422.png! Import des horaires au format .csv
+
+Les données horaires peuvent être rajoutées dans le fichier .csv, en revanche, il convient de laisser le champ _"id course"- vide. CHOUETTE se chargera de lui attribuer un numéro valide lors de l'import.
+
+L'import du fichier .csv ne concerne que le fichier .csv proprement dit. Importer un fichier .zip identique au fichier exporté, génèrera une erreur.
+
+h3. Modifier une course
+
+Il est possible de modifier une course depuis la bulle accessible en cliquant sur l'en-tête de chaque course ou en cliquant sur _"Modifier cette course"_ depuis la page de la course proprement dite.
+
+Comme pour la création, il est également possible de modifier une course par export / import .csv.
+
+h4. Modification d'une course depuis CHOUETTE
+
+La modification de la course affiche le même formulaire que lors de la création avec les informations déjà renseignées dans les champs. Chacun d'entre-eux est éditable.
+
+Un cadre situé au-dessus de la liste des horaires offre une fonction supplémentaire permettant de décaler la course en calant soit l'horaire de départ, soit l'horaire d'arrivée à un horaire précis. Les temps de parcours inter-arrêts ne sont pas modifiés, la course est simplement décalée dans le temps.
+
+h4. Modification d'une course par import .csv
+
+L'import d'un fichier .csv permet de modifier des courses éditées dans un tableur. Cliquer sur _"export des horaires aux arrêts"_ permet de récupérer le fichier des courses. Les modifications ou même les ajouts de courses seront pris en compte après import dans la base. Le séparateur retenu pour le fichier .csv est le point-virgule. Il ne faut pas saisir _"d'id de course"_ lorsque l'on saisit au travers d'un fichier .csv. CHOUETTE génèrera un numéro valide à l'import. Saisir un numéro fera échouer l'import.
+
+!2014-10-31_114639.png! Saisie d'horaire dans un tableur.
+
+L'export fournit un fichier .zip comprenant le fichier des horaires et les calendrier.
+
+L'import en retour ne concerne que le fichier .csv proprement dit. Importer un fichier .zip identique au fichier exporté, génèrera une erreur.
+
+h4. Cloner une course
+
+Depuis la page d'une course, il est possible de cloner la course en cliquant dans le menu latéral sur _"Cloner la course"_. Une boite de dialogue s'affiche et permet de choisir les paramètres de clonage. Le clonage n'est pas une duplication à l'identique. Il ne permet pas de créer une deuxième course en tout point identique mais de créer une course ayant les mêmes paramètres, les mêmes temps de trajet inter-arrêts mais à un horaire différent comme le fait la fonction de décalage présente au-dessus des horaires de la course.
+
+Contrairement au décalage qui modifie les horaires de la course existante, le clonage crée une nouvelle course avec des horaires différents. Le premier paramètre permet de choisir si on clone la nouvelle course en fonction de l'horaire de départ ou de l'horaire d'arrivée puis de choisir l'horaire exact de clonage.
+
+Deux autres paramètres facultatifs permettent de répéter l'opération "en rafale" sur des bases régulières en définissant l’intervalle entre deux courses et le nombre de copies à effectuer selon cette modalité.
+
+h3. Supprimer une course
+
+La suppression d'une course se fait depuis la page de la course en cliquant sur _"Supprimer cette course"_ dans le menu latéral.
+
+h3. Attributs
+
+* Mission : La mission assurée par la course
+* Numéro : numéro de la course
+* Nom public : nom public pour les voyageurs
+* Identifiant public : identifiant public
+* Commentaire : zone de texte libre
+* Mode de transport : mode de transport pour la course; par défaut, c'est le mode de transport de la ligne qui est appliqué
+* Accessibilité PMR : précise si la course est équipée PMR
+* Transport à la demande : précise si la course est en exploitation à la demande ou pas
+* État de trafic : état de trafic [?]
+* Équipement : équipement [?]
+* Type d'identifiant du véhicule : type d'identifiant du véhicule
+
+
diff --git a/app/views/import_tasks/_fields_gtfs_import.erb b/app/views/import_tasks/_fields_gtfs_import.erb
index 842a24ab7..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("tipsy.hints.import_task.max_distance_for_commercial"), :value => 50 } %>
-<%= form.input :ignore_last_word , :as => :boolean , :input_html => { :title => t("tipsy.hints.import_task.ignore_last_word"), :value => false }%>
-<%= form.input :ignore_end_chars , :as => :number , :input_html => { :title => t("tipsy.hints.import_task.ignore_end_chars"), :value => 0 }%>
-<%= form.input :max_distance_for_connection_link , :as => :number , :input_html => { :title => t("tipsy.hints.import_task.max_distance_for_connection_link"), :value => 100 }%>
+<%= 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 => 0 }%>
diff --git a/app/views/import_tasks/_import_task.erb b/app/views/import_tasks/_import_task.erb
index c65ee591c..7ba2c1058 100644
--- a/app/views/import_tasks/_import_task.erb
+++ b/app/views/import_tasks/_import_task.erb
@@ -1,20 +1,30 @@
-<%= div_for import_task, :class => "clearfix" do %>
- <div class="icon">
- <%= link_to image_tag("import_task-#{import_task.status}.png"), referential_import_task_path(@referential, import_task) %>
+<div id="index_item" class="panel panel-default">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to referential_import_task_path(@referential, import_task), :method => :delete, :data => {:confirm => t('import_tasks.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to( referential_import_task_path(@referential, import_task), :class => "preview", :title => "#{ImportTask.model_name.human.capitalize} #{import_task.name}") do %>
+ <span class="name">
+ <% if import_task.save_requested? %><i class="fa fa-save"></i><% end %> <%= truncate(import_task.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
- <div class="resume">
- <ul class="header clearfix">
- <li class="title"><% if import_task.save_requested? %><i class="fa fa-save"></i><% end %> <%= link_to(import_task.name, referential_import_task_path(@referential, import_task)) %></li>
- <li class="remove"><%= link_to "<i class='fa fa-trash-o'></i>".html_safe, referential_import_task_path(@referential, import_task), :method => :delete, :class => "delete", :data => {:confirm => t('import_tasks.actions.destroy_confirm')} %></li>
- </ul>
- <div class="links">
+ <div class="panel-body">
<p><%= link_to image_tag("icons/file_#{import_task.file_path_extension}.png") + t("import_tasks.show.imported_file"), file_to_import_referential_import_task_path(@referential, import_task) %></p>
<% if import_task.compliance_check_task.present? %>
<p><%= link_to image_tag( compliance_icon( import_task)) + t("import_tasks.compliance_check_task"), referential_compliance_check_task_path(@referential, import_task.compliance_check_task) %></p>
<% end %>
- </div>
+ </div>
+ <div class="panel-footer">
+ <%= import_progress_bar_tag(import_task) %>
<div class="history">
<%= l import_task.created_at, :format => "%d/%m/%Y %H:%M" %> | <%= import_task.user_name %>
</div>
</div>
-<% end %>
+</div>
diff --git a/app/views/import_tasks/_import_tasks.html.erb b/app/views/import_tasks/_import_tasks.html.erb
new file mode 100644
index 000000000..6e3825817
--- /dev/null
+++ b/app/views/import_tasks/_import_tasks.html.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @import_tasks %>
+</div>
+<div class="import_tasks paginated_content">
+ <%= paginated_content @import_tasks %>
+</div>
+<div class="pagination">
+ <%= will_paginate @import_tasks, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/import_tasks/index.html.erb b/app/views/import_tasks/index.html.erb
index f19c84929..ce0149f72 100644
--- a/app/views/import_tasks/index.html.erb
+++ b/app/views/import_tasks/index.html.erb
@@ -1,14 +1,8 @@
<%= title_tag t('.title') %>
<div class="warning"><%= t('.warning') %> </div>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @import_tasks %>
-</div>
-<div class="import_tasks paginated_content">
- <%= paginated_content @import_tasks %>
-</div>
-<div class="pagination">
- <%= will_paginate @import_tasks, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+
+<div id="import_tasks"><%= render 'import_tasks' %></div>
+
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/import_tasks/index.js.erb b/app/views/import_tasks/index.js.erb
new file mode 100644
index 000000000..79679f8ac
--- /dev/null
+++ b/app/views/import_tasks/index.js.erb
@@ -0,0 +1 @@
+$('#import_tasks').html('<%= escape_javascript(render("import_tasks")) %>'); \ No newline at end of file
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/journey_patterns/_form.html.erb b/app/views/journey_patterns/_form.html.erb
index 771283885..361f7f380 100644
--- a/app/views/journey_patterns/_form.html.erb
+++ b/app/views/journey_patterns/_form.html.erb
@@ -5,7 +5,7 @@
<%= form.input :registration_number %>
<%= form.input :comment %>
<%= form.input :stop_point_ids, :label => stop_point_ids_label(@journey_pattern), :as => :check_boxes, :collection => @route.stop_points.map { |s| [s.stop_area.name, s.id.to_s]}, :input_html => (@journey_pattern.new_record? ? { :checked => 'checked' }:{}) %>
- <%= form.input :objectid, :required => !@journey_pattern.new_record? %>
+ <%= form.input :objectid, :required => !@journey_pattern.new_record?, :input_html => { :title => t("formtastic.titles.journey_pattern.objectid")} %>
<% end %>
<%= form.actions do %>
diff --git a/app/views/journey_patterns/_journey_pattern.html.erb b/app/views/journey_patterns/_journey_pattern.html.erb
index 046f87958..1bc34b2e4 100644
--- a/app/views/journey_patterns/_journey_pattern.html.erb
+++ b/app/views/journey_patterns/_journey_pattern.html.erb
@@ -1,16 +1,29 @@
-<%= div_for(journey_pattern) do %>
- <%= link_to journey_name(journey_pattern), [@referential, @line, @route, journey_pattern] %>
- <div class="info">
+<div id="index_item" class="panel panel-default journey_pattern">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to referential_line_route_journey_pattern_path(@referential, @line, @route, journey_pattern), :method => :delete, :data => {:confirm => t('journey_patterns.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, @line, @route, journey_pattern], :class => "preview", :title => "#{Chouette::JourneyPattern.model_name.human.capitalize} #{journey_pattern.name}") do %>
+ <span class="name">
+ <%= truncate(journey_pattern.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
<% unless journey_pattern.stop_points.empty? %>
- <%= t('.from_to', :departure => journey_pattern.stop_points.first.stop_area.name, :arrival => journey_pattern.stop_points.last.stop_area.name) %>
- <% end %><br>
- <%= t('.stop_count', :count => journey_pattern.stop_points.count, :route_count => @route.stop_points.count) %> | <%= t('.vehicle_journeys_count', :count => journey_pattern.vehicle_journeys.count) %>
- <div class="actions">
- <%= link_to t("actions.destroy"), referential_line_route_journey_pattern_path(@referential, @line, @route, journey_pattern), :method => :delete, :data => {:confirm => t('journey_patterns.actions.destroy_confirm')}, :class => "remove" %>
- <% if journey_pattern.vehicle_journeys.count > 0 %>
- | <%= link_to t('journey_patterns.journey_pattern.vehicle_journey_at_stops'), referential_line_route_vehicle_journeys_path(@referential, @line, @route, :q => {:journey_pattern_id_eq => journey_pattern.id}), :class => "link" %>
- <% end %>
- </div>
+ <p><%= t('.from_to', :departure => journey_pattern.stop_points.first.stop_area.name, :arrival => journey_pattern.stop_points.last.stop_area.name) %></p>
+ <% end %>
+ <p><%= t('.stop_count', :count => journey_pattern.stop_points.count, :route_count => @route.stop_points.count) %> | <%= t('.vehicle_journeys_count', :count => journey_pattern.vehicle_journeys.count) %></p>
+ <% if journey_pattern.vehicle_journeys.count > 0 %>
+ <p>
+ <i class="fa fa-clock-o"></i><%= link_to t('journey_patterns.journey_pattern.vehicle_journey_at_stops'), referential_line_route_vehicle_journeys_path(@referential, @line, @route, :q => {:journey_pattern_id_eq => journey_pattern.id}), :class => "with_fa" %>
+ </p>
+ <% end %>
</div>
-<% end %>
-
+</div>
diff --git a/app/views/journey_patterns/edit.html.erb b/app/views/journey_patterns/edit.html.erb
index 33adb6d7d..33fac2a6c 100644
--- a/app/views/journey_patterns/edit.html.erb
+++ b/app/views/journey_patterns/edit.html.erb
@@ -1,17 +1,4 @@
<%= title_tag t('journey_patterns.edit.title', :journey_pattern => @journey_pattern.name ) %>
-<div class="journey_pattern">
- <div class="summary">
- <p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
- <label><%= Chouette::Route.model_name.human %>: </label>
- <%= link_to @route.name, [@referential, @line, @route] %>
- </p>
- <div>
-<div>
-
<%= render "form" %>
diff --git a/app/views/journey_patterns/show.html.erb b/app/views/journey_patterns/show.html.erb
index 1bdd5cc5e..dc9e852fa 100644
--- a/app/views/journey_patterns/show.html.erb
+++ b/app/views/journey_patterns/show.html.erb
@@ -5,14 +5,6 @@
<div class="summary">
<p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
- <label><%= @journey_pattern.human_attribute_name(:route) %>: </label>
- <%= link_to @route.name, [@referential, @line, @route] %>
- </p>
- <p>
<label><%= @journey_pattern.human_attribute_name(:name) %>: </label>
<%= @journey_pattern.name %>
</p>
@@ -28,10 +20,6 @@
<label><%= @journey_pattern.human_attribute_name(:comment) %>: </label>
<%= @journey_pattern.comment %>
</p>
- <p>
- <label><%= @journey_pattern.human_attribute_name("objectid") %>: </label>
- <%= @journey_pattern.objectid %>
- </p>
</div>
</div>
@@ -44,9 +32,10 @@
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('journey_patterns.actions.new'), new_referential_line_route_journey_pattern_path(@referential, @line, @route), :class => "add" %></li>
<li><%= link_to t('journey_patterns.actions.edit'), edit_referential_line_route_journey_pattern_path(@referential, @line, @route, @journey_pattern), :class => "edit" %></li>
<li><%= link_to t('journey_patterns.actions.destroy'), referential_line_route_journey_pattern_path(@referential, @line, @route, @journey_pattern), :method => :delete, :data => {:confirm => t('journey_patterns.actions.destroy_confirm')}, :class => "remove" %></li>
- <li><%= link_to t('journey_patterns.journey_pattern.vehicle_journey_at_stops'), referential_line_route_vehicle_journeys_path(@referential, @line, @route, :q => {:journey_pattern_id_eq => @journey_pattern.id}), :class => "link" %></li>
+ <li><%= link_to t('journey_patterns.journey_pattern.vehicle_journey_at_stops'), referential_line_route_vehicle_journeys_path(@referential, @line, @route, :q => {:journey_pattern_id_eq => @journey_pattern.id}), :class => "clock" %></li>
</ul>
<%= creation_tag(@journey_pattern) %>
<% end %>
diff --git a/app/views/journey_patterns/show.js.erb b/app/views/journey_patterns/show.js.erb
deleted file mode 100644
index aedb0fb9e..000000000
--- a/app/views/journey_patterns/show.js.erb
+++ /dev/null
@@ -1,4 +0,0 @@
-$(function (){
- $(".stop_points_detail").html("<%= escape_javascript(render(:partial => "stop_points_detail")) %>");
-});
-
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 2e4f98c0b..38125e112 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -18,106 +18,18 @@
</head>
<body>
<div id="header">
- <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
- <div class="container">
- <!-- Brand and toggle get grouped for better mobile display -->
- <div class="navbar-header">
- <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
- <span class="sr-only">Toggle navigation</span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar version"><%= APP_VERSION %></span>
- </button>
- <%= link_to referentials_path, :class =>"navbar-brand" do %>
- <%= image_tag("logo_chouette.png") %> <span class="version"><%= APP_VERSION %></span>
- <% end %>
- </div>
-
- <!-- Collect the nav links, forms, and other content for toggling -->
- <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
- <ul class="nav navbar-nav">
- <% if selected_referential? %>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= @referential.name %><b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><%= link_to t("layouts.navbar.return_to_referentials"), referentials_path %></li>
- <li class="divider"></li>
- <li role="presentation" class="dropdown-header"><%= t("layouts.navbar.select_referential") %></li>
- <% current_organisation.referentials.each do |referential| %>
- <li>
- <%= link_to @referential.name, referential_path(@referential) %>
- </li>
- <% end %>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= t("layouts.navbar.referential_datas") %><b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><%= link_to referential_networks_path(@referential) do %>
- <%= Referential.human_attribute_name("networks") %><span class="badge pull-right"><%= @referential.networks.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_companies_path(@referential) do %>
- <%= Referential.human_attribute_name("companies") %><span class="badge pull-right"><%= @referential.companies.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_group_of_lines_path(@referential) do %>
- <%= Referential.human_attribute_name("group_of_lines") %><span class="badge pull-right"><%= @referential.group_of_lines.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_lines_path(@referential) do %>
- <%= Referential.human_attribute_name("lines") %><span class="badge pull-right"><%= @referential.lines.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_stop_areas_path(@referential) do %>
- <%= Referential.human_attribute_name("stop_areas") %><span class="badge pull-right"><%= @referential.stop_areas.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_connection_links_path(@referential) do %>
- <%= Referential.human_attribute_name("connection_links") %><span class="badge pull-right"><%= @referential.connection_links.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_time_tables_path(@referential) do %>
- <%= Referential.human_attribute_name("time_tables") %><span class="badge pull-right"><%= @referential.time_tables.size %></span>
- <% end %>
- </li>
- </ul>
- </li>
- <li><%= link_to Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) %></li>
- <li><%= link_to Referential.human_attribute_name("export_tasks"), referential_exports_path(@referential) %></li>
- <li><%= link_to Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) %></li>
- <% end %>
- </ul>
- <ul class="nav navbar-nav navbar-right">
- <li class="<%= language_class('fr') %>"><%= link_to_language :fr %></li>
- <li class="<%= language_class('en') %>"><%= link_to_language :en %></li>
- <li><%= link_to t('layouts.help'), help_path, :class =>("current" if help_page?), :target => "_blank" %></li>
- <% if user_signed_in? %>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="gravatar"><%= user_gravatar_image_tag current_user %></span><%= current_user.name %> <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><%= link_to t('layouts.user.profile'), edit_user_registration_path %></li>
- <li><%= link_to t('layouts.user.sign_out'), destroy_user_session_path, :method => :delete %></li>
- <li class="divider"></li>
- <li><%= tab_link_to Organisation.model_name.human, organisation_path %></li>
- </ul>
- </li>
- <% end %>
- </ul>
- </div><!-- /.navbar-collapse -->
- </div><!-- /.container-fluid -->
- </nav>
+ <%= render partial: "shared/header" %>
</div>
<div id="middle" class="container">
<div class="row">
- <div class="col-md-9">
+ <div class="<%= content_for?(:sidebar) ? 'col-md-9' : 'col-md-12' %>">
<div id="workspace" class="<%= controller_name %> <%= action_name %>">
<%= render partial: "shared/flash_messages", flash: flash %>
+ <%= render partial: "shared/breadcrumb" %>
<%= yield %>
</div>
</div>
- <div id="sidebar" class="col-md-3">
+ <div id="sidebar" class="<%= content_for?(:sidebar) ? 'col-md-3' : '' %>">
<%= yield :sidebar %>
</div>
</div>
diff --git a/app/views/layouts/devise.html.erb b/app/views/layouts/devise.html.erb
new file mode 100644
index 000000000..60c531780
--- /dev/null
+++ b/app/views/layouts/devise.html.erb
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="<%= I18n.locale %>">
+ <head>
+ <title>Chouette V2 - <%= title %></title>
+ <%= stylesheet_link_tag :application %>
+ <%= javascript_include_tag :application %>
+ <% if defined?( @map) %>
+ <script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script>
+ <script src="http://openlayers.org/api/OpenLayers.js"></script>
+ <script type="text/JavaScript">
+ OpenLayers.ImgPath = "<%= polymorphic_path_patch("/assets/openlayers/") %>";
+ </script>
+ <% end %>
+ <%= analytics_init if Rails.env.production? %>
+ <%= csrf_meta_tag %>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
+ </head>
+ <body id="devise">
+ <div id="header">
+ <%= render partial: "shared/header" %>
+ </div>
+ <div class="front_bg">
+ <div id="devise_middle" class="container">
+ <div class="row">
+ <div class="<%= content_for?(:sidebar) ? 'col-md-9' : 'col-md-12' %>">
+ <div id="workspace" class="<%= controller_name %> <%= action_name %>">
+ <%= render partial: "shared/flash_messages", flash: flash %>
+ <%= render partial: "shared/breadcrumb" %>
+ <%= yield %>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="footer">
+ <%= render partial: "shared/footer" %>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/app/views/layouts/without_sidebar.html.erb b/app/views/layouts/without_sidebar.html.erb
deleted file mode 100644
index 948070695..000000000
--- a/app/views/layouts/without_sidebar.html.erb
+++ /dev/null
@@ -1,126 +0,0 @@
-<!DOCTYPE html>
-<html lang="<%= I18n.locale %>">
- <head>
- <title>Chouette V2 - <%= title %></title>
- <%= stylesheet_link_tag :application %>
- <%= javascript_include_tag :application %>
- <% if defined?( @map) %>
- <script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script>
- <script src="http://openlayers.org/api/OpenLayers.js"></script>
- <script type="text/JavaScript">
- OpenLayers.ImgPath = "<%= polymorphic_path_patch("/assets/openlayers/") %>";
- </script>
- <% end %>
- <%= analytics_init if Rails.env.production? %>
- <%= csrf_meta_tag %>
- <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
- </head>
- <body>
- <div id="header">
- <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
- <div class="container">
- <!-- Brand and toggle get grouped for better mobile display -->
- <div class="navbar-header">
- <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
- <span class="sr-only">Toggle navigation</span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar version"><%= APP_VERSION %></span>
- </button>
- <%= link_to referentials_path, :class =>"navbar-brand" do %>
- <%= image_tag("logo_chouette.png") %> <span class="version"><%= APP_VERSION %></span>
- <% end %>
- </div>
-
- <!-- Collect the nav links, forms, and other content for toggling -->
- <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
- <ul class="nav navbar-nav">
- <% if selected_referential? %>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= @referential.name %><b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><%= link_to t("layouts.navbar.return_to_referentials"), referentials_path %></li>
- <li class="divider"></li>
- <li role="presentation" class="dropdown-header"><%= t("layouts.navbar.select_referential") %></li>
- <% current_organisation.referentials.each do |referential| %>
- <li>
- <%= link_to @referential.name, referential_path(@referential) %>
- </li>
- <% end %>
- </ul>
- </li>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= t("layouts.navbar.referential_datas") %><b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><%= link_to referential_networks_path(@referential) do %>
- <%= Referential.human_attribute_name("networks") %><span class="badge pull-right"><%= @referential.networks.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_companies_path(@referential) do %>
- <%= Referential.human_attribute_name("companies") %><span class="badge pull-right"><%= @referential.companies.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_group_of_lines_path(@referential) do %>
- <%= Referential.human_attribute_name("group_of_lines") %><span class="badge pull-right"><%= @referential.group_of_lines.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_lines_path(@referential) do %>
- <%= Referential.human_attribute_name("lines") %><span class="badge pull-right"><%= @referential.lines.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_stop_areas_path(@referential) do %>
- <%= Referential.human_attribute_name("stop_areas") %><span class="badge pull-right"><%= @referential.stop_areas.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_connection_links_path(@referential) do %>
- <%= Referential.human_attribute_name("connection_links") %><span class="badge pull-right"><%= @referential.connection_links.size %></span>
- <% end %>
- </li>
- <li><%= link_to referential_time_tables_path(@referential) do %>
- <%= Referential.human_attribute_name("time_tables") %><span class="badge pull-right"><%= @referential.time_tables.size %></span>
- <% end %>
- </li>
- </ul>
- </li>
- <li><%= link_to Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) %></li>
- <li><%= link_to Referential.human_attribute_name("export_tasks"), referential_exports_path(@referential) %></li>
- <li><%= link_to Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) %></li>
- <% end %>
- </ul>
- <ul class="nav navbar-nav navbar-right">
- <li class="<%= language_class('fr') %>"><%= link_to_language :fr %></li>
- <li class="<%= language_class('en') %>"><%= link_to_language :en %></li>
- <li><%= link_to t('layouts.help'), help_path, :class =>("current" if help_page?), :target => "_blank" %></li>
- <% if user_signed_in? %>
- <li class="dropdown">
- <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="gravatar"><%= user_gravatar_image_tag current_user %></span><%= current_user.name %> <b class="caret"></b></a>
- <ul class="dropdown-menu">
- <li><%= link_to t('layouts.user.profile'), edit_user_registration_path %></li>
- <li><%= link_to t('layouts.user.sign_out'), destroy_user_session_path, :method => :delete %></li>
- <li class="divider"></li>
- <li><%= tab_link_to Organisation.model_name.human, organisation_path %></li>
- </ul>
- </li>
- <% end %>
- </ul>
- </div><!-- /.navbar-collapse -->
- </div><!-- /.container-fluid -->
- </nav>
- </div>
- <div id="middle" class="container">
- <div class="row">
- <div class="col-md-12">
- <div id="workspace" class="<%= controller_name %> <%= action_name %>">
- <%= render partial: "shared/flash_messages", flash: flash %>
- <%= yield %>
- </div>
- </div>
- </div>
- </div>
- <div id="footer">
- <%= render partial: "shared/footer" %>
- </div>
- </body>
-</html>
diff --git a/app/views/lines/_form.erb b/app/views/lines/_form.erb
index c844fbab4..c1f59ed01 100644
--- a/app/views/lines/_form.erb
+++ b/app/views/lines/_form.erb
@@ -5,11 +5,13 @@
<%= form.input :company, :as => :select, :collection => Chouette::Company.all, :include_blank => false%>
<%= form.input :name %>
<%= form.input :published_name %>
- <%= form.input :registration_number %>
+ <%= form.input :registration_number, :input_html => { :title => t("formtastic.titles.line.registration_number")} %>
<%= form.input :number %>
<%= form.input :transport_mode, :as => :select, :collection => Chouette::Line.transport_modes, :include_blank => false, :member_label => Proc.new { |mode| t("transport_modes.label.#{mode}") } %>
+ <%= form.input :mobility_restricted_suitability, :as => :select, :collection => [[@line.human_attribute_name("accessible"), true], [@line.human_attribute_name("not_accessible"), false]], :include_blank => true %>
+ <%= form.input :flexible_service, :as => :select, :collection => [[@line.human_attribute_name("on_demaond_fs"), true], [@line.human_attribute_name("regular_fs"), false]], :include_blank => true %>
<%= form.input :comment %>
- <%= form.input :objectid, :required => !@line.new_record? %>
+ <%= form.input :objectid, :required => !@line.new_record?, :input_html => { :title => t("formtastic.titles.line.objectid")} %>
<% end %>
<%= form.inputs do %>
diff --git a/app/views/lines/_line.erb b/app/views/lines/_line.erb
index 69baacd75..f5606d907 100644
--- a/app/views/lines/_line.erb
+++ b/app/views/lines/_line.erb
@@ -1,27 +1,43 @@
-<%= div_for(line) do %>
- <div><%= link_to([@referential, line], :class => "preview", :title => "#{Chouette::Line.model_name.human.capitalize} #{line.number}") do %></div>
- <div class="color">
- <% if line.number and line.number.length <= 3 %>
- <div class="number"><%= line.number %></div>
- <% end %>
- </div>
- <% end %>
- <div class="name">
- <%= check_box_tag "ids[]", line.id, false, :class => "multiple_selection", :style => "display: none;" %>
- <%= link_to truncate(line.name, :length => 30), [@referential, line], :title => "#{Chouette::Line.model_name.human.capitalize} #{line.name}"%>
+<div id="index_item" class="panel panel-default line">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_line_path(@referential, line), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_line_path(@referential, line), :method => :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= check_box_tag "ids[]", line.id, false, :class => "multiple_selection", :style => "display: none;" %>
+ <% if line.number and line.number.length <= 3 %>
+ <span class="label label-default line_number"><%= line.number %></span>
+ <% end %>
+ <%= link_to([@referential, line], :class => "preview", :title => "#{Chouette::Line.model_name.human.capitalize} #{line.name}") do %>
+ <span class="name">
+ <%= truncate(line.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
- <div class="info">
- <% if line.network.nil? %>
- <%= line.human_attribute_name('network') %> <%= t('lines.index.unset') %>
+ <div class="panel-body">
+ <p>
+ <% if line.network.nil? %>
+ <%= line.human_attribute_name('network') %> <%= t('lines.index.unset') %>
<% else %>
- <%= line.human_attribute_name('network') %> <%= link_to_if line.network, line.network.name, referential_network_path(@referential, line.network), :title => "#{line.human_attribute_name('network')} #{line.network.name}" %><br>
+ <%= line.human_attribute_name('network') %> <%= link_to_if line.network, line.network.name, referential_network_path(@referential, line.network), :title => "#{line.human_attribute_name('network')} #{line.network.name}" %>
<% end %>
+ </p>
+ <p>
<% if line.company.nil? %>
<%= line.human_attribute_name('company') %> <%= t('lines.index.unset') %>
<% else %>
<%= line.human_attribute_name('company') %> <%= link_to_if( line.company, line.company.name, referential_company_path(@referential, line.company), :title => "#{line.human_attribute_name('company')} #{line.company.name}" ) %>
<% end %>
- <br/>
+ </p>
+ <p>
<% if line.group_of_lines.count == 0 %>
<%= t('lines.form.no_group_of_line') %>
<% elsif line.group_of_lines.count == 1 %>
@@ -30,11 +46,6 @@
<% else %>
<%= t('lines.form.several_group_of_lines', :count => line.group_of_lines.count) %>
<% end %>
- <% if @group_of_line.nil? %>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_line_path(@referential, line), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_line_path(@referential, line), :method => :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, :class => "remove" %>
- </div>
- <% end %>
+ </p>
</div>
-<% end %>
+</div>
diff --git a/app/views/lines/_lines.html.erb b/app/views/lines/_lines.html.erb
new file mode 100644
index 000000000..a4d9a3f0b
--- /dev/null
+++ b/app/views/lines/_lines.html.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @lines %>
+</div>
+<div class="lines paginated_content">
+ <%= paginated_content(@lines) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @lines, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/lines/index.html.erb b/app/views/lines/index.html.erb
index edcdbcc9c..ae0cbabf7 100644
--- a/app/views/lines/index.html.erb
+++ b/app/views/lines/index.html.erb
@@ -1,80 +1,36 @@
<%= title_tag t('lines.index.title') %>
-<%= search_form_for @q, :url => referential_lines_path(@referential), :html => {:method => :get} do |f| %>
- <%= f.label :name_or_number_cont, "#{t('.name_or_number')} :" %>
- <%= f.text_field :name_or_number_cont %>
-
- <%= f.hidden_field :company_id_eq %>
- <%= f.hidden_field :network_id_eq %>
- <%= f.hidden_field :group_of_lines_id_eq %>
-
- <%= f.submit t('actions.search') %> <%= t("or") %>
- <%= link_to t("cancel"), referential_lines_path(@referential) %>
-<% end %>
-
-<% if @q.network_id_eq.present? %>
-<p>
- <%= Chouette::Line.human_attribute_name('network') %> : <%= @referential.networks.find(@q.network_id_eq).name %>
-</p>
-<% end %>
-
-<% if @q.company_id_eq.present? %>
-<p>
- <%= Chouette::Line.human_attribute_name('company') %> : <%= @referential.companies.find(@q.company_id_eq).name %>
-</p>
-<% end %>
+<%= search_form_for @q, :url => referential_lines_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-9">
+ <%= f.text_field :name_or_number_cont, :placeholder => "#{t('.name_or_number')}", :class => 'form-control' %>
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <a data-toggle="collapse" data-parent="#search" href="#advanced_search">
+ <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %>
+ </a>
+ </div>
-<% if @q.group_of_lines_id_eq.present? %>
-<p>
- <%= Chouette::Line.human_attribute_name('group_of_line') %> : <%= @referential.group_of_lines.find(@q.group_of_lines_id_eq).name %>
-</p>
+ <div id="advanced_search" class="panel-collapse collapse">
+ <div class="panel-body">
+ <%= f.select(:network_id_eq, @referential.networks.collect {|n| [ n.name, n.id ] }.unshift([t('.no_networks'), -1]), {include_blank: t('.all_networks')}, { :class => 'form-control' }) %>
+ <%= f.select(:company_id_eq, @referential.companies.collect {|c| [ c.name, c.id ] }.unshift([t('.no_companies'), -1]), { include_blank: t('.all_companies')}, { :class => 'form-control' }) %>
+ <%= f.select(:group_of_lines_id_eq, @referential.group_of_lines.collect {|c| [ c.name, c.id ] }.unshift([t('.no_group_of_lines'), -1]), {include_blank: t('.all_group_of_lines')}, { :class => 'form-control' }) %>
+ </div>
+ </div>
+</div>
<% end %>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @lines %>
-</div>
-<div class="lines paginated_content">
- <%= paginated_content(@lines) %>
-</div>
-<div class="pagination">
- <%= will_paginate @lines, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+<div id="lines"><%= render 'lines' %></div>
<% content_for :sidebar do %>
<ul class="actions">
<li><%= link_to t('lines.actions.new'), new_referential_line_path(@referential), :class => "add" %></li>
</ul>
-<h4><%= t(".selection") %></h4>
-
-<h5><%= Chouette::Company.model_name.human.pluralize %></h5>
-
-<ul class="selection">
-<% @referential.companies.each do |company| %>
-<li><%= link_with_search company.name, "company_id_eq" => company.id %></li>
-<% end %>
-<li><%= link_with_search t(".selection_all"), {"company_id_eq" => nil}, :class => "all" %></li>
-</ul>
-
-<h5><%= Chouette::Network.model_name.human.pluralize %></h5>
-
-<ul class="selection">
-<% @referential.networks.each do |network| %>
-<li><%= link_with_search network.name, "network_id_eq" => network.id %></li>
-<% end %>
-<li><%= link_with_search t(".selection_all"), {"network_id_eq" => nil}, :class => "all" %></li>
-</ul>
-
-<% if @referential.group_of_lines.count > 0 %>
- <h5><%= Chouette::GroupOfLine.model_name.human.pluralize %></h5>
- <ul class="selection">
- <% @referential.group_of_lines.each do |group_of_line| %>
- <li><%= link_with_search group_of_line.name, "group_of_lines_id_eq" => group_of_line.id %></li>
- <% end %>
- <li><%= link_with_search t(".selection_all"), {"group_of_lines_id_eq" => nil}, :class => "all" %></li>
- </ul>
-<% end %>
-
<div id="multiple_selection_menu">
<h4><%= t(".multi_selection") %> </h4>
<div class="disabled">
@@ -93,3 +49,5 @@
</div>
<% end %>
+
+
diff --git a/app/views/lines/index.js.erb b/app/views/lines/index.js.erb
new file mode 100644
index 000000000..97595d5e9
--- /dev/null
+++ b/app/views/lines/index.js.erb
@@ -0,0 +1 @@
+$('#lines').html('<%= escape_javascript(render("lines")) %>'); \ No newline at end of file
diff --git a/app/views/lines/show.html.erb b/app/views/lines/show.html.erb
index d62be2066..24eebd794 100644
--- a/app/views/lines/show.html.erb
+++ b/app/views/lines/show.html.erb
@@ -21,10 +21,6 @@
<% end %>
</p>
<p>
- <label><%= @line.human_attribute_name("name") %>: </label>
- <%= @line.name %>
- </p>
- <p>
<label><%= @line.human_attribute_name("published_name") %>: </label>
<%= @line.published_name %>
</p>
@@ -40,13 +36,45 @@
<label><%= @line.human_attribute_name("transport_mode") %>: </label>
<%= t("transport_modes.label.#{@line.transport_mode}") %>
</p>
+
<p>
- <label><%= @line.human_attribute_name("comment") %>: </label>
- <%= @line.comment %>
+ <label><%= @line.human_attribute_name("mobility_restricted_suitability") %> : </label>
+ <% if @line.mobility_restricted_suitability.nil? %>
+ <%= @line.human_attribute_name("unspecified_mrs") %>
+ <% elsif @line.mobility_restricted_suitability? %>
+ <%= @line.human_attribute_name("accessible") %>
+ <% else %>
+ <%= @line.human_attribute_name("not_accessible") %>
+ <% end %>
+ <br>&nbsp;&nbsp;<%= @line.human_attribute_name("number_of_mrs_vj") %> : <%= @line.vehicle_journeys.where("mobility_restricted_suitability = ?", true).count %>
+ <br>&nbsp;&nbsp;<%= @line.human_attribute_name("number_of_non_mrs_vj") %> : <%= @line.vehicle_journeys.where("mobility_restricted_suitability = ?", false).count %>
+ <br>&nbsp;&nbsp;<%= @line.human_attribute_name("number_of_null_mrs_vj") %> : <%= @line.vehicle_journeys.count -
+ (@line.vehicle_journeys.where("mobility_restricted_suitability = ?", true).count +
+ @line.vehicle_journeys.where("mobility_restricted_suitability = ?", false).count) %>
</p>
<p>
- <label><%= @line.human_attribute_name("objectid") %>: </label>
- <%= @line.objectid %>
+ <label><%= @line.human_attribute_name("flexible_service") %> : </label>
+ <% if @line.flexible_service.nil? %>
+ <%= @line.human_attribute_name("unspecified_fs") %>
+ <% elsif @line.flexible_service? %>
+ <%= @line.human_attribute_name("on_demaond_fs") %>
+ <% else %>
+ <%= @line.human_attribute_name("regular_fs") %>
+ <% end %>
+ <br>&nbsp;&nbsp;<%= @line.human_attribute_name("number_of_fs_vj") %> : <%= @line.vehicle_journeys.where("flexible_service = ?", true).count %>
+ <br>&nbsp;&nbsp;<%= @line.human_attribute_name("number_of_non_fs_vj") %> : <%= @line.vehicle_journeys.where("flexible_service = ?", false).count %>
+ <br>&nbsp;&nbsp;<%= @line.human_attribute_name("number_of_null_fs_vj") %>
+ <% if @line.flexible_service.nil? %>
+ (<%= @line.human_attribute_name("default_fs_msg") %>)
+ <% end %>
+ : <%= @line.vehicle_journeys.count -
+ (@line.vehicle_journeys.where("flexible_service = ?", true).count +
+ @line.vehicle_journeys.where("flexible_service = ?", false).count) %>
+ </p>
+
+ <p>
+ <label><%= @line.human_attribute_name("comment") %>: </label>
+ <%= @line.comment %>
</p>
</div>
</div>
@@ -60,14 +88,15 @@
<% if @line.group_of_lines.any? %>
<h3 class="line_group_of_lines"><%= t('.group_of_lines') %></h3>
<div class="group_of_lines paginated_content">
- <%= paginated_content @group_of_lines, "group_of_lines/group_of_line" %>
+ <%= paginated_content @group_of_lines, "group_of_lines/group_of_line", :delete => false %>
</div>
<% end %>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('lines.actions.new'), new_referential_line_path(@referential), :class => "add" %></li>
<li><%= link_to t('lines.actions.edit'), edit_referential_line_path(@referential, @line), :class => "edit" %></li>
- <li><%= link_to t('lines.actions.destroy'), referential_line_path(@referential, @line), :method => :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, :class => "remove" %></li>
+ <li><%= link_to t('lines.actions.destroy'), referential_line_path(@referential, @line), :method => :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, :class => "remove" %></li>
<li><%= link_to t('routes.actions.new'), new_referential_line_route_path(@referential, @line), :class => "add" %></li>
</ul>
<%= creation_tag(@line) %>
diff --git a/app/views/lines/show.kml.erb b/app/views/lines/show.kml.erb
index 1ea08fa5a..8e1c82eef 100644
--- a/app/views/lines/show.kml.erb
+++ b/app/views/lines/show.kml.erb
@@ -5,6 +5,7 @@
<Placemark id="<%= stop_area.id %>" >
<name><%= stop_area.name %></name>
<stop_area_type><%= stop_area.area_type.underscore %></stop_area_type>
+ <stop_area_type_label><%= t("area_types.label.#{stop_area.stop_area_type}") %></stop_area_type_label>
<%= (stop_area.position or stop_area.default_position).kml_representation.html_safe %>
</Placemark>
<% end %>
diff --git a/app/views/networks/_form.erb b/app/views/networks/_form.erb
index 61b52a6a4..bb87d9e46 100644
--- a/app/views/networks/_form.erb
+++ b/app/views/networks/_form.erb
@@ -1,13 +1,13 @@
<%= semantic_form_for [@referential, @network] do |form| %>
<%= form.inputs do %>
<%= form.input :name %>
- <%= form.input :registration_number %>
+ <%= form.input :registration_number, :input_html => { :title => t("formtastic.titles.network.registration_number")} %>
<%= form.input :comment %>
<%= form.input :version_date, :as => :date_picker %>
<%= form.input :description %>
<%= form.input :source_name %>
<%= form.input :source_identifier %>
- <%= form.input :objectid, :required => !@network.new_record? %>
+ <%= form.input :objectid, :required => !@network.new_record?, :input_html => { :title => t("formtastic.titles.network.objectid")} %>
<% end %>
<%= form.actions do %>
diff --git a/app/views/networks/_network.erb b/app/views/networks/_network.erb
index 9ae53650e..618e39b72 100644
--- a/app/views/networks/_network.erb
+++ b/app/views/networks/_network.erb
@@ -1,9 +1,21 @@
-<%= div_for(network) do %>
- <%= link_to network.name, [@referential, network] %>
- <div class="info">
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_network_path(@referential, network), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_network_path(@referential, network), :method => :delete, :data => {:confirm => t('networks.actions.destroy_confirm')}, :class => "remove" %>
- </div>
+<div id="index_item" class="panel panel-default network">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_network_path(@referential, network), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_network_path(@referential, network), :method => :delete, :data => {:confirm => t('networks.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, network], :class => "preview", :title => "#{Chouette::Network.model_name.human.capitalize} #{network.name}") do %>
+ <span class="name">
+ <%= truncate(network.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
-<% end %>
+</div>
diff --git a/app/views/networks/_networks.erb b/app/views/networks/_networks.erb
new file mode 100644
index 000000000..9d95d63b6
--- /dev/null
+++ b/app/views/networks/_networks.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @networks %>
+</div>
+<div class="networks paginated_content">
+ <%= paginated_content(@networks) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @networks, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/networks/index.html.erb b/app/views/networks/index.html.erb
index 704d9e9bb..e093a258c 100644
--- a/app/views/networks/index.html.erb
+++ b/app/views/networks/index.html.erb
@@ -1,25 +1,22 @@
<%= title_tag t('networks.index.title') %>
-<div class="container-fluid">
- <form class="navbar-form navbar-left" role="search">
- <%= search_form_for @q, :url => referential_networks_path(@referential), :html => {:method => :get} do |f| %>
- <div class="form-group">
- <%= f.text_field :name_cont, :class => "form-control", :placeholder => "#{t('.name')}" %>
- </div>
- <%= f.submit t('actions.search'), :class => "btn btn-default" %> <%= t("or") %>
- <%= link_to t("cancel"), referential_networks_path(@referential) %>
- <% end %>
- </form>
-</div>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @networks %>
-</div>
-<div class="networks paginated_content">
- <%= paginated_content(@networks) %>
-</div>
-<div class="pagination">
- <%= will_paginate @networks, :container => false, renderer: BootstrapPagination::Rails %>
+<%= search_form_for @q, :url => referential_networks_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-12">
+ <%= f.text_field :name_cont, :placeholder => "#{t('.name')}", :class => "form-control" %>
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <!-- <a data-toggle="collapse" data-parent="#search" href="#advanced_search"> -->
+ <!-- <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %> -->
+ <!-- </a> -->
+ </div>
</div>
+<% end %>
+
+<div id="networks"><%= render 'networks' %></div>
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/networks/index.js.erb b/app/views/networks/index.js.erb
new file mode 100644
index 000000000..43d9ce10c
--- /dev/null
+++ b/app/views/networks/index.js.erb
@@ -0,0 +1 @@
+$('#networks').html('<%= escape_javascript(render("networks")) %>'); \ No newline at end of file
diff --git a/app/views/networks/show.html.erb b/app/views/networks/show.html.erb
index 273a04aed..e7b103dda 100644
--- a/app/views/networks/show.html.erb
+++ b/app/views/networks/show.html.erb
@@ -4,10 +4,6 @@
<%= @map.to_html %>
<div class="summary">
<p>
- <label><%= Chouette::Network.human_attribute_name("name") %>: </label>
- <%= @network.name %>
- </p>
- <p>
<label><%= Chouette::Network.human_attribute_name("registration_number") %>: </label>
<%= @network.registration_number %>
</p>
@@ -33,15 +29,12 @@
<label><%= Chouette::Network.human_attribute_name("source_identifier") %>: </label>
<%= @network.source_identifier %>
</p>
- <p>
- <label><%= Chouette::Network.human_attribute_name("objectid") %>: </label>
- <%= @network.objectid %>
- </p>
</div>
</div>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('networks.actions.new'), new_referential_network_path(@referential), :class => "add" %></li>
<li><%= link_to t('networks.actions.edit'), edit_referential_network_path(@referential, @network), :class => "edit" %></li>
<li><%= link_to t('networks.actions.destroy'), referential_network_path(@referential, @network), :method => :delete, :data => {:confirm => t('networks.actions.destroy_confirm')}, :class => "remove" %></li>
<br>
diff --git a/app/views/networks/show.kml.erb b/app/views/networks/show.kml.erb
index c99b46a7a..34d4598fe 100644
--- a/app/views/networks/show.kml.erb
+++ b/app/views/networks/show.kml.erb
@@ -5,6 +5,7 @@
<Placemark id="<%= stop_area.id %>" >
<name><%= stop_area.name %></name>
<stop_area_type><%= stop_area.area_type.underscore %></stop_area_type>
+ <stop_area_type_label><%= t("area_types.label.#{stop_area.stop_area_type}") %></stop_area_type_label>
<%= (stop_area.position or stop_area.default_position).kml_representation.html_safe %>
</Placemark>
<% end %>
diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb
index 263933bc1..c67eeb271 100644
--- a/app/views/organisations/show.html.erb
+++ b/app/views/organisations/show.html.erb
@@ -5,14 +5,8 @@
</p>
</div>
-<div class="users">
- <% @organisation.users.each do |user| %>
- <%= div_for user do %>
- <%= user_gravatar_image_tag user %>
- <%= link_to user.name, organisation_user_path(user) %>
- <div class="info"><%= user.email %></div>
- <% end %>
- <% end %>
+<div class="users paginated_content">
+ <%= paginated_content(@organisation.users, "users/user") %>
</div>
<% content_for :sidebar do %>
diff --git a/app/views/referentials/_clean.html.erb b/app/views/referentials/_clean.html.erb
index ff2cf1185..995b7644d 100644
--- a/app/views/referentials/_clean.html.erb
+++ b/app/views/referentials/_clean.html.erb
@@ -1,7 +1,7 @@
<div id="clean_up" >
<%= semantic_form_for [@referential, CleanUp.new] do |form| %>
<%= form.inputs do %>
- <%= form.input :expected_date, :as => :date_picker , :wrapper_html => { :class => 'date' }%>
+ <%= form.input :expected_date, :as => :date_picker , :wrapper_html => { :class => 'date', :title => t('titles.clean_up.expected_date') } %>
<%= form.input :keep_lines, :as => :boolean %>
<%= form.input :keep_stops, :as => :boolean %>
<%= form.input :keep_companies, :as => :boolean %>
diff --git a/app/views/referentials/_form.erb b/app/views/referentials/_form.erb
index 60f5cacf3..814195dde 100644
--- a/app/views/referentials/_form.erb
+++ b/app/views/referentials/_form.erb
@@ -2,18 +2,18 @@
<%= form.inputs do %>
<%= form.input :name %>
<% if @referential.new_record? %>
- <%= form.input :slug%>
+ <%= form.input :slug, :input_html => { :title => t("formtastic.titles.referential.slug")}%>
<% else %>
<li class="input">
<label class="label" ><%= @referential.human_attribute_name("slug") %></label>
<%= @referential.slug %>
</li>
<% end %>
- <%= form.input :prefix %>
+ <%= form.input :prefix, :input_html => { :title => t("formtastic.titles.referential.prefix")} %>
<%= form.input :projection_type, :as => :select, :collection => Referential.available_srids %>
<%= form.input :time_zone %>
- <%= form.input :upper_corner %>
- <%= form.input :lower_corner %>
+ <%= form.input :upper_corner, :input_html => { :title => t("formtastic.titles.referential.upper_corner")} %>
+ <%= form.input :lower_corner, :input_html => { :title => t("formtastic.titles.referential.lower_corner")} %>
<% end %>
<%= form.actions do %>
diff --git a/app/views/referentials/_referential.erb b/app/views/referentials/_referential.erb
index 3bc6fd0dc..1f985bc65 100644
--- a/app/views/referentials/_referential.erb
+++ b/app/views/referentials/_referential.erb
@@ -1,14 +1,36 @@
-<%= div_for(referential) do %>
- <%= link_to referential.name, referential %>
- <div class="info">
- <%= referential.human_attribute_name('lines') %>: <span class="lines_count"></span> -
- <%= referential.human_attribute_name('networks') %>: <span class="networks_count"></span> -
- <%= referential.human_attribute_name('vehicle_journeys') %>: <span class="vehicle_journeys_count"></span> -
- <%= referential.human_attribute_name('time_tables') %>: <span class="time_tables_count"></span>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_path(referential), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_path(referential), :method => :delete, :data => {:confirm => t('referentials.actions.destroy_confirm')}, :class => "remove" %>
- </div>
+<div id="index_item" class="panel panel-default referential">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_path(referential), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_path(referential), :method => :delete, :data => {:confirm => t('referentials.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, referential], :class => "preview", :title => "#{Referential.model_name.human.capitalize} #{referential.name}") do %>
+ <span class="name">
+ <%= truncate(referential.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
</div>
+ <div id="referential_<%= referential.id %>" class="panel-body">
+ <p>
+ <%= referential.human_attribute_name('lines') %>: <span class="lines_count"></span>
+ </p>
+ <p>
+ <%= referential.human_attribute_name('networks') %>: <span class="networks_count"></span>
+ </p>
+ <p>
+ <%= referential.human_attribute_name('vehicle_journeys') %>: <span class="vehicle_journeys_count"></span>
+ </p>
+ <p>
+ <%= referential.human_attribute_name('time_tables') %>: <span class="time_tables_count"></span>
+ </p>
+ </div>
+</div>
<%= javascript_include_tag referential_path(referential,:format => :js) %>
-<% end %>
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/referentials/show.html.erb b/app/views/referentials/show.html.erb
index 5286f7ee7..d8e209c7f 100644
--- a/app/views/referentials/show.html.erb
+++ b/app/views/referentials/show.html.erb
@@ -42,11 +42,12 @@
</tr>
</table>
- <h3 class="api_keys"><%= t('.api_keys') %></h3>
-
- <div class="api_keys">
- <%= render :partial => "api_keys/api_key", :collection => @referential.api_keys %>
+ <% if @referential.api_keys.present? %>
+ <h3 class="api_keys"><%= t('.api_keys') %></h3>
+ <div class="api_keys paginated_content">
+ <%= paginated_content(@referential.api_keys, "api_keys/api_key") %>
</div>
+ <% end %>
</div>
<% content_for :sidebar do %>
diff --git a/app/views/referentials/show.js.erb b/app/views/referentials/show.js.erb
index d44962b14..05b623b93 100644
--- a/app/views/referentials/show.js.erb
+++ b/app/views/referentials/show.js.erb
@@ -1,25 +1,25 @@
-$(document).ready(function() {
+$(function (){
+ var ref, update_infos, update_referential_details, _i, _len, _ref, _results;
- jQuery(function() {
-var ref, update_infos, update_referential_details, _i, _len, _ref, _results;
-update_infos = function(json) {
-var info, update_info;
-info = $('#referential_' + json.referential_id + ' .info');
-update_info = function(key, value) {
-if (key.match(/_count$/)) {
-return $(info.find('.' + key)[0]).text(value);
-}
-};
-return $.each(json, update_info);
-};
-update_referential_details = function() {
-return $.getJSON("<%= referential_path(@referential, :format => :json) %>", update_infos);
-};
+ update_infos = function(json) {
+ var info, update_info;
+ info = $('#referential_' + json.referential_id);
+ console.log(info)
+ update_info = function(key, value) {
+ if (key.match(/_count$/)) {
+ return $(info.find('.' + key)[0]).text(value);
+ }
+ };
+ return $.each(json, update_info);
+ };
+
+ update_referential_details = function() {
+ return $.getJSON("<%= referential_path(@referential, :format => :json) %>", update_infos);
+ };
-_results = [];
-_results.push(update_referential_details());
+ _results = [];
+ _results.push(update_referential_details());
-return _results;
-});
+ return _results;
});
diff --git a/app/views/routes/_form.html.erb b/app/views/routes/_form.html.erb
index 508593d07..658fda0ae 100644
--- a/app/views/routes/_form.html.erb
+++ b/app/views/routes/_form.html.erb
@@ -7,15 +7,17 @@
<%= form.input :opposite_route, :as => :select, :collection => @line.routes.select { |r| r.id != @route.id } %>
<%= form.input :direction_code, :as => :select, :collection => Chouette::Route.directions, :include_blank => false, :member_label => Proc.new { |mode| t("directions.label.#{mode}") } %>
<%= form.input :wayback_code, :as => :select, :collection => Chouette::Route.waybacks, :include_blank => false, :member_label => Proc.new { |mode| t("waybacks.label.#{mode}") } %>
- <%= form.input :objectid, :required => !@route.new_record?%>
+ <%= form.input :objectid, :required => !@route.new_record?, :input_html => { :title => t("formtastic.titles.route.objectid")}%>
<% end %>
<div id="stop_points">
<%= form.semantic_fields_for :stop_points, :include_id => false, :label => "TOTO" do |p| %>
<%= render "stop_point_fields", :f => p, :test1 => "oiuoiu" %>
<% end %>
- <div class="links">
+ <div class="links">
<%= link_to_add_association t("routes.actions.add_stop_point"), form, :stop_points, :class => 'add_stop_point' %>
- </div>
+ <br/>
+ <%= link_to t('routes.actions.new_stop_point'), new_referential_stop_area_path(@referential), {:class => "add", :target => "_blank"} %>
+ </div>
</div>
<%= form.actions do %>
@@ -63,8 +65,10 @@ var stop_area_selection_token_input = function( element ) {
minChars: 3,
hintText: '<%= t('search_hint') %>',
noResultsText: '<%= t('no_result_text') %>',
- searchingText: '<%= t('searching_term') %>' }
- );
+ searchingText: '<%= t('searching_term') %>',
+ resultsFormatter: function(item){ return '<li><div class=\"name\">' + item.name + '</div><div class=\"info\">' + item.area_type + '</div><div class=\"info\">' + item.zip_code + ' ' + item.city_name + '</div></li>' },
+ tokenFormatter: function(item) { return '<li><p>' + item.name + '</p></li>' }
+ });
};
$(document).ready( function() {
diff --git a/app/views/routes/_route.html.erb b/app/views/routes/_route.html.erb
index 79064ed97..0fee47cd1 100644
--- a/app/views/routes/_route.html.erb
+++ b/app/views/routes/_route.html.erb
@@ -1,16 +1,28 @@
-<%= div_for(route) do %>
-<div class="header">
- <% if ( route.wayback_code ) %>
- <%= fonticon_wayback(route.wayback) %>
- <% end %>
- <%= link_to route.name, referential_line_route_path( @referential, @line, route) %>
- <% if route.wayback_code %>
- <span class="wayback"><%= route.human_attribute_name('wayback_code') %> <%= (route.wayback=="A") ? t('.wayback.positive') : t('.wayback.negative') %></span>
- <% end %>
-</div>
-<div class="clearfix"></div>
-<div class="body">
- <p>
+<div id="index_item" class="panel panel-default route">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_line_route_path(@referential, @line, route), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_line_route_path(@referential, @line, route), :method => :delete, :data => {:confirm => t('routes.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, @line, route], :class => "preview", :title => "#{Chouette::Route.model_name.human.capitalize} #{route.name}") do %>
+ <span class="name">
+ <% if ( route.wayback_code ) %>
+ <%= fonticon_wayback(route.wayback) %>
+ <% end %>
+ <%= truncate(route.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
+ <p>
<% if route.journey_patterns.size > 0 %>
<i class="fa fa-clock-o"></i><%= link_to t("vehicle_journeys.actions.index"), referential_line_route_vehicle_journeys_path(@referential, @line, route) %>
<% else %>
@@ -19,7 +31,7 @@
</p>
<p>
<% if route.opposite_route %>
- <%= fonticon_wayback(route.opposite_route.wayback) %><%= link_to route.opposite_route.name, referential_line_route_path( @referential, @line, route.opposite_route) %> [<%= t('.opposite') %>]
+ <%= fonticon_wayback(route.opposite_route.wayback) %><%= link_to truncate(route.opposite_route.name, :length => 30), referential_line_route_path( @referential, @line, route.opposite_route) %>
<% else %>
<%= t('.no_opposite') %>
<% end %>
@@ -31,6 +43,5 @@
<br>
<% end %>
</p>
+ </div>
</div>
-<% end %>
-
diff --git a/app/views/routes/_stop_point_fields.html.erb b/app/views/routes/_stop_point_fields.html.erb
index bc9d4e8db..e8b18fa87 100644
--- a/app/views/routes/_stop_point_fields.html.erb
+++ b/app/views/routes/_stop_point_fields.html.erb
@@ -5,7 +5,7 @@
<% if f.object.stop_area.nil? || f.object.new_record? %>
<%= f.input :id, :as => :hidden, :input_html => { :class => "stop_point_id added_stop_point", :value => "" } %>
<%= f.input :position, :as => :hidden, :input_html => { :class => "position" } %>
- <% data_pre = (f.object.stop_area.nil?) ? [] : [ :id => f.object.stop_area.id, :name => "#{f.object.stop_area.name} #{f.object.stop_area.country_code}" ] %>
+ <% data_pre = (f.object.stop_area.nil?) ? [] : [ :id => f.object.stop_area.id, :name => "#{f.object.stop_area.name}" ] %>
<%= f.input :stop_area_id, :label => false, :input_html => { :class => "new_stop_point stop_area_id", :"data-pre" => data_pre.to_json } %>
<% else %>
<%= f.input :id, :as => :hidden, :input_html => { :class => "stop_point_id" } %>
diff --git a/app/views/routes/_stop_points_detail.html.erb b/app/views/routes/_stop_points_detail.html.erb
deleted file mode 100644
index 6c9e4afae..000000000
--- a/app/views/routes/_stop_points_detail.html.erb
+++ /dev/null
@@ -1,10 +0,0 @@
- <div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.list") %></span> <%= page_entries_info @stop_points %>
- </div>
- <div class="stop_points paginated_content">
- <%= render :partial => "stop_points/stop_point", :collection => @stop_points %>
- </div>
- <div class="pagination">
- <%= will_paginate @stop_points, :container => false %>
- </div>
-
diff --git a/app/views/routes/show.html.erb b/app/views/routes/show.html.erb
index c36ce0e94..fe1a9c956 100644
--- a/app/views/routes/show.html.erb
+++ b/app/views/routes/show.html.erb
@@ -5,10 +5,6 @@
<div class="summary">
<p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
<label><%= @route.human_attribute_name(:name) %>: </label>
<%= @route.name %>
</p>
@@ -48,10 +44,6 @@
<%= t(".no_opposite_route") %>
<% end %>
</p>
- <p>
- <label><%= @route.human_attribute_name("objectid") %>: </label>
- <%= @route.objectid %>
- </p>
</div>
</div>
@@ -69,7 +61,9 @@
</div>
<div id="stop_points" class="panel-collapse collapse">
<div class="panel-body">
- <%= render :partial => "stop_points_detail" %>
+ <div class="stop_points paginated_content">
+ <%= paginated_content( @stop_points, "stop_points/stop_point") %>
+ </div>
</div>
</div>
</div>
@@ -86,7 +80,9 @@
</div>
<div id="journey_patterns" class="panel-collapse collapse">
<div class="panel-body">
- <%= render :partial => "journey_patterns/journey_pattern", :collection => @route.journey_patterns %>
+ <div class="journey_patterns paginated_content">
+ <%= paginated_content( @route.journey_patterns, "journey_patterns/journey_pattern") %>
+ </div>
</div>
</div>
</div>
@@ -94,21 +90,19 @@
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('routes.actions.new'), new_referential_line_route_path(@referential, @line), :class => "add" %></li>
<li><%= link_to t('routes.actions.edit'), edit_referential_line_route_path(@referential, @line, @route), :class => "edit" %></li>
<li><%= link_to t('routes.actions.destroy'), referential_line_route_path(@referential, @line, @route), :method => :delete, :data => {:confirm => t('routes.actions.destroy_confirm')}, :class => "remove" %></li>
<% if @route.stop_points.size >= 2 %>
- <li>
- <%= link_to t('journey_patterns.actions.new'), new_referential_line_route_journey_pattern_path(@referential, @line, @route), :class => "add" %>
- </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 t('journey_patterns.actions.new'), new_referential_line_route_journey_pattern_path(@referential, @line, @route), :class => "add" %></li>
+ <% end %>
<% if @route.journey_patterns.size > 0 %>
<li>
- <i class="fa fa-clock-o"></i><%= link_to t('vehicle_journeys.actions.index'), [@referential, @line, @route, :vehicle_journeys], :class => "vehicle_journeys" %>
+ <%= link_to t('vehicle_journeys.actions.index'), [@referential, @line, @route, :vehicle_journeys], :class => "clock" %>
</li>
-<% end %>
+ <% 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 t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, :format => :zip), :class => "export" %></li>
</ul>
<%= creation_tag(@route) %>
diff --git a/app/views/routes/show.js.erb b/app/views/routes/show.js.erb
deleted file mode 100644
index aedb0fb9e..000000000
--- a/app/views/routes/show.js.erb
+++ /dev/null
@@ -1,4 +0,0 @@
-$(function (){
- $(".stop_points_detail").html("<%= escape_javascript(render(:partial => "stop_points_detail")) %>");
-});
-
diff --git a/app/views/routes/show.kml.erb b/app/views/routes/show.kml.erb
index 91ffb9918..e6ef8b81d 100644
--- a/app/views/routes/show.kml.erb
+++ b/app/views/routes/show.kml.erb
@@ -9,6 +9,7 @@
<% @route.stop_areas.where("latitude is not null and longitude is not null").each_with_index do |stop_area, index| %>
<Placemark id="<%= stop_area.id %>" >
<name><%= "#{stop_area.name} (#{index+1})" %></name>
+ <stop_area_type_label><%= t("area_types.label.#{stop_area.stop_area_type}") %></stop_area_type_label>
<% if stop_area.id==@route.stop_areas.first.id %>
<departure>true</departure>
<% elsif stop_area.id==@route.stop_areas.last.id %>
diff --git a/app/views/rule_parameter_sets/_form.html.erb b/app/views/rule_parameter_sets/_form.html.erb
index 1f12d6b14..90d6850fb 100644
--- a/app/views/rule_parameter_sets/_form.html.erb
+++ b/app/views/rule_parameter_sets/_form.html.erb
@@ -14,10 +14,29 @@
<%= form.input :inter_access_link_distance_max, :as => :number %>
<%= form.input :inter_stop_duration_max, :as => :number %>
<%= form.input :facility_stop_area_distance_max, :as => :number %>
-
+
+ <%= form.input :vehicle_journey_number_min, :as => :number %>
+ <%= form.input :vehicle_journey_number_max, :as => :number %>
+ <%= form.input :check_allowed_transport_modes, :as => :boolean %>
+
+ <table class="table table-striped table-condensed">
+ <tr>
+ <th><%= t("transport_modes.name") %></th>
+ <% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %>
+ <% if prefix == "allowed_transport" %>
+ <% hidden = (@rule_parameter_set.check_allowed_transport_modes == "1") ? "" : 'display:none;'%>
+ <th class="allowed" style="<%= hidden %>" ><%= RuleParameterSet.human_attribute_name(prefix) %></th>
+ <% else %>
+ <th><%= RuleParameterSet.human_attribute_name(prefix) %></th>
+ <% end %>
+ <% end %>
+ </tr>
<% Chouette::Line.transport_modes.map(&:to_s).each do |mode| %>
+ <tr>
<%= render :partial => "mode_fields", :locals => { :f => form, :mode => mode} %>
+ </tr>
<% end %>
+ </table>
<% end %>
<%= form.actions do %>
@@ -25,3 +44,11 @@
<%= form.action :cancel, :as => :link %>
<% end %>
<% end %>
+
+<script>
+ $(function() {
+ $( "#rule_parameter_set_check_allowed_transport_modes").change( function(){
+ $(".allowed").toggle();
+ });
+ });
+</script>
diff --git a/app/views/rule_parameter_sets/_mode_fields.html.erb b/app/views/rule_parameter_sets/_mode_fields.html.erb
index 0a17b4d82..a305c4d0a 100644
--- a/app/views/rule_parameter_sets/_mode_fields.html.erb
+++ b/app/views/rule_parameter_sets/_mode_fields.html.erb
@@ -1,5 +1,12 @@
-<%= f.inputs t("transport_modes.label.#{mode}"), :id => "specific_parameters_#{mode}" do %>
+ <td><%= t("transport_modes.label.#{mode}") %></td>
<% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %>
- <%= f.input "#{prefix}_mode_#{mode}".to_sym, :as => :number, :label => RuleParameterSet.human_attribute_name(prefix), :wrapper_html => { :class => "special"} %>
+ <% if prefix == "allowed_transport" %>
+ <% hidden = (@rule_parameter_set.check_allowed_transport_modes == "1") ? "" : 'display: none;'%>
+ <td class="allowed" style="<%= hidden %>" >
+ <%= f.check_box "#{prefix}_mode_#{mode}".to_sym, :class => "special" %>
+ <% else%>
+ <td>
+ <%= f.number_field "#{prefix}_mode_#{mode}".to_sym, :class => "special" %>
+ <% end %>
+ </td>
<% end %>
-<% end %>
diff --git a/app/views/rule_parameter_sets/_rule_parameter_set.html.erb b/app/views/rule_parameter_sets/_rule_parameter_set.html.erb
new file mode 100644
index 000000000..3b9af4751
--- /dev/null
+++ b/app/views/rule_parameter_sets/_rule_parameter_set.html.erb
@@ -0,0 +1,23 @@
+<div id="index_item" class="panel panel-default rule_parameter_set">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_rule_parameter_set_path(@referential, rule_parameter_set), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <% if @referential.rule_parameter_sets.size > 1 %>
+ <%= link_to referential_rule_parameter_set_path(@referential, rule_parameter_set), :method => :delete, :data => {:confirm => t('rule_parameter_sets.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, rule_parameter_set], :class => "preview", :title => "#{RuleParameterSet.model_name.human.capitalize} #{rule_parameter_set.name}") do %>
+ <span class="name">
+ <%= truncate(rule_parameter_set.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+</div>
diff --git a/app/views/rule_parameter_sets/index.html.erb b/app/views/rule_parameter_sets/index.html.erb
index c03ff0d15..a92840529 100644
--- a/app/views/rule_parameter_sets/index.html.erb
+++ b/app/views/rule_parameter_sets/index.html.erb
@@ -1,18 +1,6 @@
<%= title_tag t('rule_parameter_sets.index.title') %>
-<% @rule_parameter_sets.each do |rule_parameter_set| %>
- <%= div_for(rule_parameter_set) do %>
- <%= link_to( rule_parameter_set.name, [@referential, rule_parameter_set]) %>
- <div class="info">
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_rule_parameter_set_path(@referential, rule_parameter_set), :class => "edit" %>
- <% if @referential.rule_parameter_sets.size > 1 %>
- | <%= link_to t("actions.destroy"), referential_rule_parameter_set_path(@referential, rule_parameter_set), :method => :delete, :data => {:confirm => t('rule_parameter_sets.actions.destroy_confirm')}, :class => "remove" %>
- <% end %>
- </div>
- </div>
- <% end %>
-<% end %>
+<%= paginated_content(@rule_parameter_sets) %>
<% content_for :sidebar do %>
<ul class="actions">
diff --git a/app/views/rule_parameter_sets/show.html.erb b/app/views/rule_parameter_sets/show.html.erb
index f2427e36e..66e002b94 100644
--- a/app/views/rule_parameter_sets/show.html.erb
+++ b/app/views/rule_parameter_sets/show.html.erb
@@ -4,10 +4,6 @@
<div class="summary">
<p>
- <label><%= RuleParameterSet.human_attribute_name("name") %>: </label>
- <%= @rule_parameter_set.name %>
- </p>
- <p>
<label><%= RuleParameterSet.human_attribute_name("stop_areas_area") %>: </label>
<%= @rule_parameter_set.stop_areas_area %>
</p>
@@ -72,38 +68,65 @@
<label><%= t(".inter_stop_duration_max") %>: </label>
<%= @rule_parameter_set.inter_stop_duration_max %>
</p>
- <div class="rule_parameter_by_mode">
- <label><%= t(".rule_parameter_by_mode") %>: </label>
- <select id="mode" >
- <%= options_for_select( Chouette::Line.transport_modes.map(&:to_s).map { |s| [ I18n.t("transport_modes.label.#{s}"), s]}, 1) %>
- </select>
- <% Chouette::Line.transport_modes.map(&:to_s).each_with_index do |mode, index| %>
- <% selected_class = (index==0) ? 'selected' : '' %>
- <% style = (index==0) ? "style='display: block;'" : '' %>
- <div class='<%= "#{mode} mode_specific #{selected_class}" %>' <%= style %> >
- <% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %>
- <% unless @rule_parameter_set.send("#{prefix}_mode_#{mode}" ).blank? %>
- <p>
- <label><%= RuleParameterSet.human_attribute_name( prefix) %>: </label>
- <%= @rule_parameter_set.send "#{prefix}_mode_#{mode}" %>
- </p>
- <% end %>
- <% end %>
+ <% if @rule_parameter_set.vehicle_journey_number_min.present? && @rule_parameter_set.vehicle_journey_number_max.present? %>
+ <div class="attributes_group" >
+ <span class="title"><%= t(".vehicle_journey_number_bounds") %></span>
+ <div class="columns">
+ <div class="two_columns">
+ <label><%= t(".min_value") %> : </label>
+ <span class="value"><%= @rule_parameter_set.vehicle_journey_number_min %></span>
+ </div>
+ <div class="two_columns">
+ <label><%= t(".max_value") %> : </label>
+ <span class="value"><%= @rule_parameter_set.vehicle_journey_number_max %></span>
+ </div>
</div>
- <% end %>
+ </div>
+ <% end %>
+ <p>
+ <label><%= RuleParameterSet.human_attribute_name("check_allowed_transport_modes") %>: </label>
+ <%= @rule_parameter_set.check_allowed_transport_modes ? t("true") : t("false") %>
+ </p>
+
+ <div class="rule_parameter_by_mode">
+ <label><%= t(".rule_parameter_by_mode") %>
+ <%= t(".modes_allowed") if @rule_parameter_set.check_allowed_transport_modes %>
+ </label>
+ <table class="table table-striped table-condensed">
+ <tr>
+ <th><%= t("transport_modes.name") %></th>
+ <% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %>
+ <% unless prefix == "allowed_transport" %>
+ <th><%= RuleParameterSet.human_attribute_name(prefix) %></th>
+ <% end %>
+ <% end %>
+ </tr>
+ <% Chouette::Line.transport_modes.map(&:to_s).each do |mode| %>
+ <% if @rule_parameter_set.allowed(mode) %>
+ <tr>
+ <td><%= t("transport_modes.label.#{mode}") %></td>
+ <% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %>
+
+ <% unless prefix == "allowed_transport" %>
+ <td><%= @rule_parameter_set.send "#{prefix}_mode_#{mode}" %></td>
+ <% end %>
+ <% end %>
+ </tr>
+ <% end %>
+ <% end %>
+ </table>
</div>
</div>
</div>
<% 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/shared/_breadcrumb.erb b/app/views/shared/_breadcrumb.erb
new file mode 100644
index 000000000..728d445ae
--- /dev/null
+++ b/app/views/shared/_breadcrumb.erb
@@ -0,0 +1,3 @@
+<% if @breadcrumbs.present? %>
+ <%= render_breadcrumbs builder: BootstrapBreadcrumbsBuilder, :tag => :li, :separator => "" %>
+<% end %>
diff --git a/app/views/shared/_footer.erb b/app/views/shared/_footer.erb
index 059a96d4c..9b21219a0 100644
--- a/app/views/shared/_footer.erb
+++ b/app/views/shared/_footer.erb
@@ -6,9 +6,9 @@
<div class="col-md-3">
<ul>
<li><h4><%= t("layouts.footer.product.title") %></h4></li>
- <li><%= link_to t("layouts.footer.product.licence"), "http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html" %></li>
- <li><%= link_to t("layouts.footer.product.source_code"), "https://github.com/afimb/chouette2" %></li>
- <li><%= link_to t("layouts.footer.product.user_group") %></li>
+ <li><%= link_to t("layouts.footer.product.licence"), "http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html", :target => "_blank" %></li>
+ <li><%= link_to t("layouts.footer.product.source_code"), "https://github.com/afimb/chouette2", :target => "_blank" %></li>
+ <li><%= link_to t("layouts.footer.product.user_group"), "http://www.chouette.mobi/les-utilisateurs/club-utilisateur-des-outils-chouette-et-irys/", :target => "_blank" %></li>
</ul>
</div>
<div class="col-md-3">
@@ -18,10 +18,10 @@
<% if ChouetteIhm::Application.config.company_contact.include?("@") %>
<%= mail_to "#{ChouetteIhm::Application.config.company_contact}", t("layouts.footer.contact.mail") %>
<% else %>
- <%= link_to t("layouts.footer.contact.mail"), "#{ChouetteIhm::Application.config.company_contact}" %>
+ <%= link_to t("layouts.footer.contact.mail"), "#{ChouetteIhm::Application.config.company_contact}", :target => "_blank" %>
<% end %>
</li>
- <li><%= link_to t("layouts.footer.support.help"), "/help" %></li>
+ <li><%= link_to t("layouts.footer.support.help"), help_path, :target => "chouette_help" %></li>
</ul>
</div>
<div class="col-md-3">
@@ -31,11 +31,11 @@
<% if ChouetteIhm::Application.config.company_contact.include?("@") %>
<%= mail_to "#{ChouetteIhm::Application.config.company_contact}", t("layouts.footer.contact.mail") %>
<% else %>
- <%= link_to t("layouts.footer.contact.mail"), "#{ChouetteIhm::Application.config.company_contact}" %>
+ <%= link_to t("layouts.footer.contact.mail"), "#{ChouetteIhm::Application.config.company_contact}", :target => "_blank" %>
<% end %>
</li>
- <li><%= link_to t("layouts.footer.contact.newsletter"),"http://www.chouette.mobi/les-utilisateurs/etre-informe/" %></li>
- <li><%= link_to t("layouts.footer.contact.forum"), "http://forum.chouette.mobi/" %></li>
+ <li><%= link_to t("layouts.footer.contact.newsletter"),"http://www.chouette.mobi/les-utilisateurs/etre-informe/", :target => "_blank" %></li>
+ <li><%= link_to t("layouts.footer.contact.forum"), "http://forum.chouette.mobi/", :target => "_blank" %></li>
</ul>
</div>
</div>
diff --git a/app/views/shared/_header.erb b/app/views/shared/_header.erb
new file mode 100644
index 000000000..380f5b520
--- /dev/null
+++ b/app/views/shared/_header.erb
@@ -0,0 +1,100 @@
+<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
+ <div class="container">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar version"><%= APP_VERSION %></span>
+ </button>
+ <%= link_to referentials_path, :class =>"navbar-brand" do %>
+ <%= image_tag("logo_chouette.png") %>
+ <% end %>
+ <p class="navbar-text"><span class="brand_name">CHOUETTE</span></i><span class="version"><%= APP_VERSION %></span></p>
+ </div>
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+ <ul class="nav navbar-nav">
+ <% if selected_referential? %>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown", title="<%= @referential.name %>"><%= truncate @referential.name, :length => 15 %><b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><%= link_to t("layouts.navbar.return_to_referentials"), referentials_path %></li>
+ <li class="divider"></li>
+ <li role="presentation" class="dropdown-header"><%= t("layouts.navbar.select_referential") %></li>
+ <% current_organisation.referentials.each do |referential| %>
+ <li>
+ <%= link_to referential.name, referential_path(referential) %>
+ </li>
+ <% end %>
+ </ul>
+ </li>
+ <li class="dropdown datas">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown"><%= t("layouts.navbar.referential_datas") %><b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><%= link_to t("layouts.navbar.return_to_dashboard"), referential_path(@referential) %></li>
+ <li class="divider"></li>
+ <li role="presentation" class="dropdown-header"><%= t("layouts.navbar.select_referential_datas") %></li>
+ <li><%= link_to referential_networks_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.networks.size %></span><%= Referential.human_attribute_name("networks") %>
+ <% end %>
+ </li>
+ <li><%= link_to referential_companies_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.companies.size %></span><%= Referential.human_attribute_name("companies") %>
+ <% end %>
+ </li>
+ <li><%= link_to referential_group_of_lines_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.group_of_lines.size %></span><%= Referential.human_attribute_name("group_of_lines") %>
+ <% end %>
+ </li>
+ <li><%= link_to referential_lines_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.lines.size %></span><%= Referential.human_attribute_name("lines") %>
+ <% end %>
+ </li>
+ <li><%= link_to referential_stop_areas_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.stop_areas.size %></span><%= Referential.human_attribute_name("stop_areas") %>
+ <% end %>
+ </li>
+ <li><%= link_to referential_connection_links_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.connection_links.size %></span><%= Referential.human_attribute_name("connection_links") %>
+ <% end %>
+ </li>
+ <li><%= link_to referential_time_tables_path(@referential) do %>
+ <span class="badge pull-right"><%= @referential.time_tables.size %></span><%= Referential.human_attribute_name("time_tables") %>
+ <% end %>
+ </li>
+ </ul>
+ </li>
+ <li><%= link_to Referential.human_attribute_name("import_tasks"), referential_import_tasks_path(@referential) %></li>
+ <li><%= link_to Referential.human_attribute_name("export_tasks"), referential_exports_path(@referential) %></li>
+ <li><%= link_to Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) %></li>
+ <% end %>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="dropdown languages">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+ <%= image_tag("language_engine/#{selected_language}_flag.png", { :'data-locale' => "#{selected_language}" } ) %><b class='caret'></b>
+ </a>
+ <ul class="dropdown-menu">
+ <li><%= link_to_language :fr, { :class => language_class( :fr ) } %></li>
+ <li><%= link_to_language :en, { :class => language_class( :en ) } %></li>
+ </ul>
+ </li>
+ <li><%= link_to t('layouts.help'), help_path, :class =>("current" if help_page?), :target => "chouette_help" %></li>
+ <% if user_signed_in? %>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="gravatar"><%= user_gravatar_image_tag(current_user, 16) %></span><%= truncate(current_user.name, :length => 20) %> <b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li><%= link_to t('layouts.user.profile'), edit_user_registration_path %></li>
+ <li><%= link_to t('layouts.user.sign_out'), destroy_user_session_path, :method => :delete %></li>
+ <li class="divider"></li>
+ <li><%= tab_link_to Organisation.model_name.human, organisation_path %></li>
+ </ul>
+ </li>
+ <% end %>
+ </ul>
+ </div><!-- /.navbar-collapse -->
+ </div><!-- /.container-fluid -->
+</nav>
diff --git a/app/views/stop_area_copies/new.html.erb b/app/views/stop_area_copies/new.html.erb
new file mode 100644
index 000000000..5edc005cc
--- /dev/null
+++ b/app/views/stop_area_copies/new.html.erb
@@ -0,0 +1,22 @@
+<%= title_tag t("stop_area_copies.new.title."+@stop_area_copy.hierarchy) %>
+
+<%= semantic_form_for [@referential, @stop_area, @stop_area_copy] do |form| %>
+ <br>
+ <%= form.inputs do %>
+ <%= form.input :source_id, :as => :hidden %>
+ <%= form.input :hierarchy, :as => :hidden %>
+ <% if @stop_area_copy.hierarchy == "child"%>
+ <% if @stop_area.area_type.underscore == "stop_place"%>
+ <%= form.input :area_type, :as => :select, :collection => ["stop_place","commercial_stop_point"], :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } %>
+ <% else%>
+ <%= form.input :area_type, :as => :select, :collection => ["boarding_position","quay"], :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } %>
+ <% end %>
+ <% else %>
+ <%= form.input :area_type, :as => :select, :collection => [@stop_area_copy.area_type], :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } %>
+ <% end %>
+ <% end %>
+ <%= form.actions do %>
+ <%= form.action :submit, :as => :button , :label => t( 'formtastic.duplicate' ) %>
+ <%= 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 74bccc816..d108ef193 100644
--- a/app/views/stop_areas/_form.html.erb
+++ b/app/views/stop_areas/_form.html.erb
@@ -1,53 +1,159 @@
-<div class="container-fluid">
- <div class="col-md-7">
- <%= semantic_form_for [@referential, @stop_area] do |form| %>
- <%= 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}") } %>
- <% if ! @referential.projection_type_label.empty? %>
- <div class="panel panel-default">
- <div class="panel-heading">@referential.projection_type_label</div>
- <div class="panel-body">
- <%= form.input :projection_x %>
- <%= form.input :projection_y %>
- </div>
- </div>
- <% end %>
- <div class="panel panel-default">
- <div class="panel-heading">WGS84</div>
- <div class="panel-body">
- <%= form.input :longitude %>
- <%= form.input :latitude %>
- </div>
- </div>
- <%= form.input :registration_number %>
- <%= form.input :street_name %>
- <%= form.input :country_code %>
- <%= form.input :fare_code %>
- <%= form.input :nearest_topic_name %>
- <%= form.input :comment, :as => :text %>
-
- <% 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 :objectid, :required => !@stop_area.new_record? %>
+<%= semantic_form_for [@referential, @stop_area] do |form| %>
+ <div class="row">
+ <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>
+ <div id="prefetch">
+ <label><%= t('.geolocalize') %></label>
+ <input class="typeahead form-control input-lg" maxlength="255" type="text" placeholder="<%= t('.address') %>" />
+ </div>
+ <% 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")} %>
+ <% 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 :city_name %>
+ <% end %>
+ </div>
+ <div class="col-md-6">
+ <% if !manage_itl && @map %>
+ <%= @map.to_html %>
<% end %>
-
- <%= form.actions do %>
- <%= form.action :submit, :as => :button %>
- <%= form.action :cancel, :as => :link %>
+ </div>
+ </div>
+ <div class="stop_areas.stop_area.general_info">
+ <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 :comment, :as => :text, :input_html => { :rows => 5 } %>
<% end %>
- <% end %>
-
</div>
- <div class="col-md-5">
- <% if !manage_itl && @map %>
- <%= @map.to_html %>
+ <div class="pmr_info">
+ <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 %>
<% end %>
</div>
-</div>
+
+ <%= form.actions do %>
+ <%= form.action :submit, :as => :button %>
+ <%= form.action :cancel, :as => :link %>
+ <% end %>
+<% end %>
+
+<script>
+ $(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.village) {
+ name += address.village;
+ } else if ( address.town) {
+ name += address.town;
+ } else if ( address.county ) {
+ name += address.county;
+ } else if ( address.country ) {
+ name += address.country;
+ }
+
+
+ return name;
+ };
+ var filtering = function(list) {
+ // update map view
+ removeAddress();
+
+ 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) {
+ var city = "";
+ if ( d.address.city) {
+ city = d.address.city;
+ } else if ( d.address.town) {
+ city = d.address.town;
+ } else if ( d.address.village) {
+ city = d.address.village;
+ }
+ return { postcode: d.address.postcode,
+ road: d.address.road,
+ lon: d.lon, lat: d.lat,
+ suburb: d.address.suburb,
+ city: 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();
+
+ // 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) {
+ // 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/_genealogical.html.erb b/app/views/stop_areas/_genealogical.html.erb
index 3b935ce92..54e117053 100644
--- a/app/views/stop_areas/_genealogical.html.erb
+++ b/app/views/stop_areas/_genealogical.html.erb
@@ -2,7 +2,7 @@
<% if @stop_area.parent.present? %>
<div class="parent">
- <%= link_to([@referential, @stop_area.parent]) do %>
+ <%= link_to([@referential, @stop_area.parent], :title => t("area_types.label.#{ @stop_area.parent.stop_area_type}") + " #{ @stop_area.parent.name}") do %>
<%= image_tag "map/" + @stop_area.parent.stop_area_type + ".png" %><span><%= @stop_area.parent.name %></span>
<% end %>
</div>
@@ -31,7 +31,7 @@
<div class="children">
<% @stop_area.children.each do |child| %>
<div class="child">
- <%= link_to([@referential, child]) do %>
+ <%= link_to([@referential, child], :title => t("area_types.label.#{ child.stop_area_type}") + " #{ child.name}") do %>
<%= image_tag "map/" + child.stop_area_type + ".png" %><span><%= child.name %></span>
<% end %>
</div>
@@ -42,7 +42,7 @@
<div class="children">
<% @stop_area.routing_stops.each do |stop| %>
<div class="child">
- <%= link_to([@referential, stop]) do %>
+ <%= link_to([@referential, stop], :title => t("area_types.label.#{ stop.stop_area_type}") + " #{ stop.name}") do %>
<%= image_tag "map/" + stop.stop_area_type + ".png" %><span><%= stop.name %></span>
<% end %>
</div>
diff --git a/app/views/stop_areas/_stop_area.html.erb b/app/views/stop_areas/_stop_area.html.erb
index 4f2a1a695..8136f9078 100644
--- a/app/views/stop_areas/_stop_area.html.erb
+++ b/app/views/stop_areas/_stop_area.html.erb
@@ -1,15 +1,37 @@
-<%= div_for(stop_area) do %>
- <%= link_to([@referential, stop_area], :class => "preview") do %>
- <div class="area_type">
- <%= image_tag "map/" + stop_area.stop_area_type + ".png" %>
- </div>
- <% end %>
- <%= link_to stop_area.name, [@referential, stop_area] %>
- <div class="info">
+<div id="index_item" class="panel panel-default stop_area">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_stop_area_path(@referential, stop_area), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to referential_stop_area_path(@referential, stop_area), :method => :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to([@referential, stop_area], :class => "preview", :title => t("area_types.label.#{stop_area.stop_area_type}") + " #{stop_area.name}") do %>
+ <span class="name">
+ <%= image_tag "map/" + stop_area.stop_area_type + ".png" %> <%= truncate(stop_area.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
<p>
<% unless stop_area.area_type == 'ITL' || stop_area.geometry %>
<span class="warning"><%= t('.no_position') %></span> -
<% end %>
+ <span class="warning">
+ <% if stop_area.zip_code.blank? %>
+ <%= stop_area.human_attribute_name('country_code')+' '+stop_area.country_code unless stop_area.country_code.blank? %>
+ <% else %>
+ <%= stop_area.zip_code %>
+ <% end %>
+ <%= stop_area.city_name %>
+ &nbsp;
+ </span>
</p>
<p>
<% if stop_area.area_type == 'ITL' %>
@@ -22,9 +44,5 @@
<% end %>
<% end %>
</p>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_stop_area_path(@referential, stop_area), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_stop_area_path(@referential, stop_area), :method => :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, :class => "remove" %>
- </div>
</div>
-<% end %>
+</div>
diff --git a/app/views/stop_areas/_stop_areas.html.erb b/app/views/stop_areas/_stop_areas.html.erb
new file mode 100644
index 000000000..9c7a82d6d
--- /dev/null
+++ b/app/views/stop_areas/_stop_areas.html.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @stop_areas %>
+</div>
+<div class="stop_areas paginated_content">
+ <%= paginated_content(@stop_areas) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @stop_areas, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/stop_areas/access_links.html.erb b/app/views/stop_areas/access_links.html.erb
index d4727d7db..3cea2fbdd 100644
--- a/app/views/stop_areas/access_links.html.erb
+++ b/app/views/stop_areas/access_links.html.erb
@@ -1,33 +1,46 @@
<%= title_tag t('stop_areas.access_links.title', :stop_area => @stop_area.name ) %>
<div class="stop_area_show">
- <h3 class="stop_area_generics">
- <a class="generics"><%= t('.generic_access_links') %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
-
- </h3>
- <div class="generics content">
- <div class="access_link_pairs">
- <table>
- <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@generic_access_links) %>
- </table>
- </div>
+
+<div class="panel-group" id="generic">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h4 class="panel-title">
+ <a data-toggle="collapse" data-parent="#generic" href="#generic_access_links">
+ <%= t('.generic_access_links') %>
+ </a>
+ </h4>
+ </div>
+ <div id="generic_access_links" class="panel-collapse collapse in">
+ <div class="panel-body">
+ <div class="access_link_pairs">
+ <table>
+ <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@generic_access_links) %>
+ </table>
+ </div>
+ </div>
+ </div>
</div>
- <h3 class="stop_area_generics">
- <a class="details"><%= t('.detail_access_links') %>
- <%= image_tag("icons/plus.png" , :class => "switcher") %>
- <%= image_tag("icons/minus.png" , :class => "switcher", :style => "display: none;" ) %>
- </a>
-
- </h3>
- <div class="details content" style="display: none;">
- <div class="access_link_pairs">
- <table>
- <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@detail_access_links) %>
- </table>
- </div>
+</div>
+
+<div class="panel-group" id="detail">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h4 class="panel-title">
+ <a data-toggle="collapse" data-parent="#detail" href="#detail_access_links">
+ <%= t('.detail_access_links') %>
+ </a>
+ </h4>
+ </div>
+ <div id="detail_access_links" class="panel-collapse collapse">
+ <div class="panel-body">
+ <div class="access_link_pairs">
+ <table>
+ <%= render :partial => "access_link_pairs/access_link_pair", :collection => access_links_pairs(@detail_access_links) %>
+ </table>
+ </div>
+ </div>
+ </div>
</div>
</div>
diff --git a/app/views/stop_areas/add_children.html.erb b/app/views/stop_areas/add_children.html.erb
index acf4ff603..732e28466 100644
--- a/app/views/stop_areas/add_children.html.erb
+++ b/app/views/stop_areas/add_children.html.erb
@@ -3,7 +3,7 @@
<%= semantic_form_for [@referential, @stop_area] do |form| %>
<div>
<%= form.inputs do %>
- <%= form.input :children_ids, :as => :text, :input_html => { :"data-pre" => ( @children.map { |child| { :id => child.id.to_s, :name => "#{child.name} #{child.country_code}" } } ).to_json } %>
+ <%= form.input :children_ids, :as => :search_stop_area, :json => referential_stop_area_stop_area_children_path(@referential, @stop_area, :format => :json), :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :input_html => { :"data-pre" => Rabl::Renderer.new('stop_areas/index', @children, :view_path => 'app/views', :format => :json).render } %>
<% end %>
<%= form.actions do %>
@@ -13,19 +13,6 @@
</div>
<% end %>
-<script>
- $(function() {
- $( "#stop_area_children_ids" ).tokenInput('<%= referential_stop_area_stop_area_children_path(@referential, @stop_area, :format => :json) %>', {
- crossDomain: false,
- prePopulate: $('#stop_area_children_id').data('pre'),
- minChars: 3,
- hintText: '<%= t('search_hint') %>',
- noResultsText: '<%= t('no_result_text') %>',
- searchingText: '<%= t('searching_term') %>'
- });
- });
-</script>
-
<% content_for :sidebar do %>
<ul class="actions">
</ul>
diff --git a/app/views/stop_areas/index.html.erb b/app/views/stop_areas/index.html.erb
index 5519ea55e..93406dc81 100644
--- a/app/views/stop_areas/index.html.erb
+++ b/app/views/stop_areas/index.html.erb
@@ -1,42 +1,38 @@
<%= title_tag t('stop_areas.index.title') %>
-<form class="navbar-form" role="search">
- <%= search_form_for @q, :url => referential_stop_areas_path(@referential), :html => {:method => :get} do |f| %>
- <div class="form-group">
- <%= f.label :name_or_country_code_cont, "#{t('.name_or_country_code')} :" %>
- <%= f.text_field :name_or_country_code_cont %>
- <%= f.hidden_field :area_type_eq %>
- </div>
- <%= f.submit t('actions.search') %> <%= t("or") %>
- <%= link_to t("cancel"), referential_stop_areas_path(@referential) %>
- <% end %>
-</form>
-
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @stop_areas %>
+<div id="country_codes">
+ <%= @country_codes.to_json %>
</div>
-<div class="stop_areas paginated_content">
- <%= paginated_content(@stop_areas) %>
-</div>
-<div class="pagination">
- <%= will_paginate @stop_areas, :container => false, renderer: BootstrapPagination::Rails %>
+
+<%= search_form_for @q, :url => referential_stop_areas_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-9">
+ <%= f.text_field :name_cont, :placeholder => "#{t('.name')}", :class => 'form-control' %>
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <a data-toggle="collapse" data-parent="#search" href="#advanced_search">
+ <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %>
+ </a>
+ </div>
+
+ <div id="advanced_search" class="panel-collapse collapse">
+ <div class="panel-body">
+ <%= f.text_field :country_code_cont, :placeholder => "#{t('.country_code')}", :class => 'form-control typeahead' %>
+ <%= f.select(:area_type_cont, options_from_collection_for_select(Chouette::StopArea.stop_area_types, 'name', Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } ), { :include_blank => "#{t('.area_type')}" }, { :class => 'form-control' }) %>
+ </div>
+ </div>
</div>
+<% end %>
+
+<div id="stop_areas"><%= render 'stop_areas' %></div>
<% content_for :sidebar do %>
<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>
-</ul>
-
-<h4><%= t(".selection") %></h4>
-
-<h5><%= t(".area_type") %></h5>
-
-<ul class="selection">
-<% Chouette::StopArea.stop_area_types.each do |area_type| %>
-<li><%= link_with_search (image_tag("map/" + area_type + ".png")+t("area_types.label.#{area_type.to_s}")), "area_type_eq" => area_type.name %></li>
-<% end %>
-<li><%= link_with_search (image_tag("map/all.png")+t(".selection_all")), {"area_type_eq" => nil}, :class => "all" %></li>
+ <li><%= link_to t('stop_areas.actions.default_geometry'), default_geometry_referential_stop_areas_path(@referential), :method => :put, :class => "calculator" %></li>
</ul>
<% end %>
diff --git a/app/views/stop_areas/index.js.erb b/app/views/stop_areas/index.js.erb
new file mode 100644
index 000000000..1621823cc
--- /dev/null
+++ b/app/views/stop_areas/index.js.erb
@@ -0,0 +1 @@
+$('#stop_areas').html('<%= escape_javascript(render("stop_areas")) %>'); \ No newline at end of file
diff --git a/app/views/stop_areas/index.kml.erb b/app/views/stop_areas/index.kml.erb
index 69a31db32..f43f130b6 100644
--- a/app/views/stop_areas/index.kml.erb
+++ b/app/views/stop_areas/index.kml.erb
@@ -5,6 +5,7 @@
<Placemark id="<%= stop_area.id %>" >
<name><%= stop_area.name %></name>
<stop_area_type><%= stop_area.stop_area_type %></stop_area_type>
+ <stop_area_type_label><%= t("area_types.label.#{stop_area.stop_area_type}") %></stop_area_type_label>
<%= stop_area.geometry.kml_representation.html_safe %>
</Placemark>
<% end %>
diff --git a/app/views/stop_areas/index.rabl b/app/views/stop_areas/index.rabl
new file mode 100644
index 000000000..72b736858
--- /dev/null
+++ b/app/views/stop_areas/index.rabl
@@ -0,0 +1,9 @@
+collection @stop_areas
+
+node do |stop_area|
+ { :id => stop_area.id, :name => stop_area.name || "", :zip_code => stop_area.zip_code || "", :city_name => stop_area.city_name || "" }
+end
+
+node :area_type do |area|
+ I18n.t("area_types.label.#{area.area_type.underscore}") || ""
+end \ No newline at end of file
diff --git a/app/views/stop_areas/select_parent.html.erb b/app/views/stop_areas/select_parent.html.erb
index 2e5f4ca94..fd1b292c6 100644
--- a/app/views/stop_areas/select_parent.html.erb
+++ b/app/views/stop_areas/select_parent.html.erb
@@ -2,8 +2,8 @@
<%= semantic_form_for [@referential, @stop_area] do |form| %>
<div>
- <%= form.inputs do %>
- <%= form.input :parent_id, :as => :text, :input_html => { :"data-pre" => ( @parent.present? ? [ { :id => @parent.id.to_s, :name => "#{@parent.name} #{@parent.country_code}" } ]: [] ).to_json } %>
+ <%= form.inputs do %>
+ <%= form.input :parent_id, :as => :search_stop_area, :json => referential_stop_area_stop_area_parents_path(@referential, @stop_area, :format => :json), :hint_text => t('search_hint'), :no_result_text => t('no_result_text'), :searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :"data-pre" => Rabl::Renderer.new('stop_areas/show', [@parent].compact, :view_path => 'app/views', :format => :json).render } %>
<% end %>
<%= form.actions do %>
@@ -13,20 +13,6 @@
</div>
<% end %>
-<script>
- $(function() {
- $( "#stop_area_parent_id" ).tokenInput('<%= referential_stop_area_stop_area_parents_path(@referential, @stop_area, :format => :json) %>', {
- crossDomain: false,
- prePopulate: $('#stop_area_parent_id').data('pre'),
- tokenLimit: 1,
- minChars: 3,
- hintText: '<%= t('search_hint') %>',
- noResultsText: '<%= t('no_result_text') %>',
- searchingText: '<%= t('searching_term') %>'
- });
- });
-</script>
-
<% content_for :sidebar do %>
<ul class="actions">
</ul>
diff --git a/app/views/stop_areas/show.html.erb b/app/views/stop_areas/show.html.erb
index d812ff4e3..3a6d88207 100644
--- a/app/views/stop_areas/show.html.erb
+++ b/app/views/stop_areas/show.html.erb
@@ -6,10 +6,6 @@
<% end %>
<div class="summary">
<p>
- <label><%= @stop_area.human_attribute_name("name") %>: </label>
- <%= @stop_area.name %>
- </p>
- <p>
<label><%= @stop_area.human_attribute_name("comment") %>: </label>
<%= @stop_area.comment %>
</p>
@@ -26,6 +22,14 @@
<%= @stop_area.country_code %>
</p>
<p>
+ <label><%= @stop_area.human_attribute_name("zip_code") %>: </label>
+ <%= @stop_area.zip_code %>
+ </p>
+ <p>
+ <label><%= @stop_area.human_attribute_name("city_name") %>: </label>
+ <%= @stop_area.city_name %>
+ </p>
+ <p>
<label><%= @stop_area.human_attribute_name("fare_code") %>: </label>
<%= @stop_area.fare_code %>
</p>
@@ -84,10 +88,6 @@
<% end %>
<% end %>
<% end %>
- <p>
- <label><%= @stop_area.human_attribute_name("objectid") %>: </label>
- <%= @stop_area.objectid %>
- </p>
</div>
</div>
<p class="after_map" />
@@ -110,26 +110,31 @@
<table>
<tr><td>
<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.edit'), edit_referential_stop_area_path(@referential, @stop_area), :class => "edit" %></li>
- <li><%= link_to t('stop_areas.actions.destroy'), referential_stop_area_path(@referential, @stop_area), :method => :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, :class => "remove" %></li>
+ <li><%= link_to t('stop_areas.actions.destroy'), referential_stop_area_path(@referential, @stop_area), :method => :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, :class => "remove" %></li>
</ul>
</td></tr>
<% if manage_itl %>
<tr><td>
<h4><%= t(".itl_managment") %></h4>
<ul class="actions">
- <li><%= link_to t('stop_areas.actions.add_routing_lines'), add_routing_lines_referential_stop_area_path(@referential, @stop_area), :class => "add_routing_lines" %></li>
- <li><%= link_to t('stop_areas.actions.add_routing_stops'), add_routing_stops_referential_stop_area_path(@referential, @stop_area), :class => "add_routing_stops" %></li>
+ <li><%= link_to t('stop_areas.actions.add_routing_lines'), add_routing_lines_referential_stop_area_path(@referential, @stop_area), :class => "add_routing_lines" %></li>
+ <li><%= link_to t('stop_areas.actions.add_routing_stops'), add_routing_stops_referential_stop_area_path(@referential, @stop_area), :class => "add_routing_stops" %></li>
</ul>
</td></tr>
<% else %>
<tr><td>
<h4><%= t(".stop_managment") %></h4>
<ul class="actions">
- <li><%= link_to t('stop_areas.actions.select_parent'), select_parent_referential_stop_area_path(@referential, @stop_area), :class => "select_parent" %></li>
- <% if manage_children %>
- <li><%= link_to t('stop_areas.actions.add_children'), add_children_referential_stop_area_path(@referential, @stop_area), :class => "add_children" %></li>
- <% end %>
+ <li><%= link_to t('stop_areas.actions.select_parent'), select_parent_referential_stop_area_path(@referential, @stop_area), :class => "parent" %></li>
+ <% if @stop_area.parent == nil %>
+ <li><%= link_to t('stop_areas.actions.clone_as_parent'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, :hierarchy => "parent"), :class => "clone" %></li>
+ <% end %>
+ <% if manage_children %>
+ <li></i></font><%= link_to t('stop_areas.actions.add_children'), add_children_referential_stop_area_path(@referential, @stop_area), :class => "children" %></li>
+ <li><%= link_to t('stop_areas.actions.clone_as_child'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, :hierarchy => "child"), :class => "clone" %></li>
+ <% end %>
</ul>
</td></tr>
@@ -138,7 +143,7 @@
<h4><%= t(".access_managment") %></h4>
<ul class="actions">
<li><%= link_to t('access_points.actions.new'), new_referential_stop_area_access_point_path(@referential,@stop_area), :class => "add" %></li>
- <li><%= link_to t('stop_areas.actions.manage_access_links'), access_links_referential_stop_area_path(@referential,@stop_area), :class => "select_parent" %></li>
+ <li><%= link_to t('stop_areas.actions.manage_access_links'), access_links_referential_stop_area_path(@referential,@stop_area), :class => "access_link" %></li>
</ul>
</td></tr>
<% end %>
diff --git a/app/views/stop_areas/show.rabl b/app/views/stop_areas/show.rabl
new file mode 100644
index 000000000..a03a3511d
--- /dev/null
+++ b/app/views/stop_areas/show.rabl
@@ -0,0 +1,9 @@
+object @stop_area
+
+node do |stop_area|
+ { :id => stop_area.id, :name => stop_area.name || "", :zip_code => stop_area.zip_code || "", :city_name => stop_area.city_name || "" }
+end
+
+node :area_type do |area|
+ I18n.t("area_types.label.#{area.area_type.underscore}") || ""
+end
diff --git a/app/views/stop_points/_stop_point.html.erb b/app/views/stop_points/_stop_point.html.erb
index 641ddf683..5eb4bb8b9 100644
--- a/app/views/stop_points/_stop_point.html.erb
+++ b/app/views/stop_points/_stop_point.html.erb
@@ -1,9 +1,16 @@
-<%= div_for(stop_point) do %>
- <span class="position">
- <%= stop_point.position + 1 %>
- </span>
- <%= link_to stop_point.stop_area.name, [@referential, stop_point.stop_area] %>
- <div class="info">
+<div id="index_item" class="panel panel-default stop_point">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <h5>
+ <%= link_to([@referential, stop_point.stop_area], :class => "preview", :title => "#{Chouette::StopArea.model_name.human.capitalize} #{stop_point.stop_area.name}") do %>
+ <span class="name">
+ <span class="label label-default"><%= stop_point.position + 1 %></span><%= truncate(stop_point.stop_area.name, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
<p>
<% unless stop_point.stop_area.geometry %>
<span class="warning"><%= t('.no_position') %></span> -
@@ -12,9 +19,16 @@
<p>
<%= t('.lines') %> <% stop_point.stop_area.lines.reject { |l| l.id==@line.id}.each do |line| %>
<span class="line"><%= line.number %></span>
- <% end %> -
- <%= stop_point.stop_area.human_attribute_name('country_code') %> <%= stop_point.stop_area.country_code %>
+ <% end %>
+ </p>
+ <p>
+ <% if stop_point.stop_area.zip_code.blank? %>
+ <%= stop_point.stop_area.human_attribute_name('country_code') %> <%= stop_point.stop_area.country_code %>
+ <% else %>
+ <%= stop_point.stop_area.zip_code %>
+ <% end %>
+ <%= stop_point.stop_area.city_name %>
</p>
</div>
-<% end %>
+</div>
diff --git a/app/views/time_table_combinations/_combine.html.erb b/app/views/time_table_combinations/_combine.html.erb
new file mode 100644
index 000000000..27b5f056f
--- /dev/null
+++ b/app/views/time_table_combinations/_combine.html.erb
@@ -0,0 +1,12 @@
+<div id="modal_combine" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+ <h4 class="modal-title" id="myModalLabel"><%= t('time_tables.show.combine_form') %></h4>
+ </div>
+ <%= render "time_table_combinations/combine_form" %>
+ </div>
+ </div>
+
+</div>
diff --git a/app/views/time_table_combinations/_combine_form.html.erb b/app/views/time_table_combinations/_combine_form.html.erb
new file mode 100644
index 000000000..aad31a218
--- /dev/null
+++ b/app/views/time_table_combinations/_combine_form.html.erb
@@ -0,0 +1,14 @@
+<%= semantic_form_for [@referential, @time_table, @time_table_combination], :remote => true do |form| %>
+ <div class="modal-body">
+ <%= render "shared/flash_messages" %>
+ <%= form.inputs do %>
+ <%= form.input :operation, :as => :radio, :collection => Hash[TimeTableCombination.operations.map {|b| [t( b, :scope => "time_table_combinations.operations"),b]}] %>
+ <%= form.input :combined_id, :label => t('.time_tables'), :as => :search_time_table, :json => referential_time_tables_path(@referential, :format => :json), :hint_text => t('search_hint'), :no_result_text => t('no_result_text'), :searching_text => t('searching_term'), :tokenLimit => 1 %>
+ <% end %>
+ </div>
+ <div class="modal-footer">
+ <%= form.actions do %>
+ <%= form.action :submit, :as => :button , :label => t('time_tables.show.combine') %>
+ <% end %>
+ </div>
+<% end %>
diff --git a/app/views/time_table_combinations/create_failure.js.erb b/app/views/time_table_combinations/create_failure.js.erb
new file mode 100644
index 000000000..65cc241c5
--- /dev/null
+++ b/app/views/time_table_combinations/create_failure.js.erb
@@ -0,0 +1,5 @@
+
+var combine_form_partial = '<%= j render "time_table_combinations/combine_form" %> ';
+
+$('#new_time_table_combination').replaceWith(combine_form_partial);
+
diff --git a/app/views/time_table_combinations/create_success.js.erb b/app/views/time_table_combinations/create_success.js.erb
new file mode 100644
index 000000000..79ab543d9
--- /dev/null
+++ b/app/views/time_table_combinations/create_success.js.erb
@@ -0,0 +1,8 @@
+
+var combine_form_partial = '<%= j render "time_table_combinations/combine_form" %> ';
+
+$('#new_time_table_combination').replaceWith(combine_form_partial);
+
+var time_table_partial = '<%= j render "time_tables/show_time_table" %> ';
+$('#time_table_show').replaceWith(time_table_partial);
+
diff --git a/app/views/time_table_combinations/new.js.erb b/app/views/time_table_combinations/new.js.erb
new file mode 100644
index 000000000..ea98d9aaf
--- /dev/null
+++ b/app/views/time_table_combinations/new.js.erb
@@ -0,0 +1,4 @@
+var combine_form_partial = '<%= j render "time_table_combinations/combine_form" %> ';
+$('#new_time_table_combination').replaceWith(combine_form_partial);
+
+
diff --git a/app/views/time_tables/_date_fields.erb b/app/views/time_tables/_date_fields.erb
index 5d24456a3..2702e8e52 100644
--- a/app/views/time_tables/_date_fields.erb
+++ b/app/views/time_tables/_date_fields.erb
@@ -1,4 +1,6 @@
-<%= f.inputs :class => 'dates nested-fields' do %>
- <%= f.input :date, :as => :date_picker, :label => @time_table.human_attribute_name("date"), :wrapper_html => { :class => 'fl1' }%>
- <%= link_to_remove_association t('actions.destroy'), f %>
+<%= f.inputs :class => 'nested-fields date' do %>
+ <%= f.label @time_table.human_attribute_name("date"), :class => 'col-md-1' %>
+ <%= f.input :date, :as => :date_picker, :label => false, :input_html => { :class => 'form-control col-md-3' }%>
+ <%= f.input :in_out, :as => :hidden, :input_html => {:value => true} %>
+ <%= link_to_remove_association t('actions.destroy'), f, :class => "col-md-3" %>
<% end %>
diff --git a/app/views/time_tables/_dates.html.erb b/app/views/time_tables/_dates.html.erb
index 663efec58..c6af6ee8c 100644
--- a/app/views/time_tables/_dates.html.erb
+++ b/app/views/time_tables/_dates.html.erb
@@ -1,5 +1,5 @@
<ul class='dates'>
- <% @time_table.dates.each do |tmd| %>
+ <% @time_table.dates.where("in_out = true").to_a.each do |tmd| %>
<li class="<%= (tmd.position%2==0) ? 'odd' : 'even' %>"><%= l tmd.date %>
</li>
<% end %>
diff --git a/app/views/time_tables/_excluded_date_fields.erb b/app/views/time_tables/_excluded_date_fields.erb
new file mode 100644
index 000000000..2302cb711
--- /dev/null
+++ b/app/views/time_tables/_excluded_date_fields.erb
@@ -0,0 +1,6 @@
+<%= f.inputs :class => 'nested-fields date' do %>
+ <%= f.label @time_table.human_attribute_name("date"), :class => 'col-md-1' %>
+ <%= f.input :date, :as => :date_picker, :label => false, :input_html => { :class => 'form-control col-md-3' } %>
+ <%= f.input :in_out, :as => :hidden, :input_html => {:value => false} %>
+ <%= link_to_remove_association t('actions.destroy'), f, :class => "col-md-3" %>
+<% end %>
diff --git a/app/views/time_tables/_excluded_dates.html.erb b/app/views/time_tables/_excluded_dates.html.erb
new file mode 100644
index 000000000..8097c618f
--- /dev/null
+++ b/app/views/time_tables/_excluded_dates.html.erb
@@ -0,0 +1,7 @@
+ <ul class='dates'>
+ <% @time_table.dates.where("in_out = false").to_a.each do |tmd| %>
+ <li class="<%= (tmd.position%2==0) ? 'odd' : 'even' %>"><%= l tmd.date %>
+ </li>
+ <% end %>
+ </ul>
+
diff --git a/app/views/time_tables/_form.erb b/app/views/time_tables/_form.erb
index da303a5bc..7dceab747 100644
--- a/app/views/time_tables/_form.erb
+++ b/app/views/time_tables/_form.erb
@@ -1,25 +1,15 @@
<%= semantic_form_for [@referential, @time_table] do |form| %>
<%= form.inputs do %>
<%= form.input :comment %>
- <%= form.input :version %>
- <% end %>
- <%= form.inputs :class => 'day_type' do %>
- <label class="day_type_label"><%= @time_table.human_attribute_name("peculiarities") %></label>
- <%= form.input :school_holliday, :as => :boolean, :class => "others" %>
- <%= form.input :public_holliday, :as => :boolean %>
- <% end %>
- <%= form.inputs do %>
- <%= form.input :objectid, :required => !@time_table.new_record? %>
+ <%= form.input :version %>
+ <%= form.input :tag_search, :as => :tags, :input_html => { :id => "tag_search",:placeholder => t("formtastic.placeholders.time_table.tag_search") } %>
+ <%= form.input :tag_list, :as => :hidden, :input_html => { :id => "tag_list" } %>
+
+ <%= form.input :objectid, :required => !@time_table.new_record?, :input_html => { :title => t("formtastic.titles.time_table.objectid")} %>
<% end %>
- <h3 class="time_table_periods">
- <a class="periods"><%= @time_table.human_attribute_name("periods") %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
-
- </h3>
- <div class="periods content" id="periods_content">
+ <h3 class="time_table_periods"><%= @time_table.human_attribute_name("periods") %></h3>
+ <div id="periods_content">
<%= form.inputs :class => 'day_type' do %>
<label class="day_type_label"><%= @time_table.human_attribute_name("day_types") %></label>
<%= form.input :monday, :as => :boolean, :class => "others" %>
@@ -40,30 +30,62 @@
:"data-association-insertion-node" => "div#periods"%>
</div>
- <h3 class="time_table_dates">
- <a class="dates"><%= @time_table.human_attribute_name("dates") %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
- </h3>
-
- <div class="dates content" id="dates_content">
- <div id="dates">
- <%= form.semantic_fields_for :dates do |p| %>
- <%= render "date_fields", :f => p %>
+ <h3 class="time_table_dates"><%= @time_table.human_attribute_name("dates") %></h3>
+ <div id="dates_content">
+ <div id="dates">
+ <%= form.semantic_fields_for :dates, @time_table.dates.to_a.select {|d| d.in_out == true} do |p| %>
+ <%= render "date_fields", :f => p %>
<% end %>
</div>
<%= link_to_add_association t("time_tables.actions.add_date"), form, :dates ,
- :"data-association-insertion-method" => "append",
+ :"data-association-insertion-method" => "append",
+ :"partial" => "date_fields",
:"data-association-insertion-node" => "div#dates" %>
</div>
+
+ <h3 class="time_table_dates"><%= @time_table.human_attribute_name("excluded_dates") %></h3>
+ <div id="excluded_dates_content">
+ <div id="excluded_dates">
+ <%= form.semantic_fields_for :dates, @time_table.dates.to_a.select {|d| d.in_out == false} do |p| %>
+ <%= render "excluded_date_fields", :f => p %>
+ <% end %>
+ </div>
+ <%= link_to_add_association t("time_tables.actions.add_excluded_date"), form, :dates ,
+ :"data-association-insertion-method" => "append",
+ :"partial" => "excluded_date_fields",
+ :"data-association-insertion-node" => "div#excluded_dates" %>
+ </div>
- <p/>
- <%= form.actions do %>
- <%= form.action :submit, :as => :button %>
- <%= form.action :cancel, :as => :link %>
- <% end %>
+ <%= form.actions do %>
+ <%= form.action :submit, :as => :button %>
+ <%= form.action :cancel, :as => :link %>
+ <% end %>
<% end %>
+<%= javascript_tag "var items = #{ @time_table.tag_list.to_a };" %>
+
+<script>
+ $("#tag_search").tagsManager(
+ {
+ prefilled: items,
+ output: '#tag_list',
+ tagsContainer: '#tagsContainer'
+ });
+
+ var time_tables_tag_list = new Bloodhound({
+ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
+ queryTokenizer: Bloodhound.tokenizers.whitespace,
+ remote: '<%= tags_referential_time_tables_path(@referential, :format => 'json') %>?tag=%QUERY',
+ });
+
+ time_tables_tag_list.initialize();
+
+ $("#tag_search").typeahead(null, {
+ name: 'time_tables_tag_list',
+ displayKey: 'name',
+ source: time_tables_tag_list.ttAdapter()
+ });
+
+</script>
diff --git a/app/views/time_tables/_period_fields.erb b/app/views/time_tables/_period_fields.erb
index 120a526bb..0094008f1 100644
--- a/app/views/time_tables/_period_fields.erb
+++ b/app/views/time_tables/_period_fields.erb
@@ -1,5 +1,7 @@
-<%= f.inputs :class => 'periods nested-fields' do %>
- <%= f.input :period_start, :as => :date_picker, :label => @time_table.human_attribute_name("period_start"), :wrapper_html => { :class => 'fl1' }%>
- <%= f.input :period_end, :as => :date_picker, :label => @time_table.human_attribute_name("period_end"), :wrapper_html => { :class => 'fl2' }%>
- <%= link_to_remove_association t('actions.destroy'), f %>
+<%= f.inputs :class => 'nested-fields period' do %>
+ <%= f.label @time_table.human_attribute_name("period_start"), :class => "col-md-1" %>
+ <%= f.input :period_start, :as => :date_picker, :label => false, :input_html => { :class => 'form-control col-md-3' }%>
+ <%= f.label @time_table.human_attribute_name("period_end"), :class => "col-md-1" %>
+ <%= f.input :period_end, :as => :date_picker, :label => false, :input_html => { :class => 'form-control col-md-3' }%>
+ <%= link_to_remove_association t('actions.destroy'), f, :class => "col-md-2" %>
<% end %>
diff --git a/app/views/time_tables/_periods.html.erb b/app/views/time_tables/_periods.html.erb
index 41bf9db2d..1f0aea057 100644
--- a/app/views/time_tables/_periods.html.erb
+++ b/app/views/time_tables/_periods.html.erb
@@ -1,39 +1,4 @@
<ul class='periods'>
- <p>
- <label><%= @time_table.human_attribute_name("day_types") %>:&nbsp;&nbsp;</label>
- <% if @time_table.int_day_types & 508 == 0 %>
- <label><%= @time_table.human_attribute_name("none") %></label>
- <% else %>
- <% if @time_table.monday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("monday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.tuesday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("tuesday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.wednesday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("wednesday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.thursday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("thursday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.friday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("friday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.saturday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("saturday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.sunday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("sunday") %>&nbsp;</span>
- <% end %>
- <% end %>
-
- </p>
<% @time_table.periods.each do |tmp| %>
<li class='period'><%= t('time_tables.show.from')%> <%= l tmp.period_start %> <%= t('time_tables.show.to')%> <%= l tmp.period_end %>
</li>
diff --git a/app/views/time_tables/_show_time_table.html.erb b/app/views/time_tables/_show_time_table.html.erb
new file mode 100644
index 000000000..a439aed1b
--- /dev/null
+++ b/app/views/time_tables/_show_time_table.html.erb
@@ -0,0 +1,101 @@
+<div class="time_table_show" id="time_table_show">
+ <p>
+ <span class="state-code <%= time_table_state_code(@time_table) %>"><i class="fa fa-certificate"></i></span>
+ <label>
+ <% if @time_table.bounding_dates.empty? %>
+ <%= t(".resume_empty") %>
+ <% else %>
+ <%= t(".resume", :start_date => l(@time_table.bounding_dates.min), :end_date => l(@time_table.bounding_dates.max)) %>
+ <% end %>
+ </label>
+ </p>
+ <p>
+ <label><%= @time_table.human_attribute_name("tag_list") %>: </label>
+ <%= @time_table.tag_list %>
+ </p>
+ <ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
+ <li class="active"><a href="#time_tables" data-toggle="tab"><%= @time_table.human_attribute_name("calendars") %></a></li>
+ <li><a href="#time_tables_datas" data-toggle="tab"><%= @time_table.human_attribute_name("calendar_details") %></a></li>
+ </ul>
+ <div id="my-tab-content" class="tab-content">
+ <div class="tab-pane active" id="time_tables">
+ <div class="well legend">
+ <span class="title"><%= t(".legend") %></span>
+ <span class="label excluded_date">X</span><%= t(".excluded_date") %>
+ <span class="label overlaped_date">X</span><%= t(".overlap_date") %>
+ <span class="label selected_date">X</span><%= t(".selected_date") %>
+ <span class="label selected_period">X</span><%= t(".selected_period") %>
+ </div>
+ <div id="calendars">
+ <div class="year_choice">
+ <span class="previous"> <%= link_to("<", referential_time_table_path(@referential, @time_table, :year => (@year - 1)) ) %> </span>
+ <span class="year"> <%= "#{@year}" %> </span>
+ <span class="next"> <%= link_to(">", referential_time_table_path(@referential, @time_table, :year => (@year + 1)) ) %> </span>
+ </div>
+ <div class="calendar_helper">
+ <%= cal = ""
+ (1..12).each do |month|
+ cal << calendar(:year => @year, :month => month, :first_day_of_week => 1) do |d|
+ if @time_table.excluded_date?(d)
+ [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "day excluded_date"}]
+ elsif @time_table.include_in_overlap_dates?(d)
+ [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "day overlaped_date"}]
+ elsif @time_table.include_in_dates?(d)
+ [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "day selected_date"}]
+ elsif @time_table.include_in_periods?(d)
+ [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "day selected_period"}]
+ end
+ end
+ end
+ cal.html_safe
+ %>
+ </div>
+ </div>
+ </div>
+ <div class="tab-pane" id="time_tables_datas">
+ <div class="summary">
+ <p>
+ <label><%= @time_table.human_attribute_name("version") %>: </label>
+ <%= @time_table.version %>
+ </p>
+ <p>
+ <label><%= @time_table.human_attribute_name("day_types") %>:&nbsp;&nbsp;</label>
+ <% if @time_table.int_day_types & 508 == 0 %>
+ <label><%= @time_table.human_attribute_name("none") %></label>
+ <% else %>
+ <% %w(monday tuesday wednesday thursday friday saturday sunday).each do |day_type| %>
+ <span class="<%= @time_table.send( day_type) ? "included_day_type" : "excluded_day_type" %>">
+ <%= @time_table.human_attribute_name(day_type) %>
+ </span>
+ <% end %>
+ <% end %>
+ </p>
+
+ </div>
+
+ <% if @time_table.periods.present? %>
+ <h3 class="time_table_periods"><%= @time_table.human_attribute_name("periods") %></h3>
+ <div class="periods content">
+ <%= render "time_tables/periods" %>
+ </div>
+ <% end %>
+
+ <% if @time_table.dates.where("in_out = true").present? %>
+ <h3 class="time_table_dates"><%= @time_table.human_attribute_name("dates") %></h3>
+ <div class="dates content">
+ <%= render "time_tables/dates" %>
+ </div>
+ <% end %>
+
+ <% if @time_table.dates.where("in_out = false").present? %>
+ <h3 class="time_table_dates"><%= @time_table.human_attribute_name("excluded_dates") %></h3>
+ <div class="excluded_dates content">
+ <%= render "time_tables/excluded_dates" %>
+ </div>
+ <% end %>
+
+ </div>
+ </div>
+
+</div>
+
diff --git a/app/views/time_tables/_time_table.erb b/app/views/time_tables/_time_table.erb
deleted file mode 100644
index 0679008fc..000000000
--- a/app/views/time_tables/_time_table.erb
+++ /dev/null
@@ -1,19 +0,0 @@
-<%= div_for(time_table) do %>
- <%= link_to([@referential, time_table]) do %>
- <div class="state-code" >
- <div class="<%= time_table_state_code(time_table) %>" >
- </div>
- </div>
- <% end %>
- <div class="name">
- <%= link_to truncate(time_table.comment, :length => 30), [@referential, time_table], :title => "#{Chouette::TimeTable.model_name.human.capitalize} #{time_table.comment}"%>
- </div>
- <div class="info">
- <%= time_tables_shortest_info(time_table) %> -
- <%= composition_info(time_table) %>
- <div class="actions">
- <%= link_to t("actions.edit"), edit_referential_time_table_path(@referential, time_table), :class => "edit" %> |
- <%= link_to t("actions.destroy"), referential_time_table_path(@referential, time_table), :method => :delete, :data => {:confirm => t('time_tables.actions.destroy_confirm')}, :class => "remove" %>
- </div>
- </div>
-<% end %>
diff --git a/app/views/time_tables/_time_table.html.erb b/app/views/time_tables/_time_table.html.erb
new file mode 100644
index 000000000..0642f5a6c
--- /dev/null
+++ b/app/views/time_tables/_time_table.html.erb
@@ -0,0 +1,35 @@
+<div id="index_item" class="panel panel-default time_table">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_referential_time_table_path(@referential, time_table), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to('<span class="fa fa-trash-o"></span>'.html_safe, referential_time_table_path(@referential, time_table), :method => :delete, :data => {:confirm => t('time_tables.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm") if delete %>
+ </span>
+ <h5>
+ <%= link_to([@referential, time_table], :class => "preview", :title => "#{Chouette::TimeTable.model_name.human.capitalize} #{time_table.comment}") do %>
+ <span class="state-code <%= time_table_state_code(time_table) %>"><i class="fa fa-certificate"></i></span>
+ <span class="name">
+ <%= truncate(time_table.comment, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+ <div class="panel-body">
+ <%= time_tables_shortest_info(time_table) %>
+ <% unless time_table.periods.empty? %>
+ <div>
+ <% %w(monday tuesday wednesday thursday friday saturday sunday).each do |day_type| %>
+ <span class="<%= time_table.send( day_type) ? "included_day_type" : "excluded_day_type" %>">
+ <%= time_table.human_attribute_name(day_type).first(2) %>
+ </span>
+ <% end %>
+ </div>
+ <% end %>
+ <% unless time_table.tags.empty? %>
+ <div><%= tag_list_shortened(time_table) %></div>
+ <% end %>
+ </div>
+</div>
diff --git a/app/views/time_tables/_time_tables.html.erb b/app/views/time_tables/_time_tables.html.erb
new file mode 100644
index 000000000..4458f653d
--- /dev/null
+++ b/app/views/time_tables/_time_tables.html.erb
@@ -0,0 +1,9 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @time_tables %>
+</div>
+<div class="time_tables paginated_content">
+ <%= paginated_content(@time_tables) %>
+</div>
+<div class="pagination">
+ <%= will_paginate @time_tables, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
diff --git a/app/views/time_tables/edit.html.erb b/app/views/time_tables/edit.html.erb
index d80974841..ac3beaeaa 100644
--- a/app/views/time_tables/edit.html.erb
+++ b/app/views/time_tables/edit.html.erb
@@ -1,3 +1,4 @@
<%= title_tag t('time_tables.edit.title', :time_table => @time_table.comment) %>
<%= render "form" %>
+
diff --git a/app/views/time_tables/index.html.erb b/app/views/time_tables/index.html.erb
index d08476b79..e9802b4bc 100644
--- a/app/views/time_tables/index.html.erb
+++ b/app/views/time_tables/index.html.erb
@@ -1,22 +1,37 @@
<%= title_tag t('time_tables.index.title') %>
-<%= search_form_for @q, :url => referential_time_tables_path(@referential), :html => {:method => :get} do |f| %>
- <%= f.label :comment_cont, "#{t('.comment')} :" %>
- <%= f.text_field :comment_cont %>
-
- <%= f.submit t('actions.search') %> <%= t("or") %>
- <%= link_to t("cancel"), referential_time_tables_path(@referential) %>
+<%= search_form_for @q, :url => referential_time_tables_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <div class="input-group col-md-9">
+ <%= f.text_field :comment_cont, :placeholder => "#{t('.comment')}", :class => 'form-control' %>
+
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ </div>
+ </div><!-- /input-group -->
+ <a data-toggle="collapse" data-parent="#search" href="#advanced_search">
+ <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %>
+ </a>
+ </div>
+
+ <div id="advanced_search" class="panel-collapse collapse">
+ <div class="panel-body">
+ <div>
+ <label><%= "#{t('.from')}" %></label>
+ <%= f.text_field :start_date_gteq, :placeholder => "#{t('.start_date')}", :class => 'form-control date_picker', :type => "date" %>
+ <label><%= "#{t('.to')}" %></label>
+ <%= f.text_field :end_date_lteq, :placeholder => "#{t('.end_date')}", :class => 'form-control date_picker', :type => "date" %>
+ </div>
+ <div>
+ <%= f.text_field :tag_search, :placeholder => "#{t('.tag_search')}", :class => 'form-control' %>
+ </div>
+ </div>
+ </div>
+</div>
<% end %>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @time_tables %>
-</div>
-<div class="time_tables paginated_content">
- <%= paginated_content(@time_tables) %>
-</div>
-<div class="pagination">
- <%= will_paginate @time_tables, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
+<div id="time_tables"><%= render 'time_tables' %></div>
<% content_for :sidebar do %>
diff --git a/app/views/time_tables/index.js.erb b/app/views/time_tables/index.js.erb
new file mode 100644
index 000000000..3b37cde65
--- /dev/null
+++ b/app/views/time_tables/index.js.erb
@@ -0,0 +1 @@
+$('#time_tables').html('<%= escape_javascript(render("time_tables")) %>'); \ No newline at end of file
diff --git a/app/views/time_tables/index.json.rabl b/app/views/time_tables/index.json.rabl
new file mode 100644
index 000000000..443cb13a2
--- /dev/null
+++ b/app/views/time_tables/index.json.rabl
@@ -0,0 +1,9 @@
+collection @time_tables, :object_root => false
+
+node do |time_table|
+ { :id => time_table.id, :comment => time_table.comment,
+ :time_table_bounding => time_table_bounding( time_table),
+ :composition_info => composition_info(time_table),
+ :tags => time_table.tags.join(','),
+ :day_types => %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| time_table.send(d) }.map{ |d| time_table.human_attribute_name(d).first(2)}.join('')}
+end
diff --git a/app/views/time_tables/show.html.erb b/app/views/time_tables/show.html.erb
index dbc9fe7ec..6b2233a55 100644
--- a/app/views/time_tables/show.html.erb
+++ b/app/views/time_tables/show.html.erb
@@ -1,112 +1,20 @@
<% require 'calendar_helper' %>
-<%= title_tag t('time_tables.show.title', :time_table => @time_table.comment )%>
-
-<div class="time_table_show">
-
- <div class="resume">
- <div class="validity <%= time_table_state_code(@time_table) %>"></div>
- <label>
- <% if @time_table.bounding_dates.empty? %>
- <%= t(".resume_empty") %>
- <% else %>
- <%= t(".resume", :start_date => l(@time_table.bounding_dates.min),
- :end_date => l(@time_table.bounding_dates.max)) %>
- <% end %>
- </label>
- </div>
- <div class="summary">
- <p>
- <label><%= @time_table.human_attribute_name("comment") %>: </label>
- <%= @time_table.comment %>
- </p>
- <p>
- <label><%= @time_table.human_attribute_name("version") %>: </label>
- <%= @time_table.version %>
- </p>
- <p>
- <label><%= @time_table.human_attribute_name("peculiarities") %>:&nbsp;&nbsp;</label>
- <% if @time_table.int_day_types & 1536 == 0 %>
- <label><%= @time_table.human_attribute_name("none") %></label>
- <% else %>
- <% if @time_table.school_holliday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("school_holliday") %>&nbsp;</span>
- <% end %>
-
- <% if @time_table.public_holliday %>
- <span class='day_type'>&nbsp;<%= @time_table.human_attribute_name("public_holliday") %>&nbsp;</span>
- <% end %>
-
- <% end %>
-
- </p>
- <p>
- <label><%= @time_table.human_attribute_name("objectid") %>: </label>
- <%= @time_table.objectid %>
- </p>
-
- <h3 class="time_table_calendars">
- <a class="calendars"><%= @time_table.human_attribute_name("calendars") %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
-
- </h3>
- <div class="calendars content">
- <div class="year_choice">
- <span class="previous"> <%= link_to("<", referential_time_table_path(@referential, @time_table, :year => (@year - 1)) ) %> </span>
- <span class="year"> <%= "#{@year}" %> </span>
- <span class="next"> <%= link_to(">", referential_time_table_path(@referential, @time_table, :year => (@year + 1)) ) %> </span>
- </div>
- <div class="calendar_helper">
- <%= cal = ""
- (1..12).each do |month|
- cal << calendar(:year => @year, :month => month, :first_day_of_week => 1) do |d|
- if @time_table.include_in_dates?(d)
- [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "selected_date"}]
- elsif @time_table.include_in_periods?(d)
- [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "selected_period"}]
- elsif @time_table.include_in_overlap_dates?(d)
- [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {:class => "overlap_date"}]
- end
- end
- end
- cal.html_safe
- %>
- </div>
- </div>
+<%= title_tag t('time_tables.show.title', :time_table => @time_table.comment )%>
- </div>
- <h3 class="time_table_periods">
- <a class="periods"><%= @time_table.human_attribute_name("periods") %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
-
- </h3>
- <div class="periods content">
- <%= render "periods" %>
- </div>
-
- <h3 class="time_table_dates">
- <a class="dates"><%= @time_table.human_attribute_name("dates") %>
- <%= image_tag("icons/plus.png" , :class => "switcher", :style => "display: none;") %>
- <%= image_tag("icons/minus.png" , :class => "switcher" ) %>
- </a>
- </h3>
+<%= render "time_table_combinations/combine" %>
- <div class="dates content">
- <%= render "dates" %>
- </div>
-
-</div>
+<%= render "show_time_table" %>
<% content_for :sidebar do %>
<ul class="actions">
+ <li><%= link_to t('time_tables.actions.new'), new_referential_time_table_path(@referential), :class => "add" %></li>
<li><%= link_to t('time_tables.actions.edit'), edit_referential_time_table_path(@referential, @time_table), :class => "edit" %></li>
<li><%= link_to t('time_tables.actions.destroy'), referential_time_table_path(@referential, @time_table), :method => :delete, :data => {:confirm => t('time_tables.actions.destroy_confirm')}, :class => "remove" %></li>
- <br>
+ <li><%= link_to t('time_tables.actions.duplicate'), duplicate_referential_time_table_path(@referential, @time_table), :class => "clone" %></li>
+ <li><%= link_to t('time_tables.actions.combine'), new_referential_time_table_time_table_combination_path(@referential, @time_table), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal_combine', :class => "merge"} %></li>
</ul>
+
<%= creation_tag(@time_table) %>
<% end %>
diff --git a/app/views/time_tables/time_tables.json.rabl b/app/views/time_tables/time_tables.json.rabl
new file mode 100644
index 000000000..dec29cb69
--- /dev/null
+++ b/app/views/time_tables/time_tables.json.rabl
@@ -0,0 +1,5 @@
+collection @time_tables, :object_root => false
+
+node do |time_table|
+ { :id => time_table.id, :comment => time_table.comment, :time_table_bounding => time_table_bounding( time_table), :composition_info => composition_info(time_table) }
+end
diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb
index 3b19dddf2..ff452c924 100644
--- a/app/views/users/_form.html.erb
+++ b/app/views/users/_form.html.erb
@@ -6,6 +6,6 @@
<%= form.actions do %>
<%= form.action :submit, :as => :button %>
- <%= form.action :cancel, :as => :link %>
+ <%= form.action :cancel, :as => :link , :url => organisation_path %>
<% end %>
<% end %>
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb
new file mode 100644
index 000000000..3f70e8479
--- /dev/null
+++ b/app/views/users/_user.html.erb
@@ -0,0 +1,22 @@
+<div id="index_item" class="panel panel-default user">
+ <div class="panel-heading">
+ <div class="panel-title clearfix">
+ <span class="pull-right">
+ <%= link_to edit_organisation_user_path( user), :class => "btn btn-default btn-sm" do %>
+ <span class="fa fa-pencil"></span>
+ <% end %>
+ <%= link_to organisation_user_path(user), :method => :delete, :data => {:confirm => t('users.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %>
+ <span class="fa fa-trash-o"></span>
+ <% end %>
+ </span>
+ <h5>
+ <%= link_to( organisation_user_path(user), :class => "preview", :title => "#{User.model_name.human.capitalize} #{user.email}") do %>
+ <%= user_gravatar_image_tag(user, 20) %>
+ <span class="name">
+ <%= truncate(user.email, :length => 20) %>
+ </span>
+ <% end %>
+ </h5>
+ </div>
+ </div>
+</div>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
index 38a9ff78b..89d01b648 100644
--- a/app/views/users/edit.html.erb
+++ b/app/views/users/edit.html.erb
@@ -1,4 +1,3 @@
<%= title_tag t('.title', :user => @user.email) %>
-<p>iouoiu</p>
<%= render "form" %>
diff --git a/app/views/vehicle_journey_exports/index.xls.erb b/app/views/vehicle_journey_exports/index.xls.erb
new file mode 100644
index 000000000..b6fea2b73
--- /dev/null
+++ b/app/views/vehicle_journey_exports/index.xls.erb
@@ -0,0 +1,26 @@
+<?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>
+ <% vehicle_journey_at_stops_matrix = (@vehicle_journeys.collect{ |vj| vj.vehicle_journey_at_stops.collect(&:departure_time).collect{|time| time.strftime("%H:%M")} }).transpose %>
+ <% @route.stop_points.each_with_index do |stop_point, index| %>
+ <Row>
+ <Cell><Data ss:Type="Number"><%= stop_point.id %></Data></Cell>
+ <Cell><Data ss:Type="String"><%= stop_point.stop_area.name %></Data></Cell>
+ <% vehicle_journey_at_stops_matrix[index].each do |vehicle_journey_at_stop| %>
+ <Cell><Data ss:Type="String"><%= vehicle_journey_at_stop %></Data></Cell>
+ <% end %>
+ </Row>
+ <% end %>
+ </Table>
+ </Worksheet>
+</Workbook>
diff --git a/app/views/vehicle_journey_imports/new.html.erb b/app/views/vehicle_journey_imports/new.html.erb
index a8459848c..7a0e0ac96 100644
--- a/app/views/vehicle_journey_imports/new.html.erb
+++ b/app/views/vehicle_journey_imports/new.html.erb
@@ -1,31 +1,11 @@
<%= title_tag t('vehicle_journey_imports.new.title') %>
<div class="main_actions">
- <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>
- </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>
</div>
<%= semantic_form_for [@referential, @line, @route, @vehicle_journey_import] do |form| %>
- <% if @vehicle_journey_import.errors.any? %>
- <div id="error_explanation">
- <h2><%= pluralize(@vehicle_journey_import.errors.count, "error") %> prohibited this import from completing:</h2>
- <ul>
- <% @vehicle_journey_import.errors.full_messages.each do |msg| %>
- <li><%= msg %></li>
- <% end %>
- </ul>
- </div>
- <% end %>
- <br>
<%= form.inputs do %>
- <%= form.input :file, :as => :file %>
+ <%= 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' ) %>
diff --git a/app/views/vehicle_journeys/_form.html.erb b/app/views/vehicle_journeys/_form.html.erb
index 530fce22e..1c3945164 100644
--- a/app/views/vehicle_journeys/_form.html.erb
+++ b/app/views/vehicle_journeys/_form.html.erb
@@ -1,64 +1,68 @@
<%= semantic_form_for [@referential, @line, @route, @vehicle_journey] do |form| %>
<%= form.inputs do %>
<%= form.input :journey_pattern, :as => :select, :collection => @route.journey_patterns, :member_label => Proc.new { |jp| journey_name(jp) } %>
+ <%= form.input :number %>
<%= form.input :published_journey_name %>
<%= form.input :published_journey_identifier %>
<%= form.input :comment %>
<%= form.input :transport_mode_name, :as => :select, :collection => Chouette::Line.transport_modes, :include_blank => true, :member_label => Proc.new { |mode| t("transport_modes.label.#{mode}") } %>
+ <%= form.input :mobility_restricted_suitability, :as => :select, :collection => [[@vehicle_journey.human_attribute_name("accessible"), true], [@vehicle_journey.human_attribute_name("not_accessible"), false]], :include_blank => true %>
+ <%= form.input :flexible_service, :as => :select, :collection => [[@vehicle_journey.human_attribute_name("on_demaond_fs"), true], [@vehicle_journey.human_attribute_name("regular_fs"), false]], :include_blank => true %>
<%= form.input :status_value %>
<%= form.input :facility %>
<%= form.input :vehicle_type_identifier%>
- <%= form.input :objectid, :required => !@vehicle_journey.new_record? %>
+ <%= form.input :objectid, :required => !@vehicle_journey.new_record?, :input_html => { :title => t("formtastic.titles.vehicle_journey.objectid")} %>
+ <%= form.input :time_table_tokens, :label => t('.time_tables'), :as => :search_time_table, :json => referential_time_tables_path(@referential, :format => :json), :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :input_html => { :"data-pre" => ( @vehicle_journey.time_tables.map{ |time_table| { :id => time_table.id, :tags => time_table.tags.join(','), :day_types => %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| time_table.send(d) }.map{ |d| time_table.human_attribute_name(d).first(2)}.join(''), :comment => time_table.comment, :time_table_bounding => time_table_bounding( time_table), :composition_info => composition_info(time_table) } } ).to_json } %>
+ <li class="input">
+ <%= form.label @vehicle_journey.human_attribute_name(:vehicle_journey_at_stop_ids), :class => "label" %>
+ </li>
- <%= form.inputs :class => "stop_times", :name => @vehicle_journey.human_attribute_name(:vehicle_journey_at_stop_ids) do %>
- <table border="0" class="vehicle_journey_at_stops">
- <thead>
- <tr>
- <th class="hour title"><%= t('.arrival') %></th>
- <th class="stop title" ><%= t('.stop_title') %></th>
- <th class="hour title"><%= t('.departure') %></th>
- </tr>
- </thead>
- <tfoot>
- <tr>
- <td class="title"> <a class="to_departures"><%= t('.to_departures') %></a></td>
- <td class="title" ></td>
- <td class="title"><a class="to_arrivals"><%= t('.to_arrivals') %></a></td>
- </tr>
- </tfoot>
- <tbody class="journey_pattern_dependent_list">
- <%= render :partial => "vehicle_journeys/vehicle_journey_at_stop_fields",
- :collection => @vehicle_journey.vehicle_journey_at_stops, :as => :vehicle_journey_at_stop %>
- </tbody>
- </table>
- <% end %>
- <%= form.input :time_table_tokens, :label => t('.time_tables'), :as => :text, :input_html => { :"data-pre" => ( @vehicle_journey.time_tables.map { |time_table| { :id => time_table.id, :name => time_table.comment } } ).to_json } %>
-
- <% end %>
+ <% unless @vehicle_journey.vehicle_journey_at_stops.empty? ||
+ @vehicle_journey.vehicle_journey_at_stops.any? { |vjas| vjas.departure_time.nil? } %> <div class="vehicle_journey_at_stops">
+ <div class="well">
+ <span class="title"><%= t(".slide_title") %></span>
+ <div>
+ <span><%= t(".set") %></span> <%= select_tag "", options_for_select( [ [t('.slide_departure'), "departure"], [t('.slide_arrival'), "arrival"] ] ), :class => "departure_or_arrival" %> <span><%= t(".to") %></span>
+ <%= select_hour(@vehicle_journey.vehicle_journey_at_stops.first.departure_time.hour) %>
+ <%= select_minute(@vehicle_journey.vehicle_journey_at_stops.first.departure_time.min) %>
+ <a class="slide btn btn-default"><%= t(".slide") %></a>
+ </div>
+ </div>
+ <% end %>
+ <table class="table table-hover table-striped">
+ <thead>
+ <tr>
+ <th class="hour title"><%= t('.arrival') %></th>
+ <th class="stop title" ><%= t('.stop_title') %></th>
+ <th class="hour title"><%= t('.departure') %></th>
+ </tr>
+ </thead>
+ <tfoot>
+ <tr>
+ <td class="title"> <a class="to_departures"><%= t('.to_departures') %></a></td>
+ <td class="title" ></td>
+ <td class="title"><a class="to_arrivals"><%= t('.to_arrivals') %></a></td>
+ </tr>
+ </tfoot>
+ <tbody class="journey_pattern_dependent_list">
+ <%= render :partial => "vehicle_journeys/vehicle_journey_at_stop_fields",
+ :collection => @vehicle_journey.vehicle_journey_at_stops, :as => :vehicle_journey_at_stop, :locals => { :vehicle_journey_at_stops_size => @vehicle_journey.vehicle_journey_at_stops.size } %>
+
+ </tbody>
+ </table>
+
+ <% end %>
+
<%= form.actions do %>
<%= form.action :submit, :as => :button %>
<%= form.action :cancel, :as => :link %>
<% end %>
<% end %>
-
+
<% if @vehicle_journey.new_record? %>
<%= javascript_include_tag new_referential_line_route_vehicle_journey_path(@referential, @line, @route, :format => :js) %>
<% else %>
<%= javascript_include_tag edit_referential_line_route_vehicle_journey_path(@referential, @line, @route, @vehicle_journey, :format => :js) %>
<% end %>
-<script>
- $(function() {
- $( "#vehicle_journey_time_table_tokens" ).tokenInput('<%= comment_filter_referential_time_tables_path(@referential, :format => :json) %>', {
- crossDomain: false,
- prePopulate: $('#time_table_tokens').data('pre'),
- minChars: 3,
- preventDuplicates: true,
- hintText: '<%= t('search_hint') %>',
- noResultsText: '<%= t('no_result_text') %>',
- searchingText: '<%= t('searching_term') %>'
- });
- });
-</script>
-
diff --git a/app/views/vehicle_journeys/_route_popover.html.erb b/app/views/vehicle_journeys/_route_popover.html.erb
new file mode 100644
index 000000000..1acba5665
--- /dev/null
+++ b/app/views/vehicle_journeys/_route_popover.html.erb
@@ -0,0 +1,6 @@
+<ul>
+<% (selected_route.line.routes.limit(10).reject{ |route| route == selected_route}).each do |route| %>
+ <li><%= link_to route.name.truncate(30), [@referential, route.line, route, 'vehicle_journeys'] %></li>
+<% end %>
+</ul>
+</p>
diff --git a/app/views/vehicle_journeys/_show_popover.html.erb b/app/views/vehicle_journeys/_show_popover.html.erb
new file mode 100644
index 000000000..5f6fe51ea
--- /dev/null
+++ b/app/views/vehicle_journeys/_show_popover.html.erb
@@ -0,0 +1,26 @@
+<p>
+ <%= Chouette::JourneyPattern.model_name.human %> : <%= link_to journey_name( vehicle_journey.journey_pattern ), [@referential, @line, @route, vehicle_journey.journey_pattern] %>
+</p>
+<p>
+ <%= vehicle_journey.time_tables.size %> <%= Chouette::TimeTable.model_name.human.pluralize %> <small><%= time_tables_shortest_info( vehicle_journey ) %></small> :
+ <ul>
+ <% vehicle_journey.time_tables.limit(4).each do |time_table| %>
+ <li>
+ <%= link_to [@referential, time_table] do %>
+ <span class="state-code <%= time_table_state_code(time_table) %>"><i class="fa fa-certificate"></i></span> <%= time_table.comment %>
+ <% end %>
+ <% if time_table.tag_list.present? %>
+ <br>
+ <span class="time_table_info"><%= truncate(time_table.tag_list.to_s, :length => 35) %></span>
+ <% end %>
+ <br>
+ <% %w(monday tuesday wednesday thursday friday saturday sunday).each do |day_type| %>
+ <span class="<%= time_table.send( day_type) ? "included_day_type" : "excluded_day_type"%> time_table_info">
+ <%= time_table.human_attribute_name(day_type).first(2) %>
+ </span>
+ <% end %>
+ <span class="bounding"><%= time_table_bounding( time_table) %></span>
+ </li>
+ <% end %>
+ </ul>
+</p>
diff --git a/app/views/vehicle_journeys/_sidebar.html.erb b/app/views/vehicle_journeys/_sidebar.html.erb
new file mode 100644
index 000000000..8d6f310d3
--- /dev/null
+++ b/app/views/vehicle_journeys/_sidebar.html.erb
@@ -0,0 +1,6 @@
+ <ul class="actions">
+ <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('vehicle_journey_imports.new.title'), new_referential_line_route_vehicle_journey_import_path( @referential, @line, @route ), :class => "import" %></li>
+ <li><%= link_to t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, :format => :zip), :class => "export" %></li>
+ </ul>
+
diff --git a/app/views/vehicle_journeys/_time_table.html.erb b/app/views/vehicle_journeys/_time_table.html.erb
index 61043ab3b..f9e51ac37 100644
--- a/app/views/vehicle_journeys/_time_table.html.erb
+++ b/app/views/vehicle_journeys/_time_table.html.erb
@@ -1,15 +1,7 @@
<%= div_for(time_table, :class => "time_table") do %>
- <%= link_to time_table.comment, [@referential, time_table] %>
+ <%= render "time_tables/cell_title", time_table: time_table %>
<div class="info">
- <%= composition_info(time_table) %> -
- <% unless time_table.periods.empty? %>
- <% %w(monday tuesday wednesday thursday friday saturday sunday).each do |day_type| %>
- <span class="<%= time_table.send( day_type) ? "included_day_type" : "excluded_day_type" %>">
- <%= time_table.human_attribute_name(day_type).first(2) %>
- </span>
- <% end %>
- <% end %> -
- <%= bounding_info(time_table) %>
+ <%= render "time_tables/cell_info", time_table: time_table %>
</div>
<% end %>
diff --git a/app/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb b/app/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb
index 150ecde4b..fbd4e733a 100644
--- a/app/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb
+++ b/app/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb
@@ -1,8 +1,11 @@
-<% vjas = vehicle_journey_at_stop %>
+<% vjas = vehicle_journey_at_stop
+ tab_counter_arrival = 2 * vehicle_journey_at_stop_counter + 100
+ tab_counter_departure = (vehicle_journey_at_stops_size * 2) + 2 * vehicle_journey_at_stop_counter + 100
+ %>
<tr class="time input optional <%= vjas._destroy ? "no_stop" : "" %> <%= (vehicle_journey_at_stop_counter%2==0) ? "odd" : "even" %>" >
<td class="arrival_time <%= vjas.arrival_time.nil? ? "missing" : "" %> <%= vjas.errors[:arrival_time].blank? ? "" : "invalid_position" %>">
- <%= select_hour(vjas.arrival_time ? vjas.arrival_time.hour : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][arrival_time(4i)]"}, :class => "hour") %>
- <%= select_minute(vjas.arrival_time ? vjas.arrival_time.min : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][arrival_time(5i)]"}, :class => "minute") %>
+ <%= select_hour(vjas.arrival_time ? vjas.arrival_time.hour : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][arrival_time(4i)]"}, :class => "hour", :tabindex => tab_counter_arrival + 1 ) %>
+ <%= select_minute(vjas.arrival_time ? vjas.arrival_time.min : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][arrival_time(5i)]"}, :class => "minute", :tabindex => tab_counter_arrival + 2) %>
</td>
<td>
<input name=<%= "vehicle_journey[vehicle_journey_at_stops_attributes][#{vehicle_journey_at_stop_counter}][id]" %> type="hidden" value="<%= vjas.id %>">
@@ -17,8 +20,8 @@
<label for=<%= "vehicle_journey_vehicle_journey_at_stops_attributes_#{vehicle_journey_at_stop_counter}_departure_time_5i" %>><%= vjas.stop_point.stop_area.name %></label>
</td>
<td class="departure_time <%= vjas.departure_time.nil? ? "missing" : "" %> <%= vjas.errors[:departure_time].blank? ? "" : "invalid_position" %>">
- <%= select_hour(vjas.departure_time ? vjas.departure_time.hour : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][departure_time(4i)]"}, :class => "hour") %>
- <%= select_minute(vjas.departure_time ? vjas.departure_time.min : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][departure_time(5i)]"}, :class => "minute") %>
+ <%= select_hour(vjas.departure_time ? vjas.departure_time.hour : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][departure_time(4i)]"}, :class => "hour", :tabindex => tab_counter_departure + 1 ) %>
+ <%= select_minute(vjas.departure_time ? vjas.departure_time.min : 0, { :prefix => "vehicle_journey", :field_name => "vehicle_journey_at_stops_attributes[#{vehicle_journey_at_stop_counter}][departure_time(5i)]"}, :class => "minute", :tabindex => tab_counter_departure + 2) %>
</td>
</tr>
diff --git a/app/views/vehicle_journeys/_vehicle_journeys.html.erb b/app/views/vehicle_journeys/_vehicle_journeys.html.erb
new file mode 100644
index 000000000..ecdb12c6e
--- /dev/null
+++ b/app/views/vehicle_journeys/_vehicle_journeys.html.erb
@@ -0,0 +1,39 @@
+<div class="page_info">
+ <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @vehicle_journeys %>
+</div>
+<div class="pagination">
+ <%= will_paginate @vehicle_journeys, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
+<div class="vehicle_journeys paginated_content">
+ <table class="table table-hover table-striped">
+ <thead>
+ <tr>
+ <th class="title">
+ <button data-style="primary" data-container="body" rel="popover" data-toggle="popover" title='<%= t(".line_routes") %>' data-placement="top" data-content='<%= render( partial: "route_popover", :locals => { :selected_route => @route }) %>' class="route_popover btn btn-default btn-sm"><i class='fa fa-search'></i><%= Chouette::Route.model_name.human.capitalize %></button>
+ </th>
+ <% @vehicle_journeys.each do |vj| %>
+ <th class="vehicle_journey">
+ <button data-style="primary" data-container="body" rel="popover" data-toggle="popover" data-title='<%= link_to(vehicle_title(vj), [@referential, @line, @route, vj] ) %> <%= link_to('<span class="fa fa-pencil"></span>'.html_safe, ["edit", @referential, @line, @route, vj], :class => "btn btn-default btn-sm" ) %>' data-placement= "top" data-content='<%= render( partial: "show_popover", :locals => { :vehicle_journey => vj }) %>' class="vehicle_journey_popover btn btn-default btn-sm"><i class='fa fa-search'></i></button>
+ </th>
+ <% end %>
+ </tr>
+ </thead>
+ <tbody>
+ <% @route.stop_points.each_with_index do |sp, index| %>
+ <tr class="<%= cycle('odd', 'even') %>">
+ <td class="stop_area"><%= sp.stop_area.name %></td>
+ <% @vehicle_journeys.each do |vj| %>
+ <td class="hours <%= missing_time_check(@matrix["#{vj.id}-#{sp.id}"]) %>">
+ <%= (@matrix["#{vj.id}-#{sp.id}"] && @matrix["#{vj.id}-#{sp.id}"].departure_time) ? l( @matrix["#{vj.id}-#{sp.id}"].departure_time, :format => :hour) : "--" %>
+ </td>
+ <% end %>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+</div>
+<div class="pagination">
+ <%= will_paginate @vehicle_journeys, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %>
+</div>
+
+
diff --git a/app/views/vehicle_journeys/edit.html.erb b/app/views/vehicle_journeys/edit.html.erb
index dba18248e..51653a34a 100644
--- a/app/views/vehicle_journeys/edit.html.erb
+++ b/app/views/vehicle_journeys/edit.html.erb
@@ -1,17 +1,4 @@
<%= title_tag edit_vehicle_title(@vehicle_journey) %>
-<div class="vehicle_journey">
- <div class="summary">
- <p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
- <label><%= @vehicle_journey.human_attribute_name(:route) %>: </label>
- <%= link_to @route.name, [@referential, @line, @route] %>
- </p>
- </div>
-</div>
-
<%= render "form" %>
diff --git a/app/views/vehicle_journeys/index.html.erb b/app/views/vehicle_journeys/index.html.erb
index 651aea739..990f028e9 100644
--- a/app/views/vehicle_journeys/index.html.erb
+++ b/app/views/vehicle_journeys/index.html.erb
@@ -1,86 +1,91 @@
-<ol class="breadcrumb">
- <li><%= link_to line_formatted_name( @line), [@referential, @line] %></li>
- <li><%= link_to @route.name, [@referential, @line, @route] %></li>
-</ol>
-
<%= title_tag t('vehicle_journeys.index.title', :route => @route.name ) %>
-<div class="page_info">
- <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @vehicle_journeys %>
-</div>
-<div class="pagination">
- <%= will_paginate @vehicle_journeys, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
-<div class="vehicle_journeys paginated_content">
- <table class="table table-hover table-striped">
- <thead>
- <tr>
- <th class="title"><%= Chouette::JourneyPattern.model_name.human.pluralize %> :</th>
- <% @vehicle_journeys.map(&:journey_pattern).each do |jp| %>
- <th><%= link_to journey_name( jp), [@referential, @line, @route, jp] %></th>
- <% end %>
- </tr>
- <tr>
- <th class="title"><%= Chouette::TimeTable.model_name.human.pluralize %> :</th>
- <% @vehicle_journeys.each do |vj| %>
- <th title="<%= time_tables_info( vj) %>" class="calendars">
- <%= time_tables_shortest_info( vj) %>
- </th>
- <% end %>
- </tr>
- <tr>
- <th class="title"><%= Chouette::VehicleJourney.model_name.human.pluralize %> :</th>
- <% @vehicle_journeys.each do |vj| %>
- <th> <%= link_to vehicle_name(vj), [@referential, @line, @route, vj]%></th>
- <% end %>
- </tr>
- </thead>
- <tbody>
- <% @route.stop_points.each_with_index do |sp, index| %>
- <tr class="<%= cycle('odd', 'even') %>">
- <td class="stop_area"><%= sp.stop_area.name %></td>
- <% @vehicle_journeys.each do |vj| %>
- <td class="hours <%= missing_time_check(@matrix["#{vj.id}-#{sp.id}"]) %>">
- <%= (@matrix["#{vj.id}-#{sp.id}"] && @matrix["#{vj.id}-#{sp.id}"].departure_time) ? l( @matrix["#{vj.id}-#{sp.id}"].departure_time, :format => :hour) : "" %>
- </td>
- <% end %>
- </tr>
- <% end %>
- </tbody>
- </table>
-</div>
-<div class="pagination">
- <%= will_paginate @vehicle_journeys, :container => false, renderer: BootstrapPagination::Rails %>
-</div>
-<% content_for :sidebar do %>
- <ul class="actions">
- <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>
- </ul>
- <h4><%= t(".selection") %></h4>
- <h5><%= Chouette::JourneyPattern.model_name.human.pluralize %></h5>
+<%= search_form_for @q, :url => referential_line_route_vehicle_journeys_path(@referential,@line,@route), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| %>
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <%= f.label :journey_pattern_id_eq, "Missions" %>
+ <%= f.text_field(:journey_pattern_id_eq, :class => "form-control") %>
+ <button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
+ <a data-toggle="collapse" data-parent="#search" href="#advanced_search" class="advanced_search">
+ <i class="fa fa-plus"></i> <%= "#{t('.advanced_search')}" %>
+ </a>
+ </div>
+
+ <div id="advanced_search" class="panel-collapse collapse">
+ <div class="panel-body">
+ <div>
+ <%= f.label :time_tables_id_not_eq, "Sans calendrier" %>
+ <%= f.check_box :time_tables_id_not_eq %>
- <ul class="selection">
- <% @route.journey_patterns.each do |journey_pattern| %>
- <li><%= link_with_search journey_name(journey_pattern), "journey_pattern_id_eq" => journey_pattern.id %></li>
- <% end %>
- <li><%= link_with_search t(".selection_all"), {"journey_pattern_id_eq" => nil}, :class => "all" %></li>
- </ul>
+ <span class="time_tables_id_eq">
+ <%= f.label :time_tables_id_eq, "Sélectionner calendriers" %>
+ <%= f.text_field :time_tables_id_eq, :input_html => { :"data-pre" => [].to_json} %>
+ </span>
+ </div>
- <h5><%= Chouette::TimeTable.model_name.human.pluralize %></h5>
+ <div>
+ <%= f.label :vehicle_journey_at_stops_departure_time_not_eq, "Sans horaire" %>
+ <%= f.check_box :vehicle_journey_at_stops_departure_time_not_eq %>
- <ul class="selection">
- <% @route.time_tables.each do |time_table| %>
- <li><%= link_with_search time_table.comment, "time_tables_comment_eq" => time_table.comment %></li>
- <% end %>
- <li><%= link_with_search t(".selection_all"), {"time_tables_comment_eq" => nil}, :class => "all" %></li>
- </ul>
+ <span class="vehicle_journey_at_stops_departure_time_gt">
+ <input name=<%= "q[vehicle_journey_at_stops_departure_time_gt(3i)]" %> type="hidden" value="1">
+ <input name=<%= "q[vehicle_journey_at_stops_departure_time_gt(2i)]" %> type="hidden" value="1">
+ <input name=<%= "q[vehicle_journey_at_stops_departure_time_gt(1i)]" %> type="hidden" value="2000">
+ <%= f.label :vehicle_journey_at_stops_departure_time_gt, t('.time_range') %>
+ <%= select_hour(@q.send( "vehicle_journey_at_stops_departure_time_gt") ? @q.send( "vehicle_journey_at_stops_departure_time_gt").hour : 0,
+ :prefix => "q", :field_name => "vehicle_journey_at_stops_departure_time_gt(4i)") %>
+ <%= select_minute(@q.send( "vehicle_journey_at_stops_departure_time_gt") ? @q.send( "vehicle_journey_at_stops_departure_time_gt").min : 0,
+ :prefix => "q", :field_name => "vehicle_journey_at_stops_departure_time_gt(5i)") %>
+ </span>
+ </div>
+ </div>
+ </div>
+</div>
+<% end %>
+<div id="vehicle_journeys" ><%= render "vehicle_journeys" %></div>
- <h4><%= t('.time_range') %></h4>
- <%= render :partial => "time_filter", :locals => { :time_field => "departure_time"} %>
+<% content_for :sidebar do %>
+ <%= render "sidebar" %>
<% end %>
+<script>
+ $(function() {
+ var time_tables_url = function(){
+ return '<%= referential_time_tables_path(@referential, :format => :json) %>?route_id=<%= @route.id %>';
+ };
+ var time_table_to_html = function( item ){
+ return '<li><div class=\"comment\">' + item.comment +
+ '</div><div class=\"info\">' + item.time_table_bounding +
+ '</div><div class=\"info\">' + item.composition_info + '</div></li>';
+ };
+ $( "#q_time_tables_id_eq" ).tokenInput( time_tables_url, {
+ crossDomain: false,
+ prePopulate: $('#q_time_tables_id_eq').data('pre'),
+ minChars: 3,
+ queryParam: 'q[comment_cont]',
+ propertyToSearch: 'comment',
+ hintText: '<%= t('search_hint') %>',
+ noResultsText: '<%= t('no_result_text') %>',
+ searchingText: '<%= t('searching_term') %>',
+ resultsFormatter: time_table_to_html,
+ tokenFormatter: time_table_to_html,
+ });
+ $( "#q_journey_pattern_id_eq" ).tokenInput( '<%= referential_line_route_journey_patterns_path(@referential, @line, @route, :format => :json) %>', {
+ crossDomain: false,
+ prePopulate: $('#q_journey_pattern_id_eq').data('pre'),
+ minChars: 1,
+ queryParam: 'q[name_cont]',
+ propertyToSearch: 'name',
+ hintText: '<%= t('search_hint') %>',
+ noResultsText: '<%= t('no_result_text') %>',
+ searchingText: '<%= t('searching_term') %>',
+ resultsFormatter: function(item){ return '<li><div class=\"name\">' + item.name + ', (' + item.id + ') </div></li>' },
+ });
+ $( 'input[name="q[time_tables_id_not_eq]"]').change( function(){
+ $('span.time_tables_id_eq').toggle( $(this).filter(":checked").val()==undefined);
+ });
+ $( 'input[name="q[vehicle_journey_at_stops_departure_time_not_eq]"]').change( function(){
+ $('span.vehicle_journey_at_stops_departure_time_gt').toggle( $(this).filter(":checked").val()==undefined);
+ });
+ });
+</script>
diff --git a/app/views/vehicle_journeys/index.js.erb b/app/views/vehicle_journeys/index.js.erb
new file mode 100644
index 000000000..72b57c8fb
--- /dev/null
+++ b/app/views/vehicle_journeys/index.js.erb
@@ -0,0 +1,2 @@
+$('#vehicle_journeys').html('<%= escape_javascript(render("vehicle_journeys")) %>');
+
diff --git a/app/views/vehicle_journeys/new.html.erb b/app/views/vehicle_journeys/new.html.erb
index db344438e..a32e9cc31 100644
--- a/app/views/vehicle_journeys/new.html.erb
+++ b/app/views/vehicle_journeys/new.html.erb
@@ -1,17 +1,4 @@
<%= title_tag t('vehicle_journeys.new.title') %>
-<div class="vehicle_journey">
- <div class="summary">
- <p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
- <label><%= @vehicle_journey.human_attribute_name(:route) %>: </label>
- <%= link_to @route.name, [@referential, @line, @route] %>
- </p>
- <div>
-<div>
-
<%= render "form" %>
diff --git a/app/views/vehicle_journeys/select_journey_pattern.js.erb b/app/views/vehicle_journeys/select_journey_pattern.js.erb
index 3487da1ae..6a32c7b9d 100644
--- a/app/views/vehicle_journeys/select_journey_pattern.js.erb
+++ b/app/views/vehicle_journeys/select_journey_pattern.js.erb
@@ -1,6 +1,7 @@
$('.journey_pattern_dependent_list').html('<%= escape_javascript(
render(:partial => 'vehicle_journeys/vehicle_journey_at_stop_fields',
:collection => @vehicle_journey.vehicle_journey_at_stops,
- :as => :vehicle_journey_at_stop)).html_safe %>');
+ :as => :vehicle_journey_at_stop,
+ :locals => { :vehicle_journey_at_stops_size => @vehicle_journey.vehicle_journey_at_stops.size })).html_safe %>');
diff --git a/app/views/vehicle_journeys/show.html.erb b/app/views/vehicle_journeys/show.html.erb
index e083e81e6..667ca570c 100644
--- a/app/views/vehicle_journeys/show.html.erb
+++ b/app/views/vehicle_journeys/show.html.erb
@@ -1,20 +1,28 @@
<%= title_tag vehicle_title(@vehicle_journey) %>
+<div id="modal_translation" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+ <h4 class="modal-title" id="myModalLabel"><%= t('.translation_form') %></h4>
+ <div id="translate_form"></div>
+ </div>
+ </div>
+ </div>
+</div>
+
<div class="vehicle_journey">
<div class="summary">
<p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
- <label><%= @vehicle_journey.human_attribute_name(:route) %>: </label>
- <%= link_to @route.name, [@referential, @line, @route] %>
- </p>
- <p>
<label><%= @vehicle_journey.human_attribute_name(:journey_pattern) %>: </label>
<%= link_to journey_name(@vehicle_journey.journey_pattern), [@referential, @line, @route, @vehicle_journey.journey_pattern] %>
</p>
<p>
+ <label><%= @vehicle_journey.human_attribute_name("number") %>: </label>
+ <%= @vehicle_journey.number %>
+ </p>
+ <p>
<label><%= @vehicle_journey.human_attribute_name("published_journey_name") %>: </label>
<%= @vehicle_journey.published_journey_name %>
</p>
@@ -22,6 +30,28 @@
<label><%= @vehicle_journey.human_attribute_name("published_journey_identifier") %>: </label>
<%= @vehicle_journey.published_journey_identifier %>
</p>
+
+ <p>
+ <label><%= @vehicle_journey.human_attribute_name("mobility_restricted_suitability") %>: </label>
+ <% if @vehicle_journey.mobility_restricted_suitability.nil? %>
+ <%= @vehicle_journey.human_attribute_name("unspecified_mrs") %>
+ <% elsif @vehicle_journey.mobility_restricted_suitability? %>
+ <%= @vehicle_journey.human_attribute_name("accessible") %>
+ <% else %>
+ <%= @vehicle_journey.human_attribute_name("not_accessible") %>
+ <% end %>
+ </p>
+ <p>
+ <label><%= @vehicle_journey.human_attribute_name("flexible_service") %>: </label>
+ <% if @vehicle_journey.flexible_service.nil? %>
+ <%= @vehicle_journey.human_attribute_name("unspecified_fs") %>
+ <% elsif @vehicle_journey.flexible_service? %>
+ <%= @vehicle_journey.human_attribute_name("on_demaond_fs") %>
+ <% else %>
+ <%= @vehicle_journey.human_attribute_name("regular_fs") %>
+ <% end %>
+ </p>
+
<p>
<label><%= @vehicle_journey.human_attribute_name("comment") %>: </label>
<%= @vehicle_journey.comment %>
@@ -38,15 +68,11 @@
<label><%= @vehicle_journey.human_attribute_name("vehicle_type_identifier") %>: </label>
<%= @vehicle_journey.vehicle_type_identifier %>
</p>
- <p>
- <label><%= @vehicle_journey.human_attribute_name("objectid") %>: </label>
- <%= @vehicle_journey.objectid %>
- </p>
</div>
</div>
<h3><%= @vehicle_journey.human_attribute_name(:vehicle_journey_at_stop_ids) %></h3>
<div class="vehicle_journey_at_stops content">
- <table class="table table-hover">
+ <table class="table table-hover table-striped">
<thead>
<tr>
<th class="hour title"><%= t('.arrival') %></th>
@@ -68,28 +94,18 @@
<h3><%= t('.time_tables') %></h3>
<div class="time_tables paginated_content">
- <%= paginated_content @vehicle_journey.time_tables, "time_table" %>
+ <%= paginated_content @vehicle_journey.time_tables, "time_tables/time_table", :delete => false %>
</div>
+
<% content_for :sidebar do %>
<ul class="actions">
+ <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('vehicle_journeys.actions.edit'), edit_referential_line_route_vehicle_journey_path(@referential, @line, @route, @vehicle_journey), :class => "edit" %></li>
- <li><%= link_to t('vehicle_journeys.actions.destroy'), referential_line_route_vehicle_journey_path(@referential, @line, @route, @vehicle_journey), :method => :delete, :data => {:confirm => t('vehicle_journeys.actions.destroy_confirm')}, :class => "remove" %></li>
+ <li><%= link_to t('vehicle_journeys.actions.destroy'), referential_line_route_vehicle_journey_path(@referential, @line, @route, @vehicle_journey), :method => :delete, :data => {:confirm => t('vehicle_journeys.actions.destroy_confirm')}, :class => "remove" %></li>
+ <% unless @vehicle_journey.vehicle_journey_at_stops.empty? %>
+ <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>
- <% unless @vehicle_journey.vehicle_journey_at_stops.empty? ||
- @vehicle_journey.vehicle_journey_at_stops.any? { |vjas| vjas.departure_time.nil? } %>
- <h4><%= t('.translation_form') %></h4>
- <div id="compact_form" >
- <%= semantic_form_for [@referential, @line, @route, @vehicle_journey, VehicleTranslation.new] do |form| %>
- <%= form.inputs do %>
- <%= form.input :duration %>
- <%= form.input :count %>
- <% end %>
- <%= form.actions do %>
- <%= form.action :submit, :as => :button, :label => t('.validation') %>
- <% end %>
- <% end %>
- </div>
<%= creation_tag(@vehicle_journey) %>
- <% end %>
<% end %>
diff --git a/app/views/vehicle_journeys/timeless.html.erb b/app/views/vehicle_journeys/timeless.html.erb
deleted file mode 100644
index af5ee93ea..000000000
--- a/app/views/vehicle_journeys/timeless.html.erb
+++ /dev/null
@@ -1,28 +0,0 @@
-<%= title_tag t('.title', :route => @route.name ) %>
-
-<div class="timeless_vehicle_journey_index">
- <div class="summary">
- <p>
- <label><%= @route.human_attribute_name(:line) %>: </label>
- <%= link_to line_formatted_name( @line), [@referential, @line] %>
- </p>
- <p>
- <label><%= Chouette::Route.model_name.human %>: </label>
- <%= link_to @route.name, [@referential, @line, @route] %>
- </p>
- </div>
-</div>
-
-<h3><%= t('.vehicles_list') %></h3>
-<div class="timeless_vehicles">
- <%= render :partial => "timeless_vehicle_journey", :collection => @vehicle_journeys, :as => :vehicle_journey %>
-</div>
-
-<% content_for :sidebar do %>
-<ul class="actions">
- <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('.vehicle_journeys'), [@referential, @line, @route, :vehicle_journeys], :class => "link" %></li>
-</ul>
-<% end %>
diff --git a/app/views/vehicle_translations/_translate_form.html.erb b/app/views/vehicle_translations/_translate_form.html.erb
new file mode 100644
index 000000000..0ca6a6b84
--- /dev/null
+++ b/app/views/vehicle_translations/_translate_form.html.erb
@@ -0,0 +1,24 @@
+<%= render "shared/flash_messages" %>
+<%= semantic_form_for [@referential, @line, @route, @vehicle_journey, @vehicle_translation], remote: true do |form| %>
+ <div class="modal-body">
+ <%= form.inputs do %>
+ <%= form.input :departure_or_arrival, as: :select, label: t('.set'), collection: [ [ t('.first_stop_departure_time', stop_name: @vehicle_translation.first_stop_name), "departure"], [t('.first_stop_arrival_time', stop_name: @vehicle_translation.first_stop_name), "arrival"] ], include_blank: false, required: true %>
+ <%= form.input :first_stop_time,
+ as: :time_picker, label: t( ".to"),
+ input_html: { class: "form-control input-sm timepicker_basic"}, wrapper_html: { class: "input-append bootstrap-timepicker" } %>
+
+ <div class="repeat_cloning">
+ <h4>
+ <%= t('.multiple_cloning_form') %>
+ </h4>
+ <%= form.input :duration, as: :number %>
+ <%= form.input :count, as: :number %>
+ </div>
+ <% end %>
+ </div>
+ <div class="modal-footer">
+ <%= form.actions do %>
+ <%= form.action :submit, as: :button, label: t('formtastic.clone') %>
+ <% end %>
+ </div>
+<% end %>
diff --git a/app/views/vehicle_translations/new.js.erb b/app/views/vehicle_translations/new.js.erb
new file mode 100644
index 000000000..0c7869fb6
--- /dev/null
+++ b/app/views/vehicle_translations/new.js.erb
@@ -0,0 +1,4 @@
+var modal_translation_content = '<%= escape_javascript( render "vehicle_translations/translate_form") %> ';
+$('#translate_form').html(modal_translation_content);
+
+
diff --git a/config/application.rb b/config/application.rb
index 8032f9e9a..d86b254f3 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,5 +1,7 @@
require File.expand_path('../boot', __FILE__)
+ENV['RANSACK_FORM_BUILDER'] = '::SimpleForm::FormBuilder'
+
require 'rails/all'
if defined?(Bundler)
@@ -21,7 +23,7 @@ module ChouetteIhm
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
- # config.autoload_paths += %W(#{config.root}/extras)
+ config.autoload_paths += %W(#{config.root}/lib)
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
diff --git a/config/deploy.rb b/config/deploy.rb
index c3dbb5db5..4d7e28009 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -1,7 +1,7 @@
require 'capistrano/ext/multistage'
require './config/boot'
-set :stages, %w(sandbox unstable staging production)
+set :stages, %w(sandbox unstable staging production sismo)
set :application, "chouette2"
set :scm, :git
set :repository, "https://github.com/afimb/chouette2.git"
@@ -12,7 +12,7 @@ set :group_writable, true
set :rake, "bundle exec rake"
set :keep_releases, 4
set :rails_env, "production" #added for delayed job
-set :user, "mflorisson"
+set :user, "ldonnet"
set :deploy_via, :copy
set :copy_via, :scp
set :copy_exclude, ".git/*"
@@ -64,7 +64,7 @@ namespace :deploy do
desc "Install chouette command"
task :chouette_command, :except => { :no_release => true } do
run "mkdir -p /var/lib/chouette/imports"
- run "mkdir -p /var/lib/chouette/imports"
+ run "mkdir -p /var/lib/chouette/exports"
run "mkdir -p /var/lib/chouette/validations"
run "mkdir -p /usr/local/opt/chouette-command/"
end
diff --git a/config/deploy/sismo.rb b/config/deploy/sismo.rb
new file mode 100644
index 000000000..a8cb59006
--- /dev/null
+++ b/config/deploy/sismo.rb
@@ -0,0 +1,2 @@
+server "chouette-sismo.marseille.cityway.fr", :app, :web, :db, :primary => true
+set :branch, "V2_5"
diff --git a/config/deploy/unstable.rb b/config/deploy/unstable.rb
index 82b4724db..0c19b9fbc 100644
--- a/config/deploy/unstable.rb
+++ b/config/deploy/unstable.rb
@@ -1,2 +1,2 @@
server "chouette-p.aix.cityway.fr", :app, :web, :db, :primary => true
-set :branch, "master"
+set :branch, "sismo"
diff --git a/config/environment.rb b/config/environment.rb
index 299eb7b07..cc2b4fa95 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -6,4 +6,4 @@ require File.expand_path('../application', __FILE__)
ChouetteIhm::Application.initialize!
# Fix version
-APP_VERSION = '2.4.1'
+APP_VERSION = '2.5.0'
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 842d9a471..0d33ac03c 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -45,13 +45,21 @@ ChouetteIhm::Application.configure do
GA.tracker = "UA-AAAAAAAA"
# api key to geoportail IGN (production key link to application url root referer)
- config.geoportail_api_key = "aaaaaaaaaaaaaa"
+ #config.geoportail_api_key = "aaaaaaaaaaaaaa"
- # Specific for each company
- config.company_name = "afimb"
- config.company_theme = "#61970b"
+ # Specific theme for each company
+ # AFIMB
+ config.company_name = "afimb"
+ config.company_theme = "#61970b" # AFIMB color
config.company_contact = "http://www.chouette.mobi/contact-support/"
+ config.accept_user_creation = true
+ # CITYWAY
+ # config.company_name = "cityway"
+ # config.company_theme = "#32adb0"
+ # config.company_contact = "http://www.cityway.fr/contact/?rub_code=14"
+ # config.accept_user_creation = false
+
# file to data for demo
config.demo_data = "tmp/demo.zip"
diff --git a/config/environments/production.rb b/config/environments/production.rb
index c0dcc1933..de408f29f 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -126,16 +126,22 @@ ChouetteIhm::Application.configure do
end
# api key to geoportail IGN (production key link to application url root referer)
- if ENV['CHOUETTE_GEOPORTAIL_KEY'].nil?
- config.geoportail_api_key = "aaaaaaaaaaaaaa"
- else
+ if !ENV['CHOUETTE_GEOPORTAIL_KEY'].nil?
config.geoportail_api_key = ENV['CHOUETTE_GEOPORTAIL_KEY']
end
- # Specific for each company
- config.company_name = "afimb"
- config.company_theme = "#61970b"
+ # Specific theme for each company
+ # AFIMB
+ config.company_name = "afimb"
+ config.company_theme = "#61970b" # AFIMB color
config.company_contact = "http://www.chouette.mobi/contact-support/"
+ config.accept_user_creation = true
+
+ # CITYWAY
+ # config.company_name = "cityway"
+ # config.company_theme = "#32adb0"
+ # config.company_contact = "http://www.cityway.fr/contact/?rub_code=14"
+ # config.accept_user_creation = false
# file to data for demo
config.demo_data = ENV['CHOUETTE_DEMO_DATA'].nil? ? "/path/to/demo.zip" : ENV['CHOUETTE_DEMO_DATA']
@@ -146,7 +152,7 @@ ChouetteIhm::Application.configure do
# paths for external resources
config.to_prepare do
Devise::Mailer.layout "mailer"
- Chouette::Command.command = ENV['CHOUETTE_GUI_COMMAND'].nil? ? "/usr/local/opt/chouette-command/chouette-cmd_2.4.1/chouette" : ENV['CHOUETTE_GUI_COMMAND']
+ Chouette::Command.command = ENV['CHOUETTE_GUI_COMMAND'].nil? ? "/usr/local/opt/chouette-command/chouette-cmd_2.5.0/chouette" : ENV['CHOUETTE_GUI_COMMAND']
ImportTask.root = "/var/lib/chouette/imports"
Export.root = "/var/lib/chouette/exports"
end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index ef5c89fbf..8434a26c8 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -1,6 +1,7 @@
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
+
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
@@ -243,24 +244,10 @@ Devise.setup do |config|
# end
end
-# class Devise::FailureApp
-# def return_to_root_path?
-# root_path == session["#{scope}_return_to"]
-# end
-# def redirect
-# store_location!
-# if flash[:timedout] && flash[:alert]
-# flash.keep(:timedout)
-# flash.keep(:alert)
-# else
-# Rails.logger.debug "A" * 30
-# Rails.logger.debug i18n_message
-# Rails.logger.debug redirect_url
-# Rails.logger.debug scope
-# Rails.logger.debug root_path
-# Rails.logger.debug session["#{scope}_return_to"]
-# flash[:alert] = i18n_message unless return_to_root_path?
-# end
-# redirect_to redirect_url
-# end
-# end
+Rails.application.config.to_prepare do
+ Devise::SessionsController.layout "devise"
+ Devise::RegistrationsController.layout proc{ |controller| ( action_name == "edit") ? "application" : "devise" }
+ Devise::ConfirmationsController.layout "devise"
+ Devise::UnlocksController.layout "devise"
+ Devise::PasswordsController.layout "devise"
+end
diff --git a/config/initializers/formtastic.rb b/config/initializers/formtastic.rb
index c1f7f972f..2cdc37243 100644
--- a/config/initializers/formtastic.rb
+++ b/config/initializers/formtastic.rb
@@ -1,20 +1,76 @@
- Formtastic::FormBuilder.i18n_lookups_by_default = true
-
-module Formtastic
- module Inputs
- class CheckBoxesInput
- def selected_values
- if object.respond_to?(method)
- selected_items = [object.send(method)].compact.flatten
-
- # FIX for ids only
- return selected_items.map(&:to_s).compact if selected_items.all?{ |i| i.is_a? Integer}
-
- [*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
- else
- []
- end
- end
- end
- end
-end
+# encoding: utf-8
+
+# Set the default text field size when input is a string. Default is nil.
+Formtastic::FormBuilder.default_text_field_size = 50
+
+# Set the default text area height when input is a text. Default is 20.
+Formtastic::FormBuilder.default_text_area_height = 5
+
+# Set the default text area width when input is a text. Default is nil.
+Formtastic::FormBuilder.default_text_area_width = 50
+
+# Should all fields be considered "required" by default?
+# Defaults to true.
+# Formtastic::FormBuilder.all_fields_required_by_default = true
+
+# Should select fields have a blank option/prompt by default?
+# Defaults to true.
+# Formtastic::FormBuilder.include_blank_for_select_by_default = true
+
+# Set the string that will be appended to the labels/fieldsets which are required
+# It accepts string or procs and the default is a localized version of
+# '<abbr title="required">*</abbr>'. In other words, if you configure formtastic.required
+# in your locale, it will replace the abbr title properly. But if you don't want to use
+# abbr tag, you can simply give a string as below
+# Formtastic::FormBuilder.required_string = "(required)"
+
+# Set the string that will be appended to the labels/fieldsets which are optional
+# Defaults to an empty string ("") and also accepts procs (see required_string above)
+# Formtastic::FormBuilder.optional_string = "(optional)"
+
+# Set the way inline errors will be displayed.
+# Defaults to :sentence, valid options are :sentence, :list, :first and :none
+# Formtastic::FormBuilder.inline_errors = :sentence
+# Formtastic uses the following classes as default for hints, inline_errors and error list
+
+# If you override the class here, please ensure to override it in your stylesheets as well
+# Formtastic::FormBuilder.default_hint_class = "inline-hints"
+# Formtastic::FormBuilder.default_inline_error_class = "inline-errors"
+# Formtastic::FormBuilder.default_error_list_class = "errors"
+
+# Set the method to call on label text to transform or format it for human-friendly
+# reading when formtastic is used without object. Defaults to :humanize.
+# Formtastic::FormBuilder.label_str_method = :humanize
+
+# Set the array of methods to try calling on parent objects in :select and :radio inputs
+# for the text inside each @<option>@ tag or alongside each radio @<input>@. The first method
+# that is found on the object will be used.
+# Defaults to ["to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"]
+# Formtastic::FormBuilder.collection_label_methods = [
+# "to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"]
+
+# Specifies if labels/hints for input fields automatically be looked up using I18n.
+# Default value: true. Overridden for specific fields by setting value to true,
+# i.e. :label => true, or :hint => true (or opposite depending on initialized value)
+# Formtastic::FormBuilder.i18n_lookups_by_default = false
+
+# Specifies if I18n lookups of the default I18n Localizer should be cached to improve performance.
+# Defaults to true.
+# Formtastic::FormBuilder.i18n_cache_lookups = false
+
+# Specifies the class to use for localization lookups. You can create your own
+# class and use it instead by subclassing Formtastic::Localizer (which is the default).
+# Formtastic::FormBuilder.i18n_localizer = MyOwnLocalizer
+
+# You can add custom inputs or override parts of Formtastic by subclassing Formtastic::FormBuilder and
+# specifying that class here. Defaults to Formtastic::FormBuilder.
+# Formtastic::Helpers::FormHelper.builder = MyCustomBuilder
+
+# You can opt-in to Formtastic's use of the HTML5 `required` attribute on `<input>`, `<select>`
+# and `<textarea>` tags by setting this to false (defaults to true).
+# Formtastic::FormBuilder.use_required_attribute = true
+
+# You can opt-in to new HTML5 browser validations (for things like email and url inputs) by setting
+# this to false. Doing so will add a `novalidate` attribute to the `<form>` tag.
+# See http://diveintohtml5.org/forms.html#validation for more info.
+# Formtastic::FormBuilder.perform_browser_validations = true
diff --git a/config/initializers/rabl_config.rb b/config/initializers/rabl_config.rb
index 2dcac1a0d..22ae54788 100644
--- a/config/initializers/rabl_config.rb
+++ b/config/initializers/rabl_config.rb
@@ -1,5 +1,27 @@
Rabl.configure do |config|
+ # Commented as these are defaults
+ # config.cache_all_output = false
+ # config.cache_sources = Rails.env != 'development' # Defaults to false
+ # config.cache_engine = Rabl::CacheEngine.new # Defaults to Rails cache
+ # config.perform_caching = false
+ # config.escape_all_output = false
+ # config.json_engine = nil # Class with #dump class method (defaults JSON)
+ # config.msgpack_engine = nil # Defaults to ::MessagePack
+ # config.bson_engine = nil # Defaults to ::BSON
+ # config.plist_engine = nil # Defaults to ::Plist::Emit
config.include_json_root = false
+ # config.include_msgpack_root = true
+ # config.include_bson_root = true
+ # config.include_plist_root = true
+ # config.include_xml_root = false
+ # config.include_child_root = true
+ # config.enable_json_callbacks = false
config.xml_options = { :camelize => true }
+ # config.view_paths = []
+ # config.raise_on_missing_attribute = true # Defaults to false
+ # config.replace_nil_values_with_empty_strings = true
+ # config.replace_empty_string_values_with_nil_values = true # Defaults to false
+ # config.exclude_nil_values = true # Defaults to false
+ # config.exclude_empty_values_in_collections = true # Defaults to false
end
diff --git a/config/initializers/remove_simple_form_bootstrap3_inputs.rb b/config/initializers/remove_simple_form_bootstrap3_inputs.rb
new file mode 100644
index 000000000..448487308
--- /dev/null
+++ b/config/initializers/remove_simple_form_bootstrap3_inputs.rb
@@ -0,0 +1,32 @@
+inputs = %w[
+ CollectionSelectInput
+ DateTimeInput
+ FileInput
+ GroupedCollectionSelectInput
+ NumericInput
+ PasswordInput
+ RangeInput
+ StringInput
+ TextInput
+]
+
+# Instead of creating top-level custom input classes like TextInput, we wrap it into a module and override
+# mapping in SimpleForm::FormBuilder directly
+#
+SimpleFormBootstrapInputs = Module.new
+inputs.each do |input_type|
+ superclass = "SimpleForm::Inputs::#{input_type}".constantize
+
+ new_class = SimpleFormBootstrapInputs.const_set(input_type, Class.new(superclass) do
+ def input_html_classes
+ super.push('form-control')
+ end
+ end)
+
+ # Now override existing usages of superclass with new_class
+ SimpleForm::FormBuilder.mappings.each do |(type, target_class)|
+ if target_class == superclass
+ SimpleForm::FormBuilder.map_type(type, to: new_class)
+ end
+ end
+end
diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb
new file mode 100644
index 000000000..e2ad34eee
--- /dev/null
+++ b/config/initializers/simple_form.rb
@@ -0,0 +1,142 @@
+# Use this setup block to configure all options available in SimpleForm.
+SimpleForm.setup do |config|
+ # Wrappers are used by the form builder to generate a
+ # complete input. You can remove any component from the
+ # wrapper, change the order or even add your own to the
+ # stack. The options given below are used to wrap the
+ # whole input.
+ config.wrappers :default, :class => :input,
+ :hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
+ ## Extensions enabled by default
+ # Any of these extensions can be disabled for a
+ # given input by passing: `f.input EXTENSION_NAME => false`.
+ # You can make any of these extensions optional by
+ # renaming `b.use` to `b.optional`.
+
+ # Determines whether to use HTML5 (:email, :url, ...)
+ # and required attributes
+ b.use :html5
+
+ # Calculates placeholders automatically from I18n
+ # You can also pass a string as f.input :placeholder => "Placeholder"
+ b.use :placeholder
+
+ ## Optional extensions
+ # They are disabled unless you pass `f.input EXTENSION_NAME => :lookup`
+ # to the input. If so, they will retrieve the values from the model
+ # if any exists. If you want to enable the lookup for any of those
+ # extensions by default, you can change `b.optional` to `b.use`.
+
+ # Calculates maxlength from length validations for string inputs
+ b.optional :maxlength
+
+ # Calculates pattern from format validations for string inputs
+ b.optional :pattern
+
+ # Calculates min and max from length validations for numeric inputs
+ b.optional :min_max
+
+ # Calculates readonly automatically from readonly attributes
+ b.optional :readonly
+
+ ## Inputs
+ b.use :label_input
+ b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
+ b.use :error, :wrap_with => { :tag => :span, :class => :error }
+ end
+
+ # The default wrapper to be used by the FormBuilder.
+ config.default_wrapper = :default
+
+ # Define the way to render check boxes / radio buttons with labels.
+ # Defaults to :nested for bootstrap config.
+ # :inline => input + label
+ # :nested => label > input
+ config.boolean_style = :nested
+
+ # Default class for buttons
+ config.button_class = 'btn'
+
+ # Method used to tidy up errors. Specify any Rails Array method.
+ # :first lists the first message for each field.
+ # Use :to_sentence to list all errors for each field.
+ # config.error_method = :first
+
+ # Default tag used for error notification helper.
+ config.error_notification_tag = :div
+
+ # CSS class to add for error notification helper.
+ config.error_notification_class = 'alert alert-error'
+
+ # ID to add for error notification helper.
+ # config.error_notification_id = nil
+
+ # Series of attempts to detect a default label method for collection.
+ # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
+
+ # Series of attempts to detect a default value method for collection.
+ # config.collection_value_methods = [ :id, :to_s ]
+
+ # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
+ # config.collection_wrapper_tag = nil
+
+ # You can define the class to use on all collection wrappers. Defaulting to none.
+ # config.collection_wrapper_class = nil
+
+ # You can wrap each item in a collection of radio/check boxes with a tag,
+ # defaulting to :span. Please note that when using :boolean_style = :nested,
+ # SimpleForm will force this option to be a label.
+ # config.item_wrapper_tag = :span
+
+ # You can define a class to use in all item wrappers. Defaulting to none.
+ # config.item_wrapper_class = nil
+
+ # How the label text should be generated altogether with the required text.
+ # config.label_text = lambda { |label, required| "#{required} #{label}" }
+
+ # You can define the class to use on all labels. Default is nil.
+ config.label_class = 'col-lg-2 control-label'
+
+ # You can define the class to use on all forms. Default is simple_form.
+ config.form_class = "simple_form form-horizontal"
+
+ # You can define which elements should obtain additional classes
+ # config.generate_additional_classes_for = [:wrapper, :label, :input]
+
+ # Whether attributes are required by default (or not). Default is true.
+ # config.required_by_default = true
+
+ # Tell browsers whether to use default HTML5 validations (novalidate option).
+ # Default is enabled.
+ config.browser_validations = false
+
+ # Collection of methods to detect if a file type was given.
+ # config.file_methods = [ :mounted_as, :file?, :public_filename ]
+
+ # Custom mappings for input types. This should be a hash containing a regexp
+ # to match as key, and the input type that will be used when the field name
+ # matches the regexp as value.
+ # config.input_mappings = { /count/ => :integer }
+
+ # Custom wrappers for input types. This should be a hash containing an input
+ # type as key and the wrapper that will be used for all inputs with specified type.
+ # config.wrapper_mappings = { :string => :prepend }
+
+ # Default priority for time_zone inputs.
+ # config.time_zone_priority = nil
+
+ # Default priority for country inputs.
+ # config.country_priority = nil
+
+ # Default size for text inputs.
+ # config.default_input_size = 50
+
+ # When false, do not use translations for labels.
+ # config.translate_labels = true
+
+ # Automatically discover new inputs in Rails' autoload path.
+ # config.inputs_discovery = false
+
+ # Cache SimpleForm inputs discovery
+ # config.cache_discovery = !Rails.env.development?
+end
diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb
new file mode 100644
index 000000000..c3dd5e348
--- /dev/null
+++ b/config/initializers/simple_form_bootstrap.rb
@@ -0,0 +1,58 @@
+# Use this setup block to configure all options available in SimpleForm.
+SimpleForm.setup do |config|
+ config.wrappers :bootstrap, :tag => 'div', :class => 'form-group', :error_class => 'error' do |b|
+ b.use :html5
+ b.use :placeholder
+ b.use :label
+ b.wrapper :tag => 'div', :class => 'col-lg-10' do |ba|
+ ba.use :input
+ ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
+ ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
+ end
+ end
+
+ config.wrappers :form_without_label, :tag => 'div', :class => 'form-group', :error_class => 'error' do |b|
+ b.use :html5
+ b.use :placeholder
+ b.use :label
+ b.wrapper :tag => 'div', :class => 'col-lg-12' do |ba|
+ ba.use :input
+ ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
+ ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
+ end
+ end
+
+ config.wrappers :prepend, :tag => 'div', :class => "form-group", :error_class => 'error' do |b|
+ b.use :html5
+ b.use :placeholder
+ b.use :label
+ b.wrapper :tag => 'div', :class => 'col-lg-10' do |input|
+ input.wrapper :tag => 'div', :class => 'input-prepend' do |prepend|
+ prepend.use :input
+ end
+ input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
+ input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
+ end
+ end
+
+ config.wrappers :append, :tag => 'div', :class => "form-group", :error_class => 'error' do |b|
+ b.use :html5
+ b.use :placeholder
+ b.use :label
+ b.wrapper :tag => 'div', :class => 'col-lg-10' do |input|
+ input.wrapper :tag => 'div', :class => 'input-append' do |append|
+ append.use :input
+ end
+ input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
+ input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
+ end
+ end
+
+ # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
+ # Check the Bootstrap docs (http://twitter.github.com/bootstrap)
+ # to learn about the different styles for forms and inputs,
+ # buttons and other elements.
+ config.default_wrapper = :bootstrap
+ config.button_class = 'btn'
+ config.label_class = 'col-lg-2 control-label'
+end
diff --git a/config/locales/access_links.yml b/config/locales/access_links.yml
index b714bfad4..0a0aeedbb 100644
--- a/config/locales/access_links.yml
+++ b/config/locales/access_links.yml
@@ -40,7 +40,7 @@ en:
creation_time: "Created on"
creatorid: "Created by "
formtastic:
- hints:
+ titles:
access_link:
objectid: "[prefix]:AccessLink:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -86,7 +86,7 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
access_link:
objectid: "[prefixe]:AccessLink:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/access_points.yml b/config/locales/access_points.yml
index 470a6914b..d6352253c 100644
--- a/config/locales/access_points.yml
+++ b/config/locales/access_points.yml
@@ -41,6 +41,7 @@ en:
projection: "Projection type"
projection_x: "x-position"
projection_y: "y-position"
+ projection_xy: "position (x,y)"
long_lat_type: "Projection type"
longitude: "Longitude"
latitude: "Latitude"
@@ -51,10 +52,15 @@ en:
object_version: "Version"
creation_time: "Created on"
creatorid: "Created by"
+ coordinates: "Coordinates (lat,lng)"
+ zip_code: "Zip code"
+ city_name: "City"
formtastic:
- hints:
+ titles:
access_point:
objectid: "[prefix]:AccessPoint:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
+ coordinates: "latitude,longitude in WGS84 referential, dot for decimal separator"
+ projection_xy: "x,y in secondary referential, dot for decimal separator"
fr:
access_points:
@@ -97,6 +103,7 @@ fr:
projection: "Projection"
projection_x: "Position X"
projection_y: "Position Y"
+ projection_xy: "Position (x,y)"
long_lat_type: "Projection"
longitude: "Longitude"
latitude: "Latitude"
@@ -109,9 +116,14 @@ fr:
object_version: "Version"
creation_time: "Créé le"
creator_id: "Créé par"
+ coordinates: "Coordonnées (lat,lng)"
+ zip_code: "Code postal"
+ city_name: "Commune"
formtastic:
- hints:
+ titles:
access_point:
objectid: "[prefixe]:AccessPoint:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
+ coordinates: "latitude,longitude dans le référentiel WGS84, le séparateur de décimales est 'point'"
+ projection_xy: "x,y dans le référentiel secondaire, le séparateur de décimales est 'point'"
diff --git a/config/locales/breadcrumbs.yml b/config/locales/breadcrumbs.yml
new file mode 100644
index 000000000..ccf97c414
--- /dev/null
+++ b/config/locales/breadcrumbs.yml
@@ -0,0 +1,10 @@
+en:
+ breadcrumbs:
+ vehicle_journeys: "Passing times"
+ referentials: "Home"
+ users: "Users"
+fr:
+ breadcrumbs:
+ vehicle_journeys: "Horaires"
+ referentials: "Accueil"
+ users: "Utilisateurs"
diff --git a/config/locales/clean_ups.yml b/config/locales/clean_ups.yml
index 09abc5adf..48d22981e 100644
--- a/config/locales/clean_ups.yml
+++ b/config/locales/clean_ups.yml
@@ -16,16 +16,15 @@ en:
activemodel:
attributes:
clean_up:
- expected_date: "Final date"
+ expected_date: "Final date : "
keep_lines: "keep lines"
keep_stops: "keep stop areas"
keep_companies: "keep companies"
keep_networks: "keep networks"
keep_group_of_lines: "keep groups of lines"
- formtastic:
- hints:
- clean_up:
- expected_date: "value included in clean up"
+ titles:
+ clean_up:
+ expected_date: "value included in clean up"
fr:
clean_ups:
success_tm: "%{count} calendrier(s) supprimé(s)"
@@ -44,14 +43,13 @@ fr:
activemodel:
attributes:
clean_up:
- expected_date: "date limite"
+ expected_date: "Date limite : "
keep_lines: "conserver les lignes"
keep_stops: "conserver les arrêts"
keep_companies: "conserver les transporteurs"
keep_networks: "conserver les réseaux"
keep_group_of_lines: "conserver les groupes de lignes"
- formtastic:
- hints:
- clean_up:
- expected_date: "valeur incluse dans la purge"
+ titles:
+ clean_up:
+ expected_date: "valeur incluse dans la purge"
diff --git a/config/locales/companies.yml b/config/locales/companies.yml
index 3585f3ff5..aad451fc8 100644
--- a/config/locales/companies.yml
+++ b/config/locales/companies.yml
@@ -13,7 +13,7 @@ en:
title: "Company %{company}"
index:
title: "Companies"
- name: "Name"
+ name: "Search by name"
activerecord:
models:
@@ -28,7 +28,7 @@ en:
short_name: "Short name"
organizational_unit: "Unit"
operating_department_name: "Department"
- code: "Postcode"
+ code: "Code"
phone: "Phone number"
fax: "Fax number"
email: "Email"
@@ -37,7 +37,7 @@ en:
creation_time: "Created on"
creator_id: "Created by "
formtastic:
- hints:
+ titles:
company:
registration_number: "only alphanumerical or underscore characters "
objectid: "[prefix]:Company:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -57,7 +57,7 @@ fr:
title: "Transporteur %{company}"
index:
title: "Transporteurs"
- name: "Nom"
+ name: "Recherche par nom"
activerecord:
models:
@@ -72,7 +72,7 @@ fr:
short_name: "Nom court"
organizational_unit: "Nom d'unité dans la société"
operating_department_name: "Nom du département dans la société"
- code: "Code postal"
+ code: "Code"
phone: "Numéro de téléphone"
fax: "Numéro de fax"
email: "Email"
@@ -81,7 +81,7 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
company:
registration_number: "caractères autorisés : alphanumériques et 'souligné'"
objectid: "[prefixe]:Company:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/compliance_check_results.yml b/config/locales/compliance_check_results.yml
index cc6196e52..96ac952fe 100644
--- a/config/locales/compliance_check_results.yml
+++ b/config/locales/compliance_check_results.yml
@@ -96,6 +96,7 @@ en:
detail_3_stoparea_3: "Les arrêts %{name} (%{objectId} et %{areaId}) sont desservis par les mêmes lignes"
detail_3_stoparea_4: "L'arrêt %{name} (%{objectId}) est en dehors du périmètre de contrôle"
detail_3_stoparea_5: "L'arrêt %{name} (%{objectId}) est localisé trop loin de son parent %{parentName} (%{parentId}) : distance %{distance} > %{distanceLimit}"
+ detail_3_stoparea_6: "L'arrêt %{name} (%{objectId}) n'a pas de code commune"
detail_3_accesspoint_1: "L'accès %{name} (%{objectId}) de l'arrêt %{areaName} (%{areaId}) n'est pas géolocalisé"
detail_3_accesspoint_2: "L'accès %{name} (%{objectId}) est localisé trop près de l'accès %{accessName} (%{accessId}) : distance %{distance} < %{distanceLimit}"
detail_3_accesspoint_3: "L'accès %{name} (%{objectId}) est localisé trop loin de son parent %{parentName} (%{parentId}) : distance %{distance} > %{distanceLimit}"
@@ -113,6 +114,7 @@ en:
detail_3_accesslink_3_4: "Sur le lien d'accès %{name} (%{objectId}), la vitesse pour un voyageur à mobilité réduite %{speed} est supérieure à %{speedLimit} km/h"
detail_3_line_1: "La ligne %{number} : %{name} ( %{objectId}) a une ligne homonyme sur le même réseau %{networkName} (%{networkId})"
detail_3_line_2: "La ligne %{number} : %{name} ( %{objectId}) n'a pas de séquence d'arrêts"
+ detail_3_line_3: "La ligne %{number} : %{name} ( %{objectId}) a un mode de transport interdit %{transportMode}"
detail_3_route_1: "Sur la séquence d'arrêt %{objectId}, l'arrêt %{areaName} (%{areaId}) est desservi 2 fois consécutivement"
detail_3_route_2: "Les terminus de la séquence d'arrêt %{objectId} ne sont pas cohérent avec ceux de la séquence opposée %{routeId} : l'une part de %{firstName} (%firstId}) et l'autre arrive à %{lastName} (%lastId})"
detail_3_route_3: "Sur la séquence d'arrêt %{objectId}, entre les arrêts de rang %{firstStopRank} (%{firstStop} et %{nextStopRank} (%{nextStop}, distance %{distance} %{orientation} %{distanceLimit} "
@@ -129,6 +131,10 @@ en:
detail_3_vehiclejourney_2_3: "La course %{objectId} a une vitesse %{speed} > %{speedLimit} km/h entre les arrêts n° %{firstStopRank} (%{firstStopName}) et n° %{lastStopRank} (%{lastStopName})"
detail_3_vehiclejourney_3: "La course %{objectId} a une variation de progression entre les arrêts n° %{firstStopRank} (%{firstStopName}) et n° %{lastStopRank} (%{lastStopName}) %{variation} > %{maxVariation} avec la course %{vehicleJourneyId}"
detail_3_vehiclejourney_4: "La course %{objectId} n'a pas de calendrier d'application"
+ detail_3_vehiclejourney_5_1: "La course %{objectId} n'a pas de numéro"
+ detail_3_vehiclejourney_5_2: "La course %{objectId} a un numéro hors plage (%{number})"
+ detail_3_vehiclejourney_5_3: "La course %{objectId} a un numéro partagé avec la course %{vehicleJourneyId}"
+ detail_3_vehiclejourney_6: "La course %{objectId} a un mode de transport interdit %{transportMode}"
detail_3_facility_1: "L'équipement %{name} (%{objectId}) n'est pas géolocalisé"
detail_3_facility_2: "L'équipement %{name} (%{objectId}) est localisé trop loin de son parent %{areaName} (%{areaId}) : distance %{distance} > %{distanceLimit}"
activerecord:
@@ -217,6 +223,7 @@ en:
3-StopArea-3: "Vérification de l'unicité des arrêts"
3-StopArea-4: "Vérification de la géolocalisation des arrêts"
3-StopArea-5: "Vérification de la position relative des arrêts et de leur parent"
+ 3-StopArea-6: "Vérification de l'information de commune des arrêts"
3-AccessPoint-1: "Vérification de la géolocalisation de tous les accès"
3-AccessPoint-2: "Vérification que deux accès de nom différents ne sont pas trop proches"
3-AccessPoint-3: "Vérification de la proximité entre les accès et leur arrêt de rattachement"
@@ -228,6 +235,7 @@ en:
3-AccessLink-3: "Vérification de la vitesse de parcours entre les deux extrémités d'un lien d'accès"
3-Line-1: "Vérification de la non homonymie des lignes"
3-Line-2: "Vérification de la présence de séquences d'arrêts sur la ligne"
+ 3-Line-3: "Vérification des modes de transport"
3-Route-1: "Vérification de la succession des arrêts de la séquence"
3-Route-2: "Vérification de la séquence inverse"
3-Route-3: "Vérification de la distance entre deux arrêts successifs de la séquence"
@@ -242,6 +250,8 @@ en:
3-VehicleJourney-2: "Vérification de la vitesse de transfert entre deux arrêts"
3-VehicleJourney-3: "Vérification de la cohérence des courses successives desservant deux mêmes arrêts"
3-VehicleJourney-4: "Vérification de l'affectation des courses à un calendrier"
+ 3-VehicleJourney-5: "Vérification des numéros de course"
+ 3-VehicleJourney-6: "Vérification des modes de transport"
3-Facility-1: "Vérification de la géolocalisation de tous les accès"
3-Facility-2: "Vérification de la proximité entre les équipements et leur arrêt de rattachement"
severity: "Severity"
@@ -351,6 +361,7 @@ fr:
detail_3_stoparea_3: "Les arrêts %{name} (%{objectId} et %{areaId}) sont desservis par les mêmes lignes"
detail_3_stoparea_4: "L'arrêt %{name} (%{objectId}) est en dehors du périmètre de contrôle"
detail_3_stoparea_5: "L'arrêt %{name} (%{objectId}) est localisé trop loin de son parent %{parentName} (%{parentId}) : distance %{distance} > %{distanceLimit}"
+ detail_3_stoparea_6: "L'arrêt %{name} (%{objectId}) n'a pas de code commune"
detail_3_accesspoint_1: "L'accès %{name} (%{objectId}) de l'arrêt %{areaName} (%{areaId}) n'est pas géolocalisé"
detail_3_accesspoint_2: "L'accès %{name} (%{objectId}) est localisé trop près de l'accès %{accessName} (%{accessId}) : distance %{distance} < %{distanceLimit}"
detail_3_accesspoint_3: "L'accès %{name} (%{objectId}) est localisé trop loin de son parent %{parentName} (%{parentId}) : distance %{distance} > %{distanceLimit}"
@@ -368,6 +379,7 @@ fr:
detail_3_accesslink_3_4: "Sur le lien d'accès %{name} (%{objectId}), la vitesse pour un voyageur à mobilité réduite %{speed} est supérieure à %{speedLimit} km/h"
detail_3_line_1: "La ligne %{number} : %{name} ( %{objectId}) a une ligne homonyme sur le même réseau %{networkName} (%{networkId})"
detail_3_line_2: "La ligne %{number} : %{name} ( %{objectId}) n'a pas de séquence d'arrêts"
+ detail_3_line_3: "La ligne %{number} : %{name} ( %{objectId}) a un mode de transport interdit %{transportMode}"
detail_3_route_1: "Sur la séquence d'arrêt %{objectId}, l'arrêt %{areaName} (%{areaId}) est desservi 2 fois consécutivement"
detail_3_route_2: "Les terminus de la séquence d'arrêt %{objectId} ne sont pas cohérent avec ceux de la séquence opposée %{routeId} : l'une part de %{firstName} (%firstId}) et l'autre arrive à %{lastName} (%lastId})"
detail_3_route_3: "Sur la séquence d'arrêt %{objectId}, entre les arrêts de rang %{firstStopRank} (%{firstStop} et %{nextStopRank} (%{nextStop}, distance %{distance} %{orientation} %{distanceLimit} "
@@ -384,6 +396,10 @@ fr:
detail_3_vehiclejourney_2_3: "La course %{objectId} a une vitesse %{speed} > %{speedLimit} km/h entre les arrêts n° %{firstStopRank} (%{firstStopName}) et n° %{lastStopRank} (%{lastStopName})"
detail_3_vehiclejourney_3: "La course %{objectId} a une variation de progression entre les arrêts n° %{firstStopRank} (%{firstStopName}) et n° %{lastStopRank} (%{lastStopName}) %{variation} > %{maxVariation} avec la course %{vehicleJourneyId}"
detail_3_vehiclejourney_4: "La course %{objectId} n'a pas de calendrier d'application"
+ detail_3_vehiclejourney_5_1: "La course %{objectId} n'a pas de numéro"
+ detail_3_vehiclejourney_5_2: "La course %{objectId} a un numéro hors plage (%{number})"
+ detail_3_vehiclejourney_5_3: "La course %{objectId} a un numéro partagé avec la course %{vehicleJourneyId}"
+ detail_3_vehiclejourney_6: "La course %{objectId} a un mode de transport interdit %{transportMode}"
detail_3_facility_1: "L'équipement %{name} (%{objectId}) n'est pas géolocalisé"
detail_3_facility_2: "L'équipement %{name} (%{objectId}) est localisé trop loin de son parent %{areaName} (%{areaId}) : distance %{distance} > %{distanceLimit}"
@@ -473,6 +489,7 @@ fr:
3-StopArea-3: "Vérification de l'unicité des arrêts"
3-StopArea-4: "Vérification de la géolocalisation des arrêts"
3-StopArea-5: "Vérification de la position relative des arrêts et de leur parent"
+ 3-StopArea-6: "Vérification de l'information de commune des arrêts"
3-AccessPoint-1: "Vérification de la géolocalisation de tous les accès"
3-AccessPoint-2: "Vérification que deux accès de nom différents ne sont pas trop proches"
3-AccessPoint-3: "Vérification de la proximité entre les accès et leur arrêt de rattachement"
@@ -483,6 +500,8 @@ fr:
3-AccessLink-2: "Vérification de la cohérence entre la distance fournie sur le lien d'accès et la distance géographique entre les deux extrémités du lien d'accès"
3-AccessLink-3: "Vérification de la vitesse de parcours entre les deux extrémités d'un lien d'accès"
3-Line-1: "Vérification de la non homonymie des lignes"
+ 3-Line-2: "Vérification de la présence de séquences d'arrêts sur la ligne"
+ 3-Line-3: "Vérification des modes de transport"
3-Route-1: "Vérification de la succession des arrêts de la séquence"
3-Route-2: "Vérification de la séquence inverse"
3-Route-3: "Vérification de la distance entre deux arrêts successifs de la séquence"
@@ -495,6 +514,8 @@ fr:
3-VehicleJourney-2: "Vérification de la vitesse de transfert entre deux arrêts"
3-VehicleJourney-3: "Vérification de la cohérence des courses successives desservant deux mêmes arrêts"
3-VehicleJourney-4: "Vérification de l'affectation des courses à un calendrier"
+ 3-VehicleJourney-5: "Vérification des numéros de course"
+ 3-VehicleJourney-6: "Vérification des modes de transport"
3-Facility-1: "Vérification de la géolocalisation de tous les accès"
3-Facility-2: "Vérification de la proximité entre les équipements et leur arrêt de rattachement"
severity: "Sévérité"
diff --git a/config/locales/compliance_check_tasks.yml b/config/locales/compliance_check_tasks.yml
index c9472136a..00376c2bf 100644
--- a/config/locales/compliance_check_tasks.yml
+++ b/config/locales/compliance_check_tasks.yml
@@ -16,6 +16,7 @@ en:
title: "Create a new validation"
submit: "Create a validation"
all: "All"
+ flash: "Validation task on queue, refresh page to see progression"
actions:
new: "Add a validation"
destroy_confirm: "Do you confirm to destroy this validation ?"
@@ -24,6 +25,7 @@ en:
rule_parameter_set: "Rule parameter set"
statuses:
pending: "Pending"
+ processing: "Processing"
completed: "Completed"
failed: "Failed"
file_validation_log_messages:
@@ -80,6 +82,7 @@ fr:
title: "Démarrer une nouvelle validation"
submit: "Lancer la validation"
all: "Toutes"
+ flash: "La demande de validation est mise en file d'attente, veuillez rafraichir régulièrement la page pour en suivre la progression"
actions:
new: "Ajouter une validation"
destroy_confirm: "Voulez-vous supprimer ce résultat de validation ?"
@@ -87,7 +90,8 @@ fr:
edit: "Editer cette validation"
rule_parameter_set: "Jeu de paramètres"
statuses:
- pending: "En cours"
+ pending: "En attente ..."
+ processing: "En cours ..."
completed: "Achevé"
failed: "Echoué"
uncheck_count:
diff --git a/config/locales/connection_links.yml b/config/locales/connection_links.yml
index 4fe76b36b..815a913f8 100644
--- a/config/locales/connection_links.yml
+++ b/config/locales/connection_links.yml
@@ -18,7 +18,7 @@ en:
to: "to"
index:
title: "Connection links"
- name: "Name"
+ name: "Search by name"
departure: "Start of link"
arrival: "End of link"
selection: "Selection"
@@ -58,7 +58,7 @@ en:
creation_time: "Created on"
creator_id: "Created by"
formtastic:
- hints:
+ titles:
connection_link:
objectid: "[prefix]:ConnectionLink:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -81,7 +81,7 @@ fr:
from: "De"
to: "vers"
index:
- name: "Nom"
+ name: "Recherche par nom"
title: "Correspondances"
departure: "Arrêt de départ"
arrival: "Arrêt d'arrivée"
@@ -122,7 +122,7 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
connection_link:
objectid: "[prefixe]:ConnectionLink:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 4fb3980f1..933eca4a3 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -11,7 +11,7 @@ en:
title: Resend confirmation instructions
registrations:
new:
- title: Sign up
+ title: "Sign up"
commit: Sign up
edit:
title: "Your profile"
@@ -36,6 +36,8 @@ en:
helpers:
label:
user:
+ email: "Email"
+ organisation_name: "Organisation name"
name: Full name
password: Password
password_confirmation: Password confirmation
diff --git a/config/locales/devise.fr.yml b/config/locales/devise.fr.yml
index b1a9a743a..cb45578e5 100644
--- a/config/locales/devise.fr.yml
+++ b/config/locales/devise.fr.yml
@@ -15,8 +15,8 @@ fr:
title: Renvoyer le mail de confirmation
registrations:
new:
- title: "S'inscrire"
- commit: Créer un compte
+ title: "Inscrivez vous"
+ commit: "S'inscrire"
edit:
title: "Votre Profil"
commit: Modifier
@@ -35,11 +35,13 @@ fr:
links:
sign_in: "Se connecter"
sign_up: "S'inscrire"
- new_password: Mot de passe oublié
+ new_password: "Mot de passe oublié?"
new_confirmation: "Vous n'avez pas reçu les instructions de confirmation ?"
helpers:
label:
user:
+ email: "Email"
+ organisation_name: "Nom de l'organisation"
name: Nom complet
password: Mot de passe
password_confirmation: Confirmation du mot de passe
diff --git a/config/locales/exchange.yml b/config/locales/exchange.yml
new file mode 100644
index 000000000..7c8ff9646
--- /dev/null
+++ b/config/locales/exchange.yml
@@ -0,0 +1,18 @@
+en:
+ exchange:
+ format:
+ neptune: "Neptune"
+ gtfs: "GTFS (General Transit Feed Specification)"
+ csv: "CSV (Chouette format)"
+ netex: "NeTEx (experimental)"
+ hub: "HUB 1.3 (Specific Transdev Format)"
+ kml: "KML (line, route, ... drawings on Keyhole Markup Language format)"
+fr:
+ exchange:
+ format:
+ neptune: "profil Neptune"
+ gtfs: "GTFS (General Transit Feed Specification défini par Google)"
+ csv: "CSV (format spécifique à Chouette)"
+ netex: "profil NeTEx expérimental"
+ hub: "HUB 1.3 (format spécifique Transdev)"
+ kml: "KML (tracés de lignes, séquences d'arrêts, ... en 'Keyhole Markup Language')"
diff --git a/config/locales/exports.yml b/config/locales/exports.yml
index d9efdd2d6..7b1531314 100644
--- a/config/locales/exports.yml
+++ b/config/locales/exports.yml
@@ -1,5 +1,7 @@
en:
exports:
+ export:
+ exported_file: "Exported file"
actions:
new: "New export"
destroy: "Destroy"
@@ -8,13 +10,18 @@ en:
new:
title: "New export"
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: ""
show:
report: "Report"
statuses:
- pending: "Pending"
+ pending: "Pending ..."
+ processing: "Processing ..."
completed: "Completed"
failed: "Failed"
export_log_messages:
@@ -25,6 +32,9 @@ en:
undefined: "%{key} undefined"
overflow: "Can't export more than %{count} %{data} in a single KML export operation. You should proceed with some exports, each one based on less selected lines."
LINE_COUNT: "Exported line count : %{0}"
+ GROUP_OF_LINES_COUNT: "Exported group of lines count : %{0}"
+ COMMUNE_COUNT: "City count : %{0}"
+ TRANSPORT_MODE_COUNT: "Transport Mode count : %{0}"
ROUTE_COUNT: "Route count : %{0}"
JOURNEY_PATTERN_COUNT: "Journey pattern count : %{0}"
QUAY_AND_BOARDING_POSITION_COUNT: "Quays and Boarding positions count : %{0}"
@@ -34,6 +44,16 @@ en:
CONNECTION_LINK_COUNT: "Connection link count : %{0}"
ACCES_LINK_COUNT: "Access Link count : %{0}"
ACCES_POINT_COUNT: "Access Point count : %{0}"
+ TIME_TABLE_COUNT: "Time Table count : %{0}"
+ DIRECTION_COUNT: "Direction count : %{0}"
+ SCHEMA_COUNT: "Schema count : %{0}"
+ VEHICLE_JOURNEY_COUNT: "Vehicle journey count : %{0}"
+ VEHICLE_JOURNEY_OPERATION_COUNT: "Vehicle journey operation count : %{0}"
+ VEHICLE_JOURNEY_AT_STOP_COUNT: "Vehicle journey At Stop count : %{0}"
+ PHYSICAL_STOP_AREA_COUNT: "Physical Stop Areas count : %{0}"
+ COMMERCIAL_STOP_AREA_COUNT: "Logical Stop Areas count : %{0}"
+ NETWORK_COUNT: "Networks count : %{0}"
+ COMPANY_COUNT: "Companies count : %{0}"
EXPORT: "%{0} Export"
EXPORTED_LINE: "Line %{0} (%{1}) exported"
EMPTY_LINE: "Line without valid vehicle journey : not exported"
@@ -72,6 +92,7 @@ en:
one: "export"
other: "exports"
kml_export: "KML export"
+ hub_export: "HUB export"
neptune_export: "Neptune export"
csv_export: "CSV export"
gtfs_export: "GTFS export"
@@ -90,10 +111,11 @@ en:
position: "N."
full_message: "Message"
formtastic:
- hints:
- time_zone: "according to TZ encoding (see http://en.wikipedia.org/wiki/Tz_database)"
- start_date: "reduce import to vehicle journeys running from this date"
- end_date: "reduce import to vehicle journeys running until this date"
+ titles:
+ export:
+ time_zone: "according to TZ encoding (see http://en.wikipedia.org/wiki/Tz_database)"
+ start_date: "reduce import to vehicle journeys running from this date"
+ end_date: "reduce import to vehicle journeys running until this date"
area_types:
quay: "Quays and Boarding Positions"
commercial_stop_point: "Commercial Stop Points"
@@ -101,6 +123,8 @@ en:
itl: "Restriction Constraints"
fr:
exports:
+ export:
+ exported_file: "Fichier exporté"
actions:
new: "Nouvel export"
destroy: "Supprimer cet export"
@@ -109,13 +133,18 @@ fr:
new:
title: "Nouvel export"
all: "Toutes"
+ flash: "La demande d'export est mise en file d'attente, veuillez rafraichir régulièrement la page pour en suivre la progression"
+ 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 cours"
+ pending: "En attente ..."
+ processing: "En cours ..."
completed: "Achevé"
failed: "Echoué"
export_log_messages:
@@ -126,6 +155,9 @@ fr:
undefined: "%{key} non défini"
overflow: "Impossible d'exporter plus de %{count} %{data} en un seul export. Veuillez procéder par exports successifs en sélectionnant une moindre quantité de lignes."
LINE_COUNT: "Nombre de lignes exportées : %{0}"
+ GROUP_OF_LINES_COUNT: "Nombre de groupe de lignes exportés : %{0}"
+ COMMUNE_COUNT: "Nombre de communes : %{0}"
+ TRANSPORT_MODE_COUNT: "Nombre de modes de transport : %{0}"
ROUTE_COUNT: "Nombre de séquences d'arrêts exportées : %{0}"
QUAY_AND_BOARDING_POSITION_COUNT: "Nombre d'arrêts physiques exportés : %{0}"
COMMERCIAL_COUNT: "Nombre d'arrêts commerciaux exportés : %{0}"
@@ -135,6 +167,16 @@ fr:
CONNECTION_LINK_COUNT: "Nombre de correspondances exportées : %{0}"
ACCES_LINK_COUNT: "Nombre de liaison d'accès exportées : %{0}"
ACCES_POINT_COUNT: "Nombre de points d'accès exportés : %{0}"
+ TIME_TABLE_COUNT: "Nombre de tableaux de marche : %{0}"
+ DIRECTION_COUNT: "Nombre de directions : %{0}"
+ SCHEMA_COUNT: "Nombre de schémas : %{0}"
+ VEHICLE_JOURNEY_COUNT: "Nombre de courses : %{0}"
+ VEHICLE_JOURNEY_OPERATION_COUNT: "Nombre de courses opérations : %{0}"
+ VEHICLE_JOURNEY_AT_STOP_COUNT: "Nombre d'horaires : %{0}"
+ PHYSICAL_STOP_AREA_COUNT: "Nombre d'arrêts physiques : %{0}"
+ COMMERCIAL_STOP_AREA_COUNT: "Nombre d'arrêts logiques : %{0}"
+ NETWORK_COUNT: "Nombre de réseaux : %{0}"
+ COMPANY_COUNT: "Nombre de transporteurs : %{0}"
EXPORT: "Export %{0}"
EXPORTED_LINE: "Ligne %{0} (%{1}) exportée"
EMPTY_LINE: "Ligne sans course valide : non exportée"
@@ -173,6 +215,7 @@ fr:
one: "export"
other: "exports"
kml_export: "export KML"
+ hub_export: "export HUB"
neptune_export: "export Neptune "
csv_export: "export CSV"
gtfs_export: "export GTFS "
@@ -191,10 +234,11 @@ fr:
position: "No"
full_message: "Message"
formtastic:
- hints:
- time_zone: "selon le codage TZ (http://fr.wikipedia.org/wiki/Tz_database)"
- start_date: "limite l'export aux courses circulant à partir de cette date"
- end_date: "limite l'export aux courses circulant jusqu'à cette date"
+ titles:
+ export:
+ time_zone: "selon le codage TZ (http://fr.wikipedia.org/wiki/Tz_database)"
+ start_date: "limite l'export aux courses circulant à partir de cette date"
+ end_date: "limite l'export aux courses circulant jusqu'à cette date"
area_types:
quay: "Arrêts"
commercial_stop_point: "Arrêts commerciaux"
diff --git a/config/locales/formtastic.yml b/config/locales/formtastic.yml
index 52c413da8..13b82ef2e 100644
--- a/config/locales/formtastic.yml
+++ b/config/locales/formtastic.yml
@@ -1,17 +1,3 @@
-fr:
- formtastic:
- yes: 'Oui'
- no: 'Non'
- create: "Créer %{model}"
- update: "Modifier %{model}"
- submit: 'Valider %{model}'
- cancel: 'Annuler'
- reset: 'Réinitialiser %{model}'
- required: 'requis'
- import: "Lancer l'import"
- export: "Lancer l'export"
- validate: "Lancer la validation"
-
en:
formtastic:
yes: 'Yes'
@@ -25,3 +11,21 @@ en:
import: "Launch import"
export: "Launch export"
validate: "Launch validation"
+ duplicate: "Duplicate"
+ clone: "Clone"
+
+fr:
+ formtastic:
+ yes: 'Oui'
+ no: 'Non'
+ create: "Créer %{model}"
+ update: "Modifier %{model}"
+ submit: 'Valider %{model}'
+ cancel: 'Annuler'
+ reset: 'Réinitialiser %{model}'
+ required: 'requis'
+ import: "Lancer l'import"
+ export: "Lancer l'export"
+ validate: "Lancer la validation"
+ duplicate: "Dupliquer"
+ clone: "Cloner" \ No newline at end of file
diff --git a/config/locales/group_of_lines.yml b/config/locales/group_of_lines.yml
index 13e356cf2..1f970d4f9 100644
--- a/config/locales/group_of_lines.yml
+++ b/config/locales/group_of_lines.yml
@@ -14,7 +14,7 @@ en:
lines: "Lines list"
index:
title: "Group of Lines"
- name: "Name"
+ name: "Search by name"
form:
lines: "Associated lines"
activerecord:
@@ -33,7 +33,7 @@ en:
creation_time: "Created on"
creator_id: "Created by"
formtastic:
- hints:
+ titles:
group_of_line:
objectid: "[prefix]:GroupOfLine:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -53,7 +53,7 @@ fr:
lines: "Liste des lignes"
index:
title: "Groupes de lignes"
- name: "Nom"
+ name: "Recherche par nom"
form:
lines: "Lignes associées"
activerecord:
@@ -72,7 +72,7 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
group_of_line:
objectid: "[prefixe]:GroupOfLine:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/import_tasks.yml b/config/locales/import_tasks.yml
index f927a1f4b..df81a28d1 100644
--- a/config/locales/import_tasks.yml
+++ b/config/locales/import_tasks.yml
@@ -6,6 +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: ""
@@ -37,6 +41,7 @@ en:
journey_patterns_stats: "Journey Patterns"
statuses:
pending: "Pending"
+ processing: "Processing"
completed: "Completed"
failed: "Failed"
compliance_check_task: "Validate Report"
@@ -74,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"
@@ -81,8 +87,8 @@ en:
max_distance_for_connection_link: "Max distance for connection link"
ignore_last_word: "ignore last word"
ignore_end_chars: "ignore last chars"
- tipsy:
- hints:
+ formtastic:
+ titles:
import_task:
max_distance_for_commercial: "Maximal distance to merge homonymous stops in commercial stop in meter"
max_distance_for_connection_link: "Maximal distance to link stops by connection link stop in meter"
@@ -96,6 +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 en suivre la progression"
+ 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: ""
@@ -140,7 +150,8 @@ fr:
saved: "Sauvé"
save_error: "Sauvegarde en erreur"
statuses:
- pending: "En cours"
+ pending: "En attente ..."
+ processing: "En cours ..."
completed: "Achevé"
failed: "Echoué"
compliance_check_task: "Validation"
@@ -179,14 +190,15 @@ 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"
max_distance_for_connection_link: "Distance max pour créer les correspondances"
ignore_last_word: "ignorer le dernier mot"
ignore_end_chars: "ignorer les n derniers caractères"
- tipsy:
- hints:
+ formtastic:
+ titles:
import_task:
max_distance_for_commercial: "Distance maximale entre deux arrêts homonymes pour créer les zones d'arrêt (en mètre)"
max_distance_for_connection_link: "Distance maximale entre deux arrêts pour créer les correspondances (en mètre)"
diff --git a/config/locales/journey_patterns.yml b/config/locales/journey_patterns.yml
index 3c781d656..b16985c2c 100644
--- a/config/locales/journey_patterns.yml
+++ b/config/locales/journey_patterns.yml
@@ -40,7 +40,7 @@ en:
creation_time: "Created on"
creator_id: "Created by"
formtastic:
- hints:
+ titles:
journey_pattern:
objectid: "[prefix]:JourneyPattern:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -86,6 +86,6 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
journey_pattern:
objectid: "[prefixe]:JourneyPattern:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/layouts.yml b/config/locales/layouts.yml
index 5b239e664..d679fc01f 100644
--- a/config/locales/layouts.yml
+++ b/config/locales/layouts.yml
@@ -7,13 +7,13 @@ en:
profile: "My Profile"
sign_out: "Sign out"
navbar:
- return_to_referentials: "Return to referentials"
- select_referential: "Sélect referential"
- referential_datas: "Referential datas"
- creation_tag:
- title: "Create"
+ 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"
history_tag:
- title: "History"
+ title: "Metadatas"
created_at: "Created at"
updated_at: "Updated at"
user_name: "User"
@@ -41,19 +41,19 @@ en:
fr:
layouts:
back_to_dashboard: "Retour au Tableau de Bord"
- help: "Besoin d'aide?"
+ help: "Aide"
home: "Accueil"
user:
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"
- referential_datas: "Données du référentiel"
- creation_tag:
- title: "Création"
+ 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"
history_tag:
- title: "Historique"
+ title: "Métadonnées"
created_at: "Créé le"
updated_at: "Mise à jour le"
user_name: "Auteur"
diff --git a/config/locales/lines.yml b/config/locales/lines.yml
index ade5bb2cf..93f50b6bb 100644
--- a/config/locales/lines.yml
+++ b/config/locales/lines.yml
@@ -9,6 +9,8 @@ en:
import: "Import lines"
export_kml: "Export KML line"
export__kml_all: "Export KML lines"
+ export_hub: "Export HUB line"
+ export__hub_all: "Export HUB lines"
new:
title: "Add a new line"
edit:
@@ -19,9 +21,13 @@ en:
group_of_lines: "Groups of lines"
index:
title: "Lines"
- name_or_number: "Name or number"
- selection: "Filter on"
- selection_all: "All"
+ name_or_number: "Search by name or number"
+ no_networks: "No networks"
+ no_companies: "No companies"
+ no_group_of_lines: "No group of lines"
+ all_networks: "All networks"
+ all_companies: "All companies"
+ all_group_of_lines: "All group of lines"
multi_selection: "Multiple selection"
multi_selection_enable: "Enable multiple selection"
multi_selection_disable: "Disable multiple selection"
@@ -30,6 +36,7 @@ en:
select_all: "Select all"
deselect_all: "Deselect all"
unset: "undefined"
+ advanced_search: "Advanced Search"
form:
group_of_lines: "Associated groups of lines"
no_group_of_line: "No group of line"
@@ -49,6 +56,22 @@ en:
published_name: "Published name"
number: "Number"
transport_mode: "Transport mode"
+ mobility_restricted_suitability: "PRM accessibility"
+ flexible_service: "On demond transportation"
+ unspecified_mrs: "Not specified"
+ accessible: "Accessible"
+ not_accessible: "Not accessible"
+ unspecified_fs: "Not specified"
+ on_demaond_fs: "On demond service"
+ regular_fs: "Regular service"
+ number_of_vj: "Total number of vehicle journeys"
+ number_of_fs_vj: "Number of on demond vehicle journeys"
+ number_of_mrs_vj: "Number of accessible vehicle journeys"
+ number_of_non_fs_vj: "Number of non on demond vehicle journeys"
+ number_of_non_mrs_vj: "Number of non accessible vehicle journeys"
+ number_of_null_fs_vj: "Number of unspecified on demond vehicle journeys"
+ number_of_null_mrs_vj: "Number of unspecified accessible vehicle journeys"
+ default_fs_msg: "These vehicle journeys are considered as regular"
group_of_line: "Group of lines"
comment: "Comments"
objectid: "Neptune identifier"
@@ -56,7 +79,7 @@ en:
creation_time: "Created on"
creator_id: "Created by"
formtastic:
- hints:
+ titles:
line:
registration_number: "only alphanumerical or underscore characters"
objectid: "[prefix]:Line:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -72,6 +95,8 @@ fr:
import: "Importer des lignes"
export_kml: "Export KML de la ligne"
export_kml_all: "Export KML des lignes"
+ export_hub: "Export HUB de la ligne"
+ export_hub_all: "Export HUB des lignes"
new:
title: "Ajouter une ligne"
edit:
@@ -81,10 +106,14 @@ fr:
itineraries: "Liste des séquences d'arrêts de la ligne"
group_of_lines: "Groupes de lignes"
index:
- name_or_number: "Nom ou indice"
+ name_or_number: "Recherche par nom ou indice"
title: "Lignes"
- selection: "Filtrer sur"
- selection_all: "Tous"
+ no_networks: "Aucun réseaux"
+ no_companies: "Aucun transporteurs"
+ no_group_of_lines: "Aucun groupes de ligne"
+ all_networks: "Tous les réseaux"
+ all_companies: "Tous les transporteurs"
+ all_group_of_lines: "Tous les groupes de ligne"
multi_selection: "Sélection multiple"
multi_selection_enable: "Activer la sélection multiple"
multi_selection_disable: "Désactiver la sélection multiple"
@@ -93,6 +122,7 @@ fr:
select_all: "Tout sélectionner"
deselect_all: "Tout désélectionner"
unset: "non défini"
+ advanced_search: "Recherche avancée"
form:
group_of_lines: "Groupes de lignes associés"
no_group_of_line: "Aucun groupe de lignes"
@@ -112,6 +142,22 @@ fr:
published_name: "Nom public"
number: "Indice"
transport_mode: "Mode de transport"
+ mobility_restricted_suitability: "Accessibilité PMR"
+ flexible_service: "Transport à la demande"
+ unspecified_mrs: "Non spécifié"
+ accessible: "Accessible"
+ not_accessible: "Non accessible"
+ unspecified_fs: "Non spécifié"
+ on_demaond_fs: "Service à la demande"
+ regular_fs: "Service régulier"
+ number_of_vj: "Nombre total de courses"
+ number_of_fs_vj: "Nombre de courses à la demande"
+ number_of_mrs_vj: "Nombre de courses accessibles"
+ number_of_non_fs_vj: "Nombre de courses régulières"
+ number_of_non_mrs_vj: "Nombre de courses non accessibles"
+ number_of_null_fs_vj: "Nombre de courses sans spécification de type de service"
+ number_of_null_mrs_vj: "Nombre de courses sans spécification d'accessibilité"
+ default_fs_msg: "Ces courses sont considérées régulières"
group_of_line: "Groupe de lignes"
comment: "Commentaire"
objectid: "Identifiant Neptune"
@@ -119,7 +165,7 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
line:
registration_number: "caractères autorisés : alphanumériques et 'souligné'"
objectid: "[prefixe]:Line:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/networks.yml b/config/locales/networks.yml
index 6bae0667d..30cd399b9 100644
--- a/config/locales/networks.yml
+++ b/config/locales/networks.yml
@@ -13,7 +13,7 @@ en:
title: "Network"
index:
title: "Networks"
- name: "Name"
+ name: "Search by name"
activerecord:
models:
@@ -36,7 +36,7 @@ en:
creation_time: "Created on"
creator_id: "Created by "
formtastic:
- hints:
+ titles:
network:
registration_number: "only alphanumerical or underscore characters"
objectid: "[prefix]:GroupOfLine:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -56,7 +56,7 @@ fr:
title: "Réseau %{network}"
index:
title: "Réseaux"
- name: "Nom"
+ name: "Recherche par nom"
activerecord:
models:
network:
@@ -78,7 +78,7 @@ fr:
creation_time: "Créé le"
creator_id: "Créé par"
formtastic:
- hints:
+ titles:
network:
registration_number: "caractères autorisés : alphanumériques et 'souligné'"
objectid: "[prefixe]:GroupOfLine:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/referentials.yml b/config/locales/referentials.yml
index 08a82a11d..0d3a63498 100644
--- a/config/locales/referentials.yml
+++ b/config/locales/referentials.yml
@@ -65,13 +65,14 @@ en:
import_tasks: "Imports"
export_tasks: "Exports"
compliance_check_tasks: "Validations"
+ rule_parameter_sets: "Rule parameters sets"
formtastic:
- hints:
+ titles:
referential:
slug: "only lowercase alphanumerical or underscore characters, first character must be a letter"
prefix: "only alphanumerical or underscore characters"
- upper_corner: "longitude,latitude in WGS84 referential, dot for decimal separator"
- lower_corner: "longitude,latitude in WGS84 referential, dot for decimal separator"
+ upper_corner: "latitude,longitude in WGS84 referential, dot for decimal separator"
+ lower_corner: "latitude,longitude in WGS84 referential, dot for decimal separator"
fr:
referentials:
@@ -140,10 +141,11 @@ fr:
import_tasks: "Imports"
export_tasks: "Exports"
compliance_check_tasks: "Validations"
+ rule_parameter_sets: "Jeux de paramètres"
formtastic:
- hints:
+ titles:
referential:
slug: "caractères autorisés : alphanumériques minuscules et 'souligné' et doit commencer par une lettre"
prefix: "caractères autorisés : alphanumériques et 'souligné'"
- upper_corner: "longitude,latitude dans le référentiel WGS84, le séparateur de décimales est 'point'"
- lower_corner: "longitude,latitude dans le référentiel WGS84, le séparateur de décimales est 'point'"
+ upper_corner: "latitude,longitude dans le référentiel WGS84, le séparateur de décimales est 'point'"
+ lower_corner: "latitude,longitude dans le référentiel WGS84, le séparateur de décimales est 'point'"
diff --git a/config/locales/routes.yml b/config/locales/routes.yml
index 27243bd87..b68f1802a 100644
--- a/config/locales/routes.yml
+++ b/config/locales/routes.yml
@@ -7,6 +7,10 @@ en:
destroy_confirm: "Are you sure you want destroy this route?"
export_kml: "Export KML route"
export_kml_all: "Export KML routes"
+ export_hub: "Export HUB route"
+ export_hub_all: "Export HUB routes"
+ add_stop_point: "Add stop point"
+ new_stop_point: "Create new stop"
new:
title: "Add a new route"
edit:
@@ -55,7 +59,7 @@ en:
creation_time: "Created on"
creator_id: "Created by"
formtastic:
- hints:
+ titles:
route:
objectid: "[prefix]:Route:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
@@ -68,6 +72,10 @@ fr:
destroy_confirm: "Etes vous sûr de supprimer cette séquence d'arrêts ?"
export_kml: "Export KML de la séquence d'arrêts"
export_kml_all: "Export KML des séquences d'arrêts"
+ export_hub: "Export HUB de la séquence d'arrêts"
+ export_hub_all: "Export HUB des séquences d'arrêts"
+ add_stop_point: "Ajouter un arrêt"
+ new_stop_point: "Créer un arrêt pour l'ajouter"
new:
title: "Ajouter une séquence d'arrêts"
edit:
@@ -116,7 +124,7 @@ fr:
creator_id: "Créé par"
no_journey_pattern: "Pas de mission"
formtastic:
- hints:
+ titles:
route:
objectid: "[prefixe]:Route:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/rule_parameter_sets.yml b/config/locales/rule_parameter_sets.yml
index e3626fc04..b1f45c4f4 100644
--- a/config/locales/rule_parameter_sets.yml
+++ b/config/locales/rule_parameter_sets.yml
@@ -14,20 +14,25 @@ en:
add_mode_parameter_set: "Add mode specific parameter set"
show:
title: "Parameter Set %{rule_parameter_set}"
- max_distance: "Maximum distance"
- min_distance: "Minimum distance"
- walk_speed: "Maximum walk speed for"
- inter_stop_area_distance_min: "between 2 stop areas having different parent"
- parent_stop_area_distance_max: "between a stop area and its own parent"
- inter_access_point_distance_min: "between 2 access having different name for a commun stop area"
- inter_connection_link_distance_max: "between stop area departure and stop area arrival in a connection link"
- walk_default_speed_max: "a regular traveller"
- walk_occasional_traveller_speed_max: "an occasional traveller"
- walk_frequent_traveller_speed_max: "a frequent traveller"
- walk_mobility_restricted_traveller_speed_max: "for a mobility restricted traveller"
- inter_access_link_distance_max: "Access link maximum distance"
+ max_distance: "Maximum distance between "
+ min_distance: "Minimum distance between "
+ walk_speed: "Maximum walk speed for travellers"
+ inter_stop_area_distance_min: "2 stop areas having different parent"
+ parent_stop_area_distance_max: "a stop area and its own parent"
+ inter_access_point_distance_min: "2 access with different names on a same stop area"
+ inter_connection_link_distance_max: "stop areas in a connection link"
+ walk_default_speed_max: "a regular one"
+ walk_occasional_traveller_speed_max: "an occasional one"
+ walk_frequent_traveller_speed_max: "a frequent one"
+ walk_mobility_restricted_traveller_speed_max: "a mobility restricted one"
+ inter_access_link_distance_max: "an access point and a linked stop area"
inter_stop_duration_max: "Maximum duration between the moment when a vehicle is arriving at a stop and the moment when the vehicle is leaving"
- facility_stop_area_distance_max: "between a stop area and a facility"
+ facility_stop_area_distance_max: "a stop area and a facility"
+ rule_parameter_by_mode: "Parameters by mode"
+ modes_allowed: " (only for allowed ones)"
+ vehicle_journey_number_bounds: "Vehicle journey number limits (0,0 to disable check-point))"
+ min_value: "minimal value"
+ max_value: "maximal value"
index:
title: "Parameter sets"
activerecord:
@@ -48,11 +53,15 @@ en:
inter_access_link_distance_max: "Access link maximum distance"
inter_stop_duration_max: "Maximum duration for a stopping time"
facility_stop_area_distance_max: "Maximum distance between a stop area and a facility"
- inter_stop_area_distance_min: "Maximum distance between a stop areas"
- inter_stop_area_distance_max: "Maximum distance between a stop areas"
+ inter_stop_area_distance_min: "Maximum distance between 2 stop areas"
+ inter_stop_area_distance_max: "Maximum distance between 2 stop areas"
speed_min: "Minimum speed"
speed_max: "Maximum speed"
- inter_stop_duration_variation_max: "Maximum duration gap between 2 vehicle journeys and between 2 folowing stops"
+ inter_stop_duration_variation_max: "Maximum duration gap between 2 vehicle journeys and between 2 following stops"
+ vehicle_journey_number_min: "Minimal value for vehicle journey numbers (empty to disable check-point)"
+ vehicle_journey_number_min: "Maximal value for vehicle journey numbers (empty to disable check-point)"
+ check_allowed_transport_modes: "Check transport modes"
+ allowed_transport: "Allowed"
fr:
rule_parameter_sets:
@@ -85,6 +94,10 @@ fr:
facility_stop_area_distance_max: "un arrêt et un équipement"
inter_stop_duration_max: "Durée maximum de stationnement à un arrêt"
rule_parameter_by_mode: "Jeu de paramètres pour un mode de transport"
+ modes_allowed: " (uniquement pour les modes autorisés)"
+ vehicle_journey_number_bounds: "Fouchette de valeurs pour le numéro de courses"
+ min_value: "valeur minimale"
+ max_value: "valeur maximale"
index:
title: "Jeux de paramètres"
activerecord:
@@ -93,21 +106,25 @@ fr:
attributes:
rule_parameter_set:
name: "Nom"
- inter_stop_area_distance_min: Distance minimum entre 2 arrêts n'ayant pas le même parent
- parent_stop_area_distance_max: Distance maximum entre un arrêt et son parent
- stop_areas_area: Délimitation géographique des arrêts
- inter_access_point_distance_min: Distance minimum entre 2 accès de noms différents pour un même arrêt
- inter_connection_link_distance_max: Distance maximum entre les arrêts en correspondance
- walk_default_speed_max: Vitesse de marche maximum pour un voyageur ordinaire
- walk_occasional_traveller_speed_max: Vitesse de marche maximum pour un voyageur occasionnel
- walk_frequent_traveller_speed_max: Vitesse de marche maximum pour un voyageur habituel
- walk_mobility_restricted_traveller_speed_max: Vitesse de marche maximum pour un voyageur à mobilité réduite
- inter_access_link_distance_max: Distance maximum d'un liaison accès - arrêt
- inter_stop_duration_max: Durée maximum entre les horaires d'arrivée et de départ à un arrêt
- facility_stop_area_distance_max: Distance maximum entre un arrêt et un équipement
- inter_stop_area_distance_min: Distance minimum entre 2 arrêts
- inter_stop_area_distance_max: Distance maximum entre 2 arrêts
- speed_min: Vitesse minimum
- speed_max: Vitesse maximum
- inter_stop_duration_variation_max: Ecart maximum de durée de trajet entre 2 arrêts successifs pour les différentes courses
+ inter_stop_area_distance_min: "Distance minimum entre 2 arrêts n'ayant pas le même parent"
+ parent_stop_area_distance_max: "Distance maximum entre un arrêt et son parent"
+ stop_areas_area: "Délimitation géographique des arrêts"
+ inter_access_point_distance_min: "Distance minimum entre 2 accès de noms différents pour un même arrêt"
+ inter_connection_link_distance_max: "Distance maximum entre les arrêts en correspondance"
+ walk_default_speed_max: "Vitesse de marche maximum pour un voyageur ordinaire"
+ walk_occasional_traveller_speed_max: "Vitesse de marche maximum pour un voyageur occasionnel"
+ walk_frequent_traveller_speed_max: "Vitesse de marche maximum pour un voyageur habituel"
+ walk_mobility_restricted_traveller_speed_max: "Vitesse de marche maximum pour un voyageur à mobilité réduite"
+ inter_access_link_distance_max: "Distance maximum d'un liaison accès - arrêt"
+ inter_stop_duration_max: "Durée maximum entre les horaires d'arrivée et de départ à un arrêt"
+ facility_stop_area_distance_max: "Distance maximum entre un arrêt et un équipement"
+ inter_stop_area_distance_min: "Distance minimum entre 2 arrêts"
+ inter_stop_area_distance_max: "Distance maximum entre 2 arrêts"
+ speed_min: "Vitesse minimum"
+ speed_max: "Vitesse maximum"
+ inter_stop_duration_variation_max: "Ecart maximum de durée entre 2 arrêts successifs pour les différentes courses"
+ vehicle_journey_number_min: "Borne inférieur pour les numéros de course (vide pour désactiver le contrôle)"
+ vehicle_journey_number_min: "Borne supérieure pour les numéros de course (vide pour désactiver le contrôle)"
+ check_allowed_transport_modes: "Contrôler les modes de transport"
+ allowed_transport: "Autorisé"
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
new file mode 100644
index 000000000..0df11fe0f
--- /dev/null
+++ b/config/locales/simple_form.en.yml
@@ -0,0 +1,26 @@
+en:
+ simple_form:
+ "yes": 'Yes'
+ "no": 'No'
+ required:
+ text: 'required'
+ mark: '*'
+ # You can uncomment the line below if you need to overwrite the whole required html.
+ # When using html, text and mark won't be used.
+ # html: '<abbr title="required">*</abbr>'
+ error_notification:
+ default_message: "Please review the problems below:"
+ # Labels and hints examples
+ # labels:
+ # defaults:
+ # password: 'Password'
+ # user:
+ # new:
+ # email: 'E-mail to sign in.'
+ # edit:
+ # email: 'E-mail.'
+ # hints:
+ # defaults:
+ # username: 'User name to sign in.'
+ # password: 'No special characters, please.'
+
diff --git a/config/locales/stop_area_copies.yml b/config/locales/stop_area_copies.yml
new file mode 100644
index 000000000..9a50c2d48
--- /dev/null
+++ b/config/locales/stop_area_copies.yml
@@ -0,0 +1,29 @@
+en:
+ stop_area_copies:
+ new:
+ success: "Clone succedeed"
+ title:
+ child: "Clone as child"
+ parent: "Clone as parent"
+ errors:
+ copy_aborted: "Errors prohibited this copy from completing: "
+ exception: "internal error"
+ activemodel:
+ attributes:
+ stop_area_copy:
+ area_type: "Area type"
+fr:
+ stop_area_copies:
+ new:
+ success: "Clonage réussi"
+ title:
+ child: "Cloner pour créer un fils"
+ parent: "Cloner pour créer un père"
+ errors:
+ copy_aborted: "Des erreurs ont empéchées le bon déroulement de la copie: "
+ exception: "erreur interne"
+ activemodel:
+ attributes:
+ stop_area_copy:
+ area_type: "Type d'arrêt"
+ \ No newline at end of file
diff --git a/config/locales/stop_areas.yml b/config/locales/stop_areas.yml
index 1c0214210..80f05d57c 100644
--- a/config/locales/stop_areas.yml
+++ b/config/locales/stop_areas.yml
@@ -4,13 +4,18 @@ en:
stop_area:
no_position: "No Position"
lines: "Lines :"
+ general: "General"
+ localisation: "Localisation"
+ accessibility: "Accessibility"
actions:
new: "Add a new stop"
edit: "Edit this stop"
destroy: "Remove this stop"
- destroy_confirm: "Are you sure you want destroy this stop?"
+ destroy_confirm: "Are you sure you want destroy this stop and all of his children ?"
select_parent: "Manage Parent"
add_children: "Manage Children"
+ clone_as_parent: "Clone as parent"
+ clone_as_child: "Clone as child"
manage_access_points: "Manage Access Points"
manage_access_links: "Manage Access Links"
add_routing_lines: "Manage constraint's lines"
@@ -19,8 +24,14 @@ en:
export_kml_place: "Export KML places"
export_kml_commercial: "Export KML commercial stop points"
export_kml_physical: "Export KML physical"
+ export_hub_place: "Export HUB places"
+ export_hub_commercial: "Export HUB commercial stop points"
+ export_hub_physical: "Export HUB physical"
new:
title: "Add a new stop"
+ form:
+ address: "15 rue du Louvre, Paris"
+ geolocalize: "Pinpoint "
edit:
title: "Update stop %{stop_area}"
show:
@@ -36,10 +47,12 @@ en:
genealogical_routing: "Routing constraint's links"
index:
title: "Stop areas"
- name_or_country_code: "Name or Country code"
+ name: "Search by name"
+ country_code: "Postal Code : 78000"
selection: "Filter on"
selection_all: "All"
area_type: "Area Type"
+ advanced_search: "Advanced Search"
access_links:
title: "Access links for %{stop_area}'s access"
generic_access_links: "Glogal links"
@@ -76,6 +89,7 @@ en:
projection: "Projection type"
projection_x: "x-position"
projection_y: "y-position"
+ projection_xy: "position (x,y) %{projection}"
long_lat_type: "Projection type"
longitude: "Longitude"
latitude: "Latitude"
@@ -87,11 +101,16 @@ en:
routing_stop_ids: "Attached stops"
routing_line_ids: "Attached lines"
parent: "Parent"
+ coordinates: "Coordinates (lat,lng) WGS84"
+ zip_code: "Zip code"
+ city_name: "City"
formtastic:
- hints:
+ titles:
stop_area:
registration_number: "only alphanumerical or underscore characters"
objectid: "[prefix]:StopArea:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
+ coordinates: "latitude,longitude in WGS84 referential, dot for decimal separator"
+ projection_xy: "x,y in secondary referential, dot for decimal separator"
fr:
stop_areas:
@@ -99,13 +118,18 @@ fr:
stop_area:
no_position: "Pas de position"
lines: "Lignes :"
+ general: "General"
+ localisation: "Localisation"
+ accessibility: "Accessibilité"
actions:
new: "Ajouter un arrêt"
edit: "Modifier cet arrêt"
destroy: "Supprimer cet arrêt"
- destroy_confirm: "Etes vous sûr de supprimer cet arrêt ?"
+ destroy_confirm: "Etes vous sûr de supprimer cet arrêt ainsi que tous ses fils?"
select_parent: "Gérer le parent"
add_children: "Gérer les fils"
+ clone_as_parent: "Cloner pour créer un père"
+ clone_as_child: "Cloner pour créer un fils"
add_routing_lines: "Gérer les lignes de l'ITL"
add_routing_stops: "Gérer les arrêts de l'ITL"
manage_access_points: "Gérer les accès"
@@ -115,8 +139,14 @@ fr:
export_kml_place: "Export KML des pôles d'échange"
export_kml_commercial: "Export KML des arrêts commerciaux"
export_kml_physical: "Export KML des arrêts physiques"
+ export_hub_place: "Export HUB des pôles d'échange"
+ export_hub_commercial: "Export HUB des arrêts commerciaux"
+ export_hub_physical: "Export HUB des arrêts physiques"
new:
title: "Ajouter un arrêt"
+ form:
+ address: "15 rue du Louvre, Paris"
+ geolocalize: "Géolocalisez "
edit:
title: "Modifier l'arrêt %{stop_area}"
show:
@@ -137,11 +167,13 @@ fr:
access_link_legend_1: "Les flêches grises représentent des liens non définis"
access_link_legend_2: "cliquer sur les flêches pour créer/éditer un lien"
index:
- name_or_country_code: "Nom ou Code INSEE"
+ name: "Recherche par nom"
+ country_code: "Code Postal : 78000"
title: "Arrêts"
selection: "Filtrer sur"
selection_all: "Tous"
area_type: "Type d'arrêt"
+ advanced_search: "Recherche avancée"
select_parent:
title: "Gérer le parent de l'arrêt %{stop_area}"
add_children:
@@ -173,6 +205,7 @@ fr:
projection: "Projection"
projection_x: "Position X"
projection_y: "Position Y"
+ projection_xy: "Position (x,y) %{projection}"
long_lat_type: "Projection"
longitude: "Longitude"
latitude: "Latitude"
@@ -184,10 +217,15 @@ fr:
routing_stop_ids: "Arrêts concernés par l'ITL"
routing_line_ids: "Lignes affectées par l'ITL"
parent: "Parent"
+ coordinates: "Coordonnées (lat,lng) WGS84"
+ zip_code: "Code postal"
+ city_name: "Commune"
formtastic:
- hints:
+ titles:
stop_area:
registration_number: "caractères autorisés : alphanumériques et 'souligné'"
objectid: "[prefixe]:StopArea:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
+ coordinates: "latitude,longitude dans le référentiel WGS84, le séparateur de décimales est 'point'"
+ projection_xy: "x,y dans le référentiel secondaire, le séparateur de décimales est 'point'"
diff --git a/config/locales/stop_points.yml b/config/locales/stop_points.yml
index 2a4c90766..540fdc650 100644
--- a/config/locales/stop_points.yml
+++ b/config/locales/stop_points.yml
@@ -19,6 +19,8 @@ en:
subtitle: "Stops on route ordered"
move: "Move"
no_stop_point: "No stop point on route"
+ stop_point:
+ lines: "lines"
activerecord:
models:
stop_point:
@@ -49,6 +51,8 @@ fr:
subtitle: "Arrêts dans l'ordre de parcours"
move: "Déplacer"
no_stop_point: "Aucun arrêt dans la séquence"
+ stop_point:
+ lines: "lignes"
activerecord:
models:
stop_point:
diff --git a/config/locales/time_table_combinations.yml b/config/locales/time_table_combinations.yml
new file mode 100644
index 000000000..a544b0115
--- /dev/null
+++ b/config/locales/time_table_combinations.yml
@@ -0,0 +1,31 @@
+en:
+ time_table_combinations:
+ success: "operation applied on timetable"
+ failure: "operation failed on timetable"
+ operations:
+ union: "merge"
+ intersection: "intersect"
+ disjunction: "disjoin"
+ combine_form:
+ time_tables: "Time table to combine with"
+ activemodel:
+ attributes:
+ time_table_combination:
+ combined_id: "Time table id"
+ operation: "operation"
+fr:
+ time_table_combinations:
+ success: "opération appliquée sur le calendrier"
+ failure: "opération échouée"
+ operations:
+ union: "ajouter les dates"
+ intersection: "conserver les dates communes"
+ disjunction: "soustraire les dates"
+ combine_form:
+ time_tables: "Calendrier à combiner"
+ activemodel:
+ attributes:
+ time_table_combination:
+ combined_id: "Id Calendrier"
+ operation: "opération"
+
diff --git a/config/locales/time_tables.yml b/config/locales/time_tables.yml
index 7ce94359a..85b990716 100644
--- a/config/locales/time_tables.yml
+++ b/config/locales/time_tables.yml
@@ -1,5 +1,6 @@
en:
time_tables:
+ duplicate_success: "duplication succeded"
time_table:
empty: "empty"
bounding: "from %{start} to %{end}"
@@ -10,18 +11,19 @@ en:
new: "Add a new timetable"
edit: "Edit this timetable"
destroy: "Remove this timetable"
+ duplicate: "Duplicate this timetable"
+ combine: "Combine with another timetable"
destroy_confirm: "Are you sure you want destroy this timetable ?"
destroy_date_confirm: "Are you sure you want destroy this date ?"
destroy_period_confirm: "Are you sure you want destroy this period ?"
add_period: "Add a period"
- add_date: "Add a date"
+ add_date: "Add a peculiar date"
+ add_excluded_date: "Add an excluded date"
new:
title: "Add a new timetable"
edit:
title: "Update timetable %{time_table}"
show:
- resume: "From %{start_date} to %{end_date} (independently of any period day types)"
- resume_empty: "Empty timetable"
title: "Timetable %{time_table}"
dates: "Application dates"
periods: "Application periods"
@@ -29,11 +31,25 @@ en:
to: "to"
add_period: "Add a period"
add_date: "Add a date"
+ combine_form: "Combinations"
+ combine: "Apply"
+ show_time_table:
+ resume: "From %{start_date} to %{end_date}"
+ resume_empty: "Empty timetable"
+ legend: "Legend : "
+ excluded_date: "Excluded date"
+ overlap_date: "Overlap date"
+ selected_date: "Date directly included"
+ selected_period: "Date included in period"
index:
title: "Timetables"
- comment: "Name"
+ comment: "Search by name"
+ tag_search: "Tags : hollidays,public holliday"
+ from: "From : "
+ to: " to : "
selection: "Selection"
selection_all: "All"
+ advanced_search: "Advanced Search"
activerecord:
models:
time_table:
@@ -44,10 +60,7 @@ en:
time_table:
comment: "Name"
version: "Short name"
- peculiarities: "Peculiarities"
- school_holliday: "School hollidays"
- public_holliday: "Public hollidays"
- day_types: "Day types"
+ day_types: "Period day types"
none: "none"
monday: "Monday"
tuesday: "Tuesday"
@@ -61,19 +74,24 @@ en:
creation_time: "Created on"
creator_id: "Created by "
calendars: "Calendar view"
- dates: "Application dates"
+ dates: "Peculiar dates"
date: "On"
+ excluded_dates: "Excluded dates"
periods: "Application periods"
period_start: "From"
period_end: "to"
-
+ tag_search: "Tags"
formtastic:
- hints:
+ titles:
time_table:
objectid: "[prefix]:Timetable:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
+ placeholders:
+ time_table:
+ tag_search: "ex: Public hollidays,School holidays"
fr:
time_tables:
+ duplicate_success: "duplication terminée"
time_table:
empty: "vide"
bounding: "du %{start} au %{end}"
@@ -84,18 +102,19 @@ fr:
new: "Ajouter un calendrier"
edit: "Modifier ce calendrier"
destroy: "Supprimer ce calendrier"
+ duplicate: "Dupliquer ce calendrier"
+ combine: "Combiner ce calendrier"
destroy_confirm: "Etes vous sûr de supprimer ce calendrier ?"
destroy_date_confirm: "Etes vous sûr de supprimer cette date ?"
destroy_period_confirm: "Etes vous sûr de supprimer cette période ?"
add_period: "Ajouter une période"
- add_date: "Ajouter une date"
+ add_date: "Ajouter une date particulière"
+ add_excluded_date: "Ajouter une date exclue"
new:
title: "Ajouter un calendrier"
edit:
title: "Modifier le calendrier %{time_table}"
show:
- resume: "Validité comprise du %{start_date} au %{end_date} (sans tenir compte des jours d'application)"
- resume_empty: "Calendrier vide"
title: Calendrier %{time_table}
dates: "Dates d'application"
periods: "Périodes d'application"
@@ -103,11 +122,27 @@ fr:
to: "au"
add_period: "Ajouter une période"
add_date: "Ajouter une date"
+ combine_form: "Combinaison de calendriers"
+ combine: "Appliquer"
+ show_time_table:
+ resume: "Validité comprise du %{start_date} au %{end_date}"
+ resume_empty: "Calendrier vide"
+ legend: "Légende : "
+ excluded_date: "Date exclue"
+ overlap_date: "Date en doublon"
+ selected_date: "Date inclue directement"
+ selected_period: "Date inclue par période"
index:
- comment: "Nom"
+ comment: "Recherche par nom"
+ tag_search: "Tags : vacances,jour fériés"
+ from: "De : "
+ to: " à : "
+ start_date: "jj/mm/aaaa"
+ end_date: "jj/mm/aaaa"
title: "calendriers"
selection: "Sélection"
selection_all: "Tous"
+ advanced_search: "Recherche avancée"
activerecord:
models:
time_table:
@@ -118,10 +153,7 @@ fr:
time_table:
comment: "Nom"
version: "Abréviation"
- peculiarities: "Particularités"
- school_holliday: "Vacances scolaires"
- public_holliday: "Jours fériés"
- day_types: "Jours d'application"
+ day_types: "Jours d'application des périodes"
none: "aucun"
monday: "Lundi"
tuesday: "Mardi"
@@ -134,16 +166,23 @@ fr:
object_version: "Version"
creation_time: "Créé le"
creator_id: "Créé par"
- calendars: "Présentation calendaire"
- dates: "Dates d'application"
- date: "Date"
+ calendars: "Calendrier"
+ calendar_details: "Données du calendrier"
+ dates: "Dates particulières"
+ date: "Le"
+ excluded_dates: "Dates exclues"
periods: "Périodes d'application"
period_start: "Du"
period_end: "au"
-
+ tag_search: "Etiquettes"
+ tag_list: "Etiquettes"
formtastic:
- hints:
+ titles:
time_table:
objectid: "[prefixe]:Timetable:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
+ placeholders:
+ time_table:
+ tag_search: "ex: Jours fériés,Vacances scolaires"
+
diff --git a/config/locales/transport_modes.yml b/config/locales/transport_modes.yml
index 9ed0745f7..55954abeb 100644
--- a/config/locales/transport_modes.yml
+++ b/config/locales/transport_modes.yml
@@ -1,5 +1,6 @@
en:
transport_modes:
+ name: "Transport mode"
label:
unknown: "unknown"
air: "Air"
@@ -24,6 +25,7 @@ en:
fr:
transport_modes:
+ name: "Mode de transport"
label:
unknown: "Inconnu"
air: "Air"
diff --git a/config/locales/vehicle_journey_exports.yml b/config/locales/vehicle_journey_exports.yml
new file mode 100644
index 000000000..f8169c544
--- /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)"
+ published_journey_name: "published name"
+ 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)"
+ published_journey_name: "nom public"
+ 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 f3d3be918..fd442d5eb 100644
--- a/config/locales/vehicle_journey_imports.yml
+++ b/config/locales/vehicle_journey_imports.yml
@@ -2,24 +2,47 @@ en:
vehicle_journey_imports:
new:
title: "Import vehicle journey at stops"
- export_vehicle_journeys: "Export existing vehicle journey at stops :"
- form:
- file: "File"
+ export_vehicle_journeys: "Export existing vehicle journey at stops"
+ success: "Import is a success"
+ tooltip:
+ file: "Select a CSV or Excel file"
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: "An exception occured : %{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:
+ file: "File"
fr:
vehicle_journey_imports:
new:
- title: "Import des horaires à l'arrêt"
+ title: "Import des horaires aux arrêts"
export_vehicle_journeys: "Exporter les horaires existants"
- form:
- file: "Fichier"
+ 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: "
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: "Une exception est survenu : %{message}"
- \ No newline at end of file
+ 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:
+ file: "Fichier" \ No newline at end of file
diff --git a/config/locales/vehicle_journeys.yml b/config/locales/vehicle_journeys.yml
index fb13c8399..05eb1c4cb 100644
--- a/config/locales/vehicle_journeys.yml
+++ b/config/locales/vehicle_journeys.yml
@@ -1,8 +1,10 @@
en:
vehicle_journeys:
+ vehicle_journeys:
+ line_routes: "Line's routes"
vehicle_journey:
title_stopless: "Vehicle journey %{name}"
- title: "Vehicle journey %{name} leaving from %{stop} at %{time}"
+ title: "Vehicle journey leaving from %{stop} at %{time}"
actions:
index: "Vehicle time's board"
new: "Add a new vehicle journey"
@@ -21,6 +23,12 @@ en:
to_arrivals: "Copy departures to arrivals"
to_departures: "Copy arrivals to departures"
time_tables: "Associated calendars to vehicle journey"
+ slide: "Shift"
+ slide_title: "Shift all vehicle passing times"
+ set: "Set"
+ to: "at"
+ slide_departure: "departure time at first stop"
+ slide_arrival: "arrival time at first stop"
timeless:
title: "Timeless vehicle journeys"
vehicle_journeys: "Vehicle journeys with times at stop"
@@ -32,20 +40,23 @@ en:
arrival: "Arrival"
time_tables: "Calendars list"
bounding: "From %{start} to %{end}"
- validation: "Clone"
translation_form: "Vehicle journey translations"
index:
title: "Vehicle journeys on route %{route}"
vehicle_journeys: "Departure's times"
- title: "Timeless vehicle journeys"
selection: "Filter on"
selection_all: "All"
+ select_journey_patterns: "Select journey pattern"
+ select_time_tables: "Enter a timetable"
time_range: "Departure time threshold"
+ advanced_search: "Advanced Search"
+ sidebar:
+ timeless: "Timeless vehicle journeys"
time_filter:
- time_range_filter: "Filter"
- activerecord:
- models:
- vehicle_journey:
+ time_range_filter: "Filter"
+ activerecord:
+ models:
+ vehicle_journey:
zero: "vehicle journey"
one: "vehicle journey"
other: "vehicle journeys"
@@ -57,9 +68,18 @@ en:
time_tables: "Calendars"
time_slot: "Time Slot"
company: "Company"
+ number: "Number"
comment: "Comments"
status_value: "Status Value"
transport_mode_name: "Transport Mode"
+ mobility_restricted_suitability: "PRM accessibility"
+ flexible_service: "On demond transportation"
+ unspecified_mrs: "Not specified"
+ accessible: "Accessible"
+ not_accessible: "Not accessible"
+ unspecified_fs: "Not specified"
+ on_demaond_fs: "On demond service"
+ regular_fs: "Regular service"
published_journey_name: "Published Name"
published_journey_identifier: "Published Identifier"
facility: "Facility"
@@ -75,15 +95,17 @@ en:
vehicle_journey:
invalid_times: "Invalid times"
formtastic:
- hints:
+ titles:
vehicle_journey:
objectid: "[prefix]:VehicleJourney:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character"
fr:
vehicle_journeys:
+ vehicle_journeys:
+ line_routes: "Séquences d'arrêts de la ligne"
vehicle_journey:
title_stopless: "Course %{name}"
- title: "Course %{name} partant de %{stop} à %{time}"
+ title: "Course partant de %{stop} à %{time}"
actions:
index: "Horaires des courses"
new: "Ajouter une course"
@@ -102,6 +124,12 @@ fr:
to_arrivals: "Copie départs vers arrivées"
to_departures: "Copie arrivées vers départs"
time_tables: "Calendriers associés à la course"
+ slide: "Décaler"
+ slide_title: "Décaler l'ensemble des horaires de course"
+ set: "Fixer"
+ to: "à"
+ slide_departure: "horaire de départ au 1° arrêt à"
+ slide_arrival: "horaire d'arrivée au 1° arrêt à"
timeless:
title: "Courses sans horaire"
vehicle_journeys: "Courses ayant des horaires"
@@ -113,20 +141,23 @@ fr:
arrival: "Arrivée"
time_tables: "Liste des calendriers"
bounding: "De %{start} à %{end}"
- validation: "Cloner"
translation_form: "Cloner la course"
index:
- title: "Courses de la séquence d'arrêts %{route}"
- timeless: "Courses sans horaire"
+ title: "Horaires de la séquence d'arrêts %{route}"
vehicle_journeys: "Horaires de départ aux arrêts"
selection: "Filtrer sur"
selection_all: "Tous"
+ select_journey_patterns: "Sélectionner une mission"
+ select_time_tables: "Saisir un calendrier"
time_range: "Seuil horaire au départ"
+ advanced_search: "Recherche avancée"
time_filter:
- time_range_filter: "Filtrer"
- activerecord:
- models:
- vehicle_journey:
+ time_range_filter: "Filtrer"
+ sidebar:
+ timeless: "Courses sans horaire"
+ activerecord:
+ models:
+ vehicle_journey:
zero: "Course"
one: "Course"
other: "Courses"
@@ -138,9 +169,18 @@ fr:
time_tables: "Calendriers"
time_slot: "Fréquence"
company: "Transporteur"
+ number: "Numéro"
comment: "Commentaires"
status_value: "Etat de trafic"
transport_mode_name: "Mode de transport"
+ mobility_restricted_suitability: "Accessibilité PMR"
+ flexible_service: "Transport à la demande"
+ unspecified_mrs: "Non spécifié"
+ accessible: "Accessible"
+ not_accessible: "Non accessible"
+ unspecified_fs: "Non spécifié"
+ on_demaond_fs: "Service à la demande"
+ regular_fs: "Service régulier"
published_journey_name: "Nom public"
published_journey_identifier: "Identifiant public"
facility: "Equipement"
@@ -156,7 +196,7 @@ fr:
vehicle_journey:
invalid_times: "Horaires invalides"
formtastic:
- hints:
+ titles:
vehicle_journey:
objectid: "[prefixe]:VehicleJourney:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'"
diff --git a/config/locales/vehicle_translations.yml b/config/locales/vehicle_translations.yml
index 3d1e0b702..a1e33b8e4 100644
--- a/config/locales/vehicle_translations.yml
+++ b/config/locales/vehicle_translations.yml
@@ -2,18 +2,43 @@ en:
vehicle_translations:
success: "%{count} vehicle journeys created by translation"
failure: "Fail when creating vehicle journeys by translation"
- activemodel:
+ translate_form:
+ set: "Set"
+ to: "at (hh:mm)"
+ first_stop_arrival_time: "Arrival time at first stop '%{stop_name}'"
+ first_stop_departure_time: "Departure time at first stop '%{stop_name}'"
+ multiple_cloning_form: "Repeat cloning based on a time interval"
+ activemodel:
attributes:
vehicle_translation:
duration: "Duration"
count: "Count"
+ errors:
+ models:
+ vehicle_translation:
+ missing_start_time: "Departure time or arrival time is required."
+ uncompiliant_vehicle: "Vehicle creation by copy requires that the selected vehicle counts at leat a stop and has departure and arrival times at each stops"
+ unreadable_time: "Expected time format is hh:mm"
fr:
vehicle_translations:
success: "%{count} course(s) crée(s) par translation"
failure: "Echec de la création de courses par tanslation"
- activemodel:
+ translate_form:
+ set: "Fixer"
+ to: "à (hh:mm)"
+ first_stop_arrival_time: "Horaire d'arrivée au premier arrêt '%{stop_name}'"
+ first_stop_departure_time: "Horaire de départ au premier arrêt '%{stop_name}'"
+ multiple_cloning_form: "Répéter le clonage à intervalle régulier"
+
+ activemodel:
attributes:
vehicle_translation:
duration: "Durée de l'intervalle (en minutes)"
count: "Quantité de courses à ajouter"
+ errors:
+ models:
+ vehicle_translation:
+ missing_start_time: "L'horaire de départ ou celui d'arrivée est requis"
+ uncompiliant_vehicle: "Pour cloner une course, celle-ci doit compter au moins un arrêt et avoir des horaires départ arrivée sur tous ses arrêts"
+ unreadable_time: "Le format d'horaire attendu est hh:mm"
diff --git a/config/routes.rb b/config/routes.rb
index 12a83eea1..f629a963f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,9 +1,31 @@
ChouetteIhm::Application.routes.draw do
devise_scope :users do
- match "/users/sign_up" => "subscriptions#new"
+ #match "/users/sign_up" => "subscriptions#new",
end
- devise_for :users
+ devise_for :users, :controllers => { :registrations => "registrations" }
+
+ devise_scope :user do
+ authenticated :user do
+ root :to => 'referentials#index'
+ end
+
+ unauthenticated do
+ root :to => 'devise/sessions#new'
+ end
+ end
+
+ # Rails 4 syntax
+ # devise_for :users
+ # devise_scope :user do
+ # authenticated :user do
+ # root :to => 'referentials#index', as: :authenticated_root
+ # end
+ # unauthenticated :user do
+ # root :to => 'devise/registrations#new', as: :unauthenticated_root
+ # end
+ # end
+
namespace :api do
namespace :v1 do
@@ -44,6 +66,7 @@ ChouetteIhm::Application.routes.draw do
resources :group_of_lines do
resources :stop_areas do
resources :access_points
+ resources :stop_area_copies
resources :stop_area_parents
resources :stop_area_children
resources :stop_area_routing_lines
@@ -70,6 +93,7 @@ ChouetteIhm::Application.routes.draw do
resources :lines, :networks, :group_of_lines do
resources :stop_areas do
resources :access_points
+ resources :stop_area_copies
resources :stop_area_parents
resources :stop_area_children
resources :stop_area_routing_lines
@@ -88,9 +112,9 @@ ChouetteIhm::Application.routes.draw do
end
end
resources :vehicle_journeys do
- get 'timeless', :on => :collection
get 'select_journey_pattern', :on => :member
resources :vehicle_translations
+ resources :time_tables
end
resources :vehicle_journey_imports
resources :vehicle_journey_exports
@@ -123,10 +147,14 @@ ChouetteIhm::Application.routes.draw do
resources :time_tables do
collection do
- get :comment_filter
+ get :tags
+ end
+ member do
+ get 'duplicate'
end
resources :time_table_dates
resources :time_table_periods
+ resources :time_table_combinations
end
resources :access_points do
@@ -135,6 +163,7 @@ ChouetteIhm::Application.routes.draw do
resources :stop_areas do
resources :access_points
+ resources :stop_area_copies
resources :stop_area_parents
resources :stop_area_children
resources :stop_area_routing_lines
@@ -181,5 +210,4 @@ ChouetteIhm::Application.routes.draw do
match '/422', :to => 'errors#server_error'
match '/500', :to => 'errors#server_error'
- root :to => 'referentials#index'
end
diff --git a/db/migrate/20140617141550_add_on_demand_transportation_to_line.ninoxe_engine.rb b/db/migrate/20140617141550_add_on_demand_transportation_to_line.ninoxe_engine.rb
new file mode 100644
index 000000000..358312ec4
--- /dev/null
+++ b/db/migrate/20140617141550_add_on_demand_transportation_to_line.ninoxe_engine.rb
@@ -0,0 +1,6 @@
+# This migration comes from ninoxe_engine (originally 20140617131630)
+class AddOnDemandTransportationToLine < ActiveRecord::Migration
+ def change
+ add_column :lines, :on_demand_transportation, :boolean
+ end
+end
diff --git a/db/migrate/20140617141551_add_details_to_vehicle_journey.ninoxe_engine.rb b/db/migrate/20140617141551_add_details_to_vehicle_journey.ninoxe_engine.rb
new file mode 100644
index 000000000..ec0c5af40
--- /dev/null
+++ b/db/migrate/20140617141551_add_details_to_vehicle_journey.ninoxe_engine.rb
@@ -0,0 +1,7 @@
+# This migration comes from ninoxe_engine (originally 20140617132236)
+class AddDetailsToVehicleJourney < ActiveRecord::Migration
+ def change
+ add_column :vehicle_journeys, :mobility_restricted_suitability, :boolean
+ add_column :vehicle_journeys, :on_demand_transportation, :boolean
+ end
+end
diff --git a/db/migrate/20140618072859_fix_column_name.ninoxe_engine.rb b/db/migrate/20140618072859_fix_column_name.ninoxe_engine.rb
new file mode 100644
index 000000000..9802528d3
--- /dev/null
+++ b/db/migrate/20140618072859_fix_column_name.ninoxe_engine.rb
@@ -0,0 +1,12 @@
+# This migration comes from ninoxe_engine (originally 20140618071147)
+class FixColumnName < ActiveRecord::Migration
+ def up
+ rename_column :lines, :on_demand_transportation, :flexible_service
+ rename_column :vehicle_journeys, :on_demand_transportation, :flexible_service
+ end
+
+ def down
+ rename_column :lines, :flexible_service, :on_demand_transportation
+ rename_column :vehicle_journeys, :flexible_service, :on_demand_transportation
+ end
+end
diff --git a/db/migrate/20140626081657_add_in_out_to_timetable_date.ninoxe_engine.rb b/db/migrate/20140626081657_add_in_out_to_timetable_date.ninoxe_engine.rb
new file mode 100644
index 000000000..81f12e64d
--- /dev/null
+++ b/db/migrate/20140626081657_add_in_out_to_timetable_date.ninoxe_engine.rb
@@ -0,0 +1,6 @@
+# This migration comes from ninoxe_engine (originally 20140625143030)
+class AddInOutToTimetableDate < ActiveRecord::Migration
+ def change
+ add_column "time_table_dates", "in_out", "boolean"
+ end
+end
diff --git a/db/migrate/20140626081658_set_in_out_to_timetable_date.ninoxe_engine.rb b/db/migrate/20140626081658_set_in_out_to_timetable_date.ninoxe_engine.rb
new file mode 100644
index 000000000..724154466
--- /dev/null
+++ b/db/migrate/20140626081658_set_in_out_to_timetable_date.ninoxe_engine.rb
@@ -0,0 +1,9 @@
+# This migration comes from ninoxe_engine (originally 20140626054725)
+class SetInOutToTimetableDate < ActiveRecord::Migration
+ def up
+ Chouette::TimeTableDate.update_all( :in_out => true)
+ end
+
+ def down
+ end
+end
diff --git a/db/migrate/20140721080943_acts_as_taggable_on_migration.ninoxe_engine.rb b/db/migrate/20140721080943_acts_as_taggable_on_migration.ninoxe_engine.rb
new file mode 100644
index 000000000..cf116560a
--- /dev/null
+++ b/db/migrate/20140721080943_acts_as_taggable_on_migration.ninoxe_engine.rb
@@ -0,0 +1,32 @@
+# This migration comes from ninoxe_engine (originally 20140718141703)
+# This migration comes from acts_as_taggable_on_engine (originally 1)
+class ActsAsTaggableOnMigration < ActiveRecord::Migration
+ def self.up
+ create_table :tags do |t|
+ t.string :name
+ end
+
+ create_table :taggings do |t|
+ t.references :tag
+
+ # You should make sure that the column created is
+ # long enough to store the required class names.
+ t.references :taggable, polymorphic: true
+ t.references :tagger, polymorphic: true
+
+ # Limit is created to prevent MySQL error on index
+ # length for MyISAM table type: http://bit.ly/vgW2Ql
+ t.string :context, limit: 128
+
+ t.datetime :created_at
+ end
+
+ add_index :taggings, :tag_id
+ add_index :taggings, [:taggable_id, :taggable_type, :context]
+ end
+
+ def self.down
+ drop_table :taggings
+ drop_table :tags
+ end
+end
diff --git a/db/migrate/20140721080944_add_missing_unique_indices.ninoxe_engine.rb b/db/migrate/20140721080944_add_missing_unique_indices.ninoxe_engine.rb
new file mode 100644
index 000000000..f85bb4c75
--- /dev/null
+++ b/db/migrate/20140721080944_add_missing_unique_indices.ninoxe_engine.rb
@@ -0,0 +1,21 @@
+# This migration comes from ninoxe_engine (originally 20140718141704)
+# This migration comes from acts_as_taggable_on_engine (originally 2)
+class AddMissingUniqueIndices < ActiveRecord::Migration
+ def self.up
+ add_index :tags, :name, unique: true
+
+ remove_index :taggings, :tag_id
+ remove_index :taggings, [:taggable_id, :taggable_type, :context]
+ add_index :taggings,
+ [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
+ unique: true, name: 'taggings_idx'
+ end
+
+ def self.down
+ remove_index :tags, :name
+
+ remove_index :taggings, name: 'taggings_idx'
+ add_index :taggings, :tag_id
+ add_index :taggings, [:taggable_id, :taggable_type, :context]
+ end
+end
diff --git a/db/migrate/20140721080945_add_taggings_counter_cache_to_tags.ninoxe_engine.rb b/db/migrate/20140721080945_add_taggings_counter_cache_to_tags.ninoxe_engine.rb
new file mode 100644
index 000000000..27d7e4d1e
--- /dev/null
+++ b/db/migrate/20140721080945_add_taggings_counter_cache_to_tags.ninoxe_engine.rb
@@ -0,0 +1,16 @@
+# This migration comes from ninoxe_engine (originally 20140718141705)
+# This migration comes from acts_as_taggable_on_engine (originally 3)
+class AddTaggingsCounterCacheToTags < ActiveRecord::Migration
+ def self.up
+ add_column :tags, :taggings_count, :integer, default: 0
+
+ ActsAsTaggableOn::Tag.reset_column_information
+ ActsAsTaggableOn::Tag.find_each do |tag|
+ ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings)
+ end
+ end
+
+ def self.down
+ remove_column :tags, :taggings_count
+ end
+end
diff --git a/db/migrate/20140721080946_add_missing_taggable_index.ninoxe_engine.rb b/db/migrate/20140721080946_add_missing_taggable_index.ninoxe_engine.rb
new file mode 100644
index 000000000..6aba71e6f
--- /dev/null
+++ b/db/migrate/20140721080946_add_missing_taggable_index.ninoxe_engine.rb
@@ -0,0 +1,11 @@
+# This migration comes from ninoxe_engine (originally 20140718141706)
+# This migration comes from acts_as_taggable_on_engine (originally 4)
+class AddMissingTaggableIndex < ActiveRecord::Migration
+ def self.up
+ add_index :taggings, [:taggable_id, :taggable_type, :context]
+ end
+
+ def self.down
+ remove_index :taggings, [:taggable_id, :taggable_type, :context]
+ end
+end
diff --git a/db/migrate/20140820074843_add_zip_code_and_city_name_to_stop_area.ninoxe_engine.rb b/db/migrate/20140820074843_add_zip_code_and_city_name_to_stop_area.ninoxe_engine.rb
new file mode 100644
index 000000000..47493163a
--- /dev/null
+++ b/db/migrate/20140820074843_add_zip_code_and_city_name_to_stop_area.ninoxe_engine.rb
@@ -0,0 +1,9 @@
+# This migration comes from ninoxe_engine (originally 20140820060801)
+class AddZipCodeAndCityNameToStopArea < ActiveRecord::Migration
+ def change
+ change_table :stop_areas do |t|
+ t.string :zip_code
+ t.string :city_name
+ end
+ end
+end
diff --git a/db/migrate/20140820074844_add_zip_code_and_city_name_to_access_point.ninoxe_engine.rb b/db/migrate/20140820074844_add_zip_code_and_city_name_to_access_point.ninoxe_engine.rb
new file mode 100644
index 000000000..628d0a1d6
--- /dev/null
+++ b/db/migrate/20140820074844_add_zip_code_and_city_name_to_access_point.ninoxe_engine.rb
@@ -0,0 +1,9 @@
+# This migration comes from ninoxe_engine (originally 20140820060814)
+class AddZipCodeAndCityNameToAccessPoint < ActiveRecord::Migration
+ def change
+ change_table :access_points do |t|
+ t.string :zip_code
+ t.string :city_name
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0978a437a..6c45bd44a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20140207162334) do
+ActiveRecord::Schema.define(:version => 20140820074844) do
create_table "access_links", :force => true do |t|
t.integer "access_point_id", :limit => 8
@@ -57,6 +57,8 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
t.boolean "mobility_restricted_suitability"
t.boolean "stairs_availability"
t.integer "stop_area_id", :limit => 8
+ t.string "zip_code"
+ t.string "city_name"
end
add_index "access_points", ["objectid"], :name => "access_points_objectid_key", :unique => true
@@ -279,6 +281,7 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
t.string "comment"
t.boolean "mobility_restricted_suitability"
t.integer "int_user_needs"
+ t.boolean "flexible_service"
end
add_index "lines", ["objectid"], :name => "lines_objectid_key", :unique => true
@@ -389,6 +392,8 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
t.boolean "stairs_availability"
t.boolean "lift_availability"
t.integer "int_user_needs"
+ t.string "zip_code"
+ t.string "city_name"
end
add_index "stop_areas", ["objectid"], :name => "stop_areas_objectid_key", :unique => true
@@ -411,6 +416,26 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
add_index "stop_points", ["objectid"], :name => "stop_points_objectid_key", :unique => true
+ create_table "taggings", :force => true do |t|
+ t.integer "tag_id"
+ t.integer "taggable_id"
+ t.string "taggable_type"
+ t.integer "tagger_id"
+ t.string "tagger_type"
+ t.string "context", :limit => 128
+ t.datetime "created_at"
+ end
+
+ add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], :name => "taggings_idx", :unique => true
+ add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
+
+ create_table "tags", :force => true do |t|
+ t.string "name"
+ t.integer "taggings_count", :default => 0
+ end
+
+ add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true
+
create_table "time_slots", :force => true do |t|
t.string "objectid", :null => false
t.integer "object_version"
@@ -429,6 +454,7 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
t.integer "time_table_id", :limit => 8, :null => false
t.date "date"
t.integer "position", :null => false
+ t.boolean "in_out"
end
add_index "time_table_dates", ["time_table_id"], :name => "index_time_table_dates_on_time_table_id"
@@ -514,11 +540,11 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
add_index "vehicle_journey_at_stops", ["vehicle_journey_id"], :name => "index_vehicle_journey_at_stops_on_vehicle_journey_id"
create_table "vehicle_journeys", :force => true do |t|
- t.integer "route_id", :limit => 8
- t.integer "journey_pattern_id", :limit => 8
- t.integer "time_slot_id", :limit => 8
- t.integer "company_id", :limit => 8
- t.string "objectid", :null => false
+ t.integer "route_id", :limit => 8
+ t.integer "journey_pattern_id", :limit => 8
+ t.integer "time_slot_id", :limit => 8
+ t.integer "company_id", :limit => 8
+ t.string "objectid", :null => false
t.integer "object_version"
t.datetime "creation_time"
t.string "creator_id"
@@ -529,7 +555,9 @@ ActiveRecord::Schema.define(:version => 20140207162334) do
t.string "published_journey_identifier"
t.string "facility"
t.string "vehicle_type_identifier"
- t.integer "number", :limit => 8
+ t.integer "number", :limit => 8
+ t.boolean "mobility_restricted_suitability"
+ t.boolean "flexible_service"
end
add_index "vehicle_journeys", ["objectid"], :name => "vehicle_journeys_objectid_key", :unique => true
diff --git a/lib/bootstrap_breadcrumbs_builder.rb b/lib/bootstrap_breadcrumbs_builder.rb
new file mode 100644
index 000000000..daa154bdf
--- /dev/null
+++ b/lib/bootstrap_breadcrumbs_builder.rb
@@ -0,0 +1,31 @@
+# bootstrap builder for breadcrumbs_on_rails gem
+class BootstrapBreadcrumbsBuilder < BreadcrumbsOnRails::Breadcrumbs::Builder
+ def render
+ @context.content_tag(:ul, class: 'breadcrumb') do
+ @elements.collect do |element|
+ render_element(element)
+ end.join.html_safe
+ end
+ end
+
+ def render_element(element)
+ active = element.path.nil? || @context.current_page?(compute_path(element))
+ # Bootstrap use '/' divider by default but you can customize it:
+ # divider = @context.content_tag(:span, '/'.html_safe, class: 'divider') unless active
+
+ @context.content_tag(:li, :class => ('active' if active)) do
+ content = if element.path.nil?
+ compute_name(element)
+ else
+ @context.link_to_unless_current(compute_name(element), compute_path(element), element.options)
+ end
+
+ # content + (divider || '')
+ content
+ end
+ end
+end
+
+
+# Usage:
+# = render_breadcrumbs(builder: BootstrapBreadcrumbsBuilder) \ No newline at end of file
diff --git a/public/help/2014-10-30_172801.png b/public/help/2014-10-30_172801.png
new file mode 100644
index 000000000..dcd247503
--- /dev/null
+++ b/public/help/2014-10-30_172801.png
Binary files differ
diff --git a/public/help/2014-10-30_174529.png b/public/help/2014-10-30_174529.png
new file mode 100644
index 000000000..24c4a6e7a
--- /dev/null
+++ b/public/help/2014-10-30_174529.png
Binary files differ
diff --git a/public/help/2014-10-30_175216.png b/public/help/2014-10-30_175216.png
new file mode 100644
index 000000000..dcb0a9a2a
--- /dev/null
+++ b/public/help/2014-10-30_175216.png
Binary files differ
diff --git a/public/help/2014-10-30_180131.png b/public/help/2014-10-30_180131.png
new file mode 100644
index 000000000..2924629b5
--- /dev/null
+++ b/public/help/2014-10-30_180131.png
Binary files differ
diff --git a/public/help/2014-10-30_180211.png b/public/help/2014-10-30_180211.png
new file mode 100644
index 000000000..1cf52e9de
--- /dev/null
+++ b/public/help/2014-10-30_180211.png
Binary files differ
diff --git a/public/help/2014-10-30_180356.png b/public/help/2014-10-30_180356.png
new file mode 100644
index 000000000..877b2d852
--- /dev/null
+++ b/public/help/2014-10-30_180356.png
Binary files differ
diff --git a/public/help/2014-10-30_180447.png b/public/help/2014-10-30_180447.png
new file mode 100644
index 000000000..5bee70356
--- /dev/null
+++ b/public/help/2014-10-30_180447.png
Binary files differ
diff --git a/public/help/2014-10-30_180536.png b/public/help/2014-10-30_180536.png
new file mode 100644
index 000000000..cbeab115b
--- /dev/null
+++ b/public/help/2014-10-30_180536.png
Binary files differ
diff --git a/public/help/2014-10-30_182229.png b/public/help/2014-10-30_182229.png
new file mode 100644
index 000000000..0411825c2
--- /dev/null
+++ b/public/help/2014-10-30_182229.png
Binary files differ
diff --git a/public/help/2014-10-31_112140.png b/public/help/2014-10-31_112140.png
new file mode 100644
index 000000000..ad1f75954
--- /dev/null
+++ b/public/help/2014-10-31_112140.png
Binary files differ
diff --git a/public/help/2014-10-31_112324.png b/public/help/2014-10-31_112324.png
new file mode 100644
index 000000000..261056097
--- /dev/null
+++ b/public/help/2014-10-31_112324.png
Binary files differ
diff --git a/public/help/2014-10-31_112543.png b/public/help/2014-10-31_112543.png
new file mode 100644
index 000000000..9e2050259
--- /dev/null
+++ b/public/help/2014-10-31_112543.png
Binary files differ
diff --git a/public/help/2014-10-31_113648.png b/public/help/2014-10-31_113648.png
new file mode 100644
index 000000000..dd85a06bc
--- /dev/null
+++ b/public/help/2014-10-31_113648.png
Binary files differ
diff --git a/public/help/2014-10-31_113803.png b/public/help/2014-10-31_113803.png
new file mode 100644
index 000000000..692dc3bdf
--- /dev/null
+++ b/public/help/2014-10-31_113803.png
Binary files differ
diff --git a/public/help/2014-10-31_113958.png b/public/help/2014-10-31_113958.png
new file mode 100644
index 000000000..f333bf7a0
--- /dev/null
+++ b/public/help/2014-10-31_113958.png
Binary files differ
diff --git a/public/help/2014-10-31_114336.png b/public/help/2014-10-31_114336.png
new file mode 100644
index 000000000..e2c0033e7
--- /dev/null
+++ b/public/help/2014-10-31_114336.png
Binary files differ
diff --git a/public/help/2014-10-31_114422.png b/public/help/2014-10-31_114422.png
new file mode 100644
index 000000000..8c5518dfa
--- /dev/null
+++ b/public/help/2014-10-31_114422.png
Binary files differ
diff --git a/public/help/2014-10-31_114639.png b/public/help/2014-10-31_114639.png
new file mode 100644
index 000000000..0f673eaeb
--- /dev/null
+++ b/public/help/2014-10-31_114639.png
Binary files differ
diff --git a/public/help/2014-10-31_115014.png b/public/help/2014-10-31_115014.png
new file mode 100644
index 000000000..fa62cff4d
--- /dev/null
+++ b/public/help/2014-10-31_115014.png
Binary files differ
diff --git a/public/help/2014-10-31_120428.png b/public/help/2014-10-31_120428.png
new file mode 100644
index 000000000..b8f9b2d1a
--- /dev/null
+++ b/public/help/2014-10-31_120428.png
Binary files differ
diff --git a/spec/controllers/vehicle_journey_imports_controller_spec.rb b/spec/controllers/vehicle_journey_imports_controller_spec.rb
new file mode 100644
index 000000000..091826205
--- /dev/null
+++ b/spec/controllers/vehicle_journey_imports_controller_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe ImportTasksController do
+ login_user
+
+
+end
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/factories.rb b/spec/factories.rb
index 205f020bb..2599645d3 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -70,10 +70,6 @@ FactoryGirl.define do
f.referential { Referential.find_by_slug("first") }
end
- factory :file_validation_log_message do |f|
- f.association :file_validation
- f.sequence(:key) { "key_#{n}" }
- end
-
+ factory :time_table_combination
end
diff --git a/spec/fixtures/vehicle_journey_imports_valid.csv b/spec/fixtures/vehicle_journey_imports_valid.csv
index 30a7c99bc..3126ffe2b 100644
--- a/spec/fixtures/vehicle_journey_imports_valid.csv
+++ b/spec/fixtures/vehicle_journey_imports_valid.csv
@@ -1,5 +1,12 @@
-"stop area id","stop area name","import:VehicleJourney:1","import:VehicleJourney:2","import:VehicleJourney:3",""
-1,"Arrêt 1","9:00:00","10:05:00","11:10:00","12:10:00"
-2,"Arrêt 2","9:05:00",,"11:15:00","12:15:00"
-3,"Arrêt 3","9:10:00","10:20:00","11:20:00","12:20:00"
-4,"Arrêt 4","9:15:00","10:25:00","11:25:00","12:25:00"
+;id course;import:VehicleJourney:1;import:VehicleJourney:2;import:VehicleJourney:3;
+;numéro;1;2;3;4
+;nom public;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 3def5eca1..7aa59009e 100644
--- a/spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv
+++ b/spec/fixtures/vehicle_journey_imports_with_vj_invalid.csv
@@ -1,5 +1,12 @@
-"stop area id","stop area name","first:VehicleJourney:vehicle_journey_1","first:VehicleJourney:vehicle_journey_2","first:VehicleJourney:vehicle_journey_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","10:25:00","11:25:00"
+;id course;9999;import:VehicleJourney:2;import:VehicleJourney:3
+;numéro;1;2;3
+;nom public;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
new file mode 100644
index 000000000..df6b1acff
--- /dev/null
+++ b/spec/fixtures/vehicle_journey_imports_with_vjas_bad_order.csv
@@ -0,0 +1,12 @@
+;id course;import:VehicleJourney:1;import:VehicleJourney:2;
+;numéro;1;2;3
+;nopm public;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 c63b56432..bcb07a177 100644
--- a/spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv
+++ b/spec/fixtures/vehicle_journey_imports_with_vjas_invalid.csv
@@ -1,5 +1,12 @@
-"stop area id","stop area name","first:VehicleJourney:vehicle_journey_1","first:VehicleJourney:vehicle_journey_2","first:VehicleJourney:vehicle_journey_3"
-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","10:25:00","11:25:00"
+;id course;import:VehicleJourney:1;import:VehicleJourney:2;
+;numéro;1;2;3
+;nom public;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/export_spec.rb b/spec/models/export_spec.rb
index cc8c045f1..1fd47daad 100644
--- a/spec/models/export_spec.rb
+++ b/spec/models/export_spec.rb
@@ -46,7 +46,7 @@ describe Export do
describe ".types" do
it "should return available Export implementations" do
- Export.types.should =~ %w{NeptuneExport CsvExport GtfsExport NetexExport KmlExport}
+ Export.types.should =~ %w{NeptuneExport CsvExport GtfsExport NetexExport KmlExport HubExport}
end
end
diff --git a/spec/models/stop_area_copy_spec.rb b/spec/models/stop_area_copy_spec.rb
new file mode 100644
index 000000000..66aa56d30
--- /dev/null
+++ b/spec/models/stop_area_copy_spec.rb
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+require 'spec_helper'
+
+describe StopAreaCopy do
+
+ subject { StopAreaCopy.new(:source_id => 1, :hierarchy => "child", :area_type => "Quay") }
+
+ it { should validate_presence_of :source_id }
+ it { should validate_presence_of :hierarchy }
+ it { should validate_presence_of :area_type }
+
+
+ describe ".save" do
+
+ it "should create a child for source" do
+ source = Chouette::StopArea.new( :area_type => "CommercialStopPoint", :name => "test1" )
+ source.save
+ subject.source_id = source.id
+ subject.hierarchy = "child"
+ subject.area_type = "Quay"
+ subject.save
+ source.reload
+ source.children.length.should == 1
+ source.children[0].name.should == "test1"
+ end
+ it "should create a parent for source" do
+ source = Chouette::StopArea.new( :area_type => "CommercialStopPoint", :name => "test2" )
+ source.save
+ subject.source_id = source.id
+ subject.hierarchy = "parent"
+ subject.area_type = "StopPlace"
+ subject.save
+ source.reload
+ source.parent.should_not be_nil
+ source.parent.name.should == 'test2'
+ end
+
+ end
+
+end
diff --git a/spec/models/time_table_combination_spec.rb b/spec/models/time_table_combination_spec.rb
new file mode 100644
index 000000000..842c6f211
--- /dev/null
+++ b/spec/models/time_table_combination_spec.rb
@@ -0,0 +1,90 @@
+require 'spec_helper'
+
+describe TimeTableCombination do
+ let!(:source){ Factory(:time_table)}
+ let!(:combined){Factory(:time_table)}
+ subject {Factory.build(:time_table_combination)}
+
+ it { should validate_presence_of :source_id }
+ it { should validate_presence_of :combined_id }
+ it { should validate_presence_of :operation }
+
+ it { should ensure_inclusion_of(:operation).in_array(TimeTableCombination.operations) }
+
+
+ describe "#combine" do
+ context "when operation is union" do
+ before(:each) do
+ source.periods.clear
+ source.dates.clear
+ source.int_day_types = 508
+ source.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,31))
+ source.save
+ combined.periods.clear
+ combined.dates.clear
+ combined.int_day_types = 508
+ combined.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,15), :period_end => Date.new(2014,9,15))
+ combined.save
+ subject.operation = 'union'
+ subject.source_id = source.id
+ subject.combined_id = combined.id
+ subject.combine
+ source.reload
+ end
+ it "should add combined to source" do
+ source.periods.size.should == 1
+ source.periods[0].period_start.should == Date.new(2014,8,1)
+ source.periods[0].period_end.should == Date.new(2014,9,15)
+ end
+ end
+ context "when operation is intersect" do
+ before(:each) do
+ source.periods.clear
+ source.dates.clear
+ source.int_day_types = 508
+ source.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,31))
+ source.save
+ combined.periods.clear
+ combined.dates.clear
+ combined.int_day_types = 508
+ combined.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,15), :period_end => Date.new(2014,9,15))
+ combined.save
+ subject.operation = 'intersection'
+ subject.source_id = source.id
+ subject.combined_id = combined.id
+ subject.combine
+ source.reload
+ end
+ it "should intersect combined to source" do
+ source.periods.size.should == 1
+ source.periods[0].period_start.should == Date.new(2014,8,15)
+ source.periods[0].period_end.should == Date.new(2014,8,31)
+ end
+ end
+ context "when operation is disjoin" do
+ before(:each) do
+ source.periods.clear
+ source.dates.clear
+ source.int_day_types = 508
+ source.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,31))
+ source.save
+ combined.periods.clear
+ combined.dates.clear
+ combined.int_day_types = 508
+ combined.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,15), :period_end => Date.new(2014,9,15))
+ combined.save
+ subject.operation = 'disjunction'
+ subject.source_id = source.id
+ subject.combined_id = combined.id
+ subject.combine
+ source.reload
+ end
+ it "should disjoin combined to source" do
+ source.periods.size.should == 1
+ source.periods[0].period_start.should == Date.new(2014,8,1)
+ source.periods[0].period_end.should == Date.new(2014,8,14)
+ end
+ 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 c9053664b..68f8669e0 100644
--- a/spec/models/vehicle_journey_import_spec.rb
+++ b/spec/models/vehicle_journey_import_spec.rb
@@ -3,37 +3,71 @@ require 'spec_helper'
describe VehicleJourneyImport do
- let(:csv_file) { File.open(Rails.root.join("spec", "fixtures", "vehicle_journey_imports_valid.csv").to_s, "r") }
- let(:csv_file_upload) { mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) ) }
+ def update_csv_file_with_factory_data(filename)
+ csv_file = CSV.open("/tmp/#{filename}", "wb",{ :col_sep => ";"}) do |csv|
+ counter = 0
+ 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 - 7].id; row)
+ end
+ counter += 1
+ end
+ end
+
+ File.open("/tmp/#{filename}")
+ end
+
let!(:route) { create(:route) }
let!(:other_route) { create(:route) }
- let!(:journey_pattern) { create(:journey_pattern_common, :route => route) }
- let!(:other_journey_pattern) { create(:journey_pattern_common, :route => 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, :objectid => "import:VehicleJourney:1", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
- let!(:vehicle_journey2) { create(:vehicle_journey, :objectid => "import:VehicleJourney:2", :route_id => route.id, :journey_pattern_id => other_journey_pattern.id) }
- let!(:vehicle_journey3) { create(:vehicle_journey, :objectid => "import:VehicleJourney:3", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
+ let!(:vehicle_journey1) { create(:vehicle_journey_common, :objectid => "import:VehicleJourney:1", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
+ let!(:vehicle_journey2) { create(:vehicle_journey_common, :objectid => "import:VehicleJourney:2", :route_id => route.id, :journey_pattern_id => other_journey_pattern.id) }
+ let!(:vehicle_journey3) { create(:vehicle_journey_common, :objectid => "import:VehicleJourney:3", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
- let!(:stop_area1) { create(:stop_area, :name => "Arrêt 1") }
- let!(:stop_area2) { create(:stop_area, :name => "Arrêt 2") }
- let!(:stop_area3) { create(:stop_area, :name => "Arrêt 3") }
- let!(:stop_area4) { create(:stop_area, :name => "Arrêt 4") }
+ 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!(:stop_point1) { create(:stop_point, :id => 1, :stop_area => stop_area1) }
- let!(:stop_point2) { create(:stop_point, :id => 2, :stop_area => stop_area2) }
- let!(:stop_point3) { create(:stop_point, :id => 3, :stop_area => stop_area3) }
- let!(:stop_point4) { create(:stop_point, :id => 4, :stop_area => stop_area4) }
+ # Must use uploaded file and not classical ruby File!
+ let(:valid_file) {
+ csv_file = update_csv_file_with_factory_data("vehicle_journey_imports_valid.csv")
+ mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) )
+ }
+
+ let(:invalid_file_on_vj) {
+ csv_file = update_csv_file_with_factory_data("vehicle_journey_imports_with_vj_invalid.csv")
+ mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) )
+ }
+
+ let(:invalid_file_on_vjas) {
+ csv_file = update_csv_file_with_factory_data("vehicle_journey_imports_with_vjas_invalid.csv")
+ mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) )
+ }
+
+ let(:invalid_file_on_vjas_object) {
+ csv_file = update_csv_file_with_factory_data("vehicle_journey_imports_with_vjas_bad_order.csv")
+ mock("CSV", :tempfile => csv_file, :original_filename => File.basename(csv_file), :path => File.path(csv_file) )
+ }
- subject { VehicleJourneyImport.new(:route => route, :file => csv_file_upload) }
-
- before :each do
- route.stop_points.destroy_all
- route.stop_points << [stop_point1, stop_point2, stop_point3, stop_point4]
- journey_pattern.stop_points << [stop_point1, stop_point2, stop_point3, stop_point4]
- other_journey_pattern.stop_points << [stop_point1, stop_point3, stop_point4]
- end
+ subject { VehicleJourneyImport.new(:route => route, :file => valid_file) }
describe ".save" do
@@ -42,26 +76,40 @@ describe VehicleJourneyImport do
end
it "should validate presence of file" do
- expect(VehicleJourneyImport.new(:file => csv_file_upload).save).to be_false
+ expect(VehicleJourneyImport.new(:file => valid_file).save).to be_false
end
it "should import vehicle_journeys and create the right number of objects" do
- expect(VehicleJourneyImport.new(:file => csv_file_upload, :route => route).save).to be_true
+ expect(VehicleJourneyImport.new(:file => valid_file, :route => route).save).to be_true
+ expect(Chouette::VehicleJourney.all.size).to eq(4)
+ expect(Chouette::VehicleJourneyAtStop.all.size).to eq(17)
+ end
+
+ it "should not import vehicle_journeys and not create objects when vehicle journey at stops are not in ascendant order" do
+ expect(VehicleJourneyImport.new(:route => route, :file => invalid_file_on_vjas_object).save).to be_false
+ expect(Chouette::VehicleJourney.all.size).to eq(3)
+ expect(Chouette::VehicleJourneyAtStop.all.size).to eq(0)
end
+ # it "should not import vehicle_journeys and not create objects with invalid file" do
+ # expect(VehicleJourneyImport.new(:file => invalid_file_on_vj, :route => route).save).to be_false
+ # expect(Chouette::VehicleJourney.all.size).to eq(3)
+ # expect(Chouette::VehicleJourneyAtStop.all.size).to eq(0)
+ # end
+
end
describe ".find_journey_pattern_schedule" do
it "should return journey pattern with same stop points" do
- expect(subject.find_journey_pattern_schedule( { 1 => "9:00", 2 => "9:05", 3 => "9:10", 4 => "9:15"} )).to eq(journey_pattern)
- expect(subject.find_journey_pattern_schedule( { 1 => "9:00", 2 => nil, 3 => "9:10", 4 => "9:15"} )).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( { 1 => "9:00", 2 => "9:05", 3 => nil, 4 => "9:15"} )).to be_true
- expect(subject.find_journey_pattern_schedule( { 1 => "9:00", 2 => "9:05", 3 => nil, 4 => "9:15"} ).id).not_to eq(journey_pattern.id)
- expect(subject.find_journey_pattern_schedule( { 1 => "9:00", 2 => "9:05", 3 => nil, 4 => "9:15"} ).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
@@ -69,46 +117,30 @@ describe VehicleJourneyImport do
describe ".load_imported_vehicle_journeys" do
it "should return false when stop points in file are not the same in the route" do
- vehicle_journey_import = VehicleJourneyImport.new(:route => other_route, :file => csv_file_upload)
- vehicle_journey_import.load_imported_vehicle_journeys
-
- expect(vehicle_journey_import.errors.messages).not_to be_empty
- expect(Chouette::VehicleJourney.all.size).to eq(3)
- expect(Chouette::VehicleJourneyAtStop.all.size).to eq(11)
+ vehicle_journey_import = VehicleJourneyImport.new(:route => other_route, :file => valid_file)
+ expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_exception
end
- it "should return false when vehicle journeys in file are invalid" do
- invalid_file = File.open(Rails.root.join("spec", "fixtures", "vehicle_journey_imports_with_vj_invalid.csv").to_s, "r")
- invalid_csv_file_upload = mock("CSV", :tempfile => invalid_file, :original_filename => File.basename(invalid_file), :path => File.path(invalid_file) )
+ # it "should return errors when vehicle journeys in file are invalid" do
+ # vehicle_journey_import = VehicleJourneyImport.new(:route => route, :file => invalid_file_on_vj)
- vehicle_journey_import = VehicleJourneyImport.new(:route => other_route, :file => invalid_csv_file_upload)
- vehicle_journey_import.load_imported_vehicle_journeys
- puts "vehicle_journey_import.errors #{vehicle_journey_import.errors.methods.inspect}"
-
- expect(vehicle_journey_import.errors.messages).not_to be_empty
- expect(Chouette::VehicleJourney.all.size).to eq(3)
- expect(Chouette::VehicleJourneyAtStop.all.size).to eq(11)
+ # expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_error
+ # end
+
+ it "should return errors when vehicle journey at stops in file are invalid" do
+ vehicle_journey_import = VehicleJourneyImport.new(:route => route, :file => invalid_file_on_vjas)
+ expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_exception
end
- it "should return false when vehicle journey at stops in file are invalid" do
- invalid_file = File.open(Rails.root.join("spec", "fixtures", "vehicle_journey_imports_with_vjas_invalid.csv").to_s, "r")
- invalid_csv_file_upload = mock("CSV", :tempfile => invalid_file, :original_filename => File.basename(invalid_file), :path => File.path(invalid_file) )
-
- vehicle_journey_import = VehicleJourneyImport.new(:route => other_route, :file => invalid_csv_file_upload)
- vehicle_journey_import.load_imported_vehicle_journeys
-
- expect(vehicle_journey_import.errors.messages).not_to be_empty
- expect(Chouette::VehicleJourney.all.size).to eq(3)
- expect(Chouette::VehicleJourneyAtStop.all.size).to eq(11)
+ it "should return errors when vehicle journey at stops are not in ascendant order" do
+ vehicle_journey_import = VehicleJourneyImport.new(:route => route, :file => invalid_file_on_vjas_object)
+ expect(vehicle_journey_import.load_imported_vehicle_journeys.size).to eq(3)
+ expect(vehicle_journey_import.errors.messages).to be_empty
end
it "should load vehicle journeys" do
- subject.load_imported_vehicle_journeys
-
- expect(subject.errors.collect(&:messages)).to eq([])
- expect(Chouette::VehicleJourney.all.size).to eq(4)
- expect(Chouette::VehicleJourney.all.collect(&:objectid)).to include(vehicle_journey1.objectid, vehicle_journey2.objectid, vehicle_journey3.objectid)
- expect(Chouette::VehicleJourneyAtStop.all.size).to eq(15)
+ expect(subject.load_imported_vehicle_journeys.size).to eq(4)
+ expect(subject.errors.messages).to eq({})
end
end
diff --git a/spec/models/vehicle_translation_spec.rb b/spec/models/vehicle_translation_spec.rb
index 2a9c53371..bc16f2260 100644
--- a/spec/models/vehicle_translation_spec.rb
+++ b/spec/models/vehicle_translation_spec.rb
@@ -3,15 +3,42 @@ require 'spec_helper'
describe VehicleTranslation do
let!(:company){ Factory(:company )}
let!(:journey_pattern){Factory(:journey_pattern)}
- let!(:vehicle_journey){ Factory(:vehicle_journey,
+ let!(:vehicle_journey){ Factory(:vehicle_journey,
:objectid => "dummy",
:journey_pattern => journey_pattern,
:route => journey_pattern.route,
:company => company,
- :transport_mode => Chouette::TransportMode.new("metro"),
+ :transport_mode => Chouette::TransportMode.new("metro"),
:published_journey_name => "dummy"
)}
- subject {Factory.build(:vehicle_translation, :vehicle_journey_id => vehicle_journey.id)}
+ subject {Factory.build(:vehicle_translation,
+ :vehicle_journey_id => vehicle_journey.id,
+ :first_stop_time => "12:00",
+ :departure_or_arrival => "departure",
+ :duration => 9,
+ :count => 2)}
+
+ describe "#first_stop_time=" do
+ context "when setting invalid value" do
+ it "should have an error on first_stop_departure_time" do
+ subject.first_stop_time = "dummy"
+ subject.valid?
+ subject.errors[ :first_stop_time].should_not be_nil
+ end
+ end
+
+ end
+ describe "#evaluate_delta" do
+ it "should return 3600 seconds" do
+ subject.evaluate_delta( Time.parse( "11:00")).should == 3600.0
+ end
+ end
+ describe "#first_delta" do
+ it "should return 3600 seconds" do
+ subject.should_receive( :first_vjas_time).and_return( Time.parse( "11:00"))
+ subject.first_delta
+ end
+ end
describe "#translate" do
it "should add new vehicle" do
@@ -29,19 +56,19 @@ describe VehicleTranslation do
end
it "should add vehicle having same transport_mode" do
subject.translate
- last_created_vehicle.transport_mode.should == vehicle_journey.transport_mode
+ last_created_vehicle.transport_mode.should == vehicle_journey.transport_mode
end
it "should add vehicle having same journey_pattern" do
subject.translate
- last_created_vehicle.journey_pattern.should == vehicle_journey.journey_pattern
+ last_created_vehicle.journey_pattern.should == vehicle_journey.journey_pattern
end
it "should add vehicle having same route" do
subject.translate
- last_created_vehicle.route.should == vehicle_journey.route
+ last_created_vehicle.route.should == vehicle_journey.route
end
it "should add vehicle having same company" do
subject.translate
- last_created_vehicle.company.should == vehicle_journey.company
+ last_created_vehicle.company.should == vehicle_journey.company
end
it "should add vehicle with as many vehicle_journey_at_stops as on basic vehicle" do
subject.translate
@@ -49,10 +76,11 @@ describe VehicleTranslation do
end
it "should add vehicle where vehicle_journey_at_stops are translated with #duration" do
read_vehicle = Chouette::VehicleJourney.find(vehicle_journey.id) # read from bd, change time values
+ delta = subject.first_delta
subject.translate
last_created_vehicle.vehicle_journey_at_stops.each_with_index do |vjas, index|
- vjas.departure_time.should == (read_vehicle.vehicle_journey_at_stops[index].departure_time + subject.duration.minutes)
- vjas.arrival_time.should == (read_vehicle.vehicle_journey_at_stops[index].arrival_time + subject.duration.minutes)
+ vjas.departure_time.should == (read_vehicle.vehicle_journey_at_stops[index].departure_time + delta + subject.duration.minutes)
+ vjas.arrival_time.should == (read_vehicle.vehicle_journey_at_stops[index].arrival_time + delta + subject.duration.minutes)
end
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/time_tables_spec.rb b/spec/requests/time_tables_spec.rb
index 3fee137ef..fbe03db2b 100644
--- a/spec/requests/time_tables_spec.rb
+++ b/spec/requests/time_tables_spec.rb
@@ -13,19 +13,19 @@ describe "TimeTables" do
page.should have_content(time_tables.first.comment)
page.should have_content(time_tables.last.comment)
end
-
- end
- describe "show" do
+ end
+
+ describe "show" do
it "display time_table" do
visit referential_time_tables_path(referential)
click_link "#{time_tables.first.comment}"
page.should have_content(time_tables.first.comment)
end
-
+
end
- describe "new" do
+ describe "new" do
it "creates time_table and return to show" do
visit referential_time_tables_path(referential)
click_link "Ajouter un calendrier"
@@ -36,7 +36,7 @@ describe "TimeTables" do
end
end
- describe "edit and return to show" do
+ describe "edit and return to show" do
it "edit time_table" do
visit referential_time_table_path(referential, subject)
click_link "Modifier ce calendrier"
diff --git a/spec/requests/vehicle_journey_imports_spec.rb b/spec/requests/vehicle_journey_imports_spec.rb
new file mode 100644
index 000000000..68fe04e0b
--- /dev/null
+++ b/spec/requests/vehicle_journey_imports_spec.rb
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+require 'spec_helper'
+
+describe "VehicleJourneyImports" do
+ login_user
+
+ let!(:route) { create :route }
+
+ let(:valid_file_path) {
+ csv_file = update_csv_file_with_factory_data("vehicle_journey_imports_valid.csv")
+ File.path(csv_file)
+ }
+
+ let(:invalid_file_path) {
+ csv_file = update_csv_file_with_factory_data("vehicle_journey_imports_with_vjas_invalid.csv")
+ File.path(csv_file)
+ }
+
+ def update_csv_file_with_factory_data(filename)
+ csv_file = CSV.open("/tmp/#{filename}", "wb",{ :col_sep => ";"}) do |csv|
+ counter = 0
+ 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 - 7].id; row)
+ end
+ counter += 1
+ end
+
+ end
+
+ File.open("/tmp/#{filename}")
+ end
+
+ describe "new" do
+ it "should create vehicle journey file and return to route show page" do
+ visit new_referential_line_route_vehicle_journey_import_path(referential, route.line, route)
+ attach_file('Fichier', valid_file_path)
+ click_button "Lancer l'import"
+ expect(page).to have_content(I18n.t("vehicle_journey_imports.new.success"))
+ expect(page).to have_content("Séquence d'arrêts #{route.name}")
+ end
+
+ it "should return error messages when file is invalid" do
+ visit new_referential_line_route_vehicle_journey_import_path(referential, route.line, route)
+ attach_file('Fichier', invalid_file_path)
+ click_button "Lancer l'import"
+ expect(page).to have_content(I18n.t("vehicle_journey_imports.errors.import_aborted"))
+ end
+
+ it "should return error message when file missing on upload" do
+ visit new_referential_line_route_vehicle_journey_import_path(referential, route.line, route)
+ click_button "Lancer l'import"
+ expect(page).to have_content(I18n.t("vehicle_journey_imports.errors.import_aborted"))
+ end
+ end
+
+end
diff --git a/spec/views/time_tables/show.html.erb_spec.rb b/spec/views/time_tables/show.html.erb_spec.rb
index 9d0527c5d..b5b7dedb3 100644
--- a/spec/views/time_tables/show.html.erb_spec.rb
+++ b/spec/views/time_tables/show.html.erb_spec.rb
@@ -5,6 +5,7 @@ describe "/time_tables/show" do
assign_referential
let!(:time_table) { assign(:time_table, create(:time_table)) }
let!(:year) { assign(:year, Date.today.cwyear) }
+ let!(:time_table_combination) {assign(:time_table_combination, TimeTableCombination.new)}
it "should render h2 with the time_table comment" do
render
diff --git a/spec/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb_spec.rb b/spec/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb_spec.rb
index e5ee0d635..5eebb0e83 100644
--- a/spec/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb_spec.rb
+++ b/spec/views/vehicle_journeys/_vehicle_journey_at_stop_fields.html.erb_spec.rb
@@ -10,11 +10,13 @@ describe "/vehicle_journeys/_vehicle_journey_at_stop_fields" do
let!(:vehicle_journey_at_stop_counter) { assign :vehicle_journey_at_stop_counter, 0 }
def render_collection
- render( :partial => "vehicle_journeys/vehicle_journey_at_stop_fields", :collection => vehicle_journey.vehicle_journey_at_stops, :as => :vehicle_journey_at_stop)
+ render( :partial => "vehicle_journeys/vehicle_journey_at_stop_fields", :collection => vehicle_journey.vehicle_journey_at_stops, :as => :vehicle_journey_at_stop, :locals => { :vehicle_journey_at_stops_size => 1 } )
end
+
def field_name
"vehicle_journey[vehicle_journey_at_stops_attributes][0]"
end
+
it "should render vehicle_journey_at_stop's departure time" do
render_collection
rendered.should have_selector("td select", :name => "#{field_name}[departure_time(5i)]")
diff --git a/spec/views/vehicle_journeys/edit.html.erb_spec.rb b/spec/views/vehicle_journeys/edit.html.erb_spec.rb
index a3eb871e2..c7db87706 100644
--- a/spec/views/vehicle_journeys/edit.html.erb_spec.rb
+++ b/spec/views/vehicle_journeys/edit.html.erb_spec.rb
@@ -11,12 +11,6 @@ describe "/vehicle_journeys/edit" do
render
view.should render_template(:partial => "_form")
end
- context "summary part" do
- it "should render route name" do
- render
- rendered.should have_selector( ".summary a", :text => route.name)
- end
- end
end
diff --git a/spec/views/vehicle_journeys/new.html.erb_spec.rb b/spec/views/vehicle_journeys/new.html.erb_spec.rb
index 495b667bd..bc0d68c2d 100644
--- a/spec/views/vehicle_journeys/new.html.erb_spec.rb
+++ b/spec/views/vehicle_journeys/new.html.erb_spec.rb
@@ -11,12 +11,6 @@ describe "/vehicle_journeys/new" do
render
view.should render_template(:partial => "_form")
end
- context "summary part" do
- it "should render route name" do
- render
- rendered.should have_selector( ".summary a", :text => route.name)
- end
- end
end