aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert2017-09-11 18:03:06 +0200
committerRobert2017-09-11 18:03:06 +0200
commit37865fad65adacae41bff0677651ca0a4d9db974 (patch)
tree0889ea9d7883bb27b493c16b9b08426fa22545a0
parentf7bc874de79ff9a68aa03523cf653407663e7c55 (diff)
parent8fe9a39516f6fb71545d6329c448680d6f8c75d1 (diff)
downloadchouette-core-37865fad65adacae41bff0677651ca0a4d9db974.tar.bz2
merged with master
-rw-r--r--.gitignore3
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock22
-rw-r--r--app/assets/fonts/sBoiv/sboiv.eotbin2260 -> 15728 bytes
-rw-r--r--app/assets/fonts/sBoiv/sboiv.svg27
-rw-r--r--app/assets/fonts/sBoiv/sboiv.ttfbin2104 -> 15572 bytes
-rw-r--r--app/assets/fonts/sBoiv/sboiv.woffbin2180 -> 15648 bytes
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js12
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js2
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js8
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js3
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js4
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/containers/AddJourneyPattern.js1
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/containers/JourneyPatternList.js1
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/containers/SaveJourneyPattern.js14
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/index.js3
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/reducers/editMode.js12
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/reducers/index.js2
-rw-r--r--app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js4
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/actions/index.js91
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js7
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js4
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js3
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/SaveTimetable.js8
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js1
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/containers/ErrorModal.js1
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js12
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/containers/SaveTimetable.js4
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js8
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/index.js5
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js24
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js2
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js33
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js106
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js10
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js34
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js14
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourneys.js3
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js77
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js5
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js25
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js3
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js7
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js14
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Tools.js4
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/VehicleJourneysList.js1
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js4
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/EditVehicleJourney.js5
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/index.js3
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/editMode.js12
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/index.js2
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js3
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js22
-rw-r--r--app/assets/javascripts/filters/calendar.js6
-rw-r--r--app/assets/javascripts/filters/import.js6
-rw-r--r--app/assets/javascripts/filters/time_table.js7
-rw-r--r--app/assets/javascripts/filters/workbench.js6
-rw-r--r--app/assets/javascripts/helpers/date_filters.js38
-rw-r--r--app/assets/javascripts/time_table.coffee14
-rw-r--r--app/assets/javascripts/workbench.coffee18
-rw-r--r--app/assets/stylesheets/application.sass1
-rw-r--r--app/assets/stylesheets/components/_page_header.sass12
-rw-r--r--app/assets/stylesheets/components/_tables.sass69
-rw-r--r--app/assets/stylesheets/main/access_links.sass18
-rw-r--r--app/assets/stylesheets/main/access_points.sass78
-rw-r--r--app/assets/stylesheets/main/api_keys.sass7
-rw-r--r--app/assets/stylesheets/main/calendar.sass98
-rw-r--r--app/assets/stylesheets/main/calendars.sass11
-rw-r--r--app/assets/stylesheets/main/companies.sass9
-rw-r--r--app/assets/stylesheets/main/compliance_checks.sass157
-rw-r--r--app/assets/stylesheets/main/connection_links.sass30
-rw-r--r--app/assets/stylesheets/main/errors.sass21
-rw-r--r--app/assets/stylesheets/main/export_tasks.sass10
-rw-r--r--app/assets/stylesheets/main/exports.sass19
-rw-r--r--app/assets/stylesheets/main/group_of_lines.sass15
-rw-r--r--app/assets/stylesheets/main/help.sass121
-rw-r--r--app/assets/stylesheets/main/import_tasks.sass11
-rw-r--r--app/assets/stylesheets/main/imports.sass40
-rw-r--r--app/assets/stylesheets/main/journey_patterns.sass49
-rw-r--r--app/assets/stylesheets/main/layout.sass133
-rw-r--r--app/assets/stylesheets/main/lines.sass87
-rw-r--r--app/assets/stylesheets/main/multiple_selection.sass17
-rw-r--r--app/assets/stylesheets/main/networks.sass9
-rw-r--r--app/assets/stylesheets/main/organisations.sass5
-rw-r--r--app/assets/stylesheets/main/referentials.sass34
-rw-r--r--app/assets/stylesheets/main/route_sections.sass54
-rw-r--r--app/assets/stylesheets/main/routes.sass46
-rw-r--r--app/assets/stylesheets/main/rule_parameter_sets.sass45
-rw-r--r--app/assets/stylesheets/main/simple_form.sass3
-rw-r--r--app/assets/stylesheets/main/stop_areas.sass165
-rw-r--r--app/assets/stylesheets/main/stop_points.sass26
-rw-r--r--app/assets/stylesheets/main/time_table_combinations.sass7
-rw-r--r--app/assets/stylesheets/main/time_tables.sass135
-rw-r--r--app/assets/stylesheets/main/vehicle_journey_frequencies.sass155
-rw-r--r--app/assets/stylesheets/main/vehicle_journeys.sass118
-rw-r--r--app/assets/stylesheets/main/vehicle_translation.sass10
-rw-r--r--app/assets/stylesheets/modules/import_messages.sass5
-rw-r--r--app/assets/stylesheets/typography/_fonts.sass10
-rw-r--r--app/assets/stylesheets/typography/_sboiv.sass89
-rw-r--r--app/controllers/api/v1/chouette_controller.rb5
-rw-r--r--app/controllers/api/v1/iboo_controller.rb21
-rw-r--r--app/controllers/api/v1/imports_controller.rb15
-rw-r--r--app/controllers/api/v1/netex_imports_controller.rb48
-rw-r--r--app/controllers/api/v1/workbenches_controller.rb3
-rw-r--r--app/controllers/api_keys_controller.rb32
-rw-r--r--app/controllers/application_controller.rb11
-rw-r--r--app/controllers/autocomplete_time_tables_controller.rb11
-rw-r--r--app/controllers/compliance_check_tasks_controller.rb49
-rw-r--r--app/controllers/compliance_checks_controller.rb83
-rw-r--r--app/controllers/import_messages_controller.rb26
-rw-r--r--app/controllers/import_resources_controller.rb40
-rw-r--r--app/controllers/imports_controller.rb69
-rw-r--r--app/controllers/referentials_controller.rb35
-rw-r--r--app/controllers/workbenches_controller.rb9
-rw-r--r--app/decorators/api_key_decorator.rb30
-rw-r--r--app/decorators/import_decorator.rb44
-rw-r--r--app/decorators/import_resource_decorator.rb10
-rw-r--r--app/decorators/import_resources_decorator.rb12
-rw-r--r--app/decorators/referential_decorator.rb2
-rw-r--r--app/helpers/compliance_check_tasks_helper.rb11
-rw-r--r--app/helpers/compliance_checks_helper.rb96
-rw-r--r--app/helpers/import_resources_helper.rb15
-rw-r--r--app/helpers/imports_helper.rb18
-rw-r--r--app/helpers/newapplication_helper.rb2
-rw-r--r--app/helpers/table_builder_helper.rb185
-rw-r--r--app/helpers/table_builder_helper/column.rb11
-rw-r--r--app/helpers/table_builder_helper/url.rb7
-rw-r--r--app/models/api/v1/api_key.rb24
-rw-r--r--app/models/chouette/access_point.rb8
-rw-r--r--app/models/chouette/active_record.rb13
-rw-r--r--app/models/chouette/company.rb2
-rw-r--r--app/models/chouette/group_of_line.rb2
-rw-r--r--app/models/chouette/journey_pattern.rb5
-rw-r--r--app/models/chouette/network.rb2
-rw-r--r--app/models/chouette/route.rb4
-rw-r--r--app/models/chouette/routing_constraint_zone.rb4
-rw-r--r--app/models/chouette/stif_netex_objectid.rb38
-rw-r--r--app/models/chouette/time_table.rb19
-rw-r--r--app/models/chouette/trident_active_record.rb2
-rw-r--r--app/models/chouette/vehicle_journey.rb4
-rw-r--r--app/models/compliance_check.rb55
-rw-r--r--app/models/compliance_check_export.rb56
-rw-r--r--app/models/compliance_check_report.rb9
-rw-r--r--app/models/compliance_check_result.rb73
-rw-r--r--app/models/compliance_check_service.rb23
-rw-r--r--app/models/compliance_check_task.rb114
-rw-r--r--app/models/concerns/error_format.rb29
-rw-r--r--app/models/concerns/line_referential_support.rb8
-rw-r--r--app/models/concerns/report_concern.rb170
-rw-r--r--app/models/concerns/stif_netex_attributes_support.rb58
-rw-r--r--app/models/concerns/stop_area_referential_support.rb7
-rw-r--r--app/models/data_format_enumerations.rb4
-rw-r--r--app/models/export_report.rb5
-rw-r--r--app/models/import.rb70
-rw-r--r--app/models/import_message_export.rb46
-rw-r--r--app/models/import_report.rb7
-rw-r--r--app/models/import_resource.rb23
-rw-r--r--app/models/netex_import.rb18
-rw-r--r--app/models/organisation.rb1
-rw-r--r--app/models/referential.rb30
-rw-r--r--app/models/referential_metadata.rb4
-rw-r--r--app/models/vehicle_journey_import.rb80
-rw-r--r--app/models/workbench.rb2
-rw-r--r--app/models/workbench_import.rb5
-rw-r--r--app/policies/api_key_policy.rb19
-rw-r--r--app/policies/import_policy.rb7
-rw-r--r--app/services/http_service.rb15
-rw-r--r--app/services/retry_service.rb54
-rw-r--r--app/services/zip_service.rb79
-rw-r--r--app/views/api/v1/imports/index.rabl3
-rw-r--r--app/views/api/v1/imports/show.rabl6
-rw-r--r--app/views/api/v1/workbenches/index.rabl3
-rw-r--r--app/views/api/v1/workbenches/show.rabl3
-rw-r--r--app/views/api_keys/_form.html.slim13
-rw-r--r--app/views/api_keys/edit.html.slim3
-rw-r--r--app/views/api_keys/index.html.slim27
-rw-r--r--app/views/api_keys/new.html.slim3
-rw-r--r--app/views/api_keys/show.html.slim7
-rw-r--r--app/views/calendars/_filters.html.slim2
-rw-r--r--app/views/calendars/edit.html.slim2
-rw-r--r--app/views/calendars/index.html.slim17
-rw-r--r--app/views/calendars/new.html.slim2
-rw-r--r--app/views/calendars/show.html.slim2
-rw-r--r--app/views/companies/index.html.slim7
-rw-r--r--app/views/companies/show.html.slim2
-rw-r--r--app/views/compliance_check_tasks/new.html.erb39
-rw-r--r--app/views/compliance_check_tasks/new.js.coffee7
-rw-r--r--app/views/compliance_checks/_compliance_check.html.slim17
-rw-r--r--app/views/compliance_checks/_compliance_check_results.html.slim92
-rw-r--r--app/views/compliance_checks/_compliance_checks.html.slim9
-rw-r--r--app/views/compliance_checks/detailed_errors_index.csv.slim37
-rw-r--r--app/views/compliance_checks/index.html.slim14
-rw-r--r--app/views/compliance_checks/index.js.slim1
-rw-r--r--app/views/compliance_checks/report.html.slim41
-rw-r--r--app/views/compliance_checks/show.html.slim22
-rw-r--r--app/views/compliance_checks/summary_errors_index.csv.slim34
-rw-r--r--app/views/import_resources/index.html.slim58
-rw-r--r--app/views/imports/_filters.html.slim21
-rw-r--r--app/views/imports/_form.html.slim20
-rw-r--r--app/views/imports/index.html.slim63
-rw-r--r--app/views/imports/new.html.slim14
-rw-r--r--app/views/imports/show.html.slim76
-rw-r--r--app/views/journey_patterns_collections/show.html.slim2
-rw-r--r--app/views/layouts/navigation/_main_nav_left.html.slim14
-rw-r--r--app/views/line_footnotes/edit.html.slim2
-rw-r--r--app/views/line_footnotes/show.html.slim2
-rw-r--r--app/views/line_referentials/show.html.slim2
-rw-r--r--app/views/lines/index.html.slim7
-rw-r--r--app/views/lines/show.html.slim2
-rw-r--r--app/views/networks/index.html.slim9
-rw-r--r--app/views/networks/show.html.slim4
-rw-r--r--app/views/referential_companies/index.html.slim7
-rw-r--r--app/views/referential_companies/show.html.slim2
-rw-r--r--app/views/referential_lines/show.html.slim7
-rw-r--r--app/views/referential_networks/index.html.slim7
-rw-r--r--app/views/referential_networks/show.html.slim2
-rw-r--r--app/views/referential_stop_areas/show.html.slim2
-rw-r--r--app/views/referentials/_form.html.slim2
-rw-r--r--app/views/referentials/edit.html.slim2
-rw-r--r--app/views/referentials/new.html.slim4
-rw-r--r--app/views/referentials/show.html.slim7
-rw-r--r--app/views/routes/edit.html.slim2
-rw-r--r--app/views/routes/new.html.slim2
-rw-r--r--app/views/routes/show.html.slim7
-rw-r--r--app/views/routing_constraint_zones/edit.html.slim2
-rw-r--r--app/views/routing_constraint_zones/index.html.slim11
-rw-r--r--app/views/routing_constraint_zones/new.html.slim4
-rw-r--r--app/views/routing_constraint_zones/show.html.slim7
-rw-r--r--app/views/stop_area_referentials/show.html.slim2
-rw-r--r--app/views/stop_areas/index.html.slim10
-rw-r--r--app/views/stop_areas/show.html.slim2
-rw-r--r--app/views/time_table_combinations/_form.html.slim2
-rw-r--r--app/views/time_tables/edit.html.slim5
-rw-r--r--app/views/time_tables/index.html.slim9
-rw-r--r--app/views/time_tables/new.html.slim2
-rw-r--r--app/views/time_tables/show.html.slim2
-rw-r--r--app/views/vehicle_journeys/index.html.slim2
-rw-r--r--app/views/workbenches/index.html.slim10
-rw-r--r--app/views/workbenches/show.html.slim9
-rw-r--r--app/workers/workbench_import_worker.rb83
-rw-r--r--config/deploy.rb3
-rw-r--r--config/initializers/assets.rb2
-rw-r--r--config/initializers/sidekiq.rb13
-rw-r--r--config/locales/api_keys.en.yml6
-rw-r--r--config/locales/api_keys.fr.yml2
-rw-r--r--config/locales/calendars.en.yml1
-rw-r--r--config/locales/calendars.fr.yml1
-rw-r--r--config/locales/compliance_check_results.en.yml457
-rw-r--r--config/locales/compliance_check_results.fr.yml456
-rw-r--r--config/locales/compliance_check_tasks.en.yml17
-rw-r--r--config/locales/compliance_check_tasks.fr.yml17
-rw-r--r--config/locales/compliance_checks.en.yml91
-rw-r--r--config/locales/compliance_checks.fr.yml92
-rw-r--r--config/locales/import_messages.en.yml50
-rw-r--r--config/locales/import_messages.fr.yml50
-rw-r--r--config/locales/import_resources.en.yml18
-rw-r--r--config/locales/import_resources.fr.yml18
-rw-r--r--config/locales/imports.en.yml9
-rw-r--r--config/locales/imports.fr.yml11
-rw-r--r--config/locales/time_tables.en.yml4
-rw-r--r--config/locales/time_tables.fr.yml4
-rw-r--r--config/routes.rb26
-rw-r--r--db/migrate/20170808083322_change_referential_date_format_to_netex.rb9
-rw-r--r--db/migrate/20170808091929_change_objectid_suffix.rb17
-rw-r--r--db/migrate/20170816104020_add_creator_to_imports.rb5
-rw-r--r--db/migrate/20170817122914_add_organisation_to_api_keys.rb5
-rw-r--r--db/migrate/20170901132253_rename_type_in_import_resource.rb5
-rw-r--r--db/migrate/20170907082913_add_data_source_ref.rb10
-rw-r--r--db/schema.rb19
-rw-r--r--lib/stif/netex_file.rb72
-rw-r--r--lib/stif/reflex_synchronization.rb16
-rw-r--r--lib/tasks/ci.rake9
-rw-r--r--lib/tasks/erd.rake (renamed from lib/tasks/generate.rake)0
-rw-r--r--spec/controllers/api/v1/iboo_controller_spec.rb12
-rw-r--r--spec/controllers/api/v1/imports_controller_spec.rb38
-rw-r--r--spec/controllers/api/v1/workbenches_controller_spec.rb25
-rw-r--r--spec/controllers/import_tasks_controller_spec.rb34
-rw-r--r--spec/decorators/api_key_decorator_spec.rb4
-rw-r--r--spec/factories/api_keys.rb4
-rw-r--r--spec/factories/chouette_access_links.rb6
-rw-r--r--spec/factories/chouette_companies.rb2
-rw-r--r--spec/factories/chouette_connection_links.rb4
-rw-r--r--spec/factories/chouette_group_of_lines.rb2
-rw-r--r--spec/factories/chouette_journey_pattern.rb3
-rw-r--r--spec/factories/chouette_networks.rb2
-rw-r--r--spec/factories/chouette_routes.rb2
-rw-r--r--spec/factories/chouette_routing_constraint_zones.rb1
-rw-r--r--spec/factories/chouette_stop_points.rb2
-rw-r--r--spec/factories/chouette_time_table.rb2
-rw-r--r--spec/factories/chouette_timeband.rb4
-rw-r--r--spec/factories/chouette_vehicle_journey.rb2
-rw-r--r--spec/factories/compliance_check_results.rb8
-rw-r--r--spec/factories/compliance_check_tasks.rb8
-rw-r--r--spec/factories/import_messages.rb7
-rw-r--r--spec/factories/import_resources.rb4
-rw-r--r--spec/factories/imports.rb1
-rw-r--r--spec/features/connection_links_spec.rb2
-rw-r--r--spec/features/referentials_spec.rb67
-rw-r--r--spec/features/workbenches_spec.rb22
-rw-r--r--spec/fixtures/OFFRE_TRANSDEV_2017030112251.zipbin0 -> 11189 bytes
-rw-r--r--spec/fixtures/single_reference_import.zipbin220 -> 5446 bytes
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml86
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml33
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml204
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/calendriers.xml80
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml32
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml172
-rw-r--r--spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml172
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/calendriers.xml86
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/commun.xml33
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml204
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/calendriers.xml80
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/commun.xml32
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml172
-rw-r--r--spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml172
-rw-r--r--spec/helpers/table_builder_helper/column_spec.rb39
-rw-r--r--spec/helpers/table_builder_helper_spec.rb15
-rw-r--r--spec/javascripts/time_table/actions_spec.js20
-rw-r--r--spec/javascripts/time_table/reducers/modal_spec.js79
-rw-r--r--spec/javascripts/time_table/reducers/timetable_spec.js87
-rw-r--r--spec/javascripts/vehicle_journeys/actions_spec.js27
-rw-r--r--spec/javascripts/vehicle_journeys/reducers/modal_spec.js9
-rw-r--r--spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js17
-rw-r--r--spec/lib/stif/netex_file_spec.rb27
-rw-r--r--spec/models/api/v1/api_key_spec.rb39
-rw-r--r--spec/models/chouette/access_link_spec.rb12
-rw-r--r--spec/models/chouette/company_spec.rb7
-rw-r--r--spec/models/chouette/connection_link_spec.rb2
-rw-r--r--spec/models/chouette/footnote_spec.rb14
-rw-r--r--spec/models/chouette/group_of_line_spec.rb6
-rw-r--r--spec/models/chouette/network_spec.rb7
-rw-r--r--spec/models/chouette/route/route_base_spec.rb2
-rw-r--r--spec/models/chouette/routing_constraint_zone_spec.rb19
-rw-r--r--spec/models/chouette/stop_point_spec.rb2
-rw-r--r--spec/models/chouette/time_table_spec.rb208
-rw-r--r--spec/models/chouette/trident_active_record_spec.rb128
-rw-r--r--spec/models/compliance_check_result_spec.rb100
-rw-r--r--spec/models/compliance_check_task_spec.rb317
-rw-r--r--spec/models/concerns/error_format_spec.rb41
-rw-r--r--spec/models/import_resource_spec.rb6
-rw-r--r--spec/models/import_spec.rb180
-rw-r--r--spec/models/referential_metadata_spec.rb8
-rw-r--r--spec/models/referential_spec.rb27
-rw-r--r--spec/models/vehicle_journey_export_spec.rb34
-rw-r--r--spec/models/vehicle_journey_import_spec.rb8
-rw-r--r--spec/models/vehicle_translation_spec.rb1
-rw-r--r--spec/policies/api_key_policy_spec.rb28
-rw-r--r--spec/requests/api/v1/netex_import_spec.rb79
-rw-r--r--spec/services/http_service_spec.rb3
-rw-r--r--spec/services/retry_service_spec.rb137
-rw-r--r--spec/services/zip_service/regression_4273_spec.rb59
-rw-r--r--spec/services/zip_service/zip_entry_data_spec.rb32
-rw-r--r--spec/services/zip_service/zip_entry_dirs_spec.rb33
-rw-r--r--spec/services/zip_service/zip_output_streams_spec.rb8
-rw-r--r--spec/support/api_key.rb6
-rw-r--r--spec/support/devise.rb4
-rw-r--r--spec/support/referential.rb1
-rw-r--r--spec/support/shared_context.rb15
-rw-r--r--spec/workers/referential_cloning_worker_spec.rb18
-rw-r--r--spec/workers/workbench_import_worker_spec.rb93
362 files changed, 5650 insertions, 5824 deletions
diff --git a/.gitignore b/.gitignore
index 0cdaa7c9f..29cc18f2e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,6 @@ bin/
/bin/rake
/bin/rails
/bin/rspec
+
+# FIXME Ignore ./spec/services/zip_service/regression_4273_spec.rb files
+/spec/fixtures/target_*.zip \ No newline at end of file
diff --git a/Gemfile b/Gemfile
index aeb776942..2334c3fd4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -107,7 +107,7 @@ gem 'google-analytics-rails'
# Model
gem 'will_paginate'
gem 'ransack'
-gem "squeel", github: 'activerecord-hackery/squeel'
+#gem "squeel", github: 'activerecord-hackery/squeel'
gem 'active_attr'
gem 'sequel'
diff --git a/Gemfile.lock b/Gemfile.lock
index d03a26d18..1e2ac3cf8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -22,15 +22,6 @@ GIT
nokogiri (~> 1.6)
GIT
- remote: https://github.com/activerecord-hackery/squeel.git
- revision: 5542266d502db8022e14105f9dfb455a79d6fc4a
- specs:
- squeel (1.2.3)
- activerecord (>= 3.0)
- activesupport (>= 3.0)
- polyamorous (~> 1.1.0)
-
-GIT
remote: https://github.com/af83/language_engine.git
revision: c4d7d5af781b55c1df4806c3960caf3c22f1ee96
specs:
@@ -313,7 +304,7 @@ GEM
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_portile2 (2.2.0)
- minitest (5.10.2)
+ minitest (5.10.3)
multi_json (1.12.1)
multi_test (0.1.2)
multi_xml (0.6.0)
@@ -338,7 +329,7 @@ GEM
capybara (~> 2.1)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
- polyamorous (1.1.0)
+ polyamorous (1.3.1)
activerecord (>= 3.0)
polylines (0.3.0)
pry (0.10.4)
@@ -356,7 +347,7 @@ GEM
railties (>= 3.1, < 5.0)
rabl (0.13.1)
activesupport (>= 2.3.14)
- rack (1.6.5)
+ rack (1.6.8)
rack-protection (1.5.3)
rack
rack-test (0.6.3)
@@ -409,12 +400,12 @@ GEM
rainbow (2.2.2)
rake
rake (12.0.0)
- ransack (1.6.5)
+ ransack (1.8.3)
actionpack (>= 3.0)
activerecord (>= 3.0)
activesupport (>= 3.0)
i18n
- polyamorous (~> 1.1)
+ polyamorous (~> 1.3)
rb-fsevent (0.9.8)
rb-inotify (0.9.8)
ffi (>= 0.5.0)
@@ -667,7 +658,6 @@ DEPENDENCIES
spring
spring-commands-rspec
sqlite3
- squeel!
teaspoon-jasmine
therubyracer (~> 0.12)
timecop
@@ -679,4 +669,4 @@ DEPENDENCIES
will_paginate-bootstrap
BUNDLED WITH
- 1.14.6
+ 1.15.4
diff --git a/app/assets/fonts/sBoiv/sboiv.eot b/app/assets/fonts/sBoiv/sboiv.eot
index 0bc305533..7bf5449a2 100644
--- a/app/assets/fonts/sBoiv/sboiv.eot
+++ b/app/assets/fonts/sBoiv/sboiv.eot
Binary files differ
diff --git a/app/assets/fonts/sBoiv/sboiv.svg b/app/assets/fonts/sBoiv/sboiv.svg
index 018422b09..42e8988cb 100644
--- a/app/assets/fonts/sBoiv/sboiv.svg
+++ b/app/assets/fonts/sBoiv/sboiv.svg
@@ -11,4 +11,31 @@
<glyph unicode="&#xe901;" glyph-name="preparing" d="M1011.173 614.391l-80.38 80.38c-7.765 8.206-18.731 13.312-30.889 13.312-0.12 0-0.239 0-0.359-0.001-0.129 0.002-0.303 0.003-0.478 0.003-11.951 0-22.708-5.119-30.194-13.284l-56.856-56.347 142.328-142.84 56.829 54.781c7.9 7.644 12.802 18.341 12.802 30.183 0 0.188-0.001 0.376-0.004 0.563 0.035 0.625 0.055 1.389 0.055 2.159 0 12.137-4.911 23.128-12.854 31.092zM504.32 330.758v-142.84h142.84l285.17 285.681-142.328 142.328zM805.872 544.251l-185.847-185.847c-0.834-0.338-1.802-0.535-2.816-0.535s-1.982 0.196-2.868 0.553c-0.285-0.079-0.672-0.113-1.067-0.113-3.676 0-6.656 2.98-6.656 6.656 0 0.395 0.034 0.782 0.1 1.159-0.322 0.797-0.505 1.765-0.505 2.776s0.183 1.979 0.518 2.873l188.387 183.741c0.834 0.338 1.802 0.535 2.816 0.535s1.982-0.196 2.868-0.553c0.285 0.079 0.672 0.113 1.067 0.113 3.676 0 6.656-2.98 6.656-6.656 0-0.395-0.034-0.782-0.1-1.159-0.528-1.405-1.409-2.616-2.539-3.532zM592.38 231.948v44.030h-44.030v36.862l31.23 31.23 80.38-80.38-31.23-31.23zM0.028 239.627h416.234v-51.197h-416.234v51.197z" />
<glyph unicode="&#xe902;" glyph-name="current-ref" d="M530.92 258.291l-70.054 71.588c-17.993 18.204-42.963 29.478-70.566 29.478s-52.573-11.274-70.557-29.468l-30.178 30.159c18.419 18.312 29.902 43.583 30.169 71.537-0.795 26.578-11.995 50.343-29.636 67.527l-70.586 71.609c-17.861 17.868-42.538 28.92-69.798 28.92s-51.937-11.052-69.798-28.92l-51.134-51.134c-17.868-17.861-28.92-42.538-28.92-69.798s11.052-51.937 28.92-69.798l74.145-69.543c17.993-18.204 42.963-29.478 70.566-29.478s52.573 11.274 70.557 29.468l30.178-30.159c-18.419-18.312-29.902-43.583-30.169-71.537-0.004-0.365-0.006-0.734-0.006-1.105 0-25.692 9.92-49.067 26.139-66.504l70.511-71.528c17.835-17.716 42.411-28.665 69.543-28.665s51.708 10.949 69.549 28.67l51.128 51.129c17.992 17.803 29.134 42.5 29.134 69.798s-11.142 51.995-29.126 69.791zM241.499 405.047c-11.25 11.25-20.965 24.545-38.351 24.545-18.074 0-32.726-14.652-32.726-32.726 0-17.386 13.295-27.101 24.545-38.351-5.924-6.606-14.486-10.742-24.015-10.742-0.186 0-0.372 0.002-0.557 0.005-0.198-0.006-0.464-0.009-0.731-0.009-8.851 0-16.88 3.513-22.771 9.221l-71.068 71.58c-5.845 5.909-9.456 14.038-9.456 23.010s3.61 17.101 9.459 23.013l51.131 51.131c6.103 5.703 14.326 9.204 23.366 9.204 0.055 0 0.11 0 0.164 0 0.003 0 0.017 0 0.031 0 9.168 0 17.47-3.712 23.483-9.716l69.543-72.1c6.338-6.063 10.278-14.588 10.278-24.033s-3.94-17.97-10.266-24.021zM493.592 188.748c-0.074-9.007-3.775-17.135-9.713-23.007l-51.137-51.137c-5.96-5.4-13.905-8.705-22.623-8.705-0.317 0-0.631 0.004-0.946 0.013-0.18-0.007-0.446-0.010-0.713-0.010-8.851 0-16.88 3.513-22.771 9.221l-69.022 72.092c-6.338 6.063-10.278 14.588-10.278 24.033s3.94 17.97 10.266 24.021c11.262-11.238 20.977-24.533 38.363-24.533 0.611-0.041 1.326-0.064 2.045-0.064 18.074 0 32.726 14.652 32.726 32.726 0 0.023 0 0.045 0 0.068 0 17.382-13.295 27.097-24.545 38.347 5.712 7.509 14.519 12.409 24.486 12.782 0.070 0.002 0.084 0.002 0.098 0.002 9.168 0 17.47-3.712 23.483-9.716l71.077-71.077c5.998-5.856 9.719-14.023 9.719-23.059 0-0.163-0.001-0.325-0.004-0.487zM1013.117 794.18l-51.134 51.134c-6.502 6.632-15.554 10.743-25.567 10.743s-19.066-4.111-25.561-10.737l-245.451-243.917-107.894 108.405c-6.502 6.632-15.554 10.743-25.567 10.743s-19.066-4.111-25.561-10.737l-51.14-51.14c-6.632-6.502-10.743-15.554-10.743-25.567s4.111-19.066 10.737-25.561l135.512-133.978 51.134-51.134c6.502-6.632 15.554-10.743 25.567-10.743s19.066 4.111 25.561 10.737l51.14 51.14 268.967 269.99c6.632 6.502 10.743 15.554 10.743 25.567s-4.111 19.066-10.737 25.561z" />
<glyph unicode="&#xe903;" glyph-name="chrono" horiz-adv-x="931" d="M440.957-64c243.751 0 440.957 196.267 440.957 438.857 0 225.524-171.483 412.038-391.962 436.419v51.2h73.493v97.524h-244.976v-97.524h73.493v-51.2c-220.478-24.381-391.962-209.676-391.962-436.419 0-242.59 197.206-438.857 440.957-438.857zM756.974 864.917l-71.043-70.705c71.043-41.448 131.062-101.181 172.708-171.886l71.055 70.705c-44.108 69.486-104.115 128-172.72 171.886z" />
+<glyph unicode="&#xe904;" glyph-name="ZDLR" d="M510.771 898.56c248.837 0 450.56-201.723 450.56-450.56s-201.723-450.56-450.56-450.56c-248.837 0-450.56 201.723-450.56 450.56v0c0 248.837 201.723 450.56 450.56 450.56v0zM510.771 929.28c-265.804 0-481.28-215.476-481.28-481.28s215.476-481.28 481.28-481.28c265.804 0 481.28 215.476 481.28 481.28v0c-0.349 265.663-215.617 480.931-481.246 481.28h-0.034zM553.984 778.547c-12.888 4.792-27.778 7.565-43.315 7.565s-30.427-2.773-44.201-7.85l0.886 0.286c-164.787-22.179-290.509-161.908-290.509-331.002 0-184.366 149.458-333.824 333.824-333.824s333.824 149.458 333.824 333.824c0 169.093-125.722 308.823-288.79 330.812l-1.718 0.19zM410.624 655.667c-0.065 1.347-0.102 2.926-0.102 4.514 0 54.97 44.562 99.533 99.533 99.533s99.533-44.562 99.533-99.533c0-1.588-0.037-3.166-0.111-4.736l0.008 0.222c-0.119-4.799-0.561-9.394-1.308-13.886l0.079 0.574c0-2.662 0-5.12-1.229-7.578-8.335-37.442-36.943-66.529-73.458-75.431l-0.68-0.14v-125.952c0-12.668-10.27-22.938-22.938-22.938s-22.938 10.27-22.938 22.938v126.157c-37.195 9.042-65.803 38.129-74.014 74.909l-0.124 0.662c0 2.458 0 5.12-1.229 7.578-0.667 3.917-1.109 8.512-1.226 13.188l-0.002 0.124zM510.157 379.597c29.634 0 53.658 24.023 53.658 53.658v20.48c27.443-10.445 45.875-28.058 45.875-48.742 0-32.154-44.442-58.368-99.533-58.368s-98.918 27.443-98.918 60.416c0 20.48 18.432 38.298 45.875 48.742v-20.48c-0.016-0.488-0.025-1.062-0.025-1.638 0-29.634 24.023-53.658 53.658-53.658 0.009 0 0.018 0 0.026 0h-0.001zM510.157 236.237c-0.112 0-0.244 0-0.377 0-116.275 0-210.534 94.259-210.534 210.534 0 69.683 33.854 131.459 86.012 169.779l0.586 0.41c11.324-36.013 36.951-64.648 70.051-79.746l0.81-0.331v-50.381l-4.71-1.638c-44.237-14.95-70.861-44.646-70.861-79.462 0-50.79 55.91-89.088 130.253-89.088s130.253 38.298 130.253 89.088c0 34.611-26.419 64.307-70.861 79.462l-4.71 1.638v51.2c33.079 15.862 57.944 44.403 68.572 79.16l0.241 0.917c52.743-38.73 86.597-100.506 86.597-170.189 0-116.275-94.259-210.534-210.534-210.534-0.060 0-0.12 0-0.181 0h0.009z" />
+<glyph unicode="&#xe905;" glyph-name="ZDER" d="M510.771 898.56c248.837 0 450.56-201.723 450.56-450.56s-201.723-450.56-450.56-450.56c-248.837 0-450.56 201.723-450.56 450.56v0c0 248.837 201.723 450.56 450.56 450.56v0zM510.771 929.28c-265.804 0-481.28-215.476-481.28-481.28s215.476-481.28 481.28-481.28c265.804 0 481.28 215.476 481.28 481.28v0c-0.349 265.663-215.617 480.931-481.246 481.28h-0.034zM610.099 656.077c0 0.088 0 0.191 0 0.295 0 54.97-44.562 99.533-99.533 99.533s-99.533-44.562-99.533-99.533c0-46.684 32.14-85.862 75.501-96.612l0.684-0.144v-125.952c0-12.668 10.27-22.938 22.938-22.938s22.938 10.27 22.938 22.938v125.747c44.403 10.501 76.946 49.775 77.005 96.659v0.007zM614.4 732.672c8.961-12.008 15.986-26.074 20.264-41.289l0.216-0.9c89.003-46.035 148.787-137.4 148.787-242.728 0-150.434-121.95-272.384-272.384-272.384s-272.384 121.95-272.384 272.384c0 105.328 59.784 196.693 147.27 242.013l1.518 0.715c4.494 16.115 11.519 30.18 20.721 42.527l-0.241-0.338c-118.013-43.249-200.704-154.609-200.704-285.283 0-167.4 135.704-303.104 303.104-303.104s303.104 135.704 303.104 303.104c0 130.674-82.691 242.034-198.601 284.607l-2.103 0.676zM570.163 485.478l-4.71 1.638h-2.662v-31.539c28.467-10.24 47.514-28.467 47.514-49.357 0-32.154-44.442-58.368-99.533-58.368s-99.533 26.010-99.533 59.187c0 20.48 19.251 39.117 47.514 49.357v30.72h-2.662l-4.71-1.638c-44.237-14.95-70.861-44.646-70.861-79.462 0-50.79 55.91-89.088 130.253-89.088s130.253 38.298 130.253 89.088c-0.205 34.816-26.624 64.512-70.861 79.462z" />
+<glyph unicode="&#xe906;" glyph-name="ZDEP" d="M510.771 898.56c248.837 0 450.56-201.723 450.56-450.56s-201.723-450.56-450.56-450.56c-248.837 0-450.56 201.723-450.56 450.56v0c0 248.837 201.723 450.56 450.56 450.56v0zM510.771 929.28c-265.804 0-481.28-215.476-481.28-481.28s215.476-481.28 481.28-481.28c265.804 0 481.28 215.476 481.28 481.28v0c-0.349 265.663-215.617 480.931-481.246 481.28h-0.034zM616.653 731.443c-23.824 33.267-62.351 54.688-105.882 54.688s-82.057-21.421-105.615-54.297l-0.266-0.391c-116.172-44.199-197.222-154.639-197.222-284.009 0-167.4 135.704-303.104 303.104-303.104s303.104 135.704 303.104 303.104c0 129.37-81.050 239.81-195.142 283.312l-2.080 0.697zM545.587 748.851v0c5.438-2.071 10.025-4.275 14.399-6.806l-0.473 0.253 2.048-1.024c4.507-2.73 8.386-5.5 12.043-8.529l-0.164 0.132 2.048-1.638c3.771-3.26 7.185-6.674 10.338-10.319l0.106-0.126 1.024-1.434c3.219-3.804 6.26-8.019 8.965-12.46l0.251-0.443c9.009-14.585 14.347-32.266 14.347-51.194 0-46.344-32.002-85.213-75.113-95.714l-0.674-0.139v-125.952c0-12.668-10.27-22.938-22.938-22.938s-22.938 10.27-22.938 22.938v0 125.952c-43.785 10.64-75.787 49.509-75.787 95.853 0 18.928 5.338 36.609 14.591 51.619l-0.244-0.425c2.956 4.884 5.997 9.098 9.338 13.051l-0.122-0.148 1.024 1.229c3.26 3.771 6.674 7.185 10.319 10.338l0.126 0.106 2.048 1.638c3.492 2.896 7.371 5.666 11.443 8.15l0.435 0.247 2.048 1.024c13.841 8.242 30.52 13.114 48.337 13.114 12.527 0 24.492-2.409 35.457-6.788l-0.645 0.227zM510.976 175.411c-0.337-0.002-0.735-0.002-1.133-0.002-150.32 0-272.179 121.859-272.179 272.179 0 104.729 59.15 195.643 145.866 241.157l1.494 0.714c-2.847-10.119-4.483-21.74-4.483-33.742 0-52.303 31.072-97.348 75.763-117.684l0.81-0.33v-52.224l-4.506-1.638c-43.622-14.746-69.632-43.827-69.632-77.619 0-49.766 55.296-87.245 128.41-87.245s128.41 37.478 128.41 87.245c0 33.792-26.010 62.874-69.632 77.619l-4.506 1.638v52.224c45.501 20.666 76.573 65.712 76.573 118.014 0 12.003-1.636 23.623-4.698 34.651l0.215-0.908c87.994-46.294 146.97-137.094 146.97-241.67 0-150.32-121.859-272.179-272.179-272.179-0.621 0-1.242 0.002-1.863 0.006l0.095-0.001z" />
+<glyph unicode="&#xe907;" glyph-name="transporteur" d="M512 741.069c-81.92 0-147.661-73.318-147.661-163.84 0-93.389 69.018-175.104 147.661-175.104s147.661 81.92 147.661 175.104c0 90.522-65.741 163.84-147.661 163.84zM512 441.651c-56.73 0-108.339 64.717-108.339 135.782s48.538 124.109 108.339 124.109 108.339-55.706 108.339-124.109-51.61-135.782-108.339-135.782zM837.837 960h-651.674c-79.176 0-143.36-64.184-143.36-143.36v0-736.051l6.349-5.734c5.53-5.12 124.723-112.026 376.832-133.939l15.974-1.229 26.010-1.638c15.565 0 31.539-1.229 48.333-1.229s32.563 0 47.923 1.229c11.469 0 22.528 1.229 33.382 2.253h6.554c252.723 20.48 366.797 129.229 371.917 134.349l5.939 5.734v735.027c0.003 0.366 0.005 0.798 0.005 1.231 0 79.176-64.184 143.36-143.36 143.36-0.29 0-0.58-0.001-0.869-0.003h0.045zM586.547-21.197h-9.626l-19.046-1.024c-13.722 0-27.648 0-41.984 0s-28.672 0-42.394 0h-31.13c-36.211 2.821-68.876 7.322-100.909 13.59l5.472-0.892c3.223 88.741 75.939 159.457 165.171 159.457s161.948-70.716 165.163-159.163l0.008-0.293c-25.397-5.041-56.477-9.184-88.060-11.516l-2.666-0.158zM715.981-0.717c-9.114 105.498-97.002 187.68-204.083 187.68s-194.969-82.182-204.030-186.914l-0.053-0.766c-18.227 4.506-32.358 8.806-40.96 11.878 2.048 179.814 46.080 290.611 245.76 290.611s243.507-111.002 245.76-290.816c-9.83-2.253-23.757-6.758-41.574-11.469zM941.261 97.792c-41.585-32.278-89.897-58.509-142.149-76.192l-3.464-1.018c-3.277 162.406-44.646 321.331-284.672 321.331-137.011 0-276.89-38.707-284.467-319.488-55.233 19.071-103.124 44.821-145.948 76.957l1.359-0.976v716.8c0.462 57.303 46.908 103.604 104.221 103.834h651.696c57.264-0.228 103.666-46.414 104.243-103.574v-0.055z" />
+<glyph unicode="&#xe908;" glyph-name="trace" d="M220.57 153.702c7.656 11.232 12.225 25.102 12.225 40.038s-4.568 28.806-12.384 40.287l0.16-0.249c-5.259 7.728-11.728 14.197-19.207 19.296l-0.249 0.16c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-0.201 0.002-0.438 0.003-0.676 0.003-5.716 0-11.276-0.673-16.603-1.944l0.485 0.098c-3.413 6.868-10.381 11.506-18.432 11.506-11.331 0-20.517-9.186-20.517-20.517 0-3.28 0.77-6.381 2.139-9.13l-0.054 0.119c0.592-1.011 1.201-1.881 1.872-2.698l-0.028 0.036c-12.243-12.806-19.779-30.202-19.779-49.358 0-39.475 32.001-71.475 71.475-71.475 0.113 0 0.227 0 0.34 0.001h-0.017c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.635 5.218 14.033 11.617 19.092 19.005l0.159 0.247zM561.357 67.072c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-0.080 0-0.175 0.001-0.27 0.001-31.454 0-58.121-20.493-67.378-48.856l-0.142-0.501c-2.637 2.573-5.971 4.443-9.693 5.298l-0.138 0.027c-1.139 0.221-2.449 0.348-3.789 0.348-11.503 0-20.828-9.325-20.828-20.828 0-10.163 7.279-18.626 16.909-20.459l0.13-0.021h3.891c0.198-0.007 0.43-0.011 0.663-0.011 4.002 0 7.736 1.148 10.891 3.133l-0.085-0.050c4.426-34.809 33.858-61.449 69.513-61.449 0.402 0 0.803 0.003 1.204 0.010l-0.060-0.001c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c7.656 11.232 12.225 25.102 12.225 40.038s-4.568 28.806-12.384 40.287l0.16-0.249c-5.494 7.696-12.234 14.109-19.987 19.079l-0.288 0.173zM966.246 274.125c-3.801 5.452-8.124 10.165-12.995 14.244l-0.112 0.092c18.132 47.444 28.632 102.317 28.632 159.643 0 64.372-13.241 125.652-37.147 181.264l1.142-2.986c13.419 12.977 21.749 31.143 21.749 51.255 0 39.362-31.909 71.27-71.27 71.27-8.378 0-16.419-1.446-23.886-4.101l0.498 0.155c-70.085 82.874-167.895 140.378-278.969 158.168l-2.631 0.347c-2.074 9.484-5.766 17.855-10.808 25.23l0.158-0.245c-5.218 7.635-11.617 14.033-19.005 19.092l-0.247 0.159c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-34.182-0.131-62.713-24.169-69.75-56.255l-0.087-0.474c-138.493-22.099-254.554-103.131-323.456-216.080l-1.152-2.032c-3.778 0.747-8.123 1.175-12.567 1.175-9.827 0-19.165-2.091-27.595-5.852l0.431 0.172c-26.103-11.293-44.035-36.823-44.035-66.543 0-39.927 32.367-72.294 72.294-72.294s72.294 32.367 72.294 72.294c0 20.824-8.804 39.592-22.894 52.784l-0.040 0.037c63.358 102.396 166.932 174.75 288.137 195.238l2.474 0.346s0-1.434 0-2.048c11.157-25.972 36.517-43.831 66.049-43.831 0.252 0 0.503 0.001 0.754 0.004h-0.038c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c2.682 3.948 5.090 8.467 6.998 13.24l0.17 0.482c101.026-16.869 187.935-67.795 250.419-140.354l0.461-0.548c-9.791-12.103-15.719-27.684-15.719-44.649 0-39.362 31.909-71.27 71.27-71.27 0.198 0 0.396 0.001 0.594 0.002h-0.030c0.015 0 0.033 0 0.051 0 5.056 0 9.99 0.522 14.752 1.515l-0.467-0.081c19.62-46.693 31.019-100.964 31.019-157.897 0-51.76-9.422-101.32-26.644-147.058l0.95 2.875c-3.225 0.59-6.936 0.928-10.725 0.928-9.403 0-18.32-2.078-26.319-5.799l0.385 0.161c-25.94-11.145-43.784-36.456-43.827-65.94v-0.006c0-39.588 32.092-71.68 71.68-71.68s71.68 32.092 71.68 71.68v0 0c0.001 0.129 0.001 0.282 0.001 0.436 0 14.807-4.515 28.559-12.244 39.955l0.16-0.25zM637.338 500.429c-5.189 5.188-12.356 8.398-20.274 8.398-0.072 0-0.145 0-0.217-0.001h0.011c-0.187 0.005-0.408 0.007-0.629 0.007-7.786 0-14.82-3.218-19.845-8.397l-0.007-0.007-36.864-36.659 92.365-92.16 36.864 36.864c5.067 5.137 8.196 12.196 8.196 19.987 0 0.173-0.002 0.347-0.005 0.519v-0.026c0 0.024 0 0.053 0 0.082 0 7.92-3.122 15.11-8.202 20.408l0.010-0.010zM361.677 265.114v-92.365h92.365l184.525 184.73-92.365 92.16-184.525-184.525zM299.008 91.853c-3.082 1.95-6.833 3.107-10.854 3.107-11.33 0-20.515-9.185-20.515-20.515 0-7.309 3.822-13.724 9.576-17.358l0.085-0.050c3.050-1.901 6.752-3.028 10.718-3.028 7.27 0 13.656 3.788 17.29 9.499l0.049 0.083c1.994 3.104 3.178 6.892 3.178 10.958 0 7.247-3.765 13.616-9.445 17.256l-0.082 0.049zM102.4 311.194c8.784 2.437 15.124 10.362 15.124 19.767 0 2.005-0.288 3.942-0.825 5.773l0.036-0.145c-2.519 8.66-10.383 14.881-19.7 14.881-1.954 0-3.845-0.274-5.635-0.785l0.144 0.035c-9.005-2.283-15.56-10.316-15.56-19.88 0-2.038 0.298-4.007 0.852-5.865l-0.037 0.145c2.491-8.702 10.376-14.964 19.723-14.964 0.266 0 0.531 0.005 0.795 0.015l-0.038-0.001c1.888 0.167 3.628 0.529 5.287 1.071l-0.167-0.047zM83.968 391.27c10.421 1.048 18.489 9.773 18.489 20.383 0 0.539-0.021 1.072-0.062 1.601l0.004-0.070c-0.84 10.616-9.661 18.912-20.42 18.912-0.598 0-1.19-0.026-1.775-0.076l0.076 0.005c-10.962-0.452-19.677-9.448-19.677-20.48 0-11.32 9.177-20.496 20.496-20.496 0.288 0 0.575 0.006 0.86 0.018l-0.041-0.001zM81.92 472.986h2.048c10.861 0.561 19.456 9.504 19.456 20.454 0 11.311-9.169 20.48-20.48 20.48s-20.48-9.169-20.48-20.48c0-10.951 8.595-19.894 19.406-20.452l0.050-0.002zM208.077 137.933c-3.68-3.702-5.955-8.804-5.955-14.438s2.275-10.737 5.956-14.439l-0.001 0.001c3.635-3.41 8.534-5.51 13.923-5.53h0.004c6.006 0.015 11.403 2.613 15.14 6.741l0.016 0.018c3.897 3.735 6.32 8.982 6.32 14.796 0 11.311-9.169 20.48-20.48 20.48-6.426 0-12.16-2.959-15.915-7.59l-0.030-0.038zM368.64 56.832c-2.218 0.878-4.787 1.387-7.475 1.387-11.511 0-20.843-9.332-20.843-20.843 0-8.823 5.482-16.365 13.226-19.407l0.142-0.049c2.143-0.907 4.635-1.434 7.25-1.434 0.043 0 0.086 0 0.129 0h-0.007c0.043 0 0.093-0.001 0.144-0.001 8.659 0 16.063 5.374 19.059 12.969l0.048 0.139c1.042 2.374 1.648 5.141 1.648 8.050 0 8.74-5.475 16.201-13.182 19.141l-0.141 0.047z" />
+<glyph unicode="&#xe909;" glyph-name="tableau-de-bord" d="M349.594 623.923c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.373c22.622 0 40.96-18.338 40.96-40.96v0zM349.594 407.45c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.51c0 22.622 18.338 40.96 40.96 40.96v0h135.373c22.622 0 40.96-18.338 40.96-40.96v0zM349.594 190.976c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.373c22.622 0 40.96-18.338 40.96-40.96v0zM620.339 623.923c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.168c22.622 0 40.96-18.338 40.96-40.96v0zM620.339 407.45c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.51c0 22.622 18.338 40.96 40.96 40.96v0h135.168c22.622 0 40.96-18.338 40.96-40.96v0zM620.339 190.976c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.168c22.622 0 40.96-18.338 40.96-40.96v0zM890.88 623.923c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.373c22.622 0 40.96-18.338 40.96-40.96v0zM890.88 407.040c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.373c22.622 0 40.96-18.338 40.96-40.96v0zM890.88 190.566c0-22.622-18.338-40.96-40.96-40.96v0h-134.963c-22.622 0-40.96 18.338-40.96 40.96v0 81.92c0 22.622 18.338 40.96 40.96 40.96v0h135.373c22.622 0 40.96-18.338 40.96-40.96v0z" />
+<glyph unicode="&#xe90a;" glyph-name="synchro-ilico" d="M581.837 816.64l-139.674 143.36v-122.88c-0.227 0-0.496 0.001-0.765 0.001-214.905 0-389.12-174.215-389.12-389.12 0-134.343 68.080-252.785 171.622-322.707l1.379-0.878 22.733 33.997c-93.932 63.339-154.888 169.345-154.888 289.588 0 192.283 155.877 348.16 348.16 348.16 0.309 0 0.618 0 0.927-0.001h-0.048v-122.88zM277.914 537.907q0 17.818 20.48 17.818t20.48-17.818c0.024-0.344 0.038-0.745 0.038-1.15 0-4.734-1.89-9.027-4.956-12.165l0.003 0.003c-3.533-2.979-8.136-4.789-13.161-4.789-0.63 0-1.253 0.028-1.869 0.084l0.079-0.006q-21.094 0-21.094 18.022zM316.006 369.152h-36.454v133.939h36.659zM390.963 368.947h-36.454v186.778h36.659zM427.827 537.907q0 17.818 20.48 17.818t20.48-17.818c0.024-0.344 0.038-0.745 0.038-1.15 0-4.734-1.89-9.027-4.956-12.165l0.003 0.003c-3.533-2.979-8.136-4.789-13.161-4.789-0.63 0-1.253 0.028-1.869 0.084l0.079-0.006q-21.094 0-21.094 18.022zM465.92 369.152h-35.84v133.939h36.659zM558.899 366.080q-62.669 0-62.669 68.813c-0.112 1.517-0.176 3.287-0.176 5.071 0 18.008 6.492 34.5 17.264 47.262l-0.090-0.109c11.504 11.229 27.251 18.156 44.616 18.156 1.452 0 2.892-0.048 4.32-0.144l-0.194 0.010c0.164 0.001 0.357 0.002 0.551 0.002 14.696 0 28.597-3.402 40.958-9.461l-0.549 0.243-9.011-27.443q-8.602 3.482-16.179 5.734c-4.469 1.413-9.611 2.236-14.942 2.253h-0.009q-28.467 0-28.467-40.96t28.467-39.322c0.394-0.009 0.859-0.013 1.325-0.013 6.836 0 13.426 1.053 19.616 3.006l-0.461-0.126c6.87 2.249 12.839 5.237 18.262 8.962l-0.24-0.156v-31.334c-5.173-3.395-11.184-6.071-17.614-7.695l-0.409-0.087c-6.923-1.697-14.871-2.671-23.047-2.671-0.466 0-0.931 0.003-1.395 0.009l0.070-0.001zM752.64 436.326c0.082-1.289 0.129-2.795 0.129-4.311 0-17.949-6.559-34.365-17.412-46.984l0.080 0.095c-11.359-11.45-27.099-18.537-44.495-18.537-1.278 0-2.547 0.038-3.806 0.114l0.173-0.008c-0.416-0.009-0.906-0.014-1.397-0.014-11.964 0-23.2 3.118-32.939 8.586l0.339-0.175c-9.865 5.717-17.665 14.043-22.586 24.041l-0.147 0.331c-5.049 10.329-8.002 22.476-8.002 35.313 0 0.545 0.005 1.090 0.016 1.632l-0.001-0.081c-0.088 1.331-0.138 2.886-0.138 4.452 0 17.905 6.565 34.277 17.419 46.839l-0.077-0.091c11.402 11.337 27.119 18.345 44.473 18.345 1.358 0 2.706-0.043 4.043-0.127l-0.183 0.009c0.386 0.008 0.84 0.012 1.295 0.012 11.998 0 23.268-3.117 33.044-8.585l-0.343 0.176c9.848-5.656 17.644-13.913 22.586-23.841l0.147-0.326c4.927-10.221 7.806-22.224 7.806-34.9 0-0.691-0.009-1.379-0.026-2.066l0.002 0.102zM659.866 436.326c-0.044-0.833-0.069-1.808-0.069-2.789 0-9.7 2.452-18.827 6.77-26.795l-0.147 0.297c4.256-6.231 11.327-10.268 19.34-10.268 0.401 0 0.8 0.010 1.196 0.030l-0.056-0.002c0.404-0.025 0.876-0.040 1.351-0.040 7.954 0 14.962 4.048 19.077 10.197l0.052 0.083c4.075 7.663 6.469 16.756 6.469 26.408 0 1.301-0.043 2.592-0.129 3.871l0.009-0.173c0.072 1.055 0.112 2.287 0.112 3.529 0 9.662-2.469 18.748-6.811 26.66l0.145-0.288c-5.106 6.068-12.704 9.897-21.197 9.897s-16.091-3.829-21.162-9.855l-0.034-0.042c-3.28-6.858-5.197-14.907-5.197-23.403 0-2.58 0.177-5.119 0.519-7.605l-0.032 0.288zM581.837-64l-139.674 143.36 139.674 143.36v-122.88c0.017 0 0.037 0 0.058 0 192.283 0 348.16 155.877 348.16 348.16 0 120.242-60.955 226.247-153.651 288.801l-1.236 0.786 23.552 33.997c104.921-70.8 173.001-189.242 173.001-323.585 0-214.905-174.215-389.12-389.12-389.12-0.269 0-0.537 0-0.806 0.001h0.041z" />
+<glyph unicode="&#xe90b;" glyph-name="synchro-icar" d="M581.837-64l-139.674 143.36 139.674 143.36v-122.88c0.017 0 0.037 0 0.058 0 192.283 0 348.16 155.877 348.16 348.16 0 120.242-60.955 226.247-153.651 288.801l-1.236 0.786 23.552 33.997c104.921-70.8 173.001-189.242 173.001-323.585 0-214.905-174.215-389.12-389.12-389.12-0.269 0-0.537 0-0.806 0.001h0.041zM581.837 816.64l-139.674 143.36v-122.88c-0.227 0-0.496 0.001-0.765 0.001-214.905 0-389.12-174.215-389.12-389.12 0-134.343 68.080-252.785 171.622-322.707l1.379-0.878 22.733 33.997c-93.932 63.339-154.888 169.345-154.888 289.588 0 192.283 155.877 348.16 348.16 348.16 0.309 0 0.618 0 0.927-0.001h-0.048v-122.88zM299.008 537.907q0 17.818 20.48 17.818t20.48-17.818c0.024-0.344 0.038-0.745 0.038-1.15 0-4.734-1.89-9.027-4.956-12.165l0.003 0.003c-3.533-2.979-8.136-4.789-13.161-4.789-0.63 0-1.253 0.028-1.869 0.084l0.079-0.006q-21.094 0-21.094 18.022zM337.101 369.152h-36.659v133.939h36.659zM430.080 366.080q-62.669 0-62.669 68.813c-0.112 1.517-0.176 3.287-0.176 5.071 0 18.008 6.492 34.5 17.264 47.262l-0.090-0.109c11.504 11.229 27.251 18.156 44.616 18.156 1.452 0 2.892-0.048 4.32-0.144l-0.194 0.010c0.164 0.001 0.357 0.002 0.551 0.002 14.696 0 28.597-3.402 40.958-9.461l-0.549 0.243-10.035-27.443q-8.602 3.482-16.179 5.734c-4.469 1.413-9.611 2.236-14.942 2.253h-0.009q-28.467 0-28.467-40.96t28.467-39.322c0.394-0.009 0.859-0.013 1.325-0.013 6.836 0 13.426 1.053 19.616 3.006l-0.461-0.126c6.704 2.019 12.546 4.737 17.897 8.157l-0.284-0.17v-31.334c-5.172-3.399-11.184-6.076-17.615-7.696l-0.407-0.087c-5.864-1.209-12.603-1.902-19.503-1.902-1.208 0-2.41 0.021-3.608 0.063l0.174-0.005zM586.957 368.947l-6.963 17.613c-5.005-6.763-11.38-12.222-18.745-16.037l-0.301-0.142c-6.763-2.787-14.615-4.405-22.844-4.405-1.258 0-2.506 0.038-3.745 0.112l0.17-0.008c-0.73-0.046-1.584-0.073-2.443-0.073-10.874 0-20.759 4.237-28.092 11.151l0.020-0.019c-6.917 7.519-11.157 17.595-11.157 28.662 0 1.013 0.035 2.017 0.105 3.012l-0.008-0.134c-0.059 0.767-0.093 1.66-0.093 2.562 0 11.93 5.896 22.483 14.934 28.903l0.109 0.074c12.294 7.103 27.043 11.294 42.77 11.294 0.804 0 1.605-0.011 2.404-0.033l-0.118 0.003h23.347v5.939c0.102 0.725 0.16 1.562 0.16 2.413 0 10.067-8.161 18.227-18.227 18.227-0.851 0-1.688-0.058-2.508-0.171l0.095 0.011c-13.895-0.602-26.841-4.090-38.44-9.875l0.552 0.249-12.083 24.781c14.51 7.621 31.702 12.093 49.939 12.093 0.515 0 1.030-0.004 1.544-0.011l-0.078 0.001c1.186 0.079 2.572 0.123 3.968 0.123 13.871 0 26.709-4.42 37.184-11.928l-0.192 0.131c8.901-7.985 14.475-19.523 14.475-32.364 0-1.223-0.051-2.435-0.15-3.633l0.010 0.157v-89.498zM576.102 430.387h-14.131c-0.493 0.019-1.072 0.030-1.653 0.030-8.119 0-15.739-2.138-22.328-5.882l0.224 0.117c-4.755-3.292-7.83-8.719-7.83-14.864 0-0.463 0.017-0.922 0.052-1.376l-0.004 0.060q0-15.565 17.818-15.565c0.442-0.025 0.96-0.039 1.48-0.039 7.339 0 14.019 2.817 19.019 7.429l-0.019-0.018c4.697 4.674 7.604 11.144 7.604 18.292 0 0.409-0.010 0.816-0.028 1.221l0.002-0.057zM725.197 505.754c0.379 0.009 0.825 0.014 1.273 0.014 3.896 0 7.703-0.378 11.388-1.098l-0.373 0.061-2.662-34.406c-3 0.786-6.444 1.238-9.994 1.238-0.303 0-0.605-0.003-0.906-0.010l0.045 0.001c-0.675 0.042-1.464 0.066-2.258 0.066-9.537 0-18.272-3.431-25.039-9.125l0.059 0.048c-6.098-5.925-9.882-14.203-9.882-23.365 0-0.642 0.019-1.28 0.055-1.913l-0.004 0.087v-68.198h-36.659v133.939h27.648l5.325-22.528h1.843c4.093 7.467 9.767 13.6 16.605 18.11l0.189 0.117c6.412 4.363 14.327 6.966 22.85 6.966 0.175 0 0.349-0.001 0.523-0.003h-0.026z" />
+<glyph unicode="&#xe90c;" glyph-name="reseau" d="M977.51 251.597c26.584 59.488 42.066 128.918 42.066 201.963 0 103.349-30.993 199.459-84.191 279.543l1.165-1.865c8.182 11.447 13.082 25.728 13.082 41.153 0 39.362-31.909 71.27-71.27 71.27-12.124 0-23.54-3.027-33.535-8.367l0.383 0.187c-88.479 77.598-205.176 124.937-332.929 124.937-155.213 0-294.106-69.876-386.936-179.887l-0.621-0.756c-7.012 2.526-15.104 3.987-23.537 3.987-39.475 0-71.475-32.001-71.475-71.475 0-19.503 7.811-37.181 20.475-50.077l-0.010 0.011c-28.679-61.497-45.412-133.512-45.412-209.436 0-95.079 26.242-184.028 71.877-260.001l-1.275 2.288c-6.678-10.339-10.648-22.972-10.648-36.532 0-37.552 30.442-67.994 67.994-67.994 7.54 0 14.794 1.227 21.572 3.493l-0.48-0.139c91.659-91.687 218.299-148.399 358.186-148.399 160.251 0 303.119 74.426 395.924 190.597l0.783 1.014c6.094-2.102 13.12-3.368 20.426-3.481l0.054-0.001c0.141-0.001 0.308-0.002 0.475-0.002 37.891 0 68.608 30.717 68.608 68.608 0 19.37-8.027 36.864-20.936 49.34l-0.020 0.019zM940.851 270.029c-3.742 0.74-8.044 1.163-12.445 1.163-31.627 0-58.149-21.857-65.285-51.289l-0.094-0.459c-152.576 0-287.949 56.73-399.974 133.325 4.965 8.943 7.887 19.611 7.887 30.963 0 7.388-1.238 14.488-3.518 21.102l0.136-0.455 365.158 311.501c11.97-9.766 27.415-15.683 44.243-15.683 9.599 0 18.748 1.925 27.082 5.41l-0.464-0.172c46.912-71.411 74.829-158.943 74.829-252.995 0-65.983-13.74-128.756-38.515-185.615l1.165 3zM512 919.040c0.097 0 0.211 0 0.325 0 115.788 0 221.672-42.404 302.969-112.531l-0.599 0.505c-5.939-9.892-9.452-21.827-9.452-34.584 0-8.16 1.437-15.984 4.073-23.233l-0.15 0.473-364.954-311.501c-11.41 9.098-26.039 14.598-41.953 14.598-17.258 0-33.006-6.469-44.95-17.114l0.067 0.059c-75.968 67.814-143.303 142.429-202.013 223.686l-2.787 4.052c12.214 12.682 19.737 29.955 19.737 48.985 0 16.15-5.418 31.034-14.536 42.935l0.124-0.169c85.806 100.438 212.55 163.733 354.080 163.84h0.019zM86.221 642.355c4.797-1.221 10.304-1.921 15.974-1.921s11.177 0.7 16.439 2.020l-0.465-0.099c64.986-90.797 136.529-170.074 216.023-240.585l1.474-1.284c-1.426-5.076-2.245-10.906-2.245-16.926 0-12.023 3.268-23.282 8.964-32.938l-0.165 0.303-163.84-139.878c-11.916 10.631-27.72 17.127-45.041 17.127-9.626 0-18.783-2.006-27.076-5.623l0.437 0.17c-38.346 66.114-60.976 145.471-60.976 230.113 0 68.715 14.915 133.947 41.684 192.635l-1.188-2.907zM512-13.619c-0.055 0-0.12 0-0.186 0-125.876 0-240.057 50.071-323.713 131.383l0.11-0.106c8.961 11.164 14.382 25.504 14.382 41.109 0 6.14-0.839 12.083-2.409 17.722l0.11-0.464 171.622 146.432c8.912-4.75 19.49-7.539 30.72-7.539s21.808 2.79 31.079 7.713l-0.359-0.174c119.603-81.306 262.963-144.384 426.803-144.384h5.12c2.593-6.654 5.905-12.403 9.943-17.557l-0.112 0.149c-86.016-106.627-216.662-174.268-363.108-174.285h-0.003z" />
+<glyph unicode="&#xe90d;" glyph-name="rapport-de-controle" d="M536.781 960h-467.763v-1002.496h527.565c-24.786 11.033-46.126 24.762-65.024 41.222l0.308-0.262h-421.888v920.576h397.312v-241.459h241.459v-234.496c15.787-3.204 29.504-7.303 42.682-12.474l-1.722 0.595v275.866zM548.25 890.573l172.032-172.032h-172.032zM210.33 619.008h437.862v-41.984h-437.862v41.984zM563.405 408.883h-353.075v-40.96h301.67c15.016 15.482 31.885 29.029 50.287 40.322l1.118 0.638zM210.33 304.64v-40.96h242.688c4.702 15.893 10.133 29.474 16.639 42.42l-0.665-1.46zM210.33 513.946h437.862v-41.984h-437.862v41.984zM698.982 407.040c118.763 0 215.040-96.277 215.040-215.040s-96.277-215.040-215.040-215.040c-118.763 0-215.040 96.277-215.040 215.040v0c0.117 118.716 96.324 214.923 215.029 215.040h0.011zM698.982 448c-141.385 0-256-114.615-256-256s114.615-256 256-256c141.385 0 256 114.615 256 256v0c0 141.385-114.615 256-256 256v0zM667.853 86.733c-5.799 0.023-11.026 2.452-14.738 6.341l-0.008 0.008-85.606 88.678c-3.557 3.681-5.749 8.701-5.749 14.234 0 11.319 9.176 20.495 20.495 20.495 5.787 0 11.013-2.398 14.74-6.255l0.006-0.006 70.042-72.499 119.603 136.806c3.784 4.313 9.307 7.021 15.462 7.021 11.343 0 20.538-9.195 20.538-20.538 0-5.187-1.923-9.925-5.095-13.54l0.020 0.023-134.144-153.6c-3.678-4.174-8.991-6.831-14.928-6.963h-0.023z" />
+<glyph unicode="&#xe90e;" glyph-name="OAT" d="M1018.061 298.701l-125.952 125.952c-4.509 4.641-10.809 7.52-17.781 7.52-0.951 0-1.889-0.054-2.812-0.158l0.113 0.010c-14.131-2.048-20.48-14.336-28.467-28.672-5.72-11.506-12.549-21.411-20.572-30.208l0.092 0.102c-7.913-8.859-19.369-14.409-32.122-14.409-11.342 0-21.659 4.391-29.343 11.565l0.025-0.023c-6.865 7.041-11.1 16.675-11.1 27.298 0 0.627 0.015 1.251 0.044 1.871l-0.003-0.088c0.459 12.391 5.7 23.475 13.919 31.532l0.008 0.007c8.702 7.913 18.604 14.741 29.35 20.136l0.756 0.344c14.131 7.782 26.419 14.336 28.672 28.672 0.094 0.81 0.147 1.748 0.147 2.699 0 6.972-2.88 13.272-7.514 17.775l-0.006 0.006-124.928 125.542-111.821 111.821c14.183 7.172 26.383 15.775 37.153 25.883l-0.084-0.078c15.895 15.301 25.768 36.761 25.768 60.526 0 22.438-8.801 42.82-23.139 57.883l0.033-0.035c-14.404 14.341-34.269 23.206-56.205 23.206-1.121 0-2.236-0.023-3.346-0.069l0.159 0.005c-23.237-0.826-44.038-10.617-59.176-25.998l-0.011-0.011c-9.978-10.676-18.518-22.879-25.195-36.178l-0.405-0.89-111.616 111.616c-3.702 3.68-8.804 5.955-14.438 5.955s-10.737-2.275-14.439-5.956l-327.679-327.679c-3.68-3.702-5.955-8.804-5.955-14.438s2.275-10.737 5.956-14.439l655.359-655.359c3.702-3.68 8.804-5.955 14.438-5.955s10.737 2.275 14.439 5.956l327.679 327.679c3.68 3.702 5.955 8.804 5.955 14.438s-2.275 10.737-5.956 14.439l0.001-0.001zM348.16 910.438l111.206-111.206c4.509-4.641 10.809-7.52 17.781-7.52 0.951 0 1.889 0.054 2.812 0.158l-0.113-0.010c14.131 2.048 20.48 14.336 28.262 28.467 5.72 11.429 12.548 21.266 20.565 29.994l-0.085-0.093c8.064 8.227 19.148 13.467 31.455 13.924l0.084 0.002c0.556 0.028 1.208 0.045 1.863 0.045 10.599 0 20.208-4.237 27.225-11.11l-0.007 0.007c7.207-7.672 11.635-18.028 11.635-29.418 0-12.7-5.505-24.114-14.258-31.987l-0.039-0.035c-8.697-7.926-18.601-14.754-29.353-20.139l-0.752-0.341c-14.131-7.578-26.419-14.131-28.467-28.467-0.094-0.81-0.147-1.748-0.147-2.699 0-6.972 2.88-13.272 7.514-17.775l0.006-0.006 111.821-110.387-96.87-96.87c-7.241 14.336-15.911 26.669-26.095 37.57l0.085-0.092c-15.175 15.317-35.976 25.037-59.045 25.801l-0.142 0.004c-0.677 0.020-1.474 0.032-2.274 0.032-5.059 0-10.011-0.459-14.816-1.336l0.502 0.076c-2.048 0-3.891-1.229-5.939-1.638-3.827-0.81-7.052-1.728-10.186-2.835l0.561 0.173c-3.196-1.418-5.817-2.787-8.346-4.294l0.359 0.198c-2.048-1.229-4.506-2.048-6.349-3.277-2.516-1.849-4.719-3.661-6.819-5.584l0.060 0.055c-1.843-1.638-4.096-2.867-5.734-4.71v0c-14.096-14.361-22.797-34.060-22.797-55.791 0-1.122 0.023-2.239 0.069-3.351l-0.005 0.159c0.826-23.237 10.617-44.038 25.998-59.176l0.011-0.011c10.804-10.035 23.139-18.642 36.569-25.391l0.91-0.414-98.714-98.304-298.803 299.008zM675.84-14.438l-298.394 298.598 110.797 110.797c4.641 4.509 7.52 10.809 7.52 17.781 0 0.951-0.054 1.889-0.158 2.812l0.010-0.113c-2.048 14.336-14.541 20.48-28.672 28.467-11.504 5.728-21.408 12.557-30.21 20.574l0.104-0.094c-8.859 7.913-14.409 19.369-14.409 32.122 0 11.342 4.391 21.659 11.565 29.343l-0.023-0.025c7.305 6.857 17.163 11.069 28.004 11.069 0.307 0 0.613-0.003 0.918-0.010l-0.046 0.001c12.391-0.459 23.475-5.7 31.532-13.919l0.007-0.008c7.901-8.707 14.727-18.607 20.133-29.346l0.347-0.76c7.782-14.336 14.541-26.624 28.672-28.672 0.787-0.088 1.698-0.138 2.622-0.138 6.995 0 13.318 2.874 17.854 7.506l0.004 0.004 111.821 111.206 96.87-96.87c-14.259-7.241-26.525-15.91-37.357-26.087l0.083 0.078c-15.317-15.175-25.037-35.976-25.801-59.045l-0.004-0.142c-0.036-0.892-0.056-1.938-0.056-2.99 0-21.932 8.862-41.794 23.202-56.201l-0.003 0.003c14.978-14.069 35.195-22.713 57.432-22.713 23.873 0 45.419 9.963 60.708 25.958l0.030 0.032c10.045 10.74 18.65 23.009 25.395 36.377l0.41 0.896 97.894-97.894z" />
+<glyph unicode="&#xe90f;" glyph-name="OAS" d="M1024 786.944v0c0.102 0.769 0.161 1.658 0.161 2.56s-0.058 1.791-0.172 2.663l0.011-0.103v1.638c-0.543 1.416-1.163 2.631-1.892 3.768l0.049-0.082v1.434c-1.188 1.483-2.535 2.766-4.036 3.85l-0.060 0.041c-1.702 1.208-3.676 2.186-5.794 2.829l-0.145 0.038-493.978 154.419c-1.807 0.578-3.885 0.911-6.042 0.911s-4.235-0.333-6.187-0.951l0.145 0.040-491.725-153.395c-1.951-0.631-3.647-1.465-5.193-2.504l0.073 0.046c-1.565-1.182-2.914-2.531-4.059-4.044l-0.037-0.052v-1.434c-0.753-1.063-1.438-2.275-1.997-3.554l-0.051-0.132v-1.638c-1.23-1.529-2.265-3.288-3.023-5.187l-0.049-0.138v-663.552c0-0.016 0-0.034 0-0.053 0-8.965 5.761-16.585 13.783-19.36l0.144-0.043 491.52-166.912c1.9-0.991 4.11-1.71 6.446-2.036l0.108-0.012c2.979 0.046 5.789 0.72 8.318 1.896l-0.126-0.053 489.882 166.093c8.166 2.818 13.926 10.438 13.926 19.403 0 0.019 0 0.037 0 0.056v-0.003 663.347zM512 919.040l425.165-133.12-110.182-37.069c-10.612-3.423-19.141-10.752-24.059-20.252l-0.108-0.228c-9.421-19.251-1.434-40.96 7.578-66.97 6.735-15.859 11.518-34.244 13.452-53.47l0.065-0.802c0.266-2.661 0.418-5.752 0.418-8.878 0-21.818-7.401-41.908-19.829-57.895l0.159 0.213c-7.007-7.22-16.801-11.701-27.642-11.701-0.506 0-1.010 0.010-1.512 0.029l0.072-0.002c-35.021 0-37.683 46.694-37.683 61.44 1.205 23.344 6.059 45.208 14.006 65.522l-0.489-1.419c7.578 22.733 13.312 40.96 0 53.453-5.866 4.359-13.251 6.978-21.248 6.978-6.247 0-12.122-1.598-17.236-4.409l0.186 0.094-201.114-68.813-130.867 44.442c43.622 11.674 95.232 27.034 95.232 71.066 0 35.84-31.949 59.187-81.92 59.187-37.951-2.214-72.007-17.288-98.246-40.885l0.146 0.13c-9.306-7.308-19.766-14.104-30.815-19.935l-1.134-0.545c-33.587-15.77-40.96-16.179-55.501-11.264l-73.318 25.6-48.742 16.589zM40.96 758.477l53.248-18.022 67.584-23.142 33.792-11.469c30.515-10.445 50.586-3.686 86.221 12.902 14.766 7.506 27.447 15.604 39.25 24.777l-0.543-0.406c19.79 18.314 45.69 30.283 74.321 32.536l0.431 0.027c1.638 0 40.96 0 40.96-18.227 0-14.131-45.056-26.214-69.222-32.563-22.672-4.119-42.85-12.348-60.638-23.938l0.631 0.386c-4.426-3.78-7.214-9.366-7.214-15.602 0-8.982 5.782-16.614 13.828-19.375l0.144-0.043 178.79-61.44v-209.306c-19.852 15.013-44.473 24.719-71.254 26.6l-0.426 0.024c-0.391 0.005-0.853 0.008-1.315 0.008-30.197 0-57.643-11.775-77.998-30.984l0.055 0.052c-15.44-15.359-24.996-36.622-24.996-60.116 0-0.466 0.004-0.931 0.011-1.394l-0.001 0.070c0-59.392 31.744-92.774 96.051-102.4 5.251-0.664 11.326-1.042 17.49-1.042 20.21 0 39.47 4.072 57.002 11.439l-0.97-0.362 5.939 2.048c0-2.253 0-4.915 0-8.602v0-245.76l-451.174 152.986zM983.040 138.138l-450.56-152.781v245.76c0.365 2.33 0.574 5.017 0.574 7.753 0 14.99-6.266 28.516-16.323 38.103l-0.021 0.020c-6.503 3.629-14.266 5.765-22.528 5.765s-16.025-2.136-22.767-5.887l0.239 0.122c-12.684-5.532-27.462-8.751-42.992-8.751-3.901 0-7.754 0.203-11.55 0.599l0.474-0.040c-50.586 7.373-61.44 29.286-61.44 61.44-0.011 0.359-0.017 0.782-0.017 1.206 0 11.965 4.773 22.816 12.518 30.752l-0.009-0.009c12.913 11.815 30.184 19.054 49.146 19.054 0.362 0 0.724-0.003 1.085-0.008l-0.055 0.001c22.378-3.426 42.162-12.605 58.367-25.968l-0.204 0.164c15.565-10.65 28.058-19.251 41.984-11.674 8.068 3.912 13.533 12.040 13.533 21.444 0 0.309-0.006 0.617-0.018 0.923l0.001-0.044v239.411l181.043 61.44c-8.811-22.683-14.422-48.919-15.549-76.312l-0.016-0.488c0-61.44 30.925-102.4 78.643-102.4 0.442-0.009 0.964-0.014 1.487-0.014 22.29 0 42.436 9.177 56.866 23.96l0.015 0.016c19.402 22.74 31.206 52.475 31.206 84.968 0 3.974-0.177 7.906-0.522 11.79l0.036-0.502c-1.983 24.524-7.67 47.199-16.517 68.217l0.543-1.452c-4.748 10.183-7.9 22.025-8.788 34.493l-0.018 0.323 142.131 48.538z" />
+<glyph unicode="&#xe910;" glyph-name="modele-calendrier" d="M190.464 803.738h43.213v-40.96h-43.213v40.96zM93.389 628.224h40.96v-61.44h-40.96v61.44zM93.389 730.624h40.96v-61.44h-40.96v61.44zM134.349 474.214v51.61h-40.96v-61.44h40.96v9.83zM93.389 116.224h40.96v-61.44h-40.96v61.44zM93.389 218.624h40.96v-61.44h-40.96v61.44zM93.389 423.424h40.96v-61.44h-40.96v61.44zM93.389 321.024h40.96v-61.44h-40.96v61.44zM276.48-8.909h61.44v-40.96h-61.44v40.96zM174.080-8.909h61.44v-40.96h-61.44v40.96zM378.88-8.909h61.44v-40.96h-61.44v40.96zM481.28-8.909h61.44v-40.96h-61.44v40.96zM583.68-8.909h61.44v-40.96h-61.44v40.96zM686.080-8.909h61.44v-40.96h-61.44v40.96zM788.48-8.909h61.44v-40.96h-61.44v40.96zM889.651 218.624h40.96v-61.44h-40.96v61.44zM889.651 116.224h40.96v-61.44h-40.96v61.44zM889.651 423.424h40.96v-61.44h-40.96v61.44zM889.651 321.024h40.96v-61.44h-40.96v61.44zM889.651 730.624h40.96v-61.44h-40.96v61.44zM889.651 525.005v-60.621h40.96v61.44h-40.96v-0.819zM889.651 628.224h40.96v-61.44h-40.96v61.44zM481.28 494.694h61.44v-40.96h-61.44v40.96zM174.080 494.694h61.44v-40.96h-61.44v40.96zM276.48 494.694h61.44v-40.96h-61.44v40.96zM686.080 494.694h61.44v-40.96h-61.44v40.96zM788.48 494.694h61.44v-40.96h-61.44v40.96zM583.68 494.694h61.44v-40.96h-61.44v40.96zM378.88 494.694h61.44v-40.96h-61.44v40.96zM710.246 743.526h40.96v-61.44h-40.96v61.44zM710.246 845.926h40.96v-61.44h-40.96v61.44zM313.754 682.086h-40.96v61.44h40.96zM313.754 784.486h-40.96v61.44h40.96zM136.192 750.899c3.97 6.299 10.504 10.672 18.101 11.66l0.127 0.013-4.915 40.96c-21.267-2.501-39.179-14.926-49.189-32.448l-0.168-0.32zM481.28 803.738h61.44v-40.96h-61.44v40.96zM378.88 803.738h61.44v-40.96h-61.44v40.96zM583.68 803.738h61.44v-40.96h-61.44v40.96zM790.323 803.738h43.213v-40.96h-43.213v40.96zM887.808 750.899c-3.97 6.299-10.504 10.672-18.101 11.66l-0.127 0.013 4.915 40.96c21.267-2.501 39.179-14.926 49.189-32.448l0.168-0.32zM710.246 948.326h40.96v-61.44h-40.96v61.44zM272.794 948.326h40.96v-61.44h-40.96v61.44zM143.36-4.403c-4.788 3.295-8.076 8.474-8.797 14.443l-0.010 0.098v3.686h-40.96c-0.057-0.963-0.089-2.090-0.089-3.224 0-20.354 10.455-38.266 26.288-48.659l0.22-0.136zM880.64-4.403c4.788 3.295 8.076 8.474 8.797 14.443l0.010 0.098v3.686h40.96c0.057-0.963 0.089-2.090 0.089-3.224 0-20.354-10.455-38.266-26.288-48.659l-0.22-0.136z" />
+<glyph unicode="&#xe911;" glyph-name="mission" d="M344.883 737.792l-17.203-59.392 62.874-17.408c-55.891-35.521-104.315-75.352-147.391-120.344l-0.269-0.283 43.827-42.803c41.083 43.148 87.186 80.915 137.535 112.545l2.958 1.734-20.48-71.68 59.187-16.384 46.49 168.141zM592.896 6.656c0-39.588-32.092-71.68-71.68-71.68s-71.68 32.092-71.68 71.68c0 39.588 32.092 71.68 71.68 71.68s71.68-32.092 71.68-71.68zM521.216 78.336c-39.588 0-71.68-32.092-71.68-71.68s32.092-71.68 71.68-71.68c39.588 0 71.68 32.092 71.68 71.68v0c0 39.588-32.092 71.68-71.68 71.68v0zM333.619 25.702c-28.662 12.576-53.144 26.267-76.132 41.983l1.585-1.023 23.347 33.587c19.57-13.754 41.889-26.542 65.367-37.227l2.627-1.070zM73.728 341.504c-5.080 25.685-7.988 55.216-7.988 85.426 0 0.208 0 0.415 0 0.623v-0.032h40.96c0.036-27.474 2.718-54.298 7.804-80.262l-0.431 2.643zM232.858 192.819c0-39.588-32.092-71.68-71.68-71.68s-71.68 32.092-71.68 71.68c0 39.588 32.092 71.68 71.68 71.68s71.68-32.092 71.68-71.68zM161.178 263.68c-39.588 0-71.68-32.092-71.68-71.68s32.092-71.68 71.68-71.68c39.588 0 71.68 32.092 71.68 71.68v0c0 39.588-32.092 71.68-71.68 71.68v0zM952.934 287.437c18.132 47.444 28.632 102.317 28.632 159.643 0 64.372-13.241 125.652-37.147 181.264l1.142-2.986c13.419 12.977 21.749 31.143 21.749 51.255 0 39.362-31.909 71.27-71.27 71.27-8.378 0-16.419-1.446-23.886-4.101l0.498 0.155c-70.037 82.835-167.769 140.329-278.759 158.166l-2.636 0.349c-2.074 9.484-5.766 17.855-10.808 25.23l0.158-0.245c-5.259 7.728-11.728 14.197-19.207 19.296l-0.249 0.16c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-34.154-0.253-62.606-24.354-69.546-56.462l-0.086-0.472c-138.318-22.577-254.211-103.458-323.454-216.094l-1.154-2.018c-3.814 0.759-8.199 1.194-12.686 1.194-9.858 0-19.226-2.098-27.682-5.872l0.432 0.172c-25.827-11.283-43.549-36.604-43.549-66.064 0-39.701 32.184-71.885 71.885-71.885s71.885 32.184 71.885 71.885c0 20.509-8.589 39.013-22.366 52.109l-0.031 0.029c63.709 102.142 167.215 174.376 288.298 195.225l2.518 0.359s0-1.434 0-2.048c11.145-25.94 36.456-43.784 65.94-43.827h0.006c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c2.682 3.948 5.090 8.467 6.998 13.24l0.17 0.482c101.238-16.67 188.38-67.553 251.039-140.158l0.455-0.54c-9.753-12.040-15.657-27.544-15.657-44.428 0-9.991 2.068-19.5 5.799-28.121l-0.177 0.459c11.185-25.907 36.512-43.709 65.997-43.709 4.836 0 9.56 0.479 14.127 1.392l-0.457-0.076c19.767-46.851 31.254-101.32 31.254-158.471 0-51.163-9.205-100.175-26.050-145.472l0.94 2.886c-1.286 0.083-2.788 0.131-4.301 0.131s-3.015-0.048-4.505-0.141l0.204 0.010c-0.367 0.007-0.799 0.010-1.233 0.010-40.606 0-73.523-32.917-73.523-73.523s32.917-73.523 73.523-73.523c40.606 0 73.523 32.917 73.523 73.523 0 22.44-10.053 42.532-25.902 56.018l-0.104 0.086z" />
+<glyph unicode="&#xe912;" glyph-name="ligne_commerciale" d="M921.6 960h-819.2c-56.554 0-102.4-45.846-102.4-102.4v0-819.2c0-56.554 45.846-102.4 102.4-102.4v0h819.2c56.554 0 102.4 45.846 102.4 102.4v0 819.2c0 56.554-45.846 102.4-102.4 102.4v0zM565.453 278.221c47.452 1.66 92.195 11.209 133.631 27.368l-2.764-0.949v-90.931c-40.084-16.608-86.635-26.253-135.439-26.253-1.849 0-3.695 0.014-5.537 0.041l0.278-0.003q-111.616 0-170.803 67.789t-59.597 194.765c-0.049 2.078-0.077 4.526-0.077 6.981 0 48.212 10.748 93.913 29.978 134.839l-0.82-1.941c18.41 38.818 47.109 70.217 82.601 91.425l0.958 0.53c35.125 20.385 77.29 32.416 122.265 32.416 1.873 0 3.741-0.021 5.603-0.062l-0.278 0.005c54.657-0.612 106.081-13.859 151.675-36.948l-1.966 0.903-35.021-88.269c-15.061 7.462-34.135 15.484-53.693 22.488l-4.060 1.269c-16.98 6.327-36.596 10.066-57.063 10.239l-0.076 0.001c-1.246 0.050-2.709 0.079-4.178 0.079-36.983 0-69.726-18.153-89.805-46.036l-0.225-0.328c-21.292-32.696-33.954-72.707-33.954-115.675 0-4.408 0.133-8.785 0.396-13.127l-0.029 0.597q-0.614-171.213 128-171.213z" />
+<glyph unicode="&#xe913;" glyph-name="ligne_administrative" d="M921.6 960h-819.2c-56.554 0-102.4-45.846-102.4-102.4v0-819.2c0-56.554 45.846-102.4 102.4-102.4v0h819.2c56.554 0 102.4 45.846 102.4 102.4v0 819.2c0 56.554-45.846 102.4-102.4 102.4v0zM102.4-23.040c-33.932 0-61.44 27.508-61.44 61.44v0 819.2c0 33.932 27.508 61.44 61.44 61.44v0h819.2c33.932 0 61.44-27.508 61.44-61.44v0-819.2c0-33.932-27.508-61.44-61.44-61.44v0zM642.458 194.867l-37.069 121.856h-186.573l-37.069-121.856h-116.941l180.634 513.843h132.71l181.248-513.843zM579.379 407.040q-51.405 165.478-57.958 187.187t-9.421 35.021q-11.264-44.851-65.946-222.208z" />
+<glyph unicode="&#xe914;" glyph-name="LDA" d="M510.771-64c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512v0c0-282.77-229.23-512-512-512v0zM510.771 837.12c-214.905 0-389.12-174.215-389.12-389.12s174.215-389.12 389.12-389.12c214.905 0 389.12 174.215 389.12 389.12v0c0 214.905-174.215 389.12-389.12 389.12v0zM616.653 731.443c-23.824 33.267-62.351 54.688-105.882 54.688s-82.057-21.421-105.615-54.297l-0.266-0.391c-116.172-44.199-197.222-154.639-197.222-284.009 0-167.4 135.704-303.104 303.104-303.104s303.104 135.704 303.104 303.104c0 129.37-81.050 239.81-195.142 283.312l-2.080 0.697zM545.587 748.851c5.438-2.071 10.025-4.275 14.399-6.806l-0.473 0.253 2.048-1.024c4.507-2.73 8.386-5.5 12.043-8.529l-0.164 0.132 2.048-1.638c3.771-3.259 7.185-6.673 10.338-10.319l0.106-0.126 1.024-1.229c3.219-3.804 6.26-8.019 8.965-12.46l0.251-0.443c9.009-14.585 14.347-32.266 14.347-51.194 0-46.344-32.002-85.213-75.113-95.714l-0.674-0.139v-125.952c0-12.668-10.27-22.938-22.938-22.938s-22.938 10.27-22.938 22.938v0 125.747c-44.128 10.565-76.423 49.674-76.423 96.327 0 24.298 8.761 46.55 23.296 63.77l-0.121-0.147 1.024 1.229c3.26 3.771 6.674 7.185 10.319 10.338l0.126 0.106 2.048 1.638c3.492 2.896 7.371 5.666 11.443 8.15l0.435 0.247 2.048 1.024c13.841 8.242 30.52 13.114 48.337 13.114 12.527 0 24.492-2.409 35.457-6.788l-0.645 0.227zM510.976 380.211c29.634 0 53.658 24.023 53.658 53.658v0 20.48c27.443-10.445 45.875-28.058 45.875-48.742 0-32.154-44.442-58.368-99.533-58.368s-99.738 26.624-99.738 59.802c0 20.48 18.432 38.298 45.875 48.742v-20.48c-0.016-0.488-0.025-1.062-0.025-1.638 0-29.634 24.023-53.658 53.658-53.658 0.009 0 0.018 0 0.026 0h-0.001zM510.976 175.411c-0.337-0.002-0.735-0.002-1.133-0.002-150.32 0-272.179 121.859-272.179 272.179 0 104.729 59.15 195.643 145.866 241.157l1.494 0.714c-2.847-10.119-4.483-21.74-4.483-33.742 0-52.303 31.072-97.348 75.763-117.684l0.81-0.33v-50.381l-4.71-1.638c-44.237-14.95-70.861-44.646-70.861-79.462 0-50.79 55.91-89.088 130.253-89.088s130.253 38.298 130.253 89.088c0 34.611-26.419 64.307-70.861 79.462l-4.71 1.638v50.176c45.501 20.666 76.573 65.712 76.573 118.014 0 12.003-1.636 23.623-4.698 34.651l0.215-0.908c87.779-46.36 146.582-137.047 146.582-241.468 0-150.32-121.859-272.179-272.179-272.179-0.773 0-1.545 0.003-2.316 0.010l0.118-0.001z" />
+<glyph unicode="&#xe915;" glyph-name="jeux-de-donnees" d="M512-34.304l-482.304 482.304 482.304 482.304 161.587-161.178 2.253 6.554c9.971 20.297 22.001 37.758 36.19 53.204l-0.145-0.16c21.959 20.774 51.675 33.547 84.374 33.547 2.234 0 4.455-0.060 6.66-0.177l-0.308 0.013c34.426-0.938 65.025-16.562 85.886-40.806l0.13-0.154c20.245-21.611 32.679-50.754 32.679-82.802 0-32.882-13.090-62.707-34.343-84.547l0.027 0.027c-15.289-14.109-32.749-26.203-51.749-35.666l-1.295-0.584-6.144-3.277 166.502-166.298-180.019-180.224c-4.745-4.964-11.419-8.049-18.813-8.049-1.311 0-2.599 0.097-3.858 0.284l0.142-0.017c-16.179 2.458-24.371 17.613-35.635 38.502-8.399 18.002-18.531 33.507-30.524 47.356l0.214-0.252c-13.732 15.139-33.48 24.608-55.439 24.608-20.971 0-39.925-8.636-53.5-22.545l-0.015-0.015c-14.161-13.751-22.948-32.968-22.948-54.239 0-0.444 0.004-0.887 0.011-1.329l-0.001 0.067c0.098-22.48 9.235-42.807 23.962-57.549l-0.001 0.001c12.632-11.4 26.802-21.521 42.050-29.928l1.163-0.588c20.48-12.698 36.659-21.914 38.707-38.298 0.124-0.963 0.195-2.077 0.195-3.208 0-7.514-3.137-14.295-8.173-19.106l-0.010-0.010zM87.45 448l424.55-424.55 139.878 137.83-11.878 7.373c-19.452 10.737-36.246 22.897-51.385 36.827l0.185-0.168c-22.147 22.222-35.84 52.881-35.84 86.738 0 0.034 0 0.068 0 0.102v-0.005c0.136 32.656 13.589 62.144 35.206 83.335l0.019 0.019c21.003 21.332 50.194 34.548 82.473 34.548 33.277 0 63.273-14.047 84.382-36.535l0.058-0.062c14.704-16.045 27.284-34.386 37.079-54.342l0.605-1.364 4.915-9.011 138.854 139.264-149.094 148.685c-5.080 4.792-8.242 11.569-8.242 19.084 0 1.287 0.093 2.552 0.272 3.79l-0.017-0.141c2.253 15.77 16.998 23.757 35.43 33.792 16.592 8.179 30.876 17.948 43.58 29.431l-0.163-0.145c14.023 14.438 22.669 34.164 22.669 55.91s-8.646 41.473-22.688 55.93l0.019-0.019c-13.846 15.876-33.963 25.979-56.449 26.418l-0.076 0.001c-1.677 0.122-3.632 0.192-5.605 0.192-20.919 0-40.006-7.841-54.483-20.743l0.081 0.071c-11.525-12.98-21.384-27.818-29.008-43.921l-0.483-1.135c-10.035-18.637-17.818-33.382-33.587-35.635-1.038-0.144-2.237-0.227-3.455-0.227-7.919 0-15.024 3.484-19.867 9.003l-0.026 0.030-143.36 144.179z" />
+<glyph unicode="&#xe916;" glyph-name="jeux-de-controle" d="M597.811 448c-141.385 0-256-114.615-256-256s114.615-256 256-256c141.385 0 256 114.615 256 256v0c0 141.385-114.615 256-256 256v0zM597.811-23.040c-118.763 0-215.040 96.277-215.040 215.040s96.277 215.040 215.040 215.040c118.763 0 215.040-96.277 215.040-215.040v0c-0.117-118.716-96.324-214.923-215.029-215.040h-0.011zM1009.050 471.757l-162.611 161.997 7.987 4.301c21.47 10.68 39.939 23.523 56.27 38.644l-0.155-0.141c22.279 22.974 36.013 54.346 36.013 88.925 0 33.744-13.078 64.433-34.442 87.275l0.067-0.072c-22.091 25.622-54.317 41.98-90.381 42.801l-0.141 0.003c-2.19 0.134-4.749 0.21-7.326 0.21-34.182 0-65.23-13.42-88.162-35.28l0.051 0.049c-14.917-16.17-27.696-34.643-37.683-54.747l-0.615-1.368-4.301-8.192-157.696 157.491c-3.702 3.68-8.804 5.955-14.438 5.955s-10.737-2.275-14.439-5.956l0.001 0.001-482.099-483.328c-3.68-3.702-5.955-8.804-5.955-14.438s2.275-10.737 5.956-14.439l-0.001 0.001 345.498-344.678c-9.159 22.101-15.43 47.705-17.556 74.477l-0.057 0.889-284.467 283.853 453.632 454.246 154.214-155.034c4.904-5.199 11.84-8.436 19.532-8.436 1.273 0 2.526 0.089 3.752 0.26l-0.141-0.016c16.179 2.458 23.962 16.998 34.816 37.274 8.656 17.849 19.047 33.216 31.295 46.882l-0.166-0.188c15.793 14.879 37.134 24.023 60.611 24.023 1.156 0 2.307-0.022 3.452-0.066l-0.165 0.005c24.497-0.367 46.377-11.272 61.358-28.372l0.082-0.096c15.181-15.589 24.544-36.909 24.544-60.416s-9.363-44.827-24.562-60.435l0.019 0.019c-13.427-12.136-28.723-22.588-45.32-30.81l-1.17-0.524c-20.48-10.854-34.816-18.842-37.069-35.021-0.148-1.053-0.232-2.27-0.232-3.506 0-7.658 3.233-14.561 8.41-19.418l0.014-0.013 159.539-159.13-143.36-143.36c6.302-11.528 12.194-25.071 16.889-39.162l0.519-1.798 168.55 169.37c4.378 3.778 7.132 9.334 7.132 15.533 0 5.4-2.090 10.312-5.505 13.97l0.011-0.012zM566.682 87.142c-5.799 0.023-11.026 2.452-14.738 6.341l-0.008 0.008-85.606 88.269c-3.557 3.681-5.749 8.701-5.749 14.234 0 11.319 9.176 20.495 20.495 20.495 5.787 0 11.013-2.398 14.74-6.255l0.006-0.006 70.042-72.499 119.603 136.806c3.805 4.426 9.411 7.211 15.667 7.211 11.391 0 20.625-9.234 20.625-20.625 0-5.135-1.876-9.832-4.981-13.442l0.023 0.027-134.144-153.6c-3.678-4.174-8.991-6.831-14.928-6.963h-0.023z" />
+<glyph unicode="&#xe917;" glyph-name="itl" d="M958.054 287.642c18.122 47.443 28.617 102.315 28.617 159.638 0 64.372-13.235 125.654-37.132 181.271l1.142-2.989c13.282 13.021 21.516 31.15 21.516 51.201 0 39.588-32.092 71.68-71.68 71.68-0.148 0-0.296 0-0.444-0.001h0.023c-7.957-0.123-15.543-1.538-22.614-4.044l0.496 0.153c-70.137 82.717-167.943 140.079-278.977 157.761l-2.623 0.344c-7.254 32.506-35.853 56.442-70.042 56.442s-62.787-23.936-69.952-55.964l-0.090-0.478c-135.004-21.385-248.625-98.727-318.18-207.060l-1.103-1.836c-5.207 1.178-11.188 1.853-17.325 1.853-45.243 0-81.92-36.677-81.92-81.92 0-28.864 14.928-54.241 37.485-68.833l0.321-0.194c-6.72-29.308-10.572-62.963-10.572-97.518 0-71.069 16.291-138.333 45.343-198.26l-1.185 2.709c-14.18-14.707-22.916-34.747-22.916-56.828 0-45.243 36.677-81.92 81.92-81.92 12.397 0 24.151 2.754 34.683 7.683l-0.503-0.211c66.833-66.398 153.998-112.405 251.338-127.863l2.614-0.342c7.028-32.914 35.862-57.239 70.377-57.239 39.701 0 71.885 32.184 71.885 71.885s-32.184 71.885-71.885 71.885c-30.229 0-56.1-18.659-66.724-45.087l-0.172-0.484c-88.483 14.724-165.626 55.364-225.36 113.742l0.080-0.078c8.895 12.911 14.207 28.888 14.207 46.106 0 45.243-36.677 81.92-81.92 81.92-7.678 0-15.109-1.056-22.156-3.031l0.577 0.138c-24.691 51.022-39.122 110.966-39.122 174.281 0 30.547 3.359 60.309 9.728 88.938l-0.507-2.713h3.891c0.148-0.001 0.323-0.002 0.498-0.002 45.243 0 81.92 36.677 81.92 81.92 0 24.427-10.691 46.357-27.65 61.366l-0.087 0.075c64.055 98.243 165.816 167.32 284.28 186.855l2.44 0.332c10.705-26.821 36.459-45.428 66.56-45.428s55.855 18.607 66.39 44.946l0.17 0.482c100.98-17.46 187.671-68.923 249.771-141.945l0.494-0.596c-9.562-12.045-15.34-27.47-15.34-44.244 0-39.475 32.001-71.475 71.475-71.475 0.353 0 0.705 0.003 1.057 0.008l-0.053-0.001c0.015 0 0.033 0 0.051 0 5.056 0 9.99 0.522 14.752 1.515l-0.467-0.081c19.478-46.54 30.793-100.619 30.793-157.342 0-51.738-9.414-101.278-26.622-146.999l0.949 2.876c-1.286 0.083-2.788 0.131-4.301 0.131s-3.015-0.048-4.505-0.141l0.204 0.010c-39.588 0-71.68-32.092-71.68-71.68v0 0c-0.008-0.395-0.012-0.86-0.012-1.327 0-39.814 32.276-72.090 72.090-72.090s72.090 32.276 72.090 72.090c0 22.325-10.148 42.28-26.083 55.503l-0.119 0.096zM227.738 193.024c0-33.932-27.508-61.44-61.44-61.44s-61.44 27.508-61.44 61.44c0 33.932 27.508 61.44 61.44 61.44v0c33.932 0 61.44-27.508 61.44-61.44v0zM180.634 613.888c0-33.932-27.508-61.44-61.44-61.44s-61.44 27.508-61.44 61.44c0 33.932 27.508 61.44 61.44 61.44v0c33.932 0 61.44-27.508 61.44-61.44v0zM525.926 673.28c-124.419 0-225.28-100.861-225.28-225.28s100.861-225.28 225.28-225.28c124.419 0 225.28 100.861 225.28 225.28v0c0 124.419-100.861 225.28-225.28 225.28v0zM525.926 263.68c-101.797 0-184.32 82.523-184.32 184.32s82.523 184.32 184.32 184.32c101.797 0 184.32-82.523 184.32-184.32v0c0.003-0.365 0.004-0.797 0.004-1.229 0-101.797-82.523-184.32-184.32-184.32-0.001 0-0.003 0-0.004 0v0zM405.914 486.912h240.026v-79.258h-240.026v79.258z" />
+<glyph unicode="&#xe918;" glyph-name="itineraire" d="M966.042 274.125c-3.801 5.452-8.124 10.165-12.995 14.244l-0.112 0.092c18.122 47.443 28.617 102.315 28.617 159.638 0 64.372-13.235 125.654-37.132 181.271l1.142-2.989c13.419 12.977 21.749 31.143 21.749 51.255 0 39.362-31.909 71.27-71.27 71.27-8.378 0-16.419-1.446-23.886-4.101l0.498 0.155c-70.037 82.835-167.769 140.329-278.759 158.166l-2.636 0.349c-2.074 9.484-5.766 17.855-10.808 25.23l0.158-0.245c-5.218 7.635-11.617 14.033-19.005 19.092l-0.247 0.159c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-34.155-0.028-62.702-24.010-69.749-56.051l-0.087-0.474c-138.515-22.176-254.573-103.274-323.455-216.281l-1.153-2.035c-3.778 0.747-8.123 1.175-12.567 1.175-9.827 0-19.165-2.091-27.595-5.852l0.431 0.172c-25.899-11.189-43.695-36.512-43.695-65.991 0-24.202 11.994-45.602 30.363-58.581l0.225-0.151c-8.163-32.383-12.847-69.56-12.847-107.83 0-74.679 17.836-145.192 49.481-207.511l-1.203 2.612c-11.866-12.696-19.153-29.804-19.153-48.613 0-10.032 2.073-19.58 5.814-28.24l-0.178 0.462c11.081-25.999 36.42-43.894 65.939-43.894 10.375 0 20.235 2.211 29.132 6.187l-0.454-0.181c67.716-70.683 157.509-119.73 258.272-136.044l2.643-0.353c6.969-32.512 35.461-56.533 69.564-56.533 0.384 0 0.767 0.003 1.15 0.009l-0.058-0.001c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c7.656 11.232 12.225 25.102 12.225 40.038s-4.568 28.806-12.384 40.287l0.16-0.249c-5.259 7.728-11.728 14.197-19.207 19.296l-0.249 0.16c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-0.037 0-0.081 0-0.125 0-30.078 0-55.804-18.632-66.266-44.984l-0.169-0.482c-92.341 15.058-172.625 58.425-233.603 120.756l-0.074 0.076c7.513 11.137 11.992 24.86 11.992 39.629s-4.479 28.492-12.154 39.884l0.162-0.255c-5.259 7.728-11.728 14.197-19.207 19.296l-0.249 0.16c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-6.135-0.052-12.055-0.871-17.7-2.365l0.497 0.112c-26.921 53.265-42.688 116.111-42.688 182.64 0 34.396 4.214 67.808 12.155 99.747l-0.596-2.835h1.843c39.256 0.288 70.968 32.177 70.968 71.473 0 20.172-8.356 38.392-21.796 51.387l-0.020 0.019c63.41 102.775 167.346 175.348 288.976 195.655l2.455 0.339v-1.638c11.158-25.971 36.517-43.829 66.048-43.829 0.18 0 0.36 0.001 0.54 0.002h-0.028c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c2.682 3.948 5.090 8.467 6.998 13.24l0.17 0.482c101.026-16.869 187.935-67.795 250.419-140.354l0.461-0.548c-9.791-12.103-15.719-27.684-15.719-44.649 0-39.362 31.909-71.27 71.27-71.27 0.198 0 0.396 0.001 0.594 0.002h-0.030c0.015 0 0.033 0 0.051 0 5.056 0 9.99 0.522 14.752 1.515l-0.467-0.081c19.62-46.693 31.019-100.964 31.019-157.897 0-51.76-9.422-101.32-26.644-147.058l0.95 2.875c-1.286 0.083-2.788 0.131-4.301 0.131s-3.015-0.048-4.505-0.141l0.204 0.010c-39.588 0-71.68-32.092-71.68-71.68v0 0c0-39.588 32.092-71.68 71.68-71.68s71.68 32.092 71.68 71.68v0 0c0.003 0.253 0.005 0.551 0.005 0.85 0 15.066-4.675 29.040-12.653 40.55l0.155-0.236zM346.522 738.816l-16.384-59.187 62.874-17.408c-55.726-35.538-104.014-75.364-146.969-120.329l-0.282-0.298 43.827-43.008c40.758 42.703 86.451 80.126 136.318 111.523l2.946 1.731-20.48-71.68 59.187-16.384 46.49 168.141z" />
+<glyph unicode="&#xe919;" glyph-name="importer" d="M953.754 216.986c-12.448 125.912-114.58 224.369-241.035 230.988l-0.629 0.026c-4.301 0-8.602 0-13.107 0-141.385 0-256-114.615-256-256s114.615-256 256-256c141.385 0 256 114.615 256 256v0c0 8.397-0.41 16.794-1.229 24.986zM698.982-23.040c-118.763 0-215.040 96.277-215.040 215.040s96.277 215.040 215.040 215.040c118.763 0 215.040-96.277 215.040-215.040v0c-0.117-118.716-96.324-214.923-215.029-215.040h-0.011zM731.136 309.555c-3.723 3.8-8.908 6.157-14.643 6.157-11.318 0-20.493-9.175-20.493-20.493 0-5.582 2.232-10.644 5.853-14.339l65.533-67.171h-187.802c-11.311 0-20.48-9.169-20.48-20.48s9.169-20.48 20.48-20.48v0h187.802l-65.536-67.174c-3.617-3.692-5.849-8.754-5.849-14.336 0-11.318 9.175-20.493 20.493-20.493 5.735 0 10.92 2.356 14.64 6.153l0.003 0.003 113.254 116.326zM536.781 960h-467.763v-1002.496h527.565c-24.786 11.033-46.126 24.762-65.024 41.222l0.308-0.262h-421.888v920.576h397.312v-241.459h241.459v-234.496c15.786-3.202 29.503-7.302 42.681-12.473l-1.721 0.595v275.866zM548.25 890.573l172.032-172.032h-172.032z" />
+<glyph unicode="&#xe91a;" glyph-name="horaires-des-courses" d="M512 919.040c260.148 0 471.040-210.892 471.040-471.040s-210.892-471.040-471.040-471.040c-260.148 0-471.040 210.892-471.040 471.040v0c0 260.148 210.892 471.040 471.040 471.040v0zM512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512c282.77 0 512 229.23 512 512v0c0 282.77-229.23 512-512 512v0zM761.651 468.48h-177.971c-7.25 24.808-26.392 43.95-50.673 51.068l-0.527 0.132v266.24h-40.96v-266.24c-31.737-9.111-54.567-37.877-54.567-71.975 0-41.284 33.468-74.752 74.752-74.752 34.098 0 62.864 22.831 71.845 54.040l0.13 0.528h177.971z" />
+<glyph unicode="&#xe91b;" glyph-name="calendrier-application" d="M314.573 660.582c11.311 0 20.48 9.169 20.48 20.48v0 244.326c0 11.311-9.169 20.48-20.48 20.48s-20.48-9.169-20.48-20.48v0-244.326c0-11.311 9.169-20.48 20.48-20.48v0zM376.013 803.738h270.746v-40.96h-270.746v40.96zM707.994 660.582c11.311 0 20.48 9.169 20.48 20.48v0 244.326c0 11.311-9.169 20.48-20.48 20.48s-20.48-9.169-20.48-20.48v0-244.326c0-11.311 9.169-20.48 20.48-20.48v0zM930.611 494.694v0 249.242c-1.563 33.365-28.994 59.825-62.604 59.825-0.599 0-1.196-0.008-1.79-0.025l0.087 0.002h-96.87v-40.96h96.87c0.438 0.031 0.95 0.049 1.466 0.049 11.077 0 20.251-8.142 21.866-18.768l0.015-0.123v-249.242h-755.302v249.242c1.63 10.748 10.805 18.89 21.882 18.89 0.516 0 1.027-0.018 1.534-0.052l-0.068 0.004h95.437v40.96h-95.437c-0.507 0.015-1.104 0.023-1.703 0.023-33.611 0-61.041-26.459-62.599-59.685l-0.005-0.14v-734.003c1.563-33.365 28.994-59.825 62.604-59.825 0.599 0 1.196 0.008 1.79 0.025l-0.087-0.002h708.608c0.507-0.015 1.104-0.023 1.703-0.023 33.611 0 61.041 26.459 62.599 59.685l0.005 0.14v443.802zM889.651 438.17v-428.032c-1.63-10.748-10.805-18.89-21.882-18.89-0.516 0-1.027 0.018-1.534 0.052l0.068-0.004h-708.608c-0.438-0.031-0.95-0.049-1.466-0.049-11.077 0-20.251 8.142-21.866 18.768l-0.015 0.123v443.597h755.302z" />
+<glyph unicode="&#xe91c;" glyph-name="arret" d="M921.6 960h-819.2c-56.554 0-102.4-45.846-102.4-102.4v0-819.2c0-56.554 45.846-102.4 102.4-102.4v0h819.2c56.554 0 102.4 45.846 102.4 102.4v0 819.2c0 56.554-45.846 102.4-102.4 102.4v0zM102.4-23.040c-33.932 0-61.44 27.508-61.44 61.44v0 221.184c60.305 19.387 129.686 30.612 201.674 30.72h0.054c0.213 0 0.465 0 0.716 0 38.796 0 77.035-2.381 114.58-7.006l-4.5 0.452c6.144-40.96 64.102-72.294 134.758-72.294 0.656-0.008 1.431-0.012 2.207-0.012 27.309 0 53.369 5.345 77.192 15.046l-1.37-0.493c156.058-70.656 234.086-183.091 257.638-249.037zM488.243 259.789c17.192 0 31.13 13.937 31.13 31.13v0 58.573c51.814-7.987 86.016-34.406 86.016-58.573 0-28.877-48.128-61.44-117.146-61.44s-117.146 32.358-117.146 61.44c0 24.371 34.202 50.79 86.016 58.573v-58.573c0-17.192 13.937-31.13 31.13-31.13v0zM983.040 38.4c0-33.932-27.508-61.44-61.44-61.44v0h-28.058c-20.48 84.378-107.52 212.992-273.203 296.96v0c2.010 5.035 3.206 10.867 3.277 16.969v0.029c0 37.478-44.442 68.813-104.243 77.21v131.277c60.423 14.435 104.653 67.973 104.653 131.841 0 74.764-60.608 135.373-135.373 135.373s-135.373-60.608-135.373-135.373c0-63.868 44.23-117.406 103.731-131.655l0.922-0.186v-131.482c-25.035-3.073-47.693-10.979-67.796-22.771l0.827 0.448c-43.823 7.040-94.344 11.062-145.805 11.062-0.796 0-1.593-0.001-2.389-0.003h0.123c-0.615 0.002-1.344 0.003-2.072 0.003-71.124 0-139.943-9.871-205.161-28.318l5.3 1.281v527.974c0 33.932 27.508 61.44 61.44 61.44v0h819.2c33.932 0 61.44-27.508 61.44-61.44v0z" />
+<glyph unicode="&#xe91d;" glyph-name="Acces" d="M631.194 810.701l-36.864-35.84 117.35-121.242h-352.461v-51.405h352.461l-117.35-121.446 36.864-35.635 176.947 182.682-176.947 182.886zM685.261 293.99h-373.146l117.555 121.242-36.864 35.635-176.947-182.682 176.947-182.682 36.864 35.635-117.555 121.446h373.146v51.405zM880.64-64h-737.28c-79.176 0-143.36 64.184-143.36 143.36v0 737.28c0 79.176 64.184 143.36 143.36 143.36v0h737.28c79.176 0 143.36-64.184 143.36-143.36v0-737.28c0-79.176-64.184-143.36-143.36-143.36v0zM143.36 919.040c-56.554 0-102.4-45.846-102.4-102.4v0-737.28c0-56.554 45.846-102.4 102.4-102.4v0h737.28c56.554 0 102.4 45.846 102.4 102.4v0 737.28c0 56.554-45.846 102.4-102.4 102.4v0z" />
+<glyph unicode="&#xe91e;" glyph-name="ligne" d="M966.042 274.125c-3.801 5.452-8.124 10.165-12.995 14.244l-0.112 0.092c18.122 47.443 28.617 102.315 28.617 159.638 0 64.372-13.235 125.654-37.132 181.271l1.142-2.989c13.419 12.977 21.749 31.143 21.749 51.255 0 39.362-31.909 71.27-71.27 71.27-8.378 0-16.419-1.446-23.886-4.101l0.498 0.155c-70.037 82.835-167.769 140.329-278.759 158.166l-2.636 0.349c-2.074 9.484-5.766 17.855-10.808 25.23l0.158-0.245c-5.218 7.635-11.617 14.033-19.005 19.092l-0.247 0.159c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-34.155-0.028-62.702-24.010-69.749-56.051l-0.087-0.474c-138.515-22.176-254.573-103.274-323.455-216.281l-1.153-2.035c-3.778 0.747-8.123 1.175-12.567 1.175-9.827 0-19.165-2.091-27.595-5.852l0.431 0.172c-25.899-11.189-43.695-36.512-43.695-65.991 0-24.202 11.994-45.602 30.363-58.581l0.225-0.151c-8.163-32.383-12.847-69.56-12.847-107.83 0-74.679 17.836-145.192 49.481-207.511l-1.203 2.612c-11.866-12.696-19.153-29.804-19.153-48.613 0-10.032 2.073-19.58 5.814-28.24l-0.178 0.462c11.081-25.999 36.42-43.894 65.939-43.894 10.375 0 20.235 2.211 29.132 6.187l-0.454-0.181c67.716-70.683 157.509-119.73 258.272-136.044l2.643-0.353c6.969-32.512 35.461-56.533 69.564-56.533 0.384 0 0.767 0.003 1.15 0.009l-0.058-0.001c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c7.656 11.232 12.225 25.102 12.225 40.038s-4.568 28.806-12.384 40.287l0.16-0.249c-5.259 7.728-11.728 14.197-19.207 19.296l-0.249 0.16c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-0.037 0-0.081 0-0.125 0-30.078 0-55.804-18.632-66.266-44.984l-0.169-0.482c-92.341 15.058-172.625 58.425-233.603 120.756l-0.074 0.076c7.513 11.137 11.992 24.86 11.992 39.629s-4.479 28.492-12.154 39.884l0.162-0.255c-5.259 7.728-11.728 14.197-19.207 19.296l-0.249 0.16c-11.212 7.698-25.077 12.294-40.016 12.294-0.332 0-0.663-0.002-0.994-0.007l0.050 0.001c-6.135-0.052-12.055-0.871-17.7-2.365l0.497 0.112c-26.921 53.265-42.688 116.111-42.688 182.64 0 34.396 4.214 67.808 12.155 99.747l-0.596-2.835h1.843c39.256 0.288 70.968 32.177 70.968 71.473 0 20.172-8.356 38.392-21.796 51.387l-0.020 0.019c63.41 102.775 167.346 175.348 288.976 195.655l2.455 0.339v-1.638c11.158-25.971 36.517-43.829 66.048-43.829 0.18 0 0.36 0.001 0.54 0.002h-0.028c0.281-0.004 0.612-0.006 0.944-0.006 14.939 0 28.804 4.596 40.259 12.452l-0.243-0.157c7.728 5.259 14.197 11.728 19.296 19.207l0.16 0.249c2.682 3.948 5.090 8.467 6.998 13.24l0.17 0.482c101.026-16.869 187.935-67.795 250.419-140.354l0.461-0.548c-9.791-12.103-15.719-27.684-15.719-44.649 0-39.362 31.909-71.27 71.27-71.27 0.198 0 0.396 0.001 0.594 0.002h-0.030c0.015 0 0.033 0 0.051 0 5.056 0 9.99 0.522 14.752 1.515l-0.467-0.081c19.62-46.693 31.019-100.964 31.019-157.897 0-51.76-9.422-101.32-26.644-147.058l0.95 2.875c-1.286 0.083-2.788 0.131-4.301 0.131s-3.015-0.048-4.505-0.141l0.204 0.010c-39.588 0-71.68-32.092-71.68-71.68v0 0c0-39.588 32.092-71.68 71.68-71.68s71.68 32.092 71.68 71.68v0 0c0.003 0.253 0.005 0.551 0.005 0.85 0 15.066-4.675 29.040-12.653 40.55l0.155-0.236z" />
</font></defs></svg> \ No newline at end of file
diff --git a/app/assets/fonts/sBoiv/sboiv.ttf b/app/assets/fonts/sBoiv/sboiv.ttf
index 21c79549a..d6b4d8441 100644
--- a/app/assets/fonts/sBoiv/sboiv.ttf
+++ b/app/assets/fonts/sBoiv/sboiv.ttf
Binary files differ
diff --git a/app/assets/fonts/sBoiv/sboiv.woff b/app/assets/fonts/sBoiv/sboiv.woff
index fa2e097d7..8e10ad072 100644
--- a/app/assets/fonts/sBoiv/sboiv.woff
+++ b/app/assets/fonts/sBoiv/sboiv.woff
Binary files differ
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js b/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js
index 0ed961f44..34689070d 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js
@@ -6,6 +6,12 @@ if (!window.Promise) {
}
const actions = {
+ enterEditMode: () => ({
+ type: "ENTER_EDIT_MODE"
+ }),
+ exitEditMode: () => ({
+ type: "EXIT_EDIT_MODE"
+ }),
receiveJourneyPatterns : (json) => ({
type: "RECEIVE_JOURNEY_PATTERNS",
json
@@ -84,10 +90,7 @@ const actions = {
resetValidation: (target) => {
$(target).parent().removeClass('has-error').children('.help-block').remove()
},
- humanOID : (oid) => {
- var a = oid.split(':')
- return a[a.length - 1]
- },
+ humanOID : (oid) => oid.split(':')[2],
validateFields : (fields) => {
const test = []
@@ -138,6 +141,7 @@ const actions = {
dispatch(actions.updateTotalCount(window.currentItemsLength - json.length))
}
window.currentItemsLength = json.length
+ dispatch(actions.exitEditMode())
dispatch(actions.receiveJourneyPatterns(json))
}
}
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js
index b446e2b37..12871431a 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js
@@ -17,7 +17,7 @@ class CreateModal extends Component {
}
render() {
- if(this.props.status.isFetching == true || this.props.status.policy['journey_patterns.update'] == false) {
+ if(this.props.status.isFetching == true || this.props.status.policy['journey_patterns.create'] == false || this.props.editMode == false) {
return false
}
if(this.props.status.fetchSuccess == true) {
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js
index 286cfc454..377fd0612 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js
@@ -34,7 +34,7 @@ class JourneyPattern extends Component{
type='checkbox'
id={sp.id}
checked={sp.checked}
- disabled={(this.props.value.deletable || this.props.status.policy['journey_patterns.update'] == false) ? 'disabled' : ''}
+ disabled={(this.props.value.deletable || this.props.status.policy['journey_patterns.update'] == false || this.props.editMode == false) ? 'disabled' : ''}
>
</input>
<span className='radio-label'></span>
@@ -78,7 +78,7 @@ class JourneyPattern extends Component{
<span className='fa fa-cog'></span>
</div>
<ul className='dropdown-menu'>
- <li className={(this.props.value.deletable || this.props.status.policy['journey_patterns.update'] == false) ? 'disabled' : ''}>
+ <li className={(this.props.status.policy['journey_patterns.update'] == false || this.props.editMode == false) ? 'disabled' : ''}>
<button
type='button'
onClick={this.props.onOpenEditModal}
@@ -91,10 +91,10 @@ class JourneyPattern extends Component{
<li className={this.props.value.object_id ? '' : 'disabled'}>
{this.vehicleJourneyURL(this.props.value.object_id)}
</li>
- <li className={'delete-action' + ((this.props.status.policy['journey_patterns.update'] == false)? ' disabled' : '')}>
+ <li className={'delete-action' + ((this.props.status.policy['journey_patterns.destroy'] == false || this.props.editMode == false) ? ' disabled' : '')}>
<button
type='button'
- disabled={(this.props.status.policy['journey_patterns.update'] == false)? 'disabled' : ''}
+ disabled={(this.props.status.policy['journey_patterns.destroy'] == false || this.props.editMode == false)? 'disabled' : ''}
onClick={(e) => {
e.preventDefault()
this.props.onDeleteJourneyPattern(this.props.index)}
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js
index 23473ae52..6506b706c 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js
@@ -96,7 +96,7 @@ class JourneyPatterns extends Component{
<div className="alert alert-danger mt-sm">
<strong>Erreur : </strong>
{this.props.journeyPatterns.map((jp, index) =>
- jp.errors.map((err, i) => {
+ jp.errors && jp.errors.map((err, i) => {
return (
<ul key={i}>
<li>{err}</li>
@@ -133,6 +133,7 @@ class JourneyPatterns extends Component{
onOpenEditModal= {() => this.props.onOpenEditModal(index, journeyPattern)}
onDeleteJourneyPattern={() => this.props.onDeleteJourneyPattern(index)}
status= {this.props.status}
+ editMode= {this.props.editMode}
/>
)}
</div>
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js
index 871ba00e1..767dab088 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js
@@ -21,10 +21,10 @@ class SaveJourneyPattern extends Component{
type='button'
onClick={e => {
e.preventDefault()
- actions.submitJourneyPattern(this.props.dispatch, this.props.journeyPatterns)
+ this.props.editMode ? this.props.onSubmitJourneyPattern(this.props.dispatch, this.props.journeyPatterns) : this.props.onEnterEditMode()
}}
>
- Valider
+ {this.props.editMode ? "Valider" : "Editer"}
</button>
</form>
</div>
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/containers/AddJourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/containers/AddJourneyPattern.js
index ee13819fd..7aa27754e 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/containers/AddJourneyPattern.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/containers/AddJourneyPattern.js
@@ -6,6 +6,7 @@ const mapStateToProps = (state) => {
return {
modal: state.modal,
journeyPatterns: state.journeyPatterns,
+ editMode: state.editMode,
status: state.status
}
}
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/containers/JourneyPatternList.js b/app/assets/javascripts/es6_browserified/journey_patterns/containers/JourneyPatternList.js
index bc2aaf95b..228df3ede 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/containers/JourneyPatternList.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/containers/JourneyPatternList.js
@@ -6,6 +6,7 @@ const mapStateToProps = (state) => {
return {
journeyPatterns: state.journeyPatterns,
status: state.status,
+ editMode: state.editMode,
stopPointsList: state.stopPointsList
}
}
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/containers/SaveJourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/containers/SaveJourneyPattern.js
index 33442c5a0..434264fea 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/containers/SaveJourneyPattern.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/containers/SaveJourneyPattern.js
@@ -6,11 +6,23 @@ var SaveJourneyPatternComponent = require('../components/SaveJourneyPattern')
const mapStateToProps = (state) => {
return {
journeyPatterns: state.journeyPatterns,
+ editMode: state.editMode,
page: state.pagination.page,
status: state.status
}
}
-const SaveJourneyPattern = connect(mapStateToProps)(SaveJourneyPatternComponent)
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onEnterEditMode: () => {
+ dispatch(actions.enterEditMode())
+ },
+ onSubmitJourneyPattern: (next, state) => {
+ actions.submitJourneyPattern(dispatch, state, next)
+ }
+ }
+}
+
+const SaveJourneyPattern = connect(mapStateToProps, mapDispatchToProps)(SaveJourneyPatternComponent)
module.exports = SaveJourneyPattern
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/index.js b/app/assets/javascripts/es6_browserified/journey_patterns/index.js
index b06957e0f..ca9efd2d0 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/index.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/index.js
@@ -12,6 +12,7 @@ var App = require('./components/App')
// var promise = require('redux-promise')
var initialState = {
+ editMode: false,
status: {
policy: window.perms,
fetchSuccess: true,
@@ -35,7 +36,7 @@ var initialState = {
let store = createStore(
journeyPatternsApp,
- initialState
+ initialState,
// applyMiddleware(thunkMiddleware, promise, loggerMiddleware)
)
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/editMode.js b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/editMode.js
new file mode 100644
index 000000000..2e8af1aa8
--- /dev/null
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/editMode.js
@@ -0,0 +1,12 @@
+const editMode = (state = {}, action ) => {
+ switch (action.type) {
+ case "ENTER_EDIT_MODE":
+ return true
+ case "EXIT_EDIT_MODE":
+ return false
+ default:
+ return state
+ }
+}
+
+module.exports = editMode
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/index.js b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/index.js
index aa35adf0e..a9c28b83e 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/index.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/index.js
@@ -1,4 +1,5 @@
var combineReducers = require('redux').combineReducers
+var editMode = require('./editMode')
var status = require('./status')
var journeyPatterns = require('./journeyPatterns')
var pagination = require('./pagination')
@@ -6,6 +7,7 @@ var modal = require('./modal')
var stopPointsList = require('./stopPointsList')
const journeyPatternsApp = combineReducers({
+ editMode,
status,
journeyPatterns,
pagination,
diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js
index d7ef12d0b..07bbdc249 100644
--- a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js
+++ b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js
@@ -11,6 +11,10 @@ const status = (state = {}, action) => {
return _.assign({}, state, {fetchSuccess: true, isFetching: false})
case 'RECEIVE_ERRORS':
return _.assign({}, state, {isFetching: false})
+ case 'ENTER_EDIT_MODE':
+ return _.assign({}, state, {editMode: true})
+ case 'EXIT_EDIT_MODE':
+ return _.assign({}, state, {editMode: false})
default:
return state
}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
index 951664129..02ece1654 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
@@ -96,34 +96,42 @@ const actions = {
closePeriodForm: () => ({
type: 'CLOSE_PERIOD_FORM'
}),
+ resetModalErrors: () => ({
+ type: 'RESET_MODAL_ERRORS'
+ }),
updatePeriodForm: (val, group, selectType) => ({
type: 'UPDATE_PERIOD_FORM',
val,
group,
selectType
}),
- validatePeriodForm: (modalProps, timeTablePeriods, metas) => ({
+ validatePeriodForm: (modalProps, timeTablePeriods, metas, timetableInDates, error) => ({
type: 'VALIDATE_PERIOD_FORM',
modalProps,
timeTablePeriods,
- metas
+ metas,
+ timetableInDates,
+ error
}),
- includeDateInPeriod: (index, dayTypes) => ({
+ includeDateInPeriod: (index, dayTypes, date) => ({
type: 'INCLUDE_DATE_IN_PERIOD',
index,
- dayTypes
+ dayTypes,
+ date
}),
- excludeDateFromPeriod: (index, dayTypes) => ({
+ excludeDateFromPeriod: (index, dayTypes, date) => ({
type: 'EXCLUDE_DATE_FROM_PERIOD',
index,
- dayTypes
+ dayTypes,
+ date
}),
openConfirmModal : (callback) => ({
type : 'OPEN_CONFIRM_MODAL',
callback
}),
- showErrorModal: () => ({
- type: 'OPEN_ERROR_MODAL'
+ showErrorModal: (error) => ({
+ type: 'OPEN_ERROR_MODAL',
+ error
}),
closeModal : () => ({
type : 'CLOSE_MODAL'
@@ -161,16 +169,15 @@ const actions = {
// We compare periods & currentDate, to determine if it is included or not
let testDate = false
periods.map((p, i) => {
- if(p.deleted){
- return false
- }
+ if (p.deleted) return false
+
let begin = new Date(p.period_start)
let end = new Date(p.period_end)
if(testDate === false){
if(currentDate >= begin && currentDate <= end) {
testDate = true
- p.include_date = false
+ // p.include_date = false
}
}
})
@@ -187,11 +194,11 @@ const actions = {
})
return improvedCM
},
-
checkConfirmModal: (event, callback, stateChanged, dispatch, metas, timetable) => {
- if(stateChanged === true){
- if(timetable.time_table_periods.length == 0 && _.some(metas.day_types)){
- return actions.showErrorModal()
+ if(stateChanged){
+ const error = actions.errorModalKey(timetable.time_table_periods, metas.day_types)
+ if(error){
+ return actions.showErrorModal(error)
}else{
return actions.openConfirmModal(callback)
}
@@ -207,12 +214,29 @@ const actions = {
let error = ''
start = new Date(start)
end = new Date(end)
- _.each(periods, (period, i) => {
- if(index !== i && !period.deleted){
- if((new Date(period.period_start) <= start && new Date(period.period_end) >= start) || (new Date(period.period_start) <= end && new Date(period.period_end) >= end) || (start >= new Date(period.period_start) && end <= new Date(period.period_end)) || (start <= new Date(period.period_start) && end >= new Date(period.period_end)))
- error = 'Les périodes ne peuvent pas se chevaucher'
+
+ for (let i = 0; i < periods.length; i++) {
+ let period = periods[i]
+ if (index !== i && !period.deleted) {
+ if (new Date(period.period_start) <= end && new Date(period.period_end) >= start) {
+ error = 'Les périodes ne peuvent pas se chevaucher'
+ break
+ }
}
- })
+ }
+ return error
+ },
+ checkErrorsInDates: (start, end, in_days) => {
+ let error = ''
+ start = new Date(start)
+ end = new Date(end)
+
+ for (let day of in_days) {
+ if (start <= new Date(day.date) && end >= new Date(day.date)) {
+ error = 'Une période ne peut chevaucher une date dans un calendrier'
+ break
+ }
+ }
return error
},
fetchTimeTables: (dispatch, nextPage) => {
@@ -275,6 +299,31 @@ const actions = {
}
}
})
+ },
+ errorModalKey: (periods, dayTypes) => {
+ const withoutPeriodsWithDaysTypes = _.reject(periods, 'deleted').length == 0 && _.some(dayTypes) && "withoutPeriodsWithDaysTypes"
+ const withPeriodsWithoutDayTypes = _.reject(periods, 'deleted').length > 0 && _.every(dayTypes, dt => dt == false) && "withPeriodsWithoutDayTypes"
+
+ return (withoutPeriodsWithDaysTypes || withPeriodsWithoutDayTypes) && (withoutPeriodsWithDaysTypes ? "withoutPeriodsWithDaysTypes" : "withPeriodsWithoutDayTypes")
+
+ },
+ errorModalMessage: (errorKey) => {
+ switch (errorKey) {
+ case "withoutPeriodsWithDaysTypes":
+ return window.I18n.fr.time_tables.edit.error_modal.withoutPeriodsWithDaysTypes
+ case "withPeriodsWithoutDayTypes":
+ return window.I18n.fr.time_tables.edit.error_modal.withPeriodsWithoutDayTypes
+ default:
+ return errorKey
+
+ }
+ },
+ checkIfTTHasDate: (dates, date) => {
+ if (_.some(dates, date)) {
+ return _.reject(dates, ['date', date.date])
+ } else {
+ return dates.concat(date)
+ }
}
}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js b/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js
index 31ed256ea..4e8f7e363 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js
@@ -1,18 +1,19 @@
var React = require('react')
var Component = require('react').Component
var PropTypes = require('react').PropTypes
+var errorModalMessage = require('../actions').errorModalMessage
-const ErrorModal = ({dispatch, modal, onModalClose}) => (
+const ErrorModal = ({dispatch, modal, I18n, onModalClose}) => (
<div className={ 'modal fade ' + ((modal.type == 'error') ? 'in' : '') } id='ErrorModal'>
<div className='modal-container'>
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
- <h4 className='modal-title'>Erreur</h4>
+ <h4 className='modal-title'>{window.I18n.fr.time_tables.edit.error_modal.title}</h4>
</div>
<div className='modal-body'>
<div className='mt-md mb-md'>
- <p>Un calendrier d'application ne peut pas avoir de journée(s) d'application sans période(s).</p>
+ <p>{errorModalMessage(modal.modalProps.error)}</p>
</div>
</div>
<div className='modal-footer'>
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js
index 10b558373..4879e537f 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js
@@ -20,7 +20,7 @@ class ExceptionsInDay extends Component {
data-actiontype='remove'
onClick={(e) => {
$(e.currentTarget).toggleClass('active')
- this.props.onExcludeDateFromPeriod(this.props.index, this.props.metas.day_types)
+ this.props.onExcludeDateFromPeriod(this.props.index, this.props.metas.day_types, this.props.currentDate)
}}
>
<span className='fa fa-times'></span>
@@ -36,7 +36,7 @@ class ExceptionsInDay extends Component {
data-actiontype='add'
onClick={(e) => {
$(e.currentTarget).toggleClass('active')
- this.props.onIncludeDateInPeriod(this.props.index, this.props.metas.day_types)
+ this.props.onIncludeDateInPeriod(this.props.index, this.props.metas.day_types, this.props.currentDate)
}}
>
<span className='fa fa-plus'></span>
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
index 028974fc8..3234a3fd7 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
@@ -1,5 +1,6 @@
var React = require('react')
var PropTypes = require('react').PropTypes
+var _ = require('lodash')
let monthsArray = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
const formatNumber = (val) => {
@@ -107,7 +108,7 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod
<button
type='button'
className='btn btn-outline-primary mr-sm'
- onClick={() => onValidatePeriodForm(modal.modalProps, timetable.time_table_periods, metas)}
+ onClick={() => onValidatePeriodForm(modal.modalProps, timetable.time_table_periods, metas, _.filter(timetable.time_table_dates, ['in_out', true]))}
>
Valider
</button>
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/SaveTimetable.js b/app/assets/javascripts/es6_browserified/time_tables/components/SaveTimetable.js
index e8c0aa3ba..779fd8e25 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/SaveTimetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/SaveTimetable.js
@@ -10,6 +10,8 @@ class SaveTimetable extends Component{
}
render() {
+ const error = actions.errorModalKey(this.props.timetable.time_table_periods, this.props.metas.day_types)
+
return (
<div className='row mt-md'>
<div className='col-lg-12 text-right'>
@@ -19,9 +21,9 @@ class SaveTimetable extends Component{
type='button'
onClick={e => {
e.preventDefault()
- if(this.props.timetable.time_table_periods.length == 0 && _.some(this.props.metas.day_types)){
- this.props.onShowErrorModal()
- }else{
+ if (error) {
+ this.props.onShowErrorModal(error)
+ } else {
actions.submitTimetable(this.props.getDispatch(), this.props.timetable, this.props.metas)
}
}}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
index d562655b9..3af1a11a4 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
@@ -79,6 +79,7 @@ class Timetable extends Component{
<ExceptionsInDay
index={i}
value={this.props.timetable}
+ currentDate={d.date}
metas={this.props.metas}
blueDaytype={this.props.metas.day_types[d.wday]}
onExcludeDateFromPeriod={this.props.onExcludeDateFromPeriod}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/ErrorModal.js b/app/assets/javascripts/es6_browserified/time_tables/containers/ErrorModal.js
index 16a7d45dd..e0b2c1240 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/containers/ErrorModal.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/containers/ErrorModal.js
@@ -12,6 +12,7 @@ const mapDispatchToProps = (dispatch) => {
return {
onModalClose: () =>{
dispatch(actions.closeModal())
+ dispatch(actions.resetModalErrors())
}
}
}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js
index 7f2db785a..951a09741 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js
@@ -7,7 +7,7 @@ const mapStateToProps = (state) => {
return {
modal: state.modal,
timetable: state.timetable,
- metas: state.metas
+ metas: state.metas,
}
}
@@ -27,8 +27,14 @@ const mapDispatchToProps = (dispatch) => {
val = (val < 10) ? '0' + String(val) : String(val)
dispatch(actions.updatePeriodForm(val, group, 'day'))
},
- onValidatePeriodForm: (modalProps, timeTablePeriods, metas) => {
- dispatch(actions.validatePeriodForm(modalProps, timeTablePeriods, metas))
+ onValidatePeriodForm: (modalProps, timeTablePeriods, metas, timetableInDates) => {
+ let period_start = actions.formatDate(modalProps.begin)
+ let period_end = actions.formatDate(modalProps.end)
+ let error = ''
+ if (new Date(period_end) <= new Date(period_start)) error = 'La date de départ doit être antérieure à la date de fin'
+ if (error == '') error = actions.checkErrorsInPeriods(period_start, period_end, modalProps.index, timeTablePeriods)
+ if (error == '') error = actions.checkErrorsInDates(period_start, period_end, timetableInDates)
+ dispatch(actions.validatePeriodForm(modalProps, timeTablePeriods, metas, timetableInDates, error))
}
}
}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/SaveTimetable.js b/app/assets/javascripts/es6_browserified/time_tables/containers/SaveTimetable.js
index b5539e7d8..6287da15b 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/containers/SaveTimetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/containers/SaveTimetable.js
@@ -13,8 +13,8 @@ const mapStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => {
return {
- onShowErrorModal: () => {
- dispatch(actions.showErrorModal())
+ onShowErrorModal: (errorKey) => {
+ dispatch(actions.showErrorModal(errorKey))
},
getDispatch: () => {
return dispatch
diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js b/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js
index c6b5fcc6b..639a1e2ab 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js
@@ -15,11 +15,11 @@ const mapDispatchToProps = (dispatch) => {
onDeletePeriod: (index, dayTypes) =>{
dispatch(actions.deletePeriod(index, dayTypes))
},
- onExcludeDateFromPeriod: (index, dayTypes) => {
- dispatch(actions.excludeDateFromPeriod(index, dayTypes))
+ onExcludeDateFromPeriod: (index, dayTypes, date) => {
+ dispatch(actions.excludeDateFromPeriod(index, dayTypes, date))
},
- onIncludeDateInPeriod: (index, dayTypes) => {
- dispatch(actions.includeDateInPeriod(index, dayTypes))
+ onIncludeDateInPeriod: (index, dayTypes, date) => {
+ dispatch(actions.includeDateInPeriod(index, dayTypes, date))
},
onOpenEditPeriodForm: (period, index) => {
dispatch(actions.openEditPeriodForm(period, index))
diff --git a/app/assets/javascripts/es6_browserified/time_tables/index.js b/app/assets/javascripts/es6_browserified/time_tables/index.js
index 01f8c428e..a91747991 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/index.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/index.js
@@ -22,7 +22,8 @@ var initialState = {
current_month: [],
current_periode_range: '',
periode_range: [],
- time_table_periods: []
+ time_table_periods: [],
+ time_table_dates: []
},
metas: {
comment: '',
@@ -61,7 +62,7 @@ var initialState = {
let store = createStore(
timeTablesApp,
- initialState
+ initialState,
// applyMiddleware(thunkMiddleware, promise, loggerMiddleware)
)
diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js
index 69f7b206e..c61296f1c 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js
@@ -21,9 +21,13 @@ const modal = (state = {}, action) => {
})
case 'OPEN_ERROR_MODAL':
$('#ErrorModal').modal('show')
- return _.assign({}, state, {type: 'error'})
+ newModalProps = _.assign({}, state.modalProps, {error: action.error})
+ return _.assign({}, state, {type: 'error'}, {modalProps: newModalProps})
+ case 'RESET_MODAL_ERRORS':
+ newModalProps = _.assign({}, state.modalProps, {error: ''})
+ return _.assign({}, state, {type: ''}, {modalProps: newModalProps})
case 'CLOSE_PERIOD_FORM':
- newModalProps = _.assign({}, state.modalProps, {active: false})
+ newModalProps = _.assign({}, state.modalProps, {active: false, error: ""})
return _.assign({}, state, {modalProps: newModalProps})
case 'OPEN_EDIT_PERIOD_FORM':
period_start = action.period.period_start.split('-')
@@ -50,19 +54,9 @@ const modal = (state = {}, action) => {
newModalProps[action.group][action.selectType] = action.val
return _.assign({}, state, {modalProps: newModalProps})
case 'VALIDATE_PERIOD_FORM':
- period_start = actions.formatDate(action.modalProps.begin)
- period_end = actions.formatDate(action.modalProps.end)
- newModalProps = _.assign({}, state.modalProps)
-
- if(new Date(period_end) <= new Date(period_start)){
- newModalProps.error = 'La date de départ doit être antérieure à la date de fin'
- return _.assign({}, state, {modalProps: newModalProps})
- }
-
- let newPeriods = JSON.parse(JSON.stringify(action.timeTablePeriods))
- let error = actions.checkErrorsInPeriods(period_start, period_end, action.modalProps.index, newPeriods)
- newModalProps.error = error
- newModalProps.active = (error == '') ? false : true
+ newModalProps = JSON.parse(JSON.stringify(state.modalProps))
+ newModalProps.error = action.error
+ newModalProps.active = (newModalProps.error == '') ? false : true
return _.assign({}, state, {modalProps: newModalProps})
default:
return state
diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js
index 3d96fb7b7..45fec6b5f 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js
@@ -26,6 +26,8 @@ const pagination = (state = {}, action) => {
case 'VALIDATE_PERIOD_FORM':
case 'UPDATE_COMMENT':
case 'UPDATE_COLOR':
+ case 'UPDATE_DAY_TYPES':
+ case 'UPDATE_CURRENT_MONTH_FROM_DAYTYPES':
toggleOnConfirmModal('modal')
return _.assign({}, state, {stateChanged: true})
default:
diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
index 65cd9231a..390bdffb0 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
@@ -1,6 +1,7 @@
const _ = require('lodash')
var actions = require('../actions')
let newState = {}
+let newDates = []
const timetable = (state = {}, action) => {
switch (action.type) {
@@ -9,7 +10,8 @@ const timetable = (state = {}, action) => {
current_month: action.json.current_month,
current_periode_range: action.json.current_periode_range,
periode_range: action.json.periode_range,
- time_table_periods: action.json.time_table_periods
+ time_table_periods: action.json.time_table_periods,
+ time_table_dates: action.json.time_table_dates
})
return _.assign({}, fetchedState, {current_month: actions.updateSynthesis(fetchedState, actions.strToArrayDayTypes(action.json.day_types))})
case 'RECEIVE_MONTH':
@@ -38,36 +40,46 @@ const timetable = (state = {}, action) => {
newState = _.assign({}, state, {time_table_periods : ttperiods})
return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)})
case 'INCLUDE_DATE_IN_PERIOD':
+ newDates = actions.checkIfTTHasDate(state.time_table_dates, {date: action.date, in_out: true})
let newCMi = state.current_month.map((d, i) => {
if(i == action.index){
d.include_date = !d.include_date
}
return d
})
- newState = _.assign({}, state, {current_month: newCMi})
+ newState = _.assign({}, state, {current_month: newCMi, time_table_dates: newDates})
return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)})
case 'EXCLUDE_DATE_FROM_PERIOD':
+ newDates = actions.checkIfTTHasDate(state.time_table_dates, {date: action.date, in_out: false})
let newCMe = state.current_month.map((d, i) => {
if(i == action.index){
d.excluded_date = !d.excluded_date
}
return d
})
- newState = _.assign({}, state, {current_month: newCMe})
+ newState = _.assign({}, state, {current_month: newCMe, time_table_dates: newDates})
return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)})
+ case 'UPDATE_DAY_TYPES':
+ // We get the week days of the activated day types to reject the out_dates that that are out of newDayTypes
+ let weekDays = _.reduce(action.dayTypes, (array, dt, i) => {
+ if (dt) array.push(i)
+ return array
+ }, [])
+
+ newDates = _.reject(state.time_table_dates, (d) => {
+ return d.in_out == false && !weekDays.includes(new Date(d.date).getDay())
+ })
+ return _.assign({}, state, {time_table_dates: newDates})
case 'UPDATE_CURRENT_MONTH_FROM_DAYTYPES':
return _.assign({}, state, {current_month: actions.updateSynthesis(state, action.dayTypes)})
case 'VALIDATE_PERIOD_FORM':
+ if (action.error != '') return state
+
let period_start = actions.formatDate(action.modalProps.begin)
let period_end = actions.formatDate(action.modalProps.end)
- if(new Date(period_end) <= new Date(period_start)){
- return state
- }
+
let newPeriods = JSON.parse(JSON.stringify(action.timeTablePeriods))
- let error = actions.checkErrorsInPeriods(period_start, period_end, action.modalProps.index, newPeriods)
- if(error != ''){
- return state
- }
+
if (action.modalProps.index !== false){
newPeriods[action.modalProps.index].period_start = period_start
newPeriods[action.modalProps.index].period_end = period_end
@@ -80,7 +92,6 @@ const timetable = (state = {}, action) => {
}
newState =_.assign({}, state, {time_table_periods: newPeriods})
return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.metas.day_types)})
-
default:
return state
}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js
index c30f460d8..de87c14af 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js
@@ -7,6 +7,12 @@ if (!window.Promise) {
var batchActions = require('../batch').batchActions
const actions = {
+ enterEditMode: () => ({
+ type: "ENTER_EDIT_MODE"
+ }),
+ exitEditMode: () => ({
+ type: "EXIT_EDIT_MODE"
+ }),
receiveVehicleJourneys : (json) => ({
type: "RECEIVE_VEHICLE_JOURNEYS",
json
@@ -121,6 +127,9 @@ const actions = {
objectid: selectedCompany.objectid
}
}),
+ unselect2Company: () => ({
+ type: 'UNSELECT_CP_EDIT_MODAL',
+ }),
editVehicleJourney : (data, selectedCompany) => ({
type: 'EDIT_VEHICLEJOURNEY',
data,
@@ -130,13 +139,14 @@ const actions = {
type: 'EDIT_VEHICLEJOURNEY_NOTES',
footnotes
}),
- shiftVehicleJourney : (data) => ({
+ shiftVehicleJourney : (addtionalTime) => ({
type: 'SHIFT_VEHICLEJOURNEY',
- data
+ addtionalTime
}),
- duplicateVehicleJourney : (data, departureDelta) => ({
+ duplicateVehicleJourney : (addtionalTime, duplicateNumber, departureDelta) => ({
type: 'DUPLICATE_VEHICLEJOURNEY',
- data,
+ addtionalTime,
+ duplicateNumber,
departureDelta
}),
deleteVehicleJourneys : () => ({
@@ -259,10 +269,7 @@ const actions = {
type: 'RECEIVE_TOTAL_COUNT',
total
}),
- humanOID : (oid) => {
- var a = oid.split(':')
- return a[a.length - 1]
- },
+ humanOID: (oid) => oid.split(':')[2],
fetchVehicleJourneys : (dispatch, currentPage, nextPage, queryString) => {
if(currentPage == undefined){
currentPage = 1
@@ -371,6 +378,7 @@ const actions = {
dispatch(actions.updateTotalCount(window.currentItemsLength - json.length))
}
window.currentItemsLength = json.length
+ dispatch(actions.exitEditMode())
dispatch(actions.receiveVehicleJourneys(json))
}
}
@@ -384,7 +392,7 @@ const actions = {
},
simplePad: (d) => {
if(d.toString().length == 1){
- return (d < 10) ? '0' + d.toString() : d.toString();
+ return '0' + d.toString()
}else{
return d.toString()
}
@@ -418,8 +426,8 @@ const actions = {
return vjas
},
getDuplicateDelta: (original, newDeparture) => {
- if (original.departure_time.hour != '' && original.departure_time.minute != '' && newDeparture.departure_time.hour != '' && newDeparture.departure_time.minute != ''){
- return (parseInt(newDeparture.departure_time.hour) - parseInt(original.departure_time.hour)) * 60 + (parseInt(newDeparture.departure_time.minute) - parseInt(original.departure_time.minute))
+ if (original.departure_time.hour != '' && original.departure_time.minute != '' && newDeparture.departure_time.hour != undefined && newDeparture.departure_time.minute != undefined){
+ return (newDeparture.departure_time.hour - parseInt(original.departure_time.hour)) * 60 + (newDeparture.departure_time.minute - parseInt(original.departure_time.minute))
}
return 0
},
@@ -431,69 +439,25 @@ const actions = {
vjas.delta = delta
return vjas
},
- checkSchedules: (schedule) => {
- let hours = 0
- let minutes = 0
- if (parseInt(schedule.departure_time.minute) > 59){
- hours = Math.floor(parseInt(schedule.departure_time.minute) / 60)
- minutes = parseInt(schedule.departure_time.minute) % 60
- schedule.departure_time.minute = actions.simplePad(minutes, 'minute')
- schedule.departure_time.hour = parseInt(schedule.departure_time.hour) + hours
- }
- if (parseInt(schedule.arrival_time.minute) > 59){
- hours = Math.floor(parseInt(schedule.arrival_time.minute) / 60)
- minutes = parseInt(schedule.arrival_time.minute) % 60
- schedule.arrival_time.minute = actions.simplePad(minutes, 'minute')
- schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) + hours
- }
- if (parseInt(schedule.departure_time.minute) < 0){
- hours = Math.floor(parseInt(schedule.departure_time.minute) / 60)
- minutes = (parseInt(schedule.departure_time.minute) % 60) + 60
- if(minutes == 60){
- minutes = 0
- }
- schedule.departure_time.minute = actions.simplePad(minutes, 'minute')
- schedule.departure_time.hour = parseInt(schedule.departure_time.hour) + hours
- }
- if (parseInt(schedule.arrival_time.minute) < 0){
- hours = Math.floor(parseInt(schedule.arrival_time.minute) / 60)
- minutes = (parseInt(schedule.arrival_time.minute) % 60) + 60
- if(minutes == 60){
- minutes = 0
- }
- schedule.arrival_time.minute = actions.simplePad(minutes, 'minute')
- schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) + hours
- }
+ getShiftedSchedule: ({departure_time, arrival_time}, additional_time) => {
+ // We create dummy dates objects to manipulate time more easily
+ let departureDT = new Date (Date.UTC(2017, 2, 1, parseInt(departure_time.hour), parseInt(departure_time.minute)))
+ let arrivalDT = new Date (Date.UTC(2017, 2, 1, parseInt(arrival_time.hour), parseInt(arrival_time.minute)))
- if(parseInt(schedule.departure_time.hour) > 23){
- schedule.departure_time.hour = '23'
- schedule.departure_time.minute = '59'
- }
- if(parseInt(schedule.arrival_time.hour) > 23){
- schedule.arrival_time.hour = '23'
- schedule.arrival_time.minute = '59'
- }
+ let newDepartureDT = new Date (departureDT.getTime() + additional_time * 60000)
+ let newArrivalDT = new Date (arrivalDT.getTime() + additional_time * 60000)
- if(parseInt(schedule.departure_time.hour) < 0){
- schedule.departure_time.hour = '00'
- schedule.departure_time.minute = '00'
- }
- if(parseInt(schedule.arrival_time.hour) < 0){
- schedule.arrival_time.hour = '00'
- schedule.arrival_time.minute = '00'
+ return {
+ departure_time: {
+ hour: actions.simplePad(newDepartureDT.getUTCHours()),
+ minute: actions.simplePad(newDepartureDT.getUTCMinutes())
+ },
+ arrival_time: {
+ hour: actions.simplePad(newArrivalDT.getUTCHours()),
+ minute: actions.simplePad(newArrivalDT.getUTCMinutes())
+ }
}
-
- schedule.departure_time.hour = actions.simplePad(parseInt(schedule.departure_time.hour), 'hour')
- schedule.arrival_time.hour = actions.simplePad(parseInt(schedule.arrival_time.hour), 'hour')
- // if (parseInt(schedule.departure_time.hour) > 23){
- // schedule.departure_time.hour = parseInt(schedule.departure_time.hour) - 24
- // }
- // if (parseInt(schedule.arrival_time.hour) > 23){
- // schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) - 24
- // }
- // schedule.departure_time.hour = actions.pad(schedule.departure_time.hour, 'hour')
- // schedule.arrival_time.hour = actions.pad(schedule.arrival_time.hour, 'hour')
- }
+ },
}
module.exports = actions
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js
index 05dda976d..3c45e5758 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js
@@ -9,7 +9,7 @@ class SaveVehicleJourneys extends Component{
}
render() {
- if(this.props.filters.policy['vehicle_journeys.update'] == false) {
+ if (this.props.filters.policy['vehicle_journeys.update'] == false) {
return false
}else{
return (
@@ -21,10 +21,10 @@ class SaveVehicleJourneys extends Component{
type='button'
onClick={e => {
e.preventDefault()
- actions.submitVehicleJourneys(this.props.dispatch, this.props.vehicleJourneys)
+ this.props.editMode ? this.props.onSubmitVehicleJourneys(this.props.dispatch, this.props.vehicleJourneys) : this.props.onEnterEditMode()
}}
>
- Valider
+ {this.props.editMode ? "Valider" : "Editer"}
</button>
</form>
</div>
@@ -38,7 +38,9 @@ SaveVehicleJourneys.propTypes = {
vehicleJourneys: PropTypes.array.isRequired,
page: PropTypes.number.isRequired,
status: PropTypes.object.isRequired,
- filters: PropTypes.object.isRequired
+ filters: PropTypes.object.isRequired,
+ onEnterEditMode: PropTypes.func.isRequired,
+ onSubmitVehicleJourneys: PropTypes.func.isRequired
}
module.exports = SaveVehicleJourneys
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js
index b417828db..4948e6b1a 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js
@@ -9,28 +9,34 @@ var NotesEditVehicleJourney = require('../containers/tools/NotesEditVehicleJourn
var TimetablesEditVehicleJourney = require('../containers/tools/TimetablesEditVehicleJourney')
var actions = require('../actions')
-const Tools = ({vehicleJourneys, onCancelSelection}) => {
+const Tools = ({vehicleJourneys, onCancelSelection, filters: {policy}, editMode}) => {
return (
- <div className='select_toolbox'>
- <ul>
- <AddVehicleJourney />
- <DuplicateVehicleJourney />
- <ShiftVehicleJourney />
- <EditVehicleJourney />
- <TimetablesEditVehicleJourney />
- <NotesEditVehicleJourney />
- <DeleteVehicleJourneys />
- </ul>
+ <div>
+ {
+ (policy['vehicle_journeys.create'] && policy['vehicle_journeys.update'] && policy['vehicle_journeys.destroy'] && editMode) &&
+ <div className='select_toolbox'>
+ <ul>
+ <AddVehicleJourney />
+ <DuplicateVehicleJourney />
+ <ShiftVehicleJourney />
+ <EditVehicleJourney />
+ <TimetablesEditVehicleJourney />
+ <NotesEditVehicleJourney />
+ <DeleteVehicleJourneys />
+ </ul>
- <span className='info-msg'>{actions.getSelected(vehicleJourneys).length} course(s) sélectionnée(s)</span>
- <button className='btn btn-xs btn-link pull-right' onClick={onCancelSelection}>Annuler la sélection</button>
+ <span className='info-msg'>{actions.getSelected(vehicleJourneys).length} course(s) sélectionnée(s)</span>
+ <button className='btn btn-xs btn-link pull-right' onClick={onCancelSelection}>Annuler la sélection</button>
+ </div>
+ }
</div>
)
}
Tools.propTypes = {
vehicleJourneys : PropTypes.array.isRequired,
- onCancelSelection: PropTypes.func.isRequired
+ onCancelSelection: PropTypes.func.isRequired,
+ filters: PropTypes.object.isRequired
}
module.exports = Tools
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js
index f2bd0c3cd..ca6694f61 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js
@@ -58,7 +58,7 @@ class VehicleJourney extends Component {
)}
</div>
- {(this.props.filters.policy['vehicle_journeys.update'] == true) &&
+ {(this.props.filters.policy['vehicle_journeys.update'] == true && this.props.editMode) &&
<div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}>
<input
id={this.props.index}
@@ -79,13 +79,13 @@ class VehicleJourney extends Component {
<div className={'cellwrap' + (this.cityNameChecker(vj) ? ' headlined' : '')}>
{this.props.filters.toggleArrivals &&
<div data-headline='Arrivée à'>
- <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false) ? 'disabled ' : '') + 'input-group time'}>
+ <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false) ? 'disabled ' : '') + 'input-group time'}>
<input
type='number'
min='00'
max='23'
className='form-control'
- disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false)}
+ disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', false, false)}}
value={vj.arrival_time['hour']}
/>
@@ -95,7 +95,7 @@ class VehicleJourney extends Component {
min='00'
max='59'
className='form-control'
- disabled={((this.isDisabled(this.props.value.deletable), vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false)}
+ disabled={((this.isDisabled(this.props.value.deletable), vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'minute', false, false)}}
value={vj.arrival_time['minute']}
/>
@@ -108,13 +108,13 @@ class VehicleJourney extends Component {
}
</div>
<div data-headline='Départ à'>
- <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false) ? 'disabled ' : '') + 'input-group time'}>
+ <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false) ? 'disabled ' : '') + 'input-group time'}>
<input
type='number'
min='00'
max='23'
className='form-control'
- disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false)}
+ disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', true, this.props.filters.toggleArrivals)}}
value={vj.departure_time['hour']}
/>
@@ -124,7 +124,7 @@ class VehicleJourney extends Component {
min='00'
max='59'
className='form-control'
- disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false)}
+ disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false || this.props.editMode == false)}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, "minute", true, this.props.filters.toggleArrivals)}}
value={vj.departure_time['minute']}
/>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourneys.js
index e8673a25a..8f3f91b25 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourneys.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourneys.js
@@ -97,7 +97,7 @@ class VehicleJourneys extends Component{
<div className="alert alert-danger mt-sm">
<strong>Erreur : </strong>
{this.props.vehicleJourneys.map((vj, index) =>
- vj.errors.map((err, i) => {
+ vj.errors && vj.errors.map((err, i) => {
return (
<ul key={i}>
<li>{err}</li>
@@ -131,6 +131,7 @@ class VehicleJourneys extends Component{
value={vj}
key={index}
index={index}
+ editMode={this.props.editMode}
filters={this.props.filters}
onUpdateTime={this.props.onUpdateTime}
onSelectVehicleJourney={this.props.onSelectVehicleJourney}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js
index 34463600a..9446b993a 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js
@@ -7,33 +7,64 @@ var _ = require('lodash')
class DuplicateVehicleJourney extends Component {
constructor(props) {
super(props)
+ this.state = {}
+ this.onFormChange = this.onFormChange.bind(this)
+ this.handleSubmit = this.handleSubmit.bind(this)
+ }
+
+ componentWillReceiveProps() {
+ if (actions.getSelected(this.props.vehicleJourneys).length > 0) {
+ let hour = parseInt(this.getDefaultValue('hour'))
+ let miunte = parseInt(this.getDefaultValue('minute'))
+ this.setState((state, props) => {
+ return {
+ originalDT: {
+ hour: hour,
+ minute: miunte
+ },
+ duplicate_time_hh: hour,
+ duplicate_time_mm: miunte,
+ additional_time: 0,
+ duplicate_number: 1
+ }
+ })
+ }
}
handleSubmit() {
if(actions.validateFields(this.refs) == true) {
let newDeparture = {
departure_time : {
- hour: this.refs.duplicate_time_hh.value,
- minute: this.refs.duplicate_time_mm.value
+ hour: this.state.duplicate_time_hh,
+ minute: this.state.duplicate_time_mm
}
}
let val = actions.getDuplicateDelta(_.find(actions.getSelected(this.props.vehicleJourneys)[0].vehicle_journey_at_stops, {'dummy': false}), newDeparture)
- this.refs.additional_time.value = parseInt(this.refs.additional_time.value)
- this.props.onDuplicateVehicleJourney(this.refs, val)
+ this.props.onDuplicateVehicleJourney(this.state.additional_time, this.state.duplicate_number, val)
this.props.onModalClose()
$('#DuplicateVehicleJourneyModal').modal('hide')
}
}
+ onFormChange(e) {
+ let {name, value} = e.target
+ this.setState((state, props) => {
+ return {
+ [name]: parseInt(value)
+ }
+ })
+ }
+
getDefaultValue(type) {
let vjas = _.find(actions.getSelected(this.props.vehicleJourneys)[0].vehicle_journey_at_stops, {'dummy': false})
return vjas.departure_time[type]
}
+
render() {
if(this.props.status.isFetching == true) {
return false
}
- if(this.props.status.fetchSuccess == true) {
+ if(this.props.status.fetchSuccess == true && actions.getSelected(this.props.vehicleJourneys).length > 0) {
return (
<li className='st_action'>
<button
@@ -65,22 +96,26 @@ class DuplicateVehicleJourney extends Component {
<span className={'input-group time' + (actions.getSelected(this.props.vehicleJourneys).length > 1 ? ' disabled' : '')}>
<input
type='number'
+ name='duplicate_time_hh'
ref='duplicate_time_hh'
min='00'
max='23'
className='form-control'
- defaultValue={this.getDefaultValue('hour')}
- disabled={(actions.getSelected(this.props.vehicleJourneys).length > 1 ? 'disabled' : '')}
+ value={this.state.duplicate_time_hh}
+ onChange={e => this.onFormChange(e)}
+ disabled={actions.getSelected(this.props.vehicleJourneys) && (actions.getSelected(this.props.vehicleJourneys).length > 1 ? 'disabled' : '')}
/>
<span>:</span>
<input
type='number'
+ name='duplicate_time_mm'
ref='duplicate_time_mm'
min='00'
max='59'
className='form-control'
- defaultValue={this.getDefaultValue('minute')}
- disabled={(actions.getSelected(this.props.vehicleJourneys).length > 1 ? 'disabled' : '')}
+ value={this.state.duplicate_time_mm}
+ onChange={e => this.onFormChange(e)}
+ disabled={actions.getSelected(this.props.vehicleJourneys) && (actions.getSelected(this.props.vehicleJourneys).length > 1 ? 'disabled' : '')}
/>
</span>
</span>
@@ -92,11 +127,13 @@ class DuplicateVehicleJourney extends Component {
<input
type='number'
style={{'width': 104}}
+ name='duplicate_number'
ref='duplicate_number'
min='1'
max='20'
- defaultValue='1'
+ value={this.state.duplicate_number}
className='form-control'
+ onChange={e => this.onFormChange(e)}
onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
required
/>
@@ -105,19 +142,21 @@ class DuplicateVehicleJourney extends Component {
<div className='form-group'>
<label className='control-label is-required col-sm-8'>Décalage à partir duquel on créé les courses</label>
- <div className="col-sm-4">
+ <span className="col-sm-4">
<input
type='number'
style={{'width': 104}}
+ name='additional_time'
ref='additional_time'
- min='-59'
- max='59'
- defaultValue='0'
- className='form-control'
+ min='-720'
+ max='720'
+ value={this.state.additional_time}
+ className='form-control disabled'
+ onChange={e => this.onFormChange(e)}
onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
required
- />
- </div>
+ />
+ </span>
</div>
</div>
@@ -131,9 +170,9 @@ class DuplicateVehicleJourney extends Component {
Annuler
</button>
<button
- className='btn btn-primary'
+ className={'btn btn-primary ' + (this.state.additional_time == 0 && this.state.originalDT.hour == this.state.duplicate_time_hh && this.state.originalDT.minute == this.state.duplicate_time_mm ? 'disabled' : '')}
type='button'
- onClick={this.handleSubmit.bind(this)}
+ onClick={this.handleSubmit}
>
Valider
</button>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js
index d49ea578a..2ff4999c6 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js
@@ -14,8 +14,10 @@ class EditVehicleJourney extends Component {
var company;
if(this.props.modal.modalProps.selectedCompany) {
company = this.props.modal.modalProps.selectedCompany
- } else {
+ } else if (typeof this.props.modal.modalProps.vehicleJourney.company === Object) {
company = this.props.modal.modalProps.vehicleJourney.company
+ } else {
+ company = undefined
}
this.props.onEditVehicleJourney(this.refs, company)
this.props.onModalClose()
@@ -96,6 +98,7 @@ class EditVehicleJourney extends Component {
<CompanySelect2
company = {this.props.modal.modalProps.vehicleJourney.company}
onSelect2Company = {(e) => this.props.onSelect2Company(e)}
+ onUnselect2Company = {() => this.props.onUnselect2Company()}
/>
</div>
</div>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js
index 269bb1b8c..dd0bade39 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js
@@ -6,16 +6,27 @@ var actions = require('../../actions')
class ShiftVehicleJourney extends Component {
constructor(props) {
super(props)
+ this.state = {
+ additional_time: 0
+ }
}
handleSubmit() {
if(actions.validateFields(this.refs) == true) {
- this.props.onShiftVehicleJourney(this.refs)
+ this.props.onShiftVehicleJourney(this.state.additional_time)
this.props.onModalClose()
$('#ShiftVehicleJourneyModal').modal('hide')
}
}
+ handleAdditionalTimeChange() {
+ this.setState((state, props) => {
+ return {
+ additional_time: parseInt(this.refs.additional_time.value)
+ }
+ })
+ }
+
render() {
if(this.props.status.isFetching == true) {
return false
@@ -53,14 +64,16 @@ class ShiftVehicleJourney extends Component {
<label className='control-label is-required'>Avec un décalage de</label>
<input
type='number'
+ style={{'width': 104}}
ref='additional_time'
- min='-59'
- max='59'
+ min='-720'
+ max='720'
+ value={this.state.additional_time}
className='form-control'
- defaultValue='0'
+ onChange={this.handleAdditionalTimeChange.bind(this)}
onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
required
- />
+ />
</div>
</div>
</div>
@@ -75,7 +88,7 @@ class ShiftVehicleJourney extends Component {
Annuler
</button>
<button
- className='btn btn-primary'
+ className={'btn btn-primary ' + (this.state.additional_time == 0 ? 'disabled' : '')}
type='button'
onClick={this.handleSubmit.bind(this)}
>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
index d277be003..c1ce0e92a 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
@@ -20,10 +20,11 @@ class BSelect4 extends React.Component{
data={(this.props.company) ? [this.props.company.name] : undefined}
value={(this.props.company) ? this.props.company.name : undefined}
onSelect={(e) => this.props.onSelect2Company(e) }
+ onUnselect={() => this.props.onUnselect2Company()}
multiple={false}
ref='company_id'
options={{
- allowClear: false,
+ allowClear: true,
theme: 'bootstrap',
width: '100%',
placeholder: 'Filtrer par transporteur...',
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
index 0183aac43..5157300ba 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
@@ -33,8 +33,13 @@ class BSelect4 extends React.Component{
dataType: 'json',
delay: '500',
data: function(params) {
+ let newParmas = params.term.split(" ")
return {
- q: {short_id_or_comment_cont: params.term},
+ q: {
+ objectid_cont_any: newParmas,
+ comment_cont_any: newParmas,
+ m: 'or'
+ }
};
},
processResults: function(data, params) {
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js
index 87bbe5353..c1ce90d38 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js
@@ -5,6 +5,7 @@ var SaveVehicleJourneysComponent = require('../components/SaveVehicleJourneys')
const mapStateToProps = (state) => {
return {
+ editMode: state.editMode,
vehicleJourneys: state.vehicleJourneys,
page: state.pagination.page,
status: state.status,
@@ -12,6 +13,17 @@ const mapStateToProps = (state) => {
}
}
-const SaveVehicleJourneys = connect(mapStateToProps)(SaveVehicleJourneysComponent)
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onEnterEditMode: () => {
+ dispatch(actions.enterEditMode())
+ },
+ onSubmitVehicleJourneys: (next, state) => {
+ actions.submitVehicleJourneys(dispatch, state, next)
+ }
+ }
+}
+
+const SaveVehicleJourneys = connect(mapStateToProps, mapDispatchToProps)(SaveVehicleJourneysComponent)
module.exports = SaveVehicleJourneys
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Tools.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Tools.js
index 35f492c98..a4b3056ac 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Tools.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Tools.js
@@ -4,7 +4,9 @@ var actions = require('../actions')
const mapStateToProps = (state) => {
return {
- vehicleJourneys: state.vehicleJourneys
+ vehicleJourneys: state.vehicleJourneys,
+ editMode: state.editMode,
+ filters: state.filters
}
}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/VehicleJourneysList.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/VehicleJourneysList.js
index 176a68500..f834e4457 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/VehicleJourneysList.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/VehicleJourneysList.js
@@ -4,6 +4,7 @@ var VehicleJourneys = require('../components/VehicleJourneys')
const mapStateToProps = (state) => {
return {
+ editMode: state.editMode,
vehicleJourneys: state.vehicleJourneys,
status: state.status,
filters: state.filters,
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js
index 224b52a19..70e8fde4d 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js
@@ -19,8 +19,8 @@ const mapDispatchToProps = (dispatch) => {
onOpenDuplicateModal: () =>{
dispatch(actions.openDuplicateModal())
},
- onDuplicateVehicleJourney: (data, departureDelta) =>{
- dispatch(actions.duplicateVehicleJourney(data, departureDelta))
+ onDuplicateVehicleJourney: (addtionalTime, duplicateNumber, departureDelta) =>{
+ dispatch(actions.duplicateVehicleJourney(addtionalTime, duplicateNumber, departureDelta))
}
}
}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/EditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/EditVehicleJourney.js
index 8f4d43519..ac9772b8a 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/EditVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/EditVehicleJourney.js
@@ -24,7 +24,10 @@ const mapDispatchToProps = (dispatch) => {
},
onSelect2Company: (e) => {
dispatch(actions.select2Company(e.params.data))
- }
+ },
+ onUnselect2Company: () => {
+ dispatch(actions.unselect2Company())
+ },
}
}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js
index 97aa60526..53bbcf952 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js
@@ -19,6 +19,7 @@ if (window.journeyPatternId)
selectedJP.push(window.journeyPatternId)
var initialState = {
+ editMode: false,
filters: {
selectedJourneyPatterns : selectedJP,
policy: window.perms,
@@ -89,7 +90,7 @@ if (window.jpOrigin){
let store = createStore(
enableBatching(vehicleJourneysApp),
- initialState
+ initialState,
// applyMiddleware(thunkMiddleware, promise, loggerMiddleware)
)
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/editMode.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/editMode.js
new file mode 100644
index 000000000..2e8af1aa8
--- /dev/null
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/editMode.js
@@ -0,0 +1,12 @@
+const editMode = (state = {}, action ) => {
+ switch (action.type) {
+ case "ENTER_EDIT_MODE":
+ return true
+ case "EXIT_EDIT_MODE":
+ return false
+ default:
+ return state
+ }
+}
+
+module.exports = editMode
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/index.js
index bd4d7226b..4e0839102 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/index.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/index.js
@@ -4,6 +4,7 @@ var pagination = require('./pagination')
var modal = require('./modal')
var status = require('./status')
var filters = require('./filters')
+var editMode = require('./editMode')
var stopPointsList = require('./stopPointsList')
const vehicleJourneysApp = combineReducers({
@@ -12,6 +13,7 @@ const vehicleJourneysApp = combineReducers({
modal,
status,
filters,
+ editMode,
stopPointsList
})
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js
index 229fd2058..1e5ff4294 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js
@@ -57,6 +57,9 @@ const modal = (state = {}, action) => {
case 'SELECT_CP_EDIT_MODAL':
newModalProps = _.assign({}, state.modalProps, {selectedCompany : action.selectedItem})
return _.assign({}, state, {modalProps: newModalProps})
+ case 'UNSELECT_CP_EDIT_MODAL':
+ newModalProps = _.assign({}, state.modalProps, {selectedCompany : undefined})
+ return _.assign({}, state, {modalProps: newModalProps})
case 'SELECT_TT_CALENDAR_MODAL':
newModalProps = _.assign({}, state.modalProps, {selectedTimetable : action.selectedItem})
return _.assign({}, state, {modalProps: newModalProps})
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js
index d463d4b8f..969b2ddd8 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js
@@ -51,17 +51,8 @@ const vehicleJourney= (state = {}, action, keep) => {
let shiftedArray, shiftedSchedule, shiftedVjas
shiftedArray = state.vehicle_journey_at_stops.map((vjas, i) => {
if (!vjas.dummy){
- shiftedSchedule = {
- departure_time: {
- hour: vjas.departure_time.hour,
- minute: actions.simplePad(parseInt(vjas.departure_time.minute) + parseInt(action.data.additional_time.value))
- },
- arrival_time: {
- hour: vjas.arrival_time.hour,
- minute: actions.simplePad(parseInt(vjas.arrival_time.minute) + parseInt(action.data.additional_time.value))
- }
- }
- actions.checkSchedules(shiftedSchedule)
+ shiftedSchedule = actions.getShiftedSchedule(vjas, action.addtionalTime)
+
shiftedVjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedSchedule)
vjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedVjas)
if(!keep){
@@ -181,13 +172,16 @@ const vehicleJourneys = (state = [], action) => {
let dupeVj
let dupes = []
let selectedIndex
- let val = action.data.additional_time.value
+ let val = action.addtionalTime
let departureDelta = action.departureDelta
state.map((vj, i) => {
if(vj.selected){
selectedIndex = i
- for (i = 0; i< action.data.duplicate_number.value; i++){
- action.data.additional_time.value = (parseInt(val) * (i + 1)) + departureDelta
+ for (i = 0; i< action.duplicateNumber; i++){
+ // We check if the departureDelta is != 0 to create the first VJ on the updated deparure time if it is the case
+ // let delta = departureDelta == 0 ? 1 : 0
+ // action.addtionalTime = (val * (i + delta)) + departureDelta
+ action.addtionalTime = (val * (i + 1)) + departureDelta
dupeVj = vehicleJourney(vj, action, false)
dupeVj.published_journey_name = dupeVj.published_journey_name + '-' + i
dupeVj.selected = false
diff --git a/app/assets/javascripts/filters/calendar.js b/app/assets/javascripts/filters/calendar.js
new file mode 100644
index 000000000..a4e84777c
--- /dev/null
+++ b/app/assets/javascripts/filters/calendar.js
@@ -0,0 +1,6 @@
+const DateFilter = require('../helpers/date_filters')
+
+$(document).ready(function(){
+ const calendarDF = new DateFilter("#calendar_filter_btn", "Tous les champs du filtre de date doivent être remplis", "#q_contains_date_NUMi")
+ calendarDF()
+})
diff --git a/app/assets/javascripts/filters/import.js b/app/assets/javascripts/filters/import.js
new file mode 100644
index 000000000..d0b96da10
--- /dev/null
+++ b/app/assets/javascripts/filters/import.js
@@ -0,0 +1,6 @@
+const DateFilter = require('../helpers/date_filters')
+
+$(document).ready(function(){
+ const importDF = new DateFilter("#import_filter_btn", "Tous les champs du filtre de date doivent être remplis", "#q_started_on_date_NUMi")
+ importDF()
+})
diff --git a/app/assets/javascripts/filters/time_table.js b/app/assets/javascripts/filters/time_table.js
new file mode 100644
index 000000000..9e24d03fe
--- /dev/null
+++ b/app/assets/javascripts/filters/time_table.js
@@ -0,0 +1,7 @@
+$(document).ready(function(){
+ const DateFilter = require('../helpers/date_filters')
+
+ const timetableDF = new DateFilter("#time_table_filter_btn", window.I18n.fr.time_tables.error_period_filter, "#q_start_date_gteq_NUMi", "#q_end_date_lteq_NUMi")
+
+ timetableDF()
+})
diff --git a/app/assets/javascripts/filters/workbench.js b/app/assets/javascripts/filters/workbench.js
new file mode 100644
index 000000000..af3e13c59
--- /dev/null
+++ b/app/assets/javascripts/filters/workbench.js
@@ -0,0 +1,6 @@
+const DateFilter = require('../helpers/date_filters')
+
+$(document).ready(function(){
+ const workbenchDF = new DateFilter("#referential_filter_btn", window.I18n.fr.referentials.error_period_filter, "#q_validity_period_begin_gteq_NUMi", "#q_validity_period_end_lteq_NUMi")
+ workbenchDF()
+})
diff --git a/app/assets/javascripts/helpers/date_filters.js b/app/assets/javascripts/helpers/date_filters.js
new file mode 100644
index 000000000..1f48bb28f
--- /dev/null
+++ b/app/assets/javascripts/helpers/date_filters.js
@@ -0,0 +1,38 @@
+const DateFilter = function(buttonId, message, ...inputIds) {
+ this.buttonId = buttonId
+ this.inputIds = inputIds
+ this.message = message
+
+ const getVal = (str, key) => {
+ let newStr = str.replace(/NUM/, key)
+ return $(newStr).val()
+ }
+
+ const getDates = () => {
+ return this.inputIds.reduce((arr, id) => {
+ let newIds = [1, 2, 3].map(key => getVal(id, key))
+ arr.push(...newIds)
+ return arr
+ },[])
+ }
+
+ const allInputFilled = () => {
+ return getDates().every(date => !!date)
+ }
+
+ const noInputFilled = () => {
+ return getDates().every(date => !date)
+ }
+
+ const execute = () => {
+ $(this.buttonId).on("click", (e) => {
+ if (allInputFilled() == false && noInputFilled() == false) {
+ e.preventDefault()
+ alert(this.message)
+ }
+ })
+ }
+ return execute
+}
+
+module.exports = DateFilter
diff --git a/app/assets/javascripts/time_table.coffee b/app/assets/javascripts/time_table.coffee
deleted file mode 100644
index 8789cb226..000000000
--- a/app/assets/javascripts/time_table.coffee
+++ /dev/null
@@ -1,14 +0,0 @@
- $(document).on("click", "#time_table_filter_btn", (e) ->
- dates = [1, 2, 3].reduce (arr, key) ->
- arr.push $("#q_start_date_gteq_#{key}i").val(), $("#q_end_date_lteq_#{key}i").val()
- arr
- , []
-
- validDate = dates.every (date) -> !!date
-
- noDate = dates.every (date) -> !date
-
- unless (validDate || noDate)
- e.preventDefault()
- alert(window.I18n.fr.time_tables.error_period_filter)
- )
diff --git a/app/assets/javascripts/workbench.coffee b/app/assets/javascripts/workbench.coffee
deleted file mode 100644
index 0e9fe62a3..000000000
--- a/app/assets/javascripts/workbench.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
- $(document).on("click", "#referential_filter_btn", (e) ->
- dates = [1, 2, 3].reduce (arr, key) ->
- arr.push $("#q_validity_period_begin_gteq_#{key}i").val(), $("#q_validity_period_end_lteq_#{key}i").val()
- arr
- , []
-
- validDate = dates.every (date) -> !!date
-
- noDate = dates.every (date) -> !date
-
- console.log("valid dates :", validDate)
- console.log("no dates :", noDate)
- console.log(dates)
-
- unless (validDate || noDate)
- e.preventDefault()
- alert(window.I18n.fr.referentials.error_period_filter)
- )
diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass
index e3f776640..50f8b64cb 100644
--- a/app/assets/stylesheets/application.sass
+++ b/app/assets/stylesheets/application.sass
@@ -18,3 +18,4 @@
@import 'modules/jp_collection'
@import 'modules/vj_collection'
@import 'modules/timetables'
+@import 'modules/import_messages'
diff --git a/app/assets/stylesheets/components/_page_header.sass b/app/assets/stylesheets/components/_page_header.sass
index 18985083d..566f46d6b 100644
--- a/app/assets/stylesheets/components/_page_header.sass
+++ b/app/assets/stylesheets/components/_page_header.sass
@@ -9,13 +9,15 @@
.page-icon
display: inline-block
vertical-align: middle
- width: 45px
- height: 45px
- background-color: rgba(#fff, 0.2)
- line-height: 45px
+ width: 49px
+ height: 49px
+ line-height: 49px
text-align: center
- margin-right: 20px
+ margin-right: 15px
+
+ > .sb
+ font-size: 3.5em
.page-title
display: inline-block
diff --git a/app/assets/stylesheets/components/_tables.sass b/app/assets/stylesheets/components/_tables.sass
index 3fc92d348..8fe7be374 100644
--- a/app/assets/stylesheets/components/_tables.sass
+++ b/app/assets/stylesheets/components/_tables.sass
@@ -85,6 +85,74 @@
border-top: 2px solid $darkgrey
margin-top: 15px
+ // Overhead
+ > thead > tr.overhead
+ > th
+ font-size: 1.4rem
+ text-align: center
+
+ &.overheaded-default
+ background-color: rgba($grey, 0.15)
+
+ &.full-border
+ border-left: 2px solid rgba($grey, 0.15)
+ border-right: 2px solid rgba($grey, 0.15)
+
+ &.overheaded-danger
+ background-color: $red
+ color: #fff
+
+ &.full-border
+ border-left: 2px solid $red
+ border-right: 2px solid $red
+
+ &.overheaded-warning
+ background-color: $orange
+ color: #fff
+
+ &.full-border
+ border-left: 2px solid $orange
+ border-right: 2px solid $orange
+
+ &.overheaded-success
+ background-color: $green
+ color: #fff
+
+ &.full-border
+ border-left: 2px solid $green
+ border-right: 2px solid $green
+
+ tr:not([class*='overhead']) > th, td
+ &.overheaded-default
+ border-left: 2px solid rgba($grey, 0.15)
+ border-right: 2px solid rgba($grey, 0.15)
+
+ &.overheaded-danger
+ border-left: 2px solid $red
+ border-right: 2px solid $red
+
+ &.overheaded-warning
+ border-left: 2px solid $orange
+ border-right: 2px solid $orange
+
+ &.overheaded-success
+ border-left: 2px solid $green
+ border-right: 2px solid $green
+
+ tr:last-child
+ td
+ &.overheaded-default
+ border-bottom: 2px solid rgba($grey, 0.15)
+
+ &.overheaded-danger
+ border-bottom: 2px solid $red
+
+ &.overheaded-warning
+ border-bottom: 2px solid $orange
+
+ &.overheaded-success
+ border-bottom: 2px solid $green
+
// Specific for tables displaying stop points
&.has-stoppoints
tbody
@@ -144,7 +212,6 @@
margin-top: -8px
-
// select_toolbox
.select_toolbox
padding: 10px
diff --git a/app/assets/stylesheets/main/access_links.sass b/app/assets/stylesheets/main/access_links.sass
deleted file mode 100644
index 65a81a2f8..000000000
--- a/app/assets/stylesheets/main/access_links.sass
+++ /dev/null
@@ -1,18 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.access_links.show
- .summary p label
- font-weight: bold
-
- .duration
- padding-left: 10px
-
-#workspace.access_links.edit,
-#workspace.access_links.new,
-#workspace.access_links.create,
-#workspace.access_links.update
- .time_select ol
- padding: 0 0 0 40%
- width: 100% \ No newline at end of file
diff --git a/app/assets/stylesheets/main/access_points.sass b/app/assets/stylesheets/main/access_points.sass
deleted file mode 100644
index 11e41967b..000000000
--- a/app/assets/stylesheets/main/access_points.sass
+++ /dev/null
@@ -1,78 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.access_points.index
-
-#workspace.access_points.edit,
-#workspace.access_points.new,
-#workspace.access_points.create,
-#workspace.access_points.update
- .time_select ol
- padding: 0 0 0 40%
- width: 100%
-
-#workspace.access_points.edit
- legend
- padding-bottom: 20px
-
-#workspace.access_points.show
- .geo_data
- padding-left: 15px
-
- .summary
- p label
- font-weight: bold
-
- .access_link_pairs
- table
- border: 0px
- border-collapse: separate
- border-spacing: 3px
-
- .link
- border: 2px solid black
-
- .access_point
- padding: 3px 15px 0px 3px
- height: 25px
-
- *
- vertical-align: middle
-
- span
- margin-left: 7px
-
- img
- margin: 0px 5px 0px 5px
-
- .stop_area
- 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: 10px
- padding-left: 45px
- padding-right: 3px
- padding-bottom: 3px
-
-#sidebar ul.selection li
- a
- line-height: 27px
-
- img
- height: 25px
- width: 25px
- vertical-align: middle \ No newline at end of file
diff --git a/app/assets/stylesheets/main/api_keys.sass b/app/assets/stylesheets/main/api_keys.sass
deleted file mode 100644
index 28bf171b9..000000000
--- a/app/assets/stylesheets/main/api_keys.sass
+++ /dev/null
@@ -1,7 +0,0 @@
-// Place all the styles related to the routes controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.api_keys.show
- .summary p label
- font-weight: bold \ No newline at end of file
diff --git a/app/assets/stylesheets/main/calendar.sass b/app/assets/stylesheets/main/calendar.sass
deleted file mode 100644
index f24f2b212..000000000
--- a/app/assets/stylesheets/main/calendar.sass
+++ /dev/null
@@ -1,98 +0,0 @@
-// A grey based theme, inspired by Blinksale and their ColorBurn widget. http://firewheeldesign.com
-
-// AUTHOR: Geoffrey Grosenbach http://nubyonrails.com
-
-// Colors:
-// dk: 787888
-// lt: 4f4f5b
-// lter: a8a8a8
-// white: ffffff
-
-$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: 10px 0 0 0
- text-align: center
-
- .year
- text-align: center
-
-.calendar_helper
- padding: auto
-
-.calendar
- font-size: 10px
- color: white
- text-align: center
- margin-left: 15px
- display: inline-table
-
-thead tr
- color: black
-
-th.monthName
- font-size: 12px
- font-weight: bold
- text-align: center
- padding-top: 1em
- padding-bottom: 0.7em
- color: black
-
-.dayName th
- 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
-
-.day
- background-color: #333333
-
-.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: $selected_period_color !important
-
-.selected_date
- background-color: $selected_date_color !important
-
-.excluded_date
- background-color: $excluded_date_color !important
-
-.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
-
-.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
-
-.today
- background-color: white
- color: black \ No newline at end of file
diff --git a/app/assets/stylesheets/main/calendars.sass b/app/assets/stylesheets/main/calendars.sass
deleted file mode 100644
index 298ce2a62..000000000
--- a/app/assets/stylesheets/main/calendars.sass
+++ /dev/null
@@ -1,11 +0,0 @@
-#calendar_form
- .btn
- margin: 5px
- #delete-btn
- margin-top: 23px
- .well
- padding-left: 50px
-
-#calendar_search_form
- button
- margin-top: 24px
diff --git a/app/assets/stylesheets/main/companies.sass b/app/assets/stylesheets/main/companies.sass
deleted file mode 100644
index 2cf1f596c..000000000
--- a/app/assets/stylesheets/main/companies.sass
+++ /dev/null
@@ -1,9 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.companies.index
-
-#workspace.companies.show
- .summary p label
- font-weight: bold \ No newline at end of file
diff --git a/app/assets/stylesheets/main/compliance_checks.sass b/app/assets/stylesheets/main/compliance_checks.sass
deleted file mode 100644
index 451972fd5..000000000
--- a/app/assets/stylesheets/main/compliance_checks.sass
+++ /dev/null
@@ -1,157 +0,0 @@
-// #workspace.compliance_checks.index
-
-#workspace.compliance_checks.show
- @import '../modules/job_status_colors'
- @import '../modules/job_status_title'
- @import '../partials/ie_report'
- @import '../modules/links'
-
-#validation_success
- margin-top: 15px
-
-#workspace.compliance_checks.report, #workspace.imports.compliance_check
- @import '../modules/job_status_colors'
- @import '../modules/job_status_title'
- @import '../modules/links'
-
- .status
- margin-left: 10px
-
- .order
- margin-bottom: 10px
- padding: 5px
- border-top: 1px solid #e4e4e4
- border-bottom: 1px solid #e4e4e4
-
- .status_ok_error
- color: #8fc861
- .status_nok_error
- color: #e22b1b
- .status_uncheck_error
- color: #898e7f
-
- .status_ok_warning
- color: #8fc861
- .status_nok_warning
- color: #ffbd2b
- .status_uncheck_warning
- color: #898e7f
-
- .resume
- &:after
- content: " "
- display: block
- height: 0
- clear: both
- visibility: hidden
-
- .col1
- float: left
- width: 45%
-
- .col2
- margin-left: 10px
- float: left
- width: 45%
-
- .graph
- height: 200px
-
- .caption
- text-align: center
- font-weight: bold
-
- .report
- .table
- margin-top: 20px
-
- dl.inline
- width: 100%
- overflow: hidden
-
- dt
- float: left
- clear: left
- width: 35%
- padding-top: 5px
- border-top: 1px solid #eee
- -ms-word-break: break-all
- word-break: break-all
- word-break: break-word
- -webkit-hyphens: auto
- -moz-hyphens: auto
- -ms-hyphens: auto
- hyphens: auto
-
- dd
- float: left
- width: 65%
- padding-top: 10px
- border-top: 1px solid #eee
-
- .severity__improvment,
- .severity_warning,
- .severity_error
- border: 1px solid
- margin: 10px 0px
- padding: 10px 10px 10px 10px
- background-repeat: no-repeat
- background-position: 10px center
- -moz-border-radius: 0.5em
- -webkit-border-radius: 0.5em
- border-radius: 0.5em
- height: 100%
-
- &:after
- content: " "
- display: block
- height: 0
- clear: both
- visibility: hidden
-
- .status_icon
- float: left
- width: 20%
- height: auto
-
- img
- vertical-align: middle
- width: 48px
- height: 48px
-
- .status_text
- float: left
- width: 70%
-
- .code
- font-size: 12px
- font-weight: bold
-
- .severity
- font-size: 10px
-
- .explanation
- display: none
- font-size: 12px
- margin: 5px 0 0 0
-
- .attributes
- font-size: 10px
- font-weight: bold
- margin: 5px 0 0px 0
-
- .severity_improvment
- color: black
- background-color: #c5cf4c
-
- .severity_warning
- color: black
- background-color: #f1dd30
-
- .severity_error
- color: black
- background-color: #ff9a0c
-
- .file_error
- font-size: 14px
- color: #898e7f \ No newline at end of file
diff --git a/app/assets/stylesheets/main/connection_links.sass b/app/assets/stylesheets/main/connection_links.sass
deleted file mode 100644
index a23fbcdff..000000000
--- a/app/assets/stylesheets/main/connection_links.sass
+++ /dev/null
@@ -1,30 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.connection_links.index
-
-#workspace.connection_links.show
- .summary p label
- font-weight: bold
-
- .duration
- padding-left: 10px
-
-#workspace.connection_links.select_departure
- .token-input-list
- display: inline-block
-
-#workspace.connection_links.select_arrival
- .token-input-list
- display: inline-block
-
-#workspace.connection_links.edit,
-#workspace.connection_links.new,
-#workspace.connection_links.create,
-#workspace.connection_links.update
- legend
- border: 0px
-
- .panel
- margin-left: 25% \ No newline at end of file
diff --git a/app/assets/stylesheets/main/errors.sass b/app/assets/stylesheets/main/errors.sass
deleted file mode 100644
index ee603e459..000000000
--- a/app/assets/stylesheets/main/errors.sass
+++ /dev/null
@@ -1,21 +0,0 @@
-#workspace.errors
- body
- text-align: center
-
- div.error
- width: 45em
- padding: 1em
- margin: 2em auto 0 auto
- border: 1px solid #ccc
- border-right-color: #999
- border-bottom-color: #999
-
- h2
- font-size: 100%
- color: #f00
- line-height: 1.5em
- font-weight: bold
-
- a, a:visited
- text-decoration: underline
- color: blue \ No newline at end of file
diff --git a/app/assets/stylesheets/main/export_tasks.sass b/app/assets/stylesheets/main/export_tasks.sass
deleted file mode 100644
index 799b5a13f..000000000
--- a/app/assets/stylesheets/main/export_tasks.sass
+++ /dev/null
@@ -1,10 +0,0 @@
-#workspace.export_tasks.new, #workspace.export_tasks.create
- .nav
- margin: 30px 0 10px 0
-
- .highlight
- padding: 9px 14px
- margin-bottom: 14px
- background-color: #f7f7f9
- border: 1px solid #e1e1e8
- border-radius: 4px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/exports.sass b/app/assets/stylesheets/main/exports.sass
deleted file mode 100644
index 875dc13f5..000000000
--- a/app/assets/stylesheets/main/exports.sass
+++ /dev/null
@@ -1,19 +0,0 @@
-// Place all the styles related to the Exports controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.exports.index
- .panel.export
- .panel-footer
- .history
- margin-top: 5px
-
-#workspace.exports.show
- @import '../partials/ie_report'
- @import '../modules/job_status_colors'
- @import '../modules/job_status_title'
- @import '../modules/links'
-
- .export-attributes
- font-size: 1.7em
- margin-top: 20px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/group_of_lines.sass b/app/assets/stylesheets/main/group_of_lines.sass
deleted file mode 100644
index d63eeb607..000000000
--- a/app/assets/stylesheets/main/group_of_lines.sass
+++ /dev/null
@@ -1,15 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.group_of_lines.index
-
-#workspace.group_of_lines.show
- .summary p label
- font-weight: bold
-
- .lines_detail div.page_info
- margin-top: 0px
-
- .lines
- margin-top: 10px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/help.sass b/app/assets/stylesheets/main/help.sass
deleted file mode 100644
index 87f21c3c3..000000000
--- a/app/assets/stylesheets/main/help.sass
+++ /dev/null
@@ -1,121 +0,0 @@
-#workspace.help
- ul li
- list-style: circle
- margin: 7px 0 7px 20px
-
- ol ul li
- list-style: circle
- margin: 7px 0 7px 20px
-
- ol
- list-style: none
- margin: 7px 0 7px 20px
- padding: 0
- counter-reset: num
-
- li:before
- content: counter(num) '. '
- counter-increment: num
-
- ol li:before
- content: counters(num, '.') ' '
-
- em, cite
- font-style: italic
-
- strong
- font-weight: bold
-
- p.attr_data
- font-style: italic
- text-decoration: underline
-
- p.olnext
- margin: -7px 0 0 40px !important
-
- p.ddnext
- margin: 0 0 0 30px !important
-
- p.note
- margin-left: 20px !important
- font-weight: bold
-
- p.border_image
- text-align: center
-
- img
- border-style: solid
- border-width: 1px
- border-color: rgb(187,187,187)
-
- table
- width: 100%
-
- td
- padding: 3px 5px
- width: 30%
-
- &.meta
- width: 50%
-
- th, td
- border: 1px solid black
-
- dt
- font-style: italic
- margin: 5px 0
-
- dd
- padding-left: 10px
-
-#sidebarhelp.help
- h2
- font-size: 17px
-
- h3
- font-size: 15px
-
- h4
- font-weight: bold
- padding: 7px 0
-
- ul li
- list-style: circle
- margin: 7px 0 7px 20px
-
- ol
- list-style: none
- margin: 7px 0 7px 20px
- padding: 0
- counter-reset: num
-
- li:before
- content: counter(num) '. '
- counter-increment: num
-
- ol li:before
- content: counters(num, '.') ' '
-
- em, cite
- font-style: italic
-
- strong
- font-weight: bold
-
- p.attr_data
- font-style: italic
- text-decoration: underline
-
- table
- width: 100%
-
- td
- padding: 3px 5px
- width: 30%
-
- dt
- font-style: italic
- margin: 5px 0
-
- dd
- padding-left: 10px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/import_tasks.sass b/app/assets/stylesheets/main/import_tasks.sass
deleted file mode 100644
index 810582cf2..000000000
--- a/app/assets/stylesheets/main/import_tasks.sass
+++ /dev/null
@@ -1,11 +0,0 @@
-#workspace.import_tasks.new,
-#workspace.import_tasks.create
- .nav
- margin: 30px 0 10px 0
-
- .highlight
- padding: 9px 14px
- margin-bottom: 14px
- background-color: #f7f7f9
- border: 1px solid #e1e1e8
- border-radius: 4px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/imports.sass b/app/assets/stylesheets/main/imports.sass
deleted file mode 100644
index af5e88218..000000000
--- a/app/assets/stylesheets/main/imports.sass
+++ /dev/null
@@ -1,40 +0,0 @@
-#workspace.imports.index
- .panel.import
- .panel-footer
- min-height: 5.5em
-
- .save-mode
- color: $brand-info
-
- .fa-lg
- font-size: 1em
- .fa-ban
- opacity: 0.6
-
- .history
- margin-top: 5px
-
-#workspace.imports.index,
-#workspace.imports.show
- .import-attributes
- .save-mode, .format
- display: inline-block
-
- .save-mode
- color: $brand-info
- margin-left: 0.3em
-
- .fa-ban
- opacity: 0.6
- .fa-stack
- font-size: 0.9em
-
-#workspace.imports.show
- @import '../partials/ie_report'
- @import '../modules/job_status_colors'
- @import '../modules/job_status_title'
- @import '../modules/links'
-
- .import-attributes
- font-size: 1.7em
- margin-top: 20px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/journey_patterns.sass b/app/assets/stylesheets/main/journey_patterns.sass
deleted file mode 100644
index 07c3260d4..000000000
--- a/app/assets/stylesheets/main/journey_patterns.sass
+++ /dev/null
@@ -1,49 +0,0 @@
-// Place all the styles related to the routes controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.journey_patterns.edit,
-#workspace.journey_patterns.new,
-#workspace.journey_patterns.create,
-#workspace.journey_patterns.update
- #route_color
- width: 100px
- color: white
- font-weight: bold
-
- #journey_pattern_stop_point_ids_input fieldset .choices-group
- margin-top: 25px
-
-#workspace.journey_patterns.show
- .journey_pattern_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: 20px
-
- .journey_pattern_stop_points
- clear: both
- margin: 0px
- padding: 0px
-
- .stop_point
- .position
- width: 25px
- height: 20px
- float: left
- background-color: #61970B
- font-weight: bold
- color: white
- margin-right: 10px
- padding-left: 4px
-
- #middle #sidebar a.control-shape
- color: orange \ No newline at end of file
diff --git a/app/assets/stylesheets/main/layout.sass b/app/assets/stylesheets/main/layout.sass
deleted file mode 100644
index d75c359ae..000000000
--- a/app/assets/stylesheets/main/layout.sass
+++ /dev/null
@@ -1,133 +0,0 @@
-body
- padding-top: 50px
-
-h1
- color: white
-
-h1, .h1, h2, .h2, h3, .h3
- margin-bottom: 20px
-
-label.label
- color: black
- font-size: 100%
-
-ol.breadcrumb
- margin-top: 10px
-
-.ce-hide
- display: none
-
-#middle
- position: relative
- 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
- background: white
-
- .main_actions
- text-align: right
-
- .alert
- margin-top: 15px
-
- #sidebar
- height: 100%
- padding-top: 20px
- border-left: 1px solid $gray-lighter
-
- &.ce-SidebarFloatBlock
- position: absolute
- height: auto
- right: 0
- background-color: #fff
- top: 45px
-
- label
- color: #555555
- font-weight: normal
- font-size: 12px
-
- a
- color: #666
-
- .actions
- margin-bottom: 20px
-
- li
- margin-bottom: 5px
-
- p
- font-size: 12px
-
- fieldset.history_tag
- font-size: 12px
- color: $gray-light
-
- legend
- font-size: 14px
- margin-bottom: 10px
-
- 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
-
- &.current
- text-decoration: none
- color: black !important
- background: url(image-path('icons/accept.png')) no-repeat
-
- &.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 \ No newline at end of file
diff --git a/app/assets/stylesheets/main/lines.sass b/app/assets/stylesheets/main/lines.sass
deleted file mode 100644
index b9bdfae8f..000000000
--- a/app/assets/stylesheets/main/lines.sass
+++ /dev/null
@@ -1,87 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.lines.index
- input[type='checkbox'].multiple_selection
- vertical-align: middle
-
- #search
- label
- margin-bottom: 0px
-
- input[type='checkbox']
- margin-left: 3px
-
-#workspace.lines.edit,
-#workspace.lines.new,
-#workspace.lines.create,
-#workspace.lines.update
- #line_color_old
- width: 100px
- color: white
- font-weight: bold
-
- .nested-fields.footnote, .add_footnote
- @extend .col-md-offset-3
-
- .footnotes_block
- margin-bottom: 30px
-
-#workspace.lines.show
- .summary p
- label
- font-weight: bold
-
- .color
- padding: 3px 15px 3px 15px
-
- .group_of_line
- .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
-
- .name a
- display: inline
-
-.ce-LineBlock-header-list
- display: table
- width: 100%
- margin: 0
- padding: 0
-
- > li
- display: table-cell
- vertical-align: middle
-
- > input
- margin-top: 0
-
- &:first-child
- width: 37px
-
- &:last-child
- text-align: right
- width: 73px
-
-.ce-LineBlock-header-title
- padding: 0 !important
- line-height: 12px
- font-size: 13px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/multiple_selection.sass b/app/assets/stylesheets/main/multiple_selection.sass
deleted file mode 100644
index b46dded01..000000000
--- a/app/assets/stylesheets/main/multiple_selection.sass
+++ /dev/null
@@ -1,17 +0,0 @@
-input[type='checkbox'].multiple_selection
- margin-left: 0px
- position: absolute
- top: 0px
-
-#multiple_selection_menu
- h3
- margin-top: 20px
-
- div
- padding: 6px 8px
-
- .actions
- margin-top: 20px
-
- .select_all, .deselect_all
- font-size: 0.8em \ No newline at end of file
diff --git a/app/assets/stylesheets/main/networks.sass b/app/assets/stylesheets/main/networks.sass
deleted file mode 100644
index 4d3717f26..000000000
--- a/app/assets/stylesheets/main/networks.sass
+++ /dev/null
@@ -1,9 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.networks.index
-
-#workspace.networks.show
- .summary p label
- font-weight: bold \ No newline at end of file
diff --git a/app/assets/stylesheets/main/organisations.sass b/app/assets/stylesheets/main/organisations.sass
deleted file mode 100644
index 4bfee860a..000000000
--- a/app/assets/stylesheets/main/organisations.sass
+++ /dev/null
@@ -1,5 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.organisations.show \ No newline at end of file
diff --git a/app/assets/stylesheets/main/referentials.sass b/app/assets/stylesheets/main/referentials.sass
deleted file mode 100644
index 293807560..000000000
--- a/app/assets/stylesheets/main/referentials.sass
+++ /dev/null
@@ -1,34 +0,0 @@
-// Place all the styles related to the referentials controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.referentials.index
-
-#workspace.referentials.show
- .summary p label
- font-weight: bold
-
- .panel
- font-size: 12px
- width: 75%
-
- .panel-heading
- font-weight: bold
-
- li.list-group-item
- padding: 5px 15px
-
-#sidebar div#clean_up
- form
- fieldset
- li
- margin-bottom: 0px
-
- &.date
- input
- width: 125px
- font-size: 12px
- height: 25px
-
- label
- width: 35% \ No newline at end of file
diff --git a/app/assets/stylesheets/main/route_sections.sass b/app/assets/stylesheets/main/route_sections.sass
deleted file mode 100644
index fe3c98c10..000000000
--- a/app/assets/stylesheets/main/route_sections.sass
+++ /dev/null
@@ -1,54 +0,0 @@
-#workspace.route_sections_selectors.edit
- td.route_section
- .input
- padding: 0
- margin: 0
-
- select
- width: 100%
-
- a.edit-route-section
- background: url(image-path('icons/edit.png')) no-repeat 0% 50%
- text-indent: -9999px
- display: inline-block
- width: 16px
- height: 16px
- margin-right: 8px
-
- &.disabled
- background-image: url(image-path('icons/edit-disabled.png'))
-
- #map-selection
- position: relative
-
- span
- display: inline-block
-
- .departure, .arrival
- width: 25%
-
- .actions
- width: 25%
- overflow: visible
- padding-left: 0
- position: absolute
- right: 0
-
-#workspace.route_sections.index
- th.distance, th.points
- text-align: center
-
- td.distance, td.points, td.actions
- text-align: center
-
-#workspace.route_sections.edit
- .formtastic
- .input .label
- width: 40%
-
- .actions
- padding-left: 19%
-
- #map
- width: 600px
- heigth: 600px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/routes.sass b/app/assets/stylesheets/main/routes.sass
deleted file mode 100644
index 977d2f4b3..000000000
--- a/app/assets/stylesheets/main/routes.sass
+++ /dev/null
@@ -1,46 +0,0 @@
-// Place all the styles related to the routes controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.lines.show
-
-#workspace.routes.edit,
-#workspace.routes.new,
-#workspace.routes.create,
-#workspace.routes.update
- #route_color
- width: 100px
- color: white
- font-weight: bold
-
- #stop_points .nested-fields
- ol
- margin-left: 25%
-
- .handle
- margin-left: 5px
-
- .search_stop_area
- margin-bottom: 0px !important
-
- div.resize
- height: 40px
- line-height: 40px
- font-size: 16px
-
- #stop_points .links
- margin: 10px 0 15px 25%
-
-#workspace.routes.edit_boarding_alighting
- .stop_area
- padding-top: 7px
-
-// #workspace.routes.show
-
-.large-map
- width: 100%
- height: 600px
-
- #map
- width: 100%
- height: 100% \ No newline at end of file
diff --git a/app/assets/stylesheets/main/rule_parameter_sets.sass b/app/assets/stylesheets/main/rule_parameter_sets.sass
deleted file mode 100644
index ab58b7bf9..000000000
--- a/app/assets/stylesheets/main/rule_parameter_sets.sass
+++ /dev/null
@@ -1,45 +0,0 @@
-// Place all the styles related to the rule_parameter_sets controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.rule_parameter_sets.index
-
-#workspace.rule_parameter_sets.show,
-#workspace.compliance_check_tasks.rule_parameter_set
- .summary label
- font-weight: bold
-
- div.attributes_group
- margin: 15px 0 15px 0
-
- .title
- font-weight: bold
-
- .columns
- margin-left: 10px
-
- div
- display: inline-block
-
- &.two_columns
- width: 45%
- &.three_columns
- width: 30%
- &.four_columns
- width: 23%
-
- label
- color: #616161
-
- .value
- margin-left: 5px
-
- div.rule_parameter_by_mode
- margin: 20px 0 0 0 !important
-
- .mode_specific
- display: none
- margin: 0 0 0 10px
-
- p label
- color: #616161 \ No newline at end of file
diff --git a/app/assets/stylesheets/main/simple_form.sass b/app/assets/stylesheets/main/simple_form.sass
deleted file mode 100644
index 143ea692c..000000000
--- a/app/assets/stylesheets/main/simple_form.sass
+++ /dev/null
@@ -1,3 +0,0 @@
-#workspace
- .submit
- @extend .col-md-offset-3 \ No newline at end of file
diff --git a/app/assets/stylesheets/main/stop_areas.sass b/app/assets/stylesheets/main/stop_areas.sass
deleted file mode 100644
index f8e1e148a..000000000
--- a/app/assets/stylesheets/main/stop_areas.sass
+++ /dev/null
@@ -1,165 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.stop_areas.index
- #country_codes
- display: none
-
-#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
- width: 50%
-
-#workspace.stop_areas.show
- .geo_data
- padding-left: 15px
-
- .summary
- p label
- font-weight: bold
-
-.genealogical
- .parent
- border: 2px solid black
- float: left
- padding: 3px 15px 3px 3px
-
- *
- vertical-align: middle
-
- span
- margin-left: 7px
- img
- margin: 0px 5px 0px 5px
-
- .lines
- float: left
-
- .line
- border: 2px solid black
- padding: 3px 15px 3px 3px
- height: 25px
- margin-bottom: 5px
-
- *
- vertical-align: middle
-
- span
- margin-left: 7px
- img
- margin: 0px 5px 0px 5px
-
- .no_parent
- float: left
- padding: 3px 15px 3px 3px
- width: 150px
-
- .target
- border: 2px solid #86b41d
- float: left
- padding: 3px 15px 3px 3px
- font-weight: bold
-
- *
- vertical-align: middle
-
- span
- margin-left: 7px
- img
- margin: 0px 5px 0px 5px
-
- .children
- float: left
-
- .child
- border: 2px solid black
- padding: 3px 15px 3px 3px
- margin-bottom: 5px
-
- *
- vertical-align: middle
-
- span
- margin-left: 7px
- img
- margin: 0px 5px 0px 5px
-
- .link
- float: left
- padding: 7px
- margin-right: 10px
- margin-left: 10px
- height: 25px
-
-#workspace.stop_areas.select_parent
- .token-input-list
- display: inline-block
-
-#workspace.stop_areas.add_children
- .token-input-list
- display: inline-block
-
-#workspace.stop_areas.access_links
- .access_link_pairs
- .link
- 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
-
-#sidebar ul.selection li
- a
- line-height: 27px
-
- img
- height: 25px
- width: 25px
- vertical-align: middle \ No newline at end of file
diff --git a/app/assets/stylesheets/main/stop_points.sass b/app/assets/stylesheets/main/stop_points.sass
deleted file mode 100644
index a17814d3b..000000000
--- a/app/assets/stylesheets/main/stop_points.sass
+++ /dev/null
@@ -1,26 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-#workspace.stop_points.index
- // .stop_points
-
- #sortable_stop_points .stop_point
- /* to create multi-column index */
- width: 350px
- padding-right: 10px
-
- .handle
- cursor: move
- margin-right: 7px
- margin-bottom: 20px
-
- a.link
- background: url(image-path('icons/link-small.png')) no-repeat 0% 50%
-
- .position
- background-color: #61970B
- font-weight: bold
- color: white
- margin-right: 10px
- padding-left: 4px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/time_table_combinations.sass b/app/assets/stylesheets/main/time_table_combinations.sass
deleted file mode 100644
index 9de2c2235..000000000
--- a/app/assets/stylesheets/main/time_table_combinations.sass
+++ /dev/null
@@ -1,7 +0,0 @@
-#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.sass b/app/assets/stylesheets/main/time_tables.sass
deleted file mode 100644
index 6918bec1e..000000000
--- a/app/assets/stylesheets/main/time_tables.sass
+++ /dev/null
@@ -1,135 +0,0 @@
-// Place all the styles related to the lines controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
-
-// #workspace.time_tables.index
-
-#workspace.time_tables.show
- .modal-body
- overflow-y: visible
-
- .summary
- margin-top: 20px
-
- p label
- font-weight: bold
-
- .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: red
-
- .validity_out_soon
- color: orange
-
- .validity_regular
- color: green
-
- 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
- padding-left: 50px
-
- .odd
- padding-left: 50px
- padding-right: 450px
-
- .even
- padding-left: 50px
- padding-right: 450px
-
- .actions
- float: right
-
- #associated_calendars
- padding-top: 15px
-
-#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
-
- .tags
- overflow: visible !important
-
- h3
- .dates
- cursor: pointer
-
- .periods
- cursor: pointer
-
- .excluded_dates
- cursor: pointer
-
- #dates,
- #excluded_dates,
- #periods
- margin-left: 25%
-
- .nested-fields
- margin: 5px
-
- ol li
- display: inline
-
- .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
-
- li
- float: left
- margin: 0 0 0 0
- width: auto
- padding: 0
-
- label
- padding-left: 10%
- margin-top: 0
-
- .day_type_label
- float: left
- margin-top: 0
- width: 25%
-
- 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_journey_frequencies.sass b/app/assets/stylesheets/main/vehicle_journey_frequencies.sass
deleted file mode 100644
index a827cc4d2..000000000
--- a/app/assets/stylesheets/main/vehicle_journey_frequencies.sass
+++ /dev/null
@@ -1,155 +0,0 @@
-#workspace
- .ce-TimeBandFormTable
- .btn
- white-space: normal
- width: 130px
- font-size: 11px
- padding: 2px 0
-
- .ce-TimeBandFormTable
- th
- text-align: left
- padding: 6px 20px
-
- td
- padding: 6px 20px
-
- .ce-TimeBandFormTable td
- vertical-align: middle
-
- .ce-TimeBandFormTable-circleLine
- position: relative
-
- .ce-TimeBandFormTable-line:after
- content: ''
- position: absolute
- top: 0
- bottom: 0
- left: 50%
- width: 2px
- margin-left: -1px
- background-color: #61970b
-
- tr:first-child td .ce-TimeBandFormTable-line:after
- top: 50%
-
- tr:last-child td .ce-TimeBandFormTable-line:after
- bottom: 50%
-
- .ce-TimeBandFormTable-circle
- position: relative
- z-index: 999
- display: block
- width: 16px
- height: 16px
- border-radius: 8px
- background-color: #4d7809
-
- tr:hover .ce-TimeBandFormTable-circle
- background-color: #fff
- border: 2px solid #61970b
-
- .ce-FrequencyFormFields
- display: table
- width: 100%
- padding-left: 25%
-
- .token-input-list
- width: 80%
-
- .inline-errors
- margin: 0
-
- > li
- display: table-cell
- width: 21%
- vertical-align: top
- padding: 0
- margin: 0
-
- &:first-child select
- width: 160px
-
- &:nth-last-child(2), &:last-child
- width: 8%
-
- label
- font-size: 13px
- padding-left: 0
-
- legend
- position: relative
- width: auto
- float: none
- border: 0
-
- label
- position: relative
-
- .fragments-group
- float: none
- width: auto
- padding: 0
-
- > li
- display: inline-block
- vertical-align: top
-
- &.vehicle_journey_frequencies
- .actions-add-fields
- clear: both
- padding-left: 25%
- margin-top: 10px
-
- td.ce-VehicleJourneyBlock-frequency
- background-color: rgba(95, 95, 95, 0.2)
-
- .ce-VehicleJourneyFrequencyTableBlock
- margin: 0 !important
-
- .ce-VehicleJourneyFrequenciesMatrix
- margin: 0
- padding: 0
-
- > li
- background-color: #eee
- height: 22px
- margin-bottom: 20px
- position: relative
-
- > ul
- margin: 0
- padding: 0
-
- > li
- cursor: pointer
- position: absolute
- padding: 0 2px
- top: 0
- bottom: 0
- background-color: $brand-primary
- border-left: 1px solid #000
- border-right: 1px solid #000
-
- &:hover
- z-index: 9999
- background-color: #4d7809
- top: -2px
- bottom: -2px
-
- > span
- display: block
-
- .ce-VehicleJourneyFrequenciesMatrix-firstDepartureTime,
- .ce-VehicleJourneyFrequenciesMatrix-lastDepartureTime
- display: none
- position: absolute
- top: -13px
- font-size: 11px
- color: #262626
-
- .ce-VehicleJourneyFrequenciesMatrix-firstDepartureTime
- left: -32px
-
- .ce-VehicleJourneyFrequenciesMatrix-lastDepartureTime
- right: -32px \ No newline at end of file
diff --git a/app/assets/stylesheets/main/vehicle_journeys.sass b/app/assets/stylesheets/main/vehicle_journeys.sass
deleted file mode 100644
index ec0b25dbc..000000000
--- a/app/assets/stylesheets/main/vehicle_journeys.sass
+++ /dev/null
@@ -1,118 +0,0 @@
-#workspace.vehicle_journeys.edit,
-#workspace.vehicle_journeys.update,
-#workspace.vehicle_journeys.create,
-#workspace.vehicle_journeys.new,
-#workspace.vehicle_journey_frequencies.edit,
-#workspace.vehicle_journey_frequencies.update,
-#workspace.vehicle_journey_frequencies.create,
-#workspace.vehicle_journey_frequencies.new
- #route_color
- width: 100px
- color: white
- font-weight: bold
-
- .btn
- padding: 6px 12px
-
- .time_table_list
- padding-left: 25%
-
- #vehicle_journey_footnote_ids_input,
- #vehicle_journey_frequency_footnote_ids_input
- min-height: 3em
-
- .vehicle_journey_at_stops,
- .vehicle_journey_frequency_at_stops
- margin-left: 25%
-
- thead, tbody, tfoot
- th, td
- text-align: center
-
- .journey_pattern_dependent_list
- tr.no_stop
- display: none
-
- td.departure_time, td.arrival_time
- &.missing
- background-color: $brand-warning
-
- &.invalid_position
- background-color: $brand-danger
-
- .title
- font-weight: bold
- margin-bottom: 20px
-
- span
- margin-left: 10px
- margin-right: 10px
-
- .slide
- margin-left: 30px
-
-#workspace.vehicle_journeys.index,
-#workspace.vehicle_journey_frequencies.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
-
- .calendars
- font-size: 12px
-
- .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_journey_journey.show,
-#workspace.vehicle_journey_journey.edit,
-#workspace.vehicle_journey_journey.update,
-#workspace.vehicle_journey_journey.create,
-#workspace.vehicle_journey_journey.new
- .slide
- cursor: pointer
-
-#workspace.vehicle_journeys.show,
-#workspace.vehicle_journey_frequencies.show
- .summary p label
- font-weight: bold
-
-#workspace.vehicle_journeys.timeless,
-#workspace.vehicle_journey_frequencies.timeless
- .summary p label
- font-weight: bold
-
- .vehicle_journeys,
- .vehicle_journey_frequencies
- margin-top: 20px
-
- .vehicle_journey,
- .vehicle_journey_frequency
- span.included_day_type
- font-weight: bolder
-
- // span.excluded_day_type \ No newline at end of file
diff --git a/app/assets/stylesheets/main/vehicle_translation.sass b/app/assets/stylesheets/main/vehicle_translation.sass
deleted file mode 100644
index f1fd12e14..000000000
--- a/app/assets/stylesheets/main/vehicle_translation.sass
+++ /dev/null
@@ -1,10 +0,0 @@
-#translate_form
- .repeat_cloning
- margin-top: 30px
-
- .modal-footer
- .actions
- padding-left: 75%
-
- li
- margin: 0 \ No newline at end of file
diff --git a/app/assets/stylesheets/modules/import_messages.sass b/app/assets/stylesheets/modules/import_messages.sass
new file mode 100644
index 000000000..e5666cbcd
--- /dev/null
+++ b/app/assets/stylesheets/modules/import_messages.sass
@@ -0,0 +1,5 @@
+.import_messages
+ .status_icon
+ padding-right: 20px
+ h1
+ padding-bottom: 20px
diff --git a/app/assets/stylesheets/typography/_fonts.sass b/app/assets/stylesheets/typography/_fonts.sass
index 0cc387d74..03ef0b42d 100644
--- a/app/assets/stylesheets/typography/_fonts.sass
+++ b/app/assets/stylesheets/typography/_fonts.sass
@@ -7,34 +7,34 @@
@font-face
// Regular
font-family: 'Open Sans'
- src: url(asset-path('OpenSans/Regular/OpenSans-Regular.woff2')) format('woff2'), url(asset-path('OpenSans/Regular/OpenSans-Regular.woff')) format('woff'), url(asset-path('OpenSans/Regular/OpenSans-Regular.ttf')) format('ttf')
+ src: url(asset-path('OpenSans/Regular/OpenSans-Regular.woff2')) format('woff2'), url(asset-path('OpenSans/Regular/OpenSans-Regular.woff')) format('woff'), url(asset-path('OpenSans/Regular/OpenSans-Regular.ttf')) format('truetype')
font-weight: 400
font-style: normal
@font-face
// Regular Italic
font-family: 'Open Sans'
- src: url(asset-path('OpenSans/Regular/OpenSans-Italic.woff2')) format('woff2'), url(asset-path('OpenSans/Regular/OpenSans-Italic.woff')) format('woff'), url(asset-path('OpenSans/Regular/OpenSans-Italic.ttf')) format('ttf')
+ src: url(asset-path('OpenSans/Regular/OpenSans-Italic.woff2')) format('woff2'), url(asset-path('OpenSans/Regular/OpenSans-Italic.woff')) format('woff'), url(asset-path('OpenSans/Regular/OpenSans-Italic.ttf')) format('truetype')
font-weight: 400
font-style: italic
@font-face
// Bold
font-family: 'Open Sans'
- src: url(asset-path('OpenSans/Bold/OpenSans-Bold.woff2')) format('woff2'), url(asset-path('OpenSans/Bold/OpenSans-Bold.woff')) format('woff'), url(asset-path('OpenSans/Bold/OpenSans-Bold.ttf')) format('ttf')
+ src: url(asset-path('OpenSans/Bold/OpenSans-Bold.woff2')) format('woff2'), url(asset-path('OpenSans/Bold/OpenSans-Bold.woff')) format('woff'), url(asset-path('OpenSans/Bold/OpenSans-Bold.ttf')) format('truetype')
font-weight: 700
font-style: normal
@font-face
// Bold Italic
font-family: 'Open Sans'
- src: url(asset-path('OpenSans/Bold/OpenSans-BoldItalic.woff2')) format('woff2'), url(asset-path('OpenSans/Bold/OpenSans-BoldItalic.woff')) format('woff'), url(asset-path('OpenSans/Bold/OpenSans-BoldItalic.ttf')) format('ttf')
+ src: url(asset-path('OpenSans/Bold/OpenSans-BoldItalic.woff2')) format('woff2'), url(asset-path('OpenSans/Bold/OpenSans-BoldItalic.woff')) format('woff'), url(asset-path('OpenSans/Bold/OpenSans-BoldItalic.ttf')) format('truetype')
font-weight: 700
font-style: italic
//-- sBoiv --//
@font-face
font-family: 'sboiv'
- src: url(asset-path('sBoiv/sboiv.woff?vhxdui')) format('woff'), url(asset-path('sBoiv/sboiv.ttf?vhxdui')) format('ttf')
+ src: url(asset-path('sBoiv/sboiv.woff?ctftl5')) format('woff'), url(asset-path('sBoiv/sboiv.ttf?ctftl5')) format('truetype')
font-weight: normal
font-style: normal
diff --git a/app/assets/stylesheets/typography/_sboiv.sass b/app/assets/stylesheets/typography/_sboiv.sass
index 1f89bad74..e37f89f2d 100644
--- a/app/assets/stylesheets/typography/_sboiv.sass
+++ b/app/assets/stylesheets/typography/_sboiv.sass
@@ -53,8 +53,86 @@
font-size: 5em
-.sb-update-vj:before
- content: '\e900'
+.sb-ZDLR:before
+ content: '\e904'
+
+.sb-ZDER:before
+ content: '\e905'
+
+.sb-ZDEP:before
+ content: '\e906'
+
+.sb-transporteur:before
+ content: '\e907'
+
+.sb-trace:before
+ content: '\e908'
+
+.sb-tableau-de-bord:before
+ content: '\e909'
+
+.sb-synchro-ilico:before
+ content: '\e90a'
+
+.sb-synchro-icar:before
+ content: '\e90b'
+
+.sb-reseau:before
+ content: '\e90c'
+
+.sb-rapport-de-controle:before
+ content: '\e90d'
+
+.sb-OAT:before
+ content: '\e90e'
+
+.sb-OAS:before
+ content: '\e90f'
+
+.sb-modele-calendrier:before
+ content: '\e910'
+
+.sb-mission:before
+ content: '\e911'
+
+.sb-ligne_commerciale:before
+ content: '\e912'
+
+.sb-ligne_administrative:before
+ content: '\e913'
+
+.sb-LDA:before
+ content: '\e914'
+
+.sb-jeux-de-donnees:before
+ content: '\e915'
+
+.sb-jeux-de-controle:before
+ content: '\e916'
+
+.sb-itl:before
+ content: '\e917'
+
+.sb-itineraire:before
+ content: '\e918'
+
+.sb-importer:before
+ content: '\e919'
+
+.sb-horaires-des-courses:before
+ content: '\e91a'
+
+.sb-calendrier-application:before
+ content: '\e91b'
+
+.sb-arret:before
+ content: '\e91c'
+
+.sb-Acces:before
+ content: '\e91d'
+
+.sb-chrono:before
+ content: '\e903'
.sb-preparing:before
content: '\e901'
@@ -62,5 +140,8 @@
.sb-current-ref:before
content: '\e902'
-.sb-chrono:before
- content: '\e903'
+.sb-update-vj:before
+ content: '\e900'
+
+.sb-ligne:before
+ content: '\e91e'
diff --git a/app/controllers/api/v1/chouette_controller.rb b/app/controllers/api/v1/chouette_controller.rb
index 7805074ee..98c2fff05 100644
--- a/app/controllers/api/v1/chouette_controller.rb
+++ b/app/controllers/api/v1/chouette_controller.rb
@@ -7,7 +7,6 @@ module Api
before_action :authenticate
private
-
def authenticate
authenticate_or_request_with_http_token do |token, options|
@referential = Api::V1::ApiKey.referential_from_token(token)
@@ -16,10 +15,10 @@ module Api
switch_referential if @api_key
end
end
+
def switch_referential
Apartment::Tenant.switch!(@api_key.referential.slug)
- end
-
+ end
end
end
end
diff --git a/app/controllers/api/v1/iboo_controller.rb b/app/controllers/api/v1/iboo_controller.rb
new file mode 100644
index 000000000..4db9e9007
--- /dev/null
+++ b/app/controllers/api/v1/iboo_controller.rb
@@ -0,0 +1,21 @@
+class Api::V1::IbooController < Api::V1::ChouetteController
+ protected
+ def begin_of_association_chain
+ @current_organisation
+ end
+
+ private
+ def authenticate
+ authenticate_with_http_basic do |code, token|
+ if organisation = Organisation.find_by(code: code)
+ if organisation.api_keys.exists?(token: token)
+ @current_organisation = organisation
+ end
+ end
+ end
+
+ unless @current_organisation
+ request_http_basic_authentication
+ end
+ end
+end
diff --git a/app/controllers/api/v1/imports_controller.rb b/app/controllers/api/v1/imports_controller.rb
new file mode 100644
index 000000000..6050418d8
--- /dev/null
+++ b/app/controllers/api/v1/imports_controller.rb
@@ -0,0 +1,15 @@
+class Api::V1::ImportsController < Api::V1::IbooController
+ defaults :resource_class => WorkbenchImport
+ belongs_to :workbench
+
+ def create
+ args = workbench_import_params.merge(creator: 'Webservice')
+ @import = parent.workbench_imports.create(args)
+ create!
+ end
+
+ private
+ def workbench_import_params
+ params.require(:workbench_import).permit(:file, :name)
+ end
+end
diff --git a/app/controllers/api/v1/netex_imports_controller.rb b/app/controllers/api/v1/netex_imports_controller.rb
index 17eec2ef8..fc85e35dd 100644
--- a/app/controllers/api/v1/netex_imports_controller.rb
+++ b/app/controllers/api/v1/netex_imports_controller.rb
@@ -3,6 +3,8 @@ module Api
class NetexImportsController < ChouetteController
include ControlFlow
+ skip_before_action :authenticate
+
def create
respond_to do | format |
format.json(&method(:create_models))
@@ -26,9 +28,22 @@ module Api
end
def create_netex_import
- @netex_import = NetexImport.new(netex_import_params.merge(referential_id: @new_referential.id))
+ attributes = netex_import_params.merge creator: "Webservice"
+
+ if @new_referential.persisted?
+ attributes = attributes.merge referential_id: @new_referential.id
+ else
+ attributes = attributes.merge status: "failed"
+ end
+
+ @netex_import = NetexImport.new attributes
@netex_import.save!
- rescue ActiveRecord::RecordInvalid
+
+ unless @netex_import.referential
+ Rails.logger.info "Can't create referential for import #{@netex_import.id}: #{@new_referential.inspect} #{@new_referential.metadatas.inspect} #{@new_referential.errors.full_messages}"
+ @netex_import.messages.create criticity: :error, message_key: "referential_creation"
+ end
+ rescue ActiveRecord::RecordInvalid
render json: {errors: @netex_import.errors}, status: 406
finish_action!
end
@@ -38,17 +53,34 @@ module Api
Referential.new(
name: netex_import_params['name'],
organisation_id: @workbench.organisation_id,
- workbench_id: @workbench.id)
- @new_referential.save!
- rescue ActiveRecord::RecordInvalid
- render json: {errors: @new_referential.errors}, status: 406
- finish_action!
+ workbench_id: @workbench.id,
+ metadatas: [metadata]
+ )
+ @new_referential.save
+ end
+
+ def metadata
+ metadata = ReferentialMetadata.new
+
+ if netex_import_params['file']
+ netex_file = STIF::NetexFile.new(netex_import_params['file'].to_io)
+ frame = netex_file.frames.first
+
+ if frame
+ metadata.periodes = frame.periods
+
+ line_objectids = frame.line_refs.map { |ref| "STIF:CODIFLIGNE:Line:#{ref}" }
+ metadata.line_ids = @workbench.lines.where(objectid: line_objectids).pluck(:id)
+ end
+ end
+
+ metadata
end
def netex_import_params
params
.require('netex_import')
- .permit(:file, :name, :workbench_id)
+ .permit(:file, :name, :workbench_id, :parent_id, :parent_type)
end
end
end
diff --git a/app/controllers/api/v1/workbenches_controller.rb b/app/controllers/api/v1/workbenches_controller.rb
new file mode 100644
index 000000000..3c07997ce
--- /dev/null
+++ b/app/controllers/api/v1/workbenches_controller.rb
@@ -0,0 +1,3 @@
+class Api::V1::WorkbenchesController < Api::V1::IbooController
+ defaults :resource_class => Workbench
+end
diff --git a/app/controllers/api_keys_controller.rb b/app/controllers/api_keys_controller.rb
index 35a84da87..7059cf52e 100644
--- a/app/controllers/api_keys_controller.rb
+++ b/app/controllers/api_keys_controller.rb
@@ -1,22 +1,32 @@
-class ApiKeysController < ChouetteController
- defaults :resource_class => Api::V1::ApiKey
-
- belongs_to :referential
+class ApiKeysController < BreadcrumbController
+ defaults resource_class: Api::V1::ApiKey
def create
- create! { referential_path(@referential) }
+ @api_key = Api::V1::ApiKey.new(api_key_params.merge(organisation: current_organisation))
+ create! { organisation_api_keys_path }
+ end
+
+ def index
+ @api_keys = decorate_api_keys(current_organisation.api_keys.paginate(page: params[:page]))
end
+
def update
- update! { referential_path(@referential) }
+ update! { organisation_api_key_path(resource) }
end
+
def destroy
- destroy! { referential_path(@referential) }
+ destroy! { organisation_api_keys_path }
end
private
def api_key_params
- params.require(:api_key).permit( :name )
- end
-
-end
+ params.require(:api_key).permit(:name, :referential_id)
+ end
+ def decorate_api_keys(api_keys)
+ ModelDecorator.decorate(
+ api_keys,
+ with: ApiKeyDecorator,
+ )
+ end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d15aa336d..8cb5726c4 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -33,6 +33,17 @@ class ApplicationController < ActionController::Base
end
helper_method :current_organisation
+ def current_offer_workbench
+ current_organisation.workbenches.where(name: "Gestion de l'offre")
+ end
+ helper_method :current_offer_workbench
+
+ def current_functional_scope
+ functional_scope = current_organisation.sso_attributes.try(:[], "functional_scope") if current_organisation
+ JSON.parse(functional_scope) if functional_scope
+ end
+ helper_method :current_functional_scope
+
def begin_of_association_chain
current_organisation
end
diff --git a/app/controllers/autocomplete_time_tables_controller.rb b/app/controllers/autocomplete_time_tables_controller.rb
index e977a28b0..f65f5b9f6 100644
--- a/app/controllers/autocomplete_time_tables_controller.rb
+++ b/app/controllers/autocomplete_time_tables_controller.rb
@@ -9,20 +9,25 @@ class AutocompleteTimeTablesController < InheritedResources::Base
end
def referential
- @referential ||= current_organisation.referentials.find params[:referential_id]
+ @referential ||= Referential.find params[:referential_id]
end
protected
def select_time_tables
- scope = referential.time_tables
+ scope = params[:source_id] ? referential.time_tables.where("time_tables.id != ?", params[:source_id]) : referential.time_tables
if params[:route_id]
scope = scope.joins(vehicle_journeys: :route).where( "routes.id IN (#{params[:route_id]})")
end
- scope
+ scope.distinct
+ end
+
+ def split_params! search
+ params[:q][search] = params[:q][search].split(" ") if params[:q][search]
end
def collection
+ split_params! :comment_or_objectid_cont_any
@time_tables = select_time_tables.search(params[:q]).result.paginate(page: params[:page])
end
end
diff --git a/app/controllers/compliance_check_tasks_controller.rb b/app/controllers/compliance_check_tasks_controller.rb
deleted file mode 100644
index c2995c94d..000000000
--- a/app/controllers/compliance_check_tasks_controller.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-class ComplianceCheckTasksController < ChouetteController
- defaults :resource_class => ComplianceCheckTask
-
- respond_to :html, :only => [:new, :create]
- respond_to :js, :only => [:new, :create]
-
- belongs_to :referential
-
- def new
- begin
- new!
- rescue Ievkit::Error, Faraday::Error => error
- logger.error("Iev failure : #{error.message}")
- flash[:error] = t(error.locale_for_error)
- redirect_to referential_path(@referential)
- end
- end
-
- def create
- begin
- create! do |success, failure|
- success.html { redirect_to referential_compliance_checks_path(@referential) }
- end
- rescue Ievkit::Error, Faraday::Error => error
- logger.error("Iev failure : #{error.message}")
- flash[:error] = t(error.locale_for_error)
- redirect_to referential_path(@referential)
- end
- end
-
- def references
- references_type = params[:filter].pluralize
- references = @referential.send(references_type).where("name ilike ?", "%#{params[:q]}%").select("id, name")
- puts references.inspect
- respond_to do |format|
- format.json do
- render :json => references.collect { |child| { :id => child.id, :name => child.name } }
- end
- end
- end
-
- protected
-
- def build_resource
- @compliance_check_task ||= ComplianceCheckTask.new( params[:compliance_check_task] || {} )
- end
-
-
-end
diff --git a/app/controllers/compliance_checks_controller.rb b/app/controllers/compliance_checks_controller.rb
index 2d67aae98..07438cf99 100644
--- a/app/controllers/compliance_checks_controller.rb
+++ b/app/controllers/compliance_checks_controller.rb
@@ -1,87 +1,4 @@
-require 'will_paginate/array'
-
class ComplianceChecksController < ChouetteController
- defaults :resource_class => ComplianceCheck
-
- respond_to :html, :js
- respond_to :zip, :only => :export
- belongs_to :referential
-
- def index
- begin
- index! do
- build_breadcrumb :index
- end
- rescue Ievkit::Error, Faraday::Error => error
- logger.error("Iev failure : #{error.message}")
- flash[:error] = t(error.locale_for_error)
- redirect_to referential_path(@referential)
- end
- end
-
- def show
- begin
- show! do |format|
- build_breadcrumb :show
- end
- rescue Ievkit::Error, Faraday::Error => error
- logger.error("Iev failure : #{error.message}")
- flash[:error] = t(error.locale_for_error)
- redirect_to referential_path(@referential)
- end
- end
-
- def report
- resource
- build_breadcrumb :report
- end
-
- def references
- @references = referential.send(params[:type]).where("name ilike ?", "%#{params[:q]}%")
- respond_to do |format|
- format.json do
- render json: @references.collect { |child| { id: child.id, name: child.name } }
- end
- end
- end
-
- def rule_parameter_set
- begin
- @rule_parameter_set = resource.rule_parameter_set
- build_breadcrumb :rule_parameter_set
- render "rule_parameter_sets/show"
- rescue Ievkit::Error, Faraday::Error => error
- logger.error("Iev failure : #{error.message}")
- flash[:error] = t(error.locale_for_error)
- redirect_to referential_path(@referential)
- end
- end
-
- def export
- respond_to do |format|
- format.zip { send_file ComplianceCheckExport.new(resource, @referential.id, request).export, :type => :zip }
- end
- end
-
- protected
-
- alias_method :compliance_check, :resource
-
- def compliance_check_service
- ComplianceCheckService.new(@referential)
- end
-
- def resource
- @compliance_check ||= compliance_check_service.find(params[:id])
- @line_items = @compliance_check.report.line_items
- if @line_items.size > 500
- @line_items = @line_items.paginate(page: params[:page], per_page: 20)
- end
- @compliance_check
- end
- def collection
- @compliance_checks ||= compliance_check_service.all.sort_by{ |compliance_check| compliance_check.created_at }.reverse.paginate(:page => params[:page])
- end
end
diff --git a/app/controllers/import_messages_controller.rb b/app/controllers/import_messages_controller.rb
new file mode 100644
index 000000000..4ad398cbb
--- /dev/null
+++ b/app/controllers/import_messages_controller.rb
@@ -0,0 +1,26 @@
+class ImportMessagesController < BreadcrumbController
+ defaults resource_class: ImportMessage, collection_name: 'import_messages', instance_name: 'import_message'
+ respond_to :csv
+ belongs_to :import, :parent_class => Import do
+ belongs_to :import_resource, :parent_class => ImportResource
+ end
+
+
+ def index
+ index! do |format|
+ format.csv {
+ send_data ImportMessageExport.new(:import_messages => @import_messages).to_csv(:col_sep => ";") , :filename => "#{File.basename(@import_resource.name)}_#{Time.now.to_i}.csv"
+ }
+ end
+ end
+
+ protected
+ def collection
+ @import_messages ||= parent.messages
+ end
+
+ def parent
+ @import_resource ||= ImportResource.find(params[:import_resource_id])
+ end
+
+end
diff --git a/app/controllers/import_resources_controller.rb b/app/controllers/import_resources_controller.rb
new file mode 100644
index 000000000..ac3dd042e
--- /dev/null
+++ b/app/controllers/import_resources_controller.rb
@@ -0,0 +1,40 @@
+class ImportResourcesController < BreadcrumbController
+ defaults resource_class: ImportResource, collection_name: 'import_resources', instance_name: 'import_resource'
+ respond_to :html
+ belongs_to :import
+
+ def index
+ index! do |format|
+ format.html {
+ @import_resources = decorate_import_resources(@import_resources)
+ }
+
+ build_breadcrumb :index
+ end
+ end
+
+ def download
+ if params[:token] == resource.token_download
+ send_file resource.file.path
+ else
+ user_not_authorized
+ end
+ end
+
+ protected
+ def collection
+ @import_resources ||= parent.resources
+ end
+
+ private
+
+ def decorate_import_resources(import_resources)
+ ImportResourcesDecorator.decorate(
+ import_resources,
+ with: ImportResourceDecorator,
+ context: {
+ import: @import
+ }
+ )
+ end
+end
diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb
index 70c5c1a0d..97a8f91aa 100644
--- a/app/controllers/imports_controller.rb
+++ b/app/controllers/imports_controller.rb
@@ -1,17 +1,30 @@
class ImportsController < BreadcrumbController
skip_before_action :authenticate_user!, only: [:download]
defaults resource_class: Import, collection_name: 'imports', instance_name: 'import'
+ before_action :ransack_started_on_date, only: [:index]
respond_to :html
belongs_to :workbench
def show
show! do
+ @import = @import.decorate(context: {
+ workbench: @workbench
+ })
+
build_breadcrumb :show
end
end
def index
- index! do
+ index! do |format|
+ format.html {
+ if collection.out_of_bounds?
+ redirect_to params.merge(:page => 1)
+ end
+
+ @imports = decorate_imports(@imports)
+ }
+
build_breadcrumb :index
end
end
@@ -22,10 +35,6 @@ class ImportsController < BreadcrumbController
end
end
- def create
- create! { workbench_import_path(parent, resource) }
- end
-
def download
if params[:token] == resource.token_download
send_file resource.file.path
@@ -34,16 +43,60 @@ class ImportsController < BreadcrumbController
end
end
+ protected
+ def collection
+ @q = parent.imports.where(type: "WorkbenchImport").search(params[:q])
+
+ if sort_column && sort_direction
+ @imports ||= @q.result(distinct: true).order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: 10)
+ else
+ @imports ||= @q.result(distinct: true).order(:name).paginate(page: params[:page], per_page: 10)
+ end
+ end
+
private
+ def ransack_started_on_date
+ date =[]
+ if params[:q] && !params[:q]['started_on_date(1i)'].empty?
+ ['started_on_date(1i)', 'started_on_date(2i)', 'started_on_date(3i)'].each do |key|
+ date << params[:q][key].to_i
+ params[:q].delete(key)
+ end
+ params[:q]['started_on_date'] = DateTime.new(*date) rescue nil
+ end
+ end
+
def build_resource
- # Manage only NetexImports for the moment
- @import ||= NetexImport.new(*resource_params) do |import|
+ @import ||= WorkbenchImport.new(*resource_params) do |import|
import.workbench = parent
+ import.creator = current_user.name
end
end
def import_params
- params.require(:import).permit(:name, :file, :type, :referential_id)
+ params.require(:import).permit(
+ :name,
+ :file,
+ :type,
+ :referential_id
+ )
+ end
+
+ def sort_column
+ parent.imports.column_names.include?(params[:sort]) ? params[:sort] : 'name'
+ end
+ def sort_direction
+ %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
+ end
+
+ def decorate_imports(imports)
+ ModelDecorator.decorate(
+ imports,
+ with: ImportDecorator,
+ context: {
+ workbench: @workbench
+ }
+ )
end
end
diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb
index afd376092..c8984076a 100644
--- a/app/controllers/referentials_controller.rb
+++ b/app/controllers/referentials_controller.rb
@@ -7,17 +7,19 @@ class ReferentialsController < BreadcrumbController
respond_to :js, :only => :show
def new
- if params[:from]
- source_referential = Referential.find(params[:from])
- @referential = Referential.new_from(source_referential)
+ new! do
+ build_referenial
end
+ end
- new! do
- @referential.data_format = current_organisation.data_format
- @referential.workbench_id ||= params[:workbench_id]
+ def create
+ create! do |format|
+ build_referenial
- if @referential.in_workbench?
- @referential.init_metadatas default_date_range: Range.new(Date.today, Date.today.advance(months: 1))
+ if !!@referential.created_from_id
+ format.html { redirect_to workbench_path(@referential.workbench) }
+ else
+ build_breadcrumb :new
end
end
end
@@ -25,7 +27,7 @@ class ReferentialsController < BreadcrumbController
def show
resource.switch
show! do |format|
- @referential = @referential.decorate
+ @referential = @referential.decorate(context: { current_workbench_id: params[:current_workbench_id] } )
@reflines = lines_collection.paginate(page: params[:page], per_page: 10)
@reflines = ModelDecorator.decorate(
@reflines,
@@ -123,6 +125,21 @@ class ReferentialsController < BreadcrumbController
super
end
+ def build_referenial
+ if params[:from]
+ source_referential = Referential.find(params[:from])
+ @referential = Referential.new_from(source_referential, current_functional_scope)
+ @referential.workbench_id = params[:current_workbench_id]
+ end
+
+ @referential.data_format = current_organisation.data_format
+ @referential.workbench_id ||= params[:workbench_id]
+
+ if @referential.in_workbench?
+ @referential.init_metadatas default_date_range: Range.new(Date.today, Date.today.advance(months: 1))
+ end
+ end
+
private
def sort_column
sortable_columns = Chouette::Line.column_names + ['networks.name', 'companies.name']
diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb
index 19af28a98..54ddb8be1 100644
--- a/app/controllers/workbenches_controller.rb
+++ b/app/controllers/workbenches_controller.rb
@@ -20,8 +20,13 @@ class WorkbenchesController < BreadcrumbController
@q_for_form = scope.ransack(params[:q])
@q_for_result = scope.ransack(ransack_params)
@wbench_refs = sort_result(@q_for_result.result).paginate(page: params[:page], per_page: 30)
- @wbench_refs = ModelDecorator.decorate(@wbench_refs, with: ReferentialDecorator)
-
+ @wbench_refs = ModelDecorator.decorate(
+ @wbench_refs,
+ with: ReferentialDecorator,
+ context: {
+ current_workbench_id: params[:id]
+ }
+ )
show! do
build_breadcrumb :show
end
diff --git a/app/decorators/api_key_decorator.rb b/app/decorators/api_key_decorator.rb
new file mode 100644
index 000000000..def3a6a01
--- /dev/null
+++ b/app/decorators/api_key_decorator.rb
@@ -0,0 +1,30 @@
+class ApiKeyDecorator < Draper::Decorator
+ decorates Api::V1::ApiKey
+ delegate_all
+
+
+ def action_links
+ links = []
+
+ links << Link.new(
+ content: h.t('api_keys.actions.show'),
+ href: h.organisation_api_key_path(object),
+ )
+
+ links << Link.new(
+ content: h.t('api_keys.actions.edit'),
+ href: h.edit_organisation_api_key_path(object),
+ )
+
+ if h.policy(object).destroy?
+ links << Link.new(
+ content: h.destroy_link_content,
+ href: h.organisation_api_key_path(object),
+ method: :delete,
+ data: { confirm: h.t('api_keys.actions.destroy_confirm') }
+ )
+ end
+
+ links
+ end
+end
diff --git a/app/decorators/import_decorator.rb b/app/decorators/import_decorator.rb
new file mode 100644
index 000000000..d63d723cd
--- /dev/null
+++ b/app/decorators/import_decorator.rb
@@ -0,0 +1,44 @@
+class ImportDecorator < Draper::Decorator
+ decorates Import
+
+ delegate_all
+
+ def import_status_css_class
+ cls =''
+ cls = 'overheaded-success' if object.status == 'successful'
+ cls = 'overheaded-warning' if object.status == 'warning'
+ cls = 'overheaded-danger' if %w[failed aborted canceled].include? object.status
+ cls
+ end
+
+ def action_links
+ links = []
+
+ links << Link.new(
+ content: h.t('imports.actions.show'),
+ href: h.workbench_import_path(
+ context[:workbench],
+ object
+ )
+ )
+
+ links << Link.new(
+ content: h.t('imports.actions.download'),
+ href: object.file.url
+ )
+
+ # if h.policy(object).destroy?
+ links << Link.new(
+ content: h.destroy_link_content,
+ href: h.workbench_import_path(
+ context[:workbench],
+ object
+ ),
+ method: :delete,
+ data: { confirm: h.t('imports.actions.destroy_confirm') }
+ )
+
+ links
+ end
+
+end
diff --git a/app/decorators/import_resource_decorator.rb b/app/decorators/import_resource_decorator.rb
new file mode 100644
index 000000000..9bfd1f757
--- /dev/null
+++ b/app/decorators/import_resource_decorator.rb
@@ -0,0 +1,10 @@
+class ImportResourceDecorator < Draper::Decorator
+ decorates ImportResource
+
+ delegate_all
+
+ def action_links
+ links = []
+ end
+
+end
diff --git a/app/decorators/import_resources_decorator.rb b/app/decorators/import_resources_decorator.rb
new file mode 100644
index 000000000..2b1a25ef9
--- /dev/null
+++ b/app/decorators/import_resources_decorator.rb
@@ -0,0 +1,12 @@
+class ImportResourcesDecorator < ModelDecorator
+ delegate :where
+
+ def lines_imported
+ where(status: :OK, resource_type: :line).count
+ end
+
+ def lines_in_zipfile
+ where(resource_type: :line).count
+ end
+
+end
diff --git a/app/decorators/referential_decorator.rb b/app/decorators/referential_decorator.rb
index ccb47a654..dccf0052c 100644
--- a/app/decorators/referential_decorator.rb
+++ b/app/decorators/referential_decorator.rb
@@ -13,7 +13,7 @@ class ReferentialDecorator < Draper::Decorator
if policy.clone?
links << Link.new(
content: h.t('actions.clone'),
- href: h.new_referential_path(from: object.id)
+ href: h.new_referential_path(from: object.id, current_workbench_id: context[:current_workbench_id])
)
end
if policy.archive?
diff --git a/app/helpers/compliance_check_tasks_helper.rb b/app/helpers/compliance_check_tasks_helper.rb
deleted file mode 100644
index 5ba8bdc46..000000000
--- a/app/helpers/compliance_check_tasks_helper.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module ComplianceCheckTasksHelper
-
- def button_link_class( compliance_check_task )
- if compliance_check_task.any_error_severity_failure? || compliance_check_task.status == "failed"
- "btn-danger"
- else
- "btn-default"
- end
- end
-
-end
diff --git a/app/helpers/compliance_checks_helper.rb b/app/helpers/compliance_checks_helper.rb
deleted file mode 100644
index d7e42e187..000000000
--- a/app/helpers/compliance_checks_helper.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-module ComplianceChecksHelper
-
- def fields_for_compliance_check_format(form)
- begin
- render :partial => compliance_check_partial_name(form), :locals => { :form => form }
- rescue ActionView::MissingTemplate
- ""
- end
- end
-
- def compliance_check_partial_name(form)
- "fields_#{form.object.format.underscore}_compliance_check"
- end
-
- def compliance_icon( compliance_check)
- return nil unless compliance_check.compliance_check_validation_report
- compliance_check.compliance_check_validation_report.tap do |cct|
- if cct.failed? || cct.any_error_severity_failure?
- return 'icons/link_page_alert.png'
- else
- return 'icons/link_page.png'
- end
- end
- end
-
- def status_icon( compliance_check_result_status, compliance_check_result_severity )
- if compliance_check_result_status == "uncheck"
- ("<i class='fa fa-ban status_" + compliance_check_result_status + "_" + compliance_check_result_severity + "'></i>").html_safe
- elsif compliance_check_result_status == "ok"
- ("<i class='fa fa-check status_" + compliance_check_result_status + "_" + compliance_check_result_severity + "'></i>").html_safe
- else
- ("<i class='fa fa-times status_" + compliance_check_result_status + "_" + compliance_check_result_severity + "'></i>").html_safe
- end
- end
-
- def test_definition (compliance_check_result_code)
- Rails.application.config.validation_spec + I18n.locale.to_s + "/" + compliance_check_result_code +".html"
- end
-
- def object_url (referential_id, error)
- location = "/referentials/" + referential_id.to_s
- object_path = error[:source].object_path
- if object_path.first[:type] == "vehicle_journey"
- object_path.delete_at 1
- end
-
- types, identifiers = object_path.reverse.map { |resource| [ resource[:type], resource[:id] ] }.transpose
-
- method_name = (['referential'] + types + ['path']).join('_')
- identifiers.unshift referential_id
-
- return send method_name, *identifiers
- end
-
- def object_labels_hash (error)
- ### THE error HASH STRUCTURE
- # 1. error[:source]
- # 0..1 file
- # 1 filename
- # 0..1 line_number
- # 0..1 column_number
- # 0..1 objectid
- # 0..1 label
- # 0.. object_path
- # 1 type
- # 1 id
- # 0.. error[:target]
- # 0..1 error[:error_value]
- # 0..1 error[:reference_value]
- object_labels_hash = Hash.new
- object_labels_hash[:source_objectid] = error[:source].objectid if error[:source].objectid.present?
- object_labels_hash[:source_label] = error[:source].label if error[:source].label.present?
- if error[:source].file.present?
- object_labels_hash[:filename] = error[:source].file.filename
- object_labels_hash[:line_number] = error[:source].file.line_number if error[:source].file.line_number.present?
- object_labels_hash[:column_number] = error[:source].file.column_number if error[:source].file.column_number.present?
- end
-
- if error[:target].present?
- error[:target].each_with_index do |target, index|
- object_labels_hash["target_#{index}_objectid".to_sym] = target[:objectid] if target[:objectid]
- object_labels_hash["target_#{index}_label".to_sym] = target[:label] if target[:label]
- end
- end
- if error[:error_value].present?
- object_labels_hash[:error_value] = error[:error_value]
- end
- if error[:reference_value].present?
- object_labels_hash[:reference_value] = error[:reference_value]
- end
- return object_labels_hash
- end
-
-
-end
diff --git a/app/helpers/import_resources_helper.rb b/app/helpers/import_resources_helper.rb
new file mode 100644
index 000000000..3ee96eb9b
--- /dev/null
+++ b/app/helpers/import_resources_helper.rb
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+module ImportResourcesHelper
+
+ # Import statuses helper
+ def import_resource_status(status)
+ cls =''
+ cls = 'success' if status == 'OK'
+ cls = 'warning' if status == 'WARNING'
+ cls = 'danger' if status == 'ERROR'
+ cls = 'alert' if status == 'IGNORED'
+
+ content_tag :span, '', class: "fa fa-circle text-#{cls}"
+ end
+
+end
diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb
index 5f9db3fb1..1c4549e50 100644
--- a/app/helpers/imports_helper.rb
+++ b/app/helpers/imports_helper.rb
@@ -1,6 +1,24 @@
# -*- coding: utf-8 -*-
module ImportsHelper
+ # Import statuses helper
+ def import_status(status)
+ if %w[new running pending].include? status
+ content_tag :span, '', class: "fa fa-clock-o"
+ else
+ cls =''
+ cls = 'success' if status == 'successful'
+ cls = 'warning' if status == 'warning'
+ cls = 'danger' if %w[failed aborted canceled].include? status
+
+ content_tag :span, '', class: "fa fa-circle text-#{cls}"
+ end
+ end
+
+ ##############################
+ #      TO CLEAN!!!
+ ##############################
+
def fields_for_import_task_format(form)
begin
render :partial => import_partial_name(form), :locals => { :form => form }
diff --git a/app/helpers/newapplication_helper.rb b/app/helpers/newapplication_helper.rb
index ac57997d1..df19113db 100644
--- a/app/helpers/newapplication_helper.rb
+++ b/app/helpers/newapplication_helper.rb
@@ -222,7 +222,7 @@ module NewapplicationHelper
# Left part with pageicon & pagetitle & desc
left = content_tag :div, '', class: 'col-lg-9 col-md-8 col-sm-7 col-xs-7' do
picon = content_tag :div, '', class: 'page-icon' do
- content_tag :span, '', class: "fa fa-lg fa-#{pageicon}"
+ content_tag :span, '', class: "sb sb-#{pageicon}"
end
ptitle = content_tag :div, '', class: 'page-title' do
content_tag :h1, pagetitle, title: desc
diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb
index 375697bec..ec4d487c1 100644
--- a/app/helpers/table_builder_helper.rb
+++ b/app/helpers/table_builder_helper.rb
@@ -26,7 +26,10 @@ require 'table_builder_helper/url'
# ),
# TableBuilderHelper::Column.new(
# key: :name,
-# attribute: 'name'
+# attribute: 'name',
+# link_to: lambda do |company|
+# referential_company_path(@referential, company)
+# end
# ),
# TableBuilderHelper::Column.new(
# key: :phone,
@@ -42,7 +45,19 @@ require 'table_builder_helper/url'
# ),
# ],
# links: [:show, :edit],
-# cls: 'table has-search'
+# cls: 'table has-search',
+# overhead: [
+# {
+# title: 'one',
+# width: 1,
+# cls: 'toto'
+# },
+# {
+# title: 'two <span class="test">Info</span>',
+# width: 2,
+# cls: 'default'
+# }
+# ]
# )
module TableBuilderHelper
# TODO: rename this after migration from `table_builder`
@@ -65,19 +80,36 @@ module TableBuilderHelper
links: [],
# A CSS class to apply to the <table>
- cls: ''
+ cls: '',
+
+ # A set of content, over the th line...
+ overhead: []
)
content_tag :table,
- thead(collection, columns, sortable, selectable, links.any?) +
- tbody(collection, columns, selectable, links),
+ thead(collection, columns, sortable, selectable, links.any?, overhead) +
+ tbody(collection, columns, selectable, links, overhead),
class: cls
end
private
- def thead(collection, columns, sortable, selectable, has_links)
+ def thead(collection, columns, sortable, selectable, has_links, overhead)
content_tag :thead do
- content_tag :tr do
+ # Inserts overhead content if any specified
+ over_head = ''
+
+ unless overhead.empty?
+ over_head = content_tag :tr, class: 'overhead' do
+ oh_cont = []
+
+ overhead.each do |h|
+ oh_cont << content_tag(:th, raw(h[:title]), colspan: h[:width], class: h[:cls])
+ end
+ oh_cont.join.html_safe
+ end
+ end
+
+ main_head = content_tag :tr do
hcont = []
if selectable
@@ -85,25 +117,73 @@ module TableBuilderHelper
end
columns.each do |column|
- hcont << content_tag(:th, build_column_header(
- column,
- sortable,
- collection.model,
- params,
- params[:sort],
- params[:direction]
- ))
+ if overhead.empty?
+ hcont << content_tag(:th, build_column_header(
+ column,
+ sortable,
+ collection.model,
+ params,
+ params[:sort],
+ params[:direction]
+ ))
+
+ else
+ i = columns.index(column)
+
+ if overhead[i].blank?
+ if (i > 0) && (overhead[i - 1][:width] > 1)
+ clsArrayH = overhead[i - 1][:cls].split
+
+ hcont << content_tag(:th, build_column_header(
+ column,
+ sortable,
+ collection.model,
+ params,
+ params[:sort],
+ params[:direction]
+ ), class: td_cls(clsArrayH))
+
+ else
+ hcont << content_tag(:th, build_column_header(
+ column,
+ sortable,
+ collection.model,
+ params,
+ params[:sort],
+ params[:direction]
+ ))
+ end
+
+ else
+ clsArrayH = overhead[i][:cls].split
+
+ hcont << content_tag(:th, build_column_header(
+ column,
+ sortable,
+ collection.model,
+ params,
+ params[:sort],
+ params[:direction]
+ ), class: td_cls(clsArrayH))
+
+ end
+
+ end
end
# Inserts a blank column for the gear menu
- hcont << content_tag(:th, '') if has_links
+ if has_links || collection.last.try(:action_links).try(:any?)
+ hcont << content_tag(:th, '')
+ end
hcont.join.html_safe
end
+
+ (over_head + main_head).html_safe
end
end
- def tbody(collection, columns, selectable, links)
+ def tbody(collection, columns, selectable, links, overhead)
content_tag :tbody do
collection.map do |item|
@@ -120,19 +200,60 @@ module TableBuilderHelper
columns.each do |column|
value = column.value(item)
- if column_is_linkable?(column)
- # Build a link to the `item`
- polymorph_url = URL.polymorphic_url_parts(
- item,
- referential
- )
- bcont << content_tag(:td, link_to(value, polymorph_url), title: 'Voir')
+ if column.linkable?
+ path = column.link_to(item)
+ link = link_to(value, path)
+
+ if overhead.empty?
+ bcont << content_tag(:td, link, title: 'Voir')
+
+ else
+ i = columns.index(column)
+
+ if overhead[i].blank?
+ if (i > 0) && (overhead[i - 1][:width] > 1)
+ clsArrayAlt = overhead[i - 1][:cls].split
+
+ bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArrayAlt))
+
+ else
+ bcont << content_tag(:td, link, title: 'Voir')
+ end
+
+ else
+ clsArray = overhead[columns.index(column)][:cls].split
+
+ bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray))
+ end
+ end
+
else
- bcont << content_tag(:td, value)
+ if overhead.empty?
+ bcont << content_tag(:td, value)
+
+ else
+ i = columns.index(column)
+
+ if overhead[i].blank?
+ if (i > 0) && (overhead[i - 1][:width] > 1)
+ clsArrayAlt = overhead[i - 1][:cls].split
+
+ bcont << content_tag(:td, value, class: td_cls(clsArrayAlt))
+
+ else
+ bcont << content_tag(:td, value)
+ end
+
+ else
+ clsArray = overhead[i][:cls].split
+
+ bcont << content_tag(:td, value, class: td_cls(clsArray))
+ end
+ end
end
end
- if links.any?
+ if links.any? || item.try(:action_links).try(:any?)
bcont << content_tag(
:td,
build_links(item, links),
@@ -146,6 +267,14 @@ module TableBuilderHelper
end
end
+ def td_cls(a)
+ if a.include? 'full-border'
+ a.slice!(a.index('full-border'))
+
+ return a.join(' ')
+ end
+ end
+
def build_links(item, links)
trigger = content_tag(
:div,
@@ -216,10 +345,6 @@ module TableBuilderHelper
end
end
- def column_is_linkable?(column)
- column.attribute == 'name' || column.attribute == 'comment'
- end
-
def gear_menu_link(link)
content_tag(
:li,
diff --git a/app/helpers/table_builder_helper/column.rb b/app/helpers/table_builder_helper/column.rb
index 800a8282e..b4c569882 100644
--- a/app/helpers/table_builder_helper/column.rb
+++ b/app/helpers/table_builder_helper/column.rb
@@ -2,7 +2,7 @@ module TableBuilderHelper
class Column
attr_reader :key, :name, :attribute, :sortable
- def initialize(key: nil, name: '', attribute:, sortable: true)
+ def initialize(key: nil, name: '', attribute:, sortable: true, link_to: nil)
if key.nil? && name.empty?
raise ColumnMustHaveKeyOrNameError
end
@@ -11,6 +11,7 @@ module TableBuilderHelper
@name = name
@attribute = attribute
@sortable = sortable
+ @link_to = link_to
end
def value(obj)
@@ -29,6 +30,14 @@ module TableBuilderHelper
I18n.t("activerecord.attributes.#{model_key}.#{@key}")
end
+
+ def linkable?
+ !@link_to.nil?
+ end
+
+ def link_to(obj)
+ @link_to.call(obj)
+ end
end
diff --git a/app/helpers/table_builder_helper/url.rb b/app/helpers/table_builder_helper/url.rb
index 0894df0fe..f7ba703ae 100644
--- a/app/helpers/table_builder_helper/url.rb
+++ b/app/helpers/table_builder_helper/url.rb
@@ -12,7 +12,12 @@ module TableBuilderHelper
polymorph_url << item.stop_area if item.respond_to? :stop_area
polymorph_url << item if item.respond_to?(:stop_points) || item.is_a?(Chouette::TimeTable)
elsif item.respond_to? :referential
- polymorph_url << item.referential
+ if item.respond_to? :workbench
+ polymorph_url << item.workbench
+ polymorph_url << item
+ else
+ polymorph_url << item.referential
+ end
end
else
polymorph_url << item
diff --git a/app/models/api/v1/api_key.rb b/app/models/api/v1/api_key.rb
index e1a7ab5a4..767e65f3a 100644
--- a/app/models/api/v1/api_key.rb
+++ b/app/models/api/v1/api_key.rb
@@ -3,19 +3,31 @@ module Api
class ApiKey < ::ActiveRecord::Base
before_create :generate_access_token
belongs_to :referential, :class_name => '::Referential'
- validates_presence_of :referential
+ belongs_to :organisation, :class_name => '::Organisation'
+
+ validates_presence_of :organisation
class << self
def from(referential, name:)
find_or_create_by!(name: name, referential: referential)
end
+
+ def referential_from_token(token)
+ array = token.split('-')
+ if !array.first.empty? && array.size > 1
+ ::Referential.find array.first
+ end
+ end
+
def model_name
- ActiveModel::Name.new Api::V1, self.name.demodulize
+ ActiveModel::Name.new self, Api::V1, self.name.demodulize
end
- def referential_from_token(token)
+
+ def organisation_from_token(token)
array = token.split('-')
- return nil unless array.size==2
- ::Referential.find( array.first)
+ if !array[1].empty? && array.size > 1
+ ::Organisation.find array[1]
+ end
end
end
@@ -28,7 +40,7 @@ module Api
private
def generate_access_token
begin
- self.token = "#{referential_id}-#{SecureRandom.hex}"
+ self.token = "#{referential_id}-#{organisation_id}-#{SecureRandom.hex}"
end while self.class.exists?(:token => self.token)
end
end
diff --git a/app/models/chouette/access_point.rb b/app/models/chouette/access_point.rb
index 476f13c08..4a1ae8a0e 100644
--- a/app/models/chouette/access_point.rb
+++ b/app/models/chouette/access_point.rb
@@ -4,6 +4,7 @@ require 'geo_ruby'
class Chouette::AccessPoint < Chouette::ActiveRecord
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
self.primary_key = "id"
+
include StifReflexAttributesSupport
include Geokit::Mappable
include ProjectionFields
@@ -23,12 +24,15 @@ class Chouette::AccessPoint < Chouette::ActiveRecord
validates_numericality_of :longitude, :less_than_or_equal_to => 180, :greater_than_or_equal_to => -180, :allow_nil => true
validates_format_of :coordinates, :with => %r{\A *-?(0?[0-9](\.[0-9]*)?|[0-8][0-9](\.[0-9]*)?|90(\.[0]*)?) *\, *-?(0?[0-9]?[0-9](\.[0-9]*)?|1[0-7][0-9](\.[0-9]*)?|180(\.[0]*)?) *\Z}, :allow_nil => true, :allow_blank => true
-
+ before_save :coordinates_to_lat_lng
def self.nullable_attributes
[:street_name, :country_code, :comment, :long_lat_type, :zip_code, :city_name]
end
- before_save :coordinates_to_lat_lng
+
+ def referential
+ @referential ||= Referential.where(:slug => Apartment::Tenant.current).first!
+ end
def referential
@referential ||= Referential.where(:slug => Apartment::Tenant.current).first!
diff --git a/app/models/chouette/active_record.rb b/app/models/chouette/active_record.rb
index 1862319af..e12f30266 100644
--- a/app/models/chouette/active_record.rb
+++ b/app/models/chouette/active_record.rb
@@ -2,10 +2,8 @@
require 'deep_cloneable'
module Chouette
class ActiveRecord < ::ActiveRecord::Base
-
self.abstract_class = true
-
- before_save :nil_if_blank
+ before_save :nil_if_blank, :set_data_source_ref
# to be overridden to set nullable attrs when empty
def self.nullable_attributes
@@ -16,17 +14,22 @@ module Chouette
self.class.nullable_attributes.each { |attr| self[attr] = nil if self[attr].blank? }
end
-
def human_attribute_name(*args)
self.class.human_attribute_name(*args)
end
+ def set_data_source_ref
+ if self.respond_to?(:data_source_ref)
+ self.data_source_ref ||= 'DATASOURCEREF_EDITION_BOIV'
+ end
+ end
+
# TODO: Can we remove this?
# class << self
# alias_method :create_reflection_without_chouette_naming, :create_reflection
# def create_reflection(macro, name, options, active_record)
- # options =
+ # options =
# Reflection.new(macro, name, options, active_record).options_with_default
# create_reflection_without_chouette_naming(macro, name, options, active_record)
diff --git a/app/models/chouette/company.rb b/app/models/chouette/company.rb
index 7b96e875e..a472020e1 100644
--- a/app/models/chouette/company.rb
+++ b/app/models/chouette/company.rb
@@ -1,6 +1,6 @@
class Chouette::Company < Chouette::ActiveRecord
include CompanyRestrictions
- include DefaultNetexAttributesSupport
+ include StifCodifligneAttributesSupport
include LineReferentialSupport
has_many :lines
diff --git a/app/models/chouette/group_of_line.rb b/app/models/chouette/group_of_line.rb
index d954c6699..a987d6311 100644
--- a/app/models/chouette/group_of_line.rb
+++ b/app/models/chouette/group_of_line.rb
@@ -1,5 +1,5 @@
class Chouette::GroupOfLine < Chouette::ActiveRecord
- include DefaultNetexAttributesSupport
+ include StifCodifligneAttributesSupport
include GroupOfLineRestrictions
include LineReferentialSupport
diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb
index fa5fba26d..2b62d5c7f 100644
--- a/app/models/chouette/journey_pattern.rb
+++ b/app/models/chouette/journey_pattern.rb
@@ -21,6 +21,11 @@ class Chouette::JourneyPattern < Chouette::TridentActiveRecord
attr_accessor :control_checked
after_update :control_route_sections, :unless => "control_checked"
+
+ def local_id
+ "IBOO-#{self.try(:route).try(:line).try(:objectid).try(:local_id)}-#{self.referential.id}-#{self.id}"
+ end
+
def checksum_attributes
values = self.slice(*['name', 'published_name', 'registration_number']).values
values << self.stop_points.map(&:stop_area).map(&:user_objectid)
diff --git a/app/models/chouette/network.rb b/app/models/chouette/network.rb
index 690c39344..8df205789 100644
--- a/app/models/chouette/network.rb
+++ b/app/models/chouette/network.rb
@@ -1,5 +1,5 @@
class Chouette::Network < Chouette::ActiveRecord
- include DefaultNetexAttributesSupport
+ include StifCodifligneAttributesSupport
include NetworkRestrictions
include LineReferentialSupport
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
diff --git a/app/models/chouette/route.rb b/app/models/chouette/route.rb
index cab877dc7..8b04b95d0 100644
--- a/app/models/chouette/route.rb
+++ b/app/models/chouette/route.rb
@@ -99,6 +99,10 @@ class Chouette::Route < Chouette::TridentActiveRecord
end
end
+ def local_id
+ "IBOO-#{self.line.objectid.local_id}-#{self.referential.id}-#{self.id}"
+ end
+
def geometry_presenter
Chouette::Geometry::RoutePresenter.new self
end
diff --git a/app/models/chouette/routing_constraint_zone.rb b/app/models/chouette/routing_constraint_zone.rb
index 9931748b2..21efa2539 100644
--- a/app/models/chouette/routing_constraint_zone.rb
+++ b/app/models/chouette/routing_constraint_zone.rb
@@ -8,6 +8,10 @@ class Chouette::RoutingConstraintZone < Chouette::TridentActiveRecord
# validates :stop_point_ids, length: { minimum: 2, too_short: I18n.t('activerecord.errors.models.routing_constraint_zone.attributes.stop_points.not_enough_stop_points') }
validate :stop_points_belong_to_route, :not_all_stop_points_selected
+ def local_id
+ "IBOO-#{self.route.line.objectid.local_id}-#{self.route.objectid.local_id}-#{self.referential.id}-#{self.id}"
+ end
+
scope :order_by_stop_points_count, ->(direction) do
order("array_length(stop_point_ids, 1) #{direction}")
end
diff --git a/app/models/chouette/stif_netex_objectid.rb b/app/models/chouette/stif_netex_objectid.rb
new file mode 100644
index 000000000..3b11691d9
--- /dev/null
+++ b/app/models/chouette/stif_netex_objectid.rb
@@ -0,0 +1,38 @@
+class Chouette::StifNetexObjectid < String
+ def valid?
+ parts.present?
+ end
+
+ @@format = /^([A-Za-z_]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/
+ cattr_reader :format
+
+ def parts
+ match(format).try(:captures)
+ end
+
+ def provider_id
+ parts.try(:first)
+ end
+
+ def object_type
+ parts.try(:second)
+ end
+
+ def local_id
+ parts.try(:third)
+ end
+
+ def boiv_id
+ parts.try(:fourth)
+ end
+
+ def self.create(provider_id, object_type, local_id, boiv_id)
+ new [provider_id, object_type, local_id, boiv_id].join(":")
+ end
+
+ def self.new(string)
+ string ||= ""
+ self === string ? string : super
+ end
+
+end
diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb
index 97d2e7556..8821a5201 100644
--- a/app/models/chouette/time_table.rb
+++ b/app/models/chouette/time_table.rb
@@ -22,11 +22,19 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
belongs_to :created_from, class_name: 'Chouette::TimeTable'
scope :overlapping, -> (date_start, date_end) do
- joins(:periods).where('(period_start, period_end) OVERLAPS (?, ?)', date_start, date_end)
+ joins("
+ LEFT JOIN time_table_periods ON time_tables.id = time_table_periods.time_table_id
+ LEFT JOIN time_table_dates ON time_tables.id = time_table_dates.time_table_id
+ ")
+ .where("(time_table_periods.period_start <= :end AND time_table_periods.period_end >= :start) OR (time_table_dates.date BETWEEN :start AND :end)", {start: date_start, end: date_end})
end
after_save :save_shortcuts
+ def local_id
+ "IBOO-#{self.referential.id}-#{self.id}"
+ end
+
def checksum_attributes
[].tap do |attrs|
attrs << self.int_day_types
@@ -487,7 +495,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def merge!(another_tt)
transaction do
days = [].tap do |array|
- array.push(*self.included_days_in_dates_and_periods, *another_tt.effective_days)
+ array.push(*self.effective_days, *another_tt.effective_days)
array.uniq!
end
@@ -516,7 +524,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def intersect!(another_tt)
transaction do
days = [].tap do |array|
- array.push(*self.included_days_in_dates_and_periods)
+ array.push(*self.effective_days)
array.delete_if {|day| !another_tt.effective_days.include?(day) }
array.uniq!
end
@@ -536,7 +544,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def disjoin!(another_tt)
transaction do
days = [].tap do |array|
- array.push(*self.included_days_in_dates_and_periods)
+ array.push(*self.effective_days)
array.delete_if {|day| another_tt.effective_days.include?(day) }
array.uniq!
end
@@ -553,8 +561,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
end
def duplicate
- tt = self.deep_clone :include => [:periods, :dates], :except => :object_version
- tt.uniq_objectid
+ tt = self.deep_clone :include => [:periods, :dates], :except => [:object_version, :objectid]
tt.tag_list.add(*self.tag_list) unless self.tag_list.empty?
tt.created_from = self
tt.comment = I18n.t("activerecord.copy", :name => self.comment)
diff --git a/app/models/chouette/trident_active_record.rb b/app/models/chouette/trident_active_record.rb
index c1bc0172b..e8223e3d6 100644
--- a/app/models/chouette/trident_active_record.rb
+++ b/app/models/chouette/trident_active_record.rb
@@ -1,5 +1,5 @@
class Chouette::TridentActiveRecord < Chouette::ActiveRecord
- include DefaultAttributesSupport
+ include StifNetexAttributesSupport
self.abstract_class = true
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index d5ca58959..e60afef6e 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -56,6 +56,10 @@ module Chouette
end
end
+ def local_id
+ "IBOO-#{self.route.line.objectid.local_id}-#{self.referential.id}-#{self.id}"
+ end
+
def checksum_attributes
[].tap do |attrs|
attrs << self.published_journey_name
diff --git a/app/models/compliance_check.rb b/app/models/compliance_check.rb
index d3e4054a6..a9dbc4211 100644
--- a/app/models/compliance_check.rb
+++ b/app/models/compliance_check.rb
@@ -1,58 +1,3 @@
class ComplianceCheck
- include JobConcern
- def initialize( response )
- @datas = response
- end
-
- def report?
- links["action_report"].present?
- end
-
- def report
- Rails.cache.fetch("#{cache_key}/action_report", expires_in: cache_expiration) do
- if report_path = links["action_report"]
- ComplianceCheckReport.new Ievkit.get(report_path)
- end
- end
- end
-
- def compliance_check_validation_report?
- links["validation_report"].present?
- end
-
- def compliance_check_validation_report
- Rails.cache.fetch("#{cache_key}/validation_report", expires_in: cache_expiration) do
- if report_path = links["validation_report"]
- ComplianceCheckResult.new Ievkit.get(report_path)
- end
- end
- end
-
- def rule_parameter_set?
- links["validation_params"].present?
- end
-
- def rule_parameter_set
- Rails.cache.fetch("#{cache_key}/validation_params", expires_in: cache_expiration) do
- if rule_parameter_set_path = links["validation_params"]
- response = Ievkit.get(rule_parameter_set_path)
- RuleParameterSet.new(name: '', compliance_check: self).tap do |rps|
- rps.parameters = response.validation
- end
- end
- end
- end
-
- def destroy
- if delete_path = links["delete"]
- Ievkit.delete(delete_path)
- elsif cancel_path = links["cancel"]
- Ievkit.delete(cancel_path)
- end
- end
-
- def format
- datas.type
- end
end
diff --git a/app/models/compliance_check_export.rb b/app/models/compliance_check_export.rb
deleted file mode 100644
index 95abb3b27..000000000
--- a/app/models/compliance_check_export.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'tempfile'
-
-class ComplianceCheckExport
- include ERB::Util
- include ComplianceChecksHelper
-
- require 'zip'
-
- attr_accessor :template, :detailed_errors_template, :request
- attr_reader :compliance_check
-
- def initialize(compliance_check, referential_id, request)
- @request = request
- @compliance_check = compliance_check
- @referential_id = referential_id
- @template = File.open('app/views/compliance_checks/summary_errors_index.csv.erb' ) { |f| f.read }
- @detailed_errors_template = File.open('app/views/compliance_checks/detailed_errors_index.csv.erb' ) { |f| f.read }
- end
-
- def export
- begin
- Dir.mktmpdir("#{I18n.t('compliance_check_results.file.zip_name_prefix')}_#{@referential_id}_#{@compliance_check.id}_", Dir.tmpdir) { |temp_dir|
-
- File.open(temp_dir + "/#{I18n.t('compliance_check_results.file.summary_errors_file_prefix')}" , "a:utf-8") do |f|
- f.write("\ufeff")
- f.write(render)
- f.flush
- end
-
- File.open(temp_dir + "/#{I18n.t('compliance_check_results.file.detailed_errors_file_prefix')}" , "a:utf-8") do |f|
- f.write("\ufeff")
- f.write(detailed_errors_render)
- f.flush
- end
-
- zip_file = Tempfile.new(["#{I18n.t('compliance_check_results.file.zip_name_prefix')}_#{@referential_id}_#{@compliance_check.id}_", ".zip"])
-
- ::Zip::File.open(zip_file.path, ::Zip::File::CREATE) do |zipfile|
- Dir[File.join(temp_dir, '*.csv')].each do |f|
- zipfile.add(File.basename(f), f)
- end
- end
- return zip_file
- }
- end
- end
-
- def render()
- ERB.new(@template).result(binding)
- end
-
- def detailed_errors_render()
- ERB.new(@detailed_errors_template).result(binding)
- end
-
-end
diff --git a/app/models/compliance_check_report.rb b/app/models/compliance_check_report.rb
deleted file mode 100644
index 94deb8cc9..000000000
--- a/app/models/compliance_check_report.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-class ComplianceCheckReport
- include ReportConcern
-
- def initialize( response )
- @datas = response.action_report
- end
-
-end
-
diff --git a/app/models/compliance_check_result.rb b/app/models/compliance_check_result.rb
index cd956a021..06f8649f5 100644
--- a/app/models/compliance_check_result.rb
+++ b/app/models/compliance_check_result.rb
@@ -1,76 +1,3 @@
class ComplianceCheckResult
- extend ActiveModel::Naming
- extend ActiveModel::Translation
- include ActiveModel::Model
-
- attr_accessor :datas
-
- def initialize(response)
- @datas = response.validation_report
- end
-
- def tests?
- datas.tests?
- end
-
- def ok_error
- all('ok', 'error')
- end
-
- def nok_error
- all('nok', 'error')
- end
-
- def na_error
- all('uncheck', 'error')
- end
-
- def ok_warning
- all('ok', 'warning')
- end
-
- def nok_warning
- all('nok', 'warning')
- end
-
- def na_warning
- all('uncheck', 'warning')
- end
-
- def all(status, severity)
- tests? ? tests.select { |test| test.result == status.downcase && test.severity == severity.downcase } : []
- end
-
- def tests
- @tests ||= tests? ? datas.tests.map{ |test| Test.new(test) } : []
- end
-
- class Test
- attr_reader :options
-
- def initialize( options )
- @options = options
- end
-
- def test_id
- options.test_id if options.test_id?
- end
-
- def severity
- options.severity.downcase if options.severity?
- end
-
- def result
- options.result.downcase if options.result?
- end
-
- def errors
- options.errors if options.errors?
- end
-
- def error_count
- options.error_count if options.error_count?
- end
- end
end
diff --git a/app/models/compliance_check_service.rb b/app/models/compliance_check_service.rb
deleted file mode 100644
index c27f36894..000000000
--- a/app/models/compliance_check_service.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-class ComplianceCheckService
-
- attr_reader :referential
-
- def initialize(referential)
- @referential = referential
- end
-
- # Find a validation whith this id
- def find(id)
- ComplianceCheck.new(Ievkit.scheduled_job(referential.slug, id, { :action => "validator" }))
- end
-
- # Find all validations
- def all
- [].tap do |jobs|
- Ievkit.jobs(referential.slug, { :action => "validator" }).each do |job|
- jobs << ComplianceCheck.new(job)
- end
- end
- end
-
-end
diff --git a/app/models/compliance_check_task.rb b/app/models/compliance_check_task.rb
deleted file mode 100644
index da0508cbf..000000000
--- a/app/models/compliance_check_task.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-class ComplianceCheckTask
- extend Enumerize
- extend ActiveModel::Naming
- extend ActiveModel::Translation
- extend ActiveModel::Callbacks
- include ActiveModel::Validations
- include ActiveModel::Conversion
-
- enumerize :references_type, in: %w( network line company group_of_line )
- attr_accessor :rule_parameter_set_id, :referential_id, :user_id, :user_name, :name, :references_type, :reference_ids
-
- validates_presence_of :referential_id, :user_id, :user_name, :name
-
- def initialize( params = {} )
- params.each {|k,v| send("#{k}=",v)}
- end
-
- def referential
- Referential.find(referential_id)
- end
-
- def organisation
- referential.organisation
- end
-
- def rule_parameter_set
- organisation.rule_parameter_sets.find(rule_parameter_set_id) if rule_parameter_set_id.present?
- end
-
- def save
- if valid?
- # Call Iev Server
- begin
- Ievkit.create_job( referential.slug, "validator", "", {
- :file1 => params_io,
- } )
- rescue Exception => exception
- raise exception
- end
- true
- else
- false
- end
- end
-
- def self.references_types
- self.references_type.values
- end
-
- def params
- {}.tap do |h|
- h["parameters"] = validation_params ? action_params.merge(validation_params) : action_params
- end
- end
-
- def action_params
- {
- "validate" => {
- "name" => name,
- "references_type" => references_type,
- "reference_ids" => reference_ids,
- "user_name" => user_name,
- "organisation_name" => organisation.name,
- "referential_name" => referential.name,
- }
-
- }
- end
-
- def validation_params
- {
- "validation" => rule_parameter_set.parameters
- } if rule_parameter_set.present?
- end
-
- def self.data_formats
- self.data_format.values
- end
-
- def params_io
- file = StringIO.new( params.to_json )
- Faraday::UploadIO.new(file, "application/json", "parameters.json")
- end
-
- def transport_data_io
- file = File.new(saved_resources_path, "r")
- if file_extname == ".zip"
- Faraday::UploadIO.new(file, "application/zip", original_filename )
- elsif file_extname == ".xml"
- Faraday::UploadIO.new(file, "application/xml", original_filename )
- end
- end
-
- def save_resources
- FileUtils.mkdir_p root
- FileUtils.cp resources.path, saved_resources_path
- end
-
- def delete_resources
- FileUtils.rm saved_resources_path if File.exists? saved_resources_path
- end
-
- def original_filename
- resources.original_filename
- end
-
- def file_extname
- File.extname(resources.original_filename)
- end
-
- def saved_resources_path
- "#{root}/#{Time.now.to_i}#{file_extname}"
- end
-end
diff --git a/app/models/concerns/error_format.rb b/app/models/concerns/error_format.rb
new file mode 100644
index 000000000..158edb6e4
--- /dev/null
+++ b/app/models/concerns/error_format.rb
@@ -0,0 +1,29 @@
+# TODO: This module should be moved out of concerns to somewhere that makes
+# more sense.
+
+module ErrorFormat extend self
+
+ def details error_object
+ error_object.errors.messages.inject({}) do |hash, error|
+ hash.merge(partial(:detail, error_object, error).call)
+ end
+ end
+
+ private
+
+ def detail error_object, error
+ {
+ error.first => {
+ error: error.last.first,
+ value: error_object[error.first]
+ }
+ }
+ end
+
+ def partial name, *partial_args
+ -> *lazy_args do
+ send(name, *(partial_args + lazy_args))
+ end
+ end
+
+end
diff --git a/app/models/concerns/line_referential_support.rb b/app/models/concerns/line_referential_support.rb
index 4ad437fed..406730ddb 100644
--- a/app/models/concerns/line_referential_support.rb
+++ b/app/models/concerns/line_referential_support.rb
@@ -3,18 +3,10 @@ module LineReferentialSupport
included do
belongs_to :line_referential
- # validates_presence_of :line_referential_id
-
alias_method :referential, :line_referential
end
def hub_restricted?
false
end
-
- def prefix
- # FIXME #825
- "dummy"
- end
-
end
diff --git a/app/models/concerns/report_concern.rb b/app/models/concerns/report_concern.rb
deleted file mode 100644
index f195f8f36..000000000
--- a/app/models/concerns/report_concern.rb
+++ /dev/null
@@ -1,170 +0,0 @@
-module ReportConcern
- extend ActiveSupport::Concern
- extend ActiveModel::Naming
- extend ActiveModel::Translation
- include ActiveModel::Model
-
- included do
- attr_reader :datas
- end
-
- module ClassMethods
- end
-
- delegate :progression?, :progression, :zip_file, :stats, to: :datas
-
- def failure_code?
- datas.result == "NOK" && datas.failure?
- end
-
- def failure_code
- datas.failure.code.downcase if failure_code?
- end
-
- def percentage(a, b)
- (a.to_f / b.to_f * 100).round(0)
- end
-
- def level_progress
- percentage( progression.current_step, progression.steps_count) if progression?
- end
-
- def last_step
- datas.progression.steps.last if progression?
- end
-
- def current_step
- datas.progression.steps[ progression.current_step - 1]
- end
-
- def step_progress
- percentage( current_step.realized, current_step.total )
- end
-
- def step_progress_name
- return last_step.step if progression.current_step == progression.steps_count
-
- current_step.step
- end
-
- def files
- @files ||= datas.files || []
- end
-
- def error_files
- files.select{ |file| file[:status] == "ERROR"}
- end
-
- def ignored_files
- files.select{ |file| file[:status] == "IGNORED"}
- end
-
- def ok_files
- files.select{ |file| file[:status] == "OK"}
- end
-
- def line_items
- @line_items ||= [].tap do |line_items|
- datas.lines.each do |line|
- line_items << LineItem.new(line)
- end if datas.lines?
- end
- end
-
- def saved_lines
- line_items.map(&:status).count(true)
- end
-
- def unsaved_lines
- line_items.map(&:status).count(false)
- end
-
- def lines
- stats.present? ? stats.line_count : 0
- end
-
- def routes
- stats.present? ? stats.route_count : 0
- end
-
- def connection_links
- stats.present? ? stats.connection_link_count : 0
- end
-
- def time_tables
- stats.present? ? stats.time_table_count : 0
- end
-
- def stop_areas
- stats.present? ? stats.stop_area_count : 0
- end
-
- def access_points
- stats.present? ? stats.access_point_count : 0
- end
-
- def vehicle_journeys
- stats.present? ? stats.vehicle_journey_count : 0
- end
-
- def journey_patterns
- stats.present? ? stats.journey_pattern_count : 0
- end
-
- class LineItem
- attr_reader :options
-
- def initialize( options )
- @options = options
- end
-
- def name
- @name ||= options.name if options.name?
- end
-
- def stats
- @stats ||= options.stats if options.stats?
- end
-
- def status
- @status ||= if options.status?
- if %w{ok warning}.include? options.status.downcase
- true
- else
- false
- end
- else
- false
- end
- end
-
- def routes
- stats ? stats.route_count : 0
- end
-
- def connection_links
- stats ? stats.connection_link_count : 0
- end
-
- def time_tables
- stats ? stats.time_table_count : 0
- end
-
- def stop_areas
- stats ? stats.stop_area_count : 0
- end
-
- def access_points
- stats ? stats.access_point_count : 0
- end
-
- def vehicle_journeys
- stats ? stats.vehicle_journey_count : 0
- end
-
- def journey_patterns
- stats ? stats.journey_pattern_count : 0
- end
-
- end
-end
diff --git a/app/models/concerns/stif_netex_attributes_support.rb b/app/models/concerns/stif_netex_attributes_support.rb
new file mode 100644
index 000000000..795872755
--- /dev/null
+++ b/app/models/concerns/stif_netex_attributes_support.rb
@@ -0,0 +1,58 @@
+module StifNetexAttributesSupport
+ extend ActiveSupport::Concern
+
+ included do
+ validates_numericality_of :object_version
+ validates :objectid, uniqueness: true, presence: true
+ validate :objectid_format_compliance
+
+ after_save :build_objectid
+ before_validation :default_values, on: :create
+ end
+
+ module ClassMethods
+ def object_id_key
+ model_name
+ end
+
+ def model_name
+ ActiveModel::Name.new self, Chouette, self.name.demodulize
+ end
+ end
+
+ def objectid_format_compliance
+ errors.add :objectid, I18n.t("activerecord.errors.models.trident.invalid_object_id") if !objectid.valid?
+ end
+
+ def local_id
+ "IBOO-#{self.referential.id}-#{self.id}"
+ end
+
+ def build_objectid
+ if objectid.include? ':__pending_id__'
+ self.objectid = Chouette::StifNetexObjectid.create(self.provider_id, self.model_name, self.local_id, self.boiv_id)
+ self.save
+ end
+ end
+
+ def default_values
+ self.object_version ||= 1
+
+ if self.objectid.to_s.empty?
+ local_id = "__pending_id__#{rand(50)+ rand(50)}"
+ self.objectid = Chouette::StifNetexObjectid.create(self.provider_id, self.model_name, local_id, self.boiv_id)
+ end
+ end
+
+ def objectid
+ Chouette::StifNetexObjectid.new read_attribute(:objectid)
+ end
+
+ def provider_id
+ self.referential.workbench.organisation.name.parameterize
+ end
+
+ def boiv_id
+ 'LOC'
+ end
+end
diff --git a/app/models/concerns/stop_area_referential_support.rb b/app/models/concerns/stop_area_referential_support.rb
index 5a01ef57e..aa59cbd35 100644
--- a/app/models/concerns/stop_area_referential_support.rb
+++ b/app/models/concerns/stop_area_referential_support.rb
@@ -3,17 +3,10 @@ module StopAreaReferentialSupport
included do
belongs_to :stop_area_referential
- # validates_presence_of :stop_area_referential_id
-
alias_method :referential, :stop_area_referential
end
def hub_restricted?
false
end
-
- def prefix
- # FIXME #825
- "dummy"
- end
end
diff --git a/app/models/data_format_enumerations.rb b/app/models/data_format_enumerations.rb
index 94c39e152..787ab6cca 100644
--- a/app/models/data_format_enumerations.rb
+++ b/app/models/data_format_enumerations.rb
@@ -1,6 +1,6 @@
module DataFormatEnumerations
extend Enumerize
extend ActiveModel::Naming
-
- enumerize :data_format, in: %w[neptune netex gtfs hub], default: "neptune"
+
+ enumerize :data_format, in: %w[neptune netex gtfs hub], default: "netex"
end
diff --git a/app/models/export_report.rb b/app/models/export_report.rb
index ef54f40ea..3c0788106 100644
--- a/app/models/export_report.rb
+++ b/app/models/export_report.rb
@@ -1,9 +1,8 @@
class ExportReport
- include ReportConcern
+ #include ReportConcern
def initialize( response )
@datas = response.action_report
end
-
-end
+end
diff --git a/app/models/import.rb b/app/models/import.rb
index f8702c115..55d74c13c 100644
--- a/app/models/import.rb
+++ b/app/models/import.rb
@@ -5,14 +5,32 @@ class Import < ActiveRecord::Base
belongs_to :parent, polymorphic: true
+ has_many :messages, class_name: "ImportMessage", dependent: :destroy
+ has_many :resources, class_name: "ImportResource", dependent: :destroy
+ has_many :children, foreign_key: :parent_id, class_name: "Import", dependent: :destroy
+
+ scope :started_on_date, ->(date) { where('started_at BETWEEN ? AND ?', date.beginning_of_day, date.end_of_day) }
+
extend Enumerize
- enumerize :status, in: %i(new pending successful failed running aborted canceled)
+ enumerize :status, in: %i(new pending successful warning failed running aborted canceled), scope: true, default: :new
validates :file, presence: true
- validates_presence_of :referential, :workbench
+ validates_presence_of :workbench, :creator
before_create :initialize_fields
+ def self.ransackable_scopes(auth_object = nil)
+ [:started_on_date]
+ end
+
+ def self.model_name
+ ActiveModel::Name.new Import, Import, "Import"
+ end
+
+ def children_succeedeed
+ children.with_status(:successful).count
+ end
+
def self.failing_statuses
symbols_with_indifferent_access(%i(failed aborted canceled))
end
@@ -22,29 +40,61 @@ class Import < ActiveRecord::Base
end
def notify_parent
- parent.child_change(self)
+ parent.child_change
update(notified_parent_at: DateTime.now)
end
- def child_change(child)
+ def child_change
return if self.class.finished_statuses.include?(status)
- if self.class.failing_statuses.include?(child.status)
- return update(status: 'failed')
+ update_status
+ update_referentials
+ end
+
+ def update_status
+ status_count = children.group(:status).count
+ children_finished_count = children_failed_count = children_count = 0
+
+ status_count.each do |status, count|
+ if self.class.failing_statuses.include?(status)
+ children_failed_count += count
+ end
+ if self.class.finished_statuses.include?(status)
+ children_finished_count += count
+ end
+ children_count += count
+ end
+
+ attributes = {
+ current_step: children_finished_count
+ }
+
+ status =
+ if children_failed_count > 0
+ 'failed'
+ elsif status_count['successful'] == children_count
+ 'successful'
+ end
+
+ if self.class.finished_statuses.include?(status)
+ attributes[:ended_at] = Time.now
end
- update(status: 'successful') if ready?
+ update attributes.merge(status: status)
end
- def ready?
- current_step == total_steps
+ def update_referentials
+ return unless self.class.finished_statuses.include?(status)
+
+ children.each do |import|
+ import.referential.update(ready: true) if import.referential
+ end
end
private
def initialize_fields
self.token_download = SecureRandom.urlsafe_base64
- self.status = Import.status.new
end
def self.symbols_with_indifferent_access(array)
diff --git a/app/models/import_message_export.rb b/app/models/import_message_export.rb
new file mode 100644
index 000000000..88d0f27e2
--- /dev/null
+++ b/app/models/import_message_export.rb
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+require "csv"
+require "zip"
+
+class ImportMessageExport
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+ extend ActiveModel::Naming
+
+ attr_accessor :import_messages
+
+ def initialize(attributes = {})
+ attributes.each { |name, value| send("#{name}=", value) }
+ end
+
+ def persisted?
+ false
+ end
+
+ def label(name)
+ I18n.t "vehicle_journey_exports.label.#{name}"
+ end
+
+ def column_names
+ ["criticity", "message key", "message"]
+ end
+
+ def to_csv(options = {})
+ CSV.generate(options) do |csv|
+ csv << column_names
+ import_messages.each do |import_message|
+ csv << [import_message.criticity, import_message.message_key, I18n.t("import_messages.compliance_check_messages.#{import_message.message_key}", import_message.message_attributes.deep_symbolize_keys) ]
+ 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) }
+ zipfile.get_output_stream(label("ftn_filename")+".csv") { |f| f.puts footnotes_to_csv(options) }
+ end
+ end
+
+end
diff --git a/app/models/import_report.rb b/app/models/import_report.rb
index 1dc556e1c..ba13f0118 100644
--- a/app/models/import_report.rb
+++ b/app/models/import_report.rb
@@ -1,9 +1,8 @@
-class ImportReport
- include ReportConcern
+class ImportReport
+ #include ReportConcern
def initialize( response )
@datas = response.action_report
end
-
-end
+end
diff --git a/app/models/import_resource.rb b/app/models/import_resource.rb
index 3ddd325fd..55e752e74 100644
--- a/app/models/import_resource.rb
+++ b/app/models/import_resource.rb
@@ -1,28 +1,11 @@
class ImportResource < ActiveRecord::Base
- include AASM
belongs_to :import
extend Enumerize
- enumerize :status, in: %i(new pending successful failed)
+ enumerize :status, in: %i(OK ERROR WARNING IGNORED), scope: true
- validates_presence_of :name, :type, :reference
+ validates_presence_of :name, :resource_type, :reference
- aasm column: :status do
- state :new, :initial => true
- state :pending
- state :successful
- state :failed
+ has_many :messages, class_name: "ImportMessage", foreign_key: :resource_id
- event :run do
- transitions :from => [:new, :failed], :to => :pending
- end
-
- event :successful do
- transitions :from => [:pending, :failed], :to => :successful
- end
-
- event :failed do
- transitions :from => :pending, :to => :failed
- end
- end
end
diff --git a/app/models/netex_import.rb b/app/models/netex_import.rb
index 575cef816..32939a741 100644
--- a/app/models/netex_import.rb
+++ b/app/models/netex_import.rb
@@ -1,15 +1,19 @@
require 'net/http'
class NetexImport < Import
- after_commit :launch_java_import
+ after_commit :launch_java_import, on: :create
+ validates_presence_of :parent
def launch_java_import
- logger.warn "Call iev get #{Rails.configuration.iev_url}/boiv_iev/referentials/importer/new?id=#{id}"
- begin
- Net::HTTP.get(URI("#{Rails.configuration.iev_url}/boiv_iev/referentials/importer/new?id=#{id}"))
- rescue Exception => e
- logger.error "IEV server error : #{e.message}"
- logger.error e.backtrace.inspect
+ return if self.class.finished_statuses.include?(status)
+
+ Thread.new do
+ begin
+ Net::HTTP.get(URI("#{Rails.configuration.iev_url}/boiv_iev/referentials/importer/new?id=#{id}"))
+ rescue Exception => e
+ logger.error "IEV server error : #{e.message}"
+ logger.error e.backtrace.inspect
+ end
end
end
end
diff --git a/app/models/organisation.rb b/app/models/organisation.rb
index f697122aa..895ca03d9 100644
--- a/app/models/organisation.rb
+++ b/app/models/organisation.rb
@@ -13,6 +13,7 @@ class Organisation < ActiveRecord::Base
has_many :workbenches
has_many :calendars
+ has_many :api_keys, class_name: 'Api::V1::ApiKey'
validates_presence_of :name
validates_uniqueness_of :code
diff --git a/app/models/referential.rb b/app/models/referential.rb
index cb2c7b23b..af08aa868 100644
--- a/app/models/referential.rb
+++ b/app/models/referential.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
class Referential < ActiveRecord::Base
include DataFormatEnumerations
@@ -10,7 +11,9 @@ class Referential < ActiveRecord::Base
# validates_presence_of :lower_corner
validates_uniqueness_of :slug
- validates_uniqueness_of :name
+
+ validates_presence_of :line_referential
+ validates_presence_of :stop_area_referential
validates_format_of :slug, :with => %r{\A[a-z][0-9a-z_]+\Z}
validates_format_of :prefix, :with => %r{\A[0-9a-zA-Z_]+\Z}
validates_format_of :upper_corner, :with => %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z}
@@ -130,7 +133,7 @@ class Referential < ActiveRecord::Base
self
end
- def self.new_from(from)
+ def self.new_from(from, functional_scope)
Referential.new(
name: I18n.t("activerecord.copy", :name => from.name),
slug: "#{from.slug}_clone",
@@ -139,9 +142,8 @@ class Referential < ActiveRecord::Base
bounds: from.bounds,
line_referential: from.line_referential,
stop_area_referential: from.stop_area_referential,
- workbench: from.workbench,
created_from: from,
- metadatas: from.metadatas.map { |m| ReferentialMetadata.new_from(m) }
+ metadatas: from.metadatas.map { |m| ReferentialMetadata.new_from(m, functional_scope) }
)
end
@@ -181,12 +183,10 @@ class Referential < ActiveRecord::Base
projection_type || ""
end
- before_validation :assign_line_and_stop_area_referential, :on => :create, if: :workbench, unless: :created_from
- before_validation :clone_associations, :on => :create, if: :created_from
+ before_validation :assign_line_and_stop_area_referential, :on => :create, if: :workbench
before_validation :assign_slug, :on => :create
before_validation :assign_prefix, :on => :create
before_create :create_schema
-
after_create :clone_schema, if: :created_from
before_destroy :destroy_schema
@@ -204,18 +204,6 @@ class Referential < ActiveRecord::Base
end
end
- def clone_associations
- self.line_referential = created_from.line_referential
- self.stop_area_referential = created_from.stop_area_referential
- self.workbench = created_from.workbench
- end
-
- def clone_metadatas
- created_from.metadatas.each do |meta|
- self.metadatas << ReferentialMetadata.new_from(meta)
- end
- end
-
def metadatas_period
query = "select min(lower), max(upper) from (select lower(unnest(periodes)) as lower, upper(unnest(periodes)) as upper from public.referential_metadata where public.referential_metadata.referential_id = #{id}) bounds;"
@@ -290,7 +278,9 @@ class Referential < ActiveRecord::Base
end
def create_schema
- Apartment::Tenant.create slug
+ unless created_from
+ Apartment::Tenant.create slug
+ end
end
def assign_slug
diff --git a/app/models/referential_metadata.rb b/app/models/referential_metadata.rb
index b774072c7..393dc70d3 100644
--- a/app/models/referential_metadata.rb
+++ b/app/models/referential_metadata.rb
@@ -155,8 +155,10 @@ class ReferentialMetadata < ActiveRecord::Base
end
private :clear_periods
- def self.new_from from
+ def self.new_from(from, functional_scope)
from.dup.tap do |metadata|
+ metadata.referential_source_id = from.referential_id
+ metadata.line_ids = from.referential.lines.where(id: metadata.line_ids, objectid: functional_scope).collect(&:id)
metadata.referential_id = nil
end
end
diff --git a/app/models/vehicle_journey_import.rb b/app/models/vehicle_journey_import.rb
index 855fa2abe..44a6d457e 100644
--- a/app/models/vehicle_journey_import.rb
+++ b/app/models/vehicle_journey_import.rb
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-class VehicleJourneyImport
+class VehicleJourneyImport
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
@@ -8,11 +8,11 @@ class VehicleJourneyImport
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 = {})
+ def initialize(attributes = {})
attributes.each { |name, value| send("#{name}=", value) } if attributes
self.created_vehicle_journey_count = 0
self.updated_vehicle_journey_count = 0
@@ -20,15 +20,15 @@ class VehicleJourneyImport
self.deleted_vehicle_journey_count = 0
self.error_count = 0
end
-
+
def persisted?
false
end
-
+
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
@@ -46,8 +46,8 @@ class VehicleJourneyImport
errors.add :base, I18n.t("vehicle_journey_imports.errors.exception")
false
end
- end
-
+ end
+
def imported_vehicle_journeys
@imported_vehicle_journeys ||= load_imported_vehicle_journeys
end
@@ -61,31 +61,31 @@ class VehicleJourneyImport
if stop_points_used.length == 1
errors.add :base, I18n.t("vehicle_journey_imports.errors.one_stop_point_used", :column => column)
- raise
+ 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
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.where(:id => ids)
end
-
+
def update_footnotes(vj,ftn_ids)
vj.footnotes.clear
return unless ftn_ids.present?
@@ -94,13 +94,13 @@ class VehicleJourneyImport
end
def load_imported_vehicle_journeys
-
+
spreadsheet = open_spreadsheet(file)
-
+
vehicle_journeys = []
-
+
first_column = spreadsheet.column(1)
-
+
# fixed rows (first = 1)
number_row = 2
published_journey_name_row = 3
@@ -111,7 +111,7 @@ class VehicleJourneyImport
# rows in column (first = 0)
first_stop_row_index = 8
-
+
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 + 7
@@ -119,50 +119,50 @@ class VehicleJourneyImport
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)
raise
- end
-
+ end
+
(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?
+ if vehicle_journey.id.present?
self.deleted_vehicle_journey_count += 1
vehicle_journey.delete
end
next
end
- if vehicle_journey.id.present?
+ 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])
-
+
update_footnotes(vehicle_journey,spreadsheet.row(footnotes_row)[i-1])
-
+
# journey_pattern
vehicle_journey.journey_pattern = journey_pattern
vehicle_journey.vehicle_journey_at_stops.clear
@@ -171,7 +171,7 @@ class VehicleJourneyImport
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
+ begin
# force UTC to ignore timezone effects
main_time = Time.parse(value+" UTC")
if main_time.present?
@@ -182,14 +182,14 @@ class VehicleJourneyImport
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
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, csv_options: {col_sep: ";"})
@@ -199,5 +199,5 @@ class VehicleJourneyImport
raise "Unknown file type: #{file.original_filename}"
end
end
-
+
end
diff --git a/app/models/workbench.rb b/app/models/workbench.rb
index 4023c221b..30692e625 100644
--- a/app/models/workbench.rb
+++ b/app/models/workbench.rb
@@ -9,6 +9,8 @@ class Workbench < ActiveRecord::Base
has_many :group_of_lines, through: :line_referential
has_many :stop_areas, through: :stop_area_referential
has_many :imports
+ has_many :workbench_imports
+
validates :name, presence: true
validates :organisation, presence: true
diff --git a/app/models/workbench_import.rb b/app/models/workbench_import.rb
index 9323bd4b5..27f53a44f 100644
--- a/app/models/workbench_import.rb
+++ b/app/models/workbench_import.rb
@@ -1,2 +1,7 @@
class WorkbenchImport < Import
+ after_commit :launch_worker, :on => :create
+
+ def launch_worker
+ WorkbenchImportWorker.perform_async(id)
+ end
end
diff --git a/app/policies/api_key_policy.rb b/app/policies/api_key_policy.rb
new file mode 100644
index 000000000..7b4c22e33
--- /dev/null
+++ b/app/policies/api_key_policy.rb
@@ -0,0 +1,19 @@
+class ApiKeyPolicy < ApplicationPolicy
+ class Scope < Scope
+ def resolve
+ scope
+ end
+ end
+
+ def destroy?
+ organisation_match? && user.has_permission?('api_keys.destroy')
+ end
+
+ def create?
+ organisation_match? && user.has_permission?('api_keys.create')
+ end
+
+ def update?
+ organisation_match? && user.has_permission?('api_keys.update')
+ end
+end
diff --git a/app/policies/import_policy.rb b/app/policies/import_policy.rb
new file mode 100644
index 000000000..9e1d99a66
--- /dev/null
+++ b/app/policies/import_policy.rb
@@ -0,0 +1,7 @@
+class ImportPolicy < ApplicationPolicy
+ class Scope < Scope
+ def resolve
+ scope
+ end
+ end
+end
diff --git a/app/services/http_service.rb b/app/services/http_service.rb
index ae7d0e413..d3999f293 100644
--- a/app/services/http_service.rb
+++ b/app/services/http_service.rb
@@ -20,26 +20,23 @@ module HTTPService extend self
raise "Error on api request status : #{resp.status} => #{resp.body}"
end
end
-
# host: 'http://localhost:3000',
# path: '/api/v1/netex_imports.json',
# token: '13-74009c36638f587c9eafb1ce46e95585',
# params: { netex_import: {referential_id: 13, workbench_id: 1}},
# upload: {file: [StringIO.new('howdy'), 'application/zip', 'greeting']})
def post_resource(host:, path:, token: nil, params: {}, upload: nil)
- Faraday.new(url: host) do |c|
+ result = Faraday.new(url: host) do |c|
c.headers['Authorization'] = "Token token=#{token.inspect}" if token
c.request :multipart
c.request :url_encoded
c.adapter Faraday.default_adapter
-
- if upload
- name = upload.keys.first
- value, mime_type, as_name = upload.values.first
- params.update( name => Faraday::UploadIO.new(value, mime_type, as_name ) )
- end
-
return c.post path, params
end
end
+
+ # Expose this in order to make the service replaceable
+ def upload(*triple)
+ Faraday::UploadIO.new(*triple)
+ end
end
diff --git a/app/services/retry_service.rb b/app/services/retry_service.rb
deleted file mode 100644
index 21b1def36..000000000
--- a/app/services/retry_service.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'result'
-
-class RetryService
-
- Retry = Class.new(RuntimeError)
-
- # @param@ delays:
- # An array of delays that are used to retry after a sleep of the indicated
- # value in case of failed exceutions.
- # Once this array is exhausted the executen fails permanently
- #
- # @param@ rescue_from:
- # During execution all the excpetions from this array +plus RetryService::Retry+ are rescued from and
- # trigger just another retry after a `sleep` as indicated above.
- #
- # @param@ block:
- # This optional code is excuted before each retry, it is passed the result of the failed attempt, thus
- # an `Exception` and the number of execution already tried.
- def initialize( delays: [], rescue_from: [], &blk )
- @intervals = delays
- @registered_exceptions = Array(rescue_from) << Retry
- @failure_callback = blk
- end
-
- # @param@ blk:
- # The code to be executed it will be retried goverened by the `delay` passed into the initializer
- # as described there in case it fails with one of the predefined exceptions or `RetryService::Retry`
- #
- # Eventually it will return a `Result` object.
- def execute &blk
- result = execute_protected blk
- return result if result.ok?
- @intervals.each_with_index do | interval, retry_count |
- sleep interval
- @failure_callback.try(:call, result.value, retry_count + 1)
- result = execute_protected blk
- return result if result.ok?
- end
- result
- end
-
-
- private
-
- def execute_protected blk
- Result.ok(blk.())
- rescue Exception => e
- if @registered_exceptions.any?{ |re| e.is_a? re }
- Result.error(e)
- else
- raise
- end
- end
-end
diff --git a/app/services/zip_service.rb b/app/services/zip_service.rb
index 778bfd06d..cab301b01 100644
--- a/app/services/zip_service.rb
+++ b/app/services/zip_service.rb
@@ -1,55 +1,68 @@
class ZipService
+ # TODO: Remove me before merge https://github.com/rubyzip/rubyzip
- attr_reader :current_entry, :zip_data
+ class Subdir < Struct.new(:name, :stream)
+ end
+
+ attr_reader :current_key, :current_output, :yielder
def initialize data
- @zip_data = data
- @current_entry = nil
- end
-
- class << self
- def convert_entries entries
- -> output_stream do
- entries.each do |e|
- output_stream.put_next_entry e.name
- output_stream.write e.get_input_stream.read
- end
- end
- end
+ @zip_data = StringIO.new(data)
+ @current_key = nil
+ @current_output = nil
+ end
- def entries input_stream
- Enumerator.new do |enum|
- loop{ enum << input_stream.get_next_entry }
- end.lazy.take_while{ |e| e }
+ def subdirs
+ Enumerator.new do |yielder|
+ @yielder = yielder
+ Zip::File.open_buffer(@zip_data, &(method :_subdirs))
end
end
- def entry_groups
- self.class.entries(input_stream).group_by(&method(:entry_key))
+ def _subdirs zip_file
+ zip_file.each do | entry |
+ add_entry entry
+ end
+ finish_current_output
end
- def entry_group_streams
- entry_groups.map(&method(:make_stream)).to_h
+ def add_entry entry
+ key = entry_key entry
+ unless key == current_key
+ finish_current_output
+ open_new_output key
+ end
+ add_to_current_output entry
end
- def entry_key entry
- entry.name.split('/', -1)[-2]
+ def add_to_current_output entry
+ current_output.put_next_entry entry.name
+ write_to_current_output entry.get_input_stream
end
- def make_stream pair
- name, entries = pair
- [name, make_stream_from( entries )]
+ def write_to_current_output input_stream
+ # the condition below is true for directory entries
+ return if Zip::NullInputStream == input_stream
+ current_output.write input_stream.read
end
- def make_stream_from entries
- Zip::OutputStream.write_buffer(&self.class.convert_entries(entries))
+ def finish_current_output
+ if current_output
+ @yielder << Subdir.new(
+ current_key,
+ # Second part of the solution, yield the closed stream
+ current_output.close_buffer)
+ end
end
- def next_entry
- @current_entry = input_stream.get_next_entry
+ def open_new_output entry_key
+ @current_key = entry_key
+ # First piece of the solution, use internal way to create a Zip::OutputStream
+ @current_output = Zip::OutputStream.new(StringIO.new(''), true, nil)
end
- def input_stream
- @__input_stream__ ||= Zip::InputStream.open(StringIO.new(zip_data))
+ def entry_key entry
+ # last dir name File.dirname.split("/").last
+ entry.name.split('/', -1)[-2]
end
end
diff --git a/app/views/api/v1/imports/index.rabl b/app/views/api/v1/imports/index.rabl
new file mode 100644
index 000000000..e8cfd101e
--- /dev/null
+++ b/app/views/api/v1/imports/index.rabl
@@ -0,0 +1,3 @@
+collection @imports
+
+extends "api/v1/imports/show"
diff --git a/app/views/api/v1/imports/show.rabl b/app/views/api/v1/imports/show.rabl
new file mode 100644
index 000000000..180894cb8
--- /dev/null
+++ b/app/views/api/v1/imports/show.rabl
@@ -0,0 +1,6 @@
+object @import
+
+attributes :id, :name, :status
+node :referential_ids do |i|
+ i.workbench.referentials.map(&:id)
+end
diff --git a/app/views/api/v1/workbenches/index.rabl b/app/views/api/v1/workbenches/index.rabl
new file mode 100644
index 000000000..2f0bf5fee
--- /dev/null
+++ b/app/views/api/v1/workbenches/index.rabl
@@ -0,0 +1,3 @@
+collection @workbenches
+
+extends "api/v1/workbenches/show"
diff --git a/app/views/api/v1/workbenches/show.rabl b/app/views/api/v1/workbenches/show.rabl
new file mode 100644
index 000000000..d43727809
--- /dev/null
+++ b/app/views/api/v1/workbenches/show.rabl
@@ -0,0 +1,3 @@
+object @workbench
+
+attributes :id, :name
diff --git a/app/views/api_keys/_form.html.slim b/app/views/api_keys/_form.html.slim
index 74b806677..f3ebf3fe1 100644
--- a/app/views/api_keys/_form.html.slim
+++ b/app/views/api_keys/_form.html.slim
@@ -1,10 +1,7 @@
-= semantic_form_for [@referential, @api_key] do |form|
- = form.inputs do
- = form.input :name
-
+= simple_form_for @api_key, url: action_url do |f|
+ = f.input :name
- unless @api_key.new_record?
- = form.input :token, :input_html => { :readonly => true }
+ = f.input :token, :input_html => { readonly: true }
- = form.actions do
- = form.action :submit, as: :button
- = form.action :cancel, as: :link \ No newline at end of file
+ = f.association :referential
+ = f.button :submit, 'submit', class: 'btn-primary'
diff --git a/app/views/api_keys/edit.html.slim b/app/views/api_keys/edit.html.slim
index 110f0775d..e47deddf7 100644
--- a/app/views/api_keys/edit.html.slim
+++ b/app/views/api_keys/edit.html.slim
@@ -1,3 +1,2 @@
= title_tag t('api_keys.edit.title')
-
-== render 'form' \ No newline at end of file
+== render partial: 'form', locals: {action_url: organisation_api_key_path}
diff --git a/app/views/api_keys/index.html.slim b/app/views/api_keys/index.html.slim
new file mode 100644
index 000000000..9757b8955
--- /dev/null
+++ b/app/views/api_keys/index.html.slim
@@ -0,0 +1,27 @@
+- header_params = ['map-marker',
+ t('.title'),
+ '']
+- header_params << link_to(t('actions.add'), new_organisation_api_key_path, class: 'btn btn-default') if policy(Api::V1::ApiKey).create?
+= pageheader(*header_params) do
+
+
+- if @api_keys.any?
+ .row
+ .col-lg-12
+ = table_builder_2 @api_keys,
+ [ \
+ TableBuilderHelper::Column.new( \
+ key: :name, \
+ attribute: 'name', \
+ link_to: lambda do |api_key| \
+ organisation_api_key_path(api_key) \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :token, \
+ attribute: 'token' \
+ ), \
+ ],
+ cls: 'table has-search'
+
+ = new_pagination @api_keys, 'pull-right'
diff --git a/app/views/api_keys/new.html.slim b/app/views/api_keys/new.html.slim
index f7b1dd99b..291c9f8a6 100644
--- a/app/views/api_keys/new.html.slim
+++ b/app/views/api_keys/new.html.slim
@@ -1,3 +1,2 @@
= title_tag t('api_keys.new.title')
-
-== render "form" \ No newline at end of file
+== render partial: 'form', locals: {action_url: organisation_api_keys_path}
diff --git a/app/views/api_keys/show.html.slim b/app/views/api_keys/show.html.slim
index b65717408..de30ac125 100644
--- a/app/views/api_keys/show.html.slim
+++ b/app/views/api_keys/show.html.slim
@@ -12,7 +12,6 @@
- content_for :sidebar do
ul.actions
- li = link_to t('api_keys.actions.new'), new_referential_api_key_path(@referential), class: "add"
- li = link_to t('api_keys.actions.edit'), edit_referential_api_key_path(@referential, @api_key), class: "edit"
- li = link_to t('api_keys.actions.destroy'), referential_api_key_path(@referential, @api_key), :method => :delete, :data => {:confirm => t('api_keys.actions.destroy_confirm')}, class: "remove"
- br \ No newline at end of file
+ li = link_to t('api_keys.actions.edit'), edit_organisation_api_key_path(@api_key), class: "edit"
+ li = link_to t('api_keys.actions.destroy'), organisation_api_key_path(@api_key), :method => :delete, :data => {:confirm => t('api_keys.actions.destroy_confirm')}, class: "remove"
+ br
diff --git a/app/views/calendars/_filters.html.slim b/app/views/calendars/_filters.html.slim
index 4c30f69dc..b5283c1e8 100644
--- a/app/views/calendars/_filters.html.slim
+++ b/app/views/calendars/_filters.html.slim
@@ -19,4 +19,4 @@
.actions
= link_to 'Effacer', calendars_path, class: 'btn btn-link'
- = f.submit 'Filtrer', id: 'filter_btn', class: 'btn btn-default'
+ = f.submit 'Filtrer', id: 'calendar_filter_btn', class: 'btn btn-default'
diff --git a/app/views/calendars/edit.html.slim b/app/views/calendars/edit.html.slim
index 6668630e8..426f27881 100644
--- a/app/views/calendars/edit.html.slim
+++ b/app/views/calendars/edit.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'modele-calendrier',
t('.title', calendar: @calendar.name),
'',
t('last_update', time: l(@calendar.updated_at, format: :short))
diff --git a/app/views/calendars/index.html.slim b/app/views/calendars/index.html.slim
index e3ac16505..24ed15484 100644
--- a/app/views/calendars/index.html.slim
+++ b/app/views/calendars/index.html.slim
@@ -1,6 +1,6 @@
/ PageHeader
-- header_params = ['map-marker',
+- header_params = ['modele-calendrier',
t('.title'),
'']
- header_params << link_to(t('actions.add'), new_calendar_path, class: 'btn btn-default') if policy(Calendar).create?
@@ -13,7 +13,7 @@
.row
.col-lg-12
= render 'filters'
-
+
- if @calendars.any?
.row
.col-lg-12
@@ -21,13 +21,20 @@
[ \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |calendar| \
+ calendar_path(calendar) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :short_name, \
attribute: 'short_name' \
), \
TableBuilderHelper::Column.new( \
+ key: :organisation, \
+ attribute: Proc.new { |c| c.organisation.name } \
+ ), \
+ TableBuilderHelper::Column.new( \
key: :shared, \
attribute: Proc.new { |c| t("#{c.try(:shared)}") } \
) \
@@ -36,8 +43,10 @@
cls: 'table has-filter'
= new_pagination @calendars, 'pull-right'
-
+
- unless @calendars.any?
.row.mt-xs
.col-lg-12
= replacement_msg t('calendars.search_no_results')
+
+= javascript_include_tag 'filters/calendar.js'
diff --git a/app/views/calendars/new.html.slim b/app/views/calendars/new.html.slim
index 7faecf587..2cb6f8061 100644
--- a/app/views/calendars/new.html.slim
+++ b/app/views/calendars/new.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'modele-calendrier',
t('.title'),
'',
''
diff --git a/app/views/calendars/show.html.slim b/app/views/calendars/show.html.slim
index 4ce5de57f..eda4ef97c 100644
--- a/app/views/calendars/show.html.slim
+++ b/app/views/calendars/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'modele-calendrier',
@calendar.name,
'',
t('last_update', time: l(@calendar.updated_at, format: :short)),
diff --git a/app/views/companies/index.html.slim b/app/views/companies/index.html.slim
index ceea385b3..dad905c60 100644
--- a/app/views/companies/index.html.slim
+++ b/app/views/companies/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'transporteur',
t('companies.index.title'),
'Lorem ipsum dolor sit amet',
'',
@@ -31,7 +31,10 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |company| \
+ line_referential_company_path(current_referential, company) \
+ end \
) \
],
links: [:show, :edit],
diff --git a/app/views/companies/show.html.slim b/app/views/companies/show.html.slim
index a5c7347a8..4fb437115 100644
--- a/app/views/companies/show.html.slim
+++ b/app/views/companies/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'transporteur',
@company.name,
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@company.updated_at, format: :short)) do
diff --git a/app/views/compliance_check_tasks/new.html.erb b/app/views/compliance_check_tasks/new.html.erb
deleted file mode 100644
index 3f43a7dd7..000000000
--- a/app/views/compliance_check_tasks/new.html.erb
+++ /dev/null
@@ -1,39 +0,0 @@
-<%= title_tag t(".title") %>
-
-<%= semantic_form_for [@referential, @compliance_check_task], :url => referential_compliance_check_tasks_path(@referential) do |form| %>
- <%= form.inputs do %>
- <%= form.input :user_name, :as => :hidden, :input_html => { :value => current_user.name } %> <%= form.input :user_id, :as => :hidden, :input_html => { :value => current_user.id } %>
- <%= form.input :referential_id, :as => :hidden, :input_html => { :value => @referential.id } %>
- <%= form.input :name %>
- <%= form.input :rule_parameter_set_id, :as => :select,
- :collection => @referential.organisation.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => false %>
- <%= form.input :references_type, :as => :select, :include_blank => t(".all") %>
- <% @compliance_check_task.class.references_types.each do |type| %>
- <%= form.input :reference_ids, :as => :reference_ids, :json => references_referential_compliance_check_tasks_path(@referential, :format => :json) + "?filter=#{type}", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :id => "#{type}_reference_ids", :input_html => { :id => "#{type}_reference_ids" }, :wrapper_html => { :style => "display:none;", :id => "#{type}", :"data-type" => "#{type}" } %>
- <% end %>
- <% end %>
-
- <%= form.actions do %>
- <%= form.action :submit, :as => :button , :label => t( 'formtastic.validate' ) %>
- <%= form.action :cancel, :as => :link %>
- <% end %>
-<% end %>
-
-<!-- = title_tag t('.title')
-
-= semantic_form_for [@referential, @compliance_check_task], :url => referential_compliance_check_tasks_path(@referential) do |form|
- = form.inputs do
- = form.input :user_name, :as => :hidden, :input_html => { :value => current_user.name }
- = form.input :user_id, :as => :hidden, :input_html => { :value => current_user.id }
- = form.input :referential_id, :as => :hidden, :input_html => { :value => @referential.id }
- = form.input :name
- = form.input :rule_parameter_set_id, :as => :select,
- :collection => @referential.organisation.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => false
- = form.input :references_type, :as => :select, :include_blank => t(".all")
- - @compliance_check_task.class.references_types.each do |type|
-
- = form.input :reference_ids, as: :reference_ids, json: references_referential_compliance_check_tasks_path(@referential, format: :json) + "?filter=#{type}", hint_text: t('search_hint'), no_result_text: t('no_result_text'), searching_text: t('searching_term'), id: "#{type}_reference_ids", input_html: { :id => "#{type}_reference_ids" }, wrapper_html: { :style => "display:none;", :id => "#{type}", :"data-type" => "#{type}" }
-
- = form.actions do
- = form.action :submit, as: :button, label: t('formtastic.validate')
- = form.action :cancel, as: :link -->
diff --git a/app/views/compliance_check_tasks/new.js.coffee b/app/views/compliance_check_tasks/new.js.coffee
deleted file mode 100644
index ba62f53b2..000000000
--- a/app/views/compliance_check_tasks/new.js.coffee
+++ /dev/null
@@ -1,7 +0,0 @@
-jQuery ->
- <% ComplianceCheckTask.references_types.map { |type| type_ids_model_references_type( ComplianceCheckTask, 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 %>
-
- # - ComplianceCheckTask.references_types.map { |type| type_ids_model_references_type( ComplianceCheckTask, 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')}"});
diff --git a/app/views/compliance_checks/_compliance_check.html.slim b/app/views/compliance_checks/_compliance_check.html.slim
deleted file mode 100644
index 383a7ea82..000000000
--- a/app/views/compliance_checks/_compliance_check.html.slim
+++ /dev/null
@@ -1,17 +0,0 @@
-#index_item.panel.panel-default
- .panel-heading
- .panel-title.clearfix
- span.pull-right
- = link_to referential_compliance_check_path(@referential, compliance_check.id), :method => :delete, :data => {:confirm => t('compliance_checks.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do
- span.fa.fa-trash-o
- h5
- = link_to referential_compliance_check_path(@referential, compliance_check.id), class: 'preview', title: "#{ComplianceCheck.model_name.human.capitalize} #{compliance_check.name}" do
- = job_status_title(compliance_check)
-
- .panel-body
- p
- = link_to( font_awesome_classic_tag("fa-external-link") + t("compliance_checks.actions.report"), report_referential_compliance_check_path(@referential, compliance_check.id)) if compliance_check.report?
- .panel-footer
- .history
- = l compliance_check.created_at, :format => "%d/%m/%Y %H:%M"
- = " | #{compliance_check.user_name}"
diff --git a/app/views/compliance_checks/_compliance_check_results.html.slim b/app/views/compliance_checks/_compliance_check_results.html.slim
deleted file mode 100644
index 8e86c174e..000000000
--- a/app/views/compliance_checks/_compliance_check_results.html.slim
+++ /dev/null
@@ -1,92 +0,0 @@
-p
- form.form-inline
- .form-group
- label = t('shared.ie_report.search')
- input#filter.form-control type="text"
-
- .form-group
- label = ComplianceCheckResult.human_attribute_name(:severity)
- select.filter-severity.form-control
- option
- option value="severity-error"
- = t('compliance_check_result.severities.error')
- option value="severity-warning"
- = t('compliance_check_result.severities.warning')
-
- .form-group
- label = ComplianceCheckResult.human_attribute_name(:status)
- select.filter-status.form-control
- option
- option value="status-ok"
- = t('compliance_check_result.statuses.ok')
- option value="status-nok"
- = t('compliance_check_result.statuses.nok')
- option value="status-uncheck"
- = t('compliance_check_result.statuses.uncheck')
-
-
-table.table.table-hover.toggle-circle.toggle-medium data-filter="#filter" data-page-size="20" data-title-nok="#{t('compliance_check_result.statuses.nok')}" data-title-uncheck="#{t('compliance_check_result.statuses.uncheck')}" data-title-ok="#{t('compliance_check_result.statuses.ok')}"
- thead
- tr
- th data-sort-ignore="true"
- = ComplianceCheckResult.human_attribute_name(:status)
- th.col-md-1 data-sort-ignore="true"
- = ComplianceCheckResult.human_attribute_name(:severity)
- th.col-md-3
- = ComplianceCheckResult.human_attribute_name(:rule_code)
- th.col-md-2
- = t('compliance_check_results.errors')
- th.col-md-6 data-toggle="true" data-sort-ignore="true"
- = ComplianceCheckResult.human_attribute_name(:detail)
- th data-hide="all" data-sort-ignore="true"
-
- tbody
- - if compliance_check_validation_report
- - compliance_check_validation_report.tests.each_with_index do |test, index|
- tr class="#{test.result}_#{test.severity}"
- td data-value="status-#{test.result}"
- = status_icon( test.result, test.severity )
- td data-value="severity-#{test.severity}"
- = t("compliance_check_result.severities.#{test.severity}_txt")
- td data-value="#{test.result}_#{test.severity}"
- = link_to test.test_id, test_definition(test.test_id), title: ComplianceCheckResult.human_attribute_name(test.test_id), target: "compliance_check"
- td
- = "#{test.error_count || 0} #{ComplianceCheckResult.human_attribute_name(:violation_count)}" if test.errors.present?
- td
- = truncate(t("activemodel.attributes.compliance_check_result.#{test.test_id}"), length: 50)
- td
- p
- b
- = t("activemodel.attributes.compliance_check_result.#{test.test_id}")
-
- - if test.errors.present?
- - test.errors.first(10).each do |error|
- dl.inline
- dt
- - if error["source"].present?
- - if error[:source].object_path.present?
- - if error[:source].label.present?
- = link_to error[:source].label, object_url(@referential.id, error), target: :_blank
- - else
- = link_to "#{error[:source].object_path.type} (#{error[:source].object_path.id})", object_url(@referential.id, error), target: :_blank
-
- - if error[:source].file.present?
- = error[:source].objectid if error[:source].objectid.present?
-
- dd = t("compliance_check_result.details.detail_#{error[:error_id]}", object_labels_hash(error))
-
- - if error[:source].file.present?
- p.file_error
- = error[:source].file.filename
- = ", li: #{error[:source].file.line_number}" if error[:source].file.line_number.present?
- = ", co: #{error[:source].file.column_number}" if error[:source].file.column_number.present?
-
- - else
- tr
- td colspan="6"
- = t('compliance_check_results.in_progress')
-
- tfoot.hide-if-no-paging
- tr
- td colspan="5"
- ul.pagination.pagination-centered
diff --git a/app/views/compliance_checks/_compliance_checks.html.slim b/app/views/compliance_checks/_compliance_checks.html.slim
deleted file mode 100644
index 48db9ae94..000000000
--- a/app/views/compliance_checks/_compliance_checks.html.slim
+++ /dev/null
@@ -1,9 +0,0 @@
-.page_info
- span.search = t('will_paginate.page_entries_info.search')
- = page_entries_info @compliance_checks
-
-.compliance_checks.paginated_content
- = paginated_content @compliance_checks, "compliance_checks/compliance_check"
-
-.pagination
- = will_paginate @compliance_checks, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer \ No newline at end of file
diff --git a/app/views/compliance_checks/detailed_errors_index.csv.slim b/app/views/compliance_checks/detailed_errors_index.csv.slim
deleted file mode 100644
index 7fe20e282..000000000
--- a/app/views/compliance_checks/detailed_errors_index.csv.slim
+++ /dev/null
@@ -1,37 +0,0 @@
-= I18n.t('activemodel.attributes.compliance_check_result.severity');
-= I18n.t('activemodel.attributes.compliance_check_result.rule_code');
-= I18n.t('activemodel.attributes.compliance_check_result.object');
-= I18n.t('activemodel.attributes.compliance_check_result.resource');
-= I18n.t('activemodel.attributes.compliance_check_result.title');
-= I18n.t('activemodel.attributes.compliance_check_result.detail')
-
-- @compliance_check.compliance_check_validation_report.tests.each do |r|
- - if r.errors.present?
- - r.errors.first(10).each do |error|
- - case r.severity
- - when "warning"
- = I18n.t('compliance_check_result.severities.warning_txt')
- - when "error"
- = I18n.t('compliance_check_result.severities.error_txt')
-
- = r.test_id;
-
- - if error["source"].present?
- = error["source"]["objectid"] if error["source"]["objectid"].present?
-
- - if error["source"]["object_path"].present?
- = object_url(@referential_id, error)
- - elsif error["source"]["file"].present?
- = File.basename(error["source"]["file"]["filename"]) + " - "
- = I18n.t("compliance_check_results.index.column") + ":"
- = error["source"]["file"]["column_number"] + ","
- = I18n.t("compliance_check_results.index.line") + ":"
- = error["source"]["file"]["line_number"]
-
- - else
- = I18n.t("activemodel.attributes.compliance_check_result.#{r.test_id}");
- = I18n.t("compliance_check_result.details.detail_#{error['error_id']}", object_labels_hash(error) )
- = "\n"
-
-/ <%= I18n.t("activemodel.attributes.compliance_check_result.severity") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.rule_code") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.object") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.resource") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.title") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.detail") %>
-/ <% @compliance_check.compliance_check_validation_report.tests.each do |r| %><% if r.errors.present? %><% r.errors.first(10).each do |error| %><% case r.severity %><% when "warning" %><%= I18n.t "compliance_check_result.severities.warning_txt" %><% when "error" %><%= I18n.t "compliance_check_result.severities.error_txt" %><% end %>;<%= r.test_id %>;<% if error["source"].present? %><%= error["source"]["objectid"] if error["source"]["objectid"].present? %>;<% if error["source"]["object_path"].present? %><%= object_url(@referential_id, error) %><% elsif error["source"]["file"].present? %><%= File.basename(error["source"]["file"]["filename"]) +" - " %><%= I18n.t "compliance_check_results.index.column" %>:<%= error["source"]["file"]["column_number"] %>,<%= I18n.t "compliance_check_results.index.line" %>:<%= error["source"]["file"]["line_number"] %><% end %>;<% else %>;;<% end %><%= I18n.t("activemodel.attributes.compliance_check_result."+r.test_id) %>;<%= I18n.t("compliance_check_result.details.detail_#{error['error_id']}", object_labels_hash(error) )%><%= "\n" %><% end %><% end %><% end %>
diff --git a/app/views/compliance_checks/index.html.slim b/app/views/compliance_checks/index.html.slim
deleted file mode 100644
index 392c46663..000000000
--- a/app/views/compliance_checks/index.html.slim
+++ /dev/null
@@ -1,14 +0,0 @@
-= title_tag t('.title')
-
-.warning
- = t('.warning')
-
-#compliance_checks
- = render 'compliance_checks'
-
-- content_for :sidebar do
- ul.actions
- li
- = link_to t('compliance_check_tasks.actions.new'), new_referential_compliance_check_task_path(), class: 'add'
- li
- = link_to t('rule_parameter_sets.actions.index'), organisation_rule_parameter_sets_path, class: 'link' \ No newline at end of file
diff --git a/app/views/compliance_checks/index.js.slim b/app/views/compliance_checks/index.js.slim
deleted file mode 100644
index cfd8dc40d..000000000
--- a/app/views/compliance_checks/index.js.slim
+++ /dev/null
@@ -1 +0,0 @@
-| $('#compliance_checks').html("#{escape_javascript(render('compliance_checks'))}"); \ No newline at end of file
diff --git a/app/views/compliance_checks/report.html.slim b/app/views/compliance_checks/report.html.slim
deleted file mode 100644
index be2bb8adc..000000000
--- a/app/views/compliance_checks/report.html.slim
+++ /dev/null
@@ -1,41 +0,0 @@
-= title_tag job_status_title(@compliance_check)
-
-.compliance_check_show
- .links
- - if @compliance_check.class == Import
- = link_to(font_awesome_classic_tag('fa-eye') + t("compliance_checks.report.action_report"), referential_import_path(@referential, @compliance_check.id))
- = link_to font_awesome_classic_tag("fa-external-link") + t("compliance_checks.rule_parameter_set"), rule_parameter_set_referential_import_path(@referential, @compliance_check.id) if @compliance_check.rule_parameter_set?
- - else
- = link_to(font_awesome_classic_tag('fa-eye') + t("compliance_checks.report.action_report"), referential_compliance_check_path(@referential, @compliance_check.id))
- = link_to font_awesome_classic_tag("fa-external-link") + t("compliance_checks.rule_parameter_set"), rule_parameter_set_referential_compliance_check_path(@referential, @compliance_check.id) if @compliance_check.rule_parameter_set?
-
- .btn-group.pull-right
- button.btn.btn-default.dropdown-toggle type="button" data-toggle="dropdown" aria-expanded="false"
- = t('compliance_checks.show.export')
- span.caret
-
- ul.dropdown-menu role="menu"
- li
- - if @compliance_check.class == Import
- = link_to t('compliance_checks.show.export_csv'), export_referential_import_path(@referential, @compliance_check.id)
- - else
- = link_to t("compliance_checks.show.export_csv"), export_referential_compliance_check_path(@referential, @compliance_check.id)
-
- .report data-refresh-interval="#{job_refresh_interval(@compliance_check)}"
- = render partial: 'compliance_checks/compliance_check_results', locals: { compliance_check_validation_report: @compliance_check.compliance_check_validation_report }
-
-- content_for :sidebar do
- - if @compliance_check.compliance_check_validation_report && @compliance_check.compliance_check_validation_report.nok_error.blank?
- .row
- = font_awesome_classic_tag('fa-thumbs-up fa-5x col-md-3')
- p#validation_success.col-md-7
- = t('.validation_success')
-
- ul.actions
- li
- - if @compliance_check.class != Import
- = link_to t('compliance_checks.actions.destroy'), referential_compliance_check_path(@referential, @compliance_check.id), method: :delete, :data => {:confirm => t('compliance_checks.actions.destroy_confirm')}, class: 'remove'
-
- = history_tag(@compliance_check)
- #error.graph
- #warning.graph \ No newline at end of file
diff --git a/app/views/compliance_checks/show.html.slim b/app/views/compliance_checks/show.html.slim
deleted file mode 100644
index 8c6900981..000000000
--- a/app/views/compliance_checks/show.html.slim
+++ /dev/null
@@ -1,22 +0,0 @@
-.test
- = title_tag job_status_title(@compliance_check)
-
-- if @compliance_check.report.failure_code?
- .alert.alert-danger
- = t("iev.failure.#{@compliance_check.report.failure_code}")
-
-.progress_bars
- = progress_bar_tag(@compliance_check)
-
-.compliance_check.show
- .links
- = link_to font_awesome_classic_tag("fa-external-link") + t("compliance_checks.actions.report"), report_referential_compliance_check_path(@referential, @compliance_check.id) if @compliance_check.compliance_check_validation_report?
-
- = render partial: "shared/ie_report", locals: { job: @compliance_check, type: :validation, line_items: @line_items }
-
-- content_for :sidebar do
- ul.actions
- li
- = link_to t('compliance_checks.actions.destroy'), referential_compliance_check_path(@referential, @compliance_check.id), method: :delete, data: {confirm: t('compliance_checks.actions.destroy_confirm')}, class: 'remove'
-
- = history_tag(@compliance_check) \ No newline at end of file
diff --git a/app/views/compliance_checks/summary_errors_index.csv.slim b/app/views/compliance_checks/summary_errors_index.csv.slim
deleted file mode 100644
index 8c88d5cf6..000000000
--- a/app/views/compliance_checks/summary_errors_index.csv.slim
+++ /dev/null
@@ -1,34 +0,0 @@
-= I18n.t("activemodel.attributes.compliance_check_result.severity");
-= I18n.t("activemodel.attributes.compliance_check_result.status");
-= I18n.t("activemodel.attributes.compliance_check_result.rule_code");
-= I18n.t("activemodel.attributes.compliance_check_result.title");
-= I18n.t("activemodel.attributes.compliance_check_result.url");
-= I18n.t("activemodel.attributes.compliance_check_result.violation_count_txt");
-= I18n.t("activemodel.attributes.compliance_check_result.objects")
-
-- @compliance_check.compliance_check_validation_report.tests.each do |r|
- - case r.severity
- - when "warning"
- = I18n.t("compliance_check_result.severities.warning_txt")
- - when "error"
- = I18n.t("compliance_check_result.severities.error_txt")
-
- = r.result;
- = r.test_id;
-
- = I18n.t("activemodel.attributes.compliance_check_result.#{r.test_id}");
- = Rails.application.config.validation_spec + I18n.locale.to_s + "/" + r.test_id + ".html";
-
- = r.error_count
-
- - if r.error_count > 0
- - if r.errors.present?
- - r.errors.first(10).each do |error|
- - if error["source"]
- = error["source"]["objectid"] + " "
- - else
- = " "
-
-/ <%= I18n.t("activemodel.attributes.compliance_check_result.severity") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.status") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.rule_code") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.title") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.url") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.violation_count_txt") %>;<%= I18n.t("activemodel.attributes.compliance_check_result.objects") %>
-/ <% @compliance_check.compliance_check_validation_report.tests.each do |r| %><% case r.severity %><% when "warning" %><%= I18n.t "compliance_check_result.severities.warning_txt" %><% when "error" %><%= I18n.t "compliance_check_result.severities.error_txt" %><% end %>;<%= r.result %>;<%= r.test_id %>;<%= I18n.t("activemodel.attributes.compliance_check_result."+r.test_id) %>;<%= Rails.application.config.validation_spec + I18n.locale.to_s + "/" + r.test_id + ".html" %>;<%= r.error_count %><% if r.error_count > 0 %><% if r.errors.present? %>;<% r.errors.first(10).each do |error| %><% if error["source"] %><%= error["source"]["objectid"] + " " %><% else %><%= " " %><% end %><% end %><% end %><% end %>
-/ <% end %>
diff --git a/app/views/import_resources/index.html.slim b/app/views/import_resources/index.html.slim
new file mode 100644
index 000000000..849ed6d8d
--- /dev/null
+++ b/app/views/import_resources/index.html.slim
@@ -0,0 +1,58 @@
+/ PageHeader
+= pageheader 'importer',
+ t('.title'),
+ '',
+ '',
+ ''
+
+/ PageContent
+.page_content.import_messages
+ .container-fluid
+ .row
+ .col-lg-12
+ = definition_list t('metadatas'),{ 'Bilan d\'import' => link_to(@import.parent.name, workbench_import_path(@import.parent.workbench, @import.parent) ),
+ 'Jeu de données associé' => ( @import.referential.present? ? link_to(@import.referential.name, referential_path(@import.referential)) : '-' ) }
+
+ .row
+ .col-lg-12
+ h1
+ span.status_icon = import_status(@import.status)
+ span = t('.table_state', lines_imported: @import_resources.lines_imported , lines_in_zipfile: @import_resources.lines_in_zipfile )
+ - if @import_resources.present?
+ .col-lg-12
+ h2 = t('.table_title')
+ .col-lg-12
+ = t('.table_explanation')
+ .col-lg-12
+ = table_builder_2 @import_resources.where(resource_type: :file),
+ [ \
+ TableBuilderHelper::Column.new( \
+ key: :name, \
+ attribute: 'name', \
+ sortable: false, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :status, \
+ attribute: Proc.new { |n| import_resource_status(n.status) }, \
+ sortable: false, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ name: 'Résultat des tests' , \
+ attribute: Proc.new { |n| I18n.t('import_resources.index.metrics', n.metrics.deep_symbolize_keys) }, \
+ sortable: false, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ name: 'Téléchargement' , \
+ attribute: Proc.new { |n| '<i class="fa fa-download" aria-hidden="true"></i>'.html_safe }, \
+ sortable: false, \
+ link_to: lambda do |import_resource| \
+ workbench_import_import_resource_import_messages_path(import_resource.import.workbench, import_resource.import, import_resource, format: 'csv' ) \
+ end \
+ ), \
+ ],
+ links: [],
+ cls: 'table has-search'
+ - else
+ .col-lg-12
+ - @import.messages.each do |message|
+ = I18n.t("import_messages.compliance_check_messages.#{message.message_key}")
diff --git a/app/views/imports/_filters.html.slim b/app/views/imports/_filters.html.slim
new file mode 100644
index 000000000..a216019b6
--- /dev/null
+++ b/app/views/imports/_filters.html.slim
@@ -0,0 +1,21 @@
+= search_form_for @q, url: workbench_imports_path(@workbench), html: { method: :get, class: 'form form-filter' } do |f|
+ .ffg-row
+ .input-group.search_bar
+ = f.search_field :name_or_creator_cont, class: 'form-control', placeholder: t('imports.filters.name_or_creator_cont')
+ span.input-group-btn
+ button.btn.btn-default#search_btn type='submit'
+ span.fa.fa-search
+
+ .ffg-row
+ .form-group.togglable
+ = f.label Import.human_attribute_name(:status), required: false, class: 'control-label'
+ = f.input :status_eq_any, collection: @imports.map(&:status).uniq.compact, as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + import_status(l) + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}, input_html: { checked: true}
+
+ .form-group.togglable
+ = f.label Import.human_attribute_name(:started_at), required: false, class: 'control-label'
+ .filter_menu
+ = f.input :started_on_date, as: :date, label: false, wrapper_html: { class: 'date smart_date filter_menu-item' }, include_blank: true
+
+ .actions
+ = link_to t('actions.erase'), workbench_imports_path(@workbench), class: 'btn btn-link'
+ = f.submit t('actions.filter'), id: 'import_filter_btn', class: 'btn btn-default'
diff --git a/app/views/imports/_form.html.slim b/app/views/imports/_form.html.slim
index b795e908f..0fbf578be 100644
--- a/app/views/imports/_form.html.slim
+++ b/app/views/imports/_form.html.slim
@@ -1,6 +1,14 @@
-= simple_form_for import, as: :import, url: workbench_imports_path(workbench) do |f|
- = f.input :name
- = f.input :file
- = f.association :referential, collection: workbench.referentials
- = f.input :type, as: :hidden
- = f.button :submit
+= simple_form_for import, as: :import, url: workbench_imports_path(workbench), html: {class: 'form-horizontal', id: 'wb_import_form'}, wrapper: :horizontal_form do |form|
+
+ .row
+ .col-lg-12
+ = form.input :name
+
+ .row
+ .col-lg-12
+ .form-group
+ = form.label :file, t('activerecord.attributes.import.resources'), class: 'control-label col-sm-4 col-xs-5'
+ .col-sm-8.col-xs-7
+ = form.input_field :file, label: false, class: 'form-control'
+
+ = form.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'wb_import_form'
diff --git a/app/views/imports/index.html.slim b/app/views/imports/index.html.slim
index 6e2d49f73..2203d3584 100644
--- a/app/views/imports/index.html.slim
+++ b/app/views/imports/index.html.slim
@@ -1,12 +1,51 @@
-= title_tag t('.title')
-- @imports.each do |import|
- .import
- li = link_to import.name, workbench_import_path(@workbench, import)
- li = import.referential.name if import.referential
- li = link_to import.file.file.filename, import.file.url, target: :_blank
- hr
-
-.warning = t('.warning')
-- content_for :sidebar do
- ul.actions
- li = link_to t('imports.actions.new'), new_workbench_import_path(workbench_id: @workbench), class: 'add'
+/ PageHeader
+= pageheader 'importer',
+ t('.title'),
+ '',
+ '',
+ link_to(t('imports.actions.new'), new_workbench_import_path(workbench_id: @workbench), class: 'btn btn-primary')
+
+/ PageContent
+.page_content
+ .container-fluid
+ - if params[:q].present? or @imports.any?
+ .row
+ .col-lg-12
+ = render 'filters'
+
+ - if @imports.any?
+ .row
+ .col-lg-12
+ = table_builder_2 @imports,
+ [ \
+ TableBuilderHelper::Column.new( \
+ key: :status, \
+ attribute: Proc.new { |n| import_status(n.status) }, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :started_at, \
+ attribute: Proc.new { |n| l(n.started_at, format: :long) }, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :name, \
+ attribute: 'name', \
+ link_to: lambda do |import| \
+ workbench_import_path(@workbench, import) \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :creator, \
+ attribute: 'creator' \
+ ) \
+ ],
+ links: [],
+ cls: 'table has-search'
+
+ = new_pagination @imports, 'pull-right'
+
+ - unless @imports.any?
+ .row.mt-xs
+ .col-lg-12
+ = replacement_msg t('imports.search_no_results')
+
+= javascript_include_tag 'filters/import.js'
diff --git a/app/views/imports/new.html.slim b/app/views/imports/new.html.slim
index 55b655a85..5d5df0857 100644
--- a/app/views/imports/new.html.slim
+++ b/app/views/imports/new.html.slim
@@ -1,4 +1,10 @@
-= title_tag t('.title')
-.row
- .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2
- = render 'form', import: @import, workbench: @workbench
+/ PageHeader
+= pageheader 'importer',
+ t('.title')
+
+/ PageContent
+.page_content
+ .container-fluid
+ .row
+ .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1
+ = render 'form', import: @import, workbench: @workbench
diff --git a/app/views/imports/show.html.slim b/app/views/imports/show.html.slim
index b40e11ea4..5f5974d69 100644
--- a/app/views/imports/show.html.slim
+++ b/app/views/imports/show.html.slim
@@ -1,14 +1,68 @@
-.title.row
- .col-md-8
- = title_tag job_status_title(@import)
+/ PageHeader
+= pageheader 'importer',
+ @import.name,
+ '',
+ t('last_update', time: l(@import.updated_at, format: :short)) do
-.import_show
- .links
- = link_to font_awesome_classic_tag("fa-file-#{@import.file.file.extension}-o") + t("imports.show.imported_file"), @import.file.url
+ / Below is secundary actions & optional contents (filters, ...)
+ .row
+ .col-lg-12.text-right.mb-sm
+ - @import.action_links.each do |link|
+ = link_to link.href,
+ method: link.method,
+ data: link.data,
+ class: 'btn btn-primary' do
+ = link.content
-- content_for :sidebar do
- ul.actions
- li
- = link_to t('imports.actions.destroy'), workbench_import_path(@workbench, @import.id), method: :delete, data: {confirm: t('imports.actions.destroy_confirm')}, class: 'remove'
+/ PageContent
+.page_content
+ .container-fluid
+ .row
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ = definition_list t('metadatas'), { 'Récupération des données' => '-', "Nom de l'archive" => @import.try(:file_identifier)}
- = history_tag(@import)
+ .row
+ .col-lg-12
+ = table_builder_2 @import.children,
+ [ \
+ TableBuilderHelper::Column.new( \
+ name: 'Nom du jeu de données', \
+ attribute: 'name', \
+ sortable: false, \
+ link_to: lambda do |import| \
+ referential_path(import.referential) if import.referential.present? \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :status, \
+ attribute: Proc.new { |n| import_status(n.status) }, \
+ sortable: false, \
+ link_to: lambda do |import| \
+ workbench_import_import_resources_path(import.workbench_id, import) \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ name: 'Contrôle STIF', \
+ attribute: '', \
+ sortable: false, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ name: 'Contrôle organisation', \
+ attribute: '', \
+ sortable: false, \
+ ) \
+ ],
+ links: [],
+ cls: 'table',
+ overhead: [ \
+ {}, \
+ { \
+ title: "#{@import.children_succeedeed} jeu de données validé sur #{@import.children.count} présents dans l'archive", \
+ width: 1, \
+ cls: "#{@import.import_status_css_class} full-border" \
+ }, { \
+ title: 'Bilan des jeux de contrôles d\'import <span title="Lorem ipsum..." class="fa fa-lg fa-info-circle text-info"></span>', \
+ width: 2, \
+ cls: 'overheaded-default colspan="2"' \
+ } \
+ ]
diff --git a/app/views/journey_patterns_collections/show.html.slim b/app/views/journey_patterns_collections/show.html.slim
index eb6dfb650..bce4f28b5 100644
--- a/app/views/journey_patterns_collections/show.html.slim
+++ b/app/views/journey_patterns_collections/show.html.slim
@@ -1,5 +1,5 @@
/ pageheader
-= pageheader 'map-marker',
+= pageheader 'mission',
"Missions de #{@route.try(:stop_points).first.try(:stop_area).name} vers #{@route.try(:stop_points).last.try(:stop_area).name}",
'Lorem ipsum dolor sit amet',
''
diff --git a/app/views/layouts/navigation/_main_nav_left.html.slim b/app/views/layouts/navigation/_main_nav_left.html.slim
index 8e82ac528..4560f5fa0 100644
--- a/app/views/layouts/navigation/_main_nav_left.html.slim
+++ b/app/views/layouts/navigation/_main_nav_left.html.slim
@@ -31,10 +31,10 @@
#miTwo.panel-collapse.collapse
.list-group
- = link_to '#', class: "list-group-item #{params[:controller] == 'workbenches' ? 'active' : ''}" do
+ = link_to workbench_path(current_offer_workbench), class: "list-group-item #{params[:controller] == 'workbenches' ? 'active' : ''}" do
span Jeux de données
- = link_to '#', class: 'list-group-item' do
- span Import
+ = link_to workbench_imports_path(current_offer_workbench), class: "list-group-item #{(params[:controller] == 'imports') ? 'active' : ''}" do
+ span Import
= link_to calendars_path, class: 'list-group-item' do
span Modèles de calendrier
= link_to '#', class: 'list-group-item' do
@@ -56,13 +56,13 @@
.list-group
= link_to referential_networks_path(current_referential), class: 'list-group-item' do
span = t('networks.index.title')
-
+
= link_to referential_companies_path(current_referential), class: 'list-group-item' do
span = t('companies.index.title')
-
+
= link_to '#', class: 'list-group-item disabled' do
span Tracés
-
+
= link_to referential_time_tables_path(current_referential), class: 'list-group-item' do
span = t('time_tables.index.title')
@@ -89,7 +89,7 @@
h4.panel-title
= link_to '#miFive', data: { toggle: 'collapse', parent: '#menu-items' }, 'aria-expanded' => 'false' do
|Outils
-
+
#miFive.panel-collapse.collapse
.list-group
= link_to Rails.application.config.try(:portal_url), target: '_blank', class: 'list-group-item' do
diff --git a/app/views/line_footnotes/edit.html.slim b/app/views/line_footnotes/edit.html.slim
index fcd7a47e0..4a0fbb931 100644
--- a/app/views/line_footnotes/edit.html.slim
+++ b/app/views/line_footnotes/edit.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'ligne',
"Notes sur la ligne #{@line.name}",
'Lorem ipsum dolor sit amet',
(@line.footnotes.any? ? t('last_update', time: l(@line.footnotes.last.updated_at, format: :short)) : '')
diff --git a/app/views/line_footnotes/show.html.slim b/app/views/line_footnotes/show.html.slim
index 6ad721711..8138c1383 100644
--- a/app/views/line_footnotes/show.html.slim
+++ b/app/views/line_footnotes/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'ligne',
"Notes sur la ligne #{@line.name}",
'Lorem ipsum dolor sit amet',
'',
diff --git a/app/views/line_referentials/show.html.slim b/app/views/line_referentials/show.html.slim
index e2381e7e9..d2527f360 100644
--- a/app/views/line_referentials/show.html.slim
+++ b/app/views/line_referentials/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'synchro-ilico',
t('.title'),
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@line_referential.updated_at, format: :short)),
diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim
index 630d63068..dda5afd44 100644
--- a/app/views/lines/index.html.slim
+++ b/app/views/lines/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'ligne',
t('lines.index.title'),
'Lorem ipsum dolor sit amet',
'',
@@ -29,7 +29,10 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |line| \
+ line_referential_line_path(@line_referential, line) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :deactivated, \
diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim
index 6f75432e1..0779a0f5a 100644
--- a/app/views/lines/show.html.slim
+++ b/app/views/lines/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'ligne',
@line.name,
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@line.updated_at, format: :short)) do
diff --git a/app/views/networks/index.html.slim b/app/views/networks/index.html.slim
index 4c1f9783c..235bdebda 100644
--- a/app/views/networks/index.html.slim
+++ b/app/views/networks/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'reseau',
t('networks.index.title'),
'Lorem ipsum dolor sit amet',
'',
@@ -31,7 +31,10 @@
),
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |network| \
+ line_referential_network_path(@line_referential, network) \
+ end \
), \
],
links: [:show],
@@ -40,6 +43,6 @@
= new_pagination @networks, 'pull-right'
- unless @networks.any?
- .row
+ .row.mt-xs
.col-lg-12
= replacement_msg t('networks.search_no_results')
diff --git a/app/views/networks/show.html.slim b/app/views/networks/show.html.slim
index 09edbad2e..d237351c4 100644
--- a/app/views/networks/show.html.slim
+++ b/app/views/networks/show.html.slim
@@ -1,7 +1,7 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'reseau',
@network.name,
- 'Lorem ipsum dolor sit amet',
+ '',
t('last_update', time: l(@network.updated_at, format: :short)) do
/ Below is secundary actions & optional contents (filters, ...)
diff --git a/app/views/referential_companies/index.html.slim b/app/views/referential_companies/index.html.slim
index 23eea40ce..e5b7ce24a 100644
--- a/app/views/referential_companies/index.html.slim
+++ b/app/views/referential_companies/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'transporteur',
t('companies.index.title'),
'',
'',
@@ -31,7 +31,10 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |company| \
+ referential_company_path(@referential, company) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :phone, \
diff --git a/app/views/referential_companies/show.html.slim b/app/views/referential_companies/show.html.slim
index 177ce2d69..1d71c778a 100644
--- a/app/views/referential_companies/show.html.slim
+++ b/app/views/referential_companies/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'transporteur',
@company.name,
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@company.updated_at, format: :short)) do
diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim
index 34c296932..cbce7a7d5 100644
--- a/app/views/referential_lines/show.html.slim
+++ b/app/views/referential_lines/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'ligne',
@line.name,
'',
t('last_update', time: l(@line.updated_at, format: :short)) do
@@ -51,7 +51,10 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |route| \
+ referential_line_route_path(@referential, @line, route) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :published_name, \
diff --git a/app/views/referential_networks/index.html.slim b/app/views/referential_networks/index.html.slim
index c58a91321..ca67eca8b 100644
--- a/app/views/referential_networks/index.html.slim
+++ b/app/views/referential_networks/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'reseau',
t('networks.index.title'),
'Lorem ipsum dolor sit amet',
'',
@@ -31,7 +31,10 @@
),
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |network| \
+ referential_network_path(@referential, network) \
+ end \
) \
],
links: [:show],
diff --git a/app/views/referential_networks/show.html.slim b/app/views/referential_networks/show.html.slim
index b9d9d5d8b..d7095561e 100644
--- a/app/views/referential_networks/show.html.slim
+++ b/app/views/referential_networks/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'reseau',
@network.name,
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@network.updated_at, format: :short)) do
diff --git a/app/views/referential_stop_areas/show.html.slim b/app/views/referential_stop_areas/show.html.slim
index d594665f7..fa383c82d 100644
--- a/app/views/referential_stop_areas/show.html.slim
+++ b/app/views/referential_stop_areas/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'arret',
@stop_area.name,
'Lorem ipsum dolor sit amet'
diff --git a/app/views/referentials/_form.html.slim b/app/views/referentials/_form.html.slim
index a9e308699..6f7da84c7 100644
--- a/app/views/referentials/_form.html.slim
+++ b/app/views/referentials/_form.html.slim
@@ -46,7 +46,7 @@
.separator
- = subform.input :lines, as: :select, collection: @referential.workbench.lines.includes(:company).order(:name), selected: subform.object.line_ids, label_method: :display_name, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': t('simple_form.labels.referential.placeholders.select_lines'), 'multiple': 'multiple', style: 'width: 100%' }
+ = subform.input :lines, as: :select, collection: Chouette::Line.includes(:company).order(:name).where(objectid: current_functional_scope), selected: subform.object.line_ids, label_method: :display_name, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': t('simple_form.labels.referential.placeholders.select_lines'), 'multiple': 'multiple', style: 'width: 100%' }
.hidden = form.input :workbench_id, as: :hidden
diff --git a/app/views/referentials/edit.html.slim b/app/views/referentials/edit.html.slim
index d54b63135..1fac626e6 100644
--- a/app/views/referentials/edit.html.slim
+++ b/app/views/referentials/edit.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'jeux-de-donnees',
t('.title'),
'',
t('last_update', time: l(@referential.updated_at, format: :short))
diff --git a/app/views/referentials/new.html.slim b/app/views/referentials/new.html.slim
index 55f38eb33..f4a7e4707 100644
--- a/app/views/referentials/new.html.slim
+++ b/app/views/referentials/new.html.slim
@@ -1,9 +1,9 @@
/ PageHeader
- if @referential.created_from.present?
- = pageheader 'map-marker',
+ = pageheader 'jeux-de-donnees',
t('.duplicated.title')
- else
- = pageheader 'map-marker',
+ = pageheader 'jeux-de-donnees',
t('.title')
/ PageContent
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index 49c152789..e1d89cba4 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'jeux-de-donnees',
@referential.name,
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@referential.updated_at, format: :short)),
@@ -51,7 +51,10 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |line| \
+ referential_line_path(@referential, line) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :deactivated, \
diff --git a/app/views/routes/edit.html.slim b/app/views/routes/edit.html.slim
index c854bc867..850588aef 100644
--- a/app/views/routes/edit.html.slim
+++ b/app/views/routes/edit.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'itineraire',
@route.name,
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@route.updated_at, format: :short))
diff --git a/app/views/routes/new.html.slim b/app/views/routes/new.html.slim
index 102467677..a68f8ae4e 100644
--- a/app/views/routes/new.html.slim
+++ b/app/views/routes/new.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'itineraire',
t('routes.new.title'),
''
diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim
index ec9719355..a21b5ec8a 100644
--- a/app/views/routes/show.html.slim
+++ b/app/views/routes/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'itineraire',
@route.name,
'',
t('last_update', time: l(@route.updated_at, format: :short)),
@@ -41,7 +41,10 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: Proc.new {|s| s.try(:stop_area).try(:name)} \
+ attribute: Proc.new {|s| s.try(:stop_area).try(:name)}, \
+ link_to: lambda do |stop_point| \
+ referential_stop_area_path(@referential, stop_point.stop_area) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :deleted_at, \
diff --git a/app/views/routing_constraint_zones/edit.html.slim b/app/views/routing_constraint_zones/edit.html.slim
index d0e0ded32..2c23344df 100644
--- a/app/views/routing_constraint_zones/edit.html.slim
+++ b/app/views/routing_constraint_zones/edit.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'itl',
t('.title', routing_constraint_zone: @routing_constraint_zone.name),
'',
t('last_update', time: l(@routing_constraint_zone.updated_at, format: :short))
diff --git a/app/views/routing_constraint_zones/index.html.slim b/app/views/routing_constraint_zones/index.html.slim
index 6b3e73096..4e2534b6a 100644
--- a/app/views/routing_constraint_zones/index.html.slim
+++ b/app/views/routing_constraint_zones/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'itl',
t('routing_constraint_zones.index.title'),
'',
'',
@@ -25,7 +25,14 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |routing_constraint_zone| \
+ referential_line_routing_constraint_zone_path( \
+ @referential, \
+ @line, \
+ routing_constraint_zone \
+ ) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :stop_points_count, \
diff --git a/app/views/routing_constraint_zones/new.html.slim b/app/views/routing_constraint_zones/new.html.slim
index 600663b18..1ed65335f 100644
--- a/app/views/routing_constraint_zones/new.html.slim
+++ b/app/views/routing_constraint_zones/new.html.slim
@@ -1,6 +1,6 @@
/ PageHeader
-= pageheader 'map-marker',
- t('.title')
+= pageheader 'itl',
+ t('.title')
/ PageContent
.page_content
diff --git a/app/views/routing_constraint_zones/show.html.slim b/app/views/routing_constraint_zones/show.html.slim
index 07b5ac6e6..dbd8464a0 100644
--- a/app/views/routing_constraint_zones/show.html.slim
+++ b/app/views/routing_constraint_zones/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'itl',
@routing_constraint_zone.name,
'',
t('last_update', time: l(@routing_constraint_zone.updated_at, format: :short)) do
@@ -30,7 +30,10 @@
[ \
TableBuilderHelper::Column.new( \
name: "Arrêts de l'itinéraire", \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |stop_point| \
+ referential_stop_area_path(@referential, stop_point.stop_area) \
+ end \
),
TableBuilderHelper::Column.new( \
name: "Arrêts inclus dans l'ITL", \
diff --git a/app/views/stop_area_referentials/show.html.slim b/app/views/stop_area_referentials/show.html.slim
index 0fca15fff..dc90def50 100644
--- a/app/views/stop_area_referentials/show.html.slim
+++ b/app/views/stop_area_referentials/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'synchro-icar',
t('.title'),
'Lorem ipsum dolor sit amet',
t('last_update', time: l(@stop_area_referential.updated_at, format: :short)),
diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim
index adb023633..4c95761d2 100644
--- a/app/views/stop_areas/index.html.slim
+++ b/app/views/stop_areas/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'arret',
t('stop_areas.index.title'),
'',
'',
@@ -25,7 +25,13 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |stop_area| \
+ referential_stop_area_path( \
+ @stop_area_referential, \
+ stop_area \
+ ) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :registration_number, \
diff --git a/app/views/stop_areas/show.html.slim b/app/views/stop_areas/show.html.slim
index 05f66a33a..dce5bdbad 100644
--- a/app/views/stop_areas/show.html.slim
+++ b/app/views/stop_areas/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'arret',
@stop_area.name,
'Lorem ipsum dolor sit amet'
diff --git a/app/views/time_table_combinations/_form.html.slim b/app/views/time_table_combinations/_form.html.slim
index b4f818828..426624ee3 100644
--- a/app/views/time_table_combinations/_form.html.slim
+++ b/app/views/time_table_combinations/_form.html.slim
@@ -7,7 +7,7 @@
abbr title='Champ requis' *
= f.input :combined_type, as: :boolean, checked_value: 'time_table', unchecked_value: 'calendar', required: false, label: content_tag(:span, t("time_table_combinations.combined_type.#{@combination.combined_type}"), class: 'switch-label', data: { checkedValue: 'Calendriers', uncheckedValue: 'Modèles de calendriers' }), wrapper_html: { class: 'col-sm-8 col-xs-7' }
- = f.input :time_table_id, as: :select, input_html: {class: 'tt_combination_target', style: "width: 100%", data: { 'select2-ajax': 'true', 'select2ed-placeholder': 'Indiquez un calendrier...', term: 'comment_or_objectid_cont', url: referential_autocomplete_time_tables_path(@referential, format: :json)}}, wrapper_html: {class: @combination.combined_type != 'time_table' ? 'hidden' : ''}
+ = f.input :time_table_id, as: :select, input_html: {class: 'tt_combination_target', style: "width: 100%", data: { 'select2-ajax': 'true', 'select2ed-placeholder': 'Indiquez un calendrier...', term: 'comment_or_objectid_cont_any', url: referential_autocomplete_time_tables_path(@referential, format: :json, :source_id => @combination.source_id)}}, wrapper_html: {class: @combination.combined_type != 'time_table' ? 'hidden' : ''}
= f.input :calendar_id, as: :select, input_html: { class: 'tt_combination_target', style: "width: 100%", data: { 'select2-ajax': 'true', 'select2ed-placeholder': 'Indiquez un modèle de calendrier...', term: 'name_cont', url: autocomplete_calendars_path}}, wrapper_html: {class: @combination.combined_type != 'calendar' ? 'hidden' : ''}
diff --git a/app/views/time_tables/edit.html.slim b/app/views/time_tables/edit.html.slim
index f129cd63a..ed55dc4e3 100644
--- a/app/views/time_tables/edit.html.slim
+++ b/app/views/time_tables/edit.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'calendrier-application',
@time_table.comment,
'',
''
@@ -10,6 +10,7 @@
#periods
= javascript_tag do
- | window.actionType = "#{raw params[:action]}"
+ | window.actionType = "#{raw params[:action]}";
+ | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
= javascript_include_tag 'es6_browserified/time_tables/index.js'
diff --git a/app/views/time_tables/index.html.slim b/app/views/time_tables/index.html.slim
index 5ee854c58..a1b9c4e09 100644
--- a/app/views/time_tables/index.html.slim
+++ b/app/views/time_tables/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'calendrier-application',
t('time_tables.index.title'),
'',
((policy(Chouette::TimeTable).create? && @referential.organisation == current_organisation) ? link_to(t('actions.add'), new_referential_time_table_path(@referential), class: 'btn btn-default') : '')
@@ -27,7 +27,10 @@
), \
TableBuilderHelper::Column.new( \
key: :comment, \
- attribute: 'comment' \
+ attribute: 'comment', \
+ link_to: lambda do |time_table| \
+ referential_time_table_path(@referential, time_table) \
+ end \
), \
TableBuilderHelper::Column.new( \
name: "Période englobante", \
@@ -65,3 +68,5 @@
= javascript_tag do
| window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+
+= javascript_include_tag 'filters/timetable.js'
diff --git a/app/views/time_tables/new.html.slim b/app/views/time_tables/new.html.slim
index 8d72f49b6..8a6930b9c 100644
--- a/app/views/time_tables/new.html.slim
+++ b/app/views/time_tables/new.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'calendrier-application',
t("time_tables.#{params[:action]}.title"),
'',
''
diff --git a/app/views/time_tables/show.html.slim b/app/views/time_tables/show.html.slim
index 36b79cc25..021b55058 100644
--- a/app/views/time_tables/show.html.slim
+++ b/app/views/time_tables/show.html.slim
@@ -2,7 +2,7 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'calendrier-application',
@time_table.comment,
'',
t('last_update', time: l(@time_table.updated_at, format: :short)),
diff --git a/app/views/vehicle_journeys/index.html.slim b/app/views/vehicle_journeys/index.html.slim
index 93f4e3221..4efc34eaa 100644
--- a/app/views/vehicle_journeys/index.html.slim
+++ b/app/views/vehicle_journeys/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'horaires-des-courses',
t('vehicle_journeys.index.title', route: @route.name ),
'Lorem ipsum dolor sit amet',
'' do
diff --git a/app/views/workbenches/index.html.slim b/app/views/workbenches/index.html.slim
index ca61d439d..6140c4f8c 100644
--- a/app/views/workbenches/index.html.slim
+++ b/app/views/workbenches/index.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'tableau-de-bord',
t('.title', organisation: current_organisation.name)
/ PageContent
@@ -34,15 +34,15 @@
div
= t('.offers.referentials')
span.badge.ml-xs = @referentials.count if @referentials.any?
-
+
div
= link_to '', workbench_path(@workbench), class: ' fa fa-chevron-right pull-right', title: t('.offers.see')
- if @referentials.any?
.list-group
- @referentials.each_with_index do |referential, i|
- = link_to referential.name, referential_path(referential), class: 'list-group-item' if i < 6
-
+ = link_to referential.name, referential_path(referential, workbench_id: referential.workbench_id, current_workbench_id: @workbench.id), class: 'list-group-item' if i < 6
+
- else
.panel-body
em.small.text-muted = t('.offers.no_content')
@@ -61,7 +61,7 @@
.list-group
- @calendars.each_with_index do |calendar, i|
= link_to calendar.name, calendar_path(calendar), class: 'list-group-item' if i < 6
-
+
- else
.panel-body
em.small.text-muted = t('.offers.no_content')
diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim
index 2f845ed96..fd72979ea 100644
--- a/app/views/workbenches/show.html.slim
+++ b/app/views/workbenches/show.html.slim
@@ -1,5 +1,5 @@
/ PageHeader
-= pageheader 'map-marker',
+= pageheader 'jeux-de-donnees',
t('referentials.index.title'),
'',
'' do
@@ -27,7 +27,10 @@
[ \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: 'name' \
+ attribute: 'name', \
+ link_to: lambda do |referential| \
+ referential_path(referential, current_workbench_id: params[:id]) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :status, \
@@ -74,3 +77,5 @@
= javascript_tag do
| window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+
+= javascript_include_tag 'filters/workbench.js'
diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb
index 7f77b46dc..994493944 100644
--- a/app/workers/workbench_import_worker.rb
+++ b/app/workers/workbench_import_worker.rb
@@ -3,18 +3,17 @@ class WorkbenchImportWorker
include Rails.application.routes.url_helpers
include Configurable
- RETRY_DELAYS = [3, 5, 8]
-
# Workers
# =======
def perform(import_id)
@workbench_import = WorkbenchImport.find(import_id)
@response = nil
- @workbench_import.update_attributes(status: 'running')
+ @workbench_import.update(status: 'running', started_at: Time.now)
downloaded = download
zip_service = ZipService.new(downloaded)
upload zip_service
+ @workbench_import.update(ended_at: Time.now)
end
def download
@@ -25,59 +24,50 @@ class WorkbenchImportWorker
params: {token: @workbench_import.token_download}).body
end
- def execute_post eg_name, eg_stream
+ def execute_post eg_name, eg_file
logger.info "HTTP POST #{export_url} (for #{complete_entry_group_name(eg_name)})"
HTTPService.post_resource(
host: export_host,
path: export_path,
- token: token(eg_name),
- params: params,
- upload: {file: [eg_stream, 'application/zip', eg_name]})
- end
-
- def log_failure reason, count
- logger.warn "HTTP POST failed with #{reason}, count = #{count}, response=#{@response}"
- end
-
- def try_again
- raise RetryService::Retry
- end
-
- def try_upload_entry_group eg_name, eg_stream
- result = execute_post eg_name, eg_stream
- return result if result && result.status < 400
- @response = result.body
- try_again
+ params: params(eg_file, eg_name))
end
def upload zip_service
- entry_group_streams = zip_service.entry_group_streams
- @workbench_import.update_attributes total_steps: entry_group_streams.size
+ entry_group_streams = zip_service.subdirs
+ @workbench_import.update total_steps: entry_group_streams.size
entry_group_streams.each_with_index(&method(:upload_entry_group))
- rescue StopIteration
- @workbench_import.update_attributes( current_step: entry_group_streams.size, status: 'failed' )
+ rescue Exception => e
+ logger.error e.message
+ @workbench_import.update( current_step: entry_group_streams.size, status: 'failed' )
+ raise
end
def upload_entry_group entry_pair, element_count
- @workbench_import.update_attributes( current_step: element_count.succ )
- retry_service = RetryService.new(
- delays: RETRY_DELAYS,
- rescue_from: [HTTPService::Timeout],
- &method(:log_failure))
- status = retry_service.execute(&upload_entry_group_proc(entry_pair))
- raise StopIteration unless status.ok?
- end
+ @workbench_import.update( current_step: element_count.succ )
+ # status = retry_service.execute(&upload_entry_group_proc(entry_pair))
+ eg_name = entry_pair.name
+ eg_stream = entry_pair.stream
+
+ FileUtils.mkdir_p(Rails.root.join('tmp', 'imports'))
- def upload_entry_group_proc entry_pair
- eg_name, eg_stream = entry_pair
- # This should be fn.try_upload_entry_group(eg_name, eg_stream) ;(
- -> do
- try_upload_entry_group(eg_name, eg_stream)
+ eg_file = File.new(Rails.root.join('tmp', 'imports', "WorkbenchImport_#{eg_name}_#{$$}.zip"), 'wb').tap do |file|
+ eg_stream.rewind
+ file.write eg_stream.read
+ end
+ eg_file.close
+ eg_file = File.new(Rails.root.join('tmp', 'imports', "WorkbenchImport_#{eg_name}_#{$$}.zip"))
+ result = execute_post eg_name, eg_file
+ if result && result.status < 400
+ result
+ else
+ raise StopIteration, result.body
end
+ ensure
+ eg_file.close rescue nil
+ eg_file.unlink rescue nil
end
-
# Queries
# =======
@@ -85,10 +75,6 @@ class WorkbenchImportWorker
[@workbench_import.name, entry_group_name].join("--")
end
- def token entry_group_name
- Api::V1::ApiKey.from(@workbench_import.referential, name: complete_entry_group_name(entry_group_name)).token
- end
-
# Constants
# =========
@@ -112,7 +98,12 @@ class WorkbenchImportWorker
@__import_url__ ||= File.join(import_host, import_path)
end
- def params
- @__params__ ||= { netex_import: { referential_id: @workbench_import.referential_id, workbench_id: @workbench_import.workbench_id } }
+ def params file, name
+ { netex_import:
+ { parent_id: @workbench_import.id,
+ parent_type: @workbench_import.class.name,
+ workbench_id: @workbench_import.workbench_id,
+ name: name,
+ file: HTTPService.upload(file, 'application/zip', "#{name}.zip") } }
end
end
diff --git a/config/deploy.rb b/config/deploy.rb
index 4ab888e92..3ca2b4a4e 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -24,7 +24,7 @@ require "bundler/capistrano"
require 'whenever/capistrano'
require 'capistrano/npm'
-set :npm_options, '--production --silent --no-progress'
+set :npm_options, '--production --no-progress'
after 'deploy:finalize_update', 'npm:install'
@@ -65,6 +65,7 @@ namespace :deploy do
run "rm -rf #{release_path}/public/uploads"
run "ln -nfs #{shared_path}/public/uploads #{release_path}/public/uploads"
run "ln -nfs #{shared_path}/tmp/uploads #{release_path}/tmp/uploads"
+ run "ln -nfs #{shared_path}/tmp/imports #{release_path}/tmp/imports"
end
after 'deploy:update_code', 'deploy:symlink_shared'
before 'deploy:assets:precompile', 'deploy:symlink_shared'
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index b53dba3d8..2ee5982f3 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -5,4 +5,4 @@ Rails.application.config.assets.version = '1.0'
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
-Rails.application.config.assets.precompile += %w( base.css es6_browserified/*.js )
+Rails.application.config.assets.precompile += %w( base.css es6_browserified/*.js helpers/*.js filters/*.js)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 52ec93250..e44d8df52 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,7 +1,10 @@
Sidekiq.configure_server do |config|
- pendings = [
- LineReferential.find_by(name: 'CodifLigne').line_referential_syncs.pending.take,
- StopAreaReferential.find_by(name: 'Reflex').stop_area_referential_syncs.pending.take
- ]
- pendings.compact.map{|sync| sync.failed({error: 'Failed by Sidekiq reboot', processing_time: 0})}
+ if ENV["CHOUETTE_SIDEKIQ_CANCEL_SYNCS_ON_BOOT"]
+ [
+ LineReferentialSync.pending,
+ StopAreaReferentialSync.pending
+ ].each do |pendings|
+ pendings.map { |sync| sync.failed({error: 'Failed by Sidekiq reboot', processing_time: 0}) }
+ end
+ end
end
diff --git a/config/locales/api_keys.en.yml b/config/locales/api_keys.en.yml
index 221fa6eef..1480c8e55 100644
--- a/config/locales/api_keys.en.yml
+++ b/config/locales/api_keys.en.yml
@@ -7,12 +7,14 @@ en:
destroy_confirm: "Are you sure you want destroy this api key?"
show:
title: "Api key"
+ index:
+ title: Api key
new:
title: "Add a new api key"
edit:
title: "Update api key"
- activerecord:
- models:
+ activerecord:
+ models:
api_key: "Api Key"
attributes:
api_key:
diff --git a/config/locales/api_keys.fr.yml b/config/locales/api_keys.fr.yml
index 445367c72..20af91a49 100644
--- a/config/locales/api_keys.fr.yml
+++ b/config/locales/api_keys.fr.yml
@@ -7,6 +7,8 @@ fr:
destroy_confirm: "Etes vous sûr de vouloir détruire la clé d'accès API ?"
show:
title: "Clé d'accès API"
+ index:
+ title: Clé d'accès API
new:
title: "Ajouter une clé d'accès API"
edit:
diff --git a/config/locales/calendars.en.yml b/config/locales/calendars.en.yml
index cb1ede4c7..42e26e995 100644
--- a/config/locales/calendars.en.yml
+++ b/config/locales/calendars.en.yml
@@ -64,6 +64,7 @@ en:
date_ranges: Date ranges
dates: Dates
shared: Shared
+ organisation: Organisation
errors:
models:
calendar:
diff --git a/config/locales/calendars.fr.yml b/config/locales/calendars.fr.yml
index 1b403c3f2..63f6465d9 100644
--- a/config/locales/calendars.fr.yml
+++ b/config/locales/calendars.fr.yml
@@ -64,6 +64,7 @@ fr:
date_ranges: Intervalles de dates
dates: Dates
shared: Partagé
+ organisation: Organisation
errors:
models:
calendar:
diff --git a/config/locales/compliance_check_results.en.yml b/config/locales/compliance_check_results.en.yml
index 7a71f83f0..e0541ab36 100644
--- a/config/locales/compliance_check_results.en.yml
+++ b/config/locales/compliance_check_results.en.yml
@@ -1,458 +1,3 @@
en:
compliance_check_results:
- errors: 'Errors'
- file:
- zip_name_prefix: "compliance_check_results"
- summary_errors_file_prefix: "summary_of_tests.csv"
- detailed_errors_file_prefix: "detail_of_errors.csv"
- index:
- line: "Li"
- column: "Col"
- in_progress: "Compliance check in progress..."
- compliance_check_result:
- severities:
- error: "Required"
- warning: "Optional"
- error_txt: "Required"
- warning_txt: "Optional"
- statuses:
- nok: "Error"
- uncheck: "Unavailable"
- ok: "Success"
- details:
- #### level 1
- ## NEPTUNE
- detail_1_neptune_xml_1: "%{source_label} : %{error_value}"
- detail_1_neptune_xml_2: "%{source_label} : %{error_value}"
-
- ## GTFS
- detail_1_gtfs_csv_1: "le fichier %{filename} est inexploitable"
- detail_1_gtfs_csv_2: "le fichier %{filename} est inexploitable"
- detail_1_gtfs_csv_3: "le fichier %{filename} contient un entête vide"
- detail_1_gtfs_csv_4: "le fichier %{filename} contient des entêtes en double"
- detail_1_gtfs_csv_5: "la ligne du fichier %{filename} ne respecte pas la syntaxe CSV"
- detail_1_gtfs_csv_6: "le fichier %{filename} contient des balises HTML"
- detail_1_gtfs_csv_7: "la valeur '%{error_value}' du champ %{reference_value} contient des espaces aux extrémités"
-
- detail_1_gtfs_common_1: "le fichier %{filename} est obligatoire"
- detail_1_gtfs_common_2: "l'un des fichiers calendar.txt ou calendar_dates.txt est obligatoire"
- detail_1_gtfs_common_3: "le fichier %{filename} optionnel n'est pas présent"
- detail_1_gtfs_common_4: "le fichier %{filename} n'est pas traité"
- detail_1_gtfs_common_5: "le fichier %{filename} obligatoire doit définir au moins une entrée"
- detail_1_gtfs_common_6: "l'un des deux fichiers calendar.txt ou calendar_dates.txt doit définir au moins une entrée"
- detail_1_gtfs_common_7: "le fichier %{filename} optionnel ne contient aucune entrée"
- detail_1_gtfs_common_8: "la valeur %{error_value} est définie plusieurs fois pour la colonne %{reference_value}"
- detail_1_gtfs_common_9: "la colonne %{error_value} est obligatoire"
- detail_1_gtfs_common_10: "la colonne agency_id devrait être présente dans le fichier %{filename}"
- detail_1_gtfs_common_11: "la colonne %{error_value} n'est pas exploitée dans le fichier %{filename}"
- detail_1_gtfs_common_12: "la valeur de la colonne %{error_value} n'est pas renseignée"
- detail_1_gtfs_common_13: "la colonne agency_id doit être présente dans le fichier %{filename}"
- detail_1_gtfs_common_14: "la colonne agency_id est absente dans le fichier %{filename}"
- detail_1_gtfs_common_15_1: "la valeur arrival_time est obligatoire en présence d'une valeur pour departure_time"
- detail_1_gtfs_common_15_2: "la valeur departure_time est obligatoire en présence d'une valeur pour arrival_time"
- detail_1_gtfs_common_15_3: "la valeur min_transfer_time est obligatoire quand transfer_type=2"
- detail_1_gtfs_common_16: "la valeur %{error_value} n'est pas autorisée pour le champs %{reference_value} "
-
- detail_1_gtfs_route_1: "les champs route_long_name et route_short_name ne sont pas définies"
- detail_1_gtfs_route_2: "les valeurs des champs route_long_name et route_short_name ne sont pas renseignées"
-
- detail_1_gtfs_calendar_1: "aucun jour d'application n'est activé"
- detail_1_gtfs_calendar_2: "la date de fin du calendrier est antérieur ou égale à la date début"
-
- #### level 2
- ## NEPTUNE
- detail_2_neptune_common_1: "L'élément %{source_objectid} a des attributs qui diffèrent entre les différents fichiers qui le définissent"
- detail_2_neptune_common_2: "L'élément %{source_objectid} partage l'attribut RegistrationNumber = %{error_value} avec un autre objet de même type"
- detail_2_neptune_network_1: "La ligne %{source_objectid} est absente de la liste des lignes du réseau %{target_0_objectid}"
- detail_2_neptune_network_2: "Le réseau %{source_objectid} a un type de source non valide : %{error_value}, remplacé par %{reference_value}"
- detail_2_neptune_groupofline_1: "La ligne %{source_objectid} est absente de la liste des lignes du du groupe de lignes %{target_0_objectid}"
- detail_2_neptune_stoparea_1: "Le fils (contains = %{error_value}) de l'arrêt %{source_objectid} n'est pas de type StopArea ni StopPoint"
- detail_2_neptune_stoparea_2: "L'arrêt %{source_objectid} de type %{reference_value} ne peut contenir que des arrêts de type StopPlace ou CommercialStopPoint, or un des arrêts contenus (contains = %{target_0_objectid}) est de type %{error_value}"
- detail_2_neptune_stoparea_3: "L'arrêt %{source_objectid} de type %{reference_value} ne peut contenir que des arrêts de type BoardingPosition ou Quay, or un des arrêts contenus (contains = %{target_0_objectid}) est de type %{error_value}"
- detail_2_neptune_stoparea_4: "L'arrêt %{source_objectid} de type %{reference_value} ne peut contenir que des points d'arrêt de séquence, or un des arrêts contenus (contains = %{target_0_objectid}) est un StopArea arrêt de type %{error_value}"
- detail_2_neptune_stoparea_5: "L'arrêt %{source_objectid} référence une position géographique (centroidOfArea = %{error_value}) inexistante"
- detail_2_neptune_stoparea_6: "L'arrêt %{source_objectid} référence une position géographique (centroidOfArea = %{target_0_objectid}) qui ne le référence pas en retour (containedIn = %{error_value})"
- detail_2_neptune_itl_1: "Le fils (contains = %{target_0_objectid}) de type %{error_value} ne peut pas être contenu dans l'arrêt %{source_objectid} de type %{reference_value}"
- detail_2_neptune_itl_2: "L'arrêt de type ITL %{source_objectid} n'est pas utilisé"
- detail_2_neptune_itl_3: "L'arrêt areaId = %{error_value} référencé par l'ITL %{source_objectid} n'existe pas"
- detail_2_neptune_itl_4: "L'arrêt areaId = %{target_0_objectid} référencé par l'ITL %{source_objectid} devrait être de type ITL et non de type %{error_value}"
- detail_2_neptune_itl_5: "La référence lineIdShortCut = %{error_value} de l'ITL %{source_objectid} n'est pas cohérente avec la ligne %{target_0_objectid}"
- detail_2_neptune_areacentroid_1: "La position géographique <AreaCentroid> %{source_objectid} référence un arrêt (containedIn = %{error_value}) inexistant"
- detail_2_neptune_areacentroid_2: "La position géographique <AreaCentroid> %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- detail_2_neptune_connectionlink_1: "La correspondance %{source_objectid} référence 2 arrêts inexistants"
- detail_2_neptune_accesspoint_1: "L'accès %{source_objectid} référence un arrêt parent (containedIn = %{error_value}) inexistant"
- detail_2_neptune_accesspoint_2: "L'accès %{source_objectid} référence un arrêt parent (containedIn = %{target_0_objectid}) de type invalide (ITL)"
- detail_2_neptune_accesspoint_3: "L'accès %{source_objectid} n'a pas de lien d'accès"
- detail_2_neptune_accesspoint_4: "L'accès %{source_objectid} de type In a des liens d'accès sortants"
- detail_2_neptune_accesspoint_5: "L'accès %{source_objectid} de type Out a des liens d'accès entrants"
- detail_2_neptune_accesspoint_6: "L'accès %{source_objectid} de type InOut n'a que des liens d'accès entrants ou sortants"
- detail_2_neptune_accesspoint_7: "L'accès %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- detail_2_neptune_accesslink_1: "La liaison d'accès %{source_objectid} référence %{error_value} qui n'existe pas"
- detail_2_neptune_accesslink_2: "Sur la liaison d'accès %{source_objectid}, les références startOfLink = %{error_value} et endOfLink = %{reference_value} sont de même type"
- detail_2_neptune_line_1: "La ligne %{source_objectid} référence un réseau (ptNetworkIdShortcut = %{error_value} inexistant"
- detail_2_neptune_line_2: "La ligne %{source_objectid} référence un point d'arrêt <StopPoint> (lineEnd = %{error_value}) inexistant "
- detail_2_neptune_line_3: "La ligne %{source_objectid} référence un point d'arrêt (lineEnd = %{error_value}) qui n'est pas terminus d'une séquence d'arrêts"
- detail_2_neptune_line_4: "La ligne %{source_objectid} référence une séquence d'arrêt (routeId = %{error_value}) inexistante"
- detail_2_neptune_line_5: "La séquence d'arrêts (routeId = %{target_0_objectid}) n'est pas référencée par la ligne %{source_objectid}"
- detail_2_neptune_line_6: "La ligne %{source_objectid} ne renseigne aucun des champs name, number ou publishedName"
- detail_2_neptune_route_1: "La séquence d'arrêts %{source_objectid} référence une mission (journeyPatternId = %{error_value}) inexistante"
- detail_2_neptune_route_2: "La séquence d'arrêts %{source_objectid} référence un tronçon (ptLinkId = %{error_value}) inexistant"
- detail_2_neptune_route_3: "La séquence retour (waybackRouteId = %{error_value}) de la séquence d'arrêts %{source_objectid} n'existe pas"
- detail_2_neptune_route_4: "Le tronçon (ptLinkId = %{error_value}) référencé par la séquence d'arrêt %{source_objectid} est partagé avec %{target_0_objectid}"
- detail_2_neptune_route_5: "Le tronçon %{source_objectid} partage un %{reference_value} : %{error_value} avec un autre tronçon"
- detail_2_neptune_route_6_1: "La séquence d'arrêts %{source_objectid} n'est pas une séquence linéaire, le chainage des tronçons forme un anneau"
- detail_2_neptune_route_6_2: "La séquence d'arrêts %{source_objectid} n'est pas une séquence linéaire, le chainage des tronçons est rompu au tronçon %{target_0_objectid}"
- detail_2_neptune_route_7: "La séquence d'arrêts %{source_objectid} ne référence pas la mission %{target_0_objectid} alors que cette mission référence la séquence d'arrêt"
- detail_2_neptune_route_8: "La mission journeyPatternId = %{target_0_objectid} de la séquence d'arrêts %{source_objectid} utilise des points d'arrêts hors séquence"
- detail_2_neptune_route_9: "Le point d'arrêt (stopPointId = %{target_0_objectid}) de la séquence d'arrêts %{source_objectid} n'est utilisé dans aucune mission"
- detail_2_neptune_route_10: "La séquence retour (waybackRouteId = %{target_0_objectid}) ne référence pas la séquence d'arrêts %{source_objectid} comme retour"
- detail_2_neptune_route_11: "Le sens (%{reference_value}) de la séquence d'arrêt %{source_objectid} n'est pas compatible avec celui (%{error_value}) de la séquence opposée %{target_0_objectid}"
- detail_2_neptune_route_12: "Le départ dans la zone %{reference_value}) de la séquence d'arrêts %{source_objectid} n'est pas dans la même zone que l'arrivée (zone %{error_value} de la séquence retour %{target_0_objectid}"
- detail_2_neptune_ptlink_1: "Le tronçon %{source_objectid} reférence un %{reference_value} = %{error_value} inexistant"
- detail_2_neptune_journeypattern_1: "La mission %{source_objectid} référence une séquence d'arrêts (routeId = %{error_value}) inexistante"
- detail_2_neptune_journeypattern_2: "La mission %{source_objectid} référence un point d'arrêt (stopPointId = %{error_value}) inexistant"
- detail_2_neptune_journeypattern_3: "La mission %{source_objectid} référence une ligne (lineIdShortcut = %{error_value}) inexistante"
- detail_2_neptune_stoppoint_1: "Le point d'arrêt %{source_objectid} référence une ligne (lineIdShortcut = %{error_value}) inexistante"
- detail_2_neptune_stoppoint_2: "Le point d'arrêt %{source_objectid} référence un réseau (ptNetworkIdShortcut = %{error_value}) inexistant"
- detail_2_neptune_stoppoint_3: "Le point d'arrêt %{source_objectid} référence un arrêt (containedIn = %{error_value}) inexistant"
- detail_2_neptune_stoppoint_4: "Le point d'arrêt %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- detail_2_neptune_timetable_1: "Le calendrier (<Timetable>) %{source_objectid} ne référence aucune course existante"
- detail_2_neptune_timetable_2: "La course %{source_objectid} n'est référencée dans aucun calendrier (<Timetable>)"
- detail_2_neptune_timetable_3: "Le calendrier (<Timetable>) %{source_objectid} contient une période invalide"
- detail_2_neptune_vehiclejourney_1: "La course %{source_objectid} référence une séquence d'arrêts (routeId = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_2: "La course %{source_objectid} référence une mission (journeyPatternId = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_3: "La course %{source_objectid} référence une ligne (lineIdShortcut = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_4: "La course %{source_objectid} référence un opérateur (operatorId = %{error_value}) inexistant"
- detail_2_neptune_vehiclejourney_5: "La course %{source_objectid} référence une fréquence horaire (timeSlotId = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_6: "La course %{source_objectid} référence une mission %{error_value} incompatible de la séquence d'arrêts %{reference_value}"
- detail_2_neptune_vehiclejourney_7: "La mission %{source_objectid} n'est référencée par aucune course"
- detail_2_neptune_vehiclejourney_8: "La course %{source_objectid} doit référencer une mission si la séquence d'arrêt en possède plusieurs"
- detail_2_neptune_vehiclejourneyatstop_1: "La course %{source_objectid} fournit un horaire sur un point d'arrêt (stopPointId = %{error_value}) inexistant"
- detail_2_neptune_vehiclejourneyatstop_2: "Un horaire de la course %{source_objectid} référence une autre course : vehicleJourneyId = %{error_value}"
- detail_2_neptune_vehiclejourneyatstop_3: "La course %{source_objectid} ne fournit pas les horaires des points d'arrêts selon l'ordre de la séquence d'arrêts %{error_value}"
- detail_2_neptune_vehiclejourneyatstop_4: "La course %{source_objectid} ne fournit pas les horaires des points d'arrêts de sa mission %{error_value}"
- detail_2_neptune_facility_1: "L'équipement %{source_objectid} est situé sur un arrêt inexistant (containedId = %{error_value})"
- detail_2_neptune_facility_2: "L'équipement %{source_objectid} référence un arrêt (stopAreaId = %{error_value}) inexistant"
- detail_2_neptune_facility_3: "L'équipement %{source_objectid} référence une ligne (lineId = %{error_value} inexistante"
- detail_2_neptune_facility_4: "L'équipement %{source_objectid} référence une correspondance (connectionLinkId = %{error_value} inexistante"
- detail_2_neptune_facility_5: "L'équipement %{source_objectid} référence un point d'arrêt (stopPointId = %{error_value} inexistant"
- detail_2_neptune_facility_6: "L'équipement %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
-
- ## GTFS
- detail_2_gtfs_common_1: "Identifiant %{reference_value} inconnu : %{error_value}"
- detail_2_gtfs_common_2: "Identifiant %{reference_value} non référencé : %{error_value}"
- detail_2_gtfs_common_3: "Le couple de champs (%{reference_value}) est en doublon (%{error_value}): "
- detail_2_gtfs_common_4: "Les valeurs des champs (%{reference_value}) sont identiques : '%{error_value}'"
- detail_2_gtfs_stop_1: "L'arrêt (%{source_objectid}) ne peut appartenir à un parent de type %{error_value}"
- detail_2_gtfs_stop_2: "La colonne location_type n'est pas renseignée"
- detail_2_gtfs_stop_3: "Le nom et la description de l'arrêt (%{source_objectid}) sont identiques : '%{error_value}'"
- detail_2_gtfs_stop_4: "L'arrêt (%{source_objectid}) de type station ne peut appartenir à une autre station (%{error_value})"
- detail_2_gtfs_route_1: "La route (%{source_objectid}) a la même valeur (%{error_value}) pour route_short_name et route_long_name"
- detail_2_gtfs_route_2: "La route (%{source_objectid}) réutilise la valeur de route_short_name (%{error_value}) dans route_long_name (%{reference_value})"
- detail_2_gtfs_route_3: "les couleurs de la route (%{source_objectid}) ne sont pas contrastées"
- detail_2_gtfs_route_4: "La route (%{source_objectid}) utilise les valeurs (route_short_name,route_long_name) de la route (%{error_value}) "
-
- #### level 3
- detail_3_stoparea_1: "L'arrêt %{source_label} (%{source_objectid}) n'est pas géolocalisé"
- detail_3_stoparea_2: "L'arrêt %{source_label} (%{source_objectid}) est localisé trop près de l'arrêt %{target_0_label} (%{target_0_objectid}) : distance %{error_value} < %{reference_value}"
- detail_3_stoparea_3: "Les arrêts %{source_label} (%{source_objectid} et %{target_0_objectid}) sont desservis par les mêmes lignes"
- detail_3_stoparea_4: "L'arrêt %{source_label} (%{source_objectid}) est en dehors du périmètre de contrôle"
- detail_3_stoparea_5: "L'arrêt %{source_label} (%{source_objectid}) est localisé trop loin de son parent %{target_0_label} (%{target_0_objectid}) : distance %{error_value} > %{reference_value}"
- detail_3_accesspoint_1: "L'accès %{source_label} (%{source_objectid}) n'est pas géolocalisé"
- detail_3_accesspoint_2: "L'accès %{source_label} (%{source_objectid}) est localisé trop près de l'accès %{target_0_label} (%{target_0_objectid}) : distance %{error_value} < %{reference_value}"
- detail_3_accesspoint_3: "L'accès %{source_label} (%{source_objectid}) est localisé trop loin de son parent %{target_0_label} (%{target_0_objectid}) : distance %{error_value} > %{reference_value}"
- detail_3_connectionlink_1: "Sur la correspondance %{source_label} (%{source_objectid}), la distance entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est trop grande : distance %{error_value} > %{reference_value}"
- detail_3_connectionlink_2: "Sur la correspondance %{source_label} (%{source_objectid}), la distance entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) : %{error_value} est supérieure à la longueur du lien : %{reference_value}"
- detail_3_connectionlink_3_1: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse par défaut %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_connectionlink_3_2: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse pour un voyageur occasionnel %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_connectionlink_3_3: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse pour un voyageur habitué %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_connectionlink_3_4: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse pour un voyageur à mobilité réduite %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_1: "Sur le lien d'accès %{source_label} (%{source_objectid}), la distance entre l'arrêt %{target_0_label} (%{target_0_objectid}) et l'accès %{target_1_label} (%{target_1_objectid}) est trop grande : distance %{error_value} > %{reference_value}"
- detail_3_accesslink_2: "Sur le lien d'accès %{source_label} (%{source_objectid}), la distance entre l'arrêt %{target_0_label} (%{target_0_objectid}) et l'accès %{target_1_label} (%{target_1_objectid}) : %{error_value} est supérieure à la longueur du lien : %{reference_value}"
- detail_3_accesslink_3_1: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse par défaut %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_3_2: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse pour un voyageur occasionnel %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_3_3: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse pour un voyageur habitué %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_3_4: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse pour un voyageur à mobilité réduite %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_line_1: "La ligne %{source_label} (%{source_objectid}) a une ligne homonyme sur le même réseau %{target_0_label} (%{target_0_objectid})"
- detail_3_line_2: "La ligne %{source_label} (%{source_objectid}) n'a pas de séquence d'arrêts"
- detail_3_route_1: "Sur la séquence d'arrêt %{source_label} (%{source_objectid}), l'arrêt %{target_0_label} (%{target_0_objectid}) est desservi 2 fois consécutivement"
- detail_3_route_2: "Les terminus de la séquence d'arrêt %{source_label} (%{source_objectid}) ne sont pas cohérent avec ceux de sa séquence opposée : l'une part de %{target_0_label} (%{target_0_objectid}) et l'autre arrive à %{target_1_label} (%{target_1_objectid})"
- detail_3_route_3_1: "Sur la séquence d'arrêt %{source_label} (%{source_objectid}), entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}), distance %{error_value} < %{reference_value} "
- detail_3_route_3_2: "Sur la séquence d'arrêt %{source_label} (%{source_objectid}), entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}), distance %{error_value} > %{reference_value} "
- detail_3_route_4: "La séquence d'arrêt %{source_label} (%{source_objectid}) utilise la même liste ordonnée d'arrêts que la séquence d'arrêts %{target_0_label} (%{target_0_objectid})"
- detail_3_route_5: "La séquence d'arrêt %{source_label} (%{source_objectid}) peut admettre la séquence %{target_0_label} (%{target_0_objectid}) comme séquence opposée"
- detail_3_route_6: "La séquence d'arrêt %{source_label} (%{source_objectid}) doit avoir un minimum de 2 arrêts"
- detail_3_route_7: "La séquence d'arrêt %{source_label} (%{source_objectid}) n'a pas de mission"
- detail_3_route_8: "La séquence d'arrêt %{source_label} (%{source_objectid}) a %{error_value} arrêts non utilisés par des missions"
- detail_3_route_9: "La séquence d'arrêt %{source_label} (%{source_objectid}) n'a pas de mission desservant l'ensemble de ses arrêts"
- detail_3_journeypattern_1: "La mission %{source_label} (%{source_objectid}) utilise les mêmes arrêts que la mission %{target_0_label} (%{target_0_objectid}) - nombre d'arrêts = %{error_value}"
- detail_3_vehiclejourney_1: "Arrêt %{target_0_label} (%{target_0_objectid}) : durée d'arrêt mesurée %{error_value} > %{reference_value}"
- detail_3_vehiclejourney_2_1: "La course %{source_label} (%{source_objectid}) a des horaires décroissants entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
- detail_3_vehiclejourney_2_2: "La course %{source_label} (%{source_objectid}) a une vitesse %{error_value} < %{reference_value} km/h entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
- detail_3_vehiclejourney_2_3: "La course %{source_label} (%{source_objectid}) a une vitesse %{error_value} > %{reference_value} km/h entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
- detail_3_vehiclejourney_3: "La course %{source_label} (%{source_objectid}) a une variation de progression entre les arrêts %{target_1_label} (%{target_1_objectid}) et %{target_2_label} (%{target_2_objectid}) %{error_value} > %{reference_value} avec la course %{target_0_label} (%{target_0_objectid})"
- detail_3_vehiclejourney_4: "La course %{source_label} (%{source_objectid}) n'a pas de calendrier d'application"
- detail_3_facility_1: "L'équipement %{source_label} (%{source_objectid}) n'est pas géolocalisé"
- detail_3_facility_2: "L'équipement %{source_label} (%{source_objectid}) est localisé trop loin de son parent %{areaName} (%{areaId}) : distance %{error_value} > %{reference_value}"
-
- detail_4_network_1_min_size: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value}) "
- detail_4_network_1_max_size: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_network_1_pattern: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_network_1_unique: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) a une valeur partagée avec le réseau %{target_0_label} (%{target_0_objectid})"
- detail_4_company_1_min_size: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_company_1_max_size: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_company_1_pattern: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_company_1_unique: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) a une valeur partagée avec le transporteur %{target_0_label} (%{target_0_objectid})"
- detail_4_groupofline_1_min_size: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_groupofline_1_max_size: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_groupofline_1_pattern: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_groupofline_1_unique: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) a une valeur partagée avec le groupe de lignes %{target_0_label} (%{target_0_objectid})"
- detail_4_stoparea_1_min_size: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_stoparea_1_max_size: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_stoparea_1_pattern: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_stoparea_1_unique: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) a une valeur partagée avec l'arrêt %{target_0_label} (%{target_0_objectid})"
- detail_4_stoparea_2: "L'arrêt physique %{source_label} (%{source_objectid}) n'a pas de parent"
- detail_4_accesspoint_1_min_size: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_accesspoint_1_max_size: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_accesspoint_1_pattern: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_accesspoint_1_unique: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) a une valeur partagée avec le point d'accès %{target_0_label} (%{target_0_objectid})"
- detail_4_accesslink_1_min_size: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_accesslink_1_max_size: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_accesslink_1_pattern: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_accesslink_1_unique: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) a une valeur partagée avec le lien d'accès %{target_0_label} (%{target_0_objectid})"
- detail_4_connectionlink_1_min_size: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_connectionlink_1_max_size: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_connectionlink_1_pattern: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_connectionlink_1_unique: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) a une valeur partagée avec la correspondance %{target_0_label} (%{target_0_objectid})"
- detail_4_connectionlink_2: "Sur la correspondance %{source_label} (%{source_objectid}) au moins l'un des arrêts %{startName} (%{startId}) et %{endName} (%{endId}) n'est pas un arrêt physique"
- detail_4_timetable_1_min_size: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_timetable_1_max_size: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_timetable_1_pattern: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_timetable_1_unique: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) a une valeur partagée avec le calendrier %{target_0_label} (%{target_0_objectid})"
- detail_4_line_1_min_size: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_line_1_max_size: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_line_1_pattern: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_line_1_unique: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) a une valeur partagée avec la ligne %{target_0_label} (%{target_0_objectid})"
- detail_4_line_2: "La ligne %{source_label} (%{source_objectid}) a un mode de transport interdit %{error_value}"
- detail_4_line_3_1: "La ligne %{source_label} (%{source_objectid}) n'a pas de groupe de lignes"
- detail_4_line_3_2: "La ligne %{source_label} (%{source_objectid}) a plusieurs groupes de lignes"
- detail_4_line_4_1: "La ligne %{source_label} (%{source_objectid}) n'a pas de séquence d'arrêts"
- detail_4_line_4_2: "La ligne %{source_label} (%{source_objectid}) a trop de séquences d'arrêts non associées (%{error_value})"
- detail_4_route_1_min_size: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_route_1_max_size: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_route_1_pattern: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_route_1_unique: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) a une valeur partagée avec la séquence d'arrêts %{target_0_label} (%{target_0_objectid})"
- detail_4_journeypattern_1_min_size: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_journeypattern_1_max_size: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_journeypattern_1_pattern: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_journeypattern_1_unique: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) a une valeur partagée avec la mission %{target_0_label} (%{target_0_objectid})"
- detail_4_vehiclejourney_1_min_size: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_vehiclejourney_1_max_size: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_vehiclejourney_1_pattern: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_vehiclejourney_1_unique: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) a une valeur partagée avec la course %{target_0_label} (%{target_0_objectid})"
- detail_4_vehiclejourney_2: "La course %{source_label} (%{source_objectid}) a un mode de transport interdit %{error_value}"
- activemodel:
- models:
- compliance_check_result:
- zero: "Validation"
- one: "Validation"
- other: "Validation"
- attributes:
- compliance_check_result:
- 1-NEPTUNE-XML-1: "Conformité à la syntaxe XML suivant les recommandations du W3C."
- 1-NEPTUNE-XML-2: "Conformité au schéma défini par la XSD du profil TRIDENT/NEPTUNE."
- 2-NEPTUNE-Common-1: "Unicité des éléments objectId des différents objets d'un lot de fichiers Neptune."
- 2-NEPTUNE-Common-2: "Unicité des éléments regitrationNumber des différents objets d'un lot de fichiers Neptune."
- 2-NEPTUNE-Network-1: "Correcte référence à des lignes <Line> dans version du réseau <PTNetwork>."
- 2-NEPTUNE-Network-2: "Valeur autorisée pour le type de source <SourceType> dans version du réseau <PTNetwork>."
- 2-NEPTUNE-GroupOfLine-1: "Correcte référence à des lignes <Line> dans groupe de lignes <GroupOfLine>."
- 2-NEPTUNE-StopArea-1: "Correcte référence à des arrêts <StopArea> et/ou à des points d'arrêt sur parcours <StopPoint> dans les arrêts <StopArea>."
- 2-NEPTUNE-StopArea-2: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type StopPlace."
- 2-NEPTUNE-StopArea-3: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type CommercialStopPoint."
- 2-NEPTUNE-StopArea-4: "Correcte référence à des points d'arrêt sur parcours <StopPoint> dans les arrêts <StopArea> de type BoardingPosition ou Quay."
- 2-NEPTUNE-StopArea-5: "Correcte référence à une position géographique <AreaCentroid> dans les arrêts <StopArea> de tout type StopPlace, CommercialStopPoint, BoardingPosition et Quay."
- 2-NEPTUNE-StopArea-6: "référenceréciproque d'une position géographique <AreaCentroid> dans les arrêts <StopArea> de tout type StopPlace, CommercialStopPoint, BoardingPosition et Quay."
- 2-NEPTUNE-ITL-1: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type ITL."
- 2-NEPTUNE-ITL-2: "Correcte référence à des arrêts <StopArea> de type ITL dans la classe d’objets <ITL>."
- 2-NEPTUNE-ITL-3: "Correcte référence à des arrêts <StopArea> dans la classe d’objets <ITL>."
- 2-NEPTUNE-ITL-4: "Vérification du type de référence à des arrêts <StopArea> type ITL dans la classe d’objets <ITL>."
- 2-NEPTUNE-ITL-5: "Bonne référence à la ligne <Line> dans la classe d’objets <ITL>."
- 2-NEPTUNE-AreaCentroid-1: "Correcte référence à des arrêts <StopArea> dans la classe d’objets <AreaCentroid>."
- 2-NEPTUNE-AreaCentroid-2: "Vérification du modèle de projection de référence utilisé."
- 2-NEPTUNE-ConnectionLink-1: "Correcte référence aux arrêts <StopArea> définissant des tronçons de correspondance <ConnectionLink>."
- 2-NEPTUNE-AccessPoint-1: "Correcte référence à un arrêt <StopArea> dans les accès <AccessPoint>."
- 2-NEPTUNE-AccessPoint-2: "Correcte référence à un arrêt <StopArea> dans les accès <AccessPoint>."
- 2-NEPTUNE-AccessPoint-3: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint>."
- 2-NEPTUNE-AccessPoint-4: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> de type 'in'."
- 2-NEPTUNE-AccessPoint-5: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> sur les accès de type 'out'."
- 2-NEPTUNE-AccessPoint-6: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> sur les accès de type 'inout'."
- 2-NEPTUNE-AccessPoint-7: "Vérification du modèle de projection de référence utilisé."
- 2-NEPTUNE-AccessLink-1: "Correcte référence aux arrêts <StopArea> et accès <AccessPoint> définissant des liens d'accès <AccessLink>."
- 2-NEPTUNE-AccessLink-2: "Correcte référence aux arrêts <StopArea> et accès <AccessPoint> définissant des liens d'accès <AccessLink>."
- 2-NEPTUNE-Line-1: "Correcte référence au réseau dans l'objet ligne <Line>."
- 2-NEPTUNE-Line-2: "Correcte référence à un point d'arrêt sur parcours <StopPoint> comme terminus de ligne <Line>."
- 2-NEPTUNE-Line-3: "Correcte référence à un point d'arrêt sur parcours <StopPoint> comme terminus de ligne <Line>."
- 2-NEPTUNE-Line-4: "Correcte référence aux séquences d'arrêts <ChouetteRoute> dans l'objet ligne <Line>."
- 2-NEPTUNE-Line-5: "Correcte référence aux séquences d'arrêts <ChouetteRoute> dans l'objet ligne <Line>."
- 2-NEPTUNE-Line-6: "Présence d'au moins une valeur parmi <name>,<number> ou <publishedName> dans l'objet ligne <Line>."
- 2-NEPTUNE-Route-1: "Existence des missions <JourneyPattern> référencées par la séquence d'arrêt <ChouetteRoute>."
- 2-NEPTUNE-Route-2: "Existence des tronçons commerciaux <PtLink> référencés par la séquence d'arrêt <ChouetteRoute>."
- 2-NEPTUNE-Route-3: "Existence de la séquence opposée <ChouetteRoute> référencée par la séquence d'arrêt <ChouetteRoute>."
- 2-NEPTUNE-Route-4: "Correcte référence à un tronçon commercial <PtLink> dans une séquence d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-5: "Vérification que tous les points d'arrêts sur parcours sont rattachés à une séquence d'arrêts <ChouetteRoute> au départ d'un tronçon commercial <PtLink> et/ou à l'arrivée d'un autre tronçon commercial <PtLink> de la même séquence d'arrêts."
- 2-NEPTUNE-Route-6: "Vérification du correct ordonnancement des points d'arrêts sur parcours <StopPoint> dans le chainage des tronçons <PtLink> d'une séquence d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-7: "référence mutuelle des missions <JourneyPattern> et des séquences d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-8: "Cohérence des références aux points d'arrêt des missions <JourneyPattern> et des séquences d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-9: "Utilité des points d'arrêts sur parcours des séquences d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-10: "référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée."
- 2-NEPTUNE-Route-11: "Cohérence des sens de la référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée."
- 2-NEPTUNE-Route-12: "Cohérence des terminus de la référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée."
- 2-NEPTUNE-PtLink-1: "Existence des arrêts <StopPoint> référencés par les tronçons commerciaux <PTLink>."
- 2-NEPTUNE-JourneyPattern-1: "Existence de la séquence d'arrêt <ChouetteRoute> référencée par la mission <JourneyPattern>."
- 2-NEPTUNE-JourneyPattern-2: "Existence des arrêts <StopPoint> référencés par la mission <JourneyPattern>."
- 2-NEPTUNE-JourneyPattern-3: "Existence de la ligne <Line> référencée par la mission <JourneyPattern>."
- 2-NEPTUNE-StopPoint-1: "Existence de la ligne <Line> référencée par l'arrêt <StopPoint>."
- 2-NEPTUNE-StopPoint-2: "Existence du réseau <PTNetwork> référence par l'arrêt <StopPoint>."
- 2-NEPTUNE-StopPoint-3: "Existence de l'arrêt <StopArea> référencé par l'arrêt <StopPoint>."
- 2-NEPTUNE-StopPoint-4: "Vérification du modèle de projection de référence utilisé."
- 2-NEPTUNE-Timetable-1: "Utilité des calendriers."
- 2-NEPTUNE-Timetable-2: "Utilité des calendriers."
- 2-NEPTUNE-Timetable-2: "Validité des dates de début et de fin des périodes des calendriers"
- 2-NEPTUNE-Timetable-3: "Validité des dates de début et de fin des périodes des calendriers"
- 2-NEPTUNE-VehicleJourney-1: "Existence de la séquence d'arrêt <ChouetteRoute> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-2: "Existence de la mission <JourneyPattern> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-3: "Existence de la ligne <Line> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-4: "Existence de l'opérateur <Company> référencé par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-5: "Existence de la tranche horaire <TimeSlot> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-6: "Cohérence entre la course, la mission et la séquence d'arrêts."
- 2-NEPTUNE-VehicleJourney-7: "Utilité des missions"
- 2-NEPTUNE-VehicleJourney-8: "Mission implicite"
- 2-NEPTUNE-VehicleJourneyAtStop-1: "Existence de l'arrêt <StopPoint> référencé par l'horaire <VehicleJourneyAtStop>."
- 2-NEPTUNE-VehicleJourneyAtStop-2: "Existence de la course <VehicleJourney> référenceé par l'horaire <VehicleJourneyAtStop>."
- 2-NEPTUNE-VehicleJourneyAtStop-3: "adéquation des horaires de la course à la séquence d'arrêts."
- 2-NEPTUNE-VehicleJourneyAtStop-4: "adéquation des horaires de la course à la mission."
- 2-NEPTUNE-Facility-1: "Existence de l'arrêt <StopArea> référencé par l'équipement <Facility>."
- 2-NEPTUNE-Facility-2: "Existence de l'arrêt <StopArea> référencé par l'équipement <Facility>."
- 2-NEPTUNE-Facility-3: "Existence de la ligne <Line> référencée par l'équipement <Facility>."
- 2-NEPTUNE-Facility-4: "Existence de la correspondance <ConnectionLink> référencée par l'équipement <Facility>."
- 2-NEPTUNE-Facility-5: "Existence de l'arrêt <StopPoint> référencé par l'équipement <Facility>."
- 2-NEPTUNE-Facility-6: "Vérification du modèle de projection de référence utilisé."
-
- ## GTFS
- 1-GTFS-CSV-1: "Contrôle de la lecture du fichier"
- 1-GTFS-CSV-2: "Contrôle de la syntaxe d'une ligne"
- 1-GTFS-CSV-3: "Contrôle de la syntaxe des entêtes"
- 1-GTFS-CSV-4: "Contrôle de la non présence de doublons dans les entêtes"
- 1-GTFS-CSV-5: "Contrôle de la syntaxe CSV GTFS du fichier"
- 1-GTFS-CSV-6: "Contrôle de la non présence de balise HTML"
- 1-GTFS-CSV-7: "Contrôle de la non présence d'espace en début ou fin de colonne"
-
- 1-GTFS-Common-1: "Contrôle de la présence des fichiers obligatoires"
- 1-GTFS-Common-2: "Contrôle de la présence des fichiers calendar ou calendar_dates"
- 1-GTFS-Common-3: "Contrôle de la présence des fichiers optionnels"
- 1-GTFS-Common-4: "Contrôle de la présence des fichiers non traités"
-
- 1-GTFS-Common-5: "Contrôle de la présence de données dans les fichiers obligatoires"
- 1-GTFS-Common-6: "Contrôle de la présence de données dans les fichiers calendar ou calendar_dates"
- 1-GTFS-Common-7: "Contrôle de la présence de données dans les fichiers optionnels"
-
- 1-GTFS-Common-8: "Contrôle de l'unicité des identifiants"
- 1-GTFS-Common-9: "Contrôle de la présence des colonnes obligatoires"
- 1-GTFS-Common-10: "Contrôle de la présence des colonnes qui devraient être obligatoires "
- 1-GTFS-Common-11: "Contrôle de la présence de colonnes non traités"
-
- 1-GTFS-Common-12: "Contrôle de la présence des données obligatoires"
- 1-GTFS-Common-13: "Contrôle de la présence de la colonne agency_id si plusieurs agences sont définies"
- 1-GTFS-Common-14: "Contrôle de la présence de la colonne agency_id même si une seule agence est définie"
- 1-GTFS-Common-15: "Contrôle de la présence d'une donnée sur valeur d'une autre"
-
- 1-GTFS-Common-16: "Contrôle du type des données"
-
- 1-GTFS-Route-1: "Contrôle de la présence des colonnes obligatoires conditionnelles"
- 1-GTFS-Route-2: "Contrôle de la présence de données dans route_long_name ou route_short_name"
-
- 1-GTFS-Calendar-1: "Contrôle de la présence d'au moins un jour d'application "
- 1-GTFS-Calendar-2: "Contrôle de la chronologie des dates de début et fin de période"
-
- 2-GTFS-Common-1: "Contrôle de la présence des objets référencés"
- 2-GTFS-Common-2: "Contrôle de l'utilité des objets"
- 2-GTFS-Common-3: "Contrôle de l'unicité d'un couple de données"
- 2-GTFS-Common-4: "Contrôle de la non redondance de valeurs"
- 2-GTFS-Stop-1: "Contrôle du type du parent_station"
- 2-GTFS-Stop-2: "Contrôle de l'utilité de la colonne location_type"
- 2-GTFS-Stop-3: "Contrôle de l'unicité de désignation (stop_name,stop_desc)"
- 2-GTFS-Stop-4: "Contrôle de la non présence de station dans des stations"
- 2-GTFS-Route-1: "Contrôle de la différence entre route_short_name et route_long_name"
- 2-GTFS-Route-2: "Contrôle de la non inclusion de route_short_name dans route_long_name"
- 2-GTFS-Route-3: "Contrôle du contraste des couleurs"
- 2-GTFS-Route-4: "Contrôle de la non présence d'une route inversant les valeurs route_short_name et route_long_name d'une autre"
-
- ## COMMON
- 3-StopArea-1: "Vérification de la géolocalisation de tous les arrêts hors ITL"
- 3-StopArea-2: "Vérification que 2 arrêts de noms différents en dehors d'un même regroupement d'arrêts ne sont pas trop proches"
- 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-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"
- 3-ConnectionLink-1: "Vérification de la proximité entre les deux arrêts d'une correspondance"
- 3-ConnectionLink-2: "Vérification de la cohérence entre la distance fournie sur la correspondance et la distance géographique entre les deux arrêts de la correspondance"
- 3-ConnectionLink-3: "Vérification de la vitesse de parcours entre les deux arrêts d'une correspondance"
- 3-AccessLink-1: "Vérification de la proximité entre les deux extrémités d'un lien d'accès"
- 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-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"
- 3-Route-4: "Vérification de double définition de séquences"
- 3-Route-5: "Vérification de séquences sans séquence opposée"
- 3-Route-6: "Vérification de la présence d'arrêts dans la séquence"
- 3-Route-7: "Vérification de la présence de missions"
- 3-Route-8: "Vérification de l'utilisation des arrêts par les missions"
- 3-Route-9: "Vérification de l’existence d’une mission passant par tous les arrêts de la séquence"
- 3-JourneyPattern-1: "Vérification de double définition de missions"
- 3-JourneyPattern-2: "Vérification de l’existence d’une mission passant par tous les arrêts de la séquence"
- 3-JourneyPattern-3: "Vérification de double définition de missions"
- 3-VehicleJourney-1: "Vérification de la chronologie des horaires de passage à un arrêt"
- 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-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"
- 4-Network-1: "Vérification de contraintes sur les attributs des réseaux"
- 4-Company-1: "Vérification de contraintes sur les attributs des transporteurs"
- 4-GroupOfLine-1: "Vérification de contraintes sur les attributs des groupes de lignes"
- 4-StopArea-1: "Vérification de contraintes sur les attributs des arrêts"
- 4-StopArea-2: "Vérification de l'existance d'un arrêt commercial pour les arrêts physiques"
- 4-StopArea-3: "Vérification de la cohérence entre les noms de communes et leur code INSEE"
- 4-AccessPoint-1: "Vérification de contraintes sur les attributs des accès"
- 4-AccessLink-1: "Vérification de contraintes sur les attributs des liens d'accès"
- 4-ConnectionLink-1: "Vérification de contraintes sur les attributs des correspondances"
- 4-ConnectionLink-2: "Vérification des type d'arrêts en correspondance"
- 4-Timetable-1: "Vérification de contraintes sur les attributs des calendiers"
- 4-Line-1: "Vérification de contraintes sur les attributs des lignes"
- 4-Line-2: "Vérification des modes de transport des lignes"
- 4-Line-3: "Vérification des groupes de lignes d'une ligne"
- 4-Line-4: "Vérification des séquences d'arrêts d'une ligne"
- 4-Route-1: "Vérification de contraintes sur les attributs des séquences d'arrêt"
- 4-JourneyPattern-1: "Vérification de contraintes sur les attributs des missions"
- 4-VehicleJourney-1: "Vérification de contraintes sur les attributs des courses"
- 4-VehicleJourney-2: "Vérification des modes de transport des courses"
- severity: "Severity"
- status: "Status"
- rule_level: "Level"
- rule_target: "Object"
- rule_number: "Step"
- rule_code: "Code"
- violation_count: "errors"
- violation_count_txt: "Number of errors"
- objects: "Objects in violations"
- detail: "Detail"
- title: "Test title"
- object: "Error object"
- resource: "Resources of the error object"
- url: "URL"
- first_violations: "First violations"
+
diff --git a/config/locales/compliance_check_results.fr.yml b/config/locales/compliance_check_results.fr.yml
index 19f436582..b3ddc53f2 100644
--- a/config/locales/compliance_check_results.fr.yml
+++ b/config/locales/compliance_check_results.fr.yml
@@ -1,457 +1,3 @@
fr:
compliance_check_results:
- errors: 'Erreurs'
- file:
- zip_name_prefix: "resultats_de_validation"
- summary_errors_file_prefix: "sommaire_des_tests.csv"
- detailed_errors_file_prefix: "details_des_erreurs.csv"
- index:
- line: "Li"
- column: "Col"
- in_progress: "Validation en cours..."
- compliance_check_result:
- severities:
- error: "Obligatoires"
- warning: "Optionnels"
- error_txt: "Obligatoire"
- warning_txt: "Optionnel"
- statuses:
- nok: "Erreur"
- uncheck: "Absent"
- ok: "Succès"
- details:
- #### level 1
- ## NEPTUNE
- detail_1_neptune_xml_1: "%{source_label} : %{error_value}"
- detail_1_neptune_xml_2: "%{source_label} : %{error_value}"
-
- ## GTFS
- detail_1_gtfs_csv_1: "le fichier %{filename} est inexploitable"
- detail_1_gtfs_csv_2: "le fichier %{filename} est inexploitable"
- detail_1_gtfs_csv_3: "le fichier %{filename} contient un entête vide"
- detail_1_gtfs_csv_4: "le fichier %{filename} contient des entêtes en double"
- detail_1_gtfs_csv_5: "la ligne du fichier %{filename} ne respecte pas la syntaxe CSV"
- detail_1_gtfs_csv_6: "le fichier %{filename} contient des balises HTML"
- detail_1_gtfs_csv_7: "la valeur '%{error_value}' du champ %{reference_value} contient des espaces aux extrémités"
-
- detail_1_gtfs_common_1: "le fichier %{filename} est obligatoire"
- detail_1_gtfs_common_2: "l'un des fichiers calendar.txt ou calendar_dates.txt est obligatoire"
- detail_1_gtfs_common_3: "le fichier %{filename} optionnel n'est pas présent"
- detail_1_gtfs_common_4: "le fichier %{filename} n'est pas traité"
- detail_1_gtfs_common_5: "le fichier %{filename} obligatoire doit définir au moins une entrée"
- detail_1_gtfs_common_6: "l'un des deux fichiers calendar.txt ou calendar_dates.txt doit définir au moins une entrée"
- detail_1_gtfs_common_7: "le fichier %{filename} optionnel ne contient aucune entrée"
- detail_1_gtfs_common_8: "la valeur %{error_value} est définie plusieurs fois pour la colonne %{reference_value}"
- detail_1_gtfs_common_9: "la colonne %{error_value} est obligatoire"
- detail_1_gtfs_common_10: "la colonne agency_id devrait être présente dans le fichier %{filename}"
- detail_1_gtfs_common_11: "la colonne %{error_value} n'est pas exploitée dans le fichier %{filename}"
- detail_1_gtfs_common_12: "la valeur de la colonne %{error_value} n'est pas renseignée"
- detail_1_gtfs_common_13: "la colonne agency_id doit être présente dans le fichier %{filename}"
- detail_1_gtfs_common_14: "la colonne agency_id est absente dans le fichier %{filename}"
- detail_1_gtfs_common_15_1: "la valeur arrival_time est obligatoire en présence d'une valeur pour departure_time"
- detail_1_gtfs_common_15_2: "la valeur departure_time est obligatoire en présence d'une valeur pour arrival_time"
- detail_1_gtfs_common_15_3: "la valeur min_transfer_time est obligatoire quand transfer_type=2"
- detail_1_gtfs_common_16: "la valeur %{error_value} n'est pas autorisée pour le champs %{reference_value} "
-
- detail_1_gtfs_route_1: "les champs route_long_name et route_short_name ne sont pas définies"
- detail_1_gtfs_route_2: "les valeurs des champs route_long_name et route_short_name ne sont pas renseignées"
-
- detail_1_gtfs_calendar_1: "aucun jour d'application n'est activé"
- detail_1_gtfs_calendar_2: "la date de fin du calendrier est antérieur ou égale à la date début"
-
- #### level 2
- ## NEPTUNE
- detail_2_neptune_common_1: "L'élément %{source_objectid} a des attributs qui diffèrent entre les différents fichiers qui le définissent"
- detail_2_neptune_common_2: "L'élément %{source_objectid} partage l'attribut RegistrationNumber = %{error_value} avec un autre objet de même type"
- detail_2_neptune_network_1: "La ligne %{source_objectid} est absente de la liste des lignes du réseau %{target_0_objectid}"
- detail_2_neptune_network_2: "Le réseau %{source_objectid} a un type de source non validee : %{error_value}, remplacé par %{reference_value}"
- detail_2_neptune_groupofline_1: "La ligne %{source_objectid} est absente de la liste des lignes du du groupe de lignes %{target_0_objectid}"
- detail_2_neptune_stoparea_1: "Le fils (contains = %{error_value}) de l'arrêt %{source_objectid} n'est pas de type StopArea ni StopPoint"
- detail_2_neptune_stoparea_2: "L'arrêt %{source_objectid} de type %{reference_value} ne peut contenir que des arrêts de type StopPlace ou CommercialStopPoint, or un des arrêts contenus (contains = %{target_0_objectid}) est de type %{error_value}"
- detail_2_neptune_stoparea_3: "L'arrêt %{source_objectid} de type %{reference_value} ne peut contenir que des arrêts de type BoardingPosition ou Quay, or un des arrêts contenus (contains = %{target_0_objectid}) est de type %{error_value}"
- detail_2_neptune_stoparea_4: "L'arrêt %{source_objectid} de type %{reference_value} ne peut contenir que des points d'arrêt de séquence, or un des arrêts contenus (contains = %{target_0_objectid}) est un StopArea arrêt de type %{error_value}"
- detail_2_neptune_stoparea_5: "L'arrêt %{source_objectid} référence une position géographique (centroidOfArea = %{error_value}) inexistante"
- detail_2_neptune_stoparea_6: "L'arrêt %{source_objectid} référence une position géographique (centroidOfArea = %{target_0_objectid}) qui ne le référence pas en retour (containedIn = %{error_value})"
- detail_2_neptune_itl_1: "Le fils (contains = %{target_0_objectid}) de type %{error_value} ne peut pas être contenu dans l'arrêt %{source_objectid} de type %{reference_value}"
- detail_2_neptune_itl_2: "L'arrêt de type ITL %{source_objectid} n'est pas utilisé"
- detail_2_neptune_itl_3: "L'arrêt areaId = %{error_value} référencé par l'ITL %{source_objectid} n'existe pas"
- detail_2_neptune_itl_4: "L'arrêt areaId = %{target_0_objectid} référencé par l'ITL %{source_objectid} devrait être de type ITL et non de type %{error_value}"
- detail_2_neptune_itl_5: "La référence lineIdShortCut = %{error_value} de l'ITL %{source_objectid} n'est pas cohérente avec la ligne %{target_0_objectid}"
- detail_2_neptune_areacentroid_1: "La position géographique <AreaCentroid> %{source_objectid} référence un arrêt (containedIn = %{error_value}) inexistant"
- detail_2_neptune_areacentroid_2: "La position géographique <AreaCentroid> %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- detail_2_neptune_connectionlink_1: "La correspondance %{source_objectid} référence 2 arrêts inexistants"
- detail_2_neptune_accesspoint_1: "L'accès %{source_objectid} référence un arrêt parent (containedIn = %{error_value}) inexistant"
- detail_2_neptune_accesspoint_2: "L'accès %{source_objectid} référence un arrêt parent (containedIn = %{target_0_objectid}) de type invalide (ITL)"
- detail_2_neptune_accesspoint_3: "L'accès %{source_objectid} n'a pas de lien d'accès"
- detail_2_neptune_accesspoint_4: "L'accès %{source_objectid} de type In a des liens d'accès sortants"
- detail_2_neptune_accesspoint_5: "L'accès %{source_objectid} de type Out a des liens d'accès entrants"
- detail_2_neptune_accesspoint_6: "L'accès %{source_objectid} de type InOut n'a que des liens d'accès entrants ou sortants"
- detail_2_neptune_accesspoint_7: "L'accès %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- detail_2_neptune_accesslink_1: "La liaison d'accès %{source_objectid} référence %{error_value} qui n'existe pas"
- detail_2_neptune_accesslink_2: "Sur la liaison d'accès %{source_objectid}, les références startOfLink = %{error_value} et endOfLink = %{reference_value} sont de même type"
- detail_2_neptune_line_1: "La ligne %{source_objectid} référence un réseau (ptNetworkIdShortcut = %{error_value} inexistant"
- detail_2_neptune_line_2: "La ligne %{source_objectid} référence un point d'arrêt <StopPoint> (lineEnd = %{error_value}) inexistant "
- detail_2_neptune_line_3: "La ligne %{source_objectid} référence un point d'arrêt (lineEnd = %{error_value}) qui n'est pas terminus d'une séquence d'arrêts"
- detail_2_neptune_line_4: "La ligne %{source_objectid} référence une séquence d'arrêt (routeId = %{error_value}) inexistante"
- detail_2_neptune_line_5: "La séquence d'arrêts (routeId = %{target_0_objectid}) n'est pas référencée par la ligne %{source_objectid}"
- detail_2_neptune_line_6: "La ligne %{source_objectid} ne renseigne aucun des champs name, number ou publishedName"
- detail_2_neptune_route_1: "La séquence d'arrêts %{source_objectid} référence une mission (journeyPatternId = %{error_value}) inexistante"
- detail_2_neptune_route_2: "La séquence d'arrêts %{source_objectid} référence un tronçon (ptLinkId = %{error_value}) inexistant"
- detail_2_neptune_route_3: "La séquence retour (waybackRouteId = %{error_value}) de la séquence d'arrêts %{source_objectid} n'existe pas"
- detail_2_neptune_route_4: "Le tronçon (ptLinkId = %{error_value}) référencé par la séquence d'arrêt %{source_objectid} est partagé avec %{target_0_objectid}"
- detail_2_neptune_route_5: "Le tronçon %{source_objectid} partage un %{reference_value} : %{error_value} avec un autre tronçon"
- detail_2_neptune_route_6_1: "La séquence d'arrêts %{source_objectid} n'est pas une séquence linéaire, le chainage des tronçons forme un anneau"
- detail_2_neptune_route_6_2: "La séquence d'arrêts %{source_objectid} n'est pas une séquence linéaire, le chainage des tronçons est rompu au tronçon %{target_0_objectid}"
- detail_2_neptune_route_7: "La séquence d'arrêts %{source_objectid} ne référence pas la mission %{target_0_objectid} alors que cette mission référence la séquence d'arrêt"
- detail_2_neptune_route_8: "La mission journeyPatternId = %{target_0_objectid} de la séquence d'arrêts %{source_objectid} utilise des points d'arrêts hors séquence"
- detail_2_neptune_route_9: "Le point d'arrêt (stopPointId = %{target_0_objectid}) de la séquence d'arrêts %{source_objectid} n'est utilisé dans aucune mission"
- detail_2_neptune_route_10: "La séquence retour (waybackRouteId = %{target_0_objectid}) ne référence pas la séquence d'arrêts %{source_objectid} comme retour"
- detail_2_neptune_route_11: "Le sens (%{reference_value}) de la séquence d'arrêt %{source_objectid} n'est pas compatible avec celui (%{error_value}) de la séquence opposée %{target_0_objectid}"
- detail_2_neptune_route_12: "Le départ dans la zone %{reference_value}) de la séquence d'arrêts %{source_objectid} n'est pas dans la même zone que l'arrivée (zone %{error_value} de la séquence retour %{target_0_objectid}"
- detail_2_neptune_ptlink_1: "Le tronçon %{source_objectid} reférence un %{reference_value} = %{error_value} inexistant"
- detail_2_neptune_journeypattern_1: "La mission %{source_objectid} référence une séquence d'arrêts (routeId = %{error_value}) inexistante"
- detail_2_neptune_journeypattern_2: "La mission %{source_objectid} référence un point d'arrêt (stopPointId = %{error_value}) inexistant"
- detail_2_neptune_journeypattern_3: "La mission %{source_objectid} référence une ligne (lineIdShortcut = %{error_value}) inexistante"
- detail_2_neptune_stoppoint_1: "Le point d'arrêt %{source_objectid} référence une ligne (lineIdShortcut = %{error_value}) inexistante"
- detail_2_neptune_stoppoint_2: "Le point d'arrêt %{source_objectid} référence un réseau (ptNetworkIdShortcut = %{error_value}) inexistant"
- detail_2_neptune_stoppoint_3: "Le point d'arrêt %{source_objectid} référence un arrêt (containedIn = %{error_value}) inexistant"
- detail_2_neptune_stoppoint_4: "Le point d'arrêt %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- detail_2_neptune_timetable_1: "Le calendrier (<Timetable>) %{source_objectid} ne référence aucune course existante"
- detail_2_neptune_timetable_2: "La course %{source_objectid} n'est référencée dans aucun calendrier (<Timetable>)"
- detail_2_neptune_timetable_3: "Le calendrier (<Timetable>) %{source_objectid} contient une période invalide"
- detail_2_neptune_vehiclejourney_1: "La course %{source_objectid} référence une séquence d'arrêts (routeId = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_2: "La course %{source_objectid} référence une mission (journeyPatternId = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_3: "La course %{source_objectid} référence une ligne (lineIdShortcut = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_4: "La course %{source_objectid} référence un opérateur (operatorId = %{error_value}) inexistant"
- detail_2_neptune_vehiclejourney_5: "La course %{source_objectid} référence une fréquence horaire (timeSlotId = %{error_value}) inexistante"
- detail_2_neptune_vehiclejourney_6: "La course %{source_objectid} référence une mission %{error_value} incompatible de la séquence d'arrêts %{reference_value}"
- detail_2_neptune_vehiclejourney_7: "La mission %{source_objectid} n'est référencée par aucune course"
- detail_2_neptune_vehiclejourney_8: "La course %{source_objectid} doit référencer une mission si la séquence d'arrêt en possède plusieurs"
- detail_2_neptune_vehiclejourneyatstop_1: "La course %{source_objectid} fournit un horaire sur un point d'arrêt (stopPointId = %{error_value}) inexistant"
- detail_2_neptune_vehiclejourneyatstop_2: "Un horaire de la course %{source_objectid} référence une autre course : vehicleJourneyId = %{error_value}"
- detail_2_neptune_vehiclejourneyatstop_3: "La course %{source_objectid} ne fournit pas les horaires des points d'arrêts selon l'ordre de la séquence d'arrêts %{error_value}"
- detail_2_neptune_vehiclejourneyatstop_4: "La course %{source_objectid} ne fournit pas les horaires des points d'arrêts de sa mission %{error_value}"
- detail_2_neptune_facility_1: "L'équipement %{source_objectid} est situé sur un arrêt inexistant (containedId = %{error_value})"
- detail_2_neptune_facility_2: "L'équipement %{source_objectid} référence un arrêt (stopAreaId = %{error_value}) inexistant"
- detail_2_neptune_facility_3: "L'équipement %{source_objectid} référence une ligne (lineId = %{error_value} inexistante"
- detail_2_neptune_facility_4: "L'équipement %{source_objectid} référence une correspondance (connectionLinkId = %{error_value} inexistante"
- detail_2_neptune_facility_5: "L'équipement %{source_objectid} référence un point d'arrêt (stopPointId = %{error_value} inexistant"
- detail_2_neptune_facility_6: "L'équipement %{source_objectid} utilise un référentiel géographique (longLatType = %{error_value}) invalide"
- ## GTFS
- detail_2_gtfs_common_1: "Identifiant %{reference_value} inconnu : %{error_value}"
- detail_2_gtfs_common_2: "Identifiant %{reference_value} non référencé : %{error_value}"
- detail_2_gtfs_common_3: "Le couple de champs (%{reference_value}) est en doublon (%{error_value}): "
- detail_2_gtfs_common_4: "Les valeurs des champs (%{reference_value}) sont identiques : '%{error_value}'"
- detail_2_gtfs_stop_1: "L'arrêt (%{source_objectid}) ne peut appartenir à un parent de type %{error_value}"
- detail_2_gtfs_stop_2: "La colonne location_type n'est pas renseignée"
- detail_2_gtfs_stop_3: "Le nom et la description de l'arrêt (%{source_objectid}) sont identiques : '%{error_value}'"
- detail_2_gtfs_stop_4: "L'arrêt (%{source_objectid}) de type station ne peut appartenir à une autre station (%{error_value})"
- detail_2_gtfs_route_1: "La route (%{source_objectid}) a la même valeur (%{error_value}) pour route_short_name et route_long_name"
- detail_2_gtfs_route_2: "La route (%{source_objectid}) réutilise la valeur de route_short_name (%{error_value}) dans route_long_name (%{reference_value})"
- detail_2_gtfs_route_3: "les couleurs de la route (%{source_objectid}) ne sont pas contrastées"
- detail_2_gtfs_route_4: "La route (%{source_objectid}) utilise les valeurs (route_short_name,route_long_name) de la route (%{error_value}) "
-
- #### level 3
- detail_3_stoparea_1: "L'arrêt %{source_label} (%{source_objectid}) n'est pas géolocalisé"
- detail_3_stoparea_2: "L'arrêt %{source_label} (%{source_objectid}) est localisé trop près de l'arrêt %{target_0_label} (%{target_0_objectid}) : distance %{error_value} < %{reference_value}"
- detail_3_stoparea_3: "Les arrêts %{source_label} (%{source_objectid} et %{target_0_objectid}) sont desservis par les mêmes lignes"
- detail_3_stoparea_4: "L'arrêt %{source_label} (%{source_objectid}) est en dehors du périmètre de contrôle"
- detail_3_stoparea_5: "L'arrêt %{source_label} (%{source_objectid}) est localisé trop loin de son parent %{target_0_label} (%{target_0_objectid}) : distance %{error_value} > %{reference_value}"
- detail_3_accesspoint_1: "L'accès %{source_label} (%{source_objectid}) n'est pas géolocalisé"
- detail_3_accesspoint_2: "L'accès %{source_label} (%{source_objectid}) est localisé trop près de l'accès %{target_0_label} (%{target_0_objectid}) : distance %{error_value} < %{reference_value}"
- detail_3_accesspoint_3: "L'accès %{source_label} (%{source_objectid}) est localisé trop loin de son parent %{target_0_label} (%{target_0_objectid}) : distance %{error_value} > %{reference_value}"
- detail_3_connectionlink_1: "Sur la correspondance %{source_label} (%{source_objectid}), la distance entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est trop grande : distance %{error_value} > %{reference_value}"
- detail_3_connectionlink_2: "Sur la correspondance %{source_label} (%{source_objectid}), la distance entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) : %{error_value} est supérieure à la longueur du lien : %{reference_value}"
- detail_3_connectionlink_3_1: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse par défaut %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_connectionlink_3_2: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse pour un voyageur occasionnel %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_connectionlink_3_3: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse pour un voyageur habitué %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_connectionlink_3_4: "Sur la correspondance %{source_label} (%{source_objectid}), la vitesse pour un voyageur à mobilité réduite %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_1: "Sur le lien d'accès %{source_label} (%{source_objectid}), la distance entre l'arrêt %{target_0_label} (%{target_0_objectid}) et l'accès %{target_1_label} (%{target_1_objectid}) est trop grande : distance %{error_value} > %{reference_value}"
- detail_3_accesslink_2: "Sur le lien d'accès %{source_label} (%{source_objectid}), la distance entre l'arrêt %{target_0_label} (%{target_0_objectid}) et l'accès %{target_1_label} (%{target_1_objectid}) : %{error_value} est supérieure à la longueur du lien : %{reference_value}"
- detail_3_accesslink_3_1: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse par défaut %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_3_2: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse pour un voyageur occasionnel %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_3_3: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse pour un voyageur habitué %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_accesslink_3_4: "Sur le lien d'accès %{source_label} (%{source_objectid}), la vitesse pour un voyageur à mobilité réduite %{error_value} est supérieure à %{reference_value} km/h"
- detail_3_line_1: "La ligne %{source_label} (%{source_objectid}) a une ligne homonyme sur le même réseau %{target_0_label} (%{target_0_objectid})"
- detail_3_line_2: "La ligne %{source_label} (%{source_objectid}) n'a pas de séquence d'arrêts"
- detail_3_route_1: "Sur la séquence d'arrêt %{source_label} (%{source_objectid}), l'arrêt %{target_0_label} (%{target_0_objectid}) est desservi 2 fois consécutivement"
- detail_3_route_2: "Les terminus de la séquence d'arrêt %{source_label} (%{source_objectid}) ne sont pas cohérent avec ceux de sa séquence opposée : l'une part de %{target_0_label} (%{target_0_objectid}) et l'autre arrive à %{target_1_label} (%{target_1_objectid})"
- detail_3_route_3_1: "Sur la séquence d'arrêt %{source_label} (%{source_objectid}), entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}), distance %{error_value} < %{reference_value} "
- detail_3_route_3_2: "Sur la séquence d'arrêt %{source_label} (%{source_objectid}), entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}), distance %{error_value} > %{reference_value} "
- detail_3_route_4: "La séquence d'arrêt %{source_label} (%{source_objectid}) utilise la même liste ordonnée d'arrêts que la séquence d'arrêts %{target_0_label} (%{target_0_objectid})"
- detail_3_route_5: "La séquence d'arrêt %{source_label} (%{source_objectid}) peut admettre la séquence %{target_0_label} (%{target_0_objectid}) comme séquence opposée"
- detail_3_route_6: "La séquence d'arrêt %{source_label} (%{source_objectid}) doit avoir un minimum de 2 arrêts"
- detail_3_route_7: "La séquence d'arrêt %{source_label} (%{source_objectid}) n'a pas de mission"
- detail_3_route_8: "La séquence d'arrêt %{source_label} (%{source_objectid}) a %{error_value} arrêts non utilisés par des missions"
- detail_3_route_9: "La séquence d'arrêt %{source_label} (%{source_objectid}) n'a pas de mission desservant l'ensemble de ses arrêts"
- detail_3_journeypattern_1: "La mission %{source_label} (%{source_objectid}) utilise les mêmes arrêts que la mission %{target_0_label} (%{target_0_objectid}) - nombre d'arrêts = %{error_value}"
- detail_3_vehiclejourney_1: "Arrêt %{target_0_label} (%{target_0_objectid}) : durée d'arrêt mesurée %{error_value} > %{reference_value}"
- detail_3_vehiclejourney_2_1: "La course %{source_label} (%{source_objectid}) a des horaires décroissants entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
- detail_3_vehiclejourney_2_2: "La course %{source_label} (%{source_objectid}) a une vitesse %{error_value} < %{reference_value} km/h entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
- detail_3_vehiclejourney_2_3: "La course %{source_label} (%{source_objectid}) a une vitesse %{error_value} > %{reference_value} km/h entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
- detail_3_vehiclejourney_3: "La course %{source_label} (%{source_objectid}) a une variation de progression entre les arrêts %{target_1_label} (%{target_1_objectid}) et %{target_2_label} (%{target_2_objectid}) %{error_value} > %{reference_value} avec la course %{target_0_label} (%{target_0_objectid})"
- detail_3_vehiclejourney_4: "La course %{source_label} (%{source_objectid}) n'a pas de calendrier d'application"
- detail_3_facility_1: "L'équipement %{source_label} (%{source_objectid}) n'est pas géolocalisé"
- detail_3_facility_2: "L'équipement %{source_label} (%{source_objectid}) est localisé trop loin de son parent %{areaName} (%{areaId}) : distance %{error_value} > %{reference_value}"
-
- detail_4_network_1_min_size: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value}) "
- detail_4_network_1_max_size: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_network_1_pattern: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_network_1_unique: "L'attribut %{reference_value} du réseau %{source_label} (%{source_objectid}) a une valeur partagée avec le réseau %{target_0_label} (%{target_0_objectid})"
- detail_4_company_1_min_size: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_company_1_max_size: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_company_1_pattern: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_company_1_unique: "L'attribut %{reference_value} du transporteur %{source_label} (%{source_objectid}) a une valeur partagée avec le transporteur %{target_0_label} (%{target_0_objectid})"
- detail_4_groupofline_1_min_size: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_groupofline_1_max_size: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_groupofline_1_pattern: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_groupofline_1_unique: "L'attribut %{reference_value} du groupe de lignes %{source_label} (%{source_objectid}) a une valeur partagée avec le groupe de lignes %{target_0_label} (%{target_0_objectid})"
- detail_4_stoparea_1_min_size: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_stoparea_1_max_size: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_stoparea_1_pattern: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_stoparea_1_unique: "L'attribut %{reference_value} de l'arrêt %{source_label} (%{source_objectid}) a une valeur partagée avec l'arrêt %{target_0_label} (%{target_0_objectid})"
- detail_4_stoparea_2: "L'arrêt physique %{source_label} (%{source_objectid}) n'a pas de parent"
- detail_4_accesspoint_1_min_size: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_accesspoint_1_max_size: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_accesspoint_1_pattern: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_accesspoint_1_unique: "L'attribut %{reference_value} du point d'accès %{source_label} (%{source_objectid}) a une valeur partagée avec le point d'accès %{target_0_label} (%{target_0_objectid})"
- detail_4_accesslink_1_min_size: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_accesslink_1_max_size: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_accesslink_1_pattern: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_accesslink_1_unique: "L'attribut %{reference_value} du lien d'accès %{source_label} (%{source_objectid}) a une valeur partagée avec le lien d'accès %{target_0_label} (%{target_0_objectid})"
- detail_4_connectionlink_1_min_size: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_connectionlink_1_max_size: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_connectionlink_1_pattern: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_connectionlink_1_unique: "L'attribut %{reference_value} de la correspondance %{source_label} (%{source_objectid}) a une valeur partagée avec la correspondance %{target_0_label} (%{target_0_objectid})"
- detail_4_connectionlink_2: "Sur la correspondance %{source_label} (%{source_objectid}) au moins l'un des arrêts %{startName} (%{startId}) et %{endName} (%{endId}) n'est pas un arrêt physique"
- detail_4_timetable_1_min_size: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_timetable_1_max_size: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_timetable_1_pattern: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_timetable_1_unique: "L'attribut %{reference_value} du calendrier %{source_label} (%{source_objectid}) a une valeur partagée avec le calendrier %{target_0_label} (%{target_0_objectid})"
- detail_4_line_1_min_size: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_line_1_max_size: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_line_1_pattern: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_line_1_unique: "L'attribut %{reference_value} de la ligne %{source_label} (%{source_objectid}) a une valeur partagée avec la ligne %{target_0_label} (%{target_0_objectid})"
- detail_4_line_2: "La ligne %{source_label} (%{source_objectid}) a un mode de transport interdit %{error_value}"
- detail_4_line_3_1: "La ligne %{source_label} (%{source_objectid}) n'a pas de groupe de lignes"
- detail_4_line_3_2: "La ligne %{source_label} (%{source_objectid}) a plusieurs groupes de lignes"
- detail_4_line_4_1: "La ligne %{source_label} (%{source_objectid}) n'a pas de séquence d'arrêts"
- detail_4_line_4_2: "La ligne %{source_label} (%{source_objectid}) a trop de séquences d'arrêts non associées (%{error_value})"
- detail_4_route_1_min_size: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_route_1_max_size: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_route_1_pattern: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_route_1_unique: "L'attribut %{reference_value} de la séquence d'arrêts %{source_label} (%{source_objectid}) a une valeur partagée avec la séquence d'arrêts %{target_0_label} (%{target_0_objectid})"
- detail_4_journeypattern_1_min_size: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_journeypattern_1_max_size: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_journeypattern_1_pattern: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_journeypattern_1_unique: "L'attribut %{reference_value} de la mission %{source_label} (%{source_objectid}) a une valeur partagée avec la mission %{target_0_label} (%{target_0_objectid})"
- detail_4_vehiclejourney_1_min_size: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) n'est pas renseigné ou trop petit (%{error_value})"
- detail_4_vehiclejourney_1_max_size: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) est trop grand (%{error_value})"
- detail_4_vehiclejourney_1_pattern: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) n'est pas au bon format (%{error_value})"
- detail_4_vehiclejourney_1_unique: "L'attribut %{reference_value} de la course %{source_label} (%{source_objectid}) a une valeur partagée avec la course %{target_0_label} (%{target_0_objectid})"
- detail_4_vehiclejourney_2: "La course %{source_label} (%{source_objectid}) a un mode de transport interdit %{error_value}"
- activemodel:
- models:
- compliance_check_result:
- zero: "Validation"
- one: "Validation"
- other: "Validations"
- attributes:
- compliance_check_result:
- ## Neptune
- 1-NEPTUNE-XML-1: "Conformité à la syntaxe XML suivant les recommandations du W3C."
- 1-NEPTUNE-XML-2: "Conformité au schéma défini par la XSD du profil TRIDENT/NEPTUNE."
- 2-NEPTUNE-Common-1: "Unicité des éléments objectId des différents objets d'un lot de fichiers Neptune."
- 2-NEPTUNE-Common-2: "Unicité des éléments regitrationNumber des différents objets d'un lot de fichiers Neptune."
- 2-NEPTUNE-Network-1: "Correcte référence à des lignes <Line> dans version du réseau <PTNetwork>."
- 2-NEPTUNE-Network-2: "Valeur autorisée pour le type de source <SourceType> dans version du réseau <PTNetwork>."
- 2-NEPTUNE-GroupOfLine-1: "Correcte référence à des lignes <Line> dans groupe de lignes <GroupOfLine>."
- 2-NEPTUNE-StopArea-1: "Correcte référence à des arrêts <StopArea> et/ou à des points d'arrêt sur parcours <StopPoint> dans les arrêts <StopArea>."
- 2-NEPTUNE-StopArea-2: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type StopPlace."
- 2-NEPTUNE-StopArea-3: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type CommercialStopPoint."
- 2-NEPTUNE-StopArea-4: "Correcte référence à des points d'arrêt sur parcours <StopPoint> dans les arrêts <StopArea> de type BoardingPosition ou Quay."
- 2-NEPTUNE-StopArea-5: "Correcte référence à une position géographique <AreaCentroid> dans les arrêts <StopArea> de tout type StopPlace, CommercialStopPoint, BoardingPosition et Quay."
- 2-NEPTUNE-StopArea-6: "référenceréciproque d'une position géographique <AreaCentroid> dans les arrêts <StopArea> de tout type StopPlace, CommercialStopPoint, BoardingPosition et Quay."
- 2-NEPTUNE-ITL-1: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type ITL."
- 2-NEPTUNE-ITL-2: "Correcte référence à des arrêts <StopArea> de type ITL dans la classe d’objets <ITL>."
- 2-NEPTUNE-ITL-3: "Correcte référence à des arrêts <StopArea> dans la classe d’objets <ITL>."
- 2-NEPTUNE-ITL-4: "Vérification du type de référence à des arrêts <StopArea> type ITL dans la classe d’objets <ITL>."
- 2-NEPTUNE-ITL-5: "Bonne référence à la ligne <Line> dans la classe d’objets <ITL>."
- 2-NEPTUNE-AreaCentroid-1: "Correcte référence à des arrêts <StopArea> dans la classe d’objets <AreaCentroid>."
- 2-NEPTUNE-AreaCentroid-2: "Vérification du modèle de projection de référence utilisé."
- 2-NEPTUNE-ConnectionLink-1: "Correcte référence aux arrêts <StopArea> définissant des tronçons de correspondance <ConnectionLink>."
- 2-NEPTUNE-AccessPoint-1: "Correcte référence à un arrêt <StopArea> dans les accès <AccessPoint>."
- 2-NEPTUNE-AccessPoint-2: "Correcte référence à un arrêt <StopArea> dans les accès <AccessPoint>."
- 2-NEPTUNE-AccessPoint-3: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint>."
- 2-NEPTUNE-AccessPoint-4: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> de type 'in'."
- 2-NEPTUNE-AccessPoint-5: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> sur les accès de type 'out'."
- 2-NEPTUNE-AccessPoint-6: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> sur les accès de type 'inout'."
- 2-NEPTUNE-AccessPoint-7: "Vérification du modèle de projection de référence utilisé."
- 2-NEPTUNE-AccessLink-1: "Correcte référence aux arrêts <StopArea> et accès <AccessPoint> définissant des liens d'accès <AccessLink>."
- 2-NEPTUNE-AccessLink-2: "Correcte référence aux arrêts <StopArea> et accès <AccessPoint> définissant des liens d'accès <AccessLink>."
- 2-NEPTUNE-Line-1: "Correcte référence au réseau dans l'objet ligne <Line>."
- 2-NEPTUNE-Line-2: "Correcte référence à un point d'arrêt sur parcours <StopPoint> comme terminus de ligne <Line>."
- 2-NEPTUNE-Line-3: "Correcte référence à un point d'arrêt sur parcours <StopPoint> comme terminus de ligne <Line>."
- 2-NEPTUNE-Line-4: "Correcte référence aux séquences d'arrêts <ChouetteRoute> dans l'objet ligne <Line>."
- 2-NEPTUNE-Line-5: "Correcte référence aux séquences d'arrêts <ChouetteRoute> dans l'objet ligne <Line>."
- 2-NEPTUNE-Line-6: "Présence d'au moins une valeur parmi <name>,<number> ou <publishedName> dans l'objet ligne <Line>."
- 2-NEPTUNE-Route-1: "Existence des missions <JourneyPattern> référencées par la séquence d'arrêt <ChouetteRoute>."
- 2-NEPTUNE-Route-2: "Existence des tronçons commerciaux <PtLink> référencés par la séquence d'arrêt <ChouetteRoute>."
- 2-NEPTUNE-Route-3: "Existence de la séquence opposée <ChouetteRoute> référencée par la séquence d'arrêt <ChouetteRoute>."
- 2-NEPTUNE-Route-4: "Correcte référence à un tronçon commercial <PtLink> dans une séquence d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-5: "Vérification que tous les points d'arrêts sur parcours sont rattachés à une séquence d'arrêts <ChouetteRoute> au départ d'un tronçon commercial <PtLink> et/ou à l'arrivée d'un autre tronçon commercial <PtLink> de la même séquence d'arrêts."
- 2-NEPTUNE-Route-6: "Vérification du correct ordonnancement des points d'arrêts sur parcours <StopPoint> dans le chainage des tronçons <PtLink> d'une séquence d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-7: "référence mutuelle des missions <JourneyPattern> et des séquences d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-8: "Cohérence des références aux points d'arrêt des missions <JourneyPattern> et des séquences d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-9: "Utilité des points d'arrêts sur parcours des séquences d'arrêts <ChouetteRoute>."
- 2-NEPTUNE-Route-10: "référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée."
- 2-NEPTUNE-Route-11: "Cohérence des sens de la référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée."
- 2-NEPTUNE-Route-12: "Cohérence des terminus de la référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée."
- 2-NEPTUNE-PtLink-1: "Existence des arrêts <StopPoint> référencés par les tronçons commerciaux <PTLink>."
- 2-NEPTUNE-JourneyPattern-1: "Existence de la séquence d'arrêt <ChouetteRoute> référencée par la mission <JourneyPattern>."
- 2-NEPTUNE-JourneyPattern-2: "Existence des arrêts <StopPoint> référencés par la mission <JourneyPattern>."
- 2-NEPTUNE-JourneyPattern-3: "Existence de la ligne <Line> référencée par la mission <JourneyPattern>."
- 2-NEPTUNE-StopPoint-1: "Existence de la ligne <Line> référencée par l'arrêt <StopPoint>."
- 2-NEPTUNE-StopPoint-2: "Existence du réseau <PTNetwork> référence par l'arrêt <StopPoint>."
- 2-NEPTUNE-StopPoint-3: "Existence de l'arrêt <StopArea> référencé par l'arrêt <StopPoint>."
- 2-NEPTUNE-StopPoint-4: "Vérification du modèle de projection de référence utilisé."
- 2-NEPTUNE-Timetable-1: "Utilité des calendriers."
- 2-NEPTUNE-Timetable-2: "Utilité des calendriers."
- 2-NEPTUNE-Timetable-3: "Validité des dates de début et de fin des périodes des calendriers"
- 2-NEPTUNE-VehicleJourney-1: "Existence de la séquence d'arrêt <ChouetteRoute> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-2: "Existence de la mission <JourneyPattern> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-3: "Existence de la ligne <Line> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-4: "Existence de l'opérateur <Company> référencé par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-5: "Existence de la tranche horaire <TimeSlot> référencée par la course <VehicleJourney>."
- 2-NEPTUNE-VehicleJourney-6: "Cohérence entre la course, la mission et la séquence d'arrêts."
- 2-NEPTUNE-VehicleJourney-7: "Utilité des missions"
- 2-NEPTUNE-VehicleJourney-8: "Mission implicite"
- 2-NEPTUNE-VehicleJourneyAtStop-1: "Existence de l'arrêt <StopPoint> référencé par l'horaire <VehicleJourneyAtStop>."
- 2-NEPTUNE-VehicleJourneyAtStop-2: "Existence de la course <VehicleJourney> référenceé par l'horaire <VehicleJourneyAtStop>."
- 2-NEPTUNE-VehicleJourneyAtStop-3: "adéquation des horaires de la course à la séquence d'arrêts."
- 2-NEPTUNE-VehicleJourneyAtStop-4: "adéquation des horaires de la course à la mission."
- 2-NEPTUNE-Facility-1: "Existence de l'arrêt <StopArea> référencé par l'équipement <Facility>."
- 2-NEPTUNE-Facility-2: "Existence de l'arrêt <StopArea> référencé par l'équipement <Facility>."
- 2-NEPTUNE-Facility-3: "Existence de la ligne <Line> référencée par l'équipement <Facility>."
- 2-NEPTUNE-Facility-4: "Existence de la correspondance <ConnectionLink> référencée par l'équipement <Facility>."
- 2-NEPTUNE-Facility-5: "Existence de l'arrêt <StopPoint> référencé par l'équipement <Facility>."
- 2-NEPTUNE-Facility-6: "Vérification du modèle de projection de référence utilisé."
-
- ## GTFS
- 1-GTFS-CSV-1: "Contrôle de la lecture du fichier"
- 1-GTFS-CSV-2: "Contrôle de la syntaxe d'une ligne"
- 1-GTFS-CSV-3: "Contrôle de la syntaxe des entêtes"
- 1-GTFS-CSV-4: "Contrôle de la non présence de doublons dans les entêtes"
- 1-GTFS-CSV-5: "Contrôle de la syntaxe CSV GTFS du fichier"
- 1-GTFS-CSV-6: "Contrôle de la non présence de balise HTML"
- 1-GTFS-CSV-7: "Contrôle de la non présence d'espace en début ou fin de colonne"
-
- 1-GTFS-Common-1: "Contrôle de la présence des fichiers obligatoires"
- 1-GTFS-Common-2: "Contrôle de la présence des fichiers calendar ou calendar_dates"
- 1-GTFS-Common-3: "Contrôle de la présence des fichiers optionnels"
- 1-GTFS-Common-4: "Contrôle de la présence des fichiers non traités"
-
- 1-GTFS-Common-5: "Contrôle de la présence de données dans les fichiers obligatoires"
- 1-GTFS-Common-6: "Contrôle de la présence de données dans les fichiers calendar ou calendar_dates"
- 1-GTFS-Common-7: "Contrôle de la présence de données dans les fichiers optionnels"
-
- 1-GTFS-Common-8: "Contrôle de l'unicité des identifiants"
- 1-GTFS-Common-9: "Contrôle de la présence des colonnes obligatoires"
- 1-GTFS-Common-10: "Contrôle de la présence des colonnes qui devraient être obligatoires "
- 1-GTFS-Common-11: "Contrôle de la présence de colonnes non traités"
-
- 1-GTFS-Common-12: "Contrôle de la présence des données obligatoires"
- 1-GTFS-Common-13: "Contrôle de la présence de la colonne agency_id si plusieurs agences sont définies"
- 1-GTFS-Common-14: "Contrôle de la présence de la colonne agency_id même si une seule agence est définie"
- 1-GTFS-Common-15: "Contrôle de la présence d'une donnée sur valeur d'une autre"
-
- 1-GTFS-Common-16: "Contrôle du type des données"
-
- 1-GTFS-Route-1: "Contrôle de la présence des colonnes obligatoires conditionnelles"
- 1-GTFS-Route-2: "Contrôle de la présence de données dans route_long_name ou route_short_name"
-
- 1-GTFS-Calendar-1: "Contrôle de la présence d'au moins un jour d'application "
- 1-GTFS-Calendar-2: "Contrôle de la chronologie des dates de début et fin de période"
-
- 2-GTFS-Common-1: "Contrôle de la présence des objets référencés"
- 2-GTFS-Common-2: "Contrôle de l'utilité des objets"
- 2-GTFS-Common-3: "Contrôle de l'unicité d'un couple de données"
- 2-GTFS-Common-4: "Contrôle de la non redondance de valeurs"
- 2-GTFS-Stop-1: "Contrôle du type du parent_station"
- 2-GTFS-Stop-2: "Contrôle de l'utilité de la colonne location_type"
- 2-GTFS-Stop-3: "Contrôle de l'unicité de désignation (stop_name,stop_desc)"
- 2-GTFS-Stop-4: "Contrôle de la non présence de station dans des stations"
- 2-GTFS-Route-1: "Contrôle de la différence entre route_short_name et route_long_name"
- 2-GTFS-Route-2: "Contrôle de la non inclusion de route_short_name dans route_long_name"
- 2-GTFS-Route-3: "Contrôle du contraste des couleurs"
- 2-GTFS-Route-4: "Contrôle de la non présence d'une route inversant les valeurs route_short_name et route_long_name d'une autre"
-
- ## COMMON
- 3-StopArea-1: "Vérification de la géolocalisation de tous les arrêts hors ITL"
- 3-StopArea-2: "Vérification que 2 arrêts de noms différents en dehors d'un même regroupement d'arrêts ne sont pas trop proches"
- 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-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"
- 3-ConnectionLink-1: "Vérification de la proximité entre les deux arrêts d'une correspondance"
- 3-ConnectionLink-2: "Vérification de la cohérence entre la distance fournie sur la correspondance et la distance géographique entre les deux arrêts de la correspondance"
- 3-ConnectionLink-3: "Vérification de la vitesse de parcours entre les deux arrêts d'une correspondance"
- 3-AccessLink-1: "Vérification de la proximité entre les deux extrémités d'un lien d'accès"
- 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-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"
- 3-Route-4: "Vérification de double définition de séquences"
- 3-Route-5: "Vérification de séquences sans séquence opposée"
- 3-Route-6: "Vérification de la présence d'arrêts dans la séquence"
- 3-Route-7: "Vérification de la présence de missions"
- 3-Route-8: "Vérification de l'utilisation des arrêts par les missions"
- 3-Route-9: "Vérification de l’existence d’une mission passant par tous les arrêts de la séquence"
- 3-JourneyPattern-1: "Vérification de l'utilisation des arrêts par les missions"
- 3-JourneyPattern-2: "Vérification de l’existence d’une mission passant par tous les arrêts de la séquence"
- 3-JourneyPattern-3: "Vérification de double définition de missions"
- 3-VehicleJourney-1: "Vérification de la chronologie des horaires de passage à un arrêt"
- 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-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"
- 4-Network-1: "Vérification de contraintes sur les attributs des réseaux"
- 4-Company-1: "Vérification de contraintes sur les attributs des transporteurs"
- 4-GroupOfLine-1: "Vérification de contraintes sur les attributs des groupes de lignes"
- 4-StopArea-1: "Vérification de contraintes sur les attributs des arrêts"
- 4-StopArea-2: "Vérification de l'existance d'un arrêt commercial pour les arrêts physiques"
- 4-StopArea-3: "Vérification de la cohérence entre les noms de communes et leur code INSEE"
- 4-AccessPoint-1: "Vérification de contraintes sur les attributs des accès"
- 4-AccessLink-1: "Vérification de contraintes sur les attributs des liens d'accès"
- 4-ConnectionLink-1: "Vérification de contraintes sur les attributs des correspondances"
- 4-ConnectionLink-2: "Vérification des type d'arrêts en correspondance"
- 4-Timetable-1: "Vérification de contraintes sur les attributs des calendiers"
- 4-Line-1: "Vérification de contraintes sur les attributs des lignes"
- 4-Line-2: "Vérification des modes de transport des lignes"
- 4-Line-3: "Vérification des groupes de lignes d'une ligne"
- 4-Line-4: "Vérification des séquences d'arrêts d'une ligne"
- 4-Route-1: "Vérification de contraintes sur les attributs des séquences d'arrêt"
- 4-JourneyPattern-1: "Vérification de contraintes sur les attributs des missions"
- 4-VehicleJourney-1: "Vérification de contraintes sur les attributs des courses"
- 4-VehicleJourney-2: "Vérification des modes de transport des courses"
- severity: "Sévérité"
- status: "Statut"
- rule_level: "Niveau"
- rule_target: "Objet"
- rule_number: "Etape"
- rule_code: "Code"
- violation_count: "erreurs"
- violation_count_txt: "Nombre d'erreurs"
- objects: "Objets en erreur"
- detail: "Détail"
- title: "Titre du test"
- object: "Objet en erreur"
- resource: "Ressource de l'objet en erreur"
- url: "URL"
- first_violations: "Premières violations"
+
diff --git a/config/locales/compliance_check_tasks.en.yml b/config/locales/compliance_check_tasks.en.yml
deleted file mode 100644
index 61e56473c..000000000
--- a/config/locales/compliance_check_tasks.en.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-en:
- compliance_check_tasks:
- new:
- 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"
- activemodel:
- attributes:
- compliance_check_task:
- name: "Compliance check name"
- references_type: "Subset"
- reference_ids: "Subset ids"
- object_id_prefix: "Neptune Id prefix"
- rule_parameter_set_id: "Jeu de paramètres pour validation" \ No newline at end of file
diff --git a/config/locales/compliance_check_tasks.fr.yml b/config/locales/compliance_check_tasks.fr.yml
deleted file mode 100644
index d6cc88b1e..000000000
--- a/config/locales/compliance_check_tasks.fr.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-fr:
- compliance_check_tasks:
- new:
- 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"
- activemodel:
- attributes:
- compliance_check_task:
- name: "Nom de la validation"
- references_type: "Sous ensemble"
- reference_ids: "Identifiants du sous ensemble"
- object_id_prefix: "Préfixe Neptune Id"
- rule_parameter_set_id: "Jeu de paramètres pour validation"
diff --git a/config/locales/compliance_checks.en.yml b/config/locales/compliance_checks.en.yml
index c9bac8bc3..7f3e317be 100644
--- a/config/locales/compliance_checks.en.yml
+++ b/config/locales/compliance_checks.en.yml
@@ -1,93 +1,2 @@
en:
compliance_checks:
- index:
- title: "Validation"
- warning: ""
- edit:
- title: "Edit the Validation"
- show:
- title: "Neptune Validation"
- summary: "Rapport de conformité à la norme NEPTUNE"
- details: "Details"
- parameters: "Tests parameters"
- completed: "[ Completed ]"
- failed: "[ Failed ]"
- pending: "[ In the treatment queue ]"
- processing: "[ In progress... ]"
- export: "Download test report"
- export_csv: "CSV format"
- report:
- validation_success: "Validation successfully passed."
- action_report: "Action report"
- actions:
- destroy_confirm: "Do you confirm to destroy this validation ?"
- destroy: "Destroy this validation"
- edit: "Edit this validation"
- report: "Report"
- rule_parameter_set: "Rule parameter set"
- download: "Download"
- statuses:
- pending: "Pending"
- processing: "Processing"
- completed: "Completed"
- failed: "Failed"
- started: "Started"
- scheduled: "Processing ..."
- terminated: "Completed"
- canceled: "Canceled"
- aborted: "Failed"
- uncheck_count:
- zero: "no unappliable"
- one: "one unappliable"
- other: "%{count} unappliables"
- ok_count:
- zero: "No successful test"
- one: "One successful test"
- other: "%{count} successful tests"
- warning_count:
- zero: "no warning"
- one: "one warning"
- other: "%{count} warnings"
- error_count:
- zero: "no error"
- one: "one error"
- other: "%{count} errors"
- fatal_count:
- zero: "no fatal error"
- one: "one fatal error"
- other: "%{count} fatal errors"
- import: "Import"
- rule_parameter_set: "Rule parameter set"
- file_validation_log_messages:
- messages:
- undefined: "%{key} undefined"
- TooMuchDetails: ( %{0} errors / suppl. warnings )
- ONE: "Catégorie 1 : Syntaxe"
- severities:
- uncheck: "Unchecked"
- ok: "Ok"
- warning: "Warning"
- error: "Error"
- fatal: "Fatal"
- import: "Import Report"
- rule_parameter_set: "Rule Parameter Set"
- activemodel:
- models:
- compliance_check:
- zero: "Validation"
- one: "Validation"
- other: "Validation"
- attributes:
- compliance_check:
- created_at: "Executed at"
- references_type: "Associated Data Type"
- reference_ids: "Associated Data"
- rule_parameter_set_id: "Rule parameters set"
- resources: "File to validate"
- status: "Status"
- file_name: "Tested data"
- projection_reference: "Système de projection de référence"
- compliance_check_log_message:
- created_at: "Date"
- position: "N."
- full_message: "Message"
diff --git a/config/locales/compliance_checks.fr.yml b/config/locales/compliance_checks.fr.yml
index 14ae7e943..421574cbd 100644
--- a/config/locales/compliance_checks.fr.yml
+++ b/config/locales/compliance_checks.fr.yml
@@ -1,93 +1,3 @@
fr:
compliance_checks:
- index:
- title: "Validation"
- warning: ""
- edit:
- title: "Editer la validation"
- show:
- title: "Validation Neptune"
- summary: "Rapport de conformité à la norme NEPTUNE"
- details: "Détails"
- parameters: "Paramètres des tests"
- completed: "[ Terminé ]"
- failed: "[ Echoué ]"
- pending: "[ En file d'attente ]"
- processing: "[ En progression... ]"
- export: "Télécharger les résultats"
- export_csv: "Format CSV"
- report:
- validation_success: "La validation est passée avec succès."
- action_report: "Rapport d'action"
- actions:
- destroy_confirm: "Voulez-vous supprimer ce résultat de validation ?"
- destroy: "Supprimer cette validation"
- edit: "Editer cette validation"
- report: "Test de conformité"
- rule_parameter_set: "Jeu de paramètres"
- download: "Télécharger"
- statuses:
- pending: "En attente ..."
- processing: "En cours ..."
- completed: "Achevé"
- failed: "Echoué"
- started: "En file d'attente..."
- scheduled: "En cours..."
- terminated: "Achevé"
- canceled: "Annulé"
- aborted: "Echoué"
- uncheck_count:
- zero: "aucun inapplicable"
- one: "un inapplicable"
- other: "%{count} inapplicables"
- ok_count:
- zero: "aucun test réussi"
- one: "un test réussi"
- other: "%{count} tests réussis"
- warning_count:
- zero: "aucun warning"
- one: "un warning"
- other: "%{count} warnings"
- error_count:
- zero: "aucune erreur"
- one: "une erreur"
- other: "%{count} erreurs"
- fatal_count:
- zero: "aucune erreur fatale"
- one: "une erreur fatale"
- other: "%{count} erreurs fatales"
- import: "Import"
- rule_parameter_set: "Jeu de paramètres"
- file_validation_log_messages:
- messages:
- undefined: "%{key} non défini"
- TooMuchDetails: "( %{0} erreurs / warnings supplémentaires )"
- ONE: "Catégorie 1 : Syntaxe"
- severities:
- uncheck: "Non testé"
- ok: "Ok"
- warning: "Alerte"
- error: "Erreur"
- fatal: "Fatal"
- import: "Import Report"
- rule_parameter_set: "Rule Parameter Set"
- activemodel:
- models:
- compliance_check:
- zero: "Validation"
- one: "Validation"
- other: "Validations"
- attributes:
- compliance_check:
- created_at: "Exécuté le"
- references_type: "Type de données incluses"
- reference_ids: "Données incluses"
- rule_parameter_set_id: "Jeu de paramètres"
- resources: "Fichier à valider"
- status: "Status"
- file_name: "Jeu de données"
- projection_reference: "Système de projection de référence"
- compliance_check_log_message:
- created_at: "Date"
- position: "N."
- full_message: "Message"
+
diff --git a/config/locales/import_messages.en.yml b/config/locales/import_messages.en.yml
new file mode 100644
index 000000000..7f8fc622d
--- /dev/null
+++ b/config/locales/import_messages.en.yml
@@ -0,0 +1,50 @@
+en:
+ compliance_check_messages:
+ import_messages:
+ referential_creation: "The referential can't be created because another one has same periods and lines"
+ 1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
+ 1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN"
+ 2_netexstif_1_2: "Le fichier commun.xml contient une frame nommée %{source_label} non acceptée"
+ 2_netexstif_2_1: "Le fichier calendriers.xml ne contient pas de frame nommée NETEX_CALENDRIER"
+ 2_netexstif_2_2: "Le fichier calendriers.xml contient une frame nommée %{source_label} non acceptée"
+ 2_netexstif_3_1: "Le fichier %{source_filename} ne contient pas de frame nommée NETEX_OFFRE_LIGNE"
+ 2_netexstif_3_2: "Le fichier %{source_filename} contient une frame nommée %{source_label} non acceptée"
+ 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{NETEX_STRUCTURE|NETEX_HORAIRE} obligatoire"
+ 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{source_label} non acceptée"
+ 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{source_label} ne respecte pas la syntaxe [CODESPACE]:%{source_label}:[identifiant Technique]:LOC"
+ 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
+ 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{reference_value}"
+ 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type externe : référence interne attendue"
+ 2_netexstif_8_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type interne mais disposant d'un contenu (version externe possible)"
+ 2_netexstif_9_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type interne : référence externe attendue"
+ 2_netexstif_9_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type externe sans information de version"
+ 2_netexstif_10: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type externe inconnue"
+ 2_netexstif_daytype_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} ne définit aucun calendrier, il est ignoré"
+ 2_netexstif_daytype_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} est reliée à des périodes mais ne définit pas de types de jours"
+ 2_netexstif_daytypeassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingDay"
+ 2_netexstif_daytypeassignment_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingPeriod sur la condition IsAvailable à faux."
+ 2_netexstif_direction_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut Name"
+ 2_netexstif_direction_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} définit un attribut %{error_value} non autorisé"
+ 2_netexstif_notice_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} doit définir un texte"
+ 2_netexstif_notice_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} de type %{reference_value} est ignoré"
+ 2_netexstif_operatingperiod_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet OperatingPeriod d'identifiant %{source_objectid} a une date de fin %{start_date} inférieure ou égale à la date de début %{end_date}"
+ 2_netexstif_passengerstopassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'attribut %{source_label} de l'objet PassengerStopAssignment %{source_objectid} doit être renseigné"
+ 2_netexstif_passengerstopassignment_2: "L'arrêt %{source_objectid} ne fait pas partie des arrêts disponibles pour votre organisation."
+ 2_netexstif_passingtime_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} ne dispose pas de DepartureTime"
+ 2_netexstif_passingtime_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit un ArrivalTime supérieur à son DepartureTime"
+ 2_netexstif_route_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} a une valeur de l'attribut DirectionType interdite : %{error_value}"
+ 2_netexstif_route_2_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{reference_value} qui ne le référence pas"
+ 2_netexstif_route_2_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{reference_value} de même DirectionType"
+ 2_netexstif_route_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Les ServiceJourneyPattern de l'objet Route d'identifiant %{source_objectid} ne permettent pas de reconstituer la séquence des arrêts de celui-ci"
+ 2_netexstif_route_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, Les informations de montée/Descente à l'arrêt %{source_label} de la Route %{source_objectid} diffèrent sur plusieurs ServiceJourneyPattern, ces informations ne sont pas importées"
+ 2_netexstif_routingconstraintzone_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} doit référencer au moins deux ScheduledStopPoint"
+ 2_netexstif_routingconstraintzone_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} a une valeur interdite pour l'attribut ZoneUse : %{error_value}"
+ 2_netexstif_servicejourney_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} ne référence pas de ServiceJourneyPattern"
+ 2_netexstif_servicejourney_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} fournit plus d'un trainNumber"
+ 2_netexstif_servicejourney_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Le nombre d'horaires (passing_times) de l'objet ServiceJourney d'identifiant %{source_objectid} n'est pas cohérent avec le ServiceJourneyPattern associé."
+ 2_netexstif_servicejourney_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{rank} fournit des horaires antérieurs au passingTime précédent."
+ 2_netexstif_servicejourneypattern_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} ne référence pas de Route"
+ 2_netexstif_servicejourneypattern_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} doit contenir au moins 2 StopPointInJourneyPattern"
+ 2_netexstif_servicejourneypattern_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut ServiceJourneyPatternType"
+ 2_netexstif_servicejourneypattern_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, objet ServiceJourneyPattern d'identifiant %{source_objectid} : les attributs 'order' des StopPointInJourneyPattern ne sont pas croissants."
diff --git a/config/locales/import_messages.fr.yml b/config/locales/import_messages.fr.yml
new file mode 100644
index 000000000..09951c561
--- /dev/null
+++ b/config/locales/import_messages.fr.yml
@@ -0,0 +1,50 @@
+fr:
+ import_messages:
+ compliance_check_messages:
+ referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les même périodes et lignes"
+ 1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
+ 1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN"
+ 2_netexstif_1_2: "Le fichier commun.xml contient une frame nommée %{source_label} non acceptée"
+ 2_netexstif_2_1: "Le fichier calendriers.xml ne contient pas de frame nommée NETEX_CALENDRIER"
+ 2_netexstif_2_2: "Le fichier calendriers.xml contient une frame nommée %{source_label} non acceptée"
+ 2_netexstif_3_1: "Le fichier %{source_filename} ne contient pas de frame nommée NETEX_OFFRE_LIGNE"
+ 2_netexstif_3_2: "Le fichier %{source_filename} contient une frame nommée %{source_label} non acceptée"
+ 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{NETEX_STRUCTURE|NETEX_HORAIRE} obligatoire"
+ 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{source_label} non acceptée"
+ 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{source_label} ne respecte pas la syntaxe [CODESPACE]:%{source_label}:[identifiant Technique]:LOC"
+ 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
+ 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{reference_value}"
+ 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type externe : référence interne attendue"
+ 2_netexstif_8_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type interne mais disposant d'un contenu (version externe possible)"
+ 2_netexstif_9_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type interne : référence externe attendue"
+ 2_netexstif_9_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type externe sans information de version"
+ 2_netexstif_10: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de type externe inconnue"
+ 2_netexstif_daytype_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} ne définit aucun calendrier, il est ignoré"
+ 2_netexstif_daytype_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} est reliée à des périodes mais ne définit pas de types de jours"
+ 2_netexstif_daytypeassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingDay"
+ 2_netexstif_daytypeassignment_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingPeriod sur la condition IsAvailable à faux."
+ 2_netexstif_direction_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut Name"
+ 2_netexstif_direction_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} définit un attribut %{error_value} non autorisé"
+ 2_netexstif_notice_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} doit définir un texte"
+ 2_netexstif_notice_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} de type %{reference_value} est ignoré"
+ 2_netexstif_operatingperiod_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet OperatingPeriod d'identifiant %{source_objectid} a une date de fin %{error_value} inférieure ou égale à la date de début %{reference_value}"
+ 2_netexstif_passengerstopassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'attribut %{source_label} de l'objet PassengerStopAssignment %{source_objectid} doit être renseigné"
+ 2_netexstif_passengerstopassignment_2: "L'arrêt %{source_objectid} ne fait pas partie des arrêts disponibles pour votre organisation."
+ 2_netexstif_passingtime_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} ne dispose pas de DepartureTime"
+ 2_netexstif_passingtime_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit un ArrivalTime supérieur à son DepartureTime"
+ 2_netexstif_route_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} a une valeur de l'attribut DirectionType interdite : %{error_value}"
+ 2_netexstif_route_2_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{reference_value} qui ne le référence pas"
+ 2_netexstif_route_2_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{reference_value} de même DirectionType"
+ 2_netexstif_route_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Les ServiceJourneyPattern de l'objet Route d'identifiant %{source_objectid} ne permettent pas de reconstituer la séquence des arrêts de celui-ci"
+ 2_netexstif_route_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, Les informations de montée/Descente à l'arrêt %{source_label} de la Route %{source_objectid} diffèrent sur plusieurs ServiceJourneyPattern, ces informations ne sont pas importées"
+ 2_netexstif_routingconstraintzone_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} doit référencer au moins deux ScheduledStopPoint"
+ 2_netexstif_routingconstraintzone_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} a une valeur interdite pour l'attribut ZoneUse : %{error_value}"
+ 2_netexstif_servicejourney_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} ne référence pas de ServiceJourneyPattern"
+ 2_netexstif_servicejourney_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} fournit plus d'un trainNumber"
+ 2_netexstif_servicejourney_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Le nombre d'horaires (passing_times) de l'objet ServiceJourney d'identifiant %{source_objectid} n'est pas cohérent avec le ServiceJourneyPattern associé."
+ 2_netexstif_servicejourney_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{rank} fournit des horaires antérieurs au passingTime précédent."
+ 2_netexstif_servicejourneypattern_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} ne référence pas de Route"
+ 2_netexstif_servicejourneypattern_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} doit contenir au moins 2 StopPointInJourneyPattern"
+ 2_netexstif_servicejourneypattern_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut ServiceJourneyPatternType"
+ 2_netexstif_servicejourneypattern_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, objet ServiceJourneyPattern d'identifiant %{source_objectid} : les attributs 'order' des StopPointInJourneyPattern ne sont pas croissants."
diff --git a/config/locales/import_resources.en.yml b/config/locales/import_resources.en.yml
new file mode 100644
index 000000000..d98b3eacf
--- /dev/null
+++ b/config/locales/import_resources.en.yml
@@ -0,0 +1,18 @@
+en:
+ import_resources:
+ index:
+ title: "NeTEx conformity"
+ table_state: "%{lines_imported} lines imported on %{lines_in_zipfile} presents in zipfile"
+ table_title: "Satus of anlyzed files"
+ table_explanation: "When calendriers.xml and/or commun.xml are not imported, then all lines file are not processed."
+ metrics: "%{ok_count} ok, %{error_count} errors, %{warning_count} warnings, %{uncheck_count} n/a"
+ activerecord:
+ models:
+ import_resource:
+ zero: "netex conformity"
+ one: "netex conformity"
+ other: "netex conformities"
+ attributes:
+ import:
+ name: "Filename"
+ status: "Status"
diff --git a/config/locales/import_resources.fr.yml b/config/locales/import_resources.fr.yml
new file mode 100644
index 000000000..86c8d8e73
--- /dev/null
+++ b/config/locales/import_resources.fr.yml
@@ -0,0 +1,18 @@
+fr:
+ import_resources:
+ index:
+ title: "Rapport de conformité NeTEx"
+ table_state: "%{lines_imported} lignes importées sur %{lines_in_zipfile} présentes dans l'archive"
+ table_title: "Etat des fichiers analysés"
+ table_explanation: "Dans le cas ou le(s) fichiers calendriers.xml et/ou commun.xml sont dans un état non importé, alors tous les fichiers lignes sont automatiquement dans un état non traité."
+ metrics: "%{ok_count} ok, %{error_count} errors, %{warning_count} warnings, %{uncheck_count} n/a"
+ activerecord:
+ models:
+ import_resource:
+ zero: "rapport de conformité Netex"
+ one: "rapport de conformité Netex"
+ other: "rapports de conformité Netex"
+ attributes:
+ import_resource:
+ name: "Fichier"
+ status: "Etat"
diff --git a/config/locales/imports.en.yml b/config/locales/imports.en.yml
index b20f0f1da..b92b8843f 100644
--- a/config/locales/imports.en.yml
+++ b/config/locales/imports.en.yml
@@ -1,7 +1,13 @@
en:
imports:
+ search_no_results: "No import matching your query"
+ filters:
+ referential: "Select data space..."
+ name_or_creator_cont: "Select an import or creator name..."
actions:
new: "New import"
+ show: "Import report"
+ download: "Download original file"
destroy: "Destroy"
destroy_confirm: "Are you sure you want destroy this import?"
index:
@@ -50,7 +56,10 @@ en:
import:
resources: "File to import"
created_at: "Created on"
+ started_at: Started at
+ name: Name
status: "Status"
+ creator: "Creator"
references_type: "Data to be imported"
no_save: "No save"
rule_parameter_set_id: "Rule parameter set for compliance check"
diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml
index 933025c82..f7bf8c178 100644
--- a/config/locales/imports.fr.yml
+++ b/config/locales/imports.fr.yml
@@ -1,7 +1,13 @@
fr:
imports:
+ search_no_results: "Aucun import ne correspond à votre recherche"
+ filters:
+ referential: "Sélectionnez un jeu de données..."
+ name_or_creator_cont: "Indiquez un nom d'import ou d'opérateur..."
actions:
new: "Nouvel import"
+ show: "Rapport d'import"
+ download: "Téléch. fichier source"
destroy: "Supprimer cet import"
destroy_confirm: "Etes vous sûr de supprimer cet import ?"
index:
@@ -50,7 +56,10 @@ fr:
import:
resources: "Fichier à importer"
created_at: "Créé le"
- status: "Status"
+ started_at: Démarrage
+ name: "Nom de l'import"
+ status: "Etat"
+ creator: "Opérateur"
no_save: "Pas de sauvegarde"
references_type: "Données à importer"
rule_parameter_set_id: "Jeu de paramètres pour validation"
diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml
index ed2f9758e..d67e30edb 100644
--- a/config/locales/time_tables.en.yml
+++ b/config/locales/time_tables.en.yml
@@ -29,6 +29,10 @@ en:
title: "Duplicate timetable"
edit:
title: "Update timetable %{time_table}"
+ error_modal:
+ title: "Error"
+ withoutPeriodsWithDaysTypes: "A timetable can't have day type(s) without period(s)."
+ withPeriodsWithoutDayTypes: "A tiemetable can't have period(s) swithout day type(s)."
show:
title: "Timetable %{time_table}"
dates: "Application dates"
diff --git a/config/locales/time_tables.fr.yml b/config/locales/time_tables.fr.yml
index cf6888d0f..06d1d59e8 100644
--- a/config/locales/time_tables.fr.yml
+++ b/config/locales/time_tables.fr.yml
@@ -29,6 +29,10 @@ fr:
title: "Dupliquer un calendrier"
edit:
title: "Editer le calendrier %{time_table}"
+ error_modal:
+ title: "Erreur"
+ withoutPeriodsWithDaysTypes: "Un calendrier d'application ne peut pas avoir de journée(s) d'application sans période(s)."
+ withPeriodsWithoutDayTypes: "Un calendrier d'application ne peut pas avoir de période(s) sans journée(s) d'application."
show:
title: Calendrier %{time_table}
dates: "Dates d'application"
diff --git a/config/routes.rb b/config/routes.rb
index f6cf5e672..8f8989cab 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -5,6 +5,10 @@ ChouetteIhm::Application.routes.draw do
delete :referentials, on: :member, action: :delete_referentials
resources :imports do
get :download, on: :member
+ resources :import_resources, only: [:index] do
+ resources :import_messages, only: [:index]
+ end
+
end
end
@@ -32,6 +36,9 @@ ChouetteIhm::Application.routes.draw do
namespace :api do
namespace :v1 do
+ resources :workbenches, only: [:index, :show] do
+ resources :imports, only: [:index, :show, :create]
+ end
resources :access_links, only: [:index, :show]
resources :access_points, only: [:index, :show]
resources :connection_links, only: [:index, :show]
@@ -56,6 +63,7 @@ ChouetteIhm::Application.routes.draw do
end
resource :organisation, :only => [:show, :edit, :update] do
+ resources :api_keys
resources :users
resources :rule_parameter_sets
end
@@ -78,7 +86,6 @@ ChouetteIhm::Application.routes.draw do
end
resources :referentials, except: :index do
- resources :api_keys
resources :autocomplete_stop_areas, only: [:show, :index] do
get 'around', on: :member
end
@@ -146,23 +153,6 @@ ChouetteIhm::Application.routes.draw do
end
end
- resources :compliance_check_tasks, :only => [:new, :create] do
- collection do
- get 'references'
- end
- end
-
- resources :compliance_checks, :only => [:index, :show, :destroy] do
- member do
- get 'export', defaults: { format: 'zip' }
- get 'report'
- get 'rule_parameter_set'
- end
- collection do
- get 'references'
- end
- end
-
resources :companies, controller: "referential_companies"
resources :time_tables do
diff --git a/db/migrate/20170808083322_change_referential_date_format_to_netex.rb b/db/migrate/20170808083322_change_referential_date_format_to_netex.rb
new file mode 100644
index 000000000..dc706942c
--- /dev/null
+++ b/db/migrate/20170808083322_change_referential_date_format_to_netex.rb
@@ -0,0 +1,9 @@
+class ChangeReferentialDateFormatToNetex < ActiveRecord::Migration
+ def up
+ execute "UPDATE referentials SET data_format = 'netex'"
+ end
+
+ def down
+ execute "UPDATE referentials SET data_format = 'neptune'"
+ end
+end
diff --git a/db/migrate/20170808091929_change_objectid_suffix.rb b/db/migrate/20170808091929_change_objectid_suffix.rb
new file mode 100644
index 000000000..da98e8b9d
--- /dev/null
+++ b/db/migrate/20170808091929_change_objectid_suffix.rb
@@ -0,0 +1,17 @@
+class ChangeObjectidSuffix < ActiveRecord::Migration
+ def tables
+ ['routes', 'journey_patterns', 'vehicle_journeys', 'time_tables', 'routing_constraint_zones']
+ end
+
+ def up
+ self.tables.each do |table|
+ execute "UPDATE #{table} SET objectid = (objectid || ':LOC')"
+ end
+ end
+
+ def down
+ self.tables.each do |table|
+ execute "UPDATE #{table} SET objectid = replace(objectid, ':LOC', '')"
+ end
+ end
+end
diff --git a/db/migrate/20170816104020_add_creator_to_imports.rb b/db/migrate/20170816104020_add_creator_to_imports.rb
new file mode 100644
index 000000000..5fb808451
--- /dev/null
+++ b/db/migrate/20170816104020_add_creator_to_imports.rb
@@ -0,0 +1,5 @@
+class AddCreatorToImports < ActiveRecord::Migration
+ def change
+ add_column :imports, :creator, :string
+ end
+end
diff --git a/db/migrate/20170817122914_add_organisation_to_api_keys.rb b/db/migrate/20170817122914_add_organisation_to_api_keys.rb
new file mode 100644
index 000000000..14c742c87
--- /dev/null
+++ b/db/migrate/20170817122914_add_organisation_to_api_keys.rb
@@ -0,0 +1,5 @@
+class AddOrganisationToApiKeys < ActiveRecord::Migration
+ def change
+ add_reference :api_keys, :organisation, index: true, foreign_key: true
+ end
+end
diff --git a/db/migrate/20170901132253_rename_type_in_import_resource.rb b/db/migrate/20170901132253_rename_type_in_import_resource.rb
new file mode 100644
index 000000000..655d2a107
--- /dev/null
+++ b/db/migrate/20170901132253_rename_type_in_import_resource.rb
@@ -0,0 +1,5 @@
+class RenameTypeInImportResource < ActiveRecord::Migration
+ def change
+ rename_column :import_resources, :type, :resource_type
+ end
+end
diff --git a/db/migrate/20170907082913_add_data_source_ref.rb b/db/migrate/20170907082913_add_data_source_ref.rb
new file mode 100644
index 000000000..93ca8eb5f
--- /dev/null
+++ b/db/migrate/20170907082913_add_data_source_ref.rb
@@ -0,0 +1,10 @@
+class AddDataSourceRef < ActiveRecord::Migration
+ def change
+ add_column :routes, :data_source_ref, :string
+ add_column :journey_patterns, :data_source_ref, :string
+ add_column :routing_constraint_zones, :data_source_ref, :string
+ add_column :vehicle_journeys, :data_source_ref, :string
+ add_column :time_tables, :data_source_ref, :string
+ add_column :footnotes, :data_source_ref, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 01ed67d77..98e60c909 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170808110333) do
+ActiveRecord::Schema.define(version: 20170907082913) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -72,13 +72,16 @@ ActiveRecord::Schema.define(version: 20170808110333) do
add_index "access_points", ["objectid"], name: "access_points_objectid_key", unique: true, using: :btree
create_table "api_keys", id: :bigserial, force: :cascade do |t|
- t.integer "referential_id", limit: 8
+ t.integer "referential_id", limit: 8
t.string "token"
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
+ t.integer "organisation_id"
end
+ add_index "api_keys", ["organisation_id"], name: "index_api_keys_on_organisation_id", using: :btree
+
create_table "calendars", id: :bigserial, force: :cascade do |t|
t.string "name"
t.string "short_name"
@@ -218,6 +221,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.datetime "updated_at"
t.string "checksum"
t.text "checksum_source"
+ t.string "data_source_ref"
end
create_table "footnotes_vehicle_journeys", id: false, force: :cascade do |t|
@@ -261,11 +265,11 @@ ActiveRecord::Schema.define(version: 20170808110333) do
add_index "import_messages", ["resource_id"], name: "index_import_messages_on_resource_id", using: :btree
create_table "import_resources", id: :bigserial, force: :cascade do |t|
- t.integer "import_id", limit: 8
+ t.integer "import_id", limit: 8
t.string "status"
t.datetime "created_at"
t.datetime "updated_at"
- t.string "type"
+ t.string "resource_type"
t.string "reference"
t.string "name"
t.hstore "metrics"
@@ -292,6 +296,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.datetime "notified_parent_at"
t.integer "current_step", default: 0
t.integer "total_steps", default: 0
+ t.string "creator"
end
add_index "imports", ["referential_id"], name: "index_imports_on_referential_id", using: :btree
@@ -339,6 +344,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.datetime "updated_at"
t.string "checksum"
t.text "checksum_source"
+ t.string "data_source_ref"
end
add_index "journey_patterns", ["objectid"], name: "journey_patterns_objectid_key", unique: true, using: :btree
@@ -549,6 +555,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.datetime "updated_at"
t.string "checksum"
t.text "checksum_source"
+ t.string "data_source_ref"
end
add_index "routes", ["objectid"], name: "routes_objectid_key", unique: true, using: :btree
@@ -564,6 +571,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.integer "stop_point_ids", limit: 8, array: true
t.string "checksum"
t.text "checksum_source"
+ t.string "data_source_ref"
end
create_table "routing_constraints_lines", id: false, force: :cascade do |t|
@@ -729,6 +737,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.integer "created_from_id"
t.string "checksum"
t.text "checksum_source"
+ t.string "data_source_ref"
end
add_index "time_tables", ["calendar_id"], name: "index_time_tables_on_calendar_id", using: :btree
@@ -834,6 +843,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
t.datetime "updated_at"
t.string "checksum"
t.text "checksum_source"
+ t.string "data_source_ref"
end
add_index "vehicle_journeys", ["objectid"], name: "vehicle_journeys_objectid_key", unique: true, using: :btree
@@ -853,6 +863,7 @@ ActiveRecord::Schema.define(version: 20170808110333) do
add_index "workbenches", ["stop_area_referential_id"], name: "index_workbenches_on_stop_area_referential_id", using: :btree
add_foreign_key "access_links", "access_points", name: "aclk_acpt_fkey"
+ add_foreign_key "api_keys", "organisations"
add_foreign_key "group_of_lines_lines", "group_of_lines", name: "groupofline_group_fkey", on_delete: :cascade
add_foreign_key "journey_frequencies", "timebands", on_delete: :nullify
add_foreign_key "journey_frequencies", "vehicle_journeys", on_delete: :nullify
diff --git a/lib/stif/netex_file.rb b/lib/stif/netex_file.rb
new file mode 100644
index 000000000..424663c1c
--- /dev/null
+++ b/lib/stif/netex_file.rb
@@ -0,0 +1,72 @@
+module STIF
+ class NetexFile
+
+ CALENDAR_FILE_NAME = 'calendriers.xml'
+ LINE_FILE_FORMAT = /^offre_.*\.xml$/
+ XML_NAME_SPACE = "http://www.netex.org.uk/netex"
+
+ def initialize(file_name)
+ @file_name = file_name
+ end
+
+ def frames
+ frames = Hash.new { |h,k| h[k] = NetexFile::Frame.new(k) }
+ Zip::File.open(@file_name) do |zipfile|
+ zipfile.each do |entry|
+ next unless entry.ftype == :file
+
+ entry_dir_name, entry_file_name = File.split(entry.name)
+ case entry_file_name
+ when CALENDAR_FILE_NAME
+ entry.get_input_stream do |stream|
+ frames[entry_dir_name].parse_calendars(stream.read)
+ end
+ when LINE_FILE_FORMAT
+ frames[entry_dir_name].add_offer_file(entry_file_name)
+ end
+ end
+ end
+ frames.values
+ end
+
+ end
+
+ class NetexFile::Frame
+
+ attr_accessor :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def parse_calendars(calendars)
+ # <netex:ValidBetween>
+ # <netex:FromDate>2017-03-01</netex:FromDate>
+ # <netex:ToDate>2017-03-31</netex:ToDate>
+ # </netex:ValidBetween>
+ xml = Nokogiri::XML(calendars)
+ xml.xpath("//netex:ValidBetween", "netex" => NetexFile::XML_NAME_SPACE).each do |valid_between|
+ from_date = valid_between.xpath("netex:FromDate").try :text
+ to_date = valid_between.xpath("netex:ToDate").try :text
+ periods << Range.new(Date.parse(from_date), Date.parse(to_date))
+ end
+ end
+
+ LINE_FORMAT = /^offre_.*\.xml$/
+
+ def add_offer_file(file_name)
+ if file_name =~ /^offre_([^_]*)_/
+ line_refs << $1
+ end
+ end
+
+ def periods
+ @periods ||= []
+ end
+
+ def line_refs
+ @line_refs ||= []
+ end
+
+ end
+end
diff --git a/lib/stif/reflex_synchronization.rb b/lib/stif/reflex_synchronization.rb
index 63270a986..b3f474221 100644
--- a/lib/stif/reflex_synchronization.rb
+++ b/lib/stif/reflex_synchronization.rb
@@ -34,6 +34,14 @@ module Stif
Chouette::StopArea.find_by(objectid: objectid)
end
+ def save_if_valid object
+ if object.valid?
+ object.save
+ else
+ Rails.logger.error "Reflex:sync - #{object.class.model_name} with objectid #{object.objectid} and name #{object.name} can't be saved"
+ end
+ end
+
def synchronize
reset_counts
['getOR', 'getOP'].each do |method|
@@ -99,7 +107,7 @@ module Stif
if entry['parent']
stop.parent = self.find_by_object_id entry['parent']
- stop.save! if stop.changed
+ save_if_valid(stop) if stop.changed?
end
if entry['quays']
@@ -107,7 +115,7 @@ module Stif
children = self.find_by_object_id id
next unless children
children.parent = stop
- children.save! if children.changed?
+ save_if_valid(children) if children.changed?
end
end
end
@@ -138,7 +146,7 @@ module Stif
access['longitude'] = entry['gml:pos'][:lng]
access['latitude'] = entry['gml:pos'][:lat]
end
- access.save if access.valid? && access.changed?
+ save_if_valid(access) if access.changed?
end
def create_or_update_stop_area entry
@@ -166,7 +174,7 @@ module Stif
stop.import_xml = entry[:xml]
prop = stop.new_record? ? :imported_count : :updated_count
increment_counts prop, 1
- stop.save!
+ save_if_valid(stop)
end
# Create AccessPoint from StopPlaceEntrance
if entry[:stop_place_entrances]
diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake
index 658e4e04e..90e47560e 100644
--- a/lib/tasks/ci.rake
+++ b/lib/tasks/ci.rake
@@ -3,7 +3,7 @@ namespace :ci do
task :setup do
cp "config/database/jenkins.yml", "config/database.yml"
sh "RAILS_ENV=test rake db:migrate"
- sh "npm install"
+ sh "npm --production --no-progress install"
end
def git_branch
@@ -27,11 +27,14 @@ namespace :ci do
sh "bundle exec bundle-audit check --update"
end
+ task :spec do
+ sh "bundle exec rspec --profile"
+ end
+
task :teaspoon do
sh "RAILS_ENV=test bundle exec rake teaspoon"
end
-
desc "Deploy after CI"
task :deploy do
sh "cap #{deploy_env} deploy:migrations"
@@ -44,4 +47,4 @@ namespace :ci do
end
desc "Run continuous integration tasks (spec, ...)"
-task :ci => ["ci:setup", "spec", "ci:teaspoon", "cucumber", "ci:check_security", "ci:deploy", "ci:clean"]
+task :ci => ["ci:setup", "ci:spec", "ci:teaspoon", "cucumber", "ci:check_security", "ci:deploy", "ci:clean"]
diff --git a/lib/tasks/generate.rake b/lib/tasks/erd.rake
index a9b1a3454..a9b1a3454 100644
--- a/lib/tasks/generate.rake
+++ b/lib/tasks/erd.rake
diff --git a/spec/controllers/api/v1/iboo_controller_spec.rb b/spec/controllers/api/v1/iboo_controller_spec.rb
new file mode 100644
index 000000000..64a929d1a
--- /dev/null
+++ b/spec/controllers/api/v1/iboo_controller_spec.rb
@@ -0,0 +1,12 @@
+require 'rails_helper'
+
+RSpec.describe Api::V1::IbooController, type: :controller do
+ context '#authenticate' do
+ include_context 'iboo authenticated api user'
+
+ it 'should set current organisation' do
+ controller.send(:authenticate)
+ expect(assigns(:current_organisation)).to eq api_key.organisation
+ end
+ end
+end
diff --git a/spec/controllers/api/v1/imports_controller_spec.rb b/spec/controllers/api/v1/imports_controller_spec.rb
new file mode 100644
index 000000000..266b25486
--- /dev/null
+++ b/spec/controllers/api/v1/imports_controller_spec.rb
@@ -0,0 +1,38 @@
+require 'rails_helper'
+
+RSpec.describe Api::V1::ImportsController, type: :controller do
+ let(:workbench) { create :workbench, organisation: organisation }
+
+ context 'unauthenticated' do
+ include_context 'iboo wrong authorisation api user'
+
+ describe 'GET #index' do
+ it 'should not be successful' do
+ get :index, workbench_id: workbench.id
+ expect(response).not_to be_success
+ end
+ end
+ end
+
+ context 'authenticated' do
+ include_context 'iboo authenticated api user'
+
+ describe 'GET #index' do
+ it 'should be successful' do
+ get :index, workbench_id: workbench.id
+ expect(response).to be_success
+ end
+ end
+
+ describe 'POST #create' do
+ let(:file) { fixture_file_upload('multiple_references_import.zip') }
+
+ it 'should be successful' do
+ expect {
+ post :create, workbench_id: workbench.id, workbench_import: {file: file, creator: 'test'}, format: :json
+ }.to change{WorkbenchImport.count}.by(1)
+ expect(response).to be_success
+ end
+ end
+ end
+end
diff --git a/spec/controllers/api/v1/workbenches_controller_spec.rb b/spec/controllers/api/v1/workbenches_controller_spec.rb
new file mode 100644
index 000000000..7780da142
--- /dev/null
+++ b/spec/controllers/api/v1/workbenches_controller_spec.rb
@@ -0,0 +1,25 @@
+require 'rails_helper'
+
+RSpec.describe Api::V1::WorkbenchesController, type: :controller do
+ context 'unauthenticated' do
+ include_context 'iboo wrong authorisation api user'
+
+ describe 'GET #index' do
+ it 'should not be successful' do
+ get :index
+ expect(response).not_to be_success
+ end
+ end
+ end
+
+ context 'authenticated' do
+ include_context 'iboo authenticated api user'
+
+ describe 'GET #index' do
+ it 'should be successful' do
+ get :index
+ expect(response).to be_success
+ end
+ end
+ end
+end
diff --git a/spec/controllers/import_tasks_controller_spec.rb b/spec/controllers/import_tasks_controller_spec.rb
deleted file mode 100644
index 17be1a8d7..000000000
--- a/spec/controllers/import_tasks_controller_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require 'spec_helper'
-
-# describe ImportTasksController, :type => :controller do
-# login_user
-# shared_examples_for "referential dependant" do
-# it "assigns referential as @referential" do
-# expect(assigns[:referential]).to eq(referential)
-# end
-# end
-
-# describe "GET /new" do
-# before(:each) do
-# get :new,
-# :referential_id => referential.id
-# end
-# it_behaves_like "referential dependant"
-# it "should assign import_task with NeptuneImport instance" do
-# expect(assigns[:import_task].class).to eq(NeptuneImport)
-# end
-# it "should assign import_task with Neptune format" do
-# expect(assigns[:import_task].format).to eq(ImportTask.new.format)
-# end
-# it "should assign import_task with refrential.id" do
-# expect(assigns[:import_task].referential_id).to eq(referential.id)
-# end
-# it "should assign import_task with logged in user id" do
-# expect(assigns[:import_task].user_id).to eq(referential.organisation.users.first.id)
-# end
-# it "should assign import_task with logged in user name" do
-# expect(assigns[:import_task].user_name).to eq(referential.organisation.users.first.name)
-# end
-# end
-
-# end
diff --git a/spec/decorators/api_key_decorator_spec.rb b/spec/decorators/api_key_decorator_spec.rb
new file mode 100644
index 000000000..9451a3974
--- /dev/null
+++ b/spec/decorators/api_key_decorator_spec.rb
@@ -0,0 +1,4 @@
+require 'spec_helper'
+
+describe ApiKeyDecorator do
+end
diff --git a/spec/factories/api_keys.rb b/spec/factories/api_keys.rb
index bd31edecc..963938c64 100644
--- a/spec/factories/api_keys.rb
+++ b/spec/factories/api_keys.rb
@@ -1,6 +1,8 @@
FactoryGirl.define do
factory :api_key, class: Api::V1::ApiKey do
- token { "#{referential.id}-#{SecureRandom.hex}" }
+ name { SecureRandom.urlsafe_base64 }
+ token { "#{referential_id}-#{organisation_id}-#{SecureRandom.hex}" }
referential
+ organisation
end
end
diff --git a/spec/factories/chouette_access_links.rb b/spec/factories/chouette_access_links.rb
index 94717e95e..8b4e89be9 100644
--- a/spec/factories/chouette_access_links.rb
+++ b/spec/factories/chouette_access_links.rb
@@ -1,9 +1,9 @@
FactoryGirl.define do
-
+
factory :access_link, :class => Chouette::AccessLink do
sequence(:name) { |n| "Access link #{n}" }
- sequence(:objectid) { |n| "test:AccessLink:#{n}" }
- link_type "Mixed"
+ sequence(:objectid) { |n| "test:AccessLink:#{n}:loc" }
+ link_type "Mixed"
link_orientation "AccessPointToStopArea"
association :stop_area, :factory => :stop_area
diff --git a/spec/factories/chouette_companies.rb b/spec/factories/chouette_companies.rb
index 35ce34257..9272736cf 100644
--- a/spec/factories/chouette_companies.rb
+++ b/spec/factories/chouette_companies.rb
@@ -2,7 +2,7 @@ FactoryGirl.define do
factory :company, :class => Chouette::Company do
sequence(:name) { |n| "Company #{n}" }
- sequence(:objectid) { |n| "chouette:test:Company:#{n}" }
+ sequence(:objectid) { |n| "STIF:CODIFLIGNE:Company:#{n}" }
sequence(:registration_number) { |n| "test-#{n}" }
association :line_referential, :factory => :line_referential
diff --git a/spec/factories/chouette_connection_links.rb b/spec/factories/chouette_connection_links.rb
index f70548721..9185480ac 100644
--- a/spec/factories/chouette_connection_links.rb
+++ b/spec/factories/chouette_connection_links.rb
@@ -3,11 +3,11 @@ FactoryGirl.define do
factory :connection_link, :class => Chouette::ConnectionLink do
sequence(:name) { |n| "Connection link #{n}" }
sequence(:link_type) { |n| "Mixed" }
- sequence(:objectid) { |n| "test:ConnectionLink:#{n}" }
+ sequence(:objectid) { |n| "test:ConnectionLink:#{n}:loc" }
association :departure, :factory => :stop_area
association :arrival, :factory => :stop_area
end
-
+
end
diff --git a/spec/factories/chouette_group_of_lines.rb b/spec/factories/chouette_group_of_lines.rb
index 75739d6d3..8b359fea5 100644
--- a/spec/factories/chouette_group_of_lines.rb
+++ b/spec/factories/chouette_group_of_lines.rb
@@ -2,7 +2,7 @@ FactoryGirl.define do
factory :group_of_line, :class => Chouette::GroupOfLine do
sequence(:name) { |n| "Group Of Line #{n}" }
- sequence(:objectid) { |n| "chouette:test:GroupOfLine:#{n}" }
+ sequence(:objectid) { |n| "STIF:CODIFLIGNE:GroupOfLine:#{n}" }
sequence(:registration_number) { |n| "#{n}" }
association :line_referential
diff --git a/spec/factories/chouette_journey_pattern.rb b/spec/factories/chouette_journey_pattern.rb
index 62241f313..05d8d536a 100644
--- a/spec/factories/chouette_journey_pattern.rb
+++ b/spec/factories/chouette_journey_pattern.rb
@@ -5,8 +5,7 @@ FactoryGirl.define do
sequence(:published_name) { |n| "jp publishedname #{n}" }
sequence(:comment) { |n| "jp comment #{n}" }
sequence(:registration_number) { |n| "jp registration_number #{n}" }
- sequence(:objectid) { |n| "test:JourneyPattern:#{n}" }
-
+ sequence(:objectid) { |n| "organisation:JourneyPattern:lineId-#{n}:LOC" }
association :route, :factory => :route
factory :journey_pattern do
diff --git a/spec/factories/chouette_networks.rb b/spec/factories/chouette_networks.rb
index 3ad719cd9..afeac9e28 100644
--- a/spec/factories/chouette_networks.rb
+++ b/spec/factories/chouette_networks.rb
@@ -2,7 +2,7 @@ FactoryGirl.define do
factory :network, :class => Chouette::Network do
sequence(:name) { |n| "Network #{n}" }
- sequence(:objectid) { |n| "chouette:test:GroupOfLine:#{n}" }
+ sequence(:objectid) { |n| "STIF:CODIFLIGNE:Network:#{n}" }
sequence(:registration_number) { |n| "test-#{n}" }
association :line_referential
diff --git a/spec/factories/chouette_routes.rb b/spec/factories/chouette_routes.rb
index a707bcbf6..4986ab70e 100644
--- a/spec/factories/chouette_routes.rb
+++ b/spec/factories/chouette_routes.rb
@@ -6,7 +6,7 @@ FactoryGirl.define do
sequence(:number) { |n| "#{n}" }
sequence(:wayback) { |n| Chouette::Route.wayback.values[n % 2] }
sequence(:direction) { |n| Chouette::Route.direction.values[n % 12] }
- sequence(:objectid) { |n| "test:Route:#{n}" }
+ sequence(:objectid) { |n| "organisation:Route:lineId-routeId#{n}:LOC" }
association :line, :factory => :line
diff --git a/spec/factories/chouette_routing_constraint_zones.rb b/spec/factories/chouette_routing_constraint_zones.rb
index 8ef2ddb43..7748a4f74 100644
--- a/spec/factories/chouette_routing_constraint_zones.rb
+++ b/spec/factories/chouette_routing_constraint_zones.rb
@@ -1,6 +1,7 @@
FactoryGirl.define do
factory :routing_constraint_zone, class: Chouette::RoutingConstraintZone do
sequence(:name) { |n| "Routing constraint zone #{n}" }
+ sequence(:objectid) { |n| "organisation:RoutingConstraintZone:lineId-routeId-#{n}:LOC" }
association :route, factory: :route
after(:build) do |zone|
route = Chouette::Route.find(zone.route_id)
diff --git a/spec/factories/chouette_stop_points.rb b/spec/factories/chouette_stop_points.rb
index 690d1c688..14e08b1ac 100644
--- a/spec/factories/chouette_stop_points.rb
+++ b/spec/factories/chouette_stop_points.rb
@@ -1,7 +1,7 @@
FactoryGirl.define do
factory :stop_point, :class => Chouette::StopPoint do
- sequence(:objectid) { |n| "test:StopPoint:#{n}" }
+ sequence(:objectid) { |n| "test:StopPoint:#{n}:loc" }
association :stop_area, :factory => :stop_area
end
diff --git a/spec/factories/chouette_time_table.rb b/spec/factories/chouette_time_table.rb
index b410d4ab8..a3ff63b2f 100644
--- a/spec/factories/chouette_time_table.rb
+++ b/spec/factories/chouette_time_table.rb
@@ -1,7 +1,7 @@
FactoryGirl.define do
factory :time_table, :class => Chouette::TimeTable do
sequence(:comment) { |n| "Timetable #{n}" }
- sequence(:objectid) { |n| "test:Timetable:#{n}" }
+ sequence(:objectid) { |n| "organisation:Timetable:#{n}:LOC" }
sequence(:int_day_types) { (1..7).to_a.map{ |n| 2**(n+1)}.sum }
calendar nil
diff --git a/spec/factories/chouette_timeband.rb b/spec/factories/chouette_timeband.rb
index 6e2825c22..010461479 100644
--- a/spec/factories/chouette_timeband.rb
+++ b/spec/factories/chouette_timeband.rb
@@ -4,14 +4,14 @@ FactoryGirl.define do
sequence(:name) { |n| "Name: #{n}" }
start_time { Time.now }
end_time { Time.now + 1.hour }
- sequence(:objectid) { |n| "test:Timeband:#{n}" }
+ sequence(:objectid) { |n| "test:Timeband:#{n}:loc" }
end
factory :timeband_invalid, class: Chouette::Timeband do
sequence(:name) { |n| "Name: #{n}" }
start_time { Time.now + 1.hour }
end_time { Time.now }
- sequence(:objectid) { |n| "test:Timeband:#{n}" }
+ sequence(:objectid) { |n| "test:Timeband:#{n}:loc" }
end
end
diff --git a/spec/factories/chouette_vehicle_journey.rb b/spec/factories/chouette_vehicle_journey.rb
index d1e00cd1d..5f64bd502 100644
--- a/spec/factories/chouette_vehicle_journey.rb
+++ b/spec/factories/chouette_vehicle_journey.rb
@@ -1,7 +1,7 @@
FactoryGirl.define do
factory :vehicle_journey_common, :class => Chouette::VehicleJourney do
- sequence(:objectid) { |n| "test:VehicleJourney:#{n}" }
+ sequence(:objectid) { |n| "organisation:VehicleJourney:lineid-#{n}:LOC" }
factory :vehicle_journey_empty do
association :journey_pattern, :factory => :journey_pattern
diff --git a/spec/factories/compliance_check_results.rb b/spec/factories/compliance_check_results.rb
deleted file mode 100644
index 7a3a3e956..000000000
--- a/spec/factories/compliance_check_results.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-FactoryGirl.define do
- factory :compliance_check_result do
- association :compliance_check_task
- rule_code "2-NEPTUNE-StopArea-6"
- severity "warning"
- status "nok"
- end
-end
diff --git a/spec/factories/compliance_check_tasks.rb b/spec/factories/compliance_check_tasks.rb
deleted file mode 100644
index e9fdeb5ef..000000000
--- a/spec/factories/compliance_check_tasks.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-FactoryGirl.define do
- factory :compliance_check_task do
- user_id 1
- user_name "Dummy"
- status "pending"
- referential { Referential.find_by_slug("first") }
- end
-end
diff --git a/spec/factories/import_messages.rb b/spec/factories/import_messages.rb
new file mode 100644
index 000000000..75f80566c
--- /dev/null
+++ b/spec/factories/import_messages.rb
@@ -0,0 +1,7 @@
+FactoryGirl.define do
+ factory :import_message do
+ association :import
+ association :resource, factory: :import_resource
+ criticity :info
+ end
+end
diff --git a/spec/factories/import_resources.rb b/spec/factories/import_resources.rb
index 6854dc4af..76afcc486 100644
--- a/spec/factories/import_resources.rb
+++ b/spec/factories/import_resources.rb
@@ -1,9 +1,9 @@
FactoryGirl.define do
factory :import_resource do
association :import
- status :new
+ status :WARNING
sequence(:name) { |n| "Import resource #{n}" }
- type 'type'
+ resource_type 'type'
reference 'reference'
end
end
diff --git a/spec/factories/imports.rb b/spec/factories/imports.rb
index afced3b57..2c53106c3 100644
--- a/spec/factories/imports.rb
+++ b/spec/factories/imports.rb
@@ -9,6 +9,7 @@ FactoryGirl.define do
status :new
started_at nil
ended_at nil
+ creator 'rspec'
after(:build) do |import|
import.class.skip_callback(:create, :before, :initialize_fields)
diff --git a/spec/features/connection_links_spec.rb b/spec/features/connection_links_spec.rb
index 0325e6e1c..7272242fe 100644
--- a/spec/features/connection_links_spec.rb
+++ b/spec/features/connection_links_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe "ConnectionLinks", :type => :feature do
visit referential_connection_links_path(referential)
click_link "Ajouter une correspondance"
fill_in "Nom", :with => "ConnectionLink 1"
- fill_in "Identifiant Neptune", :with => "test:ConnectionLink:1"
+ fill_in "Identifiant Neptune", :with => "test:ConnectionLink:1:LOC"
click_button("Créer correspondance")
expect(page).to have_content("ConnectionLink 1")
end
diff --git a/spec/features/referentials_spec.rb b/spec/features/referentials_spec.rb
index 337271fea..a38577aba 100644
--- a/spec/features/referentials_spec.rb
+++ b/spec/features/referentials_spec.rb
@@ -120,6 +120,73 @@ describe "Referentials", :type => :feature do
end
+ describe "new_from" do
+ # let(:cloning)
+ let(:worker) { ReferentialCloningWorker.new }
+
+ let(:line) { create(:line_with_stop_areas) }
+ let(:jp) { create(:journey_pattern, route: line.routes.first) }
+ let(:tt) { create(:time_table) }
+ let(:vj) { create(:vehicle_journey, journey_pattern: jp, time_table: tt) }
+ let(:ref_metadata) { create(:referential_metadata, lines: [line], referential: referential) }
+
+ context "when user is from the same organisation" do
+
+ xit "should" do
+ visit new_referential_path(from: referential.id, current_workbench_id: @user.organisation.workbenches.first.id)
+
+ select "2018", :from => "referential_metadatas_attributes_0_periods_attributes_0_begin_1i"
+
+ select "2018", :from => "referential_metadatas_attributes_0_periods_attributes_0_end_1i"
+
+ click_button "Valider"
+
+ clone = Referential.where(name: "Copie de first")
+
+ expect(clone.lines).to include(line)
+ expect(clone.lines.first.routes).to match_array(referential.lines.first.routes)
+
+ clone_jp = clone.lines.first.routes.first.journey_patterns
+ expect(clone_jp).to include(jp)
+
+ clone_vj = clone.lines.first.routes.first.journey_patterns.first.vehicle_journeys
+ expect(clone_vj).to include(vj)
+
+ clone_tt = clone.lines.first.routes.first.journey_patterns.first.vehicle_journeys.first.time_tables
+ expect(clone_tt).to include(tt)
+ end
+
+ # it "should have the lines from source" do
+ # expect(clone.lines).to include(line)
+ # end
+ #
+ # it "should have the routes from source" do
+ # expect(clone.lines.first.routes).to match_array(referential.lines.first.routes)
+ # end
+ #
+ # it "should have the journey patterns from source" do
+ # clone_jp = clone.lines.first.routes.first.journey_patterns
+ # expect(clone_jp).to include(jp)
+ # end
+ #
+ # it "should have the vehicle journeys from source" do
+ # clone_vj = clone.lines.first.routes.first.journey_patterns.first.vehicle_journeys
+ # expect(clone_vj).to include(vj)
+ # end
+ #
+ # it "should have the timetables from source" do
+ # clone_tt = clone.lines.first.routes.first.journey_patterns.first.vehicle_journeys.first.time_tables
+ # expect(clone_tt).to include(tt)
+ # end
+ end
+
+ # context "when user is from another organisation" do
+ # before :each do
+ #
+ # end
+ # end
+ end
+
describe "destroy" do
let(:referential) { create(:referential, :organisation => @user.organisation) }
diff --git a/spec/features/workbenches_spec.rb b/spec/features/workbenches_spec.rb
index 536469a46..14809dec1 100644
--- a/spec/features/workbenches_spec.rb
+++ b/spec/features/workbenches_spec.rb
@@ -178,16 +178,24 @@ describe 'Workbenches', type: :feature do
end
describe 'create new Referential' do
+ #TODO Manage functional_scope
it "create a new Referential with a specifed line and period" do
- referential.destroy
+ skip "The functional scope for the Line collection causes problems" do
+ functional_scope = JSON.generate(Chouette::Line.all.map(&:objectid))
+ lines = Chouette::Line.where(objectid: functional_scope)
- visit workbench_path(workbench)
- click_link I18n.t('actions.add')
- fill_in "referential[name]", with: "Referential to test creation"
- select workbench.lines.first.id, from: 'referential[metadatas_attributes][0][lines][]'
+ @user.organisation.update_attribute(:sso_attributes, { functional_scope: functional_scope } )
+ ref_metadata.update_attribute(:line_ids, lines.map(&:id))
+
+ referential.destroy
+ visit workbench_path(workbench)
+ click_link I18n.t('actions.add')
+ fill_in "referential[name]", with: "Referential to test creation"
+ select ref_metadata.line_ids.first, from: 'referential[metadatas_attributes][0][lines][]'
- click_button "Valider"
- expect(page).to have_css("h1", text: "Referential to test creation")
+ click_button "Valider"
+ expect(page).to have_css("h1", text: "Referential to test creation")
+ end
end
end
end
diff --git a/spec/fixtures/OFFRE_TRANSDEV_2017030112251.zip b/spec/fixtures/OFFRE_TRANSDEV_2017030112251.zip
new file mode 100644
index 000000000..566cc5b0b
--- /dev/null
+++ b/spec/fixtures/OFFRE_TRANSDEV_2017030112251.zip
Binary files differ
diff --git a/spec/fixtures/single_reference_import.zip b/spec/fixtures/single_reference_import.zip
index 4aee23614..37a516f69 100644
--- a/spec/fixtures/single_reference_import.zip
+++ b/spec/fixtures/single_reference_import.zip
Binary files differ
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:siri="http://www.siri.org.uk/siri" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_CALENDRIER-1_20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_CALENDRIER"/>
+ <netex:ValidBetween>
+ <netex:FromDate>2017-03-01</netex:FromDate>
+ <netex:ToDate>2017-03-31</netex:ToDate>
+ </netex:ValidBetween>
+ <netex:members>
+ <netex:dayTypes>
+ <netex:DayType id="CITYWAY:DayType:1:LOC" version="any" >
+ <netex:Name>Semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Monday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Tuesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Wednesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Thursday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Friday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:2:LOC" version="any" >
+ <netex:Name>Fin de semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Saturday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Sunday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:3:LOC" version="any" >
+ <netex:Name>Service spécial</netex:Name>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:4:LOC" version="any" >
+ <netex:Name>Restriction</netex:Name>
+ </netex:DayType>
+ </netex:dayTypes>
+ <netex:dayTypeAssignments>
+ <netex:DayTypeAssignment version="any" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment version="any" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:2:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment version="any" >
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC" version="any"/>
+ <netex:isAvailable>true</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment version="any" >
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ </netex:dayTypeAssignments>
+ <netex:operatingPeriods>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:1:LOC" version="any" >
+ <netex:FromDate>2017-01-01</netex:FromDate>
+ <netex:ToDate>2017-12-31</netex:ToDate>
+ </netex:OperatingPeriod>
+ </netex:operatingPeriods>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:siri="http://www.siri.org.uk/siri" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_COMMUN-1_20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_COMMUN"/>
+ <netex:members>
+ <netex:notices>
+ <netex:Notice id="CITYWAY:Notice:1:LOC" version="any">
+ <netex:Text>Notice 1</netex:Text>
+ <netex:PublicCode>1</netex:PublicCode>
+ <netex:TypeOfNoticeRef>ServiceJourneyNotice</netex:TypeOfNoticeRef>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:2:LOC" version="any">
+ <netex:Text>Notice 2</netex:Text>
+ <netex:PublicCode>2</netex:PublicCode>
+ <netex:TypeOfNoticeRef>ServiceJourneyNotice</netex:TypeOfNoticeRef>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:3:LOC" version="any">
+ <netex:Text>Notice 3</netex:Text>
+ <netex:PublicCode>3</netex:PublicCode>
+ <netex:TypeOfNoticeRef>ServiceJourneyNotice</netex:TypeOfNoticeRef>
+ </netex:Notice>
+ </netex:notices>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd"
+ xmlns:netex="http://www.netex.org.uk/netex" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ifopt="http://www.ifopt.org.uk/ifopt" xmlns:gml="http://www.opengis.net/gml/3.2"
+ xmlns:core="http://www.govtalk.gov.uk/core" xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+ <netex:routes>
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+ </netex:routes>
+ <netex:directions>
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là</netex:Name>
+ </netex:Direction>
+ </netex:directions>
+ <netex:serviceJourneyPatterns>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any">
+ <netex:Name>Par ici</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC"
+ version="any">
+ <netex:Name>Par là</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ </netex:serviceJourneyPatterns>
+ <netex:destinationDisplays>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC"
+ version="any">
+ <netex:FrontText>Mission 1</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC"
+ version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+ </netex:destinationDisplays>
+ <netex:scheduledStopPoints>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC"
+ version="any"/>
+ </netex:scheduledStopPoints>
+ <netex:passengerStopAssignments>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009052:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009053:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ </netex:passengerStopAssignments>
+ <netex:routingConstraintZones>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC"
+ version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ </netex:routingConstraintZones>
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+ <netex:serviceJourneys>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment>
+ <netex:NoticeRef ref="CITYWAY:Notice:1:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC">
+ version="any"</netex:DayTypeRef>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:011">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ </netex:serviceJourneys>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd"
+ xmlns:netex="http://www.netex.org.uk/netex" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ifopt="http://www.ifopt.org.uk/ifopt" xmlns:gml="http://www.opengis.net/gml/3.2"
+ xmlns:core="http://www.govtalk.gov.uk/core" xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+ <netex:routes>
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+ </netex:routes>
+ <netex:directions>
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici aussi</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là aussi</netex:Name>
+ </netex:Direction>
+ </netex:directions>
+ <netex:serviceJourneyPatterns>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any">
+ <netex:Name>Par ici itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC"
+ version="any">
+ <netex:Name>Par là itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ </netex:serviceJourneyPatterns>
+ <netex:destinationDisplays>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC"
+ version="any">
+ <netex:FrontText>Mission 1 bis</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC"
+ version="any">
+ <netex:FrontText>Mission 2 bis</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+ </netex:destinationDisplays>
+ <netex:scheduledStopPoints>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC"
+ version="any"/>
+ </netex:scheduledStopPoints>
+ <netex:passengerStopAssignments>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000918:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000917:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ </netex:passengerStopAssignments>
+ <netex:routingConstraintZones>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC"
+ version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ </netex:routingConstraintZones>
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+ <netex:serviceJourneys>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici aussi</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment>
+ <netex:NoticeRef ref="CITYWAY:Notice:2:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC">
+ version="any"</netex:DayTypeRef>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC">
+ version="any"</netex:DayTypeRef>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:212">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>23:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>23:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>1</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ </netex:serviceJourneys>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/calendriers.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/calendriers.xml
new file mode 100644
index 000000000..1043e0cde
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/calendriers.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_CALENDRIER-1_20170214090012:LOC" version="any">
+ <netex:ValidBetween>
+ <netex:FromDate>2017-04-01T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-12-31T00:00:00</netex:ToDate>
+ </netex:ValidBetween>
+ <netex:TypeOfFrameRef ref="NETEX_CALENDRIER"/>
+ <netex:members>
+ <netex:DayType id="CITYWAY:DayType:1:LOC" version="any">
+ <netex:Name>Semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Monday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Tuesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Wednesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Thursday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Friday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:2:LOC" version="any">
+ <netex:Name>Fin de semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Saturday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Sunday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:3:LOC" version="any">
+ <netex:Name>Service spécial</netex:Name>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:4:LOC" version="any">
+ <netex:Name>Restriction</netex:Name>
+ </netex:DayType>
+ <netex:DayTypeAssignment id="dta1" version="any" order="0">
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="dta2" version="any" order="0">
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:2:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="dta3" version="any" order="0">
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC" version="any"/>
+ <netex:isAvailable>true</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="dta4" version="any" order="0">
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:1:LOC" version="any">
+ <netex:FromDate>2017-01-01T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-12-31T00:00:00</netex:ToDate>
+ </netex:OperatingPeriod>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml
new file mode 100644
index 000000000..f59f8ac2d
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt" xmlns:gml="http://www.opengis.net/gml/3.2"
+ xmlns:core="http://www.govtalk.gov.uk/core" xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_COMMUN-1_20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_COMMUN"/>
+ <netex:members>
+
+ <netex:Notice id="CITYWAY:Notice:1:LOC" version="any">
+ <netex:Text>Notice 1</netex:Text>
+ <netex:PublicCode>1</netex:PublicCode>
+ <netex:TypeOfNoticeRef ref="ServiceJourneyNotice"/>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:2:LOC" version="any">
+ <netex:Text>Notice 2</netex:Text>
+ <netex:PublicCode>2</netex:PublicCode>
+ <netex:TypeOfNoticeRef ref="ServiceJourneyNotice"/>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:3:LOC" version="any">
+ <netex:Text>Notice 3</netex:Text>
+ <netex:PublicCode>3</netex:PublicCode>
+ <netex:TypeOfNoticeRef ref="ServiceJourneyNotice"/>
+ </netex:Notice>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
new file mode 100644
index 000000000..9eefeeb43
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+
+
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là</netex:Name>
+ </netex:Direction>
+
+
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>Par ici</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC" version="any">
+ <netex:Name>Par là</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+
+
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC" version="any">
+ <netex:FrontText>Mission 1</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+
+
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+
+
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009052:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009053:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+
+
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC" version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="ns1" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:1:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:dayTypes>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:011">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
new file mode 100644
index 000000000..d260ef17e
--- /dev/null
+++ b/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+
+
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici aussi</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là aussi</netex:Name>
+ </netex:Direction>
+
+
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>Par ici itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC" version="any">
+ <netex:Name>Par là itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+
+
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC" version="any">
+ <netex:FrontText>Mission 1 bis</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2 bis</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+
+
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+
+
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000918:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000917:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+
+
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC" version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici aussi</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="ns1" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:2:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:dayTypes>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC"> version="any"</netex:DayTypeRef>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:212">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>23:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>23:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>1</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/calendriers.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/calendriers.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:siri="http://www.siri.org.uk/siri" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_CALENDRIER-1_20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_CALENDRIER"/>
+ <netex:ValidBetween>
+ <netex:FromDate>2017-03-01</netex:FromDate>
+ <netex:ToDate>2017-03-31</netex:ToDate>
+ </netex:ValidBetween>
+ <netex:members>
+ <netex:dayTypes>
+ <netex:DayType id="CITYWAY:DayType:1:LOC" version="any" >
+ <netex:Name>Semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Monday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Tuesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Wednesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Thursday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Friday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:2:LOC" version="any" >
+ <netex:Name>Fin de semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Saturday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Sunday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:3:LOC" version="any" >
+ <netex:Name>Service spécial</netex:Name>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:4:LOC" version="any" >
+ <netex:Name>Restriction</netex:Name>
+ </netex:DayType>
+ </netex:dayTypes>
+ <netex:dayTypeAssignments>
+ <netex:DayTypeAssignment version="any" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment version="any" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:2:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment version="any" >
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC" version="any"/>
+ <netex:isAvailable>true</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment version="any" >
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ </netex:dayTypeAssignments>
+ <netex:operatingPeriods>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:1:LOC" version="any" >
+ <netex:FromDate>2017-01-01</netex:FromDate>
+ <netex:ToDate>2017-12-31</netex:ToDate>
+ </netex:OperatingPeriod>
+ </netex:operatingPeriods>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/commun.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/commun.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:siri="http://www.siri.org.uk/siri" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_COMMUN-1_20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_COMMUN"/>
+ <netex:members>
+ <netex:notices>
+ <netex:Notice id="CITYWAY:Notice:1:LOC" version="any">
+ <netex:Text>Notice 1</netex:Text>
+ <netex:PublicCode>1</netex:PublicCode>
+ <netex:TypeOfNoticeRef>ServiceJourneyNotice</netex:TypeOfNoticeRef>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:2:LOC" version="any">
+ <netex:Text>Notice 2</netex:Text>
+ <netex:PublicCode>2</netex:PublicCode>
+ <netex:TypeOfNoticeRef>ServiceJourneyNotice</netex:TypeOfNoticeRef>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:3:LOC" version="any">
+ <netex:Text>Notice 3</netex:Text>
+ <netex:PublicCode>3</netex:PublicCode>
+ <netex:TypeOfNoticeRef>ServiceJourneyNotice</netex:TypeOfNoticeRef>
+ </netex:Notice>
+ </netex:notices>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd"
+ xmlns:netex="http://www.netex.org.uk/netex" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ifopt="http://www.ifopt.org.uk/ifopt" xmlns:gml="http://www.opengis.net/gml/3.2"
+ xmlns:core="http://www.govtalk.gov.uk/core" xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+ <netex:routes>
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+ </netex:routes>
+ <netex:directions>
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là</netex:Name>
+ </netex:Direction>
+ </netex:directions>
+ <netex:serviceJourneyPatterns>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any">
+ <netex:Name>Par ici</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC"
+ version="any">
+ <netex:Name>Par là</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ </netex:serviceJourneyPatterns>
+ <netex:destinationDisplays>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC"
+ version="any">
+ <netex:FrontText>Mission 1</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC"
+ version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+ </netex:destinationDisplays>
+ <netex:scheduledStopPoints>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC"
+ version="any"/>
+ </netex:scheduledStopPoints>
+ <netex:passengerStopAssignments>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009052:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009053:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ </netex:passengerStopAssignments>
+ <netex:routingConstraintZones>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC"
+ version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ </netex:routingConstraintZones>
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+ <netex:serviceJourneys>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment>
+ <netex:NoticeRef ref="CITYWAY:Notice:1:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC">
+ version="any"</netex:DayTypeRef>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:011">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ </netex:serviceJourneys>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd"
+ xmlns:netex="http://www.netex.org.uk/netex" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:ifopt="http://www.ifopt.org.uk/ifopt" xmlns:gml="http://www.opengis.net/gml/3.2"
+ xmlns:core="http://www.govtalk.gov.uk/core" xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+ <netex:routes>
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+ </netex:routes>
+ <netex:directions>
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici aussi</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là aussi</netex:Name>
+ </netex:Direction>
+ </netex:directions>
+ <netex:serviceJourneyPatterns>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any">
+ <netex:Name>Par ici itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC"
+ version="any">
+ <netex:Name>Par là itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC"
+ version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern
+ id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ </netex:serviceJourneyPatterns>
+ <netex:destinationDisplays>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC"
+ version="any">
+ <netex:FrontText>Mission 1 bis</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC"
+ version="any">
+ <netex:FrontText>Mission 2 bis</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+ </netex:destinationDisplays>
+ <netex:scheduledStopPoints>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC"
+ version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC"
+ version="any"/>
+ </netex:scheduledStopPoints>
+ <netex:passengerStopAssignments>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000918:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000917:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment
+ id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any">
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ </netex:passengerStopAssignments>
+ <netex:routingConstraintZones>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC"
+ version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef
+ ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ </netex:routingConstraintZones>
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC"
+ version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+ <netex:serviceJourneys>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici aussi</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment>
+ <netex:NoticeRef ref="CITYWAY:Notice:2:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC">
+ version="any"</netex:DayTypeRef>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC">
+ version="any"</netex:DayTypeRef>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC"
+ version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:212">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>23:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>23:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>1</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ </netex:serviceJourneys>
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/calendriers.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/calendriers.xml
new file mode 100644
index 000000000..1043e0cde
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/calendriers.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_CALENDRIER-1_20170214090012:LOC" version="any">
+ <netex:ValidBetween>
+ <netex:FromDate>2017-04-01T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-12-31T00:00:00</netex:ToDate>
+ </netex:ValidBetween>
+ <netex:TypeOfFrameRef ref="NETEX_CALENDRIER"/>
+ <netex:members>
+ <netex:DayType id="CITYWAY:DayType:1:LOC" version="any">
+ <netex:Name>Semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Monday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Tuesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Wednesday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Thursday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Friday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:2:LOC" version="any">
+ <netex:Name>Fin de semaine</netex:Name>
+ <netex:properties>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Saturday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ <netex:PropertyOfDay>
+ <netex:DaysOfWeek>Sunday</netex:DaysOfWeek>
+ </netex:PropertyOfDay>
+ </netex:properties>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:3:LOC" version="any">
+ <netex:Name>Service spécial</netex:Name>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:4:LOC" version="any">
+ <netex:Name>Restriction</netex:Name>
+ </netex:DayType>
+ <netex:DayTypeAssignment id="dta1" version="any" order="0">
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="dta2" version="any" order="0">
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:1:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:2:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="dta3" version="any" order="0">
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC" version="any"/>
+ <netex:isAvailable>true</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="dta4" version="any" order="0">
+ <netex:Date>2017-03-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:1:LOC" version="any">
+ <netex:FromDate>2017-01-01T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-12-31T00:00:00</netex:ToDate>
+ </netex:OperatingPeriod>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/commun.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/commun.xml
new file mode 100644
index 000000000..f59f8ac2d
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/commun.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt" xmlns:gml="http://www.opengis.net/gml/3.2"
+ xmlns:core="http://www.govtalk.gov.uk/core" xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_COMMUN-1_20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_COMMUN"/>
+ <netex:members>
+
+ <netex:Notice id="CITYWAY:Notice:1:LOC" version="any">
+ <netex:Text>Notice 1</netex:Text>
+ <netex:PublicCode>1</netex:PublicCode>
+ <netex:TypeOfNoticeRef ref="ServiceJourneyNotice"/>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:2:LOC" version="any">
+ <netex:Text>Notice 2</netex:Text>
+ <netex:PublicCode>2</netex:PublicCode>
+ <netex:TypeOfNoticeRef ref="ServiceJourneyNotice"/>
+ </netex:Notice>
+ <netex:Notice id="CITYWAY:Notice:3:LOC" version="any">
+ <netex:Text>Notice 3</netex:Text>
+ <netex:PublicCode>3</netex:PublicCode>
+ <netex:TypeOfNoticeRef ref="ServiceJourneyNotice"/>
+ </netex:Notice>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
new file mode 100644
index 000000000..9eefeeb43
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00108">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+
+
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là</netex:Name>
+ </netex:Direction>
+
+
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>Par ici</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC" version="any">
+ <netex:Name>Par là</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+
+
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC" version="any">
+ <netex:FrontText>Mission 1</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+
+
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+
+
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009052:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50009053:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+
+
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC" version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="ns1" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:1:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:dayTypes>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:011">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>01:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>01:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
new file mode 100644
index 000000000..d260ef17e
--- /dev/null
+++ b/spec/fixtures/target/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<netex:PublicationDelivery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.netex.org.uk/netex ../../xsd/NeTEx_publication.xsd" xmlns:netex="http://www.netex.org.uk/netex"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ifopt="http://www.ifopt.org.uk/ifopt"
+ xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:core="http://www.govtalk.gov.uk/core"
+ xmlns:siri="http://www.siri.org.uk/siri" version="1.0">
+ <netex:PublicationTimestamp>2017-02-14T09:13:51.0</netex:PublicationTimestamp>
+ <netex:ParticipantRef>CITYWAY</netex:ParticipantRef>
+ <netex:dataObjects>
+ <netex:CompositeFrame id="CITYWAY:CompositeFrame:NETEX_OFFRE_LIGNE-1:LOC" version="any">
+ <netex:Name>Ligne 1</netex:Name>
+ <netex:TypeOfFrameRef ref="NETEX_OFFRE_LIGNE"/>
+ <netex:frames>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_STRUCTURE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_STRUCTURE"/>
+ <netex:members>
+
+ <netex:Route id="CITYWAY:Route:1:LOC" version="any">
+ <netex:Name>route 1</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:2:LOC" version="any">
+ <netex:Name>route 2</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00109">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+
+
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>Par ici aussi</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Par là aussi</netex:Name>
+ </netex:Direction>
+
+
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>Par ici itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:1:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:2:LOC" version="any">
+ <netex:Name>Par là itou</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-1:LOC" order="1"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-2:LOC" order="2"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ </netex:pointsInSequence>
+ <netex:ServiceJourneyPatternType>passenger</netex:ServiceJourneyPatternType>
+ </netex:ServiceJourneyPattern>
+
+
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:1:LOC" version="any">
+ <netex:FrontText>Mission 1 bis</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2 bis</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+
+
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+
+
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094817:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-1:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000918:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78402:ZDE:50000917:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-2:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78217:ZDE:50094816:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+
+
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC" version="any">
+ <netex:Name>ITL 1</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-2:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ <netex:GeneralFrame id="CITYWAY:GeneralFrame:NETEX_HORAIRE-20170214090012:LOC" version="any">
+ <netex:TypeOfFrameRef ref="NETEX_HORAIRE"/>
+ <netex:members>
+
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-1:LOC" version="any">
+ <netex:Name>Course 1 par ici aussi</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="ns1" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:2:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:dayTypes>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC"> version="any"</netex:DayTypeRef>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:212">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:1234:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>23:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>23:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>1</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+
+ </netex:members>
+ </netex:GeneralFrame>
+ </netex:frames>
+ </netex:CompositeFrame>
+ </netex:dataObjects>
+</netex:PublicationDelivery>
diff --git a/spec/helpers/table_builder_helper/column_spec.rb b/spec/helpers/table_builder_helper/column_spec.rb
index 0f27703b2..e0bfd8a6a 100644
--- a/spec/helpers/table_builder_helper/column_spec.rb
+++ b/spec/helpers/table_builder_helper/column_spec.rb
@@ -20,4 +20,43 @@ describe TableBuilderHelper::Column do
).to eq('Numéro de téléphone')
end
end
+
+ describe "#linkable?" do
+ it "returns true if :link_to is not nil" do
+ expect(
+ TableBuilderHelper::Column.new(
+ name: 'unused',
+ attribute: nil,
+ link_to: lambda do
+ train.kind
+ end
+ ).linkable?
+ ).to be true
+ end
+
+ it "returns false if :link_to is nil" do
+ expect(
+ TableBuilderHelper::Column.new(
+ name: 'unused',
+ attribute: nil
+ ).linkable?
+ ).to be false
+ end
+ end
+
+ describe "#link_to" do
+ it "calls the block passed in and returns the result" do
+ train = double('train', kind: 'TGV')
+
+ expect(
+ TableBuilderHelper::Column.new(
+ name: 'unused',
+ attribute: nil,
+ link_to: lambda do |train|
+ train.kind
+ end
+ ).link_to(train)
+ ).to eq('TGV')
+ end
+ end
end
diff --git a/spec/helpers/table_builder_helper_spec.rb b/spec/helpers/table_builder_helper_spec.rb
index c536a4c62..e17196a19 100644
--- a/spec/helpers/table_builder_helper_spec.rb
+++ b/spec/helpers/table_builder_helper_spec.rb
@@ -96,7 +96,10 @@ describe TableBuilderHelper, type: :helper do
[
TableBuilderHelper::Column.new(
key: :name,
- attribute: 'name'
+ attribute: 'name',
+ link_to: lambda do |referential|
+ referential_path(referential)
+ end
),
TableBuilderHelper::Column.new(
key: :status,
@@ -238,7 +241,10 @@ describe TableBuilderHelper, type: :helper do
),
TableBuilderHelper::Column.new(
key: :name,
- attribute: 'name'
+ attribute: 'name',
+ link_to: lambda do |company|
+ referential_company_path(referential, company)
+ end
),
TableBuilderHelper::Column.new(
key: :phone,
@@ -347,7 +353,10 @@ describe TableBuilderHelper, type: :helper do
),
TableBuilderHelper::Column.new(
key: :name,
- attribute: 'name'
+ attribute: 'name',
+ link_to: lambda do |company|
+ referential_company_path(referential, company)
+ end
),
TableBuilderHelper::Column.new(
key: :phone,
diff --git a/spec/javascripts/time_table/actions_spec.js b/spec/javascripts/time_table/actions_spec.js
index ebd1bb04c..f052aeece 100644
--- a/spec/javascripts/time_table/actions_spec.js
+++ b/spec/javascripts/time_table/actions_spec.js
@@ -158,33 +158,41 @@ describe('actions', () => {
let modalProps = {}
let timeTablePeriods = []
let metas = {}
+ let timetableInDates = []
+ let error = ''
const expectedAction = {
type: 'VALIDATE_PERIOD_FORM',
modalProps,
timeTablePeriods,
- metas
+ metas,
+ timetableInDates,
+ error
}
- expect(actions.validatePeriodForm(modalProps, timeTablePeriods, metas)).toEqual(expectedAction)
+ expect(actions.validatePeriodForm(modalProps, timeTablePeriods, metas, timetableInDates, error)).toEqual(expectedAction)
})
it('should create an action to include date in period', () => {
let index = 1
+ let date = actions.formatDate(new Date)
const expectedAction = {
type: 'INCLUDE_DATE_IN_PERIOD',
index,
- dayTypes
+ dayTypes,
+ date
}
- expect(actions.includeDateInPeriod(index, dayTypes)).toEqual(expectedAction)
+ expect(actions.includeDateInPeriod(index, dayTypes, date)).toEqual(expectedAction)
})
it('should create an action to exclude date from period', () => {
let index = 1
+ let date = actions.formatDate(new Date)
const expectedAction = {
type: 'EXCLUDE_DATE_FROM_PERIOD',
index,
- dayTypes
+ dayTypes,
+ date
}
- expect(actions.excludeDateFromPeriod(index, dayTypes)).toEqual(expectedAction)
+ expect(actions.excludeDateFromPeriod(index, dayTypes, date)).toEqual(expectedAction)
})
it('should create an action to open confirm modal', () => {
diff --git a/spec/javascripts/time_table/reducers/modal_spec.js b/spec/javascripts/time_table/reducers/modal_spec.js
index 4246027b8..570eb85ed 100644
--- a/spec/javascripts/time_table/reducers/modal_spec.js
+++ b/spec/javascripts/time_table/reducers/modal_spec.js
@@ -154,7 +154,7 @@ describe('modal reducer', () => {
error: ''
}
let newModalProps = {
- active: false,
+ active: true,
begin: {
day: '01',
month: '01',
@@ -170,12 +170,15 @@ describe('modal reducer', () => {
}
let ttperiods = []
+ let ttdates = []
expect(
modalReducer(state, {
type: 'VALIDATE_PERIOD_FORM',
modalProps : modProps,
- timeTablePeriods: ttperiods
+ timeTablePeriods: ttperiods,
+ timetableInDates: ttdates,
+ error: 'La date de départ doit être antérieure à la date de fin'
})
).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
})
@@ -222,6 +225,8 @@ describe('modal reducer', () => {
{id: 265, period_start: '2017-05-14', period_end: '2017-05-24'}
]
+ let ttdates2 = []
+
let newModalProps2 = {
active: true,
begin: {
@@ -242,8 +247,76 @@ describe('modal reducer', () => {
modalReducer(state2, {
type: 'VALIDATE_PERIOD_FORM',
modalProps : modProps2,
- timeTablePeriods: ttperiods2
+ timeTablePeriods: ttperiods2,
+ timetableInDates: ttdates2,
+ error: "Les périodes ne peuvent pas se chevaucher"
})
).toEqual(Object.assign({}, state2, {modalProps: newModalProps2}))
})
+
+ it('should handle VALIDATE_PERIOD_FORM and throw error if period overlaps date', () => {
+ let state3 = {
+ confirmModal: {},
+ modalProps: {
+ active: false,
+ begin: {
+ day: '01',
+ month: '08',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '08',
+ year: '2017'
+ },
+ index: false,
+ error: ''
+ },
+ type: ''
+ }
+ let modProps3 = {
+ active: true,
+ begin: {
+ day: '01',
+ month: '08',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '08',
+ year: '2017'
+ },
+ index: false,
+ error: ''
+ }
+ let ttperiods3 = []
+
+ let ttdates3 = [{date: "2017-08-04", include_date: true}]
+
+ let newModalProps3 = {
+ active: true,
+ begin: {
+ day: '01',
+ month: '08',
+ year: '2017'
+ },
+ end: {
+ day: '09',
+ month: '08',
+ year: '2017'
+ },
+ index: false,
+ error: "Une période ne peut chevaucher une date dans un calendrier"
+ }
+
+ expect(
+ modalReducer(state3, {
+ type: 'VALIDATE_PERIOD_FORM',
+ modalProps : modProps3,
+ timeTablePeriods: ttperiods3,
+ timetableInDates: ttdates3,
+ error: "Une période ne peut chevaucher une date dans un calendrier"
+ })
+ ).toEqual(Object.assign({}, state3, {modalProps: newModalProps3}))
+ })
})
diff --git a/spec/javascripts/time_table/reducers/timetable_spec.js b/spec/javascripts/time_table/reducers/timetable_spec.js
index 0b418a52e..6585a78a0 100644
--- a/spec/javascripts/time_table/reducers/timetable_spec.js
+++ b/spec/javascripts/time_table/reducers/timetable_spec.js
@@ -12,12 +12,15 @@ let current_month = [{"day":"lundi","date":"2017-05-01","wday":1,"wnumber":"18",
let newCurrentMonth = [{"day":"lundi","date":"2017-05-01","wday":1,"wnumber":"18","mday":1,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mardi","date":"2017-05-02","wday":2,"wnumber":"18","mday":2,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mercredi","date":"2017-05-03","wday":3,"wnumber":"18","mday":3,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"jeudi","date":"2017-05-04","wday":4,"wnumber":"18","mday":4,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"vendredi","date":"2017-05-05","wday":5,"wnumber":"18","mday":5,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"samedi","date":"2017-05-06","wday":6,"wnumber":"18","mday":6,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"dimanche","date":"2017-05-07","wday":0,"wnumber":"18","mday":7,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"lundi","date":"2017-05-08","wday":1,"wnumber":"19","mday":8,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mardi","date":"2017-05-09","wday":2,"wnumber":"19","mday":9,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mercredi","date":"2017-05-10","wday":3,"wnumber":"19","mday":10,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"jeudi","date":"2017-05-11","wday":4,"wnumber":"19","mday":11,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"vendredi","date":"2017-05-12","wday":5,"wnumber":"19","mday":12,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"samedi","date":"2017-05-13","wday":6,"wnumber":"19","mday":13,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"dimanche","date":"2017-05-14","wday":0,"wnumber":"19","mday":14,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"lundi","date":"2017-05-15","wday":1,"wnumber":"20","mday":15,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mardi","date":"2017-05-16","wday":2,"wnumber":"20","mday":16,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mercredi","date":"2017-05-17","wday":3,"wnumber":"20","mday":17,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"jeudi","date":"2017-05-18","wday":4,"wnumber":"20","mday":18,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"vendredi","date":"2017-05-19","wday":5,"wnumber":"20","mday":19,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"samedi","date":"2017-05-20","wday":6,"wnumber":"20","mday":20,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"dimanche","date":"2017-05-21","wday":0,"wnumber":"20","mday":21,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"lundi","date":"2017-05-22","wday":1,"wnumber":"21","mday":22,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mardi","date":"2017-05-23","wday":2,"wnumber":"21","mday":23,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"mercredi","date":"2017-05-24","wday":3,"wnumber":"21","mday":24,"include_date":false,"excluded_date":false,"in_periods":true},{"day":"jeudi","date":"2017-05-25","wday":4,"wnumber":"21","mday":25,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"vendredi","date":"2017-05-26","wday":5,"wnumber":"21","mday":26,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"samedi","date":"2017-05-27","wday":6,"wnumber":"21","mday":27,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"dimanche","date":"2017-05-28","wday":0,"wnumber":"21","mday":28,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"lundi","date":"2017-05-29","wday":1,"wnumber":"22","mday":29,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mardi","date":"2017-05-30","wday":2,"wnumber":"22","mday":30,"include_date":false,"excluded_date":false,"in_periods":false},{"day":"mercredi","date":"2017-05-31","wday":3,"wnumber":"22","mday":31,"include_date":false,"excluded_date":false,"in_periods":false}]
+let time_table_dates = []
+
let json = {
current_month: current_month,
current_periode_range: current_periode_range,
periode_range: periode_range,
time_table_periods: time_table_periods,
- day_types: strDayTypes
+ day_types: strDayTypes,
+ time_table_dates: time_table_dates
}
describe('timetable reducer with empty state', () => {
@@ -26,7 +29,8 @@ describe('timetable reducer with empty state', () => {
current_month: [],
current_periode_range: "",
periode_range: [],
- time_table_periods: []
+ time_table_periods: [],
+ time_table_dates: []
}
})
@@ -42,6 +46,7 @@ describe('timetable reducer with empty state', () => {
current_periode_range: current_periode_range,
periode_range: periode_range,
time_table_periods: time_table_periods,
+ time_table_dates: time_table_dates
}
expect(
timetableReducer(state, {
@@ -59,6 +64,7 @@ describe('timetable reducer with filled state', () => {
current_periode_range: current_periode_range,
periode_range: periode_range,
time_table_periods: time_table_periods,
+ time_table_dates: time_table_dates
}
})
@@ -130,45 +136,92 @@ describe('timetable reducer with filled state', () => {
).toEqual(state)
})
- it('should handle INCLUDE_DATE_IN_PERIOD', () => {
+ it('should handle INCLUDE_DATE_IN_PERIOD and add in_day if TT doesnt have it', () => {
+ let newDates = state.time_table_dates.concat({date: "2017-05-05", in_out: true})
+ let newState = Object.assign({}, state, {time_table_dates: newDates})
state.current_month[4].include_date = true
expect(
timetableReducer(state, {
type: 'INCLUDE_DATE_IN_PERIOD',
index: 4,
- dayTypes: arrDayTypes
+ dayTypes: arrDayTypes,
+ date: "2017-05-05"
})
- ).toEqual(state)
+ ).toEqual(newState)
+ })
+
+ it('should handle INCLUDE_DATE_IN_PERIOD and remove in_day if TT has it', () => {
+ state.current_month[4].include_date = true
+ state.time_table_dates.push({date: "2017-05-05", in_out: true})
+ let newState = Object.assign({}, state, {time_table_dates: []})
+ expect(
+ timetableReducer(state, {
+ type: 'INCLUDE_DATE_IN_PERIOD',
+ index: 4,
+ dayTypes: arrDayTypes,
+ date: "2017-05-05"
+ })
+ ).toEqual(newState)
})
- it('should handle EXCLUDE_DATE_FROM_PERIOD', () => {
+ it('should handle EXCLUDE_DATE_FROM_PERIOD and add out_day if TT doesnt have it', () => {
+ let newDates = state.time_table_dates.concat({date: "2017-05-01", in_out: false})
+ let newState = Object.assign({}, state, {time_table_dates: newDates})
state.current_month[0].excluded_date = true
expect(
timetableReducer(state, {
type: 'EXCLUDE_DATE_FROM_PERIOD',
index: 0,
- dayTypes: arrDayTypes
+ dayTypes: arrDayTypes,
+ date: "2017-05-01"
})
- ).toEqual(state)
+ ).toEqual(newState)
})
- it('should handle VALIDATE_PERIOD_FORM', () => {
- state.current_month[13].in_periods = false
- state.time_table_periods[4].period_start = '2017-05-15'
+ it('should handle EXCLUDE_DATE_FROM_PERIOD and remove out_day if TT has it', () => {
+ state.time_table_dates = [{date: "2017-05-01", in_out: false}]
+ state.current_month[0].excluded_date = true
+ let newState = Object.assign({}, state, {time_table_dates: []})
+ expect(
+ timetableReducer(state, {
+ type: 'EXCLUDE_DATE_FROM_PERIOD',
+ index: 0,
+ dayTypes: arrDayTypes,
+ date: "2017-05-01"
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle UPDATE_DAY_TYPES and remove out_day that are out of day types', () => {
+ state.time_table_dates = [{date: "2017-05-01", in_out: false}]
+ let newArrDayTypes = arrDayTypes.slice(0)
+ newArrDayTypes[1] = false
+ let newState = Object.assign({}, state, {time_table_dates: []})
+ expect(
+ timetableReducer(state, {
+ type: 'UPDATE_DAY_TYPES',
+ dayTypes: newArrDayTypes
+ }).time_table_dates
+ ).toEqual([])
+ })
+
+ it('should handle VALIDATE_PERIOD_FORM and add period if modalProps index = false', () => {
+ let newPeriods = state.time_table_periods.concat({"period_start": "2018-05-15", "period_end": "2018-05-24"})
+ let newState = Object.assign({}, state, {time_table_periods: newPeriods})
let modalProps = {
active: false,
begin: {
day: '15',
month: '05',
- year: '2017'
+ year: '2018'
},
end: {
day: '24',
month: '05',
- year: '2017'
+ year: '2018'
},
error: '',
- index: 4
+ index: false
}
expect(
timetableReducer(state, {
@@ -177,8 +230,10 @@ describe('timetable reducer with filled state', () => {
timeTablePeriods: state.time_table_periods,
metas: {
day_types: arrDayTypes
- }
+ },
+ timetableInDates: state.time_table_dates.filter(d => d.in_out == true),
+ error: modalProps.error
})
- ).toEqual(state)
+ ).toEqual(newState)
})
})
diff --git a/spec/javascripts/vehicle_journeys/actions_spec.js b/spec/javascripts/vehicle_journeys/actions_spec.js
index d96baf8ef..707ae22cb 100644
--- a/spec/javascripts/vehicle_journeys/actions_spec.js
+++ b/spec/javascripts/vehicle_journeys/actions_spec.js
@@ -165,12 +165,12 @@ describe('when updating vjas time', () => {
})
describe('when clicking on validate button inside shifting modal', () => {
it('should create an action to shift a vehiclejourney schedule', () => {
- const data = {}
+ const addtionalTime = 0
const expectedAction = {
type: 'SHIFT_VEHICLEJOURNEY',
- data
+ addtionalTime
}
- expect(actions.shiftVehicleJourney(data)).toEqual(expectedAction)
+ expect(actions.shiftVehicleJourney(addtionalTime)).toEqual(expectedAction)
})
})
describe('when clicking on validate button inside editing modal', () => {
@@ -187,14 +187,16 @@ describe('when clicking on validate button inside editing modal', () => {
})
describe('when clicking on validate button inside duplicating modal', () => {
it('should create an action to duplicate a vehiclejourney schedule', () => {
- const data = {}
+ const addtionalTime = 0
const departureDelta = 0
+ const duplicateNumber = 1
const expectedAction = {
type: 'DUPLICATE_VEHICLEJOURNEY',
- data,
+ addtionalTime,
+ duplicateNumber,
departureDelta
}
- expect(actions.duplicateVehicleJourney(data, departureDelta)).toEqual(expectedAction)
+ expect(actions.duplicateVehicleJourney(addtionalTime, duplicateNumber, departureDelta)).toEqual(expectedAction)
})
})
describe('when clicking on edit notes modal', () => {
@@ -432,3 +434,16 @@ describe('when using select2 to pick a company', () => {
expect(actions.select2Company(selectedCompany)).toEqual(expectedAction)
})
})
+describe('when using select2 to unselect a company', () => {
+ it('should create an action to unselect a company inside modal', () => {
+ let selectedCompany = {
+ id: 1,
+ objectid: 2,
+ name: 'test',
+ }
+ const expectedAction = {
+ type: 'UNSELECT_CP_EDIT_MODAL'
+ }
+ expect(actions.unselect2Company()).toEqual(expectedAction)
+ })
+})
diff --git a/spec/javascripts/vehicle_journeys/reducers/modal_spec.js b/spec/javascripts/vehicle_journeys/reducers/modal_spec.js
index c016812da..4530b5ee7 100644
--- a/spec/javascripts/vehicle_journeys/reducers/modal_spec.js
+++ b/spec/javascripts/vehicle_journeys/reducers/modal_spec.js
@@ -167,4 +167,13 @@ describe('modal reducer', () => {
})
).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
})
+
+ it('should handle UNSELECT_CP_EDIT_MODAL', () => {
+ let newModalProps = {selectedCompany : undefined}
+ expect(
+ modalReducer(state, {
+ type: 'UNSELECT_CP_EDIT_MODAL'
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
})
diff --git a/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js b/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js
index 620e2ffdd..3b2137a2a 100644
--- a/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js
+++ b/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js
@@ -198,15 +198,12 @@ describe('vehicleJourneys reducer', () => {
},
stop_area_object_id : "FR:92024:ZDE:420553:STIF"
}]
- let fakeData = {
- objectid: {value : '11'},
- additional_time: {value: '5'}
- }
+ let addtionalTime = 5
let newVJ = Object.assign({}, state[0], {vehicle_journey_at_stops: newVJAS})
expect(
vjReducer(state, {
type: 'SHIFT_VEHICLEJOURNEY',
- data: fakeData
+ addtionalTime
})
).toEqual([newVJ, state[1]])
})
@@ -225,17 +222,17 @@ describe('vehicleJourneys reducer', () => {
stop_area_object_id : "FR:92024:ZDE:420553:STIF"
}]
let departureDelta = 1
- let fakeData = {
- duplicate_number: {value : 1},
- additional_time: {value: '5'}
- }
+ let addtionalTime = 5
+ let duplicateNumber = 1
+
let newVJ = Object.assign({}, state[0], {vehicle_journey_at_stops: newVJAS, selected: false})
newVJ.published_journey_name = state[0].published_journey_name + '-0'
delete newVJ['objectid']
expect(
vjReducer(state, {
type: 'DUPLICATE_VEHICLEJOURNEY',
- data: fakeData,
+ addtionalTime,
+ duplicateNumber,
departureDelta
})
).toEqual([state[0], newVJ, state[1]])
diff --git a/spec/lib/stif/netex_file_spec.rb b/spec/lib/stif/netex_file_spec.rb
new file mode 100644
index 000000000..d84807fe5
--- /dev/null
+++ b/spec/lib/stif/netex_file_spec.rb
@@ -0,0 +1,27 @@
+require "rails_helper"
+
+RSpec.describe STIF::NetexFile do
+
+ let( :zip_file ){ fixtures_path 'OFFRE_TRANSDEV_2017030112251.zip' }
+
+ let(:frames) { STIF::NetexFile.new(zip_file).frames }
+
+ it "should return a frame for each sub directory" do
+ expect(frames.size).to eq(2)
+ end
+
+ def period(from, to)
+ Range.new(Date.parse(from), Date.parse(to))
+ end
+
+
+ context "each frame" do
+ it "should return the line identifiers defined in frame" do
+ expect(frames.map(&:line_refs)).to eq([%w{C00109 C00108}]*2)
+ end
+ it "should return periods defined in frame calendars" do
+ expect(frames.map(&:periods)).to eq([[period("2017-04-01", "2017-12-31")], [period("2017-03-01","2017-03-31")]])
+ end
+ end
+
+end
diff --git a/spec/models/api/v1/api_key_spec.rb b/spec/models/api/v1/api_key_spec.rb
index 5f39a65e4..b700429d3 100644
--- a/spec/models/api/v1/api_key_spec.rb
+++ b/spec/models/api/v1/api_key_spec.rb
@@ -1,34 +1,25 @@
-describe Api::V1::ApiKey, :type => :model do
+require 'rails_helper'
- let(:referential){ create :referential }
+RSpec.describe Api::V1::ApiKey, type: :model do
+ subject { create(:api_key) }
- subject { described_class.create( :name => "test", :referential => referential)}
+ it { should validate_presence_of :organisation }
- it "validity test" do
- expect_it.to be_valid
- expect(subject.referential).to eq(referential)
+ it 'should have a valid factory' do
+ expect(build(:api_key)).to be_valid
end
- context 'Creation' do
- let( :name ){ SecureRandom.urlsafe_base64 }
-
- it 'can be created from a referential with a name, iff needed' do
- # 1st time create a new record
- expect{ described_class.from(referential, name: name) }.to change{ described_class.count }.by(1)
- expect( described_class.last.attributes.values_at(*%w{referential_id name}) ).to eq([
- referential.id, name
- ])
-
- # 2nd time get the same record
- expect{ described_class.from(referential, name: name) }.not_to change{ described_class.count }
- expect( described_class.last.attributes.values_at(*%w{referential_id name}) ).to eq([
- referential.id, name
- ])
+ describe '#referential_from_token' do
+ it 'should return referential' do
+ referential = Api::V1::ApiKey.referential_from_token(subject.token)
+ expect(referential).to eq(subject.referential)
end
+ end
- it 'cannot be created without a referential' do
- expect{ described_class.from(nil, name:name) rescue nil }.not_to change{ described_class.count }
+ describe '#organisation_from_token' do
+ it 'should return organisation' do
+ organisation = Api::V1::ApiKey.organisation_from_token(subject.token)
+ expect(organisation).to eq(subject.organisation)
end
end
end
-
diff --git a/spec/models/chouette/access_link_spec.rb b/spec/models/chouette/access_link_spec.rb
index 0e1e91593..5a31b8f0c 100644
--- a/spec/models/chouette/access_link_spec.rb
+++ b/spec/models/chouette/access_link_spec.rb
@@ -7,7 +7,7 @@ describe Chouette::AccessLink, :type => :model do
describe '#objectid' do
subject { super().objectid }
- it { is_expected.to be_kind_of(Chouette::ObjectId) }
+ it { is_expected.to be_kind_of(Chouette::StifNetexObjectid) }
end
it { is_expected.to validate_presence_of :name }
@@ -19,7 +19,7 @@ describe Chouette::AccessLink, :type => :model do
def self.legacy_link_types
%w{Underground Mixed Overground}
end
-
+
legacy_link_types.each do |link_type|
context "when link_type is #{link_type}" do
access_link_type = Chouette::ConnectionLinkType.new(link_type.underscore)
@@ -32,7 +32,7 @@ describe Chouette::AccessLink, :type => :model do
end
describe "#access_link_type=" do
-
+
it "should change link_type with ConnectionLinkType#name" do
subject.access_link_type = "underground"
expect(subject.link_type).to eq("Underground")
@@ -45,7 +45,7 @@ describe Chouette::AccessLink, :type => :model do
def self.legacy_link_orientations
%w{AccessPointToStopArea StopAreaToAccessPoint}
end
-
+
legacy_link_orientations.each do |link_orientation|
context "when link_orientation is #{link_orientation}" do
link_orientation_type = Chouette::LinkOrientationType.new(link_orientation.underscore)
@@ -59,7 +59,7 @@ describe Chouette::AccessLink, :type => :model do
end
describe "#link_orientation_type=" do
-
+
it "should change link_orientation with LinkOrientationType#name" do
subject.link_orientation_type = "access_point_to_stop_area"
expect(subject.link_orientation).to eq("AccessPointToStopArea")
@@ -76,7 +76,7 @@ describe Chouette::AccessLink, :type => :model do
subject.link_orientation_type = "stop_area_to_access_point"
expect(subject.link_key).to eq("S_#{subject.stop_area.id}-A_#{subject.access_point.id}")
end
-
+
end
end
diff --git a/spec/models/chouette/company_spec.rb b/spec/models/chouette/company_spec.rb
index 3da8b4311..a3101d79c 100644
--- a/spec/models/chouette/company_spec.rb
+++ b/spec/models/chouette/company_spec.rb
@@ -1,13 +1,8 @@
require 'spec_helper'
describe Chouette::Company, :type => :model do
-
subject { create(:company) }
-
- it { is_expected.to validate_presence_of :name }
-
- # it { should validate_presence_of :objectid }
- it { is_expected.to validate_uniqueness_of :objectid }
+ it { should validate_presence_of :name }
describe "#nullables empty" do
it "should set null empty nullable attributes" do
diff --git a/spec/models/chouette/connection_link_spec.rb b/spec/models/chouette/connection_link_spec.rb
index 5921bf581..57eb7d66c 100644
--- a/spec/models/chouette/connection_link_spec.rb
+++ b/spec/models/chouette/connection_link_spec.rb
@@ -11,7 +11,7 @@ describe Chouette::ConnectionLink, :type => :model do
describe '#objectid' do
subject { super().objectid }
- it { is_expected.to be_kind_of(Chouette::ObjectId) }
+ it { is_expected.to be_kind_of(Chouette::StifNetexObjectid) }
end
it { is_expected.to validate_presence_of :name }
diff --git a/spec/models/chouette/footnote_spec.rb b/spec/models/chouette/footnote_spec.rb
index 98d751499..fc5e5f306 100644
--- a/spec/models/chouette/footnote_spec.rb
+++ b/spec/models/chouette/footnote_spec.rb
@@ -2,9 +2,21 @@ require 'spec_helper'
describe Chouette::Footnote, type: :model do
let(:footnote) { create(:footnote) }
-
it { should validate_presence_of :line }
+ describe 'data_source_ref' do
+ it 'should set default if omitted' do
+ expect(footnote.data_source_ref).to eq "DATASOURCEREF_EDITION_BOIV"
+ end
+
+ it 'should not set default if not omitted' do
+ source = "RANDOM_DATASOURCE"
+ object = build(:footnote, data_source_ref: source)
+ object.save
+ expect(object.data_source_ref).to eq source
+ end
+ end
+
describe 'checksum' do
it_behaves_like 'checksum support', :footnote
diff --git a/spec/models/chouette/group_of_line_spec.rb b/spec/models/chouette/group_of_line_spec.rb
index d49329118..29b4433c5 100644
--- a/spec/models/chouette/group_of_line_spec.rb
+++ b/spec/models/chouette/group_of_line_spec.rb
@@ -3,11 +3,7 @@ require 'spec_helper'
describe Chouette::GroupOfLine, :type => :model do
subject { create(:group_of_line) }
-
- it { is_expected.to validate_presence_of :name }
-
- # it { should validate_presence_of :objectid }
- it { is_expected.to validate_uniqueness_of :objectid }
+ it { should validate_presence_of :name }
describe "#stop_areas" do
let!(:line){create(:line, :group_of_lines => [subject])}
diff --git a/spec/models/chouette/network_spec.rb b/spec/models/chouette/network_spec.rb
index c9e510e84..32bacc512 100644
--- a/spec/models/chouette/network_spec.rb
+++ b/spec/models/chouette/network_spec.rb
@@ -1,13 +1,8 @@
require 'spec_helper'
describe Chouette::Network, :type => :model do
-
subject { create(:network) }
-
- it { is_expected.to validate_presence_of :name }
-
- # it { should validate_presence_of :objectid }
- it { is_expected.to validate_uniqueness_of :objectid }
+ it { should validate_presence_of :name }
describe "#stop_areas" do
let!(:line){create(:line, :network => subject)}
diff --git a/spec/models/chouette/route/route_base_spec.rb b/spec/models/chouette/route/route_base_spec.rb
index c93b311ff..794da4f1b 100644
--- a/spec/models/chouette/route/route_base_spec.rb
+++ b/spec/models/chouette/route/route_base_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Chouette::Route, :type => :model do
describe '#objectid' do
subject { super().objectid }
- it { is_expected.to be_kind_of(Chouette::ObjectId) }
+ it { is_expected.to be_kind_of(Chouette::StifNetexObjectid) }
end
it { is_expected.to enumerize(:direction).in(:straight_forward, :backward, :clockwise, :counter_clockwise, :north, :north_west, :west, :south_west, :south, :south_east, :east, :north_east) }
diff --git a/spec/models/chouette/routing_constraint_zone_spec.rb b/spec/models/chouette/routing_constraint_zone_spec.rb
index 054cfb9e6..c344642e6 100644
--- a/spec/models/chouette/routing_constraint_zone_spec.rb
+++ b/spec/models/chouette/routing_constraint_zone_spec.rb
@@ -3,7 +3,6 @@ require 'spec_helper'
describe Chouette::RoutingConstraintZone, type: :model do
subject { create(:routing_constraint_zone) }
- let!(:routing_constraint_zone) { create(:routing_constraint_zone) }
it { is_expected.to validate_presence_of :name }
# shoulda matcher to validate length of array ?
@@ -16,38 +15,38 @@ describe Chouette::RoutingConstraintZone, type: :model do
describe 'validations' do
it 'validates the presence of route_id' do
expect {
- routing_constraint_zone.update!(route_id: nil)
+ subject.update!(route_id: nil)
}.to raise_error(NoMethodError)
end
it 'validates the presence of stop_point_ids' do
expect {
- routing_constraint_zone.update!(stop_point_ids: [])
+ subject.update!(stop_point_ids: [])
}.to raise_error(ActiveRecord::RecordInvalid)
end
it 'validates that stop points belong to the route' do
route = create(:route)
expect {
- routing_constraint_zone.update!(route_id: route.id)
+ subject.update!(route_id: route.id)
}.to raise_error(ActiveRecord::RecordInvalid)
end
xit 'validates that not all stop points from the route are selected' do
routing_constraint_zone.stop_points = routing_constraint_zone.route.stop_points
expect {
- routing_constraint_zone.save!
+ subject.save!
}.to raise_error(ActiveRecord::RecordInvalid)
end
end
describe 'deleted stop areas' do
it 'does not have them in stop_area_ids' do
- stop_point = routing_constraint_zone.route.stop_points.last
- routing_constraint_zone.stop_points << stop_point
- routing_constraint_zone.save!
- routing_constraint_zone.route.stop_points.last.destroy!
- expect(routing_constraint_zone.stop_points.map(&:id)).not_to include(stop_point.id)
+ stop_point = subject.route.stop_points.last
+ subject.stop_points << stop_point
+ subject.save!
+ subject.route.stop_points.last.destroy!
+ expect(subject.stop_points.map(&:id)).not_to include(stop_point.id)
end
end
diff --git a/spec/models/chouette/stop_point_spec.rb b/spec/models/chouette/stop_point_spec.rb
index d0314b8db..1be000b56 100644
--- a/spec/models/chouette/stop_point_spec.rb
+++ b/spec/models/chouette/stop_point_spec.rb
@@ -10,7 +10,7 @@ describe StopPoint, :type => :model do
describe '#objectid' do
subject { super().objectid }
- it { is_expected.to be_kind_of(Chouette::ObjectId) }
+ it { is_expected.to be_kind_of(Chouette::StifNetexObjectid) }
end
describe "#destroy" do
diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb
index c4eaeaaf0..761c39e5b 100644
--- a/spec/models/chouette/time_table_spec.rb
+++ b/spec/models/chouette/time_table_spec.rb
@@ -820,13 +820,13 @@ end
describe "#intersects" do
it "should return day if a date equal day" do
- time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1")
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc")
time_table.dates << Chouette::TimeTableDate.new( :date => Date.today, :in_out => true)
expect(time_table.intersects([Date.today])).to eq([Date.today])
end
it "should return [] if a period not include days" do
- time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1", :int_day_types => 12)
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 12)
time_table.periods << Chouette::TimeTablePeriod.new(
:period_start => Date.new(2013, 05, 27),
:period_end => Date.new(2013, 05, 30))
@@ -834,7 +834,7 @@ end
end
it "should return days if a period include day" do
- time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1", :int_day_types => 12) # Day type monday and tuesday
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 12) # Day type monday and tuesday
time_table.periods << Chouette::TimeTablePeriod.new(
:period_start => Date.new(2013, 05, 27),
:period_end => Date.new(2013, 05, 30))
@@ -842,6 +842,207 @@ end
end
end
+ describe "#include_day?" do
+ it "should return true if a date equal day" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc")
+ time_table.dates << Chouette::TimeTableDate.new( :date => Date.today, :in_out => true)
+ expect(time_table.include_day?(Date.today)).to eq(true)
+ end
+
+ it "should return true if a period include day" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 12) # Day type monday and tuesday
+ time_table.periods << Chouette::TimeTablePeriod.new(
+ :period_start => Date.new(2013, 05, 27),
+ :period_end => Date.new(2013, 05, 29))
+ expect(time_table.include_day?( Date.new(2013, 05, 27))).to eq(true)
+ end
+ end
+
+ describe "#include_in_dates?" do
+ it "should return true if a date equal day" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc")
+ time_table.dates << Chouette::TimeTableDate.new( :date => Date.today, :in_out => true)
+ expect(time_table.include_in_dates?(Date.today)).to eq(true)
+ end
+
+ it "should return false if a period include day but that is exclued" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 12) # Day type monday and tuesday
+ excluded_date = Date.new(2013, 05, 27)
+ time_table.dates << Chouette::TimeTableDate.new( :date => excluded_date, :in_out => false)
+ expect(time_table.include_in_dates?( excluded_date)).to be_falsey
+ end
+ end
+
+ describe "#include_in_periods?" do
+ it "should return true if a period include day" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 4)
+ time_table.periods << Chouette::TimeTablePeriod.new(
+ :period_start => Date.new(2012, 1, 1),
+ :period_end => Date.new(2012, 01, 30))
+ expect(time_table.include_in_periods?(Date.new(2012, 1, 2))).to eq(true)
+ end
+
+ it "should return false if a period include day but that is exclued" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 12) # Day type monday and tuesday
+ excluded_date = Date.new(2013, 05, 27)
+ time_table.dates << Chouette::TimeTableDate.new( :date => excluded_date, :in_out => false)
+ time_table.periods << Chouette::TimeTablePeriod.new(
+ :period_start => Date.new(2013, 05, 27),
+ :period_end => Date.new(2013, 05, 29))
+ expect(time_table.include_in_periods?( excluded_date)).to be_falsey
+ end
+ end
+
+ describe "#include_in_overlap_dates?" do
+ it "should return true if a day is included in overlap dates" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 4)
+ time_table.periods << Chouette::TimeTablePeriod.new(
+ :period_start => Date.new(2012, 1, 1),
+ :period_end => Date.new(2012, 01, 30))
+ time_table.dates << Chouette::TimeTableDate.new( :date => Date.new(2012, 1, 2), :in_out => true)
+ expect(time_table.include_in_overlap_dates?(Date.new(2012, 1, 2))).to eq(true)
+ end
+ it "should return false if the day is excluded" do
+ time_table = Chouette::TimeTable.create!(:comment => "Test", :objectid => "test:Timetable:1:loc", :int_day_types => 4)
+ time_table.periods << Chouette::TimeTablePeriod.new(
+ :period_start => Date.new(2012, 1, 1),
+ :period_end => Date.new(2012, 01, 30))
+ time_table.dates << Chouette::TimeTableDate.new( :date => Date.new(2012, 1, 2), :in_out => false)
+ expect(time_table.include_in_overlap_dates?(Date.new(2012, 1, 2))).to be_falsey
+ end
+ end
+
+ describe "#dates" do
+ it "should have with position 0" do
+ expect(subject.dates.first.position).to eq(0)
+ end
+ context "when first date has been removed" do
+ before do
+ subject.dates.first.destroy
+ end
+ it "should begin with position 0" do
+ expect(subject.dates.first.position).to eq(0)
+ end
+ end
+ end
+ describe "#validity_out_between?" do
+ let(:empty_tm) {build(:time_table)}
+ it "should be false if empty calendar" do
+ expect(empty_tm.validity_out_between?( Date.today, Date.today + 7.day)).to be_falsey
+ end
+ it "should be true if caldendar is out during start_date and end_date period" do
+ start_date = subject.bounding_dates.max - 2.day
+ end_date = subject.bounding_dates.max + 2.day
+ expect(subject.validity_out_between?( start_date, end_date)).to be_truthy
+ end
+ it "should be false if calendar is out on start date" do
+ start_date = subject.bounding_dates.max
+ end_date = subject.bounding_dates.max + 2.day
+ expect(subject.validity_out_between?( start_date, end_date)).to be_falsey
+ end
+ it "should be false if calendar is out on end date" do
+ start_date = subject.bounding_dates.max - 2.day
+ end_date = subject.bounding_dates.max
+ expect(subject.validity_out_between?( start_date, end_date)).to be_truthy
+ end
+ it "should be false if calendar is out after start_date" do
+ start_date = subject.bounding_dates.max + 2.day
+ end_date = subject.bounding_dates.max + 4.day
+ expect(subject.validity_out_between?( start_date, end_date)).to be_falsey
+ end
+ end
+ describe "#validity_out_from_on?" do
+ let(:empty_tm) {build(:time_table)}
+ it "should be false if empty calendar" do
+ expect(empty_tm.validity_out_from_on?( Date.today)).to be_falsey
+ end
+ it "should be true if caldendar ends on expected date" do
+ expected_date = subject.bounding_dates.max
+ expect(subject.validity_out_from_on?( expected_date)).to be_truthy
+ end
+ it "should be true if calendar ends before expected date" do
+ expected_date = subject.bounding_dates.max + 30.day
+ expect(subject.validity_out_from_on?( expected_date)).to be_truthy
+ end
+ it "should be false if calendars ends after expected date" do
+ expected_date = subject.bounding_dates.max - 30.day
+ expect(subject.validity_out_from_on?( expected_date)).to be_falsey
+ end
+ end
+ describe "#bounding_dates" do
+ context "when timetable contains only periods" do
+ before do
+ subject.dates = []
+ subject.save
+ end
+ it "should retreive periods.period_start.min and periods.period_end.max" do
+ expect(subject.bounding_dates.min).to eq(subject.periods.map(&:period_start).min)
+ expect(subject.bounding_dates.max).to eq(subject.periods.map(&:period_end).max)
+ end
+ end
+ context "when timetable contains only dates" do
+ before do
+ subject.periods = []
+ subject.save
+ end
+ it "should retreive dates.min and dates.max" do
+ expect(subject.bounding_dates.min).to eq(subject.dates.map(&:date).min)
+ expect(subject.bounding_dates.max).to eq(subject.dates.map(&:date).max)
+ end
+ end
+ it "should contains min date" do
+ min_date = subject.bounding_dates.min
+ subject.dates.each do |tm_date|
+ expect(min_date <= tm_date.date).to be_truthy
+ end
+ subject.periods.each do |tm_period|
+ expect(min_date <= tm_period.period_start).to be_truthy
+ end
+
+ end
+ it "should contains max date" do
+ max_date = subject.bounding_dates.max
+ subject.dates.each do |tm_date|
+ expect(tm_date.date <= max_date).to be_truthy
+ end
+ subject.periods.each do |tm_period|
+ expect(tm_period.period_end <= max_date).to be_truthy
+ end
+
+ end
+ end
+ describe "#periods" do
+ it "should begin with position 0" do
+ expect(subject.periods.first.position).to eq(0)
+ end
+ context "when first period has been removed" do
+ before do
+ subject.periods.first.destroy
+ end
+ it "should begin with position 0" do
+ expect(subject.periods.first.position).to eq(0)
+ end
+ end
+ it "should have period_start before period_end" do
+ period = Chouette::TimeTablePeriod.new
+ period.period_start = Date.today
+ period.period_end = Date.today + 10
+ expect(period.valid?).to be_truthy
+ end
+ it "should not have period_start after period_end" do
+ period = Chouette::TimeTablePeriod.new
+ period.period_start = Date.today
+ period.period_end = Date.today - 10
+ expect(period.valid?).to be_falsey
+ end
+ it "should not have period_start equal to period_end" do
+ period = Chouette::TimeTablePeriod.new
+ period.period_start = Date.today
+ period.period_end = Date.today
+ expect(period.valid?).to be_falsey
+ end
+ end
+
# it { is_expected.to validate_presence_of :comment }
# it { is_expected.to validate_uniqueness_of :objectid }
@@ -964,7 +1165,6 @@ end
target=subject.duplicate
expect(target.id).to be_nil
expect(target.comment).to eq(I18n.t("activerecord.copy", name: subject.comment))
- expect(target.objectid).to eq(subject.objectid+"_1")
expect(target.int_day_types).to eq(subject.int_day_types)
expect(target.dates.size).to eq(subject.dates.size)
target.dates.each do |d|
diff --git a/spec/models/chouette/trident_active_record_spec.rb b/spec/models/chouette/trident_active_record_spec.rb
index 76544f85d..d5e30594d 100644
--- a/spec/models/chouette/trident_active_record_spec.rb
+++ b/spec/models/chouette/trident_active_record_spec.rb
@@ -1,119 +1,57 @@
require 'spec_helper'
describe Chouette::TridentActiveRecord, :type => :model do
-
- it { expect(Chouette::TridentActiveRecord.ancestors).to include(Chouette::ActiveRecord) }
-
subject { create(:time_table) }
- describe "#uniq_objectid" do
+ it { should validate_presence_of :objectid }
+ it { should validate_uniqueness_of :objectid }
- it "should rebuild objectid" do
- tm = create(:time_table)
- tm.objectid = subject.objectid
- tm.uniq_objectid
- expect(tm.objectid).to eq(subject.objectid+"_1")
- end
+ describe "#default_values" do
+ let(:object) { build(:time_table, objectid: nil) }
- it "should rebuild objectid" do
- tm = create(:time_table)
- tm.objectid = subject.objectid
- tm.uniq_objectid
- tm.save
- tm = create(:time_table)
- tm.objectid = subject.objectid
- tm.uniq_objectid
- expect(tm.objectid).to eq(subject.objectid+"_2")
+ it 'should fill __pending_id__' do
+ object.default_values
+ expect(object.objectid.include?('__pending_id__')).to be_truthy
end
-
end
- def create_object(options = {})
- options = {name: "merge1"}.merge options
- attributes = { comment: options[:name], objectid: options[:objectid] }
- Chouette::TimeTable.new attributes
- end
-
- describe "#prepare_auto_columns" do
-
- it "should left objectid" do
- tm = create_object :objectid => "first:Timetable:merge1"
- tm.prepare_auto_columns
- expect(tm.objectid).to eq("first:Timetable:merge1")
- end
-
- it "should add pending_id to objectid" do
- tm = create_object
- tm.prepare_auto_columns
- expect(tm.objectid.start_with?("first:Timetable:__pending_id__")).to be_truthy
- end
-
- it "should set id to objectid" do
- tm = create_object
- tm.save
- expect(tm.objectid).to eq("first:Timetable:"+tm.id.to_s)
- end
+ describe "#objectid" do
+ let(:object) { build(:time_table, objectid: nil) }
- it "should detect objectid conflicts" do
- tm = create_object
- tm.save
- tm.objectid = "first:Timetable:"+(tm.id+1).to_s
- tm.save
- tm = create_object
- tm.save
- expect(tm.objectid).to eq("first:Timetable:"+tm.id.to_s+"_1")
+ it 'should build objectid on create' do
+ object.save
+ id = "#{object.provider_id}:#{object.model_name}:#{object.local_id}:#{object.boiv_id}"
+ expect(object.objectid).to eq(id)
end
- end
-
- describe "objectid" do
-
- it "should build automatic objectid when empty" do
- g1 = create_object
- g1.save
- expect(g1.objectid).to eq("first:Timetable:"+g1.id.to_s)
+ it 'should call build_objectid on after save' do
+ expect(object).to receive(:build_objectid)
+ object.save
end
- it "should build automatic objectid with fixed when only suffix given" do
- g1 = create_object
- g1.objectid = "toto"
- g1.save
- expect(g1.objectid).to eq("first:Timetable:toto")
+ it 'should not build new objectid is already set' do
+ id = "first:TimeTable:1-1:LOC"
+ object.objectid = id
+ object.save
+ expect(object.objectid).to eq(id)
end
- it "should build automatic objectid with extension when already exists" do
- g1 = create_object
- g1.save
- cnt = g1.id + 1
- g1.objectid = "first:Timetable:"+cnt.to_s
- g1.save
- g2 = create_object
- g2.save
- expect(g2.objectid).to eq("first:Timetable:"+g2.id.to_s+"_1")
+ it 'should call default_values on create' do
+ expect(object).to receive(:default_values)
+ object.save
end
- it "should build automatic objectid with extension when already exists" do
- g1 = create_object
- g1.save
- cnt = g1.id + 2
- g1.objectid = "first:Timetable:"+cnt.to_s
- g1.save
- g2 = create_object
- g2.objectid = "first:Timetable:"+cnt.to_s+"_1"
- g2.save
- g3 = create_object
- g3.save
- expect(g3.objectid).to eq("first:Timetable:"+g3.id.to_s+"_2")
+ it 'should not call default_values on update' do
+ object = create(:time_table)
+ expect(object).to_not receive(:default_values)
+ object.touch
end
- it "should build automatic objectid when id cleared" do
- g1 = create_object
- g1.objectid = "first:Timetable:xxxx"
- g1.save
- g1.objectid = nil
- g1.save
- expect(g1.objectid).to eq("first:Timetable:"+g1.id.to_s)
+ it 'should create a new objectid when cleared' do
+ object.save
+ object.objectid = nil
+ object.save
+ expect(object.objectid).to be_truthy
end
end
-
end
diff --git a/spec/models/compliance_check_result_spec.rb b/spec/models/compliance_check_result_spec.rb
deleted file mode 100644
index 42a2e4507..000000000
--- a/spec/models/compliance_check_result_spec.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-# require 'spec_helper'
-
-# describe ComplianceCheckResult, :type => :model do
-
-# subject { Factory( :compliance_check_result)}
-
-# describe "#indice" do
-# context "when 1-NEPTUNE-XML-1 result" do
-# before(:each) do
-# subject.rule_code = "1-NEPTUNE-XML-1"
-# end
-
-# describe '#indice' do
-# subject { super().indice }
-# it { is_expected.to eq(1) }
-# end
-# end
-# context "when 2-NETEX-AccessLink-2 result" do
-# before(:each) do
-# subject.rule_code = "2-NETEX-AccessLink-2"
-# end
-
-# describe '#indice' do
-# subject { super().indice }
-# it { is_expected.to eq(2) }
-# end
-# end
-# end
-
-# describe "#data_type" do
-# context "when 1-NEPTUNE-XML-1 result" do
-# before(:each) do
-# subject.rule_code = "1-NEPTUNE-XML-1"
-# end
-
-# describe '#data_type' do
-# subject { super().data_type }
-# it { is_expected.to eq("XML") }
-# end
-# end
-# context "when 2-NETEX-AccessLink-2 result" do
-# before(:each) do
-# subject.rule_code = "2-NETEX-AccessLink-2"
-# end
-
-# describe '#data_type' do
-# subject { super().data_type }
-# it { is_expected.to eq("AccessLink") }
-# end
-# end
-# end
-
-# describe "#format" do
-# context "when 1-NEPTUNE-XML-1 result" do
-# before(:each) do
-# subject.rule_code = "1-NEPTUNE-XML-1"
-# end
-
-# describe '#format' do
-# subject { super().format }
-# it { is_expected.to eq("NEPTUNE") }
-# end
-# end
-# context "when 2-NETEX-AccessLink-2 result" do
-# before(:each) do
-# subject.rule_code = "2-NETEX-AccessLink-2"
-# end
-
-# describe '#format' do
-# subject { super().format }
-# it { is_expected.to eq("NETEX") }
-# end
-# end
-# end
-
-# describe "#level" do
-# context "when 1-NEPTUNE-XML-1 result" do
-# before(:each) do
-# subject.rule_code = "1-NEPTUNE-XML-1"
-# end
-
-# describe '#level' do
-# subject { super().level }
-# it { is_expected.to eq(1) }
-# end
-# end
-# context "when 2-NEPTUNE-AccessLink-2 result" do
-# before(:each) do
-# subject.rule_code = "2-NEPTUNE-AccessLink-2"
-# end
-
-# describe '#level' do
-# subject { super().level }
-# it { is_expected.to eq(2) }
-# end
-# end
-# end
-
-# end
-
diff --git a/spec/models/compliance_check_task_spec.rb b/spec/models/compliance_check_task_spec.rb
deleted file mode 100644
index a062fdb58..000000000
--- a/spec/models/compliance_check_task_spec.rb
+++ /dev/null
@@ -1,317 +0,0 @@
-# require 'spec_helper'
-
-# TODO: Can we get rid of this???
-# *************************
-
-# describe ComplianceCheckTask, :type => :model do
-
-# subject { Factory( :compliance_check_task ) }
-
-# RSpec::Matchers.define :be_log_message do |expected|
-# match do |actual|
-# actual and expected.all? { |k,v| actual[k.to_s] == v }
-# end
-# end
-
-
-# describe "#any_error_severity_failure?" do
-# context "when compliance_check_results empty" do
-# before(:each) do
-# subject.compliance_check_results = []
-# end
-# it "does return false" do
-# expect(subject.any_error_severity_failure?).to be_falsey
-# end
-# end
-# context "when compliance_check_results contains a error_severity_failure" do
-# let( :valid_result){ Factory.build( :compliance_check_result) }
-# let( :invalid_result){ Factory.build( :compliance_check_result, :severity => "error", :status => "nok") }
-# before(:each) do
-# subject.compliance_check_results = [ valid_result, invalid_result]
-# end
-# it "does return true" do
-# expect(subject.any_error_severity_failure?).to be_truthy
-# end
-# end
-# context "when compliance_check_results contains no error_severity_failure" do
-# let( :valid_result){ Factory.build( :compliance_check_result) }
-# before(:each) do
-# subject.compliance_check_results = [ valid_result]
-# end
-# it "does return false" do
-# expect(subject.any_error_severity_failure?).to be_falsey
-# end
-# end
-# end
-
-# describe "#destroy" do
-# let(:import_task){ Factory( :import_task )}
-# context "with an import_task" do
-# before(:each) do
-# subject.import_task = import_task
-# end
-# it "should destroy import_task" do
-# subject.destroy
-# expect(ImportTask.exists?( import_task.id)).to be_falsey
-# end
-# end
-# context "without any import_task" do
-# before(:each) do
-# subject.import_task = nil
-# end
-# it "should not raise exception" do
-# subject.destroy
-# expect(subject).to be_destroyed
-# end
-# end
-# end
-
-# describe "#levels" do
-# let(:import_task){ Factory( :import_task )}
-# context "when validation is without import" do
-# it "should not return levels 1 and 2" do
-# expect(subject.levels.include?(1)).to be_falsey
-# expect(subject.levels.include?(2)).to be_falsey
-# end
-# context "when parameter_set is defined" do
-# before(:each) do
-# subject.parameter_set = "dummy"
-# end
-# it "should return level 3" do
-# expect(subject.levels.include?(3)).to be_truthy
-# end
-# end
-# context "when parameter_set is not defined" do
-# before(:each) do
-# subject.parameter_set = nil
-# end
-# it "should not return level 3" do
-# expect(subject.levels.include?(3)).not_to be_truthy
-# end
-# end
-# end
-# context "when validation is done with an import" do
-# before(:each) do
-# subject.import_task = import_task
-# end
-# it "should return levels 1 and 2" do
-# expect(subject.levels.include?(1)).to be_truthy
-# expect(subject.levels.include?(2)).to be_truthy
-# end
-# context "when parameter_set is defined" do
-# before(:each) do
-# subject.parameter_set = "dummy"
-# end
-# it "should return level 3" do
-# expect(subject.levels.include?(3)).to be_truthy
-# end
-# end
-# context "when parameter_set is not defined" do
-# before(:each) do
-# subject.parameter_set = nil
-# end
-# it "should not return level 3" do
-# expect(subject.levels.include?(3)).not_to be_truthy
-# end
-# end
-# end
-
-# end
-
-# describe "#chouette_command" do
-# it "should be a Chouette::Command instance" do
-# expect(subject.send( :chouette_command).class).to eq(Chouette::Command)
-# end
-# it "should have schema same as referential.slug" do
-# expect(subject.send( :chouette_command).schema).to eq(subject.referential.slug)
-# end
-# end
-
-# describe "#validate" do
-# let(:compliance_check_task){ Factory(:compliance_check_task) }
-# let(:chouette_command) { "dummy" }
-# context "for failing validation" do
-# before(:each) do
-# allow(chouette_command).to receive( :run!).and_raise( "dummy")
-# allow(compliance_check_task).to receive_messages( :chouette_command => chouette_command)
-# end
-# it "should have status 'failed'" do
-# compliance_check_task.validate
-# expect(compliance_check_task.status).to eq("failed")
-# end
-# end
-# context "for successful validation" do
-# before(:each) do
-# allow(compliance_check_task).to receive_messages( :chouette_command => double( :run! => true ))
-# end
-# it "should have status 'completed'" do
-# compliance_check_task.validate
-# expect(compliance_check_task.status).to eq("completed")
-# end
-# end
-# end
-
-# describe "#validate" do
-# let(:compliance_check_task){ Factory(:compliance_check_task) }
-# let(:command_args){ "dummy" }
-# before(:each) do
-# allow(compliance_check_task).to receive_messages( :chouette_command => double( :run! => true ))
-# allow(compliance_check_task).to receive_messages( :chouette_command_args => command_args)
-# end
-# it "should call chouette_command.run! with :c => 'import', :id => id" do
-# expect(compliance_check_task.send( :chouette_command)).to receive( :run! ).with( command_args)
-# compliance_check_task.validate
-# end
-# end
-
-# describe "#delayed_validate" do
-# let( :import_task){ Factory.build(:import_task) }
-# before(:each) do
-# allow(subject).to receive_messages( :delay => double( :validate => true))
-# end
-# it "should not call delay#validate if import_task defined" do
-# subject.import_task = import_task
-# expect(subject.delay).not_to receive( :validate)
-# subject.delayed_validate
-# end
-# it "should call delay#validate if import_task blank" do
-# subject.import_task = nil
-# expect(subject.delay).to receive( :validate)
-# subject.delayed_validate
-# end
-
-# end
-
-# describe "#define_default_attributes" do
-# it "should keep status if defined" do
-# subject.status = "dummy"
-# subject.define_default_attributes
-# expect(subject.status).to eq("dummy")
-# end
-# it "should set status to pending if not defined" do
-# subject.status = nil
-# subject.define_default_attributes
-# expect(subject.status).to eq("pending")
-# end
-# context "when rule_parameter_set is nil" do
-# before(:each) do
-# allow(subject).to receive_messages( :rule_parameter_set => nil)
-# subject.parameter_set = "dummy"
-# subject.parameter_set_name = "dummy"
-# end
-# it "should keep parameter_set_name" do
-# subject.define_default_attributes
-# expect(subject.parameter_set_name).to eq("dummy")
-# end
-# it "should keep parameter_set" do
-# subject.define_default_attributes
-# expect(subject.parameter_set).to eq("dummy")
-# end
-# end
-# context "when rule_parameter_set is defined" do
-# let( :rule_parameter_set ){ Factory( :rule_parameter_set ) }
-# before(:each) do
-# allow(subject).to receive_messages( :rule_parameter_set => rule_parameter_set)
-# subject.parameter_set = "dummy"
-# subject.parameter_set_name = "dummy"
-# end
-# it "should set parameter_set_name to rule_parameter_set.name" do
-# subject.define_default_attributes
-# expect(subject.parameter_set_name).to eq(rule_parameter_set.name)
-# end
-# it "should keep set parameter_set to rule_parameter_set.parameters" do
-# subject.define_default_attributes
-# expect(subject.parameter_set).to eq(rule_parameter_set.parameters)
-# end
-# end
-# end
-
-# describe "#rule_parameter_set" do
-# context "when rule_parameter_set_id is blank" do
-# before(:each) do
-# subject.rule_parameter_set_id = ""
-# end
-# it "should return nil" do
-# expect(subject.rule_parameter_set).to be_nil
-# end
-# end
-# context "when rule_parameter_set_id is not blank" do
-# let( :rule_parameter_set ){ Factory( :rule_parameter_set ) }
-# before(:each) do
-# subject.rule_parameter_set_id = rule_parameter_set.id
-# end
-# it "should return rule_parameter_set instance" do
-# expect(subject.rule_parameter_set).to eq(rule_parameter_set)
-# end
-# end
-# end
-
-# describe "#rule_parameter_set_archived" do
-# context "when parameter_set is blank" do
-# before(:each) do
-# subject.parameter_set = nil
-# end
-# it "should return nil" do
-# expect(subject.rule_parameter_set_archived).to be_nil
-# end
-# end
-# context "when parameter_set is blank" do
-# before(:each) do
-# subject.parameter_set = { :speed => 30, :distance => 5 }
-# end
-# it "should return RuleParameterSet#parameters same as parameter_set" do
-# expect(subject.rule_parameter_set_archived.parameters).to eq(subject.parameter_set)
-# end
-# it "should return RuleParameterSet#name same as parameter_set_name" do
-# expect(subject.rule_parameter_set_archived.name).to eq(subject.parameter_set_name)
-# end
-# end
-
-# end
-
-# # describe "#validate" do
-# #
-# # before(:each) do
-# # subject.stub :validator => mock(:validate => true)
-# # end
-# #
-# # it "should create a ComplianceCheckResult :started when started" do
-# # subject.validate
- # expect(subject.compliance_check_results.first).to be_log_message(:key => "started")
-# # end
-# #
-# # it "should create a ComplianceCheckResult :completed when completed" do
-# # subject.validate
- # expect(subject.compliance_check_results.last).to be_log_message(:key => "completed")
-# # end
-# #
-# # it "should create a ComplianceCheckResult :failed when failed" do
-# # pending
-# # # subject.loader.stub(:export).and_raise("export failed")
-# # subject.validate
- # expect(subject.compliance_check_results.last).to be_log_message(:key => "failed")
-# # end
-# #
-# # end
-
-# describe ".create" do
-# let( :new_compliance_check_task){ Factory.build( :compliance_check_task) }
-
-# it "should call #define_default_attributes" do
-# expect(new_compliance_check_task).to receive( :define_default_attributes)
-# new_compliance_check_task.save
-# end
-
-# it "should call #delayed_validate" do
-# expect(new_compliance_check_task).not_to receive( :delayed_validate)
-# new_compliance_check_task.save
-# end
-
-# end
-
-# it_behaves_like TypeIdsModelable do
-# let(:type_ids_model) { subject}
-# end
-
-# end
-
diff --git a/spec/models/concerns/error_format_spec.rb b/spec/models/concerns/error_format_spec.rb
new file mode 100644
index 000000000..f82aecf44
--- /dev/null
+++ b/spec/models/concerns/error_format_spec.rb
@@ -0,0 +1,41 @@
+RSpec.describe ErrorFormat do
+
+ context '#details' do
+ context 'are empty' do
+ it 'if no errors are present' do
+ expect(
+ described_class.details(build_stubbed(:referential))
+ ).to be_empty
+ end
+
+ it 'if no validation has been carried out' do
+ invalid = build_stubbed(:referential, name: nil)
+ expect( described_class.details(invalid) ).to be_empty
+ end
+ end
+
+ context 'are not empty' do
+ it 'if an error is present and validation has been carried out' do
+ invalid = build_stubbed(:referential, name: nil)
+ expect( invalid ).not_to be_valid
+ expect( described_class.details(invalid) ).to eq({
+ name: { error: 'doit être rempli(e)', value: nil }
+ })
+ end
+
+ it 'and can even hold many errors' do
+ create(:referential, name: 'hello')
+ invalid = build_stubbed(
+ :referential,
+ name: '',
+ slug: 'hello world'
+ )
+ expect( invalid ).not_to be_valid
+ expect( described_class.details(invalid) ).to eq({
+ name: { error: "doit être rempli(e)", value: '' },
+ slug: { error: "n'est pas valide", value: 'hello world' }
+ })
+ end
+ end
+ end
+end
diff --git a/spec/models/import_resource_spec.rb b/spec/models/import_resource_spec.rb
index 99d260b20..c88bb5dd2 100644
--- a/spec/models/import_resource_spec.rb
+++ b/spec/models/import_resource_spec.rb
@@ -3,17 +3,17 @@ require 'rails_helper'
RSpec.describe ImportResource, :type => :model do
it { should belong_to(:import) }
- it { should enumerize(:status).in(:new, :pending, :successful, :failed) }
+ it { should enumerize(:status).in("OK", "ERROR", "WARNING", "IGNORED") }
it { should validate_presence_of(:name) }
- it { should validate_presence_of(:type) }
+ it { should validate_presence_of(:resource_type) }
it { should validate_presence_of(:reference) }
describe 'states' do
let(:import_resource) { create(:import_resource) }
it 'should initialize with new state' do
- expect(import_resource.new?).to be_truthy
+ expect(import_resource.status).to eq("WARNING")
end
end
end
diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb
index 164769fd5..cd5a30982 100644
--- a/spec/models/import_spec.rb
+++ b/spec/models/import_spec.rb
@@ -1,14 +1,14 @@
-RSpec.describe Import, :type => :model do
+RSpec.describe Import, type: :model do
it { should belong_to(:referential) }
it { should belong_to(:workbench) }
it { should belong_to(:parent) }
- it { should enumerize(:status).in("aborted", "canceled", "failed", "new", "pending", "running", "successful") }
+ it { should enumerize(:status).in("aborted", "canceled", "failed", "new", "pending", "running", "successful", "warning") }
it { should validate_presence_of(:file) }
- it { should validate_presence_of(:referential) }
it { should validate_presence_of(:workbench) }
+ it { should validate_presence_of(:creator) }
let(:workbench_import) { build_stubbed(:workbench_import) }
let(:workbench_import_with_completed_steps) do
@@ -26,11 +26,41 @@ RSpec.describe Import, :type => :model do
)
end
+ describe "#destroy" do
+ it "must destroy all child imports" do
+ workbench_import = create(:workbench_import)
+ create(:netex_import, parent: workbench_import)
+
+ workbench_import.destroy
+
+ expect(workbench_import).to be_destroyed
+ expect(NetexImport.count).to eq(0)
+ end
+
+ it "must destroy all associated ImportMessages" do
+ import = create(:import)
+ create(:import_resource, import: import)
+
+ import.destroy
+
+ expect(ImportResource.count).to eq(0)
+ end
+
+ it "must destroy all associated ImportResources" do
+ import = create(:import)
+ create(:import_message, import: import)
+
+ import.destroy
+
+ expect(ImportMessage.count).to eq(0)
+ end
+ end
+
describe "#notify_parent" do
it "must call #child_change on its parent" do
allow(netex_import).to receive(:update)
- expect(workbench_import).to receive(:child_change).with(netex_import)
+ expect(workbench_import).to receive(:child_change)
netex_import.notify_parent
end
@@ -49,110 +79,142 @@ RSpec.describe Import, :type => :model do
end
describe "#child_change" do
+ it "calls #update_status" do
+ allow(workbench_import).to receive(:update)
+
+ expect(workbench_import).to receive(:update_status)
+ workbench_import.child_change
+ end
+
+ it "calls #update_referentials" do
+ allow(workbench_import).to receive(:update)
+
+ expect(workbench_import).to receive(:update_referentials)
+ workbench_import.child_change
+ end
+ end
+
+ describe "#update_status" do
shared_examples(
- "updates :status to failed when child status indicates failure"
+ "updates :status to failed when >=1 child has failing status"
) do |failure_status|
- it "updates :status to failed when child status indicates failure" do
- allow(workbench_import).to receive(:update)
-
- netex_import = build_stubbed(
+ it "updates :status to failed when >=1 child has failing status" do
+ workbench_import = create(:workbench_import)
+ create(
:netex_import,
parent: workbench_import,
status: failure_status
)
- expect(workbench_import).to receive(:update).with(status: 'failed')
+ workbench_import.update_status
- workbench_import.child_change(netex_import)
+ expect(workbench_import.status).to eq('failed')
end
end
include_examples(
- "updates :status to failed when child status indicates failure",
+ "updates :status to failed when >=1 child has failing status",
"failed"
)
include_examples(
- "updates :status to failed when child status indicates failure",
+ "updates :status to failed when >=1 child has failing status",
"aborted"
)
include_examples(
- "updates :status to failed when child status indicates failure",
+ "updates :status to failed when >=1 child has failing status",
"canceled"
)
- it "updates :status to successful when #ready?" do
- expect(workbench_import).to receive(:update).with(status: 'successful')
+ it "updates :status to successful when all children are successful" do
+ workbench_import = create(:workbench_import)
+ create_list(
+ :netex_import,
+ 2,
+ parent: workbench_import,
+ status: 'successful'
+ )
+
+ workbench_import.update_status
- workbench_import.child_change(netex_import)
+ expect(workbench_import.status).to eq('successful')
end
- it "updates :status to failed when #ready? and child is failed" do
- netex_import = build_stubbed(
+ it "Updates :status to failed when any child has failed" do
+ workbench_import = create(:workbench_import)
+ [
+ 'failed',
+ 'successful'
+ ].each do |status|
+ create(
+ :netex_import,
+ parent: workbench_import,
+ status: status
+ )
+ end
+
+ workbench_import.update_status
+
+ expect(workbench_import.status).to eq('failed')
+ end
+
+ it "updates :ended_at to now when status is finished" do
+ workbench_import = create(:workbench_import)
+ create(
:netex_import,
parent: workbench_import,
- status: :failed
+ status: 'failed'
)
- expect(workbench_import).to receive(:update).with(status: 'failed')
+ Timecop.freeze(Time.now) do
+ workbench_import.update_status
+
+ expect(workbench_import.ended_at).to eq(Time.now)
+ end
+ end
+ end
+
+ describe "#update_referentials" do
+ it "doesn't update referentials if parent status isn't finished" do
+ workbench_import = create(:workbench_import, status: 'pending')
+ netex_import = create(:netex_import, parent: workbench_import)
+ netex_import.referential.update(ready: false)
+
+ workbench_import.update_referentials
+ netex_import.referential.reload
- workbench_import.child_change(netex_import)
+ expect(netex_import.referential.ready).to be false
end
shared_examples(
- "doesn't update :status if parent import status is finished"
+ "makes child referentials `ready` when status is finished"
) do |finished_status|
- it "doesn't update :status if parent import status is finished" do
- workbench_import = build_stubbed(
- :workbench_import,
- total_steps: 2,
- current_step: 2,
- status: finished_status
- )
- child = double('Import')
+ it "makes child referentials `ready` when status is finished" do
+ workbench_import = create(:workbench_import, status: finished_status)
+ netex_import = create(:netex_import, parent: workbench_import)
+ netex_import.referential.update(ready: false)
- expect(workbench_import).not_to receive(:update)
+ workbench_import.update_referentials
+ netex_import.referential.reload
- workbench_import.child_change(child)
+ expect(netex_import.referential.ready).to be true
end
end
include_examples(
- "doesn't update :status if parent import status is finished",
+ "makes child referentials `ready` when status is finished",
"successful"
)
include_examples(
- "doesn't update :status if parent import status is finished",
+ "makes child referentials `ready` when status is finished",
"failed"
)
include_examples(
- "doesn't update :status if parent import status is finished",
+ "makes child referentials `ready` when status is finished",
"aborted"
)
include_examples(
- "doesn't update :status if parent import status is finished",
+ "makes child referentials `ready` when status is finished",
"canceled"
)
end
-
- describe "#ready?" do
- it "returns true if #current_step == #total_steps" do
- import = build_stubbed(
- :import,
- total_steps: 4,
- current_step: 4
- )
-
- expect(import.ready?).to be true
- end
-
- it "returns false if #current_step != #total_steps" do
- import = build_stubbed(
- :import,
- total_steps: 6,
- current_step: 3
- )
-
- expect(import.ready?).to be false
- end
- end
end
diff --git a/spec/models/referential_metadata_spec.rb b/spec/models/referential_metadata_spec.rb
index 91a2a7fc2..291ed974a 100644
--- a/spec/models/referential_metadata_spec.rb
+++ b/spec/models/referential_metadata_spec.rb
@@ -12,13 +12,13 @@ RSpec.describe ReferentialMetadata, :type => :model do
describe ".new_from" do
let(:referential_metadata) { create :referential_metadata, referential_source: create(:referential) }
- let(:new_referential_metadata) { ReferentialMetadata.new_from(referential_metadata) }
+ let(:new_referential_metadata) { ReferentialMetadata.new_from(referential_metadata, []) }
it "should not have an associated referential" do
expect(new_referential_metadata).to be_a_new(ReferentialMetadata)
end
- it "should have the same lines" do
+ xit "should have the same lines" do
expect(new_referential_metadata.lines).to eq(referential_metadata.lines)
end
@@ -30,8 +30,8 @@ RSpec.describe ReferentialMetadata, :type => :model do
expect(new_referential_metadata.referential).to be(nil)
end
- it "should have the same referential_source" do
- expect(new_referential_metadata.referential_source).to eq(referential_metadata.referential_source)
+ it "should have the right referential_source" do
+ expect(new_referential_metadata.referential_source).to eq(referential_metadata.referential)
end
end
diff --git a/spec/models/referential_spec.rb b/spec/models/referential_spec.rb
index 53eaa60a3..f9ace08cc 100644
--- a/spec/models/referential_spec.rb
+++ b/spec/models/referential_spec.rb
@@ -27,20 +27,21 @@ describe Referential, :type => :model do
context "Cloning referential" do
let(:clone) do
- Referential.new_from(ref)
+ Referential.new_from(ref, [])
end
- let(:saved_clone) do
- clone.tap do |clone|
- clone.organisation = ref.organisation
- clone.metadatas.each do |metadata|
- metadata.periodes = metadata.periodes.map { |period| Range.new(period.end+1, period.end+10) }
- end
- clone.save!
- end
- end
-
- it 'should create a ReferentialCloning' do
+ # let(:saved_clone) do
+ # clone.tap do |clone|
+ # clone.organisation = ref.organisation
+ # clone.metadatas.each do |metadata|
+ # metadata.line_ids = ref.lines.where(id: clone.line_ids, objectid: JSON.parse(ref.organisation.sso_attributes["functional_scope"]).collect(&:id)
+ # metadata.periodes = metadata.periodes.map { |period| Range.new(period.end+1, period.end+10) }
+ # end
+ # clone.save!
+ # end
+ # end
+
+ xit 'should create a ReferentialCloning' do
expect { saved_clone }.to change{ReferentialCloning.count}.by(1)
end
@@ -48,7 +49,7 @@ describe Referential, :type => :model do
referential.metadatas.map { |m| [ m.periodes, m.line_ids ] }
end
- it 'should clone referential_metadatas' do
+ xit 'should clone referential_metadatas' do
expect(metadatas_attributes(clone)).to eq(metadatas_attributes(ref))
end
end
diff --git a/spec/models/vehicle_journey_export_spec.rb b/spec/models/vehicle_journey_export_spec.rb
index 6252a73f9..83b3bbb04 100644
--- a/spec/models/vehicle_journey_export_spec.rb
+++ b/spec/models/vehicle_journey_export_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
describe VehicleJourneyExport, :type => :model do
-
+
let!(:line) { create(:line) }
let!(:route) { create(:route, :line => line) }
let!(:other_route) { create(:route, :line => line) }
@@ -10,10 +10,10 @@ describe VehicleJourneyExport, :type => :model do
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!(:vehicle_journey1) { create(:vehicle_journey_common, :objectid => "export:VehicleJourney:1:loc", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
+ let!(:vehicle_journey2) { create(:vehicle_journey_common, :objectid => "export:VehicleJourney:2:loc", :route_id => route.id, :journey_pattern_id => other_journey_pattern.id) }
+ let!(:vehicle_journey3) { create(:vehicle_journey_common, :objectid => "export:VehicleJourney:3:loc", :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] }
@@ -21,10 +21,10 @@ describe VehicleJourneyExport, :type => :model do
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
+ 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
@@ -35,10 +35,10 @@ describe VehicleJourneyExport, :type => :model 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
+ describe ".tt_periods" do
it "should return empty period" do
time_table.periods.clear
@@ -50,10 +50,10 @@ describe VehicleJourneyExport, :type => :model do
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
+
+ describe ".tt_included_days" do
it "should return empty included dates" do
time_table.dates.clear
@@ -65,10 +65,10 @@ describe VehicleJourneyExport, :type => :model do
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
+ describe ".tt_excluded_days" do
it "should return empty excluded dates" do
time_table.dates.clear
@@ -80,7 +80,7 @@ describe VehicleJourneyExport, :type => :model do
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 b01523dd9..7b31dc806 100644
--- a/spec/models/vehicle_journey_import_spec.rb
+++ b/spec/models/vehicle_journey_import_spec.rb
@@ -36,9 +36,9 @@ describe VehicleJourneyImport, :type => :model do
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 => "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!(:vehicle_journey1) { create(:vehicle_journey_common, :objectid => "import:VehicleJourney:1:loc", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
+ let!(:vehicle_journey2) { create(:vehicle_journey_common, :objectid => "import:VehicleJourney:2:loc", :route_id => route.id, :journey_pattern_id => other_journey_pattern.id) }
+ let!(:vehicle_journey3) { create(:vehicle_journey_common, :objectid => "import:VehicleJourney:3:loc", :route_id => route.id, :journey_pattern_id => journey_pattern.id) }
let!(:stop_point0) { route.stop_points[0] }
let!(:stop_point1) { route.stop_points[1] }
@@ -86,7 +86,7 @@ describe VehicleJourneyImport, :type => :model do
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", :skip => "Time gap validation is in pending status" do
+ it "should not import vehicle_journeys and not create objects when vehicle journey at stops are not in ascendant order", :skip => "Time gap validation is in pending status" do
expect(VehicleJourneyImport.new(:route => route, :file => invalid_file_on_vjas_object).save).to be_falsey
expect(Chouette::VehicleJourney.all.size).to eq(3)
expect(Chouette::VehicleJourneyAtStop.all.size).to eq(0)
diff --git a/spec/models/vehicle_translation_spec.rb b/spec/models/vehicle_translation_spec.rb
index c9a573ae2..d30cfa03e 100644
--- a/spec/models/vehicle_translation_spec.rb
+++ b/spec/models/vehicle_translation_spec.rb
@@ -6,7 +6,6 @@ describe VehicleTranslation, :type => :model do
# To fix : need to comment :company => company
# after adding company to apartment excluded models
let!(:vehicle_journey){ create(:vehicle_journey,
- :objectid => "dummy",
:journey_pattern => journey_pattern,
:route => journey_pattern.route,
# :company => company,
diff --git a/spec/policies/api_key_policy_spec.rb b/spec/policies/api_key_policy_spec.rb
new file mode 100644
index 000000000..5b9d59fa3
--- /dev/null
+++ b/spec/policies/api_key_policy_spec.rb
@@ -0,0 +1,28 @@
+require 'rails_helper'
+
+RSpec.describe ApiKeyPolicy do
+
+ let(:user) { User.new }
+
+ subject { described_class }
+
+ permissions ".scope" do
+ pending "add some examples to (or delete) #{__FILE__}"
+ end
+
+ permissions :show? do
+ pending "add some examples to (or delete) #{__FILE__}"
+ end
+
+ permissions :create? do
+ pending "add some examples to (or delete) #{__FILE__}"
+ end
+
+ permissions :update? do
+ pending "add some examples to (or delete) #{__FILE__}"
+ end
+
+ permissions :destroy? do
+ pending "add some examples to (or delete) #{__FILE__}"
+ end
+end
diff --git a/spec/requests/api/v1/netex_import_spec.rb b/spec/requests/api/v1/netex_import_spec.rb
index fd5f6d497..b6728168e 100644
--- a/spec/requests/api/v1/netex_import_spec.rb
+++ b/spec/requests/api/v1/netex_import_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "NetexImport", type: :request do
let( :referential ){ create :referential }
let( :workbench ){ referential.workbench }
-
+ let( :workbench_import ){ create :workbench_import }
let( :file_path ){ fixtures_path 'single_reference_import.zip' }
let( :file ){ fixture_file_upload( file_path ) }
@@ -19,42 +19,59 @@ RSpec.describe "NetexImport", type: :request do
let( :legal_attributes ) do
{
- name: 'hello world',
+ name: 'offre1',
file: file,
- workbench_id: workbench.id
+ workbench_id: workbench.id,
+ parent_id: workbench_import.id,
+ parent_type: workbench_import.class.name
}
- end
+ end
context 'with correct credentials and correct request' do
let( :authorization ){ authorization_token_header( get_api_key.token ) }
-
+ #TODO Check why referential_id is nil
it 'succeeds' do
- post_request.(netex_import: legal_attributes)
- expect( response ).to be_success
- expect( json_response_body ).to eq(
- 'id' => NetexImport.last.id,
- 'referential_id' => Referential.last.id,
- 'workbench_id' => workbench.id
- )
+ skip "Problem with referential_id" do
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00108', line_referential: workbench.line_referential)
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00109', line_referential: workbench.line_referential)
+
+ post_request.(netex_import: legal_attributes)
+ expect( response ).to be_success
+ expect( json_response_body ).to eq(
+ 'id' => NetexImport.last.id,
+ 'referential_id' => Referential.last.id,
+ 'workbench_id' => workbench.id
+ )
+ end
end
+
it 'creates a NetexImport object in the DB' do
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00108', line_referential: workbench.line_referential)
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00109', line_referential: workbench.line_referential)
+
expect{ post_request.(netex_import: legal_attributes) }.to change{NetexImport.count}.by(1)
end
+ #TODO Check why Referential count does not change
it 'creates a correct Referential' do
- legal_attributes # force object creation for correct to change behavior
- expect{post_request.(netex_import: legal_attributes)}.to change{Referential.count}.by(1)
- Referential.last.tap do | ref |
- expect( ref.workbench_id ).to eq(workbench.id)
- expect( ref.organisation_id ).to eq(workbench.organisation_id)
+ skip "Referential count does not change" do
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00108', line_referential: workbench.line_referential)
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00109', line_referential: workbench.line_referential)
+
+ legal_attributes # force object creation for correct to change behavior
+ expect{post_request.(netex_import: legal_attributes)}.to change{Referential.count}.by(1)
+ Referential.last.tap do | ref |
+ expect( ref.workbench_id ).to eq(workbench.id)
+ expect( ref.organisation_id ).to eq(workbench.organisation_id)
+ end
end
end
end
- context 'with incorrect credentials and correct request' do
+ context 'with incorrect credentials and correct request', pending: "see #4311" do
let( :authorization ){ authorization_token_header( "#{referential.id}-incorrect_token") }
it 'does not create any DB object and does not succeed' do
@@ -68,10 +85,14 @@ RSpec.describe "NetexImport", type: :request do
context 'with correct credentials and incorrect request' do
let( :authorization ){ authorization_token_header( get_api_key.token ) }
- shared_examples_for 'illegal attributes' do |bad_attribute, illegal_value=nil, referential_count: 0|
+ shared_examples_for 'illegal attributes' do |bad_attribute, illegal_value=nil|
context "missing #{bad_attribute}" do
let!( :illegal_attributes ){ legal_attributes.merge( bad_attribute => illegal_value ) }
it 'does not succeed' do
+ # TODO: Handle better when `ReferentialMetadataKludge` is reworked
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00108')
+ create(:line, objectid: 'STIF:CODIFLIGNE:Line:C00109')
+
post_request.(netex_import: illegal_attributes)
expect( response.status ).to eq(406)
expect( json_response_body['errors'][bad_attribute.to_s] ).not_to be_empty
@@ -81,20 +102,22 @@ RSpec.describe "NetexImport", type: :request do
expect{ post_request.(netex_import: illegal_attributes) }.not_to change{Import.count}
end
- it 'might create a referential' do
- expect{ post_request.(netex_import: illegal_attributes) }.to change{Referential.count}.by(referential_count)
+ it 'might not create a referential' do
+ expect{ post_request.(netex_import: illegal_attributes) }.not_to change{Referential.count}
end
end
end
- it_behaves_like 'illegal attributes', :file, referential_count: 1
+ it_behaves_like 'illegal attributes', :file
it_behaves_like 'illegal attributes', :workbench_id
- context 'name already taken' do
- before do
- create :referential, name: 'already taken'
- end
- it_behaves_like 'illegal attributes', :name, 'already taken'
- end
+
+ # TODO Create a specific test when referential is not created
+ # context 'name already taken' do
+ # before do
+ # create :referential, name: 'already taken'
+ # end
+ # it_behaves_like 'illegal attributes', name: 'already taken'
+ # end
end
end
end
diff --git a/spec/services/http_service_spec.rb b/spec/services/http_service_spec.rb
index 8c8af480c..25cc1ee35 100644
--- a/spec/services/http_service_spec.rb
+++ b/spec/services/http_service_spec.rb
@@ -33,9 +33,6 @@ RSpec.describe HTTPService do
let( :upload_list ){ [value, mime_type, as_name] }
it 'sets authorization and posts data' do
- expect(Faraday::UploadIO).to receive(:new).with(*upload_list).and_return upload_io
- expect(params).to receive(:update).with(name => upload_io)
-
expect(Faraday).to receive(:new).with(url: host).and_yield(faraday_connection)
expect(faraday_connection).to receive(:adapter).with(Faraday.default_adapter)
expect(faraday_connection).to receive(:headers).and_return headers
diff --git a/spec/services/retry_service_spec.rb b/spec/services/retry_service_spec.rb
deleted file mode 100644
index bb3416373..000000000
--- a/spec/services/retry_service_spec.rb
+++ /dev/null
@@ -1,137 +0,0 @@
-RSpec.describe RetryService do
- subject { described_class.new delays: [2, 3], rescue_from: [NameError, ArgumentError] }
-
- context 'no retry necessary' do
- before do
- expect( subject ).not_to receive(:sleep)
- end
-
- it 'returns an ok result' do
- expect( subject.execute { 42 } ).to eq(Result.ok(42))
- end
- it 'does not fail on nil' do
- expect( subject.execute { nil } ).to eq(Result.ok(nil))
- end
-
- it 'fails wihout retries if raising un unregistered exception' do
- expect{ subject.execute{ raise KeyError } }.to raise_error(KeyError)
- end
-
- end
-
- context 'all retries fail' do
- before do
- expect( subject ).to receive(:sleep).with(2)
- expect( subject ).to receive(:sleep).with(3)
- end
- it 'fails after raising a registered exception n times' do
- result = subject.execute{ raise ArgumentError }
- expect( result.status ).to eq(:error)
- expect( result.value ).to be_kind_of(ArgumentError)
- end
- it 'fails with an explicit try again (automatically registered exception)' do
- result = subject.execute{ raise RetryService::Retry }
- expect( result.status ).to eq(:error)
- expect( result.value ).to be_kind_of(RetryService::Retry)
- end
- end
-
- context "if at first you don't succeed" do
- before do
- @count = 0
- expect( subject ).to receive(:sleep).with(2)
- end
-
- it 'succeeds the second time' do
- expect( subject.execute{ succeed_later(ArgumentError){ 42 } } ).to eq(Result.ok(42))
- end
-
- it 'succeeds the second time with try again (automatically registered exception)' do
- expect( subject.execute{ succeed_later(RetryService::Retry){ 42 } } ).to eq(Result.ok(42))
- end
- end
-
- context 'last chance' do
- before do
- @count = 0
- expect( subject ).to receive(:sleep).with(2)
- expect( subject ).to receive(:sleep).with(3)
- end
- it 'succeeds the third time with try again (automatically registered exception)' do
- result = subject.execute{ succeed_later(RetryService::Retry, count: 2){ 42 } }
- expect( result ).to eq( Result.ok(42) )
- end
- end
-
- context 'failure callback once' do
- subject do
- described_class.new delays: [2, 3], rescue_from: [NameError, ArgumentError] do |reason, count|
- @reason=reason
- @callback_count=count
- @failures += 1
- end
- end
-
- before do
- @failures = 0
- @count = 0
- expect( subject ).to receive(:sleep).with(2)
- end
-
- it 'succeeds the second time and calls the failure_callback once' do
- subject.execute{ succeed_later(RetryService::Retry){ 42 } }
- expect( @failures ).to eq(1)
- end
- it '... and the failure is passed into the callback' do
- subject.execute{ succeed_later(RetryService::Retry){ 42 } }
- expect( @reason ).to be_a(RetryService::Retry)
- expect( @callback_count ).to eq(1)
- end
- end
-
- context 'failure callback twice' do
- subject do
- described_class.new delays: [2, 3], rescue_from: [NameError, ArgumentError] do |_reason, _count|
- @failures += 1
- end
- end
-
- before do
- @failures = 0
- @count = 0
- expect( subject ).to receive(:sleep).with(2)
- expect( subject ).to receive(:sleep).with(3)
- end
-
- it 'succeeds the third time and calls the failure_callback twice' do
- subject.execute{ succeed_later(NameError, count: 2){ 42 } }
- expect( @failures ).to eq(2)
- end
- end
-
- context 'failure callback in constructor' do
- subject do
- described_class.new(delays: [1, 2], &method(:add2failures))
- end
- before do
- @failures = []
- @count = 0
- expect( subject ).to receive(:sleep).with(1)
- expect( subject ).to receive(:sleep).with(2)
- end
- it 'succeeds the second time and calls the failure_callback once' do
- subject.execute{ succeed_later(RetryService::Retry, count: 2){ 42 } }
- expect( @failures ).to eq([1,2])
- end
- end
-
- def add2failures( e, c)
- @failures << c
- end
-
- def succeed_later error, count: 1, &blk
- return blk.() unless @count < count
- @count += 1
- raise error, 'error'
- end
-end
diff --git a/spec/services/zip_service/regression_4273_spec.rb b/spec/services/zip_service/regression_4273_spec.rb
new file mode 100644
index 000000000..4fe0f6539
--- /dev/null
+++ b/spec/services/zip_service/regression_4273_spec.rb
@@ -0,0 +1,59 @@
+RSpec.describe ZipService do
+ describe 'Regression Issue # 4273 https://projects.af83.io/issues/4273' do
+ let( :zip_service ){ described_class }
+ let( :unzipper ){ zip_service.new(zip_data) }
+ let( :zip_data ){ File.read zip_file }
+
+ context 'real test data' do
+ let( :subdir_names ){ %w<OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519> }
+ let( :expected_chksums ){
+ checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'source_') } )
+ }
+
+ let( :zip_file ){ fixtures_path 'OFFRE_TRANSDEV_2017030112251.zip' }
+ #
+ # Remove potential test artefacts
+ before do
+ subdir_names.each do | subdir_name |
+ File.unlink( subdir_file subdir_name, suffix: '.zip' ) rescue nil
+ Dir.unlink( subdir_file subdir_name ) rescue nil
+ end
+ end
+
+ it "yields the correct content" do
+ subdir_contents = {}
+ # Write ZipService Streams to files and inflate them to file system
+ unzipper.subdirs.each do | subdir |
+ File.open(subdir_file( subdir.name, suffix: '.zip' ), 'wb'){ |f| f.write subdir.stream.string }
+ unzip_subdir subdir
+ end
+ # Represent the inflated file_system as a checksum tree
+ actual_checksums =
+ checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'target/') } )
+ expect( actual_checksums ).to eq( expected_chksums )
+ end
+
+ end
+
+ end
+
+ def checksum_trees *dirs
+ dirs.flatten.inject({},&method(:checksum_tree))
+ end
+ def checksum_tree repr, dir
+ Dir.glob("#{dir}/**/*").each do |file|
+ if !File.directory?(file)
+ repr.merge!( File.basename(file) => %x{cksum #{file}}.split.first ){ |_, ov, nv| Array(ov) << nv }
+ end
+ end
+ repr
+ end
+
+ def subdir_file( subdir, prefix: 'target_', suffix: '' )
+ fixtures_path("#{prefix}#{subdir}#{suffix}")
+ end
+
+ def unzip_subdir subdir
+ %x{unzip -oqq #{subdir_file subdir.name, suffix: '.zip'} -d #{fixture_path}/target}
+ end
+end
diff --git a/spec/services/zip_service/zip_entry_data_spec.rb b/spec/services/zip_service/zip_entry_data_spec.rb
deleted file mode 100644
index 2a7226eb4..000000000
--- a/spec/services/zip_service/zip_entry_data_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-RSpec.describe ZipService do
-
- subject{ described_class.new(read_fixture('multiple_references_import.zip')) }
-
- it 'can group all entries' do
- expect( subject.entry_groups.keys ).to eq(%w{ref1 ref2})
- end
-
- context 'creates correct zip data for each subdir' do
- it 'e.g. reference1' do
- reference1_stream = subject.entry_group_streams['ref1']
- control_stream = Zip::InputStream.open( reference1_stream )
- control_entries = described_class.entries(control_stream)
- expect( control_entries.map{ |e| [e.name, e.get_input_stream.read]}.force ).to eq([
- ["multiref/ref1/", ""],
- ["multiref/ref1/datum-1", "multi-ref1-datum1\n"],
- ["multiref/ref1/datum-2", "multi-ref1-datum2\n"]
- ])
- end
- it 'e.g. reference2' do
- reference2_stream = subject.entry_group_streams['ref2']
- control_stream = Zip::InputStream.open( reference2_stream )
- control_entries = described_class.entries(control_stream)
- expect( control_entries.map{ |e| [e.name, e.get_input_stream.read]}.force ).to eq([
- ["multiref/ref2/", ""],
- ["multiref/ref2/datum-1", "multi-ref2-datum1\n"],
- ["multiref/ref2/datum-2", "multi-ref2-datum2\n"]
- ])
- end
- end
-
-end
diff --git a/spec/services/zip_service/zip_entry_dirs_spec.rb b/spec/services/zip_service/zip_entry_dirs_spec.rb
deleted file mode 100644
index 8ca1b0f1a..000000000
--- a/spec/services/zip_service/zip_entry_dirs_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-RSpec.describe ZipService do
-
- let( :zip_service ){ described_class }
-
- let( :zip_data ){ File.read zip_file }
-
- shared_examples_for 'a correct zip entry reader' do
- it 'gets all entries of the zip file' do
- expect( zip_service.new(zip_data).entry_groups.keys ).to eq(expected)
- end
- end
-
- context 'single entry' do
- let( :zip_file ){ fixtures_path 'multiple_references_import.zip' }
- let( :expected ){ %w{ref1 ref2} }
-
- it_behaves_like 'a correct zip entry reader'
- end
-
- context 'more entries' do
- let( :zip_file ){ fixtures_path 'single_reference_import.zip' }
- let( :expected ){ %w{ref} }
-
- it_behaves_like 'a correct zip entry reader'
- end
-
- context 'illegal file' do
- let( :zip_file ){ fixtures_path 'nozip.zip' }
- let( :expected ){ [] }
-
- it_behaves_like 'a correct zip entry reader'
- end
-end
diff --git a/spec/services/zip_service/zip_output_streams_spec.rb b/spec/services/zip_service/zip_output_streams_spec.rb
deleted file mode 100644
index 742f9b996..000000000
--- a/spec/services/zip_service/zip_output_streams_spec.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-RSpec.describe ZipService do
-
- subject{ described_class.new(read_fixture('multiple_references_import.zip')) }
-
- it "exposes its size" do
- expect( subject.entry_group_streams.size ).to eq(2)
- end
-end
diff --git a/spec/support/api_key.rb b/spec/support/api_key.rb
index 561e1f796..cc08cd7f1 100644
--- a/spec/support/api_key.rb
+++ b/spec/support/api_key.rb
@@ -5,20 +5,24 @@ module ApiKeyHelper
end
def get_api_key
- Api::V1::ApiKey.first_or_create( :referential_id => referential.id, :name => "test")
+ Api::V1::ApiKey.first_or_create(referential: referential, organisation: organisation)
end
+
def config_formatted_request_with_authorization( format)
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials( get_api_key.token)
request.accept = format
end
+
def config_formatted_request_with_dummy_authorization( format)
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials( "dummy")
request.accept = format
end
+
def config_formatted_request_without_authorization( format)
request.env['HTTP_AUTHORIZATION'] = nil
request.accept = format
end
+
def json_xml_format?
request.accept == "application/json" || request.accept == "application/xml"
end
diff --git a/spec/support/devise.rb b/spec/support/devise.rb
index 46249fef2..c9fd1b8e5 100644
--- a/spec/support/devise.rb
+++ b/spec/support/devise.rb
@@ -3,10 +3,10 @@ module DeviseRequestHelper
def login_user
organisation = Organisation.where(:code => "first").first_or_create(attributes_for(:organisation))
- @user ||=
+ @user ||=
create(:user,
:organisation => organisation,
- :permissions => Support::Permissions.all_permissions)
+ :permissions => Support::Permissions.all_permissions)
login_as @user, :scope => :user
# post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password
diff --git a/spec/support/referential.rb b/spec/support/referential.rb
index 57b510f69..c431856b8 100644
--- a/spec/support/referential.rb
+++ b/spec/support/referential.rb
@@ -12,6 +12,7 @@ module ReferentialHelper
base.class_eval do
extend ClassMethods
alias_method :referential, :first_referential
+ alias_method :organisation, :first_organisation
end
end
diff --git a/spec/support/shared_context.rb b/spec/support/shared_context.rb
new file mode 100644
index 000000000..e9b0025a2
--- /dev/null
+++ b/spec/support/shared_context.rb
@@ -0,0 +1,15 @@
+shared_context 'iboo authenticated api user' do
+ let(:api_key) { create(:api_key, organisation: organisation) }
+
+ before do
+ request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(api_key.organisation.code, api_key.token)
+ end
+end
+
+shared_context 'iboo wrong authorisation api user' do
+ let(:api_key) { create(:api_key, organisation: organisation) }
+
+ before do
+ request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials('fake code', api_key.token)
+ end
+end
diff --git a/spec/workers/referential_cloning_worker_spec.rb b/spec/workers/referential_cloning_worker_spec.rb
index 52ed8913b..7e4a2357a 100644
--- a/spec/workers/referential_cloning_worker_spec.rb
+++ b/spec/workers/referential_cloning_worker_spec.rb
@@ -3,7 +3,7 @@ require 'ostruct'
RSpec.describe ReferentialCloningWorker do
- context "given a refererntial cloning" do
+ context "given a referential cloning" do
let( :id ){ double }
@@ -34,4 +34,20 @@ RSpec.describe ReferentialCloningWorker do
end
end
+ it "should clone an existing Referential" do
+ source_referential = create :referential
+
+ source_referential.switch
+ source_time_table = create :time_table
+
+ target_referential = create :referential, created_from: source_referential
+
+ cloning = ReferentialCloning.create source_referential: source_referential, target_referential: target_referential
+ ReferentialCloningWorker.new.perform(cloning)
+
+ target_referential.switch
+ expect(Chouette::TimeTable.where(objectid: source_time_table.objectid).exists?)
+ end
+
+
end
diff --git a/spec/workers/workbench_import_worker_spec.rb b/spec/workers/workbench_import_worker_spec.rb
index b719cbb98..a349b3433 100644
--- a/spec/workers/workbench_import_worker_spec.rb
+++ b/spec/workers/workbench_import_worker_spec.rb
@@ -6,11 +6,6 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
let( :workbench ){ import.workbench }
let( :referential ){ import.referential }
let( :api_key ){ build_stubbed :api_key, referential: referential, token: "#{referential.id}-#{SecureRandom.hex}" }
- let( :params ) do
- { netex_import:
- { referential_id: referential.id, workbench_id: workbench.id }
- }
- end
# http://www.example.com/workbenches/:workbench_id/imports/:id/download
let( :host ){ Rails.configuration.rails_host }
@@ -23,12 +18,12 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
let( :upload_path ) { api_v1_netex_imports_path(format: :json) }
- let( :entry_group_streams ) do
- entry_count.times.map{ |i| double( "entry group stream #{i}" ) }
- end
- let( :entry_groups ) do
- entry_count.times.map do | i |
- {"entry_group_name#{i}" => entry_group_streams[i] }
+ let( :subdirs ) do
+ entry_count.times.map do |i|
+ ZipService::Subdir.new(
+ "subdir #{i}",
+ double("subdir #{i}", rewind: 0, read: '')
+ )
end
end
@@ -38,6 +33,8 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
let( :post_response_ok ){ double(status: 201, body: "{}") }
before do
+ Timecop.freeze(Time.now)
+
# Silence Logger
allow_any_instance_of(Logger).to receive(:info)
allow_any_instance_of(Logger).to receive(:warn)
@@ -47,8 +44,15 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
allow(Api::V1::ApiKey).to receive(:from).and_return(api_key)
allow(ZipService).to receive(:new).with(downloaded_zip).and_return zip_service
- expect(zip_service).to receive(:entry_group_streams).and_return(entry_groups)
- expect( import ).to receive(:update_attributes).with(status: 'running')
+ expect(zip_service).to receive(:subdirs).and_return(subdirs)
+ expect( import ).to receive(:update).with(
+ status: 'running',
+ started_at: Time.now
+ )
+ end
+
+ after do
+ Timecop.return
end
@@ -61,13 +65,14 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
.with(host: host, path: path, params: {token: download_token})
.and_return( download_zip_response )
- entry_groups.each do | entry_group_name, entry_group_stream |
- mock_post entry_group_name, entry_group_stream, post_response_ok
+ subdirs.each do |subdir|
+ mock_post subdir, post_response_ok
end
- expect( import ).to receive(:update_attributes).with(total_steps: 2)
- expect( import ).to receive(:update_attributes).with(current_step: 1)
- expect( import ).to receive(:update_attributes).with(current_step: 2)
+ expect( import ).to receive(:update).with(total_steps: 2)
+ expect( import ).to receive(:update).with(current_step: 1)
+ expect( import ).to receive(:update).with(current_step: 2)
+ expect( import ).to receive(:update).with(ended_at: Time.now)
worker.perform import.id
@@ -83,37 +88,45 @@ RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
.with(host: host, path: path, params: {token: download_token})
.and_return( download_zip_response )
- # First entry_group succeeds
- entry_groups[0..0].each do | entry_group_name, entry_group_stream |
- mock_post entry_group_name, entry_group_stream, post_response_ok
+ # First subdir succeeds
+ subdirs[0..0].each do |subdir|
+ mock_post subdir, post_response_ok
end
- # Second entry_group fails (M I S E R A B L Y)
- entry_groups[1..1].each do | entry_group_name, entry_group_stream |
- mock_post entry_group_name, entry_group_stream, post_response_failure
- WorkbenchImportWorker::RETRY_DELAYS.each do | delay |
- mock_post entry_group_name, entry_group_stream, post_response_failure
- expect_any_instance_of(RetryService).to receive(:sleep).with(delay)
- end
+ # Second subdir fails (M I S E R A B L Y)
+ subdirs[1..1].each do |subdir|
+ mock_post subdir, post_response_failure
end
- expect( import ).to receive(:update_attributes).with(total_steps: 3)
- expect( import ).to receive(:update_attributes).with(current_step: 1)
- expect( import ).to receive(:update_attributes).with(current_step: 2)
- expect( import ).to receive(:update_attributes).with(current_step: 3, status: 'failed')
+ expect( import ).to receive(:update).with(total_steps: 3)
+ expect( import ).to receive(:update).with(current_step: 1)
+ expect( import ).to receive(:update).with(current_step: 2)
+ expect( import ).to receive(:update).with(current_step: 3, status: 'failed')
- worker.perform import.id
+ expect { worker.perform import.id }.to raise_error(StopIteration)
end
end
- def mock_post entry_group_name, entry_group_stream, response
+ def mock_post subdir, response
+ allow(HTTPService).to receive(:upload)
expect( HTTPService ).to receive(:post_resource)
- .with(host: host,
- path: upload_path,
- token: api_key.token,
- params: params,
- upload: {file: [entry_group_stream, 'application/zip', entry_group_name]})
- .and_return(response)
+ .with(
+ host: host,
+ path: upload_path,
+ params: {
+ netex_import: {
+ parent_id: import.id,
+ parent_type: import.class.name,
+ workbench_id: workbench.id,
+ name: subdir.name,
+ file: HTTPService.upload(
+ subdir.stream,
+ 'application/zip',
+ "#{subdir.name}.zip"
+ )
+ }
+ }
+ ).and_return(response)
end
end